react-resizable-panels 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -1
- package/dist/react-resizable-panels.d.ts.map +1 -1
- package/dist/react-resizable-panels.js +336 -89
- package/dist/react-resizable-panels.js.map +1 -1
- package/dist/react-resizable-panels.module.js +336 -89
- package/dist/react-resizable-panels.module.js.map +1 -1
- package/package.json +1 -1
- package/src/Panel.tsx +6 -1
- package/src/PanelGroup.tsx +67 -143
- package/src/PanelResizeHandle.tsx +20 -8
- package/src/constants.ts +1 -0
- package/src/hooks/useWindowSplitterBehavior.ts +185 -0
- package/src/types.ts +2 -1
- package/src/utils/coordinates.ts +118 -0
- package/src/utils/group.ts +176 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/react-resizable-panels/src/index.ts","packages/react-resizable-panels/src/Panel.tsx","packages/react-resizable-panels/src/PanelContexts.ts","packages/react-resizable-panels/src/PanelGroup.tsx","packages/react-resizable-panels/src/hooks/useUniqueId.ts","packages/react-resizable-panels/src/utils/serialization.ts","packages/react-resizable-panels/src/PanelResizeHandle.tsx"],"sourcesContent":["import Panel from \"./Panel\";\nimport { PanelContext } from \"./PanelContexts\";\nimport PanelGroup from \"./PanelGroup\";\nimport PanelResizeHandle from \"./PanelResizeHandle\";\n\nexport { Panel, PanelContext, PanelGroup, PanelResizeHandle };\n","import { ReactNode, useContext, useLayoutEffect } from \"react\";\n\nimport { PanelGroupContext } from \"./PanelContexts\";\n\n// TODO [panels]\n// Support min pixel size too.\n// PanelGroup should warn if total width is less min pixel widths.\nexport default function Panel({\n children = null,\n className = \"\",\n defaultSize = 0.1,\n id,\n minSize = 0.1,\n order = null,\n}: {\n children?: ReactNode;\n className?: string;\n defaultSize?: number;\n id: string;\n minSize?: number;\n order?: number | null;\n}) {\n const context = useContext(PanelGroupContext);\n if (context === null) {\n throw Error(\n `Panel components must be rendered within a PanelGroup container`\n );\n }\n\n if (minSize > defaultSize) {\n console.error(\n `Panel minSize ${minSize} cannot be greater than defaultSize ${defaultSize}`\n );\n\n defaultSize = minSize;\n }\n\n const { getPanelStyle, registerPanel, unregisterPanel } = context;\n\n useLayoutEffect(() => {\n const panel = {\n defaultSize,\n id,\n minSize,\n order,\n };\n\n registerPanel(id, panel);\n\n return () => {\n unregisterPanel(id);\n };\n }, [defaultSize, id, minSize, order, registerPanel, unregisterPanel]);\n\n const style = getPanelStyle(id);\n\n return (\n <div className={className} style={style}>\n {children}\n </div>\n );\n}\n","import { CSSProperties, createContext } from \"react\";\n\nimport { PanelData, ResizeHandler } from \"./types\";\n\nexport const PanelContext = createContext<{\n activeHandleId: string | null;\n} | null>(null);\n\nexport const PanelGroupContext = createContext<{\n direction: \"horizontal\" | \"vertical\";\n getPanelStyle: (id: string) => CSSProperties;\n groupId: string;\n registerPanel: (id: string, panel: PanelData) => void;\n registerResizeHandle: (id: string) => ResizeHandler;\n startDragging: (id: string) => void;\n stopDragging: () => void;\n unregisterPanel: (id: string) => void;\n} | null>(null);\n","import {\n CSSProperties,\n ReactNode,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport useUniqueId from \"./hooks/useUniqueId\";\n\nimport { PanelContext, PanelGroupContext } from \"./PanelContexts\";\nimport { Direction, PanelData } from \"./types\";\nimport { loadPanelLayout, savePanelGroupLayout } from \"./utils/serialization\";\n\ntype Props = {\n autoSaveId?: string;\n children?: ReactNode;\n className?: string;\n direction: Direction;\n height: number;\n width: number;\n};\n\nconst PRECISION = 5;\n\n// TODO [panels]\n// Within an active drag, remember original positions to refine more easily on expand.\n// Look at what the Chrome devtools Sources does.\n\nexport default function PanelGroup({\n autoSaveId,\n children = null,\n className = \"\",\n direction,\n height,\n width,\n}: Props) {\n const groupId = useUniqueId();\n\n const [activeHandleId, setActiveHandleId] = useState<string | null>(null);\n const [panels, setPanels] = useState<Map<string, PanelData>>(new Map());\n\n // 0-1 values representing the relative size of each panel.\n const [sizes, setSizes] = useState<number[]>([]);\n\n // Store committed values to avoid unnecessarily re-running memoization/effects functions.\n const committedValuesRef = useRef<{\n direction: Direction;\n height: number;\n panels: Map<string, PanelData>;\n sizes: number[];\n width: number;\n }>({\n direction,\n height,\n panels,\n sizes,\n width,\n });\n useLayoutEffect(() => {\n committedValuesRef.current.direction = direction;\n committedValuesRef.current.height = height;\n committedValuesRef.current.panels = panels;\n committedValuesRef.current.sizes = sizes;\n committedValuesRef.current.width = width;\n });\n\n // Once all panels have registered themselves,\n // Compute the initial sizes based on default weights.\n // This assumes that panels register during initial mount (no conditional rendering)!\n useLayoutEffect(() => {\n const sizes = committedValuesRef.current.sizes;\n if (sizes.length === panels.size) {\n return;\n }\n\n // TODO [panels]\n // Validate that the total minSize is <= 1.\n\n // If this panel has been configured to persist sizing information,\n // default size should be restored from local storage if possible.\n let defaultSizes: number[] | undefined = undefined;\n if (autoSaveId) {\n const panelIds = panelsMapToSortedArray(panels).map((panel) => panel.id);\n defaultSizes = loadPanelLayout(autoSaveId, panelIds);\n }\n\n if (defaultSizes != null) {\n setSizes(defaultSizes);\n } else {\n const panelsArray = panelsMapToSortedArray(panels);\n const totalWeight = panelsArray.reduce((weight, panel) => {\n return weight + panel.defaultSize;\n }, 0);\n\n setSizes(panelsArray.map((panel) => panel.defaultSize / totalWeight));\n }\n }, [autoSaveId, panels]);\n\n useEffect(() => {\n // If this panel has been configured to persist sizing information, save sizes to local storage.\n if (autoSaveId) {\n if (sizes.length === 0 || sizes.length !== panels.size) {\n return;\n }\n\n const panelIds = panelsMapToSortedArray(panels).map((panel) => panel.id);\n savePanelGroupLayout(autoSaveId, panelIds, sizes);\n }\n }, [autoSaveId, panels, sizes]);\n\n const getPanelStyle = useCallback(\n (id: string): CSSProperties => {\n const { panels } = committedValuesRef.current;\n\n const offset = getOffset(panels, id, direction, sizes, height, width);\n const size = getSize(panels, id, direction, sizes, height, width);\n\n if (direction === \"horizontal\") {\n return {\n height: \"100%\",\n position: \"absolute\",\n left: offset,\n top: 0,\n width: size,\n };\n } else {\n return {\n height: size,\n position: \"absolute\",\n left: 0,\n top: offset,\n width: \"100%\",\n };\n }\n },\n [direction, height, sizes, width]\n );\n\n const registerPanel = useCallback((id: string, panel: PanelData) => {\n setPanels((prevPanels) => {\n if (prevPanels.has(id)) {\n return prevPanels;\n }\n\n const nextPanels = new Map(prevPanels);\n nextPanels.set(id, panel);\n\n return nextPanels;\n });\n }, []);\n\n const registerResizeHandle = useCallback(\n (id: string) => {\n const resizeHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n const {\n direction,\n height,\n panels,\n sizes: prevSizes,\n width,\n } = committedValuesRef.current;\n\n const handle = document.querySelector(\n `[data-panel-resize-handle-id=\"${id}\"]`\n );\n const handles = Array.from(\n document.querySelectorAll(`[data-panel-group-id=\"${groupId}\"]`)\n );\n const index = handles.indexOf(handle);\n const panelsArray = panelsMapToSortedArray(panels);\n const idBefore: string | null = panelsArray[index]?.id ?? null;\n const idAfter: string | null = panelsArray[index + 1]?.id ?? null;\n if (idBefore == null || idAfter == null) {\n return;\n }\n\n const isHorizontal = direction === \"horizontal\";\n const movement = isHorizontal ? event.movementX : event.movementY;\n const delta = isHorizontal ? movement / width : movement / height;\n\n const nextSizes = adjustByDelta(\n panels,\n idBefore,\n idAfter,\n delta,\n prevSizes\n );\n if (prevSizes !== nextSizes) {\n setSizes(nextSizes);\n }\n };\n\n return resizeHandler;\n },\n [groupId]\n );\n\n const unregisterPanel = useCallback((id: string) => {\n setPanels((prevPanels) => {\n if (!prevPanels.has(id)) {\n return prevPanels;\n }\n\n const nextPanels = new Map(prevPanels);\n nextPanels.delete(id);\n\n return nextPanels;\n });\n }, []);\n\n const panelGroupContext = useMemo(\n () => ({\n direction,\n getPanelStyle,\n groupId,\n registerPanel,\n registerResizeHandle,\n startDragging: (id: string) => setActiveHandleId(id),\n stopDragging: () => setActiveHandleId(null),\n unregisterPanel,\n }),\n [\n direction,\n getPanelStyle,\n groupId,\n registerPanel,\n registerResizeHandle,\n unregisterPanel,\n ]\n );\n\n const panelContext = useMemo(\n () => ({\n activeHandleId,\n }),\n [activeHandleId]\n );\n\n return (\n <PanelContext.Provider value={panelContext}>\n <PanelGroupContext.Provider value={panelGroupContext}>\n <div className={className}>{children}</div>\n </PanelGroupContext.Provider>\n </PanelContext.Provider>\n );\n}\n\nfunction adjustByDelta(\n panels: Map<string, PanelData>,\n idBefore: string,\n idAfter: string,\n delta: number,\n prevSizes: number[]\n): number[] {\n if (delta === 0) {\n return prevSizes;\n }\n\n const panelsArray = panelsMapToSortedArray(panels);\n\n const nextSizes = prevSizes.concat();\n\n let deltaApplied = 0;\n\n // A resizing panel affects the panels before or after it.\n //\n // A negative delta means the panel immediately after the resizer should grow/expand by decreasing its offset.\n // Other panels may also need to shrink/contract (and shift) to make room, depending on the min weights.\n //\n // A positive delta means the panel immediately before the resizer should \"expand\".\n // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resizer.\n let pivotId = delta < 0 ? idBefore : idAfter;\n let index = panelsArray.findIndex((panel) => panel.id === pivotId);\n while (true) {\n const panel = panelsArray[index];\n const prevSize = prevSizes[index];\n const nextSize = Math.max(prevSize - Math.abs(delta), panel.minSize);\n if (prevSize !== nextSize) {\n deltaApplied += prevSize - nextSize;\n\n nextSizes[index] = nextSize;\n\n if (deltaApplied.toPrecision(PRECISION) >= delta.toPrecision(PRECISION)) {\n break;\n }\n }\n\n if (delta < 0) {\n if (--index < 0) {\n break;\n }\n } else {\n if (++index >= panelsArray.length) {\n break;\n }\n }\n }\n\n // If we were unable to resize any of the panels panels, return the previous state.\n // This will essentially bailout and ignore the \"mousemove\" event.\n if (deltaApplied === 0) {\n return prevSizes;\n }\n\n // Adjust the pivot panel before, but only by the amount that surrounding panels were able to shrink/contract.\n pivotId = delta < 0 ? idAfter : idBefore;\n index = panelsArray.findIndex((panel) => panel.id === pivotId);\n nextSizes[index] = prevSizes[index] + deltaApplied;\n\n return nextSizes;\n}\n\nfunction getOffset(\n panels: Map<string, PanelData>,\n id: string,\n direction: Direction,\n sizes: number[],\n height: number,\n width: number\n): number {\n const panelsArray = panelsMapToSortedArray(panels);\n\n let index = panelsArray.findIndex((panel) => panel.id === id);\n if (index < 0) {\n return 0;\n }\n\n let scaledOffset = 0;\n\n for (index = index - 1; index >= 0; index--) {\n const panel = panelsArray[index];\n scaledOffset += getSize(panels, panel.id, direction, sizes, height, width);\n }\n\n return Math.round(scaledOffset);\n}\n\nfunction getSize(\n panels: Map<string, PanelData>,\n id: string,\n direction: Direction,\n sizes: number[],\n height: number,\n width: number\n): number {\n const totalSize = direction === \"horizontal\" ? width : height;\n\n if (panels.size === 1) {\n return totalSize;\n }\n\n const panelsArray = panelsMapToSortedArray(panels);\n\n const index = panelsArray.findIndex((panel) => panel.id === id);\n const size = sizes[index];\n if (size == null) {\n return 0;\n }\n\n return Math.round(size * totalSize);\n}\n\nfunction panelsMapToSortedArray(panels: Map<string, PanelData>): PanelData[] {\n return Array.from(panels.values()).sort((a, b) => a.order - b.order);\n}\n","import { useRef } from \"react\";\n\nlet counter = 0;\n\nexport default function useUniqueId(id: string | null = null): string {\n const idRef = useRef<string | null>(id);\n if (idRef.current === null) {\n idRef.current = \"\" + counter++;\n }\n\n return idRef.current;\n}\n","import { PanelData } from \"../types\";\n\ntype SerializedPanelGroupState = { [panelIds: string]: number[] };\n\nfunction loadSerializedPanelGroupState(\n autoSaveId: string\n): SerializedPanelGroupState | null {\n try {\n const serialized = localStorage.getItem(`PanelGroup:sizes:${autoSaveId}`);\n if (serialized) {\n const parsed = JSON.parse(serialized);\n if (typeof parsed === \"object\" && parsed != null) {\n return parsed;\n }\n }\n } catch (error) {}\n\n return null;\n}\n\nexport function loadPanelLayout(\n autoSaveId: string,\n panelIds: string[]\n): number[] | null {\n const state = loadSerializedPanelGroupState(autoSaveId);\n if (state) {\n return state[panelIds.join(\",\")] ?? null;\n }\n\n return null;\n}\n\nexport function savePanelGroupLayout(\n autoSaveId: string,\n panelIds: string[],\n sizes: number[]\n): void {\n const state = loadSerializedPanelGroupState(autoSaveId) || {};\n state[panelIds.join(\",\")] = sizes;\n\n try {\n localStorage.setItem(\n `PanelGroup:sizes:${autoSaveId}`,\n JSON.stringify(state)\n );\n } catch (error) {\n console.error(error);\n }\n}\n","import { ReactNode, useContext, useEffect, useState } from \"react\";\n\nimport useUniqueId from \"./hooks/useUniqueId\";\nimport { PanelContext, PanelGroupContext } from \"./PanelContexts\";\nimport { ResizeHandler } from \"./types\";\n\nexport default function PanelResizeHandle({\n children = null,\n className = \"\",\n disabled = false,\n id: idProp = null,\n}: {\n children?: ReactNode;\n className?: string;\n disabled?: boolean;\n id?: string | null;\n}) {\n const panelContext = useContext(PanelContext);\n const panelGroupContext = useContext(PanelGroupContext);\n if (panelContext === null || panelGroupContext === null) {\n throw Error(\n `PanelResizeHandle components must be rendered within a PanelGroup container`\n );\n }\n\n const id = useUniqueId(idProp);\n\n const { activeHandleId } = panelContext;\n const {\n direction,\n groupId,\n registerResizeHandle,\n startDragging,\n stopDragging,\n } = panelGroupContext;\n\n const isDragging = activeHandleId === id;\n\n const [resizeHandler, setResizeHandler] = useState<ResizeHandler | null>(\n null\n );\n\n useEffect(() => {\n if (disabled) {\n setResizeHandler(null);\n } else {\n const resizeHandler = registerResizeHandle(id);\n setResizeHandler(() => resizeHandler);\n }\n }, [disabled, groupId, id, registerResizeHandle]);\n\n useEffect(() => {\n if (disabled || resizeHandler == null || !isDragging) {\n return;\n }\n\n document.body.style.cursor =\n direction === \"horizontal\" ? \"ew-resize\" : \"ns-resize\";\n\n const onMouseMove = (event: MouseEvent) => {\n resizeHandler(event);\n };\n\n document.body.addEventListener(\"mouseleave\", stopDragging);\n document.body.addEventListener(\"mousemove\", onMouseMove);\n document.body.addEventListener(\"touchmove\", onMouseMove);\n document.body.addEventListener(\"mouseup\", stopDragging);\n\n return () => {\n document.body.style.cursor = \"\";\n\n document.body.removeEventListener(\"mouseleave\", stopDragging);\n document.body.removeEventListener(\"mousemove\", onMouseMove);\n document.body.removeEventListener(\"touchmove\", onMouseMove);\n document.body.removeEventListener(\"mouseup\", stopDragging);\n };\n }, [direction, disabled, isDragging, resizeHandler, stopDragging]);\n\n return (\n <div\n className={className}\n data-panel-group-id={groupId}\n data-panel-resize-handle-id={id}\n onMouseDown={() => startDragging(id)}\n onMouseUp={stopDragging}\n onTouchStart={() => startDragging(id)}\n onTouchEnd={stopDragging}\n style={{\n cursor: direction === \"horizontal\" ? \"ew-resize\" : \"ns-resize\",\n }}\n >\n {children}\n </div>\n );\n}\n"],"names":[],"version":3,"file":"react-resizable-panels.module.js.map","sourceRoot":"../../../"}
|
|
1
|
+
{"mappings":"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","sources":["packages/react-resizable-panels/src/index.ts","packages/react-resizable-panels/src/Panel.tsx","packages/react-resizable-panels/src/PanelContexts.ts","packages/react-resizable-panels/src/PanelGroup.tsx","packages/react-resizable-panels/src/hooks/useUniqueId.ts","packages/react-resizable-panels/src/utils/serialization.ts","packages/react-resizable-panels/src/utils/coordinates.ts","packages/react-resizable-panels/src/utils/group.ts","packages/react-resizable-panels/src/constants.ts","packages/react-resizable-panels/src/hooks/useWindowSplitterBehavior.ts","packages/react-resizable-panels/src/PanelResizeHandle.tsx"],"sourcesContent":["import Panel from \"./Panel\";\nimport { PanelContext } from \"./PanelContexts\";\nimport PanelGroup from \"./PanelGroup\";\nimport PanelResizeHandle from \"./PanelResizeHandle\";\n\nexport { Panel, PanelContext, PanelGroup, PanelResizeHandle };\n","import { ReactNode, useContext, useLayoutEffect } from \"react\";\n\nimport { PanelGroupContext } from \"./PanelContexts\";\n\n// TODO [panels]\n// Support min pixel size too.\n// PanelGroup should warn if total width is less min pixel widths.\nexport default function Panel({\n children = null,\n className = \"\",\n defaultSize = 0.1,\n id,\n minSize = 0.1,\n order = null,\n}: {\n children?: ReactNode;\n className?: string;\n defaultSize?: number;\n id: string;\n minSize?: number;\n order?: number | null;\n}) {\n const context = useContext(PanelGroupContext);\n if (context === null) {\n throw Error(\n `Panel components must be rendered within a PanelGroup container`\n );\n }\n\n if (minSize > defaultSize) {\n console.error(\n `Panel minSize ${minSize} cannot be greater than defaultSize ${defaultSize}`\n );\n\n defaultSize = minSize;\n }\n\n const { getPanelStyle, registerPanel, unregisterPanel } = context;\n\n useLayoutEffect(() => {\n const panel = {\n defaultSize,\n id,\n minSize,\n order,\n };\n\n registerPanel(id, panel);\n\n return () => {\n unregisterPanel(id);\n };\n }, [defaultSize, id, minSize, order, registerPanel, unregisterPanel]);\n\n const style = getPanelStyle(id);\n\n return (\n <div\n className={className}\n data-panel-id={id}\n id={`data-panel-id-${id}`}\n style={style}\n >\n {children}\n </div>\n );\n}\n","import { CSSProperties, createContext } from \"react\";\n\nimport { PanelData, ResizeHandler } from \"./types\";\n\nexport const PanelContext = createContext<{\n activeHandleId: string | null;\n} | null>(null);\n\nexport const PanelGroupContext = createContext<{\n direction: \"horizontal\" | \"vertical\";\n getPanelStyle: (id: string) => CSSProperties;\n groupId: string;\n registerPanel: (id: string, panel: PanelData) => void;\n registerResizeHandle: (id: string) => ResizeHandler;\n startDragging: (id: string) => void;\n stopDragging: () => void;\n unregisterPanel: (id: string) => void;\n} | null>(null);\n","import {\n CSSProperties,\n ReactNode,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport useUniqueId from \"./hooks/useUniqueId\";\n\nimport { PanelContext, PanelGroupContext } from \"./PanelContexts\";\nimport { Direction, PanelData, ResizeEvent } from \"./types\";\nimport { loadPanelLayout, savePanelGroupLayout } from \"./utils/serialization\";\nimport { Coordinates, getUpdatedCoordinates } from \"./utils/coordinates\";\nimport {\n adjustByDelta,\n getOffset,\n getResizeHandlePanelIds,\n getSize,\n panelsMapToSortedArray,\n} from \"./utils/group\";\nimport { useWindowSplitterPanelGroupBehavior } from \"./hooks/useWindowSplitterBehavior\";\n\nexport type CommittedValues = {\n direction: Direction;\n height: number;\n panels: Map<string, PanelData>;\n sizes: number[];\n width: number;\n};\n\nexport type PanelDataMap = Map<string, PanelData>;\n\ntype Props = {\n autoSaveId?: string;\n children?: ReactNode;\n className?: string;\n direction: Direction;\n height: number;\n width: number;\n};\n\n// TODO [panels]\n// Within an active drag, remember original positions to refine more easily on expand.\n// Look at what the Chrome devtools Sources does.\n\nexport default function PanelGroup({\n autoSaveId,\n children = null,\n className = \"\",\n direction,\n height,\n width,\n}: Props) {\n const groupId = useUniqueId();\n\n const [activeHandleId, setActiveHandleId] = useState<string | null>(null);\n const [panels, setPanels] = useState<PanelDataMap>(new Map());\n\n // 0-1 values representing the relative size of each panel.\n const [sizes, setSizes] = useState<number[]>([]);\n\n // Store committed values to avoid unnecessarily re-running memoization/effects functions.\n const committedValuesRef = useRef<CommittedValues>({\n direction,\n height,\n panels,\n sizes,\n width,\n });\n\n // Tracks the most recent coordinates of a touch/mouse event.\n // This is needed to calculate movement (because TouchEvent doesn't support movementX and movementY).\n const prevCoordinatesRef = useRef<Coordinates>({\n screenX: 0,\n screenY: 0,\n });\n\n useLayoutEffect(() => {\n committedValuesRef.current.direction = direction;\n committedValuesRef.current.height = height;\n committedValuesRef.current.panels = panels;\n committedValuesRef.current.sizes = sizes;\n committedValuesRef.current.width = width;\n });\n\n useWindowSplitterPanelGroupBehavior({\n committedValuesRef,\n groupId,\n panels,\n setSizes,\n sizes,\n });\n\n // Once all panels have registered themselves,\n // Compute the initial sizes based on default weights.\n // This assumes that panels register during initial mount (no conditional rendering)!\n useLayoutEffect(() => {\n const sizes = committedValuesRef.current.sizes;\n if (sizes.length === panels.size) {\n return;\n }\n\n // TODO [panels]\n // Validate that the total minSize is <= 1.\n\n // If this panel has been configured to persist sizing information,\n // default size should be restored from local storage if possible.\n let defaultSizes: number[] | undefined = undefined;\n if (autoSaveId) {\n const panelIds = panelsMapToSortedArray(panels).map((panel) => panel.id);\n defaultSizes = loadPanelLayout(autoSaveId, panelIds);\n }\n\n if (defaultSizes != null) {\n setSizes(defaultSizes);\n } else {\n const panelsArray = panelsMapToSortedArray(panels);\n const totalWeight = panelsArray.reduce((weight, panel) => {\n return weight + panel.defaultSize;\n }, 0);\n\n setSizes(panelsArray.map((panel) => panel.defaultSize / totalWeight));\n }\n }, [autoSaveId, panels]);\n\n useEffect(() => {\n // If this panel has been configured to persist sizing information, save sizes to local storage.\n if (autoSaveId) {\n if (sizes.length === 0 || sizes.length !== panels.size) {\n return;\n }\n\n const panelIds = panelsMapToSortedArray(panels).map((panel) => panel.id);\n savePanelGroupLayout(autoSaveId, panelIds, sizes);\n }\n }, [autoSaveId, panels, sizes]);\n\n const getPanelStyle = useCallback(\n (id: string): CSSProperties => {\n const { panels } = committedValuesRef.current;\n\n const offset = getOffset(panels, id, direction, sizes, height, width);\n const size = getSize(panels, id, direction, sizes, height, width);\n\n if (direction === \"horizontal\") {\n return {\n height: \"100%\",\n position: \"absolute\",\n left: offset,\n top: 0,\n width: size,\n };\n } else {\n return {\n height: size,\n position: \"absolute\",\n left: 0,\n top: offset,\n width: \"100%\",\n };\n }\n },\n [direction, height, sizes, width]\n );\n\n const registerPanel = useCallback((id: string, panel: PanelData) => {\n setPanels((prevPanels) => {\n if (prevPanels.has(id)) {\n return prevPanels;\n }\n\n const nextPanels = new Map(prevPanels);\n nextPanels.set(id, panel);\n\n return nextPanels;\n });\n }, []);\n\n const registerResizeHandle = useCallback(\n (handleId: string) => {\n const resizeHandler = (event: ResizeEvent) => {\n event.preventDefault();\n\n const {\n direction,\n height,\n panels,\n sizes: prevSizes,\n width,\n } = committedValuesRef.current;\n\n const panelsArray = panelsMapToSortedArray(panels);\n\n const [idBefore, idAfter] = getResizeHandlePanelIds(\n groupId,\n handleId,\n panelsArray\n );\n if (idBefore == null || idAfter == null) {\n return;\n }\n\n const nextCoordinates = getUpdatedCoordinates(\n event,\n prevCoordinatesRef.current,\n { height, width },\n direction\n );\n prevCoordinatesRef.current = {\n screenX: nextCoordinates.screenX,\n screenY: nextCoordinates.screenY,\n };\n\n const isHorizontal = direction === \"horizontal\";\n const movement = isHorizontal\n ? nextCoordinates.movementX\n : nextCoordinates.movementY;\n const delta = isHorizontal ? movement / width : movement / height;\n\n const nextSizes = adjustByDelta(\n panels,\n idBefore,\n idAfter,\n delta,\n prevSizes\n );\n if (prevSizes !== nextSizes) {\n setSizes(nextSizes);\n }\n };\n\n return resizeHandler;\n },\n [groupId]\n );\n\n const unregisterPanel = useCallback((id: string) => {\n setPanels((prevPanels) => {\n if (!prevPanels.has(id)) {\n return prevPanels;\n }\n\n const nextPanels = new Map(prevPanels);\n nextPanels.delete(id);\n\n return nextPanels;\n });\n }, []);\n\n const panelGroupContext = useMemo(\n () => ({\n direction,\n getPanelStyle,\n groupId,\n registerPanel,\n registerResizeHandle,\n startDragging: (id: string) => setActiveHandleId(id),\n stopDragging: () => {\n setActiveHandleId(null);\n prevCoordinatesRef.current = {\n screenX: 0,\n screenY: 0,\n };\n },\n unregisterPanel,\n }),\n [\n direction,\n getPanelStyle,\n groupId,\n registerPanel,\n registerResizeHandle,\n unregisterPanel,\n ]\n );\n\n const panelContext = useMemo(\n () => ({\n activeHandleId,\n }),\n [activeHandleId]\n );\n\n return (\n <PanelContext.Provider value={panelContext}>\n <PanelGroupContext.Provider value={panelGroupContext}>\n <div className={className}>{children}</div>\n </PanelGroupContext.Provider>\n </PanelContext.Provider>\n );\n}\n","import { useRef } from \"react\";\n\nlet counter = 0;\n\nexport default function useUniqueId(id: string | null = null): string {\n const idRef = useRef<string | null>(id);\n if (idRef.current === null) {\n idRef.current = \"\" + counter++;\n }\n\n return idRef.current;\n}\n","import { PanelData } from \"../types\";\n\ntype SerializedPanelGroupState = { [panelIds: string]: number[] };\n\nfunction loadSerializedPanelGroupState(\n autoSaveId: string\n): SerializedPanelGroupState | null {\n try {\n const serialized = localStorage.getItem(`PanelGroup:sizes:${autoSaveId}`);\n if (serialized) {\n const parsed = JSON.parse(serialized);\n if (typeof parsed === \"object\" && parsed != null) {\n return parsed;\n }\n }\n } catch (error) {}\n\n return null;\n}\n\nexport function loadPanelLayout(\n autoSaveId: string,\n panelIds: string[]\n): number[] | null {\n const state = loadSerializedPanelGroupState(autoSaveId);\n if (state) {\n return state[panelIds.join(\",\")] ?? null;\n }\n\n return null;\n}\n\nexport function savePanelGroupLayout(\n autoSaveId: string,\n panelIds: string[],\n sizes: number[]\n): void {\n const state = loadSerializedPanelGroupState(autoSaveId) || {};\n state[panelIds.join(\",\")] = sizes;\n\n try {\n localStorage.setItem(\n `PanelGroup:sizes:${autoSaveId}`,\n JSON.stringify(state)\n );\n } catch (error) {\n console.error(error);\n }\n}\n","import { Direction, ResizeEvent } from \"../types\";\n\nexport type Coordinates = {\n screenX: number;\n screenY: number;\n};\n\nexport type Dimensions = {\n height: number;\n width: number;\n};\n\nexport type Movement = {\n movementX: number;\n movementY: number;\n};\n\nconst element = document.createElement(\"div\");\nelement.getBoundingClientRect();\n\n// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX\nexport function getUpdatedCoordinates(\n event: ResizeEvent,\n prevCoordinates: Coordinates,\n dimensions: Dimensions,\n direction: Direction\n): Coordinates & Movement {\n const { screenX: prevScreenX, screenY: prevScreenY } = prevCoordinates;\n const { height, width } = dimensions;\n\n const getMovementBetween = (current: number, prev: number) =>\n prev === 0 ? 0 : current - prev;\n\n if (isKeyDown(event)) {\n let movementX = 0;\n let movementY = 0;\n\n const size = direction === \"horizontal\" ? width : height;\n const denominator = event.shiftKey ? 10 : 100;\n const delta = size / denominator;\n\n switch (event.key) {\n case \"ArrowDown\":\n movementY = delta;\n break;\n case \"ArrowLeft\":\n movementX = -delta;\n break;\n case \"ArrowRight\":\n movementX = delta;\n break;\n case \"ArrowUp\":\n movementY = -delta;\n break;\n case \"End\":\n if (direction === \"horizontal\") {\n movementX = size;\n } else {\n movementY = size;\n }\n break;\n case \"Home\":\n if (direction === \"horizontal\") {\n movementX = -size;\n } else {\n movementY = -size;\n }\n break;\n }\n\n // Estimate screen X/Y to be the center of the resize handle.\n // Otherwise the first mouse/touch event after a keyboard event will appear to \"jump\"\n let screenX = 0;\n let screenY = 0;\n if (document.activeElement) {\n const rect = document.activeElement.getBoundingClientRect();\n screenX = rect.left + rect.width / 2;\n screenY = rect.top + rect.height / 2;\n }\n\n return {\n movementX,\n movementY,\n screenX,\n screenY,\n };\n } else if (isTouchMoveEvent(event)) {\n const firstTouch = event.touches[0];\n\n return {\n movementX: getMovementBetween(firstTouch.screenX, prevScreenX),\n movementY: getMovementBetween(firstTouch.screenY, prevScreenY),\n screenX: firstTouch.screenX,\n screenY: firstTouch.screenY,\n };\n } else if (isMouseMoveEvent(event)) {\n return {\n movementX: getMovementBetween(event.screenX, prevScreenX),\n movementY: getMovementBetween(event.screenY, prevScreenY),\n screenX: event.screenX,\n screenY: event.screenY,\n };\n } else {\n throw Error(`Unsupported event type: \"${(event as any).type}\"`);\n }\n}\n\nexport function isKeyDown(event: ResizeEvent): event is KeyboardEvent {\n return event.type === \"keydown\";\n}\n\nexport function isMouseMoveEvent(event: ResizeEvent): event is MouseEvent {\n return event.type === \"mousemove\";\n}\n\nexport function isTouchMoveEvent(event: ResizeEvent): event is TouchEvent {\n return event.type === \"touchmove\";\n}\n","import { PRECISION } from \"../constants\";\nimport { Direction, PanelData } from \"../types\";\n\nexport function adjustByDelta(\n panels: Map<string, PanelData>,\n idBefore: string,\n idAfter: string,\n delta: number,\n prevSizes: number[]\n): number[] {\n if (delta === 0) {\n return prevSizes;\n }\n\n const panelsArray = panelsMapToSortedArray(panels);\n\n const nextSizes = prevSizes.concat();\n\n let deltaApplied = 0;\n\n // A resizing panel affects the panels before or after it.\n //\n // A negative delta means the panel immediately after the resizer should grow/expand by decreasing its offset.\n // Other panels may also need to shrink/contract (and shift) to make room, depending on the min weights.\n //\n // A positive delta means the panel immediately before the resizer should \"expand\".\n // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resizer.\n let pivotId = delta < 0 ? idBefore : idAfter;\n let index = panelsArray.findIndex((panel) => panel.id === pivotId);\n while (true) {\n const panel = panelsArray[index];\n const prevSize = prevSizes[index];\n const nextSize = Math.max(prevSize - Math.abs(delta), panel.minSize);\n if (prevSize !== nextSize) {\n deltaApplied += prevSize - nextSize;\n\n nextSizes[index] = nextSize;\n\n if (deltaApplied.toPrecision(PRECISION) >= delta.toPrecision(PRECISION)) {\n break;\n }\n }\n\n if (delta < 0) {\n if (--index < 0) {\n break;\n }\n } else {\n if (++index >= panelsArray.length) {\n break;\n }\n }\n }\n\n // If we were unable to resize any of the panels panels, return the previous state.\n // This will essentially bailout and ignore the \"mousemove\" event.\n if (deltaApplied === 0) {\n return prevSizes;\n }\n\n // Adjust the pivot panel before, but only by the amount that surrounding panels were able to shrink/contract.\n pivotId = delta < 0 ? idAfter : idBefore;\n index = panelsArray.findIndex((panel) => panel.id === pivotId);\n nextSizes[index] = prevSizes[index] + deltaApplied;\n\n return nextSizes;\n}\n\nexport function getOffset(\n panels: Map<string, PanelData>,\n id: string,\n direction: Direction,\n sizes: number[],\n height: number,\n width: number\n): number {\n const panelsArray = panelsMapToSortedArray(panels);\n\n let index = panelsArray.findIndex((panel) => panel.id === id);\n if (index < 0) {\n return 0;\n }\n\n let scaledOffset = 0;\n\n for (index = index - 1; index >= 0; index--) {\n const panel = panelsArray[index];\n scaledOffset += getSize(panels, panel.id, direction, sizes, height, width);\n }\n\n return Math.round(scaledOffset);\n}\n\nexport function getPanel(id: string): HTMLDivElement | null {\n const element = document.querySelector(`[data-panel-id=\"${id}\"]`);\n if (element) {\n return element as HTMLDivElement;\n }\n return null;\n}\n\nexport function getResizeHandle(id: string): HTMLDivElement | null {\n const element = document.querySelector(\n `[data-panel-resize-handle-id=\"${id}\"]`\n );\n if (element) {\n return element as HTMLDivElement;\n }\n return null;\n}\n\nexport function getResizeHandleIndex(id: string): number | null {\n const handles = getResizeHandles();\n const index = handles.findIndex(\n (handle) => handle.getAttribute(\"data-panel-resize-handle-id\") === id\n );\n return index ?? null;\n}\n\nexport function getResizeHandles(): HTMLDivElement[] {\n return Array.from(document.querySelectorAll(`[data-panel-resize-handle-id]`));\n}\n\nexport function getResizeHandlesForGroup(groupId: string): HTMLDivElement[] {\n return Array.from(\n document.querySelectorAll(\n `[data-panel-resize-handle-id][data-panel-group-id=\"${groupId}\"]`\n )\n );\n}\n\nexport function getResizeHandlePanelIds(\n groupId: string,\n handleId: string,\n panelsArray: PanelData[]\n): [idBefore: string | null, idAfter: string | null] {\n const handle = getResizeHandle(handleId);\n const handles = getResizeHandlesForGroup(groupId);\n const index = handles.indexOf(handle);\n\n const idBefore: string | null = panelsArray[index]?.id ?? null;\n const idAfter: string | null = panelsArray[index + 1]?.id ?? null;\n\n return [idBefore, idAfter];\n}\n\nexport function panelsMapToSortedArray(\n panels: Map<string, PanelData>\n): PanelData[] {\n return Array.from(panels.values()).sort((a, b) => a.order - b.order);\n}\n\nexport function getSize(\n panels: Map<string, PanelData>,\n id: string,\n direction: Direction,\n sizes: number[],\n height: number,\n width: number\n): number {\n const totalSize = direction === \"horizontal\" ? width : height;\n\n if (panels.size === 1) {\n return totalSize;\n }\n\n const panelsArray = panelsMapToSortedArray(panels);\n\n const index = panelsArray.findIndex((panel) => panel.id === id);\n const size = sizes[index];\n if (size == null) {\n return 0;\n }\n\n return Math.round(size * totalSize);\n}\n","export const PRECISION = 5;\n","import { RefObject, useEffect } from \"react\";\nimport { PRECISION } from \"../constants\";\n\nimport { CommittedValues, PanelDataMap } from \"../PanelGroup\";\nimport { ResizeHandler } from \"../types\";\nimport {\n adjustByDelta,\n getPanel,\n getResizeHandle,\n getResizeHandleIndex,\n getResizeHandlePanelIds,\n getResizeHandles,\n getResizeHandlesForGroup,\n getSize,\n panelsMapToSortedArray,\n} from \"../utils/group\";\n\n// https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/\n\nexport function useWindowSplitterPanelGroupBehavior({\n committedValuesRef,\n groupId,\n panels,\n setSizes,\n sizes,\n}: {\n committedValuesRef: RefObject<CommittedValues>;\n groupId: string;\n panels: PanelDataMap;\n setSizes: (sizes: number[]) => void;\n sizes: number[];\n}): void {\n useEffect(() => {\n const { direction, height, panels, width } = committedValuesRef.current;\n\n const handles = getResizeHandlesForGroup(groupId);\n const cleanupFunctions = handles.map((handle) => {\n const handleId = handle.getAttribute(\"data-panel-resize-handle-id\");\n const panelsArray = panelsMapToSortedArray(panels);\n\n const [idBefore, idAfter] = getResizeHandlePanelIds(\n groupId,\n handleId,\n panelsArray\n );\n if (idBefore == null || idAfter == null) {\n return () => {};\n }\n\n const ariaValueMax = panelsArray.reduce((difference, panel) => {\n if (panel.id !== idBefore) {\n return difference - panel.minSize;\n }\n return difference;\n }, 1);\n\n const ariaValueMin =\n panelsArray.find((panel) => panel.id == idBefore)?.minSize ?? 0;\n\n const size = getSize(panels, idBefore, direction, sizes, height, width);\n const ariaValueNow = size / (direction === \"horizontal\" ? width : height);\n\n handle.setAttribute(\"aria-valuemax\", \"\" + Math.round(100 * ariaValueMax));\n handle.setAttribute(\"aria-valuemin\", \"\" + Math.round(100 * ariaValueMin));\n handle.setAttribute(\"aria-valuenow\", \"\" + Math.round(100 * ariaValueNow));\n\n const onKeyDown = (event: KeyboardEvent) => {\n switch (event.key) {\n case \"Enter\": {\n const index = panelsArray.findIndex(\n (panel) => panel.id === idBefore\n );\n if (index >= 0) {\n const panelData = panelsArray[index];\n const size = sizes[index];\n if (size != null) {\n let delta = 0;\n if (\n size.toPrecision(PRECISION) <=\n panelData.minSize.toPrecision(PRECISION)\n ) {\n delta = direction === \"horizontal\" ? width : height;\n } else {\n delta = -(direction === \"horizontal\" ? width : height);\n }\n\n const nextSizes = adjustByDelta(\n panels,\n idBefore,\n idAfter,\n delta,\n sizes\n );\n if (sizes !== nextSizes) {\n setSizes(nextSizes);\n }\n }\n }\n break;\n }\n }\n };\n\n handle.addEventListener(\"keydown\", onKeyDown);\n\n const panelBefore = getPanel(idBefore);\n if (panelBefore != null) {\n handle.setAttribute(\"aria-controls\", panelBefore.id);\n }\n\n return () => {\n handle.removeAttribute(\"aria-valuemax\");\n handle.removeAttribute(\"aria-valuemin\");\n handle.removeAttribute(\"aria-valuenow\");\n\n handle.removeEventListener(\"keydown\", onKeyDown);\n\n if (panelBefore != null) {\n handle.removeAttribute(\"aria-controls\");\n }\n };\n });\n\n return () => {\n cleanupFunctions.forEach((cleanupFunction) => cleanupFunction());\n };\n }, [groupId, panels, sizes]);\n}\n\nexport function useWindowSplitterResizeHandlerBehavior({\n disabled,\n handleId,\n resizeHandler,\n}: {\n disabled: boolean;\n handleId: string;\n resizeHandler: ResizeHandler | null;\n}): void {\n useEffect(() => {\n if (disabled || resizeHandler == null) {\n return;\n }\n\n const handleElement = getResizeHandle(handleId);\n if (handleElement == null) {\n return;\n }\n\n const onKeyDown = (event: KeyboardEvent) => {\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowLeft\":\n case \"ArrowRight\":\n case \"ArrowUp\":\n case \"End\":\n case \"Home\": {\n resizeHandler(event);\n break;\n }\n case \"F6\": {\n const handles = getResizeHandles();\n const index = getResizeHandleIndex(handleId);\n\n const nextIndex = event.shiftKey\n ? index > 0\n ? index - 1\n : handles.length - 1\n : index + 1 < handles.length\n ? index + 1\n : 0;\n\n const nextHandle = handles[nextIndex] as HTMLDivElement;\n nextHandle.focus();\n\n break;\n }\n }\n };\n\n handleElement.addEventListener(\"keydown\", onKeyDown);\n return () => {\n handleElement.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [disabled, handleId, resizeHandler]);\n}\n","import { ReactNode, useContext, useEffect, useState } from \"react\";\n\nimport useUniqueId from \"./hooks/useUniqueId\";\nimport { useWindowSplitterResizeHandlerBehavior } from \"./hooks/useWindowSplitterBehavior\";\nimport { PanelContext, PanelGroupContext } from \"./PanelContexts\";\nimport type { ResizeHandler, ResizeEvent } from \"./types\";\n\nexport default function PanelResizeHandle({\n children = null,\n className = \"\",\n disabled = false,\n id: idProp = null,\n}: {\n children?: ReactNode;\n className?: string;\n disabled?: boolean;\n id?: string | null;\n}) {\n const panelContext = useContext(PanelContext);\n const panelGroupContext = useContext(PanelGroupContext);\n if (panelContext === null || panelGroupContext === null) {\n throw Error(\n `PanelResizeHandle components must be rendered within a PanelGroup container`\n );\n }\n\n const id = useUniqueId(idProp);\n\n const { activeHandleId } = panelContext;\n const {\n direction,\n groupId,\n registerResizeHandle,\n startDragging,\n stopDragging,\n } = panelGroupContext;\n\n const isDragging = activeHandleId === id;\n\n const [resizeHandler, setResizeHandler] = useState<ResizeHandler | null>(\n null\n );\n\n useEffect(() => {\n if (disabled) {\n setResizeHandler(null);\n } else {\n const resizeHandler = registerResizeHandle(id);\n setResizeHandler(() => resizeHandler);\n }\n }, [disabled, id, registerResizeHandle]);\n\n useEffect(() => {\n if (disabled || resizeHandler == null || !isDragging) {\n return;\n }\n\n document.body.style.cursor =\n direction === \"horizontal\" ? \"ew-resize\" : \"ns-resize\";\n\n const onMove = (event: ResizeEvent) => {\n resizeHandler(event);\n };\n\n document.body.addEventListener(\"mouseleave\", stopDragging);\n document.body.addEventListener(\"mousemove\", onMove);\n document.body.addEventListener(\"touchmove\", onMove);\n document.body.addEventListener(\"mouseup\", stopDragging);\n\n return () => {\n document.body.style.cursor = \"\";\n\n document.body.removeEventListener(\"mouseleave\", stopDragging);\n document.body.removeEventListener(\"mousemove\", onMove);\n document.body.removeEventListener(\"touchmove\", onMove);\n document.body.removeEventListener(\"mouseup\", stopDragging);\n };\n }, [direction, disabled, isDragging, resizeHandler, stopDragging]);\n\n useWindowSplitterResizeHandlerBehavior({\n disabled,\n handleId: id,\n resizeHandler,\n });\n\n return (\n <div\n className={className}\n data-panel-group-id={groupId}\n data-panel-resize-handle-enabled={!disabled}\n data-panel-resize-handle-id={id}\n onMouseDown={() => startDragging(id)}\n onMouseUp={stopDragging}\n onTouchCancel={stopDragging}\n onTouchEnd={stopDragging}\n onTouchStart={() => startDragging(id)}\n role=\"separator\"\n style={{\n cursor: direction === \"horizontal\" ? \"ew-resize\" : \"ns-resize\",\n touchAction: \"none\",\n }}\n tabIndex={0}\n >\n {children}\n </div>\n );\n}\n"],"names":[],"version":3,"file":"react-resizable-panels.module.js.map","sourceRoot":"../../../"}
|
package/package.json
CHANGED
package/src/Panel.tsx
CHANGED
|
@@ -55,7 +55,12 @@ export default function Panel({
|
|
|
55
55
|
const style = getPanelStyle(id);
|
|
56
56
|
|
|
57
57
|
return (
|
|
58
|
-
<div
|
|
58
|
+
<div
|
|
59
|
+
className={className}
|
|
60
|
+
data-panel-id={id}
|
|
61
|
+
id={`data-panel-id-${id}`}
|
|
62
|
+
style={style}
|
|
63
|
+
>
|
|
59
64
|
{children}
|
|
60
65
|
</div>
|
|
61
66
|
);
|
package/src/PanelGroup.tsx
CHANGED
|
@@ -11,8 +11,27 @@ import {
|
|
|
11
11
|
import useUniqueId from "./hooks/useUniqueId";
|
|
12
12
|
|
|
13
13
|
import { PanelContext, PanelGroupContext } from "./PanelContexts";
|
|
14
|
-
import { Direction, PanelData } from "./types";
|
|
14
|
+
import { Direction, PanelData, ResizeEvent } from "./types";
|
|
15
15
|
import { loadPanelLayout, savePanelGroupLayout } from "./utils/serialization";
|
|
16
|
+
import { Coordinates, getUpdatedCoordinates } from "./utils/coordinates";
|
|
17
|
+
import {
|
|
18
|
+
adjustByDelta,
|
|
19
|
+
getOffset,
|
|
20
|
+
getResizeHandlePanelIds,
|
|
21
|
+
getSize,
|
|
22
|
+
panelsMapToSortedArray,
|
|
23
|
+
} from "./utils/group";
|
|
24
|
+
import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterBehavior";
|
|
25
|
+
|
|
26
|
+
export type CommittedValues = {
|
|
27
|
+
direction: Direction;
|
|
28
|
+
height: number;
|
|
29
|
+
panels: Map<string, PanelData>;
|
|
30
|
+
sizes: number[];
|
|
31
|
+
width: number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type PanelDataMap = Map<string, PanelData>;
|
|
16
35
|
|
|
17
36
|
type Props = {
|
|
18
37
|
autoSaveId?: string;
|
|
@@ -23,8 +42,6 @@ type Props = {
|
|
|
23
42
|
width: number;
|
|
24
43
|
};
|
|
25
44
|
|
|
26
|
-
const PRECISION = 5;
|
|
27
|
-
|
|
28
45
|
// TODO [panels]
|
|
29
46
|
// Within an active drag, remember original positions to refine more easily on expand.
|
|
30
47
|
// Look at what the Chrome devtools Sources does.
|
|
@@ -40,25 +57,27 @@ export default function PanelGroup({
|
|
|
40
57
|
const groupId = useUniqueId();
|
|
41
58
|
|
|
42
59
|
const [activeHandleId, setActiveHandleId] = useState<string | null>(null);
|
|
43
|
-
const [panels, setPanels] = useState<
|
|
60
|
+
const [panels, setPanels] = useState<PanelDataMap>(new Map());
|
|
44
61
|
|
|
45
62
|
// 0-1 values representing the relative size of each panel.
|
|
46
63
|
const [sizes, setSizes] = useState<number[]>([]);
|
|
47
64
|
|
|
48
65
|
// Store committed values to avoid unnecessarily re-running memoization/effects functions.
|
|
49
|
-
const committedValuesRef = useRef<{
|
|
50
|
-
direction: Direction;
|
|
51
|
-
height: number;
|
|
52
|
-
panels: Map<string, PanelData>;
|
|
53
|
-
sizes: number[];
|
|
54
|
-
width: number;
|
|
55
|
-
}>({
|
|
66
|
+
const committedValuesRef = useRef<CommittedValues>({
|
|
56
67
|
direction,
|
|
57
68
|
height,
|
|
58
69
|
panels,
|
|
59
70
|
sizes,
|
|
60
71
|
width,
|
|
61
72
|
});
|
|
73
|
+
|
|
74
|
+
// Tracks the most recent coordinates of a touch/mouse event.
|
|
75
|
+
// This is needed to calculate movement (because TouchEvent doesn't support movementX and movementY).
|
|
76
|
+
const prevCoordinatesRef = useRef<Coordinates>({
|
|
77
|
+
screenX: 0,
|
|
78
|
+
screenY: 0,
|
|
79
|
+
});
|
|
80
|
+
|
|
62
81
|
useLayoutEffect(() => {
|
|
63
82
|
committedValuesRef.current.direction = direction;
|
|
64
83
|
committedValuesRef.current.height = height;
|
|
@@ -67,6 +86,14 @@ export default function PanelGroup({
|
|
|
67
86
|
committedValuesRef.current.width = width;
|
|
68
87
|
});
|
|
69
88
|
|
|
89
|
+
useWindowSplitterPanelGroupBehavior({
|
|
90
|
+
committedValuesRef,
|
|
91
|
+
groupId,
|
|
92
|
+
panels,
|
|
93
|
+
setSizes,
|
|
94
|
+
sizes,
|
|
95
|
+
});
|
|
96
|
+
|
|
70
97
|
// Once all panels have registered themselves,
|
|
71
98
|
// Compute the initial sizes based on default weights.
|
|
72
99
|
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
@@ -153,8 +180,8 @@ export default function PanelGroup({
|
|
|
153
180
|
}, []);
|
|
154
181
|
|
|
155
182
|
const registerResizeHandle = useCallback(
|
|
156
|
-
(
|
|
157
|
-
const resizeHandler = (event:
|
|
183
|
+
(handleId: string) => {
|
|
184
|
+
const resizeHandler = (event: ResizeEvent) => {
|
|
158
185
|
event.preventDefault();
|
|
159
186
|
|
|
160
187
|
const {
|
|
@@ -165,22 +192,32 @@ export default function PanelGroup({
|
|
|
165
192
|
width,
|
|
166
193
|
} = committedValuesRef.current;
|
|
167
194
|
|
|
168
|
-
const handle = document.querySelector(
|
|
169
|
-
`[data-panel-resize-handle-id="${id}"]`
|
|
170
|
-
);
|
|
171
|
-
const handles = Array.from(
|
|
172
|
-
document.querySelectorAll(`[data-panel-group-id="${groupId}"]`)
|
|
173
|
-
);
|
|
174
|
-
const index = handles.indexOf(handle);
|
|
175
195
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
176
|
-
|
|
177
|
-
const
|
|
196
|
+
|
|
197
|
+
const [idBefore, idAfter] = getResizeHandlePanelIds(
|
|
198
|
+
groupId,
|
|
199
|
+
handleId,
|
|
200
|
+
panelsArray
|
|
201
|
+
);
|
|
178
202
|
if (idBefore == null || idAfter == null) {
|
|
179
203
|
return;
|
|
180
204
|
}
|
|
181
205
|
|
|
206
|
+
const nextCoordinates = getUpdatedCoordinates(
|
|
207
|
+
event,
|
|
208
|
+
prevCoordinatesRef.current,
|
|
209
|
+
{ height, width },
|
|
210
|
+
direction
|
|
211
|
+
);
|
|
212
|
+
prevCoordinatesRef.current = {
|
|
213
|
+
screenX: nextCoordinates.screenX,
|
|
214
|
+
screenY: nextCoordinates.screenY,
|
|
215
|
+
};
|
|
216
|
+
|
|
182
217
|
const isHorizontal = direction === "horizontal";
|
|
183
|
-
const movement = isHorizontal
|
|
218
|
+
const movement = isHorizontal
|
|
219
|
+
? nextCoordinates.movementX
|
|
220
|
+
: nextCoordinates.movementY;
|
|
184
221
|
const delta = isHorizontal ? movement / width : movement / height;
|
|
185
222
|
|
|
186
223
|
const nextSizes = adjustByDelta(
|
|
@@ -221,7 +258,13 @@ export default function PanelGroup({
|
|
|
221
258
|
registerPanel,
|
|
222
259
|
registerResizeHandle,
|
|
223
260
|
startDragging: (id: string) => setActiveHandleId(id),
|
|
224
|
-
stopDragging: () =>
|
|
261
|
+
stopDragging: () => {
|
|
262
|
+
setActiveHandleId(null);
|
|
263
|
+
prevCoordinatesRef.current = {
|
|
264
|
+
screenX: 0,
|
|
265
|
+
screenY: 0,
|
|
266
|
+
};
|
|
267
|
+
},
|
|
225
268
|
unregisterPanel,
|
|
226
269
|
}),
|
|
227
270
|
[
|
|
@@ -249,122 +292,3 @@ export default function PanelGroup({
|
|
|
249
292
|
</PanelContext.Provider>
|
|
250
293
|
);
|
|
251
294
|
}
|
|
252
|
-
|
|
253
|
-
function adjustByDelta(
|
|
254
|
-
panels: Map<string, PanelData>,
|
|
255
|
-
idBefore: string,
|
|
256
|
-
idAfter: string,
|
|
257
|
-
delta: number,
|
|
258
|
-
prevSizes: number[]
|
|
259
|
-
): number[] {
|
|
260
|
-
if (delta === 0) {
|
|
261
|
-
return prevSizes;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const panelsArray = panelsMapToSortedArray(panels);
|
|
265
|
-
|
|
266
|
-
const nextSizes = prevSizes.concat();
|
|
267
|
-
|
|
268
|
-
let deltaApplied = 0;
|
|
269
|
-
|
|
270
|
-
// A resizing panel affects the panels before or after it.
|
|
271
|
-
//
|
|
272
|
-
// A negative delta means the panel immediately after the resizer should grow/expand by decreasing its offset.
|
|
273
|
-
// Other panels may also need to shrink/contract (and shift) to make room, depending on the min weights.
|
|
274
|
-
//
|
|
275
|
-
// A positive delta means the panel immediately before the resizer should "expand".
|
|
276
|
-
// This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resizer.
|
|
277
|
-
let pivotId = delta < 0 ? idBefore : idAfter;
|
|
278
|
-
let index = panelsArray.findIndex((panel) => panel.id === pivotId);
|
|
279
|
-
while (true) {
|
|
280
|
-
const panel = panelsArray[index];
|
|
281
|
-
const prevSize = prevSizes[index];
|
|
282
|
-
const nextSize = Math.max(prevSize - Math.abs(delta), panel.minSize);
|
|
283
|
-
if (prevSize !== nextSize) {
|
|
284
|
-
deltaApplied += prevSize - nextSize;
|
|
285
|
-
|
|
286
|
-
nextSizes[index] = nextSize;
|
|
287
|
-
|
|
288
|
-
if (deltaApplied.toPrecision(PRECISION) >= delta.toPrecision(PRECISION)) {
|
|
289
|
-
break;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (delta < 0) {
|
|
294
|
-
if (--index < 0) {
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
} else {
|
|
298
|
-
if (++index >= panelsArray.length) {
|
|
299
|
-
break;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// If we were unable to resize any of the panels panels, return the previous state.
|
|
305
|
-
// This will essentially bailout and ignore the "mousemove" event.
|
|
306
|
-
if (deltaApplied === 0) {
|
|
307
|
-
return prevSizes;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Adjust the pivot panel before, but only by the amount that surrounding panels were able to shrink/contract.
|
|
311
|
-
pivotId = delta < 0 ? idAfter : idBefore;
|
|
312
|
-
index = panelsArray.findIndex((panel) => panel.id === pivotId);
|
|
313
|
-
nextSizes[index] = prevSizes[index] + deltaApplied;
|
|
314
|
-
|
|
315
|
-
return nextSizes;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function getOffset(
|
|
319
|
-
panels: Map<string, PanelData>,
|
|
320
|
-
id: string,
|
|
321
|
-
direction: Direction,
|
|
322
|
-
sizes: number[],
|
|
323
|
-
height: number,
|
|
324
|
-
width: number
|
|
325
|
-
): number {
|
|
326
|
-
const panelsArray = panelsMapToSortedArray(panels);
|
|
327
|
-
|
|
328
|
-
let index = panelsArray.findIndex((panel) => panel.id === id);
|
|
329
|
-
if (index < 0) {
|
|
330
|
-
return 0;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
let scaledOffset = 0;
|
|
334
|
-
|
|
335
|
-
for (index = index - 1; index >= 0; index--) {
|
|
336
|
-
const panel = panelsArray[index];
|
|
337
|
-
scaledOffset += getSize(panels, panel.id, direction, sizes, height, width);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
return Math.round(scaledOffset);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
function getSize(
|
|
344
|
-
panels: Map<string, PanelData>,
|
|
345
|
-
id: string,
|
|
346
|
-
direction: Direction,
|
|
347
|
-
sizes: number[],
|
|
348
|
-
height: number,
|
|
349
|
-
width: number
|
|
350
|
-
): number {
|
|
351
|
-
const totalSize = direction === "horizontal" ? width : height;
|
|
352
|
-
|
|
353
|
-
if (panels.size === 1) {
|
|
354
|
-
return totalSize;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const panelsArray = panelsMapToSortedArray(panels);
|
|
358
|
-
|
|
359
|
-
const index = panelsArray.findIndex((panel) => panel.id === id);
|
|
360
|
-
const size = sizes[index];
|
|
361
|
-
if (size == null) {
|
|
362
|
-
return 0;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
return Math.round(size * totalSize);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
function panelsMapToSortedArray(panels: Map<string, PanelData>): PanelData[] {
|
|
369
|
-
return Array.from(panels.values()).sort((a, b) => a.order - b.order);
|
|
370
|
-
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ReactNode, useContext, useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import useUniqueId from "./hooks/useUniqueId";
|
|
4
|
+
import { useWindowSplitterResizeHandlerBehavior } from "./hooks/useWindowSplitterBehavior";
|
|
4
5
|
import { PanelContext, PanelGroupContext } from "./PanelContexts";
|
|
5
|
-
import { ResizeHandler } from "./types";
|
|
6
|
+
import type { ResizeHandler, ResizeEvent } from "./types";
|
|
6
7
|
|
|
7
8
|
export default function PanelResizeHandle({
|
|
8
9
|
children = null,
|
|
@@ -47,7 +48,7 @@ export default function PanelResizeHandle({
|
|
|
47
48
|
const resizeHandler = registerResizeHandle(id);
|
|
48
49
|
setResizeHandler(() => resizeHandler);
|
|
49
50
|
}
|
|
50
|
-
}, [disabled,
|
|
51
|
+
}, [disabled, id, registerResizeHandle]);
|
|
51
52
|
|
|
52
53
|
useEffect(() => {
|
|
53
54
|
if (disabled || resizeHandler == null || !isDragging) {
|
|
@@ -57,37 +58,48 @@ export default function PanelResizeHandle({
|
|
|
57
58
|
document.body.style.cursor =
|
|
58
59
|
direction === "horizontal" ? "ew-resize" : "ns-resize";
|
|
59
60
|
|
|
60
|
-
const
|
|
61
|
+
const onMove = (event: ResizeEvent) => {
|
|
61
62
|
resizeHandler(event);
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
document.body.addEventListener("mouseleave", stopDragging);
|
|
65
|
-
document.body.addEventListener("mousemove",
|
|
66
|
-
document.body.addEventListener("touchmove",
|
|
66
|
+
document.body.addEventListener("mousemove", onMove);
|
|
67
|
+
document.body.addEventListener("touchmove", onMove);
|
|
67
68
|
document.body.addEventListener("mouseup", stopDragging);
|
|
68
69
|
|
|
69
70
|
return () => {
|
|
70
71
|
document.body.style.cursor = "";
|
|
71
72
|
|
|
72
73
|
document.body.removeEventListener("mouseleave", stopDragging);
|
|
73
|
-
document.body.removeEventListener("mousemove",
|
|
74
|
-
document.body.removeEventListener("touchmove",
|
|
74
|
+
document.body.removeEventListener("mousemove", onMove);
|
|
75
|
+
document.body.removeEventListener("touchmove", onMove);
|
|
75
76
|
document.body.removeEventListener("mouseup", stopDragging);
|
|
76
77
|
};
|
|
77
78
|
}, [direction, disabled, isDragging, resizeHandler, stopDragging]);
|
|
78
79
|
|
|
80
|
+
useWindowSplitterResizeHandlerBehavior({
|
|
81
|
+
disabled,
|
|
82
|
+
handleId: id,
|
|
83
|
+
resizeHandler,
|
|
84
|
+
});
|
|
85
|
+
|
|
79
86
|
return (
|
|
80
87
|
<div
|
|
81
88
|
className={className}
|
|
82
89
|
data-panel-group-id={groupId}
|
|
90
|
+
data-panel-resize-handle-enabled={!disabled}
|
|
83
91
|
data-panel-resize-handle-id={id}
|
|
84
92
|
onMouseDown={() => startDragging(id)}
|
|
85
93
|
onMouseUp={stopDragging}
|
|
86
|
-
|
|
94
|
+
onTouchCancel={stopDragging}
|
|
87
95
|
onTouchEnd={stopDragging}
|
|
96
|
+
onTouchStart={() => startDragging(id)}
|
|
97
|
+
role="separator"
|
|
88
98
|
style={{
|
|
89
99
|
cursor: direction === "horizontal" ? "ew-resize" : "ns-resize",
|
|
100
|
+
touchAction: "none",
|
|
90
101
|
}}
|
|
102
|
+
tabIndex={0}
|
|
91
103
|
>
|
|
92
104
|
{children}
|
|
93
105
|
</div>
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PRECISION = 5;
|