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.
Files changed (463) hide show
  1. package/dist/{FloatingPanelFrame-D9Cp2al1.cjs → FloatingPanelFrame-CEmXDvUA.cjs} +2 -2
  2. package/dist/{FloatingPanelFrame-D9Cp2al1.cjs.map → FloatingPanelFrame-CEmXDvUA.cjs.map} +1 -1
  3. package/dist/{FloatingPanelFrame-lLg-Lpg7.js → FloatingPanelFrame-SgYLc6Ud.js} +11 -11
  4. package/dist/{FloatingPanelFrame-lLg-Lpg7.js.map → FloatingPanelFrame-SgYLc6Ud.js.map} +1 -1
  5. package/dist/FloatingWindow-BpdOpg_L.js +400 -0
  6. package/dist/FloatingWindow-BpdOpg_L.js.map +1 -0
  7. package/dist/FloatingWindow-TCDNY5gE.cjs +2 -0
  8. package/dist/FloatingWindow-TCDNY5gE.cjs.map +1 -0
  9. package/dist/GridLayout-B4VRsC0r.cjs +2 -0
  10. package/dist/GridLayout-B4VRsC0r.cjs.map +1 -0
  11. package/dist/GridLayout-BltqeCPK.js +927 -0
  12. package/dist/GridLayout-BltqeCPK.js.map +1 -0
  13. package/dist/HorizontalDivider-B5Z-KZLk.cjs +2 -0
  14. package/dist/HorizontalDivider-B5Z-KZLk.cjs.map +1 -0
  15. package/dist/HorizontalDivider-WF1k_qND.js +30 -0
  16. package/dist/HorizontalDivider-WF1k_qND.js.map +1 -0
  17. package/dist/PanelSystem-Bs8bQwQF.cjs +3 -0
  18. package/dist/PanelSystem-Bs8bQwQF.cjs.map +1 -0
  19. package/dist/PanelSystem-Dr1TBhxM.js +1946 -0
  20. package/dist/PanelSystem-Dr1TBhxM.js.map +1 -0
  21. package/dist/ResizeHandle-CScipO5l.cjs +2 -0
  22. package/dist/ResizeHandle-CScipO5l.cjs.map +1 -0
  23. package/dist/ResizeHandle-CdA_JYfN.js +120 -0
  24. package/dist/ResizeHandle-CdA_JYfN.js.map +1 -0
  25. package/dist/SwipePivotTabBar-BGO9X94m.js +407 -0
  26. package/dist/SwipePivotTabBar-BGO9X94m.js.map +1 -0
  27. package/dist/SwipePivotTabBar-BrQismcZ.cjs +2 -0
  28. package/dist/SwipePivotTabBar-BrQismcZ.cjs.map +1 -0
  29. package/dist/config.cjs +1 -1
  30. package/dist/config.cjs.map +1 -1
  31. package/dist/config.js +11 -9
  32. package/dist/config.js.map +1 -1
  33. package/dist/constants/styles.d.ts +18 -4
  34. package/dist/floating.cjs +1 -1
  35. package/dist/floating.js +1 -1
  36. package/dist/grid/index.d.ts +58 -0
  37. package/dist/grid.cjs +2 -0
  38. package/dist/grid.cjs.map +1 -0
  39. package/dist/grid.js +13 -0
  40. package/dist/grid.js.map +1 -0
  41. package/dist/hooks/gesture/presets.d.ts +33 -0
  42. package/dist/hooks/gesture/testing/createGestureSimulator.d.ts +110 -0
  43. package/dist/hooks/gesture/thresholdValue.d.ts +44 -0
  44. package/dist/hooks/gesture/types.d.ts +254 -0
  45. package/dist/hooks/gesture/useDirectionalLock.d.ts +20 -0
  46. package/dist/hooks/gesture/useEdgeSwipeInput.d.ts +23 -0
  47. package/dist/hooks/gesture/useNativeGestureGuard.d.ts +23 -0
  48. package/dist/hooks/gesture/usePointerTracking.d.ts +22 -0
  49. package/dist/hooks/gesture/useScrollBoundary.d.ts +23 -0
  50. package/dist/hooks/gesture/useSwipeInput.d.ts +5 -0
  51. package/dist/hooks/gesture/utils.d.ts +40 -0
  52. package/dist/hooks/useAnimatedVisibility.d.ts +58 -0
  53. package/dist/hooks/useAnimationFrame.d.ts +84 -0
  54. package/dist/hooks/useSnapAnimation.d.ts +54 -0
  55. package/dist/hooks/useSwipeContentTransform.d.ts +79 -0
  56. package/dist/index.cjs +1 -2
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.ts +0 -1
  59. package/dist/index.js +25 -2006
  60. package/dist/index.js.map +1 -1
  61. package/dist/modules/pivot/PivotContent.d.ts +1 -1
  62. package/dist/modules/pivot/SwipePivotContent.d.ts +39 -0
  63. package/dist/modules/pivot/SwipePivotContent.debug.tmp.d.ts +25 -0
  64. package/dist/modules/pivot/SwipePivotContent.test.d.ts +1 -0
  65. package/dist/modules/pivot/SwipePivotTabBar.d.ts +89 -0
  66. package/dist/modules/pivot/index.d.ts +3 -0
  67. package/dist/modules/pivot/scaleInputState.d.ts +37 -0
  68. package/dist/modules/pivot/types.d.ts +67 -2
  69. package/dist/modules/pivot/usePivotSwipeInput.d.ts +68 -0
  70. package/dist/modules/stack/StackContent.d.ts +15 -0
  71. package/dist/modules/stack/SwipeStackContent.d.ts +63 -0
  72. package/dist/modules/stack/SwipeStackOutlet.d.ts +80 -0
  73. package/dist/modules/stack/computeStackContentState.d.ts +99 -0
  74. package/dist/modules/stack/computeSwipeStackTransform.d.ts +76 -0
  75. package/dist/modules/stack/types.d.ts +194 -0
  76. package/dist/modules/stack/useStackAnimationState.d.ts +32 -0
  77. package/dist/modules/stack/useStackNavigation.d.ts +23 -0
  78. package/dist/modules/stack/useStackSwipeInput.d.ts +27 -0
  79. package/dist/panels/index.d.ts +67 -0
  80. package/dist/panels.cjs +2 -0
  81. package/dist/panels.cjs.map +1 -0
  82. package/dist/panels.js +28 -0
  83. package/dist/panels.js.map +1 -0
  84. package/dist/pivot/index.d.ts +3 -0
  85. package/dist/pivot.cjs +1 -1
  86. package/dist/pivot.cjs.map +1 -1
  87. package/dist/pivot.js +20 -2
  88. package/dist/pivot.js.map +1 -1
  89. package/dist/resizer/index.d.ts +57 -0
  90. package/dist/resizer.cjs +2 -0
  91. package/dist/resizer.cjs.map +1 -0
  92. package/dist/resizer.js +8 -0
  93. package/dist/resizer.js.map +1 -0
  94. package/dist/stack/index.d.ts +72 -0
  95. package/dist/stack.cjs +2 -0
  96. package/dist/stack.cjs.map +1 -0
  97. package/dist/stack.js +980 -0
  98. package/dist/stack.js.map +1 -0
  99. package/dist/sticky-header/StickyArea.d.ts +38 -0
  100. package/dist/sticky-header/index.d.ts +4 -4
  101. package/dist/sticky-header/types.d.ts +35 -22
  102. package/dist/sticky-header.cjs +1 -1
  103. package/dist/sticky-header.cjs.map +1 -1
  104. package/dist/sticky-header.js +65 -174
  105. package/dist/sticky-header.js.map +1 -1
  106. package/dist/styles-DPPuJ0sf.js +57 -0
  107. package/dist/styles-DPPuJ0sf.js.map +1 -0
  108. package/dist/styles-qf6ptVLD.cjs +2 -0
  109. package/dist/styles-qf6ptVLD.cjs.map +1 -0
  110. package/dist/useContentCache-CO3LYNmz.js +24 -0
  111. package/dist/useContentCache-CO3LYNmz.js.map +1 -0
  112. package/dist/useContentCache-DqXtLrLs.cjs +2 -0
  113. package/dist/useContentCache-DqXtLrLs.cjs.map +1 -0
  114. package/dist/useDocumentPointerEvents-CKdhGXd0.js +46 -0
  115. package/dist/useDocumentPointerEvents-CKdhGXd0.js.map +1 -0
  116. package/dist/useDocumentPointerEvents-ChqrKXDk.cjs +2 -0
  117. package/dist/useDocumentPointerEvents-ChqrKXDk.cjs.map +1 -0
  118. package/dist/useEffectEvent-Dp7HLCf0.js +13 -0
  119. package/dist/useEffectEvent-Dp7HLCf0.js.map +1 -0
  120. package/dist/useEffectEvent-huSsGUnl.cjs +2 -0
  121. package/dist/useEffectEvent-huSsGUnl.cjs.map +1 -0
  122. package/dist/useFloatingState-C4kRaW_R.cjs +2 -0
  123. package/dist/useFloatingState-C4kRaW_R.cjs.map +1 -0
  124. package/dist/useFloatingState-tEfA_wbc.js +74 -0
  125. package/dist/useFloatingState-tEfA_wbc.js.map +1 -0
  126. package/dist/window/index.d.ts +61 -0
  127. package/dist/window.cjs +2 -0
  128. package/dist/window.cjs.map +1 -0
  129. package/dist/window.js +149 -0
  130. package/dist/window.js.map +1 -0
  131. package/docs/design-tokens.md +405 -0
  132. package/package.json +29 -4
  133. package/src/PanelSystemContext.tsx +88 -0
  134. package/src/components/grid/GridLayerList.tsx +172 -0
  135. package/src/components/grid/GridLayerResizeHandles.tsx +145 -0
  136. package/src/components/grid/GridLayout.spec.tsx +743 -0
  137. package/src/components/grid/GridLayout.tsx +130 -0
  138. package/src/components/grid/GridTrackResizeHandle.tsx +87 -0
  139. package/src/components/paneling/FloatingPanelFrame.tsx +203 -0
  140. package/src/components/panels/DropSuggestOverlay.tsx +131 -0
  141. package/src/components/panels/PanelGroupView.tsx +112 -0
  142. package/src/components/pivot/PivotLayer.tsx +27 -0
  143. package/src/components/resizer/HorizontalDivider.tsx +52 -0
  144. package/src/components/resizer/ResizeHandle.tsx +118 -0
  145. package/src/components/tabs/TabBar.tsx +223 -0
  146. package/src/components/tabs/TabBarTab.tsx +133 -0
  147. package/src/components/tabs/TabDragOverlay.tsx +92 -0
  148. package/src/components/window/DialogOverlay.tsx +180 -0
  149. package/src/components/window/Drawer.tsx +282 -0
  150. package/src/components/window/DrawerLayers.tsx +58 -0
  151. package/src/components/window/FloatingWindow.tsx +95 -0
  152. package/src/components/window/PopupLayerPortal.tsx +218 -0
  153. package/src/config/PanelContentDeclaration.tsx +427 -0
  154. package/src/config/index.tsx +52 -0
  155. package/src/config/panelJsx.spec.tsx +54 -0
  156. package/src/config/panelJsxConfig.spec.tsx +54 -0
  157. package/src/config/panelJsxDrawer.spec.tsx +33 -0
  158. package/src/config/panelRouter.spec.ts +68 -0
  159. package/src/config/panelRouter.tsx +155 -0
  160. package/src/constants/styles.ts +261 -0
  161. package/src/demo/Layout.module.css +258 -0
  162. package/src/demo/Layout.tsx +176 -0
  163. package/src/demo/components/CodeBlock.module.css +54 -0
  164. package/src/demo/components/CodeBlock.tsx +34 -0
  165. package/src/demo/components/CodePreview.module.css +37 -0
  166. package/src/demo/components/CodePreview.tsx +31 -0
  167. package/src/demo/components/DataPreview.module.css +177 -0
  168. package/src/demo/components/DataPreview.tsx +115 -0
  169. package/src/demo/components/Story.module.css +68 -0
  170. package/src/demo/components/Story.tsx +54 -0
  171. package/src/demo/components/layout/CodePanel.module.css +183 -0
  172. package/src/demo/components/layout/CodePanel.tsx +149 -0
  173. package/src/demo/components/layout/DemoPage.module.css +60 -0
  174. package/src/demo/components/layout/DemoPage.tsx +56 -0
  175. package/src/demo/components/layout/SingleSamplePage.module.css +11 -0
  176. package/src/demo/components/layout/SingleSamplePage.tsx +35 -0
  177. package/src/demo/components/layout/SplitDemoLayout.module.css +107 -0
  178. package/src/demo/components/layout/SplitDemoLayout.tsx +218 -0
  179. package/src/demo/components/layout/index.ts +11 -0
  180. package/src/demo/components/tab-styles/ChromeTabBar.module.css +75 -0
  181. package/src/demo/components/tab-styles/ChromeTabBar.tsx +111 -0
  182. package/src/demo/components/tab-styles/GitHubTabBar.module.css +81 -0
  183. package/src/demo/components/tab-styles/GitHubTabBar.tsx +109 -0
  184. package/src/demo/components/tab-styles/VSCodeTabBar.module.css +78 -0
  185. package/src/demo/components/tab-styles/VSCodeTabBar.tsx +109 -0
  186. package/src/demo/components/tab-styles/index.ts +6 -0
  187. package/src/demo/components/ui/DemoButton.module.css +63 -0
  188. package/src/demo/components/ui/DemoButton.tsx +32 -0
  189. package/src/demo/components/ui/DemoCard.module.css +15 -0
  190. package/src/demo/components/ui/DemoCard.tsx +30 -0
  191. package/src/demo/components/ui/DemoContainer.module.css +17 -0
  192. package/src/demo/components/ui/DemoContainer.tsx +30 -0
  193. package/src/demo/components/ui/DemoPanel.module.css +23 -0
  194. package/src/demo/components/ui/DemoPanel.tsx +33 -0
  195. package/src/demo/components/ui/PanelText.module.css +18 -0
  196. package/src/demo/components/ui/PanelText.tsx +29 -0
  197. package/src/demo/components/ui/PanelTitle.module.css +18 -0
  198. package/src/demo/components/ui/PanelTitle.tsx +31 -0
  199. package/src/demo/contexts/TabbarDemoConfig.tsx +218 -0
  200. package/src/demo/demo.css +172 -0
  201. package/src/demo/hooks/useMedia.ts +41 -0
  202. package/src/demo/hooks/useShikiHighlight.ts +55 -0
  203. package/src/demo/index.tsx +293 -0
  204. package/src/demo/pages/Drawer/animations/index.tsx +22 -0
  205. package/src/demo/pages/Drawer/basics/index.tsx +17 -0
  206. package/src/demo/pages/Drawer/components/DrawerAnimations.module.css +125 -0
  207. package/src/demo/pages/Drawer/components/DrawerAnimations.tsx +118 -0
  208. package/src/demo/pages/Drawer/components/DrawerBasics.module.css +55 -0
  209. package/src/demo/pages/Drawer/components/DrawerBasics.tsx +76 -0
  210. package/src/demo/pages/Drawer/components/DrawerMenuLayout.module.css +332 -0
  211. package/src/demo/pages/Drawer/components/DrawerMenuLayout.tsx +199 -0
  212. package/src/demo/pages/Drawer/menu/index.tsx +17 -0
  213. package/src/demo/pages/FloatingPanelFrame/ResizableFloatingPanelsPreview.module.css +163 -0
  214. package/src/demo/pages/FloatingPanelFrame/ResizableFloatingPanelsPreview.tsx +234 -0
  215. package/src/demo/pages/FloatingPanelFrame/basic/index.tsx +17 -0
  216. package/src/demo/pages/FloatingPanelFrame/complex/index.tsx +26 -0
  217. package/src/demo/pages/FloatingPanelFrame/components/BasicPanel.module.css +16 -0
  218. package/src/demo/pages/FloatingPanelFrame/components/BasicPanel.tsx +24 -0
  219. package/src/demo/pages/FloatingPanelFrame/components/ComplexPanel.module.css +54 -0
  220. package/src/demo/pages/FloatingPanelFrame/components/ComplexPanel.tsx +67 -0
  221. package/src/demo/pages/FloatingPanelFrame/components/PanelWithControls.module.css +21 -0
  222. package/src/demo/pages/FloatingPanelFrame/components/PanelWithControls.tsx +41 -0
  223. package/src/demo/pages/FloatingPanelFrame/components/PanelWithMeta.module.css +5 -0
  224. package/src/demo/pages/FloatingPanelFrame/components/PanelWithMeta.tsx +43 -0
  225. package/src/demo/pages/FloatingPanelFrame/components/ScrollablePanel.module.css +11 -0
  226. package/src/demo/pages/FloatingPanelFrame/components/ScrollablePanel.tsx +42 -0
  227. package/src/demo/pages/FloatingPanelFrame/index.tsx +80 -0
  228. package/src/demo/pages/FloatingPanelFrame/scrollable/index.tsx +30 -0
  229. package/src/demo/pages/FloatingPanelFrame/with-controls/index.tsx +30 -0
  230. package/src/demo/pages/FloatingPanelFrame/with-meta/index.tsx +17 -0
  231. package/src/demo/pages/HorizontalDivider/components/PanelsWithRichContent.module.css +112 -0
  232. package/src/demo/pages/HorizontalDivider/components/PanelsWithRichContent.tsx +56 -0
  233. package/src/demo/pages/HorizontalDivider/components/SimpleResizablePanels.module.css +46 -0
  234. package/src/demo/pages/HorizontalDivider/components/SimpleResizablePanels.tsx +29 -0
  235. package/src/demo/pages/HorizontalDivider/components/ThreePanelLayout.module.css +54 -0
  236. package/src/demo/pages/HorizontalDivider/components/ThreePanelLayout.tsx +30 -0
  237. package/src/demo/pages/HorizontalDivider/index.module.css +14 -0
  238. package/src/demo/pages/HorizontalDivider/index.tsx +64 -0
  239. package/src/demo/pages/HorizontalDivider/panels-with-rich-content/index.tsx +21 -0
  240. package/src/demo/pages/HorizontalDivider/simple-resizable-panels/index.tsx +21 -0
  241. package/src/demo/pages/HorizontalDivider/three-panel-layout/index.tsx +21 -0
  242. package/src/demo/pages/PanelLayout/PanelLayoutDemo.module.css +174 -0
  243. package/src/demo/pages/PanelLayout/PanelLayoutDemo.tsx +248 -0
  244. package/src/demo/pages/PanelLayout/components/DashboardLayout.module.css +115 -0
  245. package/src/demo/pages/PanelLayout/components/DashboardLayout.tsx +124 -0
  246. package/src/demo/pages/PanelLayout/components/DraggableOverlays.module.css +101 -0
  247. package/src/demo/pages/PanelLayout/components/DraggableOverlays.tsx +122 -0
  248. package/src/demo/pages/PanelLayout/components/IDELayout.module.css +104 -0
  249. package/src/demo/pages/PanelLayout/components/IDELayout.tsx +143 -0
  250. package/src/demo/pages/PanelLayout/components/SimpleGrid.module.css +19 -0
  251. package/src/demo/pages/PanelLayout/components/SimpleGrid.tsx +62 -0
  252. package/src/demo/pages/PanelLayout/dashboard/index.tsx +22 -0
  253. package/src/demo/pages/PanelLayout/draggable-overlays/index.tsx +22 -0
  254. package/src/demo/pages/PanelLayout/ide-layout/index.tsx +22 -0
  255. package/src/demo/pages/PanelLayout/index.tsx +94 -0
  256. package/src/demo/pages/PanelLayout/simple-grid/index.tsx +22 -0
  257. package/src/demo/pages/PanelSystem/PanelSystemPreview.module.css +20 -0
  258. package/src/demo/pages/PanelSystem/PanelSystemPreview.tsx +101 -0
  259. package/src/demo/pages/PanelSystem/preview/index.tsx +18 -0
  260. package/src/demo/pages/PanelSystem/tabbar/index.tsx +129 -0
  261. package/src/demo/pages/Pivot/basics/index.tsx +17 -0
  262. package/src/demo/pages/Pivot/components/Pivot.module.css +278 -0
  263. package/src/demo/pages/Pivot/components/PivotBasics.tsx +103 -0
  264. package/src/demo/pages/Pivot/components/PivotSidebar.tsx +168 -0
  265. package/src/demo/pages/Pivot/components/PivotTabs.tsx +129 -0
  266. package/src/demo/pages/Pivot/components/PivotTransitions.tsx +120 -0
  267. package/src/demo/pages/Pivot/components/SwipePivot.module.css +114 -0
  268. package/src/demo/pages/Pivot/components/SwipePivot.tsx +193 -0
  269. package/src/demo/pages/Pivot/components/SwipeTabsPivot.module.css +203 -0
  270. package/src/demo/pages/Pivot/components/SwipeTabsPivot.tsx +289 -0
  271. package/src/demo/pages/Pivot/sidebar/index.tsx +17 -0
  272. package/src/demo/pages/Pivot/swipe/index.tsx +16 -0
  273. package/src/demo/pages/Pivot/swipe-debug/index.tsx +287 -0
  274. package/src/demo/pages/Pivot/swipe-tabs/index.tsx +15 -0
  275. package/src/demo/pages/Pivot/tabs/index.tsx +17 -0
  276. package/src/demo/pages/Pivot/transitions/index.tsx +17 -0
  277. package/src/demo/pages/ResizeHandle/both-directions/index.tsx +17 -0
  278. package/src/demo/pages/ResizeHandle/components/BothDirectionsDemo.module.css +72 -0
  279. package/src/demo/pages/ResizeHandle/components/BothDirectionsDemo.tsx +41 -0
  280. package/src/demo/pages/ResizeHandle/components/HorizontalResizeDemo.module.css +61 -0
  281. package/src/demo/pages/ResizeHandle/components/HorizontalResizeDemo.tsx +33 -0
  282. package/src/demo/pages/ResizeHandle/components/NestedPanelsDemo.module.css +83 -0
  283. package/src/demo/pages/ResizeHandle/components/NestedPanelsDemo.tsx +53 -0
  284. package/src/demo/pages/ResizeHandle/components/VerticalResizeDemo.module.css +68 -0
  285. package/src/demo/pages/ResizeHandle/components/VerticalResizeDemo.tsx +33 -0
  286. package/src/demo/pages/ResizeHandle/horizontal/index.tsx +17 -0
  287. package/src/demo/pages/ResizeHandle/index.module.css +11 -0
  288. package/src/demo/pages/ResizeHandle/index.tsx +71 -0
  289. package/src/demo/pages/ResizeHandle/nested-panels/index.tsx +17 -0
  290. package/src/demo/pages/ResizeHandle/vertical/index.tsx +17 -0
  291. package/src/demo/pages/ResponsiveLayout/adaptive-workspace/index.tsx +22 -0
  292. package/src/demo/pages/ResponsiveLayout/components/ResponsiveWorkspace.module.css +423 -0
  293. package/src/demo/pages/ResponsiveLayout/components/ResponsiveWorkspace.tsx +398 -0
  294. package/src/demo/pages/Stack/basics/index.tsx +22 -0
  295. package/src/demo/pages/Stack/components/Stack.module.css +234 -0
  296. package/src/demo/pages/Stack/components/StackBasics.tsx +217 -0
  297. package/src/demo/pages/Stack/components/StackTablet.module.css +299 -0
  298. package/src/demo/pages/Stack/components/StackTablet.tsx +401 -0
  299. package/src/demo/pages/Stack/tablet/index.tsx +22 -0
  300. package/src/demo/pages/StickyHeader/basics/index.tsx +17 -0
  301. package/src/demo/pages/StickyHeader/components/StickyHeader.module.css +219 -0
  302. package/src/demo/pages/StickyHeader/components/StickyHeaderBasics.tsx +103 -0
  303. package/src/demo/routes.tsx +193 -0
  304. package/src/demo/styles/animations.css +68 -0
  305. package/src/demo/styles/stack-themes.css +35 -0
  306. package/src/demo/utils/createPanelView.tsx +58 -0
  307. package/src/floating/index.ts +24 -0
  308. package/src/grid/index.ts +75 -0
  309. package/src/hooks/ContentCacheContext.tsx +87 -0
  310. package/src/hooks/gesture/presets.spec.ts +86 -0
  311. package/src/hooks/gesture/presets.ts +95 -0
  312. package/src/hooks/gesture/testing/createGestureSimulator.spec.ts +237 -0
  313. package/src/hooks/gesture/testing/createGestureSimulator.ts +310 -0
  314. package/src/hooks/gesture/thresholdValue.spec.ts +103 -0
  315. package/src/hooks/gesture/thresholdValue.ts +77 -0
  316. package/src/hooks/gesture/types.ts +290 -0
  317. package/src/hooks/gesture/useDirectionalLock.spec.ts +271 -0
  318. package/src/hooks/gesture/useDirectionalLock.ts +115 -0
  319. package/src/hooks/gesture/useEdgeSwipeInput.spec.ts +454 -0
  320. package/src/hooks/gesture/useEdgeSwipeInput.ts +131 -0
  321. package/src/hooks/gesture/useNativeGestureGuard.spec.ts +413 -0
  322. package/src/hooks/gesture/useNativeGestureGuard.ts +133 -0
  323. package/src/hooks/gesture/usePointerTracking.spec.ts +364 -0
  324. package/src/hooks/gesture/usePointerTracking.ts +134 -0
  325. package/src/hooks/gesture/useScrollBoundary.spec.ts +249 -0
  326. package/src/hooks/gesture/useScrollBoundary.ts +113 -0
  327. package/src/hooks/gesture/useSwipeInput.spec.ts +592 -0
  328. package/src/hooks/gesture/useSwipeInput.ts +310 -0
  329. package/src/hooks/gesture/utils.spec.ts +152 -0
  330. package/src/hooks/gesture/utils.ts +87 -0
  331. package/src/hooks/useAnimatedVisibility.spec.ts +257 -0
  332. package/src/hooks/useAnimatedVisibility.ts +146 -0
  333. package/src/hooks/useAnimationFrame.ts +200 -0
  334. package/src/hooks/useCSSMatrix.spec.ts +214 -0
  335. package/src/hooks/useCSSMatrix.ts +262 -0
  336. package/src/hooks/useClonedElementPreview.ts +28 -0
  337. package/src/hooks/useContainerScroll.ts +78 -0
  338. package/src/hooks/useContentCache.spec.tsx +232 -0
  339. package/src/hooks/useContentCache.tsx +127 -0
  340. package/src/hooks/useDocumentPointerEvents.ts +137 -0
  341. package/src/hooks/useDocumentScroll.ts +41 -0
  342. package/src/hooks/useEffectEvent.ts +40 -0
  343. package/src/hooks/useElementComponentWrapper.tsx +63 -0
  344. package/src/hooks/useIntersectionObserver.tsx +125 -0
  345. package/src/hooks/useIsomorphicLayoutEffect.ts +29 -0
  346. package/src/hooks/useResizeObserver.tsx +81 -0
  347. package/src/hooks/useScrollContainer.ts +79 -0
  348. package/src/hooks/useSnapAnimation.ts +128 -0
  349. package/src/hooks/useSwipeContentTransform.spec.ts +133 -0
  350. package/src/hooks/useSwipeContentTransform.ts +235 -0
  351. package/src/hooks/useTransitionState.ts +95 -0
  352. package/src/index.tsx +88 -0
  353. package/src/modules/grid/GridLayoutContext.tsx +57 -0
  354. package/src/modules/grid/LayerInstanceContext.tsx +56 -0
  355. package/src/modules/grid/resizeHandles.ts +157 -0
  356. package/src/modules/grid/trackUtils.ts +146 -0
  357. package/src/modules/grid/useGridPlacements.ts +143 -0
  358. package/src/modules/grid/useGridTracks.ts +156 -0
  359. package/src/modules/grid/useLayerDragHandle.ts +16 -0
  360. package/src/modules/grid/useLayerInteractions.tsx +850 -0
  361. package/src/modules/keybindings/KeybindingsProvider.tsx +111 -0
  362. package/src/modules/panels/dom/DomRegistry.tsx +94 -0
  363. package/src/modules/panels/index.ts +45 -0
  364. package/src/modules/panels/interactions/InteractionsContext.test.tsx +330 -0
  365. package/src/modules/panels/interactions/InteractionsContext.tsx +394 -0
  366. package/src/modules/panels/interactions/dnd.ts +28 -0
  367. package/src/modules/panels/keybindings/KeybindingsInstaller.tsx +15 -0
  368. package/src/modules/panels/layout/adapter.ts +124 -0
  369. package/src/modules/panels/rendering/ContentRegistry.spec.tsx +304 -0
  370. package/src/modules/panels/rendering/ContentRegistry.tsx +205 -0
  371. package/src/modules/panels/rendering/GroupContainer.tsx +65 -0
  372. package/src/modules/panels/rendering/RenderBridge.tsx +115 -0
  373. package/src/modules/panels/rendering/RenderContext.tsx +31 -0
  374. package/src/modules/panels/state/PanelSplitHandles.tsx +147 -0
  375. package/src/modules/panels/state/PanelSystemContext.splitLimits.spec.tsx +50 -0
  376. package/src/modules/panels/state/PanelSystemContext.tsx +289 -0
  377. package/src/modules/panels/state/StateContext.tsx +12 -0
  378. package/src/modules/panels/state/cleanup.ts +37 -0
  379. package/src/modules/panels/state/commands.ts +53 -0
  380. package/src/modules/panels/state/focus/Context.tsx +25 -0
  381. package/src/modules/panels/state/focus/logic.ts +57 -0
  382. package/src/modules/panels/state/groups/Context.tsx +25 -0
  383. package/src/modules/panels/state/groups/logic.ts +105 -0
  384. package/src/modules/panels/state/splitLimits.spec.ts +46 -0
  385. package/src/modules/panels/state/splitLimits.ts +90 -0
  386. package/src/modules/panels/state/state.spec.ts +49 -0
  387. package/src/modules/panels/state/tree/Context.tsx +24 -0
  388. package/src/modules/panels/state/tree/logic.spec.ts +34 -0
  389. package/src/modules/panels/state/tree/logic.ts +138 -0
  390. package/src/modules/panels/state/types.ts +142 -0
  391. package/src/modules/panels/system/PanelSystem.empty-tabbar.spec.tsx +53 -0
  392. package/src/modules/panels/system/PanelSystem.tab-click-activates.spec.tsx +44 -0
  393. package/src/modules/panels/system/PanelSystem.tab-reorder.spec.tsx +64 -0
  394. package/src/modules/panels/system/PanelSystem.tabs-no-dup.spec.tsx +57 -0
  395. package/src/modules/panels/system/PanelSystem.tsx +206 -0
  396. package/src/modules/pivot/PivotContent.spec.tsx +179 -0
  397. package/src/modules/pivot/PivotContent.tsx +77 -0
  398. package/src/modules/pivot/SwipePivotContent.debug.tmp.tsx +237 -0
  399. package/src/modules/pivot/SwipePivotContent.position.spec.tsx +167 -0
  400. package/src/modules/pivot/SwipePivotContent.spec.tsx +464 -0
  401. package/src/modules/pivot/SwipePivotContent.test.tsx +502 -0
  402. package/src/modules/pivot/SwipePivotContent.tsx +197 -0
  403. package/src/modules/pivot/SwipePivotTabBar.spec.tsx +865 -0
  404. package/src/modules/pivot/SwipePivotTabBar.tsx +523 -0
  405. package/src/modules/pivot/index.ts +8 -0
  406. package/src/modules/pivot/scaleInputState.spec.ts +210 -0
  407. package/src/modules/pivot/scaleInputState.ts +66 -0
  408. package/src/modules/pivot/types.ts +139 -0
  409. package/src/modules/pivot/usePivot.spec.ts +621 -0
  410. package/src/modules/pivot/usePivot.spec.tsx +186 -0
  411. package/src/modules/pivot/usePivot.tsx +345 -0
  412. package/src/modules/pivot/usePivotSwipeInput.spec.ts +649 -0
  413. package/src/modules/pivot/usePivotSwipeInput.ts +136 -0
  414. package/src/modules/resizer/useResizeDrag.ts +94 -0
  415. package/src/modules/stack/StackContent.spec.tsx +264 -0
  416. package/src/modules/stack/StackContent.tsx +111 -0
  417. package/src/modules/stack/SwipeStackContent.spec.tsx +1277 -0
  418. package/src/modules/stack/SwipeStackContent.tsx +356 -0
  419. package/src/modules/stack/SwipeStackOutlet.spec.tsx +252 -0
  420. package/src/modules/stack/SwipeStackOutlet.tsx +221 -0
  421. package/src/modules/stack/computeStackContentState.spec.ts +281 -0
  422. package/src/modules/stack/computeStackContentState.ts +304 -0
  423. package/src/modules/stack/computeSwipeStackTransform.spec.ts +186 -0
  424. package/src/modules/stack/computeSwipeStackTransform.ts +145 -0
  425. package/src/modules/stack/types.ts +226 -0
  426. package/src/modules/stack/useStackAnimationState.spec.ts +186 -0
  427. package/src/modules/stack/useStackAnimationState.ts +138 -0
  428. package/src/modules/stack/useStackNavigation.spec.ts +477 -0
  429. package/src/modules/stack/useStackNavigation.tsx +336 -0
  430. package/src/modules/stack/useStackSwipeInput.spec.ts +276 -0
  431. package/src/modules/stack/useStackSwipeInput.ts +139 -0
  432. package/src/modules/window/useDrawerState.ts +81 -0
  433. package/src/modules/window/useFloatingState.spec.ts +252 -0
  434. package/src/modules/window/useFloatingState.ts +141 -0
  435. package/src/panels/index.ts +119 -0
  436. package/src/pivot/index.ts +19 -0
  437. package/src/resizer/index.ts +68 -0
  438. package/src/stack/index.ts +91 -0
  439. package/src/sticky-header/StickyArea.tsx +221 -0
  440. package/src/sticky-header/index.ts +18 -0
  441. package/src/sticky-header/types.ts +68 -0
  442. package/src/types.ts +323 -0
  443. package/src/utils/CSSMatrix.ts +321 -0
  444. package/src/utils/css.ts +65 -0
  445. package/src/utils/dialogUtils.ts +43 -0
  446. package/src/utils/math.ts +18 -0
  447. package/src/utils/polyfills/createDialogPolyfill.ts +18 -0
  448. package/src/utils/typedActions.ts +103 -0
  449. package/src/vite-env.d.ts +6 -0
  450. package/src/window/index.ts +67 -0
  451. package/dist/GridLayout-BQQ63eA1.cjs +0 -2
  452. package/dist/GridLayout-BQQ63eA1.cjs.map +0 -1
  453. package/dist/GridLayout-CJTKq7Mp.js +0 -1465
  454. package/dist/GridLayout-CJTKq7Mp.js.map +0 -1
  455. package/dist/sticky-header/StickyHeader.d.ts +0 -53
  456. package/dist/styles-CA2_zLZt.js +0 -52
  457. package/dist/styles-CA2_zLZt.js.map +0 -1
  458. package/dist/styles-PsqGOEJP.cjs +0 -2
  459. package/dist/styles-PsqGOEJP.cjs.map +0 -1
  460. package/dist/usePivot-7ctin_P_.cjs +0 -2
  461. package/dist/usePivot-7ctin_P_.cjs.map +0 -1
  462. package/dist/usePivot-CgQxB8rc.js +0 -124
  463. package/dist/usePivot-CgQxB8rc.js.map +0 -1
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @file Panels entry point - VSCode-like panel system
3
+ * @packageDocumentation
4
+ *
5
+ * This is a subpath export entry point for `react-panel-layout/panels`.
6
+ *
7
+ * ## Overview
8
+ * Panels provides a VSCode-like panel system with tabbed groups, drag-and-drop
9
+ * tab reordering, split views, and keyboard navigation. Supports both controlled
10
+ * and uncontrolled state management.
11
+ *
12
+ * ## Installation
13
+ * ```ts
14
+ * import { PanelSystem, buildInitialState, usePanelSystem } from "react-panel-layout/panels";
15
+ * ```
16
+ *
17
+ * ## Basic Usage
18
+ * ```tsx
19
+ * const tabs = [
20
+ * { id: 'file1', title: 'index.ts', render: () => <Editor file="index.ts" /> },
21
+ * { id: 'file2', title: 'app.tsx', render: () => <Editor file="app.tsx" /> },
22
+ * ];
23
+ *
24
+ * function App() {
25
+ * const initialState = buildInitialState(tabs);
26
+ * let groupCounter = 1;
27
+ *
28
+ * return (
29
+ * <PanelSystem
30
+ * initialState={initialState}
31
+ * createGroupId={() => `g_${++groupCounter}`}
32
+ * layoutMode="grid"
33
+ * gridTracksInteractive={true}
34
+ * dragThresholdPx={5}
35
+ * />
36
+ * );
37
+ * }
38
+ * ```
39
+ *
40
+ * ## Controlled State
41
+ * ```tsx
42
+ * const [state, setState] = useState(() => buildInitialState(tabs));
43
+ *
44
+ * <PanelSystem
45
+ * initialState={state}
46
+ * state={state}
47
+ * onStateChange={setState}
48
+ * // ...
49
+ * />
50
+ * ```
51
+ *
52
+ * ## Using Context
53
+ * ```tsx
54
+ * function TabActions() {
55
+ * const { actions } = usePanelSystem();
56
+ * return <button onClick={() => actions.splitFocused('vertical')}>Split</button>;
57
+ * }
58
+ * ```
59
+ */
60
+
61
+ // Components
62
+ export { PanelSystem } from "../modules/panels/system/PanelSystem.js";
63
+ export { PanelGroupView } from "../components/panels/PanelGroupView.js";
64
+ export { DropSuggestOverlay } from "../components/panels/DropSuggestOverlay.js";
65
+
66
+ // Context
67
+ export {
68
+ PanelSystemProvider,
69
+ usePanelSystem,
70
+ } from "../modules/panels/state/PanelSystemContext.js";
71
+
72
+ // State operations
73
+ export {
74
+ collectGroupsInOrder,
75
+ splitLeaf,
76
+ closeLeaf,
77
+ isGroup,
78
+ setSplitRatio,
79
+ createEmptyGroup,
80
+ addTabToGroup,
81
+ removeTabFromGroup,
82
+ moveTab,
83
+ setActiveTab,
84
+ reorderTabWithinGroup,
85
+ addTabToGroupAtIndex,
86
+ setFocusedGroup,
87
+ focusGroupIndex,
88
+ nextGroup,
89
+ prevGroup,
90
+ refreshGroupOrder,
91
+ splitGroup,
92
+ buildInitialState,
93
+ } from "../modules/panels/index.js";
94
+
95
+ // Types
96
+ export type {
97
+ PanelId,
98
+ GroupId,
99
+ SplitDirection,
100
+ TabDefinition,
101
+ GroupModel,
102
+ PanelTree,
103
+ PanelSystemState,
104
+ DropZone,
105
+ DraggingTab,
106
+ PanelCommands,
107
+ PanelSystemProps,
108
+ PanelSplitLimits,
109
+ IdFactory,
110
+ } from "../modules/panels/index.js";
111
+
112
+ export type {
113
+ PanelSystemContextValue,
114
+ PanelSystemProviderProps,
115
+ PanelStateAction,
116
+ PanelStateActions,
117
+ } from "../modules/panels/state/PanelSystemContext.js";
118
+
119
+ export type { PanelGroupViewProps } from "../components/panels/PanelGroupView.js";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @file Pivot entry point - Headless content switching
3
+ *
4
+ * Import via: import { usePivot } from "react-panel-layout/pivot";
5
+ */
6
+
7
+ // Hook
8
+ export { usePivot } from "../modules/pivot";
9
+
10
+ // Components
11
+ export { SwipePivotTabBar } from "../modules/pivot";
12
+
13
+ // Utilities
14
+ export { scaleInputState } from "../modules/pivot";
15
+
16
+ // Types
17
+ export type { PivotItem, UsePivotOptions, UsePivotResult, PivotItemProps } from "../modules/pivot";
18
+ export type { SwipePivotTabBarProps, IndicatorRenderProps } from "../modules/pivot";
19
+ export type { PivotBehavior, PivotBehaviorItem } from "../types";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @file Resizer entry point - Resize handle components and hooks
3
+ * @packageDocumentation
4
+ *
5
+ * This is a subpath export entry point for `react-panel-layout/resizer`.
6
+ *
7
+ * ## Overview
8
+ * Resizer provides draggable resize handles for creating resizable layouts.
9
+ * Includes both ready-to-use components and a low-level hook for custom implementations.
10
+ *
11
+ * ## Installation
12
+ * ```ts
13
+ * import { ResizeHandle, useResizeDrag } from "react-panel-layout/resizer";
14
+ * ```
15
+ *
16
+ * ## Basic Usage with ResizeHandle
17
+ * ```tsx
18
+ * function ResizableLayout() {
19
+ * const [width, setWidth] = useState(300);
20
+ *
21
+ * return (
22
+ * <div style={{ display: 'flex' }}>
23
+ * <div style={{ width }}>Left Panel</div>
24
+ * <ResizeHandle
25
+ * direction="vertical"
26
+ * onResize={(delta) => setWidth((w) => w + delta)}
27
+ * />
28
+ * <div style={{ flex: 1 }}>Right Panel</div>
29
+ * </div>
30
+ * );
31
+ * }
32
+ * ```
33
+ *
34
+ * ## Custom Handle with useResizeDrag
35
+ * ```tsx
36
+ * function CustomHandle({ onResize }) {
37
+ * const { ref, isDragging, onPointerDown } = useResizeDrag({
38
+ * axis: 'x',
39
+ * onResize,
40
+ * });
41
+ *
42
+ * return (
43
+ * <div
44
+ * ref={ref}
45
+ * onPointerDown={onPointerDown}
46
+ * style={{ cursor: 'col-resize', background: isDragging ? 'blue' : 'gray' }}
47
+ * />
48
+ * );
49
+ * }
50
+ * ```
51
+ */
52
+
53
+ // Hooks
54
+ export { useResizeDrag } from "../modules/resizer/useResizeDrag.js";
55
+
56
+ // Components
57
+ export { ResizeHandle } from "../components/resizer/ResizeHandle.js";
58
+ export { HorizontalDivider } from "../components/resizer/HorizontalDivider.js";
59
+
60
+ // Types
61
+ export type {
62
+ ResizeDragAxis,
63
+ UseResizeDragOptions,
64
+ UseResizeDragResult,
65
+ } from "../modules/resizer/useResizeDrag.js";
66
+
67
+ export type { ResizeHandleProps } from "../components/resizer/ResizeHandle.js";
68
+ export type { HorizontalDividerProps } from "../components/resizer/HorizontalDivider.js";
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @file Stack entry point - Hierarchical navigation with swipe support
3
+ * @packageDocumentation
4
+ *
5
+ * This is a subpath export entry point for `react-panel-layout/stack`.
6
+ *
7
+ * ## Overview
8
+ * Stack provides iOS/iPadOS-style hierarchical navigation where panels stack
9
+ * as users drill down into content. Supports swipe-to-go-back gestures.
10
+ *
11
+ * ## Installation
12
+ * ```ts
13
+ * import { useStackNavigation, SwipeStackOutlet } from "react-panel-layout/stack";
14
+ * ```
15
+ *
16
+ * ## Basic Usage
17
+ * ```tsx
18
+ * const panels = [
19
+ * { id: 'list', title: 'Items', content: <ListPage /> },
20
+ * { id: 'detail', title: 'Detail', content: <DetailPage /> },
21
+ * ];
22
+ *
23
+ * function App() {
24
+ * const { push, go, Outlet } = useStackNavigation({
25
+ * panels,
26
+ * displayMode: 'overlay',
27
+ * });
28
+ *
29
+ * return (
30
+ * <div>
31
+ * <button onClick={() => push('detail')}>View Detail</button>
32
+ * <button onClick={() => go(-1)}>Back</button>
33
+ * <Outlet />
34
+ * </div>
35
+ * );
36
+ * }
37
+ * ```
38
+ *
39
+ * ## With Swipe Gestures (SwipeStackContent)
40
+ * ```tsx
41
+ * const containerRef = useRef<HTMLDivElement>(null);
42
+ * const navigation = useStackNavigation({ panels, displayMode: 'overlay' });
43
+ * const swipeInput = useStackSwipeInput({ containerRef, navigation });
44
+ * const { rect } = useResizeObserver(containerRef);
45
+ *
46
+ * return (
47
+ * <div ref={containerRef} {...swipeInput.containerProps}>
48
+ * {panels.map((panel, index) => (
49
+ * <SwipeStackContent
50
+ * key={panel.id}
51
+ * id={panel.id}
52
+ * depth={index}
53
+ * navigationDepth={navigation.state.depth}
54
+ * isActive={navigation.currentPanelId === panel.id}
55
+ * inputState={swipeInput.inputState}
56
+ * containerSize={rect?.width ?? 0}
57
+ * >
58
+ * {panel.content}
59
+ * </SwipeStackContent>
60
+ * ))}
61
+ * </div>
62
+ * );
63
+ * ```
64
+ */
65
+
66
+ // Hooks
67
+ export { useStackNavigation } from "../modules/stack/useStackNavigation.js";
68
+ export { useStackSwipeInput } from "../modules/stack/useStackSwipeInput.js";
69
+
70
+ // Components
71
+ export { StackContent } from "../modules/stack/StackContent.js";
72
+ export { SwipeStackContent } from "../modules/stack/SwipeStackContent.js";
73
+ export { SwipeStackOutlet } from "../modules/stack/SwipeStackOutlet.js";
74
+
75
+ // Types
76
+ export type {
77
+ StackDisplayMode,
78
+ StackTransitionMode,
79
+ StackPanel,
80
+ StackNavigationState,
81
+ StackPanelProps,
82
+ StackBackButtonProps,
83
+ UseStackNavigationOptions,
84
+ UseStackNavigationResult,
85
+ UseStackSwipeInputOptions,
86
+ UseStackSwipeInputResult,
87
+ StackContentProps,
88
+ } from "../modules/stack/types.js";
89
+
90
+ export type { SwipeStackContentProps } from "../modules/stack/SwipeStackContent.js";
91
+ export type { SwipeStackOutletProps } from "../modules/stack/SwipeStackOutlet.js";
@@ -0,0 +1,221 @@
1
+ /**
2
+ * @file StickyArea component for native app-like overscroll experience.
3
+ *
4
+ * Displays cover content that expands during overscroll/bounce,
5
+ * providing a native app-like pull effect commonly seen in iOS apps.
6
+ *
7
+ * Supports both top (header) and bottom (footer) positions.
8
+ * Works with document-level scroll only.
9
+ */
10
+ import * as React from "react";
11
+ import { useIsomorphicLayoutEffect } from "../hooks/useIsomorphicLayoutEffect";
12
+ import type { StickyAreaProps, StickyAreaState } from "./types";
13
+
14
+ /**
15
+ * Get area styles based on position.
16
+ */
17
+ function getAreaStyle(position: "top" | "bottom"): React.CSSProperties {
18
+ return {
19
+ position: "relative",
20
+ paddingTop: position === "top" ? "env(safe-area-inset-top)" : undefined,
21
+ paddingBottom: position === "bottom" ? "env(safe-area-inset-bottom)" : undefined,
22
+ boxSizing: "border-box",
23
+ };
24
+ }
25
+
26
+ const bodyStyle: React.CSSProperties = {
27
+ zIndex: 1,
28
+ };
29
+
30
+ /**
31
+ * Get cover styles based on position.
32
+ * Explicitly disables transitions to prevent jank from inherited CSS.
33
+ */
34
+ function getCoverStyle(position: "top" | "bottom"): React.CSSProperties {
35
+ return {
36
+ opacity: 0,
37
+ zIndex: 0,
38
+ userSelect: "none",
39
+ pointerEvents: "none",
40
+ // Disable transitions to prevent jank - styles are updated via RAF
41
+ transition: "none",
42
+ // Enable GPU acceleration for smoother animations
43
+ willChange: "height, opacity",
44
+ transform: "translateZ(0)",
45
+ position: "fixed",
46
+ top: position === "top" ? 0 : undefined,
47
+ bottom: position === "bottom" ? 0 : undefined,
48
+ left: 0,
49
+ right: 0,
50
+ };
51
+ }
52
+
53
+ const wrapperStyle: React.CSSProperties = {
54
+ position: "relative",
55
+ };
56
+
57
+ /**
58
+ * StickyArea provides a native app-like overscroll experience.
59
+ *
60
+ * When the user overscrolls (pulls beyond the edge), the cover content
61
+ * expands to fill the visible area, similar to native iOS/Android app behavior.
62
+ *
63
+ * Supports both top (header) and bottom (footer) positions.
64
+ * Works with document-level scroll only.
65
+ *
66
+ * @example
67
+ * ```tsx
68
+ * // Header (top) - expands on pull-down
69
+ * <StickyArea position="top" cover={<img src="/hero.jpg" />}>
70
+ * <header><h1>My App</h1></header>
71
+ * </StickyArea>
72
+ *
73
+ * // Footer (bottom) - expands on pull-up
74
+ * <StickyArea position="bottom" cover={<div className="footer-bg" />}>
75
+ * <footer>Footer content</footer>
76
+ * </StickyArea>
77
+ * ```
78
+ */
79
+ export const StickyArea: React.FC<StickyAreaProps> = ({
80
+ position = "top",
81
+ cover,
82
+ children,
83
+ onStateChange,
84
+ }) => {
85
+ const areaRef = React.useRef<HTMLDivElement>(null);
86
+ const coverAreaRef = React.useRef<HTMLDivElement>(null);
87
+
88
+ // State for render function and callback
89
+ const [state, setState] = React.useState<StickyAreaState>({
90
+ isStuck: false,
91
+ scrollOffset: 0,
92
+ });
93
+
94
+ // Update state when values change
95
+ const stateRef = React.useRef(state);
96
+ const updateState = React.useCallback(
97
+ (newState: StickyAreaState) => {
98
+ const prev = stateRef.current;
99
+ if (prev.isStuck !== newState.isStuck || prev.scrollOffset !== newState.scrollOffset) {
100
+ stateRef.current = newState;
101
+ setState(newState);
102
+ onStateChange?.(newState);
103
+ }
104
+ },
105
+ [onStateChange],
106
+ );
107
+
108
+ useIsomorphicLayoutEffect(() => {
109
+ const area = areaRef.current;
110
+ const coverArea = coverAreaRef.current;
111
+ if (!coverArea || !area) {
112
+ return;
113
+ }
114
+
115
+ // eslint-disable-next-line no-restricted-syntax -- Performance: mutable state for RAF loop
116
+ let prevHeight = Number.NaN;
117
+ // eslint-disable-next-line no-restricted-syntax -- Performance: mutable state for RAF loop
118
+ let prevLeft = Number.NaN;
119
+ // eslint-disable-next-line no-restricted-syntax -- Performance: mutable state for RAF loop
120
+ let prevWidth = Number.NaN;
121
+ // eslint-disable-next-line no-restricted-syntax -- Performance: mutable state for RAF loop
122
+ let prevIsStuck = false;
123
+ // eslint-disable-next-line no-restricted-syntax -- Performance: mutable state for RAF loop
124
+ let isFirstRun = true;
125
+
126
+ const loop = () => {
127
+ const liveRect = area.getBoundingClientRect();
128
+ const viewportHeight = window.innerHeight;
129
+
130
+ if (position === "top") {
131
+ // TOP: Cover expands upward during pull-down overscroll
132
+ // liveRect.top > 0 means element moved down (overscroll)
133
+ // liveRect.top < 0 means element scrolled up
134
+ const coverAreaHeight = Math.max(0, liveRect.height + liveRect.top);
135
+
136
+ if (coverAreaHeight !== prevHeight) {
137
+ coverArea.style.opacity = coverAreaHeight > 0 ? "1" : "0";
138
+ coverArea.style.height = `${coverAreaHeight}px`;
139
+ prevHeight = coverAreaHeight;
140
+ }
141
+
142
+ if (liveRect.left !== prevLeft || liveRect.width !== prevWidth) {
143
+ coverArea.style.left = `${liveRect.left}px`;
144
+ coverArea.style.width = `${liveRect.width}px`;
145
+ prevLeft = liveRect.left;
146
+ prevWidth = liveRect.width;
147
+ }
148
+
149
+ const isStuck = liveRect.top < 0;
150
+ const scrollOffset = Math.max(0, -liveRect.top);
151
+
152
+ const shouldUpdateState = isFirstRun ? true : isStuck !== prevIsStuck;
153
+ if (shouldUpdateState) {
154
+ isFirstRun = false;
155
+ prevIsStuck = isStuck;
156
+ updateState({ isStuck, scrollOffset });
157
+ }
158
+ } else {
159
+ // BOTTOM: Cover expands downward during pull-up overscroll
160
+ // liveRect.bottom < viewportHeight means element moved up (overscroll at bottom)
161
+ // liveRect.bottom > viewportHeight means element is below viewport
162
+ const distanceFromBottom = viewportHeight - liveRect.bottom;
163
+ const coverAreaHeight = Math.max(0, liveRect.height + distanceFromBottom);
164
+
165
+ if (coverAreaHeight !== prevHeight) {
166
+ coverArea.style.opacity = coverAreaHeight > 0 ? "1" : "0";
167
+ coverArea.style.height = `${coverAreaHeight}px`;
168
+ prevHeight = coverAreaHeight;
169
+ }
170
+
171
+ if (liveRect.left !== prevLeft || liveRect.width !== prevWidth) {
172
+ coverArea.style.left = `${liveRect.left}px`;
173
+ coverArea.style.width = `${liveRect.width}px`;
174
+ prevLeft = liveRect.left;
175
+ prevWidth = liveRect.width;
176
+ }
177
+
178
+ const isStuck = liveRect.bottom > viewportHeight;
179
+ const scrollOffset = Math.max(0, liveRect.bottom - viewportHeight);
180
+
181
+ const shouldUpdateState = isFirstRun ? true : isStuck !== prevIsStuck;
182
+ if (shouldUpdateState) {
183
+ isFirstRun = false;
184
+ prevIsStuck = isStuck;
185
+ updateState({ isStuck, scrollOffset });
186
+ }
187
+ }
188
+ };
189
+
190
+ // eslint-disable-next-line no-restricted-syntax -- Performance: RAF id needs reassignment
191
+ let id = requestAnimationFrame(function animate() {
192
+ loop();
193
+ id = requestAnimationFrame(animate);
194
+ });
195
+
196
+ return () => {
197
+ cancelAnimationFrame(id);
198
+ };
199
+ }, [position, updateState]);
200
+
201
+ // Render children
202
+ const renderedChildren = typeof children === "function" ? children(state) : children;
203
+
204
+ return (
205
+ <div style={wrapperStyle}>
206
+ <div ref={coverAreaRef} style={getCoverStyle(position)}>
207
+ {cover}
208
+ </div>
209
+ <div ref={areaRef} style={getAreaStyle(position)}>
210
+ <div style={bodyStyle}>{renderedChildren}</div>
211
+ </div>
212
+ </div>
213
+ );
214
+ };
215
+
216
+ StickyArea.displayName = "StickyArea";
217
+
218
+ /**
219
+ * @deprecated Use StickyArea with position="top" instead
220
+ */
221
+ export const StickyHeader = StickyArea;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @file StickyArea entry point - Native app-like overscroll experience
3
+ *
4
+ * Import via: import { StickyArea } from "react-panel-layout/sticky-header";
5
+ */
6
+
7
+ // Components
8
+ export { StickyArea, StickyHeader } from "./StickyArea";
9
+
10
+ // Types
11
+ export type {
12
+ StickyAreaPosition,
13
+ StickyAreaProps,
14
+ StickyAreaState,
15
+ // Backwards compatibility
16
+ StickyHeaderProps,
17
+ StickyHeaderState,
18
+ } from "./types";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @file Type definitions for the StickyArea component.
3
+ *
4
+ * StickyArea provides a native app-like experience for SPAs/PWAs
5
+ * by displaying cover content during overscroll/bounce.
6
+ * Supports both top (header) and bottom (footer) positions.
7
+ * Works with document-level scroll only.
8
+ */
9
+ import type * as React from "react";
10
+
11
+ /**
12
+ * Position of the sticky area.
13
+ * - "top": Header behavior - sticks to top, expands on pull-down overscroll
14
+ * - "bottom": Footer behavior - sticks to bottom, expands on pull-up overscroll
15
+ */
16
+ export type StickyAreaPosition = "top" | "bottom";
17
+
18
+ /**
19
+ * State information exposed by StickyArea.
20
+ */
21
+ export type StickyAreaState = {
22
+ /**
23
+ * Whether the area is stuck at its edge of the viewport.
24
+ * - For "top": True when scrolled past the top edge
25
+ * - For "bottom": True when scrolled past the bottom edge
26
+ */
27
+ isStuck: boolean;
28
+ /**
29
+ * The current scroll offset relative to the area.
30
+ * Positive when the area has scrolled past its edge.
31
+ */
32
+ scrollOffset: number;
33
+ };
34
+
35
+ /**
36
+ * Props for the StickyArea component.
37
+ */
38
+ export type StickyAreaProps = {
39
+ /**
40
+ * Position of the sticky area.
41
+ * - "top": Header behavior (default)
42
+ * - "bottom": Footer behavior
43
+ *
44
+ * @default "top"
45
+ */
46
+ position?: StickyAreaPosition;
47
+ /**
48
+ * Cover content displayed behind the area.
49
+ * This content expands during overscroll/bounce to create
50
+ * a native app-like pull effect.
51
+ */
52
+ cover: React.ReactNode;
53
+ /**
54
+ * Main content that scrolls over the cover.
55
+ * Can be a ReactNode or a render function receiving state.
56
+ */
57
+ children: React.ReactNode | ((state: StickyAreaState) => React.ReactNode);
58
+ /**
59
+ * Callback fired when sticky state changes.
60
+ */
61
+ onStateChange?: (state: StickyAreaState) => void;
62
+ };
63
+
64
+ // Backwards compatibility aliases
65
+ /** @deprecated Use StickyAreaState instead */
66
+ export type StickyHeaderState = StickyAreaState;
67
+ /** @deprecated Use StickyAreaProps instead */
68
+ export type StickyHeaderProps = StickyAreaProps;