Initial commit
This commit is contained in:
201
node_modules/react-resizable-panels/src/hooks/useWindowSplitterPanelGroupBehavior.ts
generated
vendored
Normal file
201
node_modules/react-resizable-panels/src/hooks/useWindowSplitterPanelGroupBehavior.ts
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
import { isDevelopment } from "#is-development";
|
||||
import { PanelData } from "../Panel";
|
||||
import { Direction } from "../types";
|
||||
import { adjustLayoutByDelta } from "../utils/adjustLayoutByDelta";
|
||||
import { assert } from "../utils/assert";
|
||||
import { calculateAriaValues } from "../utils/calculateAriaValues";
|
||||
import { determinePivotIndices } from "../utils/determinePivotIndices";
|
||||
import { getPanelGroupElement } from "../utils/dom/getPanelGroupElement";
|
||||
import { getResizeHandleElementsForGroup } from "../utils/dom/getResizeHandleElementsForGroup";
|
||||
import { getResizeHandlePanelIds } from "../utils/dom/getResizeHandlePanelIds";
|
||||
import { fuzzyNumbersEqual } from "../utils/numbers/fuzzyNumbersEqual";
|
||||
import { RefObject, useEffect, useRef } from "../vendor/react";
|
||||
import useIsomorphicLayoutEffect from "./useIsomorphicEffect";
|
||||
|
||||
// https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/
|
||||
|
||||
export function useWindowSplitterPanelGroupBehavior({
|
||||
committedValuesRef,
|
||||
eagerValuesRef,
|
||||
groupId,
|
||||
layout,
|
||||
panelDataArray,
|
||||
panelGroupElement,
|
||||
setLayout,
|
||||
}: {
|
||||
committedValuesRef: RefObject<{
|
||||
direction: Direction;
|
||||
}>;
|
||||
eagerValuesRef: RefObject<{
|
||||
panelDataArray: PanelData[];
|
||||
}>;
|
||||
groupId: string;
|
||||
layout: number[];
|
||||
panelDataArray: PanelData[];
|
||||
panelGroupElement: ParentNode | null;
|
||||
setLayout: (sizes: number[]) => void;
|
||||
}): void {
|
||||
const devWarningsRef = useRef<{
|
||||
didWarnAboutMissingResizeHandle: boolean;
|
||||
}>({
|
||||
didWarnAboutMissingResizeHandle: false,
|
||||
});
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
if (!panelGroupElement) {
|
||||
return;
|
||||
}
|
||||
const resizeHandleElements = getResizeHandleElementsForGroup(
|
||||
groupId,
|
||||
panelGroupElement
|
||||
);
|
||||
|
||||
for (let index = 0; index < panelDataArray.length - 1; index++) {
|
||||
const { valueMax, valueMin, valueNow } = calculateAriaValues({
|
||||
layout,
|
||||
panelsArray: panelDataArray,
|
||||
pivotIndices: [index, index + 1],
|
||||
});
|
||||
|
||||
const resizeHandleElement = resizeHandleElements[index];
|
||||
if (resizeHandleElement == null) {
|
||||
if (isDevelopment) {
|
||||
const { didWarnAboutMissingResizeHandle } = devWarningsRef.current;
|
||||
|
||||
if (!didWarnAboutMissingResizeHandle) {
|
||||
devWarningsRef.current.didWarnAboutMissingResizeHandle = true;
|
||||
|
||||
console.warn(
|
||||
`WARNING: Missing resize handle for PanelGroup "${groupId}"`
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const panelData = panelDataArray[index];
|
||||
assert(panelData, `No panel data found for index "${index}"`);
|
||||
|
||||
resizeHandleElement.setAttribute("aria-controls", panelData.id);
|
||||
resizeHandleElement.setAttribute(
|
||||
"aria-valuemax",
|
||||
"" + Math.round(valueMax)
|
||||
);
|
||||
resizeHandleElement.setAttribute(
|
||||
"aria-valuemin",
|
||||
"" + Math.round(valueMin)
|
||||
);
|
||||
resizeHandleElement.setAttribute(
|
||||
"aria-valuenow",
|
||||
valueNow != null ? "" + Math.round(valueNow) : ""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
resizeHandleElements.forEach((resizeHandleElement, index) => {
|
||||
resizeHandleElement.removeAttribute("aria-controls");
|
||||
resizeHandleElement.removeAttribute("aria-valuemax");
|
||||
resizeHandleElement.removeAttribute("aria-valuemin");
|
||||
resizeHandleElement.removeAttribute("aria-valuenow");
|
||||
});
|
||||
};
|
||||
}, [groupId, layout, panelDataArray, panelGroupElement]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!panelGroupElement) {
|
||||
return;
|
||||
}
|
||||
const eagerValues = eagerValuesRef.current;
|
||||
assert(eagerValues, `Eager values not found`);
|
||||
|
||||
const { panelDataArray } = eagerValues;
|
||||
const groupElement = getPanelGroupElement(groupId, panelGroupElement);
|
||||
assert(groupElement != null, `No group found for id "${groupId}"`);
|
||||
|
||||
const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
||||
assert(handles, `No resize handles found for group id "${groupId}"`);
|
||||
|
||||
const cleanupFunctions = handles.map((handle) => {
|
||||
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
||||
assert(handleId, `Resize handle element has no handle id attribute`);
|
||||
|
||||
const [idBefore, idAfter] = getResizeHandlePanelIds(
|
||||
groupId,
|
||||
handleId,
|
||||
panelDataArray,
|
||||
panelGroupElement
|
||||
);
|
||||
if (idBefore == null || idAfter == null) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case "Enter": {
|
||||
event.preventDefault();
|
||||
|
||||
const index = panelDataArray.findIndex(
|
||||
(panelData) => panelData.id === idBefore
|
||||
);
|
||||
if (index >= 0) {
|
||||
const panelData = panelDataArray[index];
|
||||
assert(panelData, `No panel data found for index ${index}`);
|
||||
|
||||
const size = layout[index];
|
||||
|
||||
const {
|
||||
collapsedSize = 0,
|
||||
collapsible,
|
||||
minSize = 0,
|
||||
} = panelData.constraints;
|
||||
|
||||
if (size != null && collapsible) {
|
||||
const nextLayout = adjustLayoutByDelta({
|
||||
delta: fuzzyNumbersEqual(size, collapsedSize)
|
||||
? minSize - collapsedSize
|
||||
: collapsedSize - size,
|
||||
initialLayout: layout,
|
||||
panelConstraints: panelDataArray.map(
|
||||
(panelData) => panelData.constraints
|
||||
),
|
||||
pivotIndices: determinePivotIndices(
|
||||
groupId,
|
||||
handleId,
|
||||
panelGroupElement
|
||||
),
|
||||
prevLayout: layout,
|
||||
trigger: "keyboard",
|
||||
});
|
||||
if (layout !== nextLayout) {
|
||||
setLayout(nextLayout);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handle.addEventListener("keydown", onKeyDown);
|
||||
|
||||
return () => {
|
||||
handle.removeEventListener("keydown", onKeyDown);
|
||||
};
|
||||
});
|
||||
|
||||
return () => {
|
||||
cleanupFunctions.forEach((cleanupFunction) => cleanupFunction());
|
||||
};
|
||||
}, [
|
||||
panelGroupElement,
|
||||
committedValuesRef,
|
||||
eagerValuesRef,
|
||||
groupId,
|
||||
layout,
|
||||
panelDataArray,
|
||||
setLayout,
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user