react-panel-layout 0.6.0 → 0.6.1
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-SgYLc6Ud.js → FloatingPanelFrame-3eU9AwPo.js} +2 -2
- package/dist/{FloatingPanelFrame-SgYLc6Ud.js.map → FloatingPanelFrame-3eU9AwPo.js.map} +1 -1
- package/dist/FloatingWindow-CUXnEtrb.js +827 -0
- package/dist/FloatingWindow-CUXnEtrb.js.map +1 -0
- package/dist/FloatingWindow-DMwyK0eK.cjs +2 -0
- package/dist/FloatingWindow-DMwyK0eK.cjs.map +1 -0
- package/dist/GridLayout-DKTg_N61.cjs +2 -0
- package/dist/{GridLayout-B4VRsC0r.cjs.map → GridLayout-DKTg_N61.cjs.map} +1 -1
- package/dist/{GridLayout-BltqeCPK.js → GridLayout-UWNxXw77.js} +34 -35
- package/dist/{GridLayout-BltqeCPK.js.map → GridLayout-UWNxXw77.js.map} +1 -1
- package/dist/{HorizontalDivider-WF1k_qND.js → HorizontalDivider-DdxzfV0l.js} +3 -3
- package/dist/{HorizontalDivider-WF1k_qND.js.map → HorizontalDivider-DdxzfV0l.js.map} +1 -1
- package/dist/{HorizontalDivider-B5Z-KZLk.cjs → HorizontalDivider-_pgV4Mcv.cjs} +2 -2
- package/dist/{HorizontalDivider-B5Z-KZLk.cjs.map → HorizontalDivider-_pgV4Mcv.cjs.map} +1 -1
- package/dist/{PanelSystem-Dr1TBhxM.js → PanelSystem-BqUzNtf2.js} +5 -5
- package/dist/{PanelSystem-Dr1TBhxM.js.map → PanelSystem-BqUzNtf2.js.map} +1 -1
- package/dist/{PanelSystem-Bs8bQwQF.cjs → PanelSystem-D603LKKv.cjs} +2 -2
- package/dist/{PanelSystem-Bs8bQwQF.cjs.map → PanelSystem-D603LKKv.cjs.map} +1 -1
- package/dist/ResizeHandle-CBcAS918.cjs +2 -0
- package/dist/{ResizeHandle-CScipO5l.cjs.map → ResizeHandle-CBcAS918.cjs.map} +1 -1
- package/dist/{ResizeHandle-CdA_JYfN.js → ResizeHandle-CXjc1meV.js} +28 -29
- package/dist/{ResizeHandle-CdA_JYfN.js.map → ResizeHandle-CXjc1meV.js.map} +1 -1
- package/dist/SwipePivotTabBar-DWrCuwEI.js +411 -0
- package/dist/SwipePivotTabBar-DWrCuwEI.js.map +1 -0
- package/dist/SwipePivotTabBar-fjjXkpj7.cjs +2 -0
- package/dist/SwipePivotTabBar-fjjXkpj7.cjs.map +1 -0
- package/dist/components/gesture/SwipeSafeZone.d.ts +40 -0
- package/dist/components/window/Drawer.d.ts +3 -1
- package/dist/components/window/DrawerLayers.d.ts +1 -1
- package/dist/components/window/drawerStyles.d.ts +69 -0
- package/dist/components/window/drawerSwipeConfig.d.ts +29 -0
- package/dist/components/window/useDrawerSwipeTransform.d.ts +23 -0
- package/dist/config.cjs +1 -1
- package/dist/config.js +3 -3
- package/dist/constants/styles.d.ts +17 -0
- package/dist/dialog/index.d.ts +69 -0
- package/dist/floating.js +1 -1
- package/dist/grid.cjs +1 -1
- package/dist/grid.js +2 -2
- package/dist/hooks/gesture/testing/createGestureSimulator.d.ts +7 -0
- package/dist/hooks/gesture/types.d.ts +48 -5
- package/dist/hooks/gesture/utils.d.ts +19 -0
- package/dist/hooks/useAnimationFrame.d.ts +2 -0
- package/dist/hooks/useOperationContinuity.d.ts +64 -0
- package/dist/hooks/useResizeObserver.d.ts +33 -1
- package/dist/hooks/useSharedElementTransition.d.ts +112 -0
- package/dist/hooks/useSwipeContentTransform.d.ts +9 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +7 -7
- package/dist/modules/dialog/AlertDialog.d.ts +9 -0
- package/dist/modules/dialog/DialogContainer.d.ts +37 -0
- package/dist/modules/dialog/Modal.d.ts +26 -0
- package/dist/modules/dialog/SwipeDialogContainer.d.ts +16 -0
- package/dist/modules/dialog/dialogAnimationUtils.d.ts +113 -0
- package/dist/modules/dialog/types.d.ts +183 -0
- package/dist/modules/dialog/useDialog.d.ts +39 -0
- package/dist/modules/dialog/useDialogContainer.d.ts +47 -0
- package/dist/modules/dialog/useDialogSwipeInput.d.ts +70 -0
- package/dist/modules/dialog/useDialogTransform.d.ts +82 -0
- package/dist/modules/drawer/types.d.ts +74 -0
- package/dist/modules/drawer/useDrawerSwipeInput.d.ts +24 -0
- package/dist/modules/pivot/SwipePivotTabBar.d.ts +3 -0
- package/dist/modules/stack/SwipeStackContent.d.ts +6 -3
- package/dist/modules/stack/SwipeStackOutlet.d.ts +4 -4
- package/dist/modules/stack/computeSwipeStackTransform.d.ts +1 -1
- package/dist/panels.cjs +1 -1
- package/dist/panels.js +1 -1
- package/dist/pivot.cjs +1 -1
- package/dist/pivot.js +1 -1
- package/dist/resizer.cjs +1 -1
- package/dist/resizer.js +2 -2
- package/dist/stack.cjs +1 -1
- package/dist/stack.cjs.map +1 -1
- package/dist/stack.js +503 -762
- package/dist/stack.js.map +1 -1
- package/dist/sticky-header/calculateStickyMetrics.d.ts +28 -0
- package/dist/sticky-header.cjs +1 -1
- package/dist/sticky-header.cjs.map +1 -1
- package/dist/sticky-header.js +59 -51
- package/dist/sticky-header.js.map +1 -1
- package/dist/{styles-DPPuJ0sf.js → styles-NkjuMOVS.js} +13 -13
- package/dist/{styles-DPPuJ0sf.js.map → styles-NkjuMOVS.js.map} +1 -1
- package/dist/styles-qf6ptVLD.cjs.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/useDocumentPointerEvents-DXxw3qWj.js +54 -0
- package/dist/useDocumentPointerEvents-DXxw3qWj.js.map +1 -0
- package/dist/useDocumentPointerEvents-DxDSOtip.cjs +2 -0
- package/dist/useDocumentPointerEvents-DxDSOtip.cjs.map +1 -0
- package/dist/useNativeGestureGuard-C7TSqEkr.cjs +2 -0
- package/dist/useNativeGestureGuard-C7TSqEkr.cjs.map +1 -0
- package/dist/useNativeGestureGuard-CGYo6O0r.js +347 -0
- package/dist/useNativeGestureGuard-CGYo6O0r.js.map +1 -0
- package/dist/window/index.d.ts +2 -0
- package/dist/window.cjs +1 -1
- package/dist/window.cjs.map +1 -1
- package/dist/window.js +114 -103
- package/dist/window.js.map +1 -1
- package/package.json +6 -1
- package/src/components/gesture/SwipeSafeZone.tsx +69 -0
- package/src/components/window/Drawer.tsx +249 -162
- package/src/components/window/DrawerLayers.tsx +13 -3
- package/src/components/window/drawerStyles.spec.ts +263 -0
- package/src/components/window/drawerStyles.ts +228 -0
- package/src/components/window/drawerSwipeConfig.spec.ts +131 -0
- package/src/components/window/drawerSwipeConfig.ts +112 -0
- package/src/components/window/useDrawerSwipeTransform.spec.ts +234 -0
- package/src/components/window/useDrawerSwipeTransform.ts +129 -0
- package/src/constants/styles.ts +19 -0
- package/src/demo/pages/Dialog/alerts/index.tsx +22 -0
- package/src/demo/pages/Dialog/card/index.tsx +22 -0
- package/src/demo/pages/Dialog/components/AlertDialogDemo.tsx +124 -0
- package/src/demo/pages/Dialog/components/CardExpandDemo.module.css +243 -0
- package/src/demo/pages/Dialog/components/CardExpandDemo.tsx +204 -0
- package/src/demo/pages/Dialog/components/CustomAlertDialogDemo.tsx +219 -0
- package/src/demo/pages/Dialog/components/DialogDemos.module.css +77 -0
- package/src/demo/pages/Dialog/components/ModalBasics.tsx +45 -0
- package/src/demo/pages/Dialog/components/SwipeDialogDemo.module.css +77 -0
- package/src/demo/pages/Dialog/components/SwipeDialogDemo.tsx +181 -0
- package/src/demo/pages/Dialog/custom-alert/index.tsx +22 -0
- package/src/demo/pages/Dialog/modal/index.tsx +17 -0
- package/src/demo/pages/Dialog/swipe/index.tsx +22 -0
- package/src/demo/pages/Drawer/components/DrawerSwipe.module.css +316 -0
- package/src/demo/pages/Drawer/components/DrawerSwipe.tsx +178 -0
- package/src/demo/pages/Drawer/swipe/index.tsx +17 -0
- package/src/demo/pages/Pivot/components/SwipeTabsPivot.tsx +54 -23
- package/src/demo/pages/Pivot/swipe-debug/index.tsx +1 -1
- package/src/demo/pages/Stack/components/StackBasics.spec.tsx +152 -0
- package/src/demo/pages/Stack/components/StackBasics.tsx +179 -95
- package/src/demo/pages/Stack/components/StackTablet.spec.tsx +120 -0
- package/src/demo/pages/Stack/components/StackTablet.tsx +42 -21
- package/src/demo/routes.tsx +22 -1
- package/src/dialog/index.ts +85 -0
- package/src/hooks/gesture/testing/createGestureSimulator.spec.ts +68 -64
- package/src/hooks/gesture/testing/createGestureSimulator.ts +112 -37
- package/src/hooks/gesture/types.ts +83 -6
- package/src/hooks/gesture/useEdgeSwipeInput.spec.ts +22 -14
- package/src/hooks/gesture/useNativeGestureGuard.spec.ts +91 -31
- package/src/hooks/gesture/useNativeGestureGuard.ts +3 -1
- package/src/hooks/gesture/utils.ts +91 -0
- package/src/hooks/useAnimatedVisibility.spec.ts +44 -24
- package/src/hooks/useAnimatedVisibility.ts +28 -2
- package/src/hooks/useAnimationFrame.ts +8 -0
- package/src/hooks/useOperationContinuity.spec.ts +387 -0
- package/src/hooks/useOperationContinuity.ts +135 -0
- package/src/hooks/useResizeObserver.spec.tsx +277 -0
- package/src/hooks/useResizeObserver.tsx +108 -39
- package/src/hooks/useScrollContainer.ts +4 -10
- package/src/hooks/useSharedElementTransition.ts +333 -0
- package/src/hooks/useSwipeContentTransform.spec.ts +18 -18
- package/src/hooks/useSwipeContentTransform.ts +166 -28
- package/src/modules/dialog/AlertDialog.spec.tsx +387 -0
- package/src/modules/dialog/AlertDialog.tsx +221 -0
- package/src/modules/dialog/DialogContainer.spec.tsx +228 -0
- package/src/modules/dialog/DialogContainer.tsx +188 -0
- package/src/modules/dialog/Modal.spec.tsx +220 -0
- package/src/modules/dialog/Modal.tsx +182 -0
- package/src/modules/dialog/SwipeDialogContainer.tsx +208 -0
- package/src/modules/dialog/dialogAnimationUtils.spec.ts +253 -0
- package/src/modules/dialog/dialogAnimationUtils.ts +297 -0
- package/src/modules/dialog/types.ts +186 -0
- package/src/modules/dialog/useDialog.spec.tsx +447 -0
- package/src/modules/dialog/useDialog.ts +214 -0
- package/src/modules/dialog/useDialogContainer.spec.ts +331 -0
- package/src/modules/dialog/useDialogContainer.ts +150 -0
- package/src/modules/dialog/useDialogSwipeInput.spec.ts +157 -0
- package/src/modules/dialog/useDialogSwipeInput.ts +319 -0
- package/src/modules/dialog/useDialogTransform.spec.ts +370 -0
- package/src/modules/dialog/useDialogTransform.ts +407 -0
- package/src/modules/drawer/types.ts +102 -0
- package/src/modules/drawer/useDrawerSwipeInput.spec.ts +566 -0
- package/src/modules/drawer/useDrawerSwipeInput.ts +399 -0
- package/src/modules/panels/rendering/ContentRegistry.spec.tsx +21 -14
- package/src/modules/pivot/SwipePivotContent.position.spec.tsx +12 -8
- package/src/modules/pivot/SwipePivotContent.spec.tsx +55 -25
- package/src/modules/pivot/SwipePivotContent.tsx +2 -2
- package/src/modules/pivot/SwipePivotTabBar.spec.tsx +85 -68
- package/src/modules/pivot/SwipePivotTabBar.tsx +75 -15
- package/src/modules/pivot/scaleInputState.spec.ts +11 -2
- package/src/modules/pivot/usePivot.spec.ts +17 -3
- package/src/modules/pivot/usePivotSwipeInput.spec.ts +182 -123
- package/src/modules/stack/SwipeStackContent.spec.tsx +387 -100
- package/src/modules/stack/SwipeStackContent.tsx +43 -33
- package/src/modules/stack/SwipeStackOutlet.spec.tsx +14 -16
- package/src/modules/stack/SwipeStackOutlet.tsx +6 -6
- package/src/modules/stack/computeSwipeStackTransform.spec.ts +5 -5
- package/src/modules/stack/computeSwipeStackTransform.ts +3 -3
- package/src/modules/stack/swipeTransitionContinuity.spec.tsx +1133 -0
- package/src/modules/stack/useStackAnimationState.spec.ts +3 -1
- package/src/modules/stack/useStackAnimationState.ts +18 -13
- package/src/modules/stack/useStackNavigation.spec.ts +198 -3
- package/src/modules/stack/useStackNavigation.tsx +113 -56
- package/src/modules/stack/useStackSwipeInput.spec.ts +65 -32
- package/src/modules/stack/useStackSwipeInput.ts +1 -1
- package/src/sticky-header/StickyArea.tsx +29 -57
- package/src/sticky-header/calculateStickyMetrics.spec.ts +105 -0
- package/src/sticky-header/calculateStickyMetrics.ts +50 -0
- package/src/types.ts +18 -0
- package/src/window/index.ts +2 -0
- package/dist/FloatingWindow-BpdOpg_L.js +0 -400
- package/dist/FloatingWindow-BpdOpg_L.js.map +0 -1
- package/dist/FloatingWindow-TCDNY5gE.cjs +0 -2
- package/dist/FloatingWindow-TCDNY5gE.cjs.map +0 -1
- package/dist/GridLayout-B4VRsC0r.cjs +0 -2
- package/dist/ResizeHandle-CScipO5l.cjs +0 -2
- package/dist/SwipePivotTabBar-BGO9X94m.js +0 -407
- package/dist/SwipePivotTabBar-BGO9X94m.js.map +0 -1
- package/dist/SwipePivotTabBar-BrQismcZ.cjs +0 -2
- package/dist/SwipePivotTabBar-BrQismcZ.cjs.map +0 -1
- package/dist/useDocumentPointerEvents-CKdhGXd0.js +0 -46
- package/dist/useDocumentPointerEvents-CKdhGXd0.js.map +0 -1
- package/dist/useDocumentPointerEvents-ChqrKXDk.cjs +0 -2
- package/dist/useDocumentPointerEvents-ChqrKXDk.cjs.map +0 -1
- package/dist/useEffectEvent-Dp7HLCf0.js +0 -13
- package/dist/useEffectEvent-Dp7HLCf0.js.map +0 -1
- package/dist/useEffectEvent-huSsGUnl.cjs +0 -2
- package/dist/useEffectEvent-huSsGUnl.cjs.map +0 -1
|
@@ -8,6 +8,7 @@ import { useStackNavigation } from "../../../../modules/stack/useStackNavigation
|
|
|
8
8
|
import { useStackSwipeInput } from "../../../../modules/stack/useStackSwipeInput.js";
|
|
9
9
|
import { SwipeStackContent } from "../../../../modules/stack/SwipeStackContent.js";
|
|
10
10
|
import { useResizeObserver } from "../../../../hooks/useResizeObserver.js";
|
|
11
|
+
import { toContinuousOperationState } from "../../../../hooks/gesture/types.js";
|
|
11
12
|
import type { StackPanel } from "../../../../modules/stack/types.js";
|
|
12
13
|
import styles from "./StackTablet.module.css";
|
|
13
14
|
import "../../../styles/stack-themes.css";
|
|
@@ -271,36 +272,53 @@ export const StackTablet: React.FC<StackTabletProps> = ({ theme = "ios" }) => {
|
|
|
271
272
|
// Get visible panels: active + behind (for swipe reveal) + exiting (for back animation)
|
|
272
273
|
const { stack, depth } = navigation.state;
|
|
273
274
|
|
|
274
|
-
// Track exiting panel when navigating back
|
|
275
|
-
|
|
275
|
+
// Track exiting panel when navigating back.
|
|
276
|
+
// CRITICAL: exitingPanelId must be computed synchronously during render
|
|
277
|
+
// to prevent the exiting panel from being unmounted for a frame.
|
|
278
|
+
// If the panel unmounts, it loses its position state and causes a visual jump.
|
|
276
279
|
const prevDepthRef = React.useRef(depth);
|
|
277
280
|
const prevStackRef = React.useRef<ReadonlyArray<string>>(stack);
|
|
281
|
+
const exitingPanelClearTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
282
|
+
const [exitingPanelState, setExitingPanelState] = React.useState<string | null>(null);
|
|
278
283
|
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
284
|
+
// Compute exiting panel ID synchronously during render
|
|
285
|
+
// This ensures the panel stays in the render tree even on the navigation change render
|
|
286
|
+
const prevDepth = prevDepthRef.current;
|
|
287
|
+
const prevStack = prevStackRef.current;
|
|
288
|
+
const isNavigatingBack = depth < prevDepth;
|
|
289
|
+
const computedExitingId = isNavigatingBack ? (prevStack[prevDepth] ?? null) : null;
|
|
290
|
+
|
|
291
|
+
// Use computed value if navigating back, otherwise use state (for timeout-based cleanup)
|
|
292
|
+
const exitingPanelId = computedExitingId ?? exitingPanelState;
|
|
283
293
|
|
|
294
|
+
// Update refs and state in effect
|
|
295
|
+
React.useLayoutEffect(() => {
|
|
284
296
|
// Update refs
|
|
285
297
|
prevDepthRef.current = depth;
|
|
286
298
|
prevStackRef.current = stack;
|
|
287
299
|
|
|
288
|
-
//
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
const exitingId = prevStack[prevDepth];
|
|
292
|
-
if (exitingId != null) {
|
|
293
|
-
setExitingPanelId(exitingId);
|
|
294
|
-
|
|
295
|
-
// Clear exiting panel after animation completes
|
|
296
|
-
const timeoutId = setTimeout(() => {
|
|
297
|
-
setExitingPanelId(null);
|
|
298
|
-
}, THEME_DURATIONS[selectedTheme]);
|
|
300
|
+
// If we just started navigating back, update state and schedule cleanup
|
|
301
|
+
if (computedExitingId != null) {
|
|
302
|
+
setExitingPanelState(computedExitingId);
|
|
299
303
|
|
|
300
|
-
|
|
304
|
+
// Clear any existing timeout
|
|
305
|
+
if (exitingPanelClearTimeoutRef.current != null) {
|
|
306
|
+
clearTimeout(exitingPanelClearTimeoutRef.current);
|
|
301
307
|
}
|
|
308
|
+
|
|
309
|
+
// Clear exiting panel after animation completes
|
|
310
|
+
exitingPanelClearTimeoutRef.current = setTimeout(() => {
|
|
311
|
+
setExitingPanelState(null);
|
|
312
|
+
exitingPanelClearTimeoutRef.current = null;
|
|
313
|
+
}, THEME_DURATIONS[selectedTheme]);
|
|
302
314
|
}
|
|
303
|
-
|
|
315
|
+
|
|
316
|
+
return () => {
|
|
317
|
+
if (exitingPanelClearTimeoutRef.current != null) {
|
|
318
|
+
clearTimeout(exitingPanelClearTimeoutRef.current);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}, [depth, stack, selectedTheme, computedExitingId]);
|
|
304
322
|
|
|
305
323
|
const visiblePanelIds = React.useMemo(() => {
|
|
306
324
|
const ids = [stack[depth]]; // Active panel
|
|
@@ -327,7 +345,10 @@ export const StackTablet: React.FC<StackTabletProps> = ({ theme = "ios" }) => {
|
|
|
327
345
|
return null;
|
|
328
346
|
}
|
|
329
347
|
|
|
330
|
-
|
|
348
|
+
// Panel is only "exiting" if it matches exitingPanelId AND is not in current stack
|
|
349
|
+
// This prevents the bug where a re-pushed panel is incorrectly treated as exiting
|
|
350
|
+
const isInCurrentStack = stack.includes(panelId);
|
|
351
|
+
const isExiting = panelId === exitingPanelId && !isInCurrentStack;
|
|
331
352
|
// For exiting panels, use depth + 1 since they were previously at the active position
|
|
332
353
|
const panelDepth = isExiting ? depth + 1 : stack.indexOf(panelId);
|
|
333
354
|
const isActive = panelDepth === depth && !isExiting;
|
|
@@ -339,7 +360,7 @@ export const StackTablet: React.FC<StackTabletProps> = ({ theme = "ios" }) => {
|
|
|
339
360
|
depth={panelDepth}
|
|
340
361
|
navigationDepth={depth}
|
|
341
362
|
isActive={isActive}
|
|
342
|
-
|
|
363
|
+
operationState={toContinuousOperationState(inputState)}
|
|
343
364
|
containerSize={containerSize}
|
|
344
365
|
animateOnMount={true}
|
|
345
366
|
animationDuration={THEME_DURATIONS[selectedTheme]}
|
package/src/demo/routes.tsx
CHANGED
|
@@ -27,6 +27,13 @@ import PL_Overlays from "./pages/PanelLayout/draggable-overlays";
|
|
|
27
27
|
import DR_Basics from "./pages/Drawer/basics";
|
|
28
28
|
import DR_Menu from "./pages/Drawer/menu";
|
|
29
29
|
import DR_Animations from "./pages/Drawer/animations";
|
|
30
|
+
import DR_Swipe from "./pages/Drawer/swipe";
|
|
31
|
+
|
|
32
|
+
import DL_Modal from "./pages/Dialog/modal";
|
|
33
|
+
import DL_Alerts from "./pages/Dialog/alerts";
|
|
34
|
+
import DL_CustomAlert from "./pages/Dialog/custom-alert";
|
|
35
|
+
import DL_Swipe from "./pages/Dialog/swipe";
|
|
36
|
+
import DL_Card from "./pages/Dialog/card";
|
|
30
37
|
|
|
31
38
|
import PS_Preview from "./pages/PanelSystem/preview";
|
|
32
39
|
import PS_Tabbar from "./pages/PanelSystem/tabbar";
|
|
@@ -46,7 +53,7 @@ import ST_Tablet from "./pages/Stack/tablet";
|
|
|
46
53
|
|
|
47
54
|
import SH_Basics from "./pages/StickyHeader/basics";
|
|
48
55
|
|
|
49
|
-
import { FiGrid, FiLayers, FiColumns, FiMaximize2, FiBox, FiCpu, FiSmartphone, FiSidebar, FiNavigation, FiImage } from "react-icons/fi";
|
|
56
|
+
import { FiGrid, FiLayers, FiColumns, FiMaximize2, FiBox, FiCpu, FiSmartphone, FiSidebar, FiNavigation, FiImage, FiMessageSquare } from "react-icons/fi";
|
|
50
57
|
|
|
51
58
|
export type DemoPage = {
|
|
52
59
|
id: string;
|
|
@@ -85,6 +92,20 @@ export const demoCategories: DemoCategory[] = [
|
|
|
85
92
|
{ id: "basics", label: "Basics", path: "basics", element: <DR_Basics /> },
|
|
86
93
|
{ id: "menu", label: "Menu", path: "menu", element: <DR_Menu /> },
|
|
87
94
|
{ id: "animations", label: "Animations", path: "animations", element: <DR_Animations /> },
|
|
95
|
+
{ id: "swipe", label: "Swipe Gestures", path: "swipe", element: <DR_Swipe /> },
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: "dialog",
|
|
100
|
+
label: "Dialog",
|
|
101
|
+
icon: <FiMessageSquare />,
|
|
102
|
+
base: "/components/dialog",
|
|
103
|
+
pages: [
|
|
104
|
+
{ id: "modal", label: "Modal", path: "modal", element: <DL_Modal /> },
|
|
105
|
+
{ id: "alerts", label: "Alert / Confirm / Prompt", path: "alerts", element: <DL_Alerts /> },
|
|
106
|
+
{ id: "custom-alert", label: "Custom Alert Component", path: "custom-alert", element: <DL_CustomAlert /> },
|
|
107
|
+
{ id: "swipe", label: "Swipe Dismiss", path: "swipe", element: <DL_Swipe /> },
|
|
108
|
+
{ id: "card", label: "Card Expansion", path: "card", element: <DL_Card /> },
|
|
88
109
|
],
|
|
89
110
|
},
|
|
90
111
|
{
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Dialog entry point - Modal and alert/confirm/prompt dialogs
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*
|
|
5
|
+
* This is a subpath export entry point for `react-panel-layout/dialog`.
|
|
6
|
+
*
|
|
7
|
+
* ## Overview
|
|
8
|
+
* Dialog provides modal dialogs and imperative alert/confirm/prompt APIs
|
|
9
|
+
* using native HTML dialog element for proper accessibility and top-layer rendering.
|
|
10
|
+
*
|
|
11
|
+
* ## Installation
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { Modal, useDialog, DialogContainer } from "react-panel-layout/dialog";
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* ## Modal Usage
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const [isOpen, setIsOpen] = useState(false);
|
|
19
|
+
*
|
|
20
|
+
* <Modal
|
|
21
|
+
* visible={isOpen}
|
|
22
|
+
* onClose={() => setIsOpen(false)}
|
|
23
|
+
* header={{ title: "Settings" }}
|
|
24
|
+
* >
|
|
25
|
+
* <form>
|
|
26
|
+
* <input type="text" placeholder="Name" />
|
|
27
|
+
* <button type="submit">Save</button>
|
|
28
|
+
* </form>
|
|
29
|
+
* </Modal>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* ## useDialog Hook Usage
|
|
33
|
+
* ```tsx
|
|
34
|
+
* function MyComponent() {
|
|
35
|
+
* const { alert, confirm, prompt, Outlet } = useDialog();
|
|
36
|
+
*
|
|
37
|
+
* const handleClick = async () => {
|
|
38
|
+
* await alert("Hello!");
|
|
39
|
+
*
|
|
40
|
+
* const confirmed = await confirm({
|
|
41
|
+
* message: "Are you sure?",
|
|
42
|
+
* confirmLabel: "Yes",
|
|
43
|
+
* cancelLabel: "No",
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* if (confirmed) {
|
|
47
|
+
* const name = await prompt({
|
|
48
|
+
* message: "Enter your name:",
|
|
49
|
+
* defaultValue: "Anonymous",
|
|
50
|
+
* });
|
|
51
|
+
* console.log("Name:", name);
|
|
52
|
+
* }
|
|
53
|
+
* };
|
|
54
|
+
*
|
|
55
|
+
* return (
|
|
56
|
+
* <>
|
|
57
|
+
* <button onClick={handleClick}>Show dialogs</button>
|
|
58
|
+
* <Outlet />
|
|
59
|
+
* </>
|
|
60
|
+
* );
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
// Components
|
|
66
|
+
export { Modal } from "../modules/dialog/Modal.js";
|
|
67
|
+
export { DialogContainer } from "../modules/dialog/DialogContainer.js";
|
|
68
|
+
export { AlertDialog } from "../modules/dialog/AlertDialog.js";
|
|
69
|
+
|
|
70
|
+
// Hooks
|
|
71
|
+
export { useDialog } from "../modules/dialog/useDialog.js";
|
|
72
|
+
export { useDialogContainer } from "../modules/dialog/useDialogContainer.js";
|
|
73
|
+
|
|
74
|
+
// Types
|
|
75
|
+
export type {
|
|
76
|
+
ModalProps,
|
|
77
|
+
ModalHeader,
|
|
78
|
+
DialogContainerProps,
|
|
79
|
+
DialogTransitionMode,
|
|
80
|
+
AlertOptions,
|
|
81
|
+
ConfirmOptions,
|
|
82
|
+
PromptOptions,
|
|
83
|
+
AlertDialogProps,
|
|
84
|
+
UseDialogReturn,
|
|
85
|
+
} from "../modules/dialog/types.js";
|
|
@@ -1,158 +1,162 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Tests for gesture simulator utilities.
|
|
3
3
|
*/
|
|
4
|
-
/* eslint-disable no-restricted-globals, no-restricted-properties -- test utilities need vi for timing and mocks */
|
|
5
4
|
import {
|
|
6
5
|
createGestureSimulator,
|
|
7
6
|
createMockContainer,
|
|
8
7
|
createMockContainerRef,
|
|
9
8
|
} from "./createGestureSimulator.js";
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
type EventTracker = {
|
|
11
|
+
calls: ReadonlyArray<PointerEvent>;
|
|
12
|
+
handler: (event: Event) => void;
|
|
13
|
+
};
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const createEventTracker = (): EventTracker => {
|
|
16
|
+
const calls: PointerEvent[] = [];
|
|
17
|
+
const handler = (event: Event): void => {
|
|
18
|
+
calls.push(event as PointerEvent);
|
|
19
|
+
};
|
|
20
|
+
return { calls, handler };
|
|
21
|
+
};
|
|
19
22
|
|
|
23
|
+
describe("createGestureSimulator", () => {
|
|
20
24
|
describe("pointerDown", () => {
|
|
21
25
|
it("dispatches pointerdown event", () => {
|
|
22
26
|
const simulator = createGestureSimulator();
|
|
23
|
-
const
|
|
24
|
-
document.addEventListener("pointerdown", handler);
|
|
27
|
+
const tracker = createEventTracker();
|
|
28
|
+
document.addEventListener("pointerdown", tracker.handler);
|
|
25
29
|
|
|
26
30
|
simulator.pointerDown(100, 200);
|
|
27
31
|
|
|
28
|
-
expect(
|
|
29
|
-
const event =
|
|
32
|
+
expect(tracker.calls).toHaveLength(1);
|
|
33
|
+
const event = tracker.calls[0] as PointerEvent;
|
|
30
34
|
expect(event.clientX).toBe(100);
|
|
31
35
|
expect(event.clientY).toBe(200);
|
|
32
36
|
expect(event.pointerType).toBe("touch");
|
|
33
37
|
expect(event.pointerId).toBe(1);
|
|
34
38
|
|
|
35
|
-
document.removeEventListener("pointerdown", handler);
|
|
39
|
+
document.removeEventListener("pointerdown", tracker.handler);
|
|
36
40
|
});
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
describe("pointerMove", () => {
|
|
40
44
|
it("dispatches pointermove event after pointerdown", () => {
|
|
41
45
|
const simulator = createGestureSimulator();
|
|
42
|
-
const
|
|
43
|
-
document.addEventListener("pointermove", handler);
|
|
46
|
+
const tracker = createEventTracker();
|
|
47
|
+
document.addEventListener("pointermove", tracker.handler);
|
|
44
48
|
|
|
45
49
|
simulator.pointerDown(100, 100);
|
|
46
50
|
simulator.pointerMove(150, 120);
|
|
47
51
|
|
|
48
|
-
expect(
|
|
49
|
-
const event =
|
|
52
|
+
expect(tracker.calls).toHaveLength(1);
|
|
53
|
+
const event = tracker.calls[0] as PointerEvent;
|
|
50
54
|
expect(event.clientX).toBe(150);
|
|
51
55
|
expect(event.clientY).toBe(120);
|
|
52
56
|
|
|
53
|
-
document.removeEventListener("pointermove", handler);
|
|
57
|
+
document.removeEventListener("pointermove", tracker.handler);
|
|
54
58
|
});
|
|
55
59
|
|
|
56
60
|
it("does not dispatch pointermove if pointer is not down", () => {
|
|
57
61
|
const simulator = createGestureSimulator();
|
|
58
|
-
const
|
|
59
|
-
document.addEventListener("pointermove", handler);
|
|
62
|
+
const tracker = createEventTracker();
|
|
63
|
+
document.addEventListener("pointermove", tracker.handler);
|
|
60
64
|
|
|
61
65
|
simulator.pointerMove(150, 120);
|
|
62
66
|
|
|
63
|
-
expect(
|
|
67
|
+
expect(tracker.calls).toHaveLength(0);
|
|
64
68
|
|
|
65
|
-
document.removeEventListener("pointermove", handler);
|
|
69
|
+
document.removeEventListener("pointermove", tracker.handler);
|
|
66
70
|
});
|
|
67
71
|
});
|
|
68
72
|
|
|
69
73
|
describe("pointerUp", () => {
|
|
70
74
|
it("dispatches pointerup event", () => {
|
|
71
75
|
const simulator = createGestureSimulator();
|
|
72
|
-
const
|
|
73
|
-
document.addEventListener("pointerup", handler);
|
|
76
|
+
const tracker = createEventTracker();
|
|
77
|
+
document.addEventListener("pointerup", tracker.handler);
|
|
74
78
|
|
|
75
79
|
simulator.pointerDown(100, 100);
|
|
76
80
|
simulator.pointerUp();
|
|
77
81
|
|
|
78
|
-
expect(
|
|
82
|
+
expect(tracker.calls).toHaveLength(1);
|
|
79
83
|
|
|
80
|
-
document.removeEventListener("pointerup", handler);
|
|
84
|
+
document.removeEventListener("pointerup", tracker.handler);
|
|
81
85
|
});
|
|
82
86
|
|
|
83
87
|
it("does not dispatch pointerup if pointer is not down", () => {
|
|
84
88
|
const simulator = createGestureSimulator();
|
|
85
|
-
const
|
|
86
|
-
document.addEventListener("pointerup", handler);
|
|
89
|
+
const tracker = createEventTracker();
|
|
90
|
+
document.addEventListener("pointerup", tracker.handler);
|
|
87
91
|
|
|
88
92
|
simulator.pointerUp();
|
|
89
93
|
|
|
90
|
-
expect(
|
|
94
|
+
expect(tracker.calls).toHaveLength(0);
|
|
91
95
|
|
|
92
|
-
document.removeEventListener("pointerup", handler);
|
|
96
|
+
document.removeEventListener("pointerup", tracker.handler);
|
|
93
97
|
});
|
|
94
98
|
});
|
|
95
99
|
|
|
96
100
|
describe("swipe", () => {
|
|
97
101
|
it("dispatches complete swipe sequence", () => {
|
|
98
102
|
const simulator = createGestureSimulator();
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const
|
|
103
|
+
const downTracker = createEventTracker();
|
|
104
|
+
const moveTracker = createEventTracker();
|
|
105
|
+
const upTracker = createEventTracker();
|
|
102
106
|
|
|
103
|
-
document.addEventListener("pointerdown",
|
|
104
|
-
document.addEventListener("pointermove",
|
|
105
|
-
document.addEventListener("pointerup",
|
|
107
|
+
document.addEventListener("pointerdown", downTracker.handler);
|
|
108
|
+
document.addEventListener("pointermove", moveTracker.handler);
|
|
109
|
+
document.addEventListener("pointerup", upTracker.handler);
|
|
106
110
|
|
|
107
111
|
simulator.swipe({ x: 100, y: 100 }, { x: 200, y: 100 }, 5);
|
|
108
112
|
|
|
109
|
-
expect(
|
|
110
|
-
expect(
|
|
111
|
-
expect(
|
|
113
|
+
expect(downTracker.calls).toHaveLength(1);
|
|
114
|
+
expect(moveTracker.calls).toHaveLength(5); // 5 steps
|
|
115
|
+
expect(upTracker.calls).toHaveLength(1);
|
|
112
116
|
|
|
113
117
|
// Check intermediate positions
|
|
114
|
-
const lastMove =
|
|
118
|
+
const lastMove = moveTracker.calls[4] as PointerEvent;
|
|
115
119
|
expect(lastMove.clientX).toBe(200);
|
|
116
120
|
expect(lastMove.clientY).toBe(100);
|
|
117
121
|
|
|
118
|
-
document.removeEventListener("pointerdown",
|
|
119
|
-
document.removeEventListener("pointermove",
|
|
120
|
-
document.removeEventListener("pointerup",
|
|
122
|
+
document.removeEventListener("pointerdown", downTracker.handler);
|
|
123
|
+
document.removeEventListener("pointermove", moveTracker.handler);
|
|
124
|
+
document.removeEventListener("pointerup", upTracker.handler);
|
|
121
125
|
});
|
|
122
126
|
});
|
|
123
127
|
|
|
124
128
|
describe("edgeSwipe", () => {
|
|
125
129
|
it("simulates left edge swipe", () => {
|
|
126
130
|
const simulator = createGestureSimulator();
|
|
127
|
-
const
|
|
128
|
-
const
|
|
131
|
+
const downTracker = createEventTracker();
|
|
132
|
+
const upTracker = createEventTracker();
|
|
129
133
|
|
|
130
|
-
document.addEventListener("pointerdown",
|
|
131
|
-
document.addEventListener("pointerup",
|
|
134
|
+
document.addEventListener("pointerdown", downTracker.handler);
|
|
135
|
+
document.addEventListener("pointerup", upTracker.handler);
|
|
132
136
|
|
|
133
137
|
simulator.edgeSwipe("left", 100, 300);
|
|
134
138
|
|
|
135
|
-
expect(
|
|
136
|
-
const downEvent =
|
|
139
|
+
expect(downTracker.calls).toHaveLength(1);
|
|
140
|
+
const downEvent = downTracker.calls[0] as PointerEvent;
|
|
137
141
|
expect(downEvent.clientX).toBe(10); // Edge offset
|
|
138
|
-
expect(
|
|
142
|
+
expect(upTracker.calls).toHaveLength(1);
|
|
139
143
|
|
|
140
|
-
document.removeEventListener("pointerdown",
|
|
141
|
-
document.removeEventListener("pointerup",
|
|
144
|
+
document.removeEventListener("pointerdown", downTracker.handler);
|
|
145
|
+
document.removeEventListener("pointerup", upTracker.handler);
|
|
142
146
|
});
|
|
143
147
|
|
|
144
148
|
it("simulates right edge swipe", () => {
|
|
145
149
|
const simulator = createGestureSimulator();
|
|
146
|
-
const
|
|
150
|
+
const downTracker = createEventTracker();
|
|
147
151
|
|
|
148
|
-
document.addEventListener("pointerdown",
|
|
152
|
+
document.addEventListener("pointerdown", downTracker.handler);
|
|
149
153
|
|
|
150
154
|
simulator.edgeSwipe("right", 100, 300);
|
|
151
155
|
|
|
152
|
-
const downEvent =
|
|
156
|
+
const downEvent = downTracker.calls[0] as PointerEvent;
|
|
153
157
|
expect(downEvent.clientX).toBe(290); // containerSize - edgeOffset
|
|
154
158
|
|
|
155
|
-
document.removeEventListener("pointerdown",
|
|
159
|
+
document.removeEventListener("pointerdown", downTracker.handler);
|
|
156
160
|
});
|
|
157
161
|
});
|
|
158
162
|
|
|
@@ -172,28 +176,28 @@ describe("createGestureSimulator", () => {
|
|
|
172
176
|
describe("options", () => {
|
|
173
177
|
it("respects custom pointer type", () => {
|
|
174
178
|
const simulator = createGestureSimulator({ pointerType: "mouse" });
|
|
175
|
-
const
|
|
176
|
-
document.addEventListener("pointerdown", handler);
|
|
179
|
+
const tracker = createEventTracker();
|
|
180
|
+
document.addEventListener("pointerdown", tracker.handler);
|
|
177
181
|
|
|
178
182
|
simulator.pointerDown(100, 100);
|
|
179
183
|
|
|
180
|
-
const event =
|
|
184
|
+
const event = tracker.calls[0] as PointerEvent;
|
|
181
185
|
expect(event.pointerType).toBe("mouse");
|
|
182
186
|
|
|
183
|
-
document.removeEventListener("pointerdown", handler);
|
|
187
|
+
document.removeEventListener("pointerdown", tracker.handler);
|
|
184
188
|
});
|
|
185
189
|
|
|
186
190
|
it("respects custom pointer ID", () => {
|
|
187
191
|
const simulator = createGestureSimulator({ pointerId: 5 });
|
|
188
|
-
const
|
|
189
|
-
document.addEventListener("pointerdown", handler);
|
|
192
|
+
const tracker = createEventTracker();
|
|
193
|
+
document.addEventListener("pointerdown", tracker.handler);
|
|
190
194
|
|
|
191
195
|
simulator.pointerDown(100, 100);
|
|
192
196
|
|
|
193
|
-
const event =
|
|
197
|
+
const event = tracker.calls[0] as PointerEvent;
|
|
194
198
|
expect(event.pointerId).toBe(5);
|
|
195
199
|
|
|
196
|
-
document.removeEventListener("pointerdown", handler);
|
|
200
|
+
document.removeEventListener("pointerdown", tracker.handler);
|
|
197
201
|
});
|
|
198
202
|
});
|
|
199
203
|
});
|