react-panel-layout 0.5.2 → 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-D9Cp2al1.cjs.map → FloatingPanelFrame-CEmXDvUA.cjs.map} +1 -1
- package/dist/{FloatingPanelFrame-lLg-Lpg7.js → FloatingPanelFrame-SgYLc6Ud.js} +11 -11
- package/dist/{FloatingPanelFrame-lLg-Lpg7.js.map → FloatingPanelFrame-SgYLc6Ud.js.map} +1 -1
- 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 +67 -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/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/GridLayout-BQQ63eA1.cjs +0 -2
- package/dist/GridLayout-BQQ63eA1.cjs.map +0 -1
- package/dist/GridLayout-CJTKq7Mp.js +0 -1465
- package/dist/GridLayout-CJTKq7Mp.js.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-7ctin_P_.cjs +0 -2
- package/dist/usePivot-7ctin_P_.cjs.map +0 -1
- package/dist/usePivot-CgQxB8rc.js +0 -124
- package/dist/usePivot-CgQxB8rc.js.map +0 -1
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Pure functions for computing StackContent state.
|
|
3
|
+
*
|
|
4
|
+
* Separates state computation logic from React/CSS concerns for testability.
|
|
5
|
+
* All functions are pure and deterministic.
|
|
6
|
+
*/
|
|
7
|
+
import {
|
|
8
|
+
STACK_ANIMATION_PUSH,
|
|
9
|
+
STACK_ANIMATION_POP,
|
|
10
|
+
STACK_TRANSITION_DURATION,
|
|
11
|
+
STACK_TRANSITION_EASING,
|
|
12
|
+
} from "../../constants/styles.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Animation type for stack panel transitions.
|
|
16
|
+
*/
|
|
17
|
+
export type StackAnimationType = "push" | "pop" | null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Display mode for stack panels.
|
|
21
|
+
*/
|
|
22
|
+
export type StackDisplayMode = "overlay" | "slide" | "stack";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Transition mode for animations.
|
|
26
|
+
*/
|
|
27
|
+
export type StackTransitionMode = "css" | "none";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Input for computing animation type.
|
|
31
|
+
*/
|
|
32
|
+
export type ComputeAnimationTypeInput = {
|
|
33
|
+
wasActive: boolean;
|
|
34
|
+
isActive: boolean;
|
|
35
|
+
transitionMode: StackTransitionMode;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Compute the animation type based on active state change.
|
|
40
|
+
*
|
|
41
|
+
* @returns The animation type to apply, or null if no animation needed.
|
|
42
|
+
*/
|
|
43
|
+
export function computeAnimationType(input: ComputeAnimationTypeInput): StackAnimationType {
|
|
44
|
+
const { wasActive, isActive, transitionMode } = input;
|
|
45
|
+
|
|
46
|
+
if (transitionMode !== "css") {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (wasActive === isActive) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return isActive ? "push" : "pop";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Input for computing visibility.
|
|
59
|
+
*/
|
|
60
|
+
export type ComputeVisibilityInput = {
|
|
61
|
+
displayMode: StackDisplayMode;
|
|
62
|
+
depth: number;
|
|
63
|
+
navigationDepth: number;
|
|
64
|
+
isActive: boolean;
|
|
65
|
+
isAnimatingOut: boolean;
|
|
66
|
+
isRevealing: boolean;
|
|
67
|
+
revealDepth: number | null;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Compute panel visibility based on display mode and state.
|
|
72
|
+
*
|
|
73
|
+
* @returns "visible" or "hidden"
|
|
74
|
+
*/
|
|
75
|
+
export function computeVisibility(input: ComputeVisibilityInput): "visible" | "hidden" {
|
|
76
|
+
const {
|
|
77
|
+
displayMode,
|
|
78
|
+
depth,
|
|
79
|
+
navigationDepth,
|
|
80
|
+
isActive,
|
|
81
|
+
isAnimatingOut,
|
|
82
|
+
isRevealing,
|
|
83
|
+
revealDepth,
|
|
84
|
+
} = input;
|
|
85
|
+
|
|
86
|
+
if (displayMode === "overlay") {
|
|
87
|
+
// In overlay mode, only show active, animating out, or revealing panel
|
|
88
|
+
if (isActive) {
|
|
89
|
+
return "visible";
|
|
90
|
+
}
|
|
91
|
+
if (isAnimatingOut) {
|
|
92
|
+
return "visible";
|
|
93
|
+
}
|
|
94
|
+
if (isRevealing && depth === revealDepth) {
|
|
95
|
+
return "visible";
|
|
96
|
+
}
|
|
97
|
+
return "hidden";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// In slide/stack mode, show all panels in stack or animating out
|
|
101
|
+
if (depth <= navigationDepth) {
|
|
102
|
+
return "visible";
|
|
103
|
+
}
|
|
104
|
+
if (isAnimatingOut) {
|
|
105
|
+
return "visible";
|
|
106
|
+
}
|
|
107
|
+
return "hidden";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Input for computing transform.
|
|
112
|
+
*/
|
|
113
|
+
export type ComputeTransformInput = {
|
|
114
|
+
depth: number;
|
|
115
|
+
activeDepth: number;
|
|
116
|
+
displayMode: StackDisplayMode;
|
|
117
|
+
isRevealing: boolean;
|
|
118
|
+
revealDepth: number | null;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Compute the transform value for a stack panel.
|
|
123
|
+
*
|
|
124
|
+
* @returns CSS transform string
|
|
125
|
+
*/
|
|
126
|
+
export function computeTransform(input: ComputeTransformInput): string {
|
|
127
|
+
const { depth, activeDepth, displayMode, isRevealing, revealDepth } = input;
|
|
128
|
+
|
|
129
|
+
const isActive = depth === activeDepth;
|
|
130
|
+
const isPrevious = depth < activeDepth;
|
|
131
|
+
|
|
132
|
+
// During reveal, shift active panel to show parent
|
|
133
|
+
if (isRevealing && isActive) {
|
|
134
|
+
if (revealDepth !== null) {
|
|
135
|
+
const revealProgress = 0.3;
|
|
136
|
+
return `translateX(${revealProgress * 100}%)`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (isActive) {
|
|
141
|
+
return "translateX(0)";
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (isPrevious) {
|
|
145
|
+
switch (displayMode) {
|
|
146
|
+
case "overlay":
|
|
147
|
+
return "translateX(0)";
|
|
148
|
+
case "slide":
|
|
149
|
+
return "translateX(-30%)";
|
|
150
|
+
case "stack": {
|
|
151
|
+
const offset = (activeDepth - depth) * -5;
|
|
152
|
+
const scale = 1 - (activeDepth - depth) * 0.05;
|
|
153
|
+
return `translateX(${offset}%) scale(${scale})`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Future panels stay off-screen
|
|
159
|
+
return "translateX(100%)";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Compute the transform value considering swipe progress.
|
|
164
|
+
*/
|
|
165
|
+
function computeSwipeTransform(
|
|
166
|
+
baseTransform: string,
|
|
167
|
+
swipeProgress: number | undefined,
|
|
168
|
+
isActive: boolean,
|
|
169
|
+
): string {
|
|
170
|
+
if (swipeProgress === undefined) {
|
|
171
|
+
return baseTransform;
|
|
172
|
+
}
|
|
173
|
+
if (swipeProgress <= 0) {
|
|
174
|
+
return baseTransform;
|
|
175
|
+
}
|
|
176
|
+
if (!isActive) {
|
|
177
|
+
return baseTransform;
|
|
178
|
+
}
|
|
179
|
+
return `translateX(${swipeProgress * 100}%)`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Compute the transition CSS value.
|
|
184
|
+
*/
|
|
185
|
+
function computeTransitionCss(transitionMode: StackTransitionMode): string | undefined {
|
|
186
|
+
if (transitionMode !== "css") {
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
return `transform ${STACK_TRANSITION_DURATION} ${STACK_TRANSITION_EASING}`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Full input for computing stack content state.
|
|
194
|
+
*/
|
|
195
|
+
export type StackContentStateInput = {
|
|
196
|
+
depth: number;
|
|
197
|
+
isActive: boolean;
|
|
198
|
+
wasActive: boolean;
|
|
199
|
+
currentAnimationType: StackAnimationType;
|
|
200
|
+
displayMode: StackDisplayMode;
|
|
201
|
+
transitionMode: StackTransitionMode;
|
|
202
|
+
navigationState: {
|
|
203
|
+
depth: number;
|
|
204
|
+
isRevealing: boolean;
|
|
205
|
+
revealDepth: number | null;
|
|
206
|
+
};
|
|
207
|
+
swipeProgress: number | undefined;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Computed state output for stack content.
|
|
212
|
+
*/
|
|
213
|
+
export type StackContentStateOutput = {
|
|
214
|
+
nextAnimationType: StackAnimationType;
|
|
215
|
+
visibility: "visible" | "hidden";
|
|
216
|
+
transform: string;
|
|
217
|
+
animation: string | undefined;
|
|
218
|
+
transition: string | undefined;
|
|
219
|
+
zIndex: number;
|
|
220
|
+
pointerEvents: "auto" | "none";
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Compute the complete state for a stack content panel.
|
|
225
|
+
*
|
|
226
|
+
* This is the main entry point that combines all state computation.
|
|
227
|
+
* Pure function with no side effects.
|
|
228
|
+
*
|
|
229
|
+
* @param input - All inputs needed to compute state
|
|
230
|
+
* @returns Computed state for rendering
|
|
231
|
+
*/
|
|
232
|
+
export function computeStackContentState(input: StackContentStateInput): StackContentStateOutput {
|
|
233
|
+
const {
|
|
234
|
+
depth,
|
|
235
|
+
isActive,
|
|
236
|
+
wasActive,
|
|
237
|
+
currentAnimationType,
|
|
238
|
+
displayMode,
|
|
239
|
+
transitionMode,
|
|
240
|
+
navigationState,
|
|
241
|
+
swipeProgress,
|
|
242
|
+
} = input;
|
|
243
|
+
|
|
244
|
+
// 1. Compute animation type
|
|
245
|
+
const stateChangeAnimationType = computeAnimationType({
|
|
246
|
+
wasActive,
|
|
247
|
+
isActive,
|
|
248
|
+
transitionMode,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Use new animation type if state changed, otherwise preserve current
|
|
252
|
+
const nextAnimationType = stateChangeAnimationType ?? currentAnimationType;
|
|
253
|
+
|
|
254
|
+
// 2. Compute visibility
|
|
255
|
+
const isAnimatingOut = nextAnimationType === "pop";
|
|
256
|
+
const visibility = computeVisibility({
|
|
257
|
+
displayMode,
|
|
258
|
+
depth,
|
|
259
|
+
navigationDepth: navigationState.depth,
|
|
260
|
+
isActive,
|
|
261
|
+
isAnimatingOut,
|
|
262
|
+
isRevealing: navigationState.isRevealing,
|
|
263
|
+
revealDepth: navigationState.revealDepth,
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// 3. Compute transform
|
|
267
|
+
const baseTransform = computeTransform({
|
|
268
|
+
depth,
|
|
269
|
+
activeDepth: navigationState.depth,
|
|
270
|
+
displayMode,
|
|
271
|
+
isRevealing: navigationState.isRevealing,
|
|
272
|
+
revealDepth: navigationState.revealDepth,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Apply swipe progress transform if swiping on active panel
|
|
276
|
+
const transform = computeSwipeTransform(baseTransform, swipeProgress, isActive);
|
|
277
|
+
|
|
278
|
+
// 4. Compute animation CSS
|
|
279
|
+
const animation = (() => {
|
|
280
|
+
if (transitionMode !== "css") {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
if (nextAnimationType === "push") {
|
|
284
|
+
return STACK_ANIMATION_PUSH;
|
|
285
|
+
}
|
|
286
|
+
if (nextAnimationType === "pop") {
|
|
287
|
+
return STACK_ANIMATION_POP;
|
|
288
|
+
}
|
|
289
|
+
return undefined;
|
|
290
|
+
})();
|
|
291
|
+
|
|
292
|
+
// 5. Compute transition CSS
|
|
293
|
+
const transition = computeTransitionCss(transitionMode);
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
nextAnimationType,
|
|
297
|
+
visibility,
|
|
298
|
+
transform,
|
|
299
|
+
animation,
|
|
300
|
+
transition,
|
|
301
|
+
zIndex: depth,
|
|
302
|
+
pointerEvents: isActive ? "auto" : "none",
|
|
303
|
+
};
|
|
304
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Tests for computeSwipeStackTransform pure functions.
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
computeActiveTargetPx,
|
|
6
|
+
computeBehindTargetPx,
|
|
7
|
+
computeSwipeProgress,
|
|
8
|
+
computeSwipeVisibility,
|
|
9
|
+
determineSwipePanelRole,
|
|
10
|
+
DEFAULT_BEHIND_OFFSET,
|
|
11
|
+
} from "./computeSwipeStackTransform.js";
|
|
12
|
+
|
|
13
|
+
describe("computeActiveTargetPx", () => {
|
|
14
|
+
it("returns 0 for no displacement", () => {
|
|
15
|
+
expect(computeActiveTargetPx(0)).toBe(0);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("returns positive displacement directly", () => {
|
|
19
|
+
expect(computeActiveTargetPx(100)).toBe(100);
|
|
20
|
+
expect(computeActiveTargetPx(250)).toBe(250);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("clamps negative displacement to 0", () => {
|
|
24
|
+
expect(computeActiveTargetPx(-50)).toBe(0);
|
|
25
|
+
expect(computeActiveTargetPx(-100)).toBe(0);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("computeBehindTargetPx", () => {
|
|
30
|
+
const containerSize = 400;
|
|
31
|
+
|
|
32
|
+
it("returns base offset position with no displacement", () => {
|
|
33
|
+
const result = computeBehindTargetPx(0, containerSize);
|
|
34
|
+
// Default offset is -0.3, so -0.3 * 400 = -120
|
|
35
|
+
expect(result).toBe(-120);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("moves towards 0 as displacement increases", () => {
|
|
39
|
+
// At 50% progress (200px displacement)
|
|
40
|
+
const halfProgress = computeBehindTargetPx(200, containerSize);
|
|
41
|
+
// Should be at -60 (halfway from -120 to 0)
|
|
42
|
+
expect(halfProgress).toBe(-60);
|
|
43
|
+
|
|
44
|
+
// At 100% progress (400px displacement)
|
|
45
|
+
const fullProgress = computeBehindTargetPx(400, containerSize);
|
|
46
|
+
// Should be at 0
|
|
47
|
+
expect(fullProgress).toBe(0);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("clamps at 0 for large displacement", () => {
|
|
51
|
+
const result = computeBehindTargetPx(800, containerSize);
|
|
52
|
+
expect(result).toBe(0);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("handles negative displacement", () => {
|
|
56
|
+
const result = computeBehindTargetPx(-50, containerSize);
|
|
57
|
+
// Negative displacement is treated as 0
|
|
58
|
+
expect(result).toBe(-120);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("handles zero container size", () => {
|
|
62
|
+
expect(computeBehindTargetPx(100, 0)).toBe(0);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("uses custom behind offset", () => {
|
|
66
|
+
const customOffset = -0.5; // -50%
|
|
67
|
+
const result = computeBehindTargetPx(0, containerSize, customOffset);
|
|
68
|
+
expect(result).toBe(-200); // -0.5 * 400
|
|
69
|
+
|
|
70
|
+
// At full progress
|
|
71
|
+
const fullProgress = computeBehindTargetPx(400, containerSize, customOffset);
|
|
72
|
+
expect(fullProgress).toBe(0);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe("computeSwipeProgress", () => {
|
|
77
|
+
const containerSize = 400;
|
|
78
|
+
|
|
79
|
+
it("returns 0 for no displacement", () => {
|
|
80
|
+
expect(computeSwipeProgress(0, containerSize)).toBe(0);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("returns correct progress for partial swipe", () => {
|
|
84
|
+
expect(computeSwipeProgress(100, containerSize)).toBe(0.25);
|
|
85
|
+
expect(computeSwipeProgress(200, containerSize)).toBe(0.5);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("clamps at 1 for full swipe", () => {
|
|
89
|
+
expect(computeSwipeProgress(400, containerSize)).toBe(1);
|
|
90
|
+
expect(computeSwipeProgress(600, containerSize)).toBe(1);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("handles negative displacement as 0", () => {
|
|
94
|
+
expect(computeSwipeProgress(-50, containerSize)).toBe(0);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("handles zero container size", () => {
|
|
98
|
+
expect(computeSwipeProgress(100, 0)).toBe(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("computeSwipeVisibility", () => {
|
|
103
|
+
it("active panel is always visible", () => {
|
|
104
|
+
expect(
|
|
105
|
+
computeSwipeVisibility({
|
|
106
|
+
depth: 2,
|
|
107
|
+
navigationDepth: 2,
|
|
108
|
+
isActive: true,
|
|
109
|
+
isSwiping: false,
|
|
110
|
+
isAnimating: false,
|
|
111
|
+
}),
|
|
112
|
+
).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("behind panel is visible when swiping", () => {
|
|
116
|
+
expect(
|
|
117
|
+
computeSwipeVisibility({
|
|
118
|
+
depth: 1,
|
|
119
|
+
navigationDepth: 2,
|
|
120
|
+
isActive: false,
|
|
121
|
+
isSwiping: true,
|
|
122
|
+
isAnimating: false,
|
|
123
|
+
}),
|
|
124
|
+
).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("behind panel is visible when animating", () => {
|
|
128
|
+
expect(
|
|
129
|
+
computeSwipeVisibility({
|
|
130
|
+
depth: 1,
|
|
131
|
+
navigationDepth: 2,
|
|
132
|
+
isActive: false,
|
|
133
|
+
isSwiping: false,
|
|
134
|
+
isAnimating: true,
|
|
135
|
+
}),
|
|
136
|
+
).toBe(true);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("behind panel is hidden when idle", () => {
|
|
140
|
+
expect(
|
|
141
|
+
computeSwipeVisibility({
|
|
142
|
+
depth: 1,
|
|
143
|
+
navigationDepth: 2,
|
|
144
|
+
isActive: false,
|
|
145
|
+
isSwiping: false,
|
|
146
|
+
isAnimating: false,
|
|
147
|
+
}),
|
|
148
|
+
).toBe(false);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("deeper panels are hidden during swipe", () => {
|
|
152
|
+
expect(
|
|
153
|
+
computeSwipeVisibility({
|
|
154
|
+
depth: 0,
|
|
155
|
+
navigationDepth: 2,
|
|
156
|
+
isActive: false,
|
|
157
|
+
isSwiping: true,
|
|
158
|
+
isAnimating: false,
|
|
159
|
+
}),
|
|
160
|
+
).toBe(false);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe("determineSwipePanelRole", () => {
|
|
165
|
+
it("returns active for current depth", () => {
|
|
166
|
+
expect(determineSwipePanelRole(2, 2)).toBe("active");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("returns behind for previous depth", () => {
|
|
170
|
+
expect(determineSwipePanelRole(1, 2)).toBe("behind");
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("returns hidden for deeper levels", () => {
|
|
174
|
+
expect(determineSwipePanelRole(0, 2)).toBe("hidden");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("returns hidden for future levels", () => {
|
|
178
|
+
expect(determineSwipePanelRole(3, 2)).toBe("hidden");
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe("DEFAULT_BEHIND_OFFSET", () => {
|
|
183
|
+
it("is -0.3 (30% offset)", () => {
|
|
184
|
+
expect(DEFAULT_BEHIND_OFFSET).toBe(-0.3);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Pure functions for computing Stack panel transforms during swipe.
|
|
3
|
+
*
|
|
4
|
+
* These functions calculate positions for iOS-style "swipe to go back" behavior
|
|
5
|
+
* where the active panel follows the finger and the behind panel reveals from -30%.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Default offset for behind panel (-30% of container width).
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_BEHIND_OFFSET = -0.3;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Compute the target position for the active panel.
|
|
15
|
+
*
|
|
16
|
+
* Active panel starts at 0 and moves right as the user swipes.
|
|
17
|
+
*
|
|
18
|
+
* @param displacement - Current swipe displacement in pixels
|
|
19
|
+
* @returns Target position in pixels
|
|
20
|
+
*/
|
|
21
|
+
export function computeActiveTargetPx(displacement: number): number {
|
|
22
|
+
// Active panel follows the finger directly
|
|
23
|
+
// Only move right (positive displacement) for left-edge swipe
|
|
24
|
+
return Math.max(0, displacement);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Compute the target position for the behind panel.
|
|
29
|
+
*
|
|
30
|
+
* Behind panel starts at -30% and moves to 0% as swipe progresses.
|
|
31
|
+
* Uses parallax effect: moves slower than the active panel.
|
|
32
|
+
*
|
|
33
|
+
* @param displacement - Current swipe displacement in pixels
|
|
34
|
+
* @param containerSize - Container width/height in pixels
|
|
35
|
+
* @param behindOffset - Starting offset ratio (default -0.3 for -30%)
|
|
36
|
+
* @returns Target position in pixels
|
|
37
|
+
*/
|
|
38
|
+
export function computeBehindTargetPx(
|
|
39
|
+
displacement: number,
|
|
40
|
+
containerSize: number,
|
|
41
|
+
behindOffset: number = DEFAULT_BEHIND_OFFSET,
|
|
42
|
+
): number {
|
|
43
|
+
if (containerSize <= 0) {
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Only respond to positive displacement (swipe right)
|
|
48
|
+
const clampedDisplacement = Math.max(0, displacement);
|
|
49
|
+
|
|
50
|
+
// Calculate progress (0 to 1)
|
|
51
|
+
const progress = Math.min(clampedDisplacement / containerSize, 1);
|
|
52
|
+
|
|
53
|
+
// Behind panel starts at behindOffset * containerSize and moves to 0
|
|
54
|
+
// Parallax: moves |behindOffset| * progress * containerSize
|
|
55
|
+
const basePosition = behindOffset * containerSize;
|
|
56
|
+
const parallaxOffset = Math.abs(behindOffset) * progress * containerSize;
|
|
57
|
+
|
|
58
|
+
return basePosition + parallaxOffset;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Compute swipe progress as a ratio (0 to 1).
|
|
63
|
+
*
|
|
64
|
+
* @param displacement - Current swipe displacement in pixels
|
|
65
|
+
* @param containerSize - Container width/height in pixels
|
|
66
|
+
* @returns Progress ratio from 0 to 1
|
|
67
|
+
*/
|
|
68
|
+
export function computeSwipeProgress(displacement: number, containerSize: number): number {
|
|
69
|
+
if (containerSize <= 0) {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const clampedDisplacement = Math.max(0, displacement);
|
|
74
|
+
return Math.min(clampedDisplacement / containerSize, 1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Input for computing swipe visibility.
|
|
79
|
+
*/
|
|
80
|
+
export type ComputeSwipeVisibilityInput = {
|
|
81
|
+
/** Panel depth in the stack */
|
|
82
|
+
depth: number;
|
|
83
|
+
/** Current navigation depth (active panel) */
|
|
84
|
+
navigationDepth: number;
|
|
85
|
+
/** Whether this panel is currently active */
|
|
86
|
+
isActive: boolean;
|
|
87
|
+
/** Whether swipe gesture is active */
|
|
88
|
+
isSwiping: boolean;
|
|
89
|
+
/** Whether snap-back animation is running */
|
|
90
|
+
isAnimating: boolean;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Compute whether a panel should be visible during swipe.
|
|
95
|
+
*
|
|
96
|
+
* During swipe:
|
|
97
|
+
* - Active panel is always visible
|
|
98
|
+
* - Behind panel (depth = navigationDepth - 1) is visible when swiping/animating
|
|
99
|
+
*
|
|
100
|
+
* @returns true if panel should be visible
|
|
101
|
+
*/
|
|
102
|
+
export function computeSwipeVisibility(input: ComputeSwipeVisibilityInput): boolean {
|
|
103
|
+
const { depth, navigationDepth, isActive, isSwiping, isAnimating } = input;
|
|
104
|
+
|
|
105
|
+
// Active panel is always visible
|
|
106
|
+
if (isActive) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Behind panel (one level back) is visible during swipe or animation
|
|
111
|
+
const isBehindPanel = depth === navigationDepth - 1;
|
|
112
|
+
if (isBehindPanel) {
|
|
113
|
+
if (isSwiping) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (isAnimating) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Other panels are hidden during swipe
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Determine the role of a panel during swipe gesture.
|
|
127
|
+
*/
|
|
128
|
+
export type SwipePanelRole = "active" | "behind" | "hidden";
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Determine the role of a panel during swipe.
|
|
132
|
+
*
|
|
133
|
+
* @param depth - Panel depth in the stack
|
|
134
|
+
* @param navigationDepth - Current navigation depth (active panel)
|
|
135
|
+
* @returns Panel role for swipe handling
|
|
136
|
+
*/
|
|
137
|
+
export function determineSwipePanelRole(depth: number, navigationDepth: number): SwipePanelRole {
|
|
138
|
+
if (depth === navigationDepth) {
|
|
139
|
+
return "active";
|
|
140
|
+
}
|
|
141
|
+
if (depth === navigationDepth - 1) {
|
|
142
|
+
return "behind";
|
|
143
|
+
}
|
|
144
|
+
return "hidden";
|
|
145
|
+
}
|