react-panel-layout 0.5.1 → 0.6.0
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/dist/{FloatingPanelFrame-D9Cp2al1.cjs → FloatingPanelFrame-CEmXDvUA.cjs} +2 -2
- package/dist/FloatingPanelFrame-CEmXDvUA.cjs.map +1 -0
- package/dist/{FloatingPanelFrame-6W5OexYe.js → FloatingPanelFrame-SgYLc6Ud.js} +12 -15
- package/dist/FloatingPanelFrame-SgYLc6Ud.js.map +1 -0
- package/dist/FloatingWindow-BpdOpg_L.js +400 -0
- package/dist/FloatingWindow-BpdOpg_L.js.map +1 -0
- package/dist/FloatingWindow-TCDNY5gE.cjs +2 -0
- package/dist/FloatingWindow-TCDNY5gE.cjs.map +1 -0
- package/dist/GridLayout-B4VRsC0r.cjs +2 -0
- package/dist/GridLayout-B4VRsC0r.cjs.map +1 -0
- package/dist/GridLayout-BltqeCPK.js +927 -0
- package/dist/GridLayout-BltqeCPK.js.map +1 -0
- package/dist/HorizontalDivider-B5Z-KZLk.cjs +2 -0
- package/dist/HorizontalDivider-B5Z-KZLk.cjs.map +1 -0
- package/dist/HorizontalDivider-WF1k_qND.js +30 -0
- package/dist/HorizontalDivider-WF1k_qND.js.map +1 -0
- package/dist/PanelSystem-Bs8bQwQF.cjs +3 -0
- package/dist/PanelSystem-Bs8bQwQF.cjs.map +1 -0
- package/dist/PanelSystem-Dr1TBhxM.js +1946 -0
- package/dist/PanelSystem-Dr1TBhxM.js.map +1 -0
- package/dist/ResizeHandle-CScipO5l.cjs +2 -0
- package/dist/ResizeHandle-CScipO5l.cjs.map +1 -0
- package/dist/ResizeHandle-CdA_JYfN.js +120 -0
- package/dist/ResizeHandle-CdA_JYfN.js.map +1 -0
- package/dist/SwipePivotTabBar-BGO9X94m.js +407 -0
- package/dist/SwipePivotTabBar-BGO9X94m.js.map +1 -0
- package/dist/SwipePivotTabBar-BrQismcZ.cjs +2 -0
- package/dist/SwipePivotTabBar-BrQismcZ.cjs.map +1 -0
- package/dist/config.cjs +1 -1
- package/dist/config.cjs.map +1 -1
- package/dist/config.js +11 -9
- package/dist/config.js.map +1 -1
- package/dist/constants/styles.d.ts +18 -4
- package/dist/floating.cjs +1 -1
- package/dist/floating.js +1 -1
- package/dist/grid/index.d.ts +58 -0
- package/dist/grid.cjs +2 -0
- package/dist/grid.cjs.map +1 -0
- package/dist/grid.js +13 -0
- package/dist/grid.js.map +1 -0
- package/dist/hooks/gesture/presets.d.ts +33 -0
- package/dist/hooks/gesture/testing/createGestureSimulator.d.ts +110 -0
- package/dist/hooks/gesture/thresholdValue.d.ts +44 -0
- package/dist/hooks/gesture/types.d.ts +254 -0
- package/dist/hooks/gesture/useDirectionalLock.d.ts +20 -0
- package/dist/hooks/gesture/useEdgeSwipeInput.d.ts +23 -0
- package/dist/hooks/gesture/useNativeGestureGuard.d.ts +23 -0
- package/dist/hooks/gesture/usePointerTracking.d.ts +22 -0
- package/dist/hooks/gesture/useScrollBoundary.d.ts +23 -0
- package/dist/hooks/gesture/useSwipeInput.d.ts +5 -0
- package/dist/hooks/gesture/utils.d.ts +40 -0
- package/dist/hooks/useAnimatedVisibility.d.ts +58 -0
- package/dist/hooks/useAnimationFrame.d.ts +84 -0
- package/dist/hooks/useSnapAnimation.d.ts +54 -0
- package/dist/hooks/useSwipeContentTransform.d.ts +79 -0
- package/dist/index.cjs +1 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +25 -2006
- package/dist/index.js.map +1 -1
- package/dist/modules/pivot/PivotContent.d.ts +1 -1
- package/dist/modules/pivot/SwipePivotContent.d.ts +39 -0
- package/dist/modules/pivot/SwipePivotContent.debug.tmp.d.ts +25 -0
- package/dist/modules/pivot/SwipePivotContent.test.d.ts +1 -0
- package/dist/modules/pivot/SwipePivotTabBar.d.ts +89 -0
- package/dist/modules/pivot/index.d.ts +3 -0
- package/dist/modules/pivot/scaleInputState.d.ts +37 -0
- package/dist/modules/pivot/types.d.ts +73 -2
- package/dist/modules/pivot/usePivotSwipeInput.d.ts +68 -0
- package/dist/modules/stack/StackContent.d.ts +15 -0
- package/dist/modules/stack/SwipeStackContent.d.ts +63 -0
- package/dist/modules/stack/SwipeStackOutlet.d.ts +80 -0
- package/dist/modules/stack/computeStackContentState.d.ts +99 -0
- package/dist/modules/stack/computeSwipeStackTransform.d.ts +76 -0
- package/dist/modules/stack/types.d.ts +194 -0
- package/dist/modules/stack/useStackAnimationState.d.ts +32 -0
- package/dist/modules/stack/useStackNavigation.d.ts +23 -0
- package/dist/modules/stack/useStackSwipeInput.d.ts +27 -0
- package/dist/panels/index.d.ts +67 -0
- package/dist/panels.cjs +2 -0
- package/dist/panels.cjs.map +1 -0
- package/dist/panels.js +28 -0
- package/dist/panels.js.map +1 -0
- package/dist/pivot/index.d.ts +3 -0
- package/dist/pivot.cjs +1 -1
- package/dist/pivot.cjs.map +1 -1
- package/dist/pivot.js +20 -2
- package/dist/pivot.js.map +1 -1
- package/dist/resizer/index.d.ts +57 -0
- package/dist/resizer.cjs +2 -0
- package/dist/resizer.cjs.map +1 -0
- package/dist/resizer.js +8 -0
- package/dist/resizer.js.map +1 -0
- package/dist/stack/index.d.ts +72 -0
- package/dist/stack.cjs +2 -0
- package/dist/stack.cjs.map +1 -0
- package/dist/stack.js +980 -0
- package/dist/stack.js.map +1 -0
- package/dist/sticky-header/StickyArea.d.ts +38 -0
- package/dist/sticky-header/index.d.ts +4 -4
- package/dist/sticky-header/types.d.ts +35 -22
- package/dist/sticky-header.cjs +1 -1
- package/dist/sticky-header.cjs.map +1 -1
- package/dist/sticky-header.js +65 -174
- package/dist/sticky-header.js.map +1 -1
- package/dist/styles-DPPuJ0sf.js +57 -0
- package/dist/styles-DPPuJ0sf.js.map +1 -0
- package/dist/styles-qf6ptVLD.cjs +2 -0
- package/dist/styles-qf6ptVLD.cjs.map +1 -0
- package/dist/types.d.ts +12 -0
- package/dist/useContentCache-CO3LYNmz.js +24 -0
- package/dist/useContentCache-CO3LYNmz.js.map +1 -0
- package/dist/useContentCache-DqXtLrLs.cjs +2 -0
- package/dist/useContentCache-DqXtLrLs.cjs.map +1 -0
- package/dist/useDocumentPointerEvents-CKdhGXd0.js +46 -0
- package/dist/useDocumentPointerEvents-CKdhGXd0.js.map +1 -0
- package/dist/useDocumentPointerEvents-ChqrKXDk.cjs +2 -0
- package/dist/useDocumentPointerEvents-ChqrKXDk.cjs.map +1 -0
- package/dist/useEffectEvent-Dp7HLCf0.js +13 -0
- package/dist/useEffectEvent-Dp7HLCf0.js.map +1 -0
- package/dist/useEffectEvent-huSsGUnl.cjs +2 -0
- package/dist/useEffectEvent-huSsGUnl.cjs.map +1 -0
- package/dist/useFloatingState-C4kRaW_R.cjs +2 -0
- package/dist/useFloatingState-C4kRaW_R.cjs.map +1 -0
- package/dist/useFloatingState-tEfA_wbc.js +74 -0
- package/dist/useFloatingState-tEfA_wbc.js.map +1 -0
- package/dist/window/index.d.ts +61 -0
- package/dist/window.cjs +2 -0
- package/dist/window.cjs.map +1 -0
- package/dist/window.js +149 -0
- package/dist/window.js.map +1 -0
- package/docs/design-tokens.md +405 -0
- package/package.json +29 -4
- package/src/PanelSystemContext.tsx +88 -0
- package/src/components/grid/GridLayerList.tsx +172 -0
- package/src/components/grid/GridLayerResizeHandles.tsx +145 -0
- package/src/components/grid/GridLayout.spec.tsx +743 -0
- package/src/components/grid/GridLayout.tsx +130 -0
- package/src/components/grid/GridTrackResizeHandle.tsx +87 -0
- package/src/components/paneling/FloatingPanelFrame.tsx +203 -0
- package/src/components/panels/DropSuggestOverlay.tsx +131 -0
- package/src/components/panels/PanelGroupView.tsx +112 -0
- package/src/components/pivot/PivotLayer.tsx +27 -0
- package/src/components/resizer/HorizontalDivider.tsx +52 -0
- package/src/components/resizer/ResizeHandle.tsx +118 -0
- package/src/components/tabs/TabBar.tsx +223 -0
- package/src/components/tabs/TabBarTab.tsx +133 -0
- package/src/components/tabs/TabDragOverlay.tsx +92 -0
- package/src/components/window/DialogOverlay.tsx +180 -0
- package/src/components/window/Drawer.tsx +282 -0
- package/src/components/window/DrawerLayers.tsx +58 -0
- package/src/components/window/FloatingWindow.tsx +95 -0
- package/src/components/window/PopupLayerPortal.tsx +218 -0
- package/src/config/PanelContentDeclaration.tsx +427 -0
- package/src/config/index.tsx +52 -0
- package/src/config/panelJsx.spec.tsx +54 -0
- package/src/config/panelJsxConfig.spec.tsx +54 -0
- package/src/config/panelJsxDrawer.spec.tsx +33 -0
- package/src/config/panelRouter.spec.ts +68 -0
- package/src/config/panelRouter.tsx +155 -0
- package/src/constants/styles.ts +261 -0
- package/src/demo/Layout.module.css +258 -0
- package/src/demo/Layout.tsx +176 -0
- package/src/demo/components/CodeBlock.module.css +54 -0
- package/src/demo/components/CodeBlock.tsx +34 -0
- package/src/demo/components/CodePreview.module.css +37 -0
- package/src/demo/components/CodePreview.tsx +31 -0
- package/src/demo/components/DataPreview.module.css +177 -0
- package/src/demo/components/DataPreview.tsx +115 -0
- package/src/demo/components/Story.module.css +68 -0
- package/src/demo/components/Story.tsx +54 -0
- package/src/demo/components/layout/CodePanel.module.css +183 -0
- package/src/demo/components/layout/CodePanel.tsx +149 -0
- package/src/demo/components/layout/DemoPage.module.css +60 -0
- package/src/demo/components/layout/DemoPage.tsx +56 -0
- package/src/demo/components/layout/SingleSamplePage.module.css +11 -0
- package/src/demo/components/layout/SingleSamplePage.tsx +35 -0
- package/src/demo/components/layout/SplitDemoLayout.module.css +107 -0
- package/src/demo/components/layout/SplitDemoLayout.tsx +218 -0
- package/src/demo/components/layout/index.ts +11 -0
- package/src/demo/components/tab-styles/ChromeTabBar.module.css +75 -0
- package/src/demo/components/tab-styles/ChromeTabBar.tsx +111 -0
- package/src/demo/components/tab-styles/GitHubTabBar.module.css +81 -0
- package/src/demo/components/tab-styles/GitHubTabBar.tsx +109 -0
- package/src/demo/components/tab-styles/VSCodeTabBar.module.css +78 -0
- package/src/demo/components/tab-styles/VSCodeTabBar.tsx +109 -0
- package/src/demo/components/tab-styles/index.ts +6 -0
- package/src/demo/components/ui/DemoButton.module.css +63 -0
- package/src/demo/components/ui/DemoButton.tsx +32 -0
- package/src/demo/components/ui/DemoCard.module.css +15 -0
- package/src/demo/components/ui/DemoCard.tsx +30 -0
- package/src/demo/components/ui/DemoContainer.module.css +17 -0
- package/src/demo/components/ui/DemoContainer.tsx +30 -0
- package/src/demo/components/ui/DemoPanel.module.css +23 -0
- package/src/demo/components/ui/DemoPanel.tsx +33 -0
- package/src/demo/components/ui/PanelText.module.css +18 -0
- package/src/demo/components/ui/PanelText.tsx +29 -0
- package/src/demo/components/ui/PanelTitle.module.css +18 -0
- package/src/demo/components/ui/PanelTitle.tsx +31 -0
- package/src/demo/contexts/TabbarDemoConfig.tsx +218 -0
- package/src/demo/demo.css +172 -0
- package/src/demo/hooks/useMedia.ts +41 -0
- package/src/demo/hooks/useShikiHighlight.ts +55 -0
- package/src/demo/index.tsx +293 -0
- package/src/demo/pages/Drawer/animations/index.tsx +22 -0
- package/src/demo/pages/Drawer/basics/index.tsx +17 -0
- package/src/demo/pages/Drawer/components/DrawerAnimations.module.css +125 -0
- package/src/demo/pages/Drawer/components/DrawerAnimations.tsx +118 -0
- package/src/demo/pages/Drawer/components/DrawerBasics.module.css +55 -0
- package/src/demo/pages/Drawer/components/DrawerBasics.tsx +76 -0
- package/src/demo/pages/Drawer/components/DrawerMenuLayout.module.css +332 -0
- package/src/demo/pages/Drawer/components/DrawerMenuLayout.tsx +199 -0
- package/src/demo/pages/Drawer/menu/index.tsx +17 -0
- package/src/demo/pages/FloatingPanelFrame/ResizableFloatingPanelsPreview.module.css +163 -0
- package/src/demo/pages/FloatingPanelFrame/ResizableFloatingPanelsPreview.tsx +234 -0
- package/src/demo/pages/FloatingPanelFrame/basic/index.tsx +17 -0
- package/src/demo/pages/FloatingPanelFrame/complex/index.tsx +26 -0
- package/src/demo/pages/FloatingPanelFrame/components/BasicPanel.module.css +16 -0
- package/src/demo/pages/FloatingPanelFrame/components/BasicPanel.tsx +24 -0
- package/src/demo/pages/FloatingPanelFrame/components/ComplexPanel.module.css +54 -0
- package/src/demo/pages/FloatingPanelFrame/components/ComplexPanel.tsx +67 -0
- package/src/demo/pages/FloatingPanelFrame/components/PanelWithControls.module.css +21 -0
- package/src/demo/pages/FloatingPanelFrame/components/PanelWithControls.tsx +41 -0
- package/src/demo/pages/FloatingPanelFrame/components/PanelWithMeta.module.css +5 -0
- package/src/demo/pages/FloatingPanelFrame/components/PanelWithMeta.tsx +43 -0
- package/src/demo/pages/FloatingPanelFrame/components/ScrollablePanel.module.css +11 -0
- package/src/demo/pages/FloatingPanelFrame/components/ScrollablePanel.tsx +42 -0
- package/src/demo/pages/FloatingPanelFrame/index.tsx +80 -0
- package/src/demo/pages/FloatingPanelFrame/scrollable/index.tsx +30 -0
- package/src/demo/pages/FloatingPanelFrame/with-controls/index.tsx +30 -0
- package/src/demo/pages/FloatingPanelFrame/with-meta/index.tsx +17 -0
- package/src/demo/pages/HorizontalDivider/components/PanelsWithRichContent.module.css +112 -0
- package/src/demo/pages/HorizontalDivider/components/PanelsWithRichContent.tsx +56 -0
- package/src/demo/pages/HorizontalDivider/components/SimpleResizablePanels.module.css +46 -0
- package/src/demo/pages/HorizontalDivider/components/SimpleResizablePanels.tsx +29 -0
- package/src/demo/pages/HorizontalDivider/components/ThreePanelLayout.module.css +54 -0
- package/src/demo/pages/HorizontalDivider/components/ThreePanelLayout.tsx +30 -0
- package/src/demo/pages/HorizontalDivider/index.module.css +14 -0
- package/src/demo/pages/HorizontalDivider/index.tsx +64 -0
- package/src/demo/pages/HorizontalDivider/panels-with-rich-content/index.tsx +21 -0
- package/src/demo/pages/HorizontalDivider/simple-resizable-panels/index.tsx +21 -0
- package/src/demo/pages/HorizontalDivider/three-panel-layout/index.tsx +21 -0
- package/src/demo/pages/PanelLayout/PanelLayoutDemo.module.css +174 -0
- package/src/demo/pages/PanelLayout/PanelLayoutDemo.tsx +248 -0
- package/src/demo/pages/PanelLayout/components/DashboardLayout.module.css +115 -0
- package/src/demo/pages/PanelLayout/components/DashboardLayout.tsx +124 -0
- package/src/demo/pages/PanelLayout/components/DraggableOverlays.module.css +101 -0
- package/src/demo/pages/PanelLayout/components/DraggableOverlays.tsx +122 -0
- package/src/demo/pages/PanelLayout/components/IDELayout.module.css +104 -0
- package/src/demo/pages/PanelLayout/components/IDELayout.tsx +143 -0
- package/src/demo/pages/PanelLayout/components/SimpleGrid.module.css +19 -0
- package/src/demo/pages/PanelLayout/components/SimpleGrid.tsx +62 -0
- package/src/demo/pages/PanelLayout/dashboard/index.tsx +22 -0
- package/src/demo/pages/PanelLayout/draggable-overlays/index.tsx +22 -0
- package/src/demo/pages/PanelLayout/ide-layout/index.tsx +22 -0
- package/src/demo/pages/PanelLayout/index.tsx +94 -0
- package/src/demo/pages/PanelLayout/simple-grid/index.tsx +22 -0
- package/src/demo/pages/PanelSystem/PanelSystemPreview.module.css +20 -0
- package/src/demo/pages/PanelSystem/PanelSystemPreview.tsx +101 -0
- package/src/demo/pages/PanelSystem/preview/index.tsx +18 -0
- package/src/demo/pages/PanelSystem/tabbar/index.tsx +129 -0
- package/src/demo/pages/Pivot/basics/index.tsx +17 -0
- package/src/demo/pages/Pivot/components/Pivot.module.css +278 -0
- package/src/demo/pages/Pivot/components/PivotBasics.tsx +103 -0
- package/src/demo/pages/Pivot/components/PivotSidebar.tsx +168 -0
- package/src/demo/pages/Pivot/components/PivotTabs.tsx +129 -0
- package/src/demo/pages/Pivot/components/PivotTransitions.tsx +120 -0
- package/src/demo/pages/Pivot/components/SwipePivot.module.css +114 -0
- package/src/demo/pages/Pivot/components/SwipePivot.tsx +193 -0
- package/src/demo/pages/Pivot/components/SwipeTabsPivot.module.css +203 -0
- package/src/demo/pages/Pivot/components/SwipeTabsPivot.tsx +289 -0
- package/src/demo/pages/Pivot/sidebar/index.tsx +17 -0
- package/src/demo/pages/Pivot/swipe/index.tsx +16 -0
- package/src/demo/pages/Pivot/swipe-debug/index.tsx +287 -0
- package/src/demo/pages/Pivot/swipe-tabs/index.tsx +15 -0
- package/src/demo/pages/Pivot/tabs/index.tsx +17 -0
- package/src/demo/pages/Pivot/transitions/index.tsx +17 -0
- package/src/demo/pages/ResizeHandle/both-directions/index.tsx +17 -0
- package/src/demo/pages/ResizeHandle/components/BothDirectionsDemo.module.css +72 -0
- package/src/demo/pages/ResizeHandle/components/BothDirectionsDemo.tsx +41 -0
- package/src/demo/pages/ResizeHandle/components/HorizontalResizeDemo.module.css +61 -0
- package/src/demo/pages/ResizeHandle/components/HorizontalResizeDemo.tsx +33 -0
- package/src/demo/pages/ResizeHandle/components/NestedPanelsDemo.module.css +83 -0
- package/src/demo/pages/ResizeHandle/components/NestedPanelsDemo.tsx +53 -0
- package/src/demo/pages/ResizeHandle/components/VerticalResizeDemo.module.css +68 -0
- package/src/demo/pages/ResizeHandle/components/VerticalResizeDemo.tsx +33 -0
- package/src/demo/pages/ResizeHandle/horizontal/index.tsx +17 -0
- package/src/demo/pages/ResizeHandle/index.module.css +11 -0
- package/src/demo/pages/ResizeHandle/index.tsx +71 -0
- package/src/demo/pages/ResizeHandle/nested-panels/index.tsx +17 -0
- package/src/demo/pages/ResizeHandle/vertical/index.tsx +17 -0
- package/src/demo/pages/ResponsiveLayout/adaptive-workspace/index.tsx +22 -0
- package/src/demo/pages/ResponsiveLayout/components/ResponsiveWorkspace.module.css +423 -0
- package/src/demo/pages/ResponsiveLayout/components/ResponsiveWorkspace.tsx +398 -0
- package/src/demo/pages/Stack/basics/index.tsx +22 -0
- package/src/demo/pages/Stack/components/Stack.module.css +234 -0
- package/src/demo/pages/Stack/components/StackBasics.tsx +217 -0
- package/src/demo/pages/Stack/components/StackTablet.module.css +299 -0
- package/src/demo/pages/Stack/components/StackTablet.tsx +401 -0
- package/src/demo/pages/Stack/tablet/index.tsx +22 -0
- package/src/demo/pages/StickyHeader/basics/index.tsx +17 -0
- package/src/demo/pages/StickyHeader/components/StickyHeader.module.css +219 -0
- package/src/demo/pages/StickyHeader/components/StickyHeaderBasics.tsx +103 -0
- package/src/demo/routes.tsx +193 -0
- package/src/demo/styles/animations.css +68 -0
- package/src/demo/styles/stack-themes.css +35 -0
- package/src/demo/utils/createPanelView.tsx +58 -0
- package/src/floating/index.ts +24 -0
- package/src/grid/index.ts +75 -0
- package/src/hooks/ContentCacheContext.tsx +87 -0
- package/src/hooks/gesture/presets.spec.ts +86 -0
- package/src/hooks/gesture/presets.ts +95 -0
- package/src/hooks/gesture/testing/createGestureSimulator.spec.ts +237 -0
- package/src/hooks/gesture/testing/createGestureSimulator.ts +310 -0
- package/src/hooks/gesture/thresholdValue.spec.ts +103 -0
- package/src/hooks/gesture/thresholdValue.ts +77 -0
- package/src/hooks/gesture/types.ts +290 -0
- package/src/hooks/gesture/useDirectionalLock.spec.ts +271 -0
- package/src/hooks/gesture/useDirectionalLock.ts +115 -0
- package/src/hooks/gesture/useEdgeSwipeInput.spec.ts +454 -0
- package/src/hooks/gesture/useEdgeSwipeInput.ts +131 -0
- package/src/hooks/gesture/useNativeGestureGuard.spec.ts +413 -0
- package/src/hooks/gesture/useNativeGestureGuard.ts +133 -0
- package/src/hooks/gesture/usePointerTracking.spec.ts +364 -0
- package/src/hooks/gesture/usePointerTracking.ts +134 -0
- package/src/hooks/gesture/useScrollBoundary.spec.ts +249 -0
- package/src/hooks/gesture/useScrollBoundary.ts +113 -0
- package/src/hooks/gesture/useSwipeInput.spec.ts +592 -0
- package/src/hooks/gesture/useSwipeInput.ts +310 -0
- package/src/hooks/gesture/utils.spec.ts +152 -0
- package/src/hooks/gesture/utils.ts +87 -0
- package/src/hooks/useAnimatedVisibility.spec.ts +257 -0
- package/src/hooks/useAnimatedVisibility.ts +146 -0
- package/src/hooks/useAnimationFrame.ts +200 -0
- package/src/hooks/useCSSMatrix.spec.ts +214 -0
- package/src/hooks/useCSSMatrix.ts +262 -0
- package/src/hooks/useClonedElementPreview.ts +28 -0
- package/src/hooks/useContainerScroll.ts +78 -0
- package/src/hooks/useContentCache.spec.tsx +232 -0
- package/src/hooks/useContentCache.tsx +127 -0
- package/src/hooks/useDocumentPointerEvents.ts +137 -0
- package/src/hooks/useDocumentScroll.ts +41 -0
- package/src/hooks/useEffectEvent.ts +40 -0
- package/src/hooks/useElementComponentWrapper.tsx +63 -0
- package/src/hooks/useIntersectionObserver.tsx +125 -0
- package/src/hooks/useIsomorphicLayoutEffect.ts +29 -0
- package/src/hooks/useResizeObserver.tsx +81 -0
- package/src/hooks/useScrollContainer.ts +79 -0
- package/src/hooks/useSnapAnimation.ts +128 -0
- package/src/hooks/useSwipeContentTransform.spec.ts +133 -0
- package/src/hooks/useSwipeContentTransform.ts +235 -0
- package/src/hooks/useTransitionState.ts +95 -0
- package/src/index.tsx +88 -0
- package/src/modules/grid/GridLayoutContext.tsx +57 -0
- package/src/modules/grid/LayerInstanceContext.tsx +56 -0
- package/src/modules/grid/resizeHandles.ts +157 -0
- package/src/modules/grid/trackUtils.ts +146 -0
- package/src/modules/grid/useGridPlacements.ts +143 -0
- package/src/modules/grid/useGridTracks.ts +156 -0
- package/src/modules/grid/useLayerDragHandle.ts +16 -0
- package/src/modules/grid/useLayerInteractions.tsx +850 -0
- package/src/modules/keybindings/KeybindingsProvider.tsx +111 -0
- package/src/modules/panels/dom/DomRegistry.tsx +94 -0
- package/src/modules/panels/index.ts +45 -0
- package/src/modules/panels/interactions/InteractionsContext.test.tsx +330 -0
- package/src/modules/panels/interactions/InteractionsContext.tsx +394 -0
- package/src/modules/panels/interactions/dnd.ts +28 -0
- package/src/modules/panels/keybindings/KeybindingsInstaller.tsx +15 -0
- package/src/modules/panels/layout/adapter.ts +124 -0
- package/src/modules/panels/rendering/ContentRegistry.spec.tsx +304 -0
- package/src/modules/panels/rendering/ContentRegistry.tsx +205 -0
- package/src/modules/panels/rendering/GroupContainer.tsx +65 -0
- package/src/modules/panels/rendering/RenderBridge.tsx +115 -0
- package/src/modules/panels/rendering/RenderContext.tsx +31 -0
- package/src/modules/panels/state/PanelSplitHandles.tsx +147 -0
- package/src/modules/panels/state/PanelSystemContext.splitLimits.spec.tsx +50 -0
- package/src/modules/panels/state/PanelSystemContext.tsx +289 -0
- package/src/modules/panels/state/StateContext.tsx +12 -0
- package/src/modules/panels/state/cleanup.ts +37 -0
- package/src/modules/panels/state/commands.ts +53 -0
- package/src/modules/panels/state/focus/Context.tsx +25 -0
- package/src/modules/panels/state/focus/logic.ts +57 -0
- package/src/modules/panels/state/groups/Context.tsx +25 -0
- package/src/modules/panels/state/groups/logic.ts +105 -0
- package/src/modules/panels/state/splitLimits.spec.ts +46 -0
- package/src/modules/panels/state/splitLimits.ts +90 -0
- package/src/modules/panels/state/state.spec.ts +49 -0
- package/src/modules/panels/state/tree/Context.tsx +24 -0
- package/src/modules/panels/state/tree/logic.spec.ts +34 -0
- package/src/modules/panels/state/tree/logic.ts +138 -0
- package/src/modules/panels/state/types.ts +142 -0
- package/src/modules/panels/system/PanelSystem.empty-tabbar.spec.tsx +53 -0
- package/src/modules/panels/system/PanelSystem.tab-click-activates.spec.tsx +44 -0
- package/src/modules/panels/system/PanelSystem.tab-reorder.spec.tsx +64 -0
- package/src/modules/panels/system/PanelSystem.tabs-no-dup.spec.tsx +57 -0
- package/src/modules/panels/system/PanelSystem.tsx +206 -0
- package/src/modules/pivot/PivotContent.spec.tsx +179 -0
- package/src/modules/pivot/PivotContent.tsx +77 -0
- package/src/modules/pivot/SwipePivotContent.debug.tmp.tsx +237 -0
- package/src/modules/pivot/SwipePivotContent.position.spec.tsx +167 -0
- package/src/modules/pivot/SwipePivotContent.spec.tsx +464 -0
- package/src/modules/pivot/SwipePivotContent.test.tsx +502 -0
- package/src/modules/pivot/SwipePivotContent.tsx +197 -0
- package/src/modules/pivot/SwipePivotTabBar.spec.tsx +865 -0
- package/src/modules/pivot/SwipePivotTabBar.tsx +523 -0
- package/src/modules/pivot/index.ts +8 -0
- package/src/modules/pivot/scaleInputState.spec.ts +210 -0
- package/src/modules/pivot/scaleInputState.ts +66 -0
- package/src/modules/pivot/types.ts +139 -0
- package/src/modules/pivot/usePivot.spec.ts +621 -0
- package/src/modules/pivot/usePivot.spec.tsx +186 -0
- package/src/modules/pivot/usePivot.tsx +345 -0
- package/src/modules/pivot/usePivotSwipeInput.spec.ts +649 -0
- package/src/modules/pivot/usePivotSwipeInput.ts +136 -0
- package/src/modules/resizer/useResizeDrag.ts +94 -0
- package/src/modules/stack/StackContent.spec.tsx +264 -0
- package/src/modules/stack/StackContent.tsx +111 -0
- package/src/modules/stack/SwipeStackContent.spec.tsx +1277 -0
- package/src/modules/stack/SwipeStackContent.tsx +356 -0
- package/src/modules/stack/SwipeStackOutlet.spec.tsx +252 -0
- package/src/modules/stack/SwipeStackOutlet.tsx +221 -0
- package/src/modules/stack/computeStackContentState.spec.ts +281 -0
- package/src/modules/stack/computeStackContentState.ts +304 -0
- package/src/modules/stack/computeSwipeStackTransform.spec.ts +186 -0
- package/src/modules/stack/computeSwipeStackTransform.ts +145 -0
- package/src/modules/stack/types.ts +226 -0
- package/src/modules/stack/useStackAnimationState.spec.ts +186 -0
- package/src/modules/stack/useStackAnimationState.ts +138 -0
- package/src/modules/stack/useStackNavigation.spec.ts +477 -0
- package/src/modules/stack/useStackNavigation.tsx +336 -0
- package/src/modules/stack/useStackSwipeInput.spec.ts +276 -0
- package/src/modules/stack/useStackSwipeInput.ts +139 -0
- package/src/modules/window/useDrawerState.ts +81 -0
- package/src/modules/window/useFloatingState.spec.ts +252 -0
- package/src/modules/window/useFloatingState.ts +141 -0
- package/src/panels/index.ts +119 -0
- package/src/pivot/index.ts +19 -0
- package/src/resizer/index.ts +68 -0
- package/src/stack/index.ts +91 -0
- package/src/sticky-header/StickyArea.tsx +221 -0
- package/src/sticky-header/index.ts +18 -0
- package/src/sticky-header/types.ts +68 -0
- package/src/types.ts +323 -0
- package/src/utils/CSSMatrix.ts +321 -0
- package/src/utils/css.ts +65 -0
- package/src/utils/dialogUtils.ts +43 -0
- package/src/utils/math.ts +18 -0
- package/src/utils/polyfills/createDialogPolyfill.ts +18 -0
- package/src/utils/typedActions.ts +103 -0
- package/src/vite-env.d.ts +6 -0
- package/src/window/index.ts +67 -0
- package/dist/FloatingPanelFrame-6W5OexYe.js.map +0 -1
- package/dist/FloatingPanelFrame-D9Cp2al1.cjs.map +0 -1
- package/dist/GridLayout-BzrIDrC9.js +0 -1465
- package/dist/GridLayout-BzrIDrC9.js.map +0 -1
- package/dist/GridLayout-ZrOhoLLB.cjs +0 -2
- package/dist/GridLayout-ZrOhoLLB.cjs.map +0 -1
- package/dist/sticky-header/StickyHeader.d.ts +0 -53
- package/dist/styles-CA2_zLZt.js +0 -52
- package/dist/styles-CA2_zLZt.js.map +0 -1
- package/dist/styles-PsqGOEJP.cjs +0 -2
- package/dist/styles-PsqGOEJP.cjs.map +0 -1
- package/dist/usePivot-BS-DGfwd.cjs +0 -2
- package/dist/usePivot-BS-DGfwd.cjs.map +0 -1
- package/dist/usePivot-BvOGxLQQ.js +0 -124
- package/dist/usePivot-BvOGxLQQ.js.map +0 -1
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Shared hook for DOM-based swipe content transform.
|
|
3
|
+
*
|
|
4
|
+
* This hook provides immediate DOM manipulation for swipe gestures,
|
|
5
|
+
* with smooth snap-back animation when the swipe ends.
|
|
6
|
+
*
|
|
7
|
+
* Used by both Pivot and Stack for consistent swipe behavior.
|
|
8
|
+
*/
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import { useAnimationFrame, interpolate, easings } from "./useAnimationFrame.js";
|
|
11
|
+
import type { GestureAxis } from "./gesture/types.js";
|
|
12
|
+
|
|
13
|
+
const DEFAULT_ANIMATION_DURATION = 300;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Options for useSwipeContentTransform hook.
|
|
17
|
+
*/
|
|
18
|
+
export type UseSwipeContentTransformOptions = {
|
|
19
|
+
/** Ref to the element to transform */
|
|
20
|
+
elementRef: React.RefObject<HTMLElement | null>;
|
|
21
|
+
/** Target position in pixels (where element should be at rest) */
|
|
22
|
+
targetPx: number;
|
|
23
|
+
/** Current swipe displacement in pixels */
|
|
24
|
+
displacement: number;
|
|
25
|
+
/** Whether swipe gesture is active */
|
|
26
|
+
isSwiping: boolean;
|
|
27
|
+
/** Axis of transformation */
|
|
28
|
+
axis?: GestureAxis;
|
|
29
|
+
/** Duration of snap animation in ms */
|
|
30
|
+
animationDuration?: number;
|
|
31
|
+
/** Container size in pixels (used for snap on resize) */
|
|
32
|
+
containerSize?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Whether to animate when targetPx changes (without swipe).
|
|
35
|
+
* Use this for tab bar animations triggered by click/button.
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
animateOnTargetChange?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Initial position in pixels when first mounted.
|
|
41
|
+
* If different from targetPx, will animate from initialPx to targetPx.
|
|
42
|
+
* Use this for push animations where new panel comes from off-screen.
|
|
43
|
+
*/
|
|
44
|
+
initialPx?: number;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Animation direction information.
|
|
49
|
+
*/
|
|
50
|
+
export type AnimationDirection = {
|
|
51
|
+
/** Source position in pixels */
|
|
52
|
+
from: number;
|
|
53
|
+
/** Target position in pixels */
|
|
54
|
+
to: number;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Result from useSwipeContentTransform hook.
|
|
59
|
+
*/
|
|
60
|
+
export type UseSwipeContentTransformResult = {
|
|
61
|
+
/** Whether snap animation is currently running */
|
|
62
|
+
isAnimating: boolean;
|
|
63
|
+
/** Current position in pixels (for visibility calculations) */
|
|
64
|
+
currentPx: number;
|
|
65
|
+
/** Animation direction info, or null if not animating */
|
|
66
|
+
animationDirection: AnimationDirection | null;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get CSS transform function name for axis.
|
|
71
|
+
*/
|
|
72
|
+
const getTransformFn = (axis: GestureAxis): "translateX" | "translateY" => {
|
|
73
|
+
return axis === "horizontal" ? "translateX" : "translateY";
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Hook for DOM-based swipe content transform.
|
|
78
|
+
*
|
|
79
|
+
* During swipe: immediately updates element.style.transform to follow finger.
|
|
80
|
+
* After swipe: animates from current position to target position.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
85
|
+
* const { isAnimating, currentPx } = useSwipeContentTransform({
|
|
86
|
+
* elementRef: containerRef,
|
|
87
|
+
* targetPx: 0,
|
|
88
|
+
* displacement: inputState.displacement.x,
|
|
89
|
+
* isSwiping: inputState.phase === "swiping",
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export function useSwipeContentTransform(
|
|
94
|
+
options: UseSwipeContentTransformOptions,
|
|
95
|
+
): UseSwipeContentTransformResult {
|
|
96
|
+
const {
|
|
97
|
+
elementRef,
|
|
98
|
+
targetPx,
|
|
99
|
+
displacement,
|
|
100
|
+
isSwiping,
|
|
101
|
+
axis = "horizontal",
|
|
102
|
+
animationDuration = DEFAULT_ANIMATION_DURATION,
|
|
103
|
+
containerSize,
|
|
104
|
+
animateOnTargetChange = false,
|
|
105
|
+
initialPx,
|
|
106
|
+
} = options;
|
|
107
|
+
|
|
108
|
+
// Use initialPx if provided, otherwise use targetPx
|
|
109
|
+
const effectiveInitialPx = initialPx ?? targetPx;
|
|
110
|
+
const currentPxRef = React.useRef<number>(effectiveInitialPx);
|
|
111
|
+
const animRef = React.useRef<{ from: number; to: number } | null>(null);
|
|
112
|
+
const prevTargetPxRef = React.useRef<number>(targetPx);
|
|
113
|
+
const prevContainerSizeRef = React.useRef<number | undefined>(containerSize);
|
|
114
|
+
const pendingAnimationRef = React.useRef<{ from: number; to: number } | null>(null);
|
|
115
|
+
const isFirstMountRef = React.useRef<boolean>(true);
|
|
116
|
+
|
|
117
|
+
// Schedule animation on first mount if initialPx differs from targetPx
|
|
118
|
+
if (isFirstMountRef.current && initialPx !== undefined && initialPx !== targetPx) {
|
|
119
|
+
pendingAnimationRef.current = { from: initialPx, to: targetPx };
|
|
120
|
+
isFirstMountRef.current = false;
|
|
121
|
+
} else if (isFirstMountRef.current) {
|
|
122
|
+
isFirstMountRef.current = false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Handle target changes when not swiping
|
|
126
|
+
if (targetPx !== prevTargetPxRef.current && !isSwiping && animRef.current === null) {
|
|
127
|
+
if (animateOnTargetChange) {
|
|
128
|
+
// Schedule animation from current position to new target
|
|
129
|
+
const distance = Math.abs(currentPxRef.current - targetPx);
|
|
130
|
+
if (distance > 1) {
|
|
131
|
+
pendingAnimationRef.current = { from: currentPxRef.current, to: targetPx };
|
|
132
|
+
} else {
|
|
133
|
+
currentPxRef.current = targetPx;
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
// Snap immediately (default behavior for resize, etc.)
|
|
137
|
+
currentPxRef.current = targetPx;
|
|
138
|
+
}
|
|
139
|
+
prevTargetPxRef.current = targetPx;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Snap when container size changes (resize)
|
|
143
|
+
if (containerSize !== undefined && containerSize !== prevContainerSizeRef.current && containerSize > 0) {
|
|
144
|
+
currentPxRef.current = targetPx;
|
|
145
|
+
prevContainerSizeRef.current = containerSize;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Animation frame handler
|
|
149
|
+
const handleFrame = React.useCallback(
|
|
150
|
+
({ easedProgress }: { easedProgress: number }) => {
|
|
151
|
+
const element = elementRef.current;
|
|
152
|
+
const anim = animRef.current;
|
|
153
|
+
if (!element || !anim) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const value = interpolate(anim.from, anim.to, easedProgress);
|
|
157
|
+
currentPxRef.current = value;
|
|
158
|
+
element.style.transform = `${getTransformFn(axis)}(${value}px)`;
|
|
159
|
+
},
|
|
160
|
+
[axis, elementRef],
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const handleComplete = React.useCallback(() => {
|
|
164
|
+
animRef.current = null;
|
|
165
|
+
currentPxRef.current = targetPx;
|
|
166
|
+
prevTargetPxRef.current = targetPx;
|
|
167
|
+
}, [targetPx]);
|
|
168
|
+
|
|
169
|
+
const { isAnimating, start, cancel } = useAnimationFrame({
|
|
170
|
+
duration: animationDuration,
|
|
171
|
+
easing: easings.easeOutExpo,
|
|
172
|
+
onFrame: handleFrame,
|
|
173
|
+
onComplete: handleComplete,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// When swipe ends or target changes with animateOnTargetChange, animate to target
|
|
177
|
+
React.useLayoutEffect(() => {
|
|
178
|
+
if (isSwiping) {
|
|
179
|
+
cancel();
|
|
180
|
+
animRef.current = null;
|
|
181
|
+
pendingAnimationRef.current = null;
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Check for pending animation (from target change or initial mount)
|
|
186
|
+
if (pendingAnimationRef.current) {
|
|
187
|
+
const pending = pendingAnimationRef.current;
|
|
188
|
+
animRef.current = pending;
|
|
189
|
+
pendingAnimationRef.current = null;
|
|
190
|
+
// Set initial position before animation starts
|
|
191
|
+
const element = elementRef.current;
|
|
192
|
+
if (element) {
|
|
193
|
+
element.style.transform = `${getTransformFn(axis)}(${pending.from}px)`;
|
|
194
|
+
}
|
|
195
|
+
start();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const currentPx = currentPxRef.current;
|
|
200
|
+
const distance = Math.abs(currentPx - targetPx);
|
|
201
|
+
|
|
202
|
+
if (distance > 1) {
|
|
203
|
+
// Need to animate from current to target
|
|
204
|
+
animRef.current = { from: currentPx, to: targetPx };
|
|
205
|
+
start();
|
|
206
|
+
} else {
|
|
207
|
+
// Close enough, snap directly
|
|
208
|
+
currentPxRef.current = targetPx;
|
|
209
|
+
prevTargetPxRef.current = targetPx;
|
|
210
|
+
}
|
|
211
|
+
}, [isSwiping, targetPx, start, cancel]);
|
|
212
|
+
|
|
213
|
+
// Direct DOM update during swipe
|
|
214
|
+
React.useLayoutEffect(() => {
|
|
215
|
+
const element = elementRef.current;
|
|
216
|
+
if (!element) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Skip if animation is running, about to start, or pending
|
|
221
|
+
if (isAnimating || animRef.current !== null || pendingAnimationRef.current !== null) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const displayPx = targetPx + displacement;
|
|
226
|
+
currentPxRef.current = displayPx;
|
|
227
|
+
element.style.transform = `${getTransformFn(axis)}(${displayPx}px)`;
|
|
228
|
+
}, [targetPx, displacement, axis, isAnimating, elementRef]);
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
isAnimating,
|
|
232
|
+
currentPx: currentPxRef.current,
|
|
233
|
+
animationDirection: animRef.current,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Generic transition state management with animation support.
|
|
3
|
+
*/
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
export type TransitionMode = "none" | "css";
|
|
7
|
+
|
|
8
|
+
export type TransitionOptions = {
|
|
9
|
+
mode?: TransitionMode;
|
|
10
|
+
element?: React.RefObject<HTMLElement>;
|
|
11
|
+
duration?: number;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type UseTransitionStateOptions = {
|
|
15
|
+
onOpen?: (id: string) => void;
|
|
16
|
+
onClose?: (id: string) => void;
|
|
17
|
+
onTransitionEnd?: (id: string, isOpen: boolean) => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const waitForTransitionEnd = (el: HTMLElement, timeout: number): Promise<void> =>
|
|
21
|
+
new Promise((resolve) => {
|
|
22
|
+
// eslint-disable-next-line no-restricted-syntax -- mutable flag needed for deduplication
|
|
23
|
+
let resolved = false;
|
|
24
|
+
const done = () => {
|
|
25
|
+
if (resolved) {return;}
|
|
26
|
+
resolved = true;
|
|
27
|
+
el.removeEventListener("transitionend", handler);
|
|
28
|
+
resolve();
|
|
29
|
+
};
|
|
30
|
+
const handler = (e: TransitionEvent) => {
|
|
31
|
+
if (e.target === el) {done();}
|
|
32
|
+
};
|
|
33
|
+
el.addEventListener("transitionend", handler);
|
|
34
|
+
setTimeout(done, timeout + 50);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const runTransition = async (
|
|
38
|
+
update: () => void,
|
|
39
|
+
mode: TransitionMode,
|
|
40
|
+
el: HTMLElement | null | undefined,
|
|
41
|
+
duration: number,
|
|
42
|
+
): Promise<void> => {
|
|
43
|
+
switch (mode) {
|
|
44
|
+
case "none":
|
|
45
|
+
update();
|
|
46
|
+
return;
|
|
47
|
+
|
|
48
|
+
case "css":
|
|
49
|
+
update();
|
|
50
|
+
if (el) {await waitForTransitionEnd(el, duration);}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const useTransitionState = (options?: UseTransitionStateOptions) => {
|
|
56
|
+
const [states, setStates] = React.useState<Record<string, boolean>>({});
|
|
57
|
+
const optionsRef = React.useRef(options);
|
|
58
|
+
optionsRef.current = options;
|
|
59
|
+
|
|
60
|
+
const update = React.useCallback(
|
|
61
|
+
async (id: string, isOpen: boolean, transitionOptions?: TransitionOptions) => {
|
|
62
|
+
const { mode = "none", element, duration = 300 } = transitionOptions ?? {};
|
|
63
|
+
|
|
64
|
+
const applyState = () => {
|
|
65
|
+
setStates((prev) => {
|
|
66
|
+
if (prev[id] === isOpen) {return prev;}
|
|
67
|
+
return { ...prev, [id]: isOpen };
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
await runTransition(applyState, mode, element?.current, duration);
|
|
72
|
+
|
|
73
|
+
const opts = optionsRef.current;
|
|
74
|
+
if (isOpen) {
|
|
75
|
+
opts?.onOpen?.(id);
|
|
76
|
+
} else {
|
|
77
|
+
opts?.onClose?.(id);
|
|
78
|
+
}
|
|
79
|
+
opts?.onTransitionEnd?.(id, isOpen);
|
|
80
|
+
},
|
|
81
|
+
[],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const state = React.useCallback((id: string): boolean => states[id] ?? false, [states]);
|
|
85
|
+
const open = React.useCallback(
|
|
86
|
+
(id: string, opts?: TransitionOptions) => update(id, true, opts),
|
|
87
|
+
[update],
|
|
88
|
+
);
|
|
89
|
+
const close = React.useCallback(
|
|
90
|
+
(id: string, opts?: TransitionOptions) => update(id, false, opts),
|
|
91
|
+
[update],
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return { state, open, close };
|
|
95
|
+
};
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Main entry point for the React Panel Layout library
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Core Type Definitions
|
|
7
|
+
// ============================================================================
|
|
8
|
+
export type {
|
|
9
|
+
// Grid / panel
|
|
10
|
+
GridTrack,
|
|
11
|
+
PanelLayoutConfig,
|
|
12
|
+
LayerPositionMode,
|
|
13
|
+
LayerDefinition,
|
|
14
|
+
PanelLayoutProps,
|
|
15
|
+
// Window / popup / drawer
|
|
16
|
+
Position,
|
|
17
|
+
WindowOffset,
|
|
18
|
+
WindowPosition,
|
|
19
|
+
WindowSize,
|
|
20
|
+
WindowBounds,
|
|
21
|
+
WindowConstraints,
|
|
22
|
+
PopupWindowFeatures,
|
|
23
|
+
PopupWindowOptions,
|
|
24
|
+
PopupWindowFactoryConfig,
|
|
25
|
+
FloatingWindowMode,
|
|
26
|
+
FloatingBehavior,
|
|
27
|
+
FloatingHeaderConfig,
|
|
28
|
+
DrawerBehavior,
|
|
29
|
+
} from "./types";
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Main Layout Component
|
|
33
|
+
// ============================================================================
|
|
34
|
+
export { GridLayout } from "./components/grid/GridLayout";
|
|
35
|
+
export type { GridLayoutProps } from "./components/grid/GridLayout";
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Drawer Components
|
|
39
|
+
// ============================================================================
|
|
40
|
+
export { Drawer } from "./components/window/Drawer";
|
|
41
|
+
export type { DrawerProps } from "./components/window/Drawer";
|
|
42
|
+
export { DrawerLayers } from "./components/window/DrawerLayers";
|
|
43
|
+
export type { DrawerLayersProps } from "./components/window/DrawerLayers";
|
|
44
|
+
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Floating Window Components
|
|
47
|
+
// ============================================================================
|
|
48
|
+
export { FloatingWindow } from "./components/window/FloatingWindow";
|
|
49
|
+
export type { FloatingWindowProps } from "./components/window/FloatingWindow";
|
|
50
|
+
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Panel Components
|
|
53
|
+
// ============================================================================
|
|
54
|
+
export { HorizontalDivider } from "./components/resizer/HorizontalDivider";
|
|
55
|
+
export type { HorizontalDividerProps } from "./components/resizer/HorizontalDivider";
|
|
56
|
+
|
|
57
|
+
export { ResizeHandle } from "./components/resizer/ResizeHandle";
|
|
58
|
+
export type { ResizeHandleProps } from "./components/resizer/ResizeHandle";
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Public Hooks
|
|
62
|
+
// ============================================================================
|
|
63
|
+
export { useLayerDragHandle } from "./modules/grid/useLayerDragHandle";
|
|
64
|
+
export { useFloatingState } from "./modules/window/useFloatingState";
|
|
65
|
+
export { useTransitionState, runTransition } from "./hooks/useTransitionState";
|
|
66
|
+
export type { TransitionMode, TransitionOptions, UseTransitionStateOptions } from "./hooks/useTransitionState";
|
|
67
|
+
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// Style Constants
|
|
70
|
+
// ============================================================================
|
|
71
|
+
export { CSS_VAR_PREFIX } from "./constants/styles";
|
|
72
|
+
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// Panel System (tabs + splits)
|
|
75
|
+
// ============================================================================
|
|
76
|
+
export { PanelSystem } from "./modules/panels/system/PanelSystem";
|
|
77
|
+
export { buildInitialState } from "./modules/panels";
|
|
78
|
+
export type {
|
|
79
|
+
PanelSystemProps,
|
|
80
|
+
PanelSystemState,
|
|
81
|
+
GroupModel,
|
|
82
|
+
TabDefinition,
|
|
83
|
+
SplitDirection,
|
|
84
|
+
TabBarRenderProps,
|
|
85
|
+
PanelGroupRenderProps,
|
|
86
|
+
PanelSplitLimits,
|
|
87
|
+
} from "./modules/panels/state/types";
|
|
88
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Context provider for grid layer rendering helpers.
|
|
3
|
+
*/
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import type { LayerDefinition } from "../../types";
|
|
6
|
+
|
|
7
|
+
export type GridLayerHandleProps = React.HTMLAttributes<HTMLElement> & {
|
|
8
|
+
"data-drag-handle": "true";
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type ResizeHandleConfig =
|
|
12
|
+
| {
|
|
13
|
+
key: "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
14
|
+
variant: "corner";
|
|
15
|
+
horizontal: "left" | "right";
|
|
16
|
+
vertical: "top" | "bottom";
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
key: "left" | "right" | "top" | "bottom";
|
|
20
|
+
variant: "edge";
|
|
21
|
+
horizontal?: "left" | "right";
|
|
22
|
+
vertical?: "top" | "bottom";
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type GridLayerRenderState = {
|
|
26
|
+
style: React.CSSProperties;
|
|
27
|
+
isResizable: boolean;
|
|
28
|
+
isResizing: boolean;
|
|
29
|
+
onResizeHandlePointerDown: (config: ResizeHandleConfig, event: React.PointerEvent<HTMLDivElement>) => void;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type GridLayoutContextValue = {
|
|
33
|
+
handleLayerPointerDown: (event: React.PointerEvent<HTMLDivElement>) => void;
|
|
34
|
+
getLayerRenderState: (layer: LayerDefinition) => GridLayerRenderState;
|
|
35
|
+
getLayerHandleProps: (layerId: string) => GridLayerHandleProps;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the GridLayout is mounted at root level.
|
|
38
|
+
* When true, scrollable layers should delegate to browser's native scroll.
|
|
39
|
+
*/
|
|
40
|
+
isRootLevel: boolean;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const GridLayoutContext = React.createContext<GridLayoutContextValue | null>(null);
|
|
44
|
+
|
|
45
|
+
export const GridLayoutProvider: React.FC<
|
|
46
|
+
React.PropsWithChildren<{ value: GridLayoutContextValue }>
|
|
47
|
+
> = ({ value, children }) => {
|
|
48
|
+
return <GridLayoutContext.Provider value={value}>{children}</GridLayoutContext.Provider>;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const useGridLayoutContext = (): GridLayoutContextValue => {
|
|
52
|
+
const context = React.useContext(GridLayoutContext);
|
|
53
|
+
if (!context) {
|
|
54
|
+
throw new Error("useGridLayoutContext must be used within a GridLayoutProvider.");
|
|
55
|
+
}
|
|
56
|
+
return context;
|
|
57
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Context exposing the current grid layer id and helpers to child components.
|
|
3
|
+
*/
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import type { LayerDefinition } from "../../types";
|
|
6
|
+
import { usePanelSystem } from "../../PanelSystemContext";
|
|
7
|
+
import { useGridLayoutContext, type GridLayerHandleProps } from "./GridLayoutContext";
|
|
8
|
+
|
|
9
|
+
type LayerInstanceContextValue = {
|
|
10
|
+
layerId: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const LayerInstanceContext = React.createContext<LayerInstanceContextValue | null>(null);
|
|
14
|
+
|
|
15
|
+
export type LayerInstanceProviderProps = React.PropsWithChildren<LayerInstanceContextValue>;
|
|
16
|
+
|
|
17
|
+
export const LayerInstanceProvider: React.FC<LayerInstanceProviderProps> = ({ layerId, children }) => {
|
|
18
|
+
const value = React.useMemo(() => ({ layerId }), [layerId]);
|
|
19
|
+
return <LayerInstanceContext.Provider value={value}>{children}</LayerInstanceContext.Provider>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const useLayerInstance = (): LayerInstanceContextValue => {
|
|
23
|
+
const value = React.useContext(LayerInstanceContext);
|
|
24
|
+
if (!value) {
|
|
25
|
+
throw new Error("useLayerInstance must be used within a LayerInstanceProvider.");
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Convenience: read the current layer definition from the core registry.
|
|
32
|
+
*/
|
|
33
|
+
export const useCurrentLayerDefinition = (): LayerDefinition => {
|
|
34
|
+
const { layerId } = useLayerInstance();
|
|
35
|
+
const { layers } = usePanelSystem();
|
|
36
|
+
const def = layers.layerById.get(layerId);
|
|
37
|
+
if (!def) {
|
|
38
|
+
throw new Error(`Layer definition not found for id: ${layerId}`);
|
|
39
|
+
}
|
|
40
|
+
return def;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Convenience: get drag handle props, pre-bound to the current layer.
|
|
45
|
+
*/
|
|
46
|
+
export const useCurrentLayerHandleProps = (): GridLayerHandleProps => {
|
|
47
|
+
const { layerId } = useLayerInstance();
|
|
48
|
+
const { getLayerHandleProps } = useGridLayoutContext();
|
|
49
|
+
return React.useMemo(() => getLayerHandleProps(layerId), [getLayerHandleProps, layerId]);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Compatibility helper for existing code using useLayerDragHandle.
|
|
54
|
+
* Prefer useCurrentLayerHandleProps for direct access.
|
|
55
|
+
*/
|
|
56
|
+
export const useLayerDragHandleProps = useCurrentLayerHandleProps;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Resize handle configuration computation for grid tracks.
|
|
3
|
+
*/
|
|
4
|
+
import type { GridTrack } from "../../types";
|
|
5
|
+
|
|
6
|
+
export type TrackHandleConfig = {
|
|
7
|
+
trackIndex: number;
|
|
8
|
+
align: "start" | "end";
|
|
9
|
+
span: { start: number; end: number };
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Computes the valid row span for a column boundary.
|
|
14
|
+
* Returns the contiguous range of rows where the adjacent areas differ.
|
|
15
|
+
*/
|
|
16
|
+
const computeColumnBoundarySpan = (
|
|
17
|
+
areas: string[][],
|
|
18
|
+
boundaryIndex: number,
|
|
19
|
+
): { start: number; end: number } => {
|
|
20
|
+
const rowCount = areas.length;
|
|
21
|
+
|
|
22
|
+
// Find rows where left and right areas differ at this boundary
|
|
23
|
+
const validRows: number[] = [];
|
|
24
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
25
|
+
const row = areas[rowIndex];
|
|
26
|
+
const leftArea = row[boundaryIndex];
|
|
27
|
+
const rightArea = row[boundaryIndex + 1];
|
|
28
|
+
if (leftArea !== rightArea) {
|
|
29
|
+
validRows.push(rowIndex);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (validRows.length === 0) {
|
|
34
|
+
// Fallback: full span if no valid rows found (shouldn't happen for resizable columns)
|
|
35
|
+
return { start: 1, end: rowCount + 1 };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Convert to 1-indexed grid lines
|
|
39
|
+
const minRow = Math.min(...validRows);
|
|
40
|
+
const maxRow = Math.max(...validRows);
|
|
41
|
+
return { start: minRow + 1, end: maxRow + 2 };
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Computes the valid column span for a row boundary.
|
|
46
|
+
* Returns the contiguous range of columns where the adjacent areas differ.
|
|
47
|
+
*/
|
|
48
|
+
const computeRowBoundarySpan = (
|
|
49
|
+
areas: string[][],
|
|
50
|
+
boundaryIndex: number,
|
|
51
|
+
): { start: number; end: number } => {
|
|
52
|
+
const topRow = areas[boundaryIndex];
|
|
53
|
+
const bottomRow = areas[boundaryIndex + 1];
|
|
54
|
+
const colCount = topRow?.length ?? 0;
|
|
55
|
+
|
|
56
|
+
// Find columns where top and bottom areas differ at this boundary
|
|
57
|
+
const validCols: number[] = [];
|
|
58
|
+
for (let colIndex = 0; colIndex < colCount; colIndex++) {
|
|
59
|
+
const topArea = topRow?.[colIndex];
|
|
60
|
+
const bottomArea = bottomRow?.[colIndex];
|
|
61
|
+
if (topArea !== bottomArea) {
|
|
62
|
+
validCols.push(colIndex);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (validCols.length === 0) {
|
|
67
|
+
// Fallback: full span if no valid columns found
|
|
68
|
+
return { start: 1, end: colCount + 1 };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Convert to 1-indexed grid lines
|
|
72
|
+
const minCol = Math.min(...validCols);
|
|
73
|
+
const maxCol = Math.max(...validCols);
|
|
74
|
+
return { start: minCol + 1, end: maxCol + 2 };
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const computeColumnResizeHandles = (
|
|
78
|
+
tracks: GridTrack[],
|
|
79
|
+
areas: string[][],
|
|
80
|
+
): TrackHandleConfig[] => {
|
|
81
|
+
if (tracks.length === 0) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const rowCount = areas.length;
|
|
86
|
+
|
|
87
|
+
if (tracks.length === 1) {
|
|
88
|
+
const onlyTrack = tracks[0];
|
|
89
|
+
if (onlyTrack?.resizable) {
|
|
90
|
+
const fullSpan = { start: 1, end: rowCount + 1 };
|
|
91
|
+
return [{ trackIndex: 0, align: "end", span: fullSpan }];
|
|
92
|
+
}
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const handles: TrackHandleConfig[] = [];
|
|
97
|
+
|
|
98
|
+
const boundaryIndexes = Array.from({ length: tracks.length - 1 }, (_, index) => index);
|
|
99
|
+
boundaryIndexes.forEach((boundaryIndex) => {
|
|
100
|
+
const leftTrack = tracks[boundaryIndex];
|
|
101
|
+
const rightTrack = tracks[boundaryIndex + 1];
|
|
102
|
+
|
|
103
|
+
if (rightTrack?.resizable) {
|
|
104
|
+
const span = computeColumnBoundarySpan(areas, boundaryIndex);
|
|
105
|
+
handles.push({ trackIndex: boundaryIndex + 1, align: "start", span });
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (leftTrack?.resizable) {
|
|
110
|
+
const span = computeColumnBoundarySpan(areas, boundaryIndex);
|
|
111
|
+
handles.push({ trackIndex: boundaryIndex, align: "end", span });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return handles;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const computeRowResizeHandles = (
|
|
119
|
+
tracks: GridTrack[],
|
|
120
|
+
areas: string[][],
|
|
121
|
+
): TrackHandleConfig[] => {
|
|
122
|
+
if (tracks.length === 0) {
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const colCount = areas[0]?.length ?? 0;
|
|
127
|
+
|
|
128
|
+
if (tracks.length === 1) {
|
|
129
|
+
const onlyTrack = tracks[0];
|
|
130
|
+
if (onlyTrack?.resizable) {
|
|
131
|
+
const fullSpan = { start: 1, end: colCount + 1 };
|
|
132
|
+
return [{ trackIndex: 0, align: "end", span: fullSpan }];
|
|
133
|
+
}
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const handles: TrackHandleConfig[] = [];
|
|
138
|
+
|
|
139
|
+
const boundaryIndexes = Array.from({ length: tracks.length - 1 }, (_, index) => index);
|
|
140
|
+
boundaryIndexes.forEach((boundaryIndex) => {
|
|
141
|
+
const topTrack = tracks[boundaryIndex];
|
|
142
|
+
const bottomTrack = tracks[boundaryIndex + 1];
|
|
143
|
+
|
|
144
|
+
if (bottomTrack?.resizable) {
|
|
145
|
+
const span = computeRowBoundarySpan(areas, boundaryIndex);
|
|
146
|
+
handles.push({ trackIndex: boundaryIndex + 1, align: "start", span });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (topTrack?.resizable) {
|
|
151
|
+
const span = computeRowBoundarySpan(areas, boundaryIndex);
|
|
152
|
+
handles.push({ trackIndex: boundaryIndex, align: "end", span });
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return handles;
|
|
157
|
+
};
|