Skip to content

Commit

Permalink
Replaced PanelGroup validateLayout with Panel units="static"
Browse files Browse the repository at this point in the history
  • Loading branch information
bvaughn committed Aug 9, 2023
1 parent e840620 commit 23d63d5
Show file tree
Hide file tree
Showing 21 changed files with 1,205 additions and 1,052 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export type IconType =
| "resize-horizontal"
| "resize-vertical"
| "search"
| "typescript";
| "typescript"
| "warning";

export default function Icon({
className = "",
Expand Down Expand Up @@ -75,6 +76,10 @@ export default function Icon({
path =
"M3,3H21V21H3V3M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86M13,11.25H8V12.75H9.5V20H11.25V12.75H13V11.25Z";
break;
case "warning":
path =
"M5,3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V5A2,2 0 0,1 5,3M13,13V7H11V13H13M13,17V15H11V17H13Z";
break;
}

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@
import { ChangeEvent, useRef, useState } from "react";
import {
ChangeEvent,
Component,
ErrorInfo,
PropsWithChildren,
useRef,
useState,
} from "react";
import {
ImperativePanelGroupHandle,
ImperativePanelHandle,
getAvailableGroupSizePixels,
} from "react-resizable-panels";

import { urlToUrlData, PanelGroupForUrlData } from "../../utils/UrlData";
import { urlPanelGroupToPanelGroup, urlToUrlData } from "../../utils/UrlData";

import DebugLog, { ImperativeDebugLogHandle } from "../examples/DebugLog";

import "./styles.css";
import styles from "./styles.module.css";
import { useLayoutEffect } from "react";
import {
assertImperativePanelGroupHandle,
assertImperativePanelHandle,
} from "../../../tests/utils/assert";
import { useLayoutEffect } from "react";
import { Metadata } from "../../../tests/utils/url";
import "./styles.css";
import styles from "./styles.module.css";

// Special route that can be configured via URL parameters.

export default function EndToEndTesting() {
const [metadata, setMetadata] = useState<Metadata | null>(() => {
const url = new URL(
typeof window !== undefined ? window.location.href : ""
);
const metadata = url.searchParams.get("metadata");
class ErrorBoundary extends Component<PropsWithChildren> {
state = {
didError: false,
};

return metadata ? JSON.parse(metadata) : null;
});
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
console.error(error);
}

render() {
return this.state.didError ? null : this.props.children;
}
}

const [urlPanelGroup, setUrlPanelGroup] = useState(() => {
function EndToEndTesting() {
const [urlData, setUrlData] = useState(() => {
const url = new URL(
typeof window !== undefined ? window.location.href : ""
);
Expand All @@ -43,52 +55,31 @@ export default function EndToEndTesting() {
typeof window !== undefined ? window.location.href : ""
);

setUrlPanelGroup(urlToUrlData(url));

const metadata = url.searchParams.get("metadata");
setMetadata(metadata ? JSON.parse(metadata) : null);
setUrlData(urlToUrlData(url));
});
}, []);

useLayoutEffect(() => {
const calculatePanelSize = (panelElement: HTMLElement) => {
if (panelElement.childElementCount > 0) {
return; // Don't override nested groups
}

const panelSize = parseFloat(panelElement.style.flexGrow);

const panelGroupElement = panelElement.parentElement!;
const groupId = panelGroupElement.getAttribute("data-panel-group-id")!;
const panelGroupPixels = getAvailableGroupSizePixels(groupId);

panelElement.textContent = `${panelSize.toFixed(1)}%\n${(
(panelSize / 100) *
panelGroupPixels
).toFixed(1)}px`;
};

const observer = new MutationObserver((mutationRecords) => {
mutationRecords.forEach((mutationRecord) => {
const panelElement = mutationRecord.target as HTMLElement;
if (panelElement.childElementCount > 0) {
return;
}

const panelSize = parseFloat(panelElement.style.flexGrow);

const panelGroupElement = panelElement.parentElement!;
const groupId = panelGroupElement.getAttribute("data-panel-group-id");
const direction = panelGroupElement.getAttribute(
"data-panel-group-direction"
);
const resizeHandles = Array.from(
panelGroupElement.querySelectorAll(
`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`
)
) as HTMLElement[];

let panelGroupPixels =
direction === "horizontal"
? panelGroupElement.offsetWidth
: panelGroupElement.offsetHeight;
if (direction === "horizontal") {
panelGroupPixels -= resizeHandles.reduce((accumulated, handle) => {
return accumulated + handle.offsetWidth;
}, 0);
} else {
panelGroupPixels -= resizeHandles.reduce((accumulated, handle) => {
return accumulated + handle.offsetHeight;
}, 0);
}

panelElement.textContent = `${panelSize.toFixed(1)}%\n${(
(panelSize / 100) *
panelGroupPixels
).toFixed(1)}px`;
calculatePanelSize(mutationRecord.target as HTMLElement);
});
});

Expand All @@ -97,6 +88,8 @@ export default function EndToEndTesting() {
observer.observe(element, {
attributes: true,
});

calculatePanelSize(element as HTMLElement);
});

return () => {
Expand All @@ -114,6 +107,10 @@ export default function EndToEndTesting() {
Map<string, ImperativePanelHandle | ImperativePanelGroupHandle>
>(new Map());

const children = urlData
? urlPanelGroupToPanelGroup(urlData, debugLogRef, idToRefMapRef)
: null;

const onLayoutInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const value = event.currentTarget.value;
setLayoutString(value);
Expand Down Expand Up @@ -208,17 +205,16 @@ export default function EndToEndTesting() {
</button>
</div>
</div>
<div className={styles.Children}>
{urlPanelGroup && (
<PanelGroupForUrlData
debugLogRef={debugLogRef}
idToRefMapRef={idToRefMapRef}
metadata={metadata}
urlPanelGroup={urlPanelGroup}
/>
)}
</div>
<div className={styles.Children}>{children}</div>
<DebugLog apiRef={debugLogRef} />
</div>
);
}

export default function Page() {
return (
<ErrorBoundary>
<EndToEndTesting />
</ErrorBoundary>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ResizeHandle from "../../components/ResizeHandle";

import Example from "./Example";
import styles from "./shared.module.css";
import Icon from "../../components/Icon";

export default function ExternalPersistence() {
return (
Expand All @@ -22,11 +23,13 @@ export default function ExternalPersistence() {
layout is saved as part of the URL hash.
</p>
<p className={styles.WarningBlock}>
<Icon className={styles.WarningIcon} type="warning" />
Note the <code>storage</code> API is <em>synchronous</em>. If an
async source is used (e.g. a database) then values should be
pre-fetched during the initial render (e.g. using Suspense).
</p>
<p className={styles.WarningBlock}>
<Icon className={styles.WarningIcon} type="warning" />
Note calls to <code>storage.setItem</code> are debounced by{" "}
<strong>100ms</strong>. Depending on your implementation, you may
wish to use a larger interval than that.
Expand Down
Loading

0 comments on commit 23d63d5

Please sign in to comment.