react-panel-layout 0.6.0 → 0.7.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 (258) hide show
  1. package/dist/{FloatingPanelFrame-SgYLc6Ud.js → FloatingPanelFrame-3eU9AwPo.js} +2 -2
  2. package/dist/{FloatingPanelFrame-SgYLc6Ud.js.map → FloatingPanelFrame-3eU9AwPo.js.map} +1 -1
  3. package/dist/FloatingWindow-Bw2djgpz.js +1542 -0
  4. package/dist/FloatingWindow-Bw2djgpz.js.map +1 -0
  5. package/dist/FloatingWindow-Cvyokf0m.cjs +2 -0
  6. package/dist/FloatingWindow-Cvyokf0m.cjs.map +1 -0
  7. package/dist/GridLayout-B4aCqSyd.js +947 -0
  8. package/dist/{GridLayout-BltqeCPK.js.map → GridLayout-B4aCqSyd.js.map} +1 -1
  9. package/dist/GridLayout-DNOClFzz.cjs +2 -0
  10. package/dist/{GridLayout-B4VRsC0r.cjs.map → GridLayout-DNOClFzz.cjs.map} +1 -1
  11. package/dist/{HorizontalDivider-WF1k_qND.js → HorizontalDivider-DdxzfV0l.js} +3 -3
  12. package/dist/{HorizontalDivider-WF1k_qND.js.map → HorizontalDivider-DdxzfV0l.js.map} +1 -1
  13. package/dist/{HorizontalDivider-B5Z-KZLk.cjs → HorizontalDivider-_pgV4Mcv.cjs} +2 -2
  14. package/dist/{HorizontalDivider-B5Z-KZLk.cjs.map → HorizontalDivider-_pgV4Mcv.cjs.map} +1 -1
  15. package/dist/PanelSystem-B8Igvnb2.cjs +3 -0
  16. package/dist/PanelSystem-B8Igvnb2.cjs.map +1 -0
  17. package/dist/{PanelSystem-Dr1TBhxM.js → PanelSystem-DDUSFjXD.js} +209 -248
  18. package/dist/PanelSystem-DDUSFjXD.js.map +1 -0
  19. package/dist/ResizeHandle-CBcAS918.cjs +2 -0
  20. package/dist/{ResizeHandle-CScipO5l.cjs.map → ResizeHandle-CBcAS918.cjs.map} +1 -1
  21. package/dist/{ResizeHandle-CdA_JYfN.js → ResizeHandle-CXjc1meV.js} +28 -29
  22. package/dist/{ResizeHandle-CdA_JYfN.js.map → ResizeHandle-CXjc1meV.js.map} +1 -1
  23. package/dist/SwipePivotTabBar-DWrCuwEI.js +411 -0
  24. package/dist/SwipePivotTabBar-DWrCuwEI.js.map +1 -0
  25. package/dist/SwipePivotTabBar-fjjXkpj7.cjs +2 -0
  26. package/dist/SwipePivotTabBar-fjjXkpj7.cjs.map +1 -0
  27. package/dist/components/gesture/SwipeSafeZone.d.ts +40 -0
  28. package/dist/components/window/Drawer.d.ts +4 -1
  29. package/dist/components/window/DrawerLayers.d.ts +1 -1
  30. package/dist/components/window/DrawerRevealContext.d.ts +61 -0
  31. package/dist/components/window/drawerRevealAnimationUtils.d.ts +212 -0
  32. package/dist/components/window/drawerStyles.d.ts +74 -0
  33. package/dist/components/window/drawerSwipeConfig.d.ts +29 -0
  34. package/dist/components/window/useDrawerSwipeTransform.d.ts +29 -0
  35. package/dist/components/window/useDrawerTransform.d.ts +68 -0
  36. package/dist/components/window/useRevealDrawerTransform.d.ts +56 -0
  37. package/dist/config.cjs +1 -1
  38. package/dist/config.cjs.map +1 -1
  39. package/dist/config.js +9 -8
  40. package/dist/config.js.map +1 -1
  41. package/dist/constants/styles.d.ts +17 -0
  42. package/dist/dialog/index.d.ts +69 -0
  43. package/dist/floating.js +1 -1
  44. package/dist/grid.cjs +1 -1
  45. package/dist/grid.js +2 -2
  46. package/dist/hooks/gesture/testing/createGestureSimulator.d.ts +7 -0
  47. package/dist/hooks/gesture/types.d.ts +48 -5
  48. package/dist/hooks/gesture/utils.d.ts +19 -0
  49. package/dist/hooks/useAnimationFrame.d.ts +2 -0
  50. package/dist/hooks/useOperationContinuity.d.ts +64 -0
  51. package/dist/hooks/useResizeObserver.d.ts +33 -1
  52. package/dist/hooks/useSharedElementTransition.d.ts +112 -0
  53. package/dist/hooks/useSwipeContentTransform.d.ts +9 -2
  54. package/dist/index.cjs +1 -1
  55. package/dist/index.js +7 -7
  56. package/dist/modules/dialog/AlertDialog.d.ts +9 -0
  57. package/dist/modules/dialog/DialogContainer.d.ts +37 -0
  58. package/dist/modules/dialog/Modal.d.ts +26 -0
  59. package/dist/modules/dialog/SwipeDialogContainer.d.ts +16 -0
  60. package/dist/modules/dialog/dialogAnimationUtils.d.ts +113 -0
  61. package/dist/modules/dialog/types.d.ts +183 -0
  62. package/dist/modules/dialog/useDialog.d.ts +39 -0
  63. package/dist/modules/dialog/useDialogContainer.d.ts +47 -0
  64. package/dist/modules/dialog/useDialogSwipeInput.d.ts +70 -0
  65. package/dist/modules/dialog/useDialogTransform.d.ts +82 -0
  66. package/dist/modules/drawer/drawerStateMachine.d.ts +168 -0
  67. package/dist/modules/drawer/revealDrawerConstants.d.ts +33 -0
  68. package/dist/modules/drawer/revealDrawerStateMachine.d.ts +146 -0
  69. package/dist/modules/drawer/strategies/index.d.ts +8 -0
  70. package/dist/modules/drawer/strategies/overlayStrategy.d.ts +12 -0
  71. package/dist/modules/drawer/strategies/revealStrategy.d.ts +12 -0
  72. package/dist/modules/drawer/strategies/types.d.ts +116 -0
  73. package/dist/modules/drawer/types.d.ts +74 -0
  74. package/dist/modules/drawer/useDrawerSwipeInput.d.ts +24 -0
  75. package/dist/modules/pivot/SwipePivotTabBar.d.ts +3 -0
  76. package/dist/modules/stack/SwipeStackContent.d.ts +6 -3
  77. package/dist/modules/stack/SwipeStackOutlet.d.ts +4 -4
  78. package/dist/modules/stack/computeSwipeStackTransform.d.ts +1 -1
  79. package/dist/panels.cjs +1 -1
  80. package/dist/panels.js +1 -1
  81. package/dist/pivot.cjs +1 -1
  82. package/dist/pivot.js +1 -1
  83. package/dist/resizer.cjs +1 -1
  84. package/dist/resizer.js +2 -2
  85. package/dist/stack.cjs +1 -1
  86. package/dist/stack.cjs.map +1 -1
  87. package/dist/stack.js +480 -780
  88. package/dist/stack.js.map +1 -1
  89. package/dist/sticky-header/calculateStickyMetrics.d.ts +28 -0
  90. package/dist/sticky-header.cjs +1 -1
  91. package/dist/sticky-header.cjs.map +1 -1
  92. package/dist/sticky-header.js +59 -51
  93. package/dist/sticky-header.js.map +1 -1
  94. package/dist/{styles-DPPuJ0sf.js → styles-NkjuMOVS.js} +13 -13
  95. package/dist/{styles-DPPuJ0sf.js.map → styles-NkjuMOVS.js.map} +1 -1
  96. package/dist/styles-qf6ptVLD.cjs.map +1 -1
  97. package/dist/types.d.ts +30 -0
  98. package/dist/useAnimationFrame-BZ6D2lMq.cjs +2 -0
  99. package/dist/useAnimationFrame-BZ6D2lMq.cjs.map +1 -0
  100. package/dist/useAnimationFrame-Bg4e-H8O.js +394 -0
  101. package/dist/useAnimationFrame-Bg4e-H8O.js.map +1 -0
  102. package/dist/useDocumentPointerEvents-DXxw3qWj.js +54 -0
  103. package/dist/useDocumentPointerEvents-DXxw3qWj.js.map +1 -0
  104. package/dist/useDocumentPointerEvents-DxDSOtip.cjs +2 -0
  105. package/dist/useDocumentPointerEvents-DxDSOtip.cjs.map +1 -0
  106. package/dist/window/index.d.ts +2 -0
  107. package/dist/window.cjs +1 -1
  108. package/dist/window.cjs.map +1 -1
  109. package/dist/window.js +114 -103
  110. package/dist/window.js.map +1 -1
  111. package/package.json +6 -1
  112. package/src/components/gesture/SwipeSafeZone.tsx +70 -0
  113. package/src/components/grid/GridLayout.tsx +110 -38
  114. package/src/components/window/Drawer.tsx +353 -162
  115. package/src/components/window/DrawerLayers.tsx +54 -11
  116. package/src/components/window/DrawerRevealContext.spec.ts +20 -0
  117. package/src/components/window/DrawerRevealContext.tsx +99 -0
  118. package/src/components/window/drawerRevealAnimationUtils.spec.ts +375 -0
  119. package/src/components/window/drawerRevealAnimationUtils.ts +415 -0
  120. package/src/components/window/drawerStyles.spec.ts +302 -0
  121. package/src/components/window/drawerStyles.ts +252 -0
  122. package/src/components/window/drawerSwipeConfig.spec.ts +131 -0
  123. package/src/components/window/drawerSwipeConfig.ts +112 -0
  124. package/src/components/window/useDrawerSwipeTransform.ts +67 -0
  125. package/src/components/window/useDrawerTransform.ts +505 -0
  126. package/src/components/window/useRevealDrawerTransform.spec.ts +1936 -0
  127. package/src/components/window/useRevealDrawerTransform.ts +105 -0
  128. package/src/constants/styles.ts +19 -0
  129. package/src/demo/components/FullscreenDemoPage.tsx +47 -0
  130. package/src/demo/fullscreenRoutes.tsx +32 -0
  131. package/src/demo/index.tsx +5 -0
  132. package/src/demo/pages/Dialog/alerts/index.tsx +22 -0
  133. package/src/demo/pages/Dialog/card/index.tsx +22 -0
  134. package/src/demo/pages/Dialog/components/AlertDialogDemo.tsx +124 -0
  135. package/src/demo/pages/Dialog/components/CardExpandDemo.module.css +243 -0
  136. package/src/demo/pages/Dialog/components/CardExpandDemo.tsx +219 -0
  137. package/src/demo/pages/Dialog/components/CustomAlertDialogDemo.tsx +219 -0
  138. package/src/demo/pages/Dialog/components/DialogDemos.module.css +77 -0
  139. package/src/demo/pages/Dialog/components/ModalBasics.tsx +45 -0
  140. package/src/demo/pages/Dialog/components/SwipeDialogDemo.module.css +77 -0
  141. package/src/demo/pages/Dialog/components/SwipeDialogDemo.tsx +181 -0
  142. package/src/demo/pages/Dialog/custom-alert/index.tsx +22 -0
  143. package/src/demo/pages/Dialog/modal/index.tsx +17 -0
  144. package/src/demo/pages/Dialog/swipe/index.tsx +22 -0
  145. package/src/demo/pages/Drawer/components/DrawerBasics.module.css +6 -1
  146. package/src/demo/pages/Drawer/components/DrawerBasics.tsx +14 -4
  147. package/src/demo/pages/Drawer/components/DrawerReveal.module.css +157 -0
  148. package/src/demo/pages/Drawer/components/DrawerReveal.tsx +128 -0
  149. package/src/demo/pages/Drawer/components/DrawerSwipe.module.css +316 -0
  150. package/src/demo/pages/Drawer/components/DrawerSwipe.tsx +178 -0
  151. package/src/demo/pages/Drawer/reveal/index.tsx +17 -0
  152. package/src/demo/pages/Drawer/reveal-fullscreen/index.tsx +135 -0
  153. package/src/demo/pages/Drawer/reveal-fullscreen/styles.module.css +233 -0
  154. package/src/demo/pages/Drawer/swipe/index.tsx +17 -0
  155. package/src/demo/pages/Pivot/components/SwipeTabsPivot.tsx +54 -23
  156. package/src/demo/pages/Pivot/swipe-debug/index.tsx +1 -1
  157. package/src/demo/pages/Stack/components/StackBasics.spec.tsx +156 -0
  158. package/src/demo/pages/Stack/components/StackBasics.tsx +179 -95
  159. package/src/demo/pages/Stack/components/StackTablet.spec.tsx +110 -0
  160. package/src/demo/pages/Stack/components/StackTablet.tsx +42 -21
  161. package/src/demo/routes.tsx +24 -1
  162. package/src/dialog/index.ts +85 -0
  163. package/src/hooks/gesture/testing/createGestureSimulator.spec.ts +68 -64
  164. package/src/hooks/gesture/testing/createGestureSimulator.ts +113 -37
  165. package/src/hooks/gesture/types.ts +83 -6
  166. package/src/hooks/gesture/useEdgeSwipeInput.spec.ts +22 -14
  167. package/src/hooks/gesture/useNativeGestureGuard.spec.ts +99 -31
  168. package/src/hooks/gesture/useNativeGestureGuard.ts +3 -1
  169. package/src/hooks/gesture/utils.ts +102 -0
  170. package/src/hooks/useAnimatedVisibility.spec.ts +44 -24
  171. package/src/hooks/useAnimatedVisibility.ts +28 -2
  172. package/src/hooks/useAnimationFrame.ts +8 -0
  173. package/src/hooks/useOperationContinuity.spec.ts +394 -0
  174. package/src/hooks/useOperationContinuity.ts +135 -0
  175. package/src/hooks/useResizeObserver.spec.tsx +277 -0
  176. package/src/hooks/useResizeObserver.tsx +108 -39
  177. package/src/hooks/useScrollContainer.ts +4 -10
  178. package/src/hooks/useSharedElementTransition.ts +354 -0
  179. package/src/hooks/useSwipeContentTransform.spec.ts +18 -18
  180. package/src/hooks/useSwipeContentTransform.ts +166 -28
  181. package/src/modules/dialog/AlertDialog.spec.tsx +387 -0
  182. package/src/modules/dialog/AlertDialog.tsx +221 -0
  183. package/src/modules/dialog/DialogContainer.spec.tsx +228 -0
  184. package/src/modules/dialog/DialogContainer.tsx +188 -0
  185. package/src/modules/dialog/Modal.spec.tsx +220 -0
  186. package/src/modules/dialog/Modal.tsx +182 -0
  187. package/src/modules/dialog/SwipeDialogContainer.tsx +208 -0
  188. package/src/modules/dialog/dialogAnimationUtils.spec.ts +252 -0
  189. package/src/modules/dialog/dialogAnimationUtils.ts +297 -0
  190. package/src/modules/dialog/types.ts +186 -0
  191. package/src/modules/dialog/useDialog.spec.tsx +447 -0
  192. package/src/modules/dialog/useDialog.ts +214 -0
  193. package/src/modules/dialog/useDialogContainer.spec.ts +339 -0
  194. package/src/modules/dialog/useDialogContainer.ts +150 -0
  195. package/src/modules/dialog/useDialogSwipeInput.spec.ts +178 -0
  196. package/src/modules/dialog/useDialogSwipeInput.ts +350 -0
  197. package/src/modules/dialog/useDialogTransform.spec.ts +403 -0
  198. package/src/modules/dialog/useDialogTransform.ts +407 -0
  199. package/src/modules/drawer/drawerStateMachine.ts +500 -0
  200. package/src/modules/drawer/revealDrawerConstants.ts +38 -0
  201. package/src/modules/drawer/revealDrawerStateMachine.spec.ts +558 -0
  202. package/src/modules/drawer/revealDrawerStateMachine.ts +197 -0
  203. package/src/modules/drawer/strategies/index.ts +9 -0
  204. package/src/modules/drawer/strategies/overlayStrategy.ts +133 -0
  205. package/src/modules/drawer/strategies/revealStrategy.ts +111 -0
  206. package/src/modules/drawer/strategies/types.ts +160 -0
  207. package/src/modules/drawer/types.ts +102 -0
  208. package/src/modules/drawer/useDrawerSwipeInput.spec.ts +566 -0
  209. package/src/modules/drawer/useDrawerSwipeInput.ts +402 -0
  210. package/src/modules/panels/rendering/ContentRegistry.spec.tsx +21 -14
  211. package/src/modules/pivot/SwipePivotContent.position.spec.tsx +12 -8
  212. package/src/modules/pivot/SwipePivotContent.spec.tsx +66 -25
  213. package/src/modules/pivot/SwipePivotContent.tsx +2 -2
  214. package/src/modules/pivot/SwipePivotTabBar.spec.tsx +85 -68
  215. package/src/modules/pivot/SwipePivotTabBar.tsx +75 -15
  216. package/src/modules/pivot/scaleInputState.spec.ts +11 -2
  217. package/src/modules/pivot/usePivot.spec.ts +17 -3
  218. package/src/modules/pivot/usePivotSwipeInput.spec.ts +182 -123
  219. package/src/modules/stack/SwipeStackContent.spec.tsx +387 -100
  220. package/src/modules/stack/SwipeStackContent.tsx +43 -33
  221. package/src/modules/stack/SwipeStackOutlet.spec.tsx +14 -16
  222. package/src/modules/stack/SwipeStackOutlet.tsx +6 -6
  223. package/src/modules/stack/computeSwipeStackTransform.spec.ts +5 -5
  224. package/src/modules/stack/computeSwipeStackTransform.ts +3 -3
  225. package/src/modules/stack/swipeTransitionContinuity.spec.tsx +1133 -0
  226. package/src/modules/stack/useStackAnimationState.spec.ts +3 -1
  227. package/src/modules/stack/useStackAnimationState.ts +18 -13
  228. package/src/modules/stack/useStackNavigation.spec.ts +198 -3
  229. package/src/modules/stack/useStackNavigation.tsx +113 -56
  230. package/src/modules/stack/useStackSwipeInput.spec.ts +65 -32
  231. package/src/modules/stack/useStackSwipeInput.ts +1 -1
  232. package/src/sticky-header/StickyArea.tsx +29 -57
  233. package/src/sticky-header/calculateStickyMetrics.spec.ts +105 -0
  234. package/src/sticky-header/calculateStickyMetrics.ts +50 -0
  235. package/src/types.ts +33 -0
  236. package/src/window/index.ts +2 -0
  237. package/dist/FloatingWindow-BpdOpg_L.js +0 -400
  238. package/dist/FloatingWindow-BpdOpg_L.js.map +0 -1
  239. package/dist/FloatingWindow-TCDNY5gE.cjs +0 -2
  240. package/dist/FloatingWindow-TCDNY5gE.cjs.map +0 -1
  241. package/dist/GridLayout-B4VRsC0r.cjs +0 -2
  242. package/dist/GridLayout-BltqeCPK.js +0 -927
  243. package/dist/PanelSystem-Bs8bQwQF.cjs +0 -3
  244. package/dist/PanelSystem-Bs8bQwQF.cjs.map +0 -1
  245. package/dist/PanelSystem-Dr1TBhxM.js.map +0 -1
  246. package/dist/ResizeHandle-CScipO5l.cjs +0 -2
  247. package/dist/SwipePivotTabBar-BGO9X94m.js +0 -407
  248. package/dist/SwipePivotTabBar-BGO9X94m.js.map +0 -1
  249. package/dist/SwipePivotTabBar-BrQismcZ.cjs +0 -2
  250. package/dist/SwipePivotTabBar-BrQismcZ.cjs.map +0 -1
  251. package/dist/useDocumentPointerEvents-CKdhGXd0.js +0 -46
  252. package/dist/useDocumentPointerEvents-CKdhGXd0.js.map +0 -1
  253. package/dist/useDocumentPointerEvents-ChqrKXDk.cjs +0 -2
  254. package/dist/useDocumentPointerEvents-ChqrKXDk.cjs.map +0 -1
  255. package/dist/useEffectEvent-Dp7HLCf0.js +0 -13
  256. package/dist/useEffectEvent-Dp7HLCf0.js.map +0 -1
  257. package/dist/useEffectEvent-huSsGUnl.cjs +0 -2
  258. package/dist/useEffectEvent-huSsGUnl.cjs.map +0 -1
@@ -0,0 +1,403 @@
1
+ /**
2
+ * @file Tests for useDialogTransform hook
3
+ */
4
+ import { renderHook, act, waitFor } from "@testing-library/react";
5
+ import { useDialogTransform } from "./useDialogTransform.js";
6
+ import type { ContinuousOperationState } from "../../hooks/gesture/types.js";
7
+ import { IDLE_CONTINUOUS_OPERATION_STATE } from "../../hooks/gesture/types.js";
8
+
9
+ // Mock ResizeObserver
10
+ const createMockResizeObserver = () => {
11
+ const callbacks: ResizeObserverCallback[] = [];
12
+ return {
13
+ callbacks,
14
+ MockClass: class {
15
+ constructor(callback: ResizeObserverCallback) {
16
+ callbacks.push(callback);
17
+ }
18
+ observe(): void {
19
+ // no-op
20
+ }
21
+ unobserve(): void {
22
+ // no-op
23
+ }
24
+ disconnect(): void {
25
+ // no-op
26
+ }
27
+ },
28
+ };
29
+ };
30
+
31
+ const { MockClass: MockResizeObserver } = createMockResizeObserver();
32
+ globalThis.ResizeObserver = MockResizeObserver;
33
+
34
+ describe("useDialogTransform", () => {
35
+ const createRAFTracker = () => {
36
+ const callbacks: FrameRequestCallback[] = [];
37
+ const tracker = { callbacks, nextId: 0 };
38
+ return tracker;
39
+ };
40
+
41
+ const rafTracker = createRAFTracker();
42
+ const originalRAF = globalThis.requestAnimationFrame;
43
+ const originalCAF = globalThis.cancelAnimationFrame;
44
+
45
+ beforeEach(() => {
46
+ rafTracker.callbacks.length = 0;
47
+ rafTracker.nextId = 0;
48
+
49
+ globalThis.requestAnimationFrame = (cb: FrameRequestCallback): number => {
50
+ rafTracker.callbacks.push(cb);
51
+ rafTracker.nextId += 1;
52
+ return rafTracker.nextId;
53
+ };
54
+ globalThis.cancelAnimationFrame = (): void => {
55
+ // Mock cancel
56
+ };
57
+ });
58
+
59
+ afterEach(() => {
60
+ globalThis.requestAnimationFrame = originalRAF;
61
+ globalThis.cancelAnimationFrame = originalCAF;
62
+ });
63
+
64
+ const runAnimationFrames = (count = 1, deltaMs = 16) => {
65
+ const now = performance.now();
66
+ for (let i = 0; i < count; i++) {
67
+ const callbacks = [...rafTracker.callbacks];
68
+ rafTracker.callbacks.length = 0;
69
+ callbacks.forEach(cb => cb(now + deltaMs * (i + 1)));
70
+ }
71
+ };
72
+
73
+ const createMockElement = (dimensions: { width: number; height: number }) => {
74
+ const setPropertyCalls: Array<{ prop: string; value: string }> = [];
75
+ // eslint-disable-next-line custom/no-as-outside-guard -- Required for DOM mock
76
+ return {
77
+ clientWidth: dimensions.width,
78
+ clientHeight: dimensions.height,
79
+ style: {
80
+ transform: "",
81
+ setProperty: (prop: string, value: string): void => {
82
+ setPropertyCalls.push({ prop, value });
83
+ },
84
+ viewTransitionName: "",
85
+ },
86
+ _setPropertyCalls: setPropertyCalls,
87
+ } as unknown as HTMLDivElement;
88
+ };
89
+
90
+ const createMockBackdrop = () => {
91
+ // eslint-disable-next-line custom/no-as-outside-guard -- Required for DOM mock
92
+ return {
93
+ style: {
94
+ opacity: "",
95
+ },
96
+ } as unknown as HTMLDivElement;
97
+ };
98
+
99
+ const idleSwipeState: ContinuousOperationState = IDLE_CONTINUOUS_OPERATION_STATE;
100
+ const zeroDisplacement2D = { x: 0, y: 0 };
101
+
102
+ describe("opening animation", () => {
103
+ it("should start animation when visible changes from false to true", async () => {
104
+ const element = createMockElement({ width: 400, height: 300 });
105
+ const backdrop = createMockBackdrop();
106
+ const elementRef = { current: element };
107
+ const backdropRef = { current: backdrop };
108
+
109
+ const { result, rerender } = renderHook(
110
+ ({ visible }) =>
111
+ useDialogTransform({
112
+ elementRef,
113
+ backdropRef,
114
+ visible,
115
+ openDirection: "bottom",
116
+ swipeState: idleSwipeState,
117
+ displacement: 0,
118
+ displacement2D: zeroDisplacement2D,
119
+ }),
120
+ { initialProps: { visible: false } },
121
+ );
122
+
123
+ expect(result.current.phase).toBe("closed");
124
+
125
+ // Trigger visible change
126
+ rerender({ visible: true });
127
+
128
+ // Should transition to opening
129
+ expect(result.current.phase).toBe("opening");
130
+ expect(result.current.isAnimating).toBe(true);
131
+ });
132
+
133
+ it("should apply transform during opening animation", async () => {
134
+ const element = createMockElement({ width: 400, height: 300 });
135
+ const backdrop = createMockBackdrop();
136
+ const elementRef = { current: element };
137
+ const backdropRef = { current: backdrop };
138
+
139
+ const { rerender } = renderHook(
140
+ ({ visible }) =>
141
+ useDialogTransform({
142
+ elementRef,
143
+ backdropRef,
144
+ visible,
145
+ openDirection: "bottom",
146
+ swipeState: idleSwipeState,
147
+ displacement: 0,
148
+ displacement2D: zeroDisplacement2D,
149
+ }),
150
+ { initialProps: { visible: false } },
151
+ );
152
+
153
+ // Trigger visible change
154
+ rerender({ visible: true });
155
+
156
+ // Run some animation frames
157
+ act(() => {
158
+ runAnimationFrames(5, 50);
159
+ });
160
+
161
+ // Transform should be applied
162
+ expect(element.style.transform).not.toBe("");
163
+ });
164
+
165
+ it("should call onOpenComplete when animation finishes", async () => {
166
+ const element = createMockElement({ width: 400, height: 300 });
167
+ const backdrop = createMockBackdrop();
168
+ const elementRef = { current: element };
169
+ const backdropRef = { current: backdrop };
170
+ const onOpenCompleteCalls: unknown[] = [];
171
+ const onOpenComplete = (): void => {
172
+ onOpenCompleteCalls.push(undefined);
173
+ };
174
+
175
+ const { result, rerender } = renderHook(
176
+ ({ visible }) =>
177
+ useDialogTransform({
178
+ elementRef,
179
+ backdropRef,
180
+ visible,
181
+ openDirection: "bottom",
182
+ swipeState: idleSwipeState,
183
+ displacement: 0,
184
+ displacement2D: zeroDisplacement2D,
185
+ animationDuration: 100,
186
+ onOpenComplete,
187
+ }),
188
+ { initialProps: { visible: false } },
189
+ );
190
+
191
+ // Trigger visible change
192
+ rerender({ visible: true });
193
+
194
+ // Run enough frames to complete animation
195
+ act(() => {
196
+ runAnimationFrames(10, 20);
197
+ });
198
+
199
+ await waitFor(() => {
200
+ expect(result.current.phase).toBe("open");
201
+ });
202
+
203
+ expect(onOpenCompleteCalls.length).toBeGreaterThan(0);
204
+ });
205
+ });
206
+
207
+ describe("closing animation", () => {
208
+ it("should animate close when triggerClose is called", async () => {
209
+ const element = createMockElement({ width: 400, height: 300 });
210
+ const backdrop = createMockBackdrop();
211
+ const elementRef = { current: element };
212
+ const backdropRef = { current: backdrop };
213
+
214
+ const { result, rerender } = renderHook(
215
+ ({ visible }) =>
216
+ useDialogTransform({
217
+ elementRef,
218
+ backdropRef,
219
+ visible,
220
+ openDirection: "bottom",
221
+ swipeState: idleSwipeState,
222
+ displacement: 0,
223
+ displacement2D: zeroDisplacement2D,
224
+ }),
225
+ { initialProps: { visible: false } },
226
+ );
227
+
228
+ // Open first
229
+ rerender({ visible: true });
230
+ act(() => {
231
+ runAnimationFrames(30, 20);
232
+ });
233
+
234
+ await waitFor(() => {
235
+ expect(result.current.phase).toBe("open");
236
+ });
237
+
238
+ // Now trigger close
239
+ act(() => {
240
+ result.current.triggerClose();
241
+ });
242
+
243
+ expect(result.current.phase).toBe("closing");
244
+ });
245
+
246
+ it("should call onCloseComplete when close animation finishes", async () => {
247
+ const element = createMockElement({ width: 400, height: 300 });
248
+ const backdrop = createMockBackdrop();
249
+ const elementRef = { current: element };
250
+ const backdropRef = { current: backdrop };
251
+ const onCloseCompleteCalls: unknown[] = [];
252
+ const onCloseComplete = (): void => {
253
+ onCloseCompleteCalls.push(undefined);
254
+ };
255
+
256
+ const { result, rerender } = renderHook(
257
+ ({ visible }) =>
258
+ useDialogTransform({
259
+ elementRef,
260
+ backdropRef,
261
+ visible,
262
+ openDirection: "bottom",
263
+ swipeState: idleSwipeState,
264
+ displacement: 0,
265
+ displacement2D: zeroDisplacement2D,
266
+ animationDuration: 100,
267
+ onCloseComplete,
268
+ }),
269
+ { initialProps: { visible: false } },
270
+ );
271
+
272
+ // Open first
273
+ rerender({ visible: true });
274
+ act(() => {
275
+ runAnimationFrames(30, 20);
276
+ });
277
+
278
+ await waitFor(() => {
279
+ expect(result.current.phase).toBe("open");
280
+ });
281
+
282
+ // Trigger close
283
+ act(() => {
284
+ result.current.triggerClose();
285
+ });
286
+
287
+ // Run animation
288
+ act(() => {
289
+ runAnimationFrames(30, 20);
290
+ });
291
+
292
+ await waitFor(() => {
293
+ expect(result.current.phase).toBe("closed");
294
+ });
295
+
296
+ expect(onCloseCompleteCalls.length).toBeGreaterThan(0);
297
+ });
298
+ });
299
+
300
+ describe("swipe interaction", () => {
301
+ it("should apply 2D transform during swipe", () => {
302
+ const element = createMockElement({ width: 400, height: 300 });
303
+ const backdrop = createMockBackdrop();
304
+ const elementRef = { current: element };
305
+ const backdropRef = { current: backdrop };
306
+
307
+ const operatingSwipeState: ContinuousOperationState = {
308
+ phase: "operating",
309
+ displacement: { x: 30, y: 100 },
310
+ velocity: { x: 0, y: 0 },
311
+ };
312
+
313
+ renderHook(() =>
314
+ useDialogTransform({
315
+ elementRef,
316
+ backdropRef,
317
+ visible: true,
318
+ openDirection: "bottom",
319
+ swipeState: operatingSwipeState,
320
+ displacement: 100,
321
+ displacement2D: { x: 30, y: 100 },
322
+ }),
323
+ );
324
+
325
+ // Transform should reflect 2D displacement
326
+ expect(element.style.transform).toContain("translate(30px, 100px)");
327
+ });
328
+
329
+ it("should animate snapback when swipe ends below threshold", async () => {
330
+ const element = createMockElement({ width: 400, height: 300 });
331
+ const backdrop = createMockBackdrop();
332
+ const elementRef = { current: element };
333
+ const backdropRef = { current: backdrop };
334
+
335
+ const operatingState: ContinuousOperationState = {
336
+ phase: "operating",
337
+ displacement: { x: 20, y: 50 },
338
+ velocity: { x: 0, y: 0 },
339
+ };
340
+
341
+ const displacement2D = { x: 20, y: 50 };
342
+
343
+ const { rerender, result } = renderHook(
344
+ ({ swipeState, displacement, d2d }) =>
345
+ useDialogTransform({
346
+ elementRef,
347
+ backdropRef,
348
+ visible: true,
349
+ openDirection: "bottom",
350
+ swipeState,
351
+ displacement,
352
+ displacement2D: d2d,
353
+ }),
354
+ { initialProps: { swipeState: operatingState, displacement: 50, d2d: displacement2D } },
355
+ );
356
+
357
+ // End swipe
358
+ const endedState: ContinuousOperationState = {
359
+ phase: "ended",
360
+ displacement: { x: 20, y: 50 },
361
+ velocity: { x: 0, y: 0 },
362
+ };
363
+ rerender({ swipeState: endedState, displacement: 50, d2d: displacement2D });
364
+
365
+ // Should start snapback animation
366
+ expect(result.current.isAnimating).toBe(true);
367
+ });
368
+ });
369
+
370
+ describe("container size handling", () => {
371
+ it("should not apply transform when container size is 0", () => {
372
+ const element = createMockElement({ width: 0, height: 0 });
373
+ const backdrop = createMockBackdrop();
374
+ const elementRef = { current: element };
375
+ const backdropRef = { current: backdrop };
376
+
377
+ const { rerender } = renderHook(
378
+ ({ visible }) =>
379
+ useDialogTransform({
380
+ elementRef,
381
+ backdropRef,
382
+ visible,
383
+ openDirection: "bottom",
384
+ swipeState: idleSwipeState,
385
+ displacement: 0,
386
+ displacement2D: zeroDisplacement2D,
387
+ }),
388
+ { initialProps: { visible: false } },
389
+ );
390
+
391
+ rerender({ visible: true });
392
+
393
+ act(() => {
394
+ runAnimationFrames(5, 50);
395
+ });
396
+
397
+ // This test documents the current BROKEN behavior
398
+ // Transform should NOT be empty - this is the bug!
399
+ // When we fix it, this expectation should change
400
+ expect(element.style.transform).toBe("");
401
+ });
402
+ });
403
+ });