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
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import * as React from "react";
|
|
11
11
|
import { useSwipeContentTransform } from "../../hooks/useSwipeContentTransform.js";
|
|
12
|
-
import
|
|
12
|
+
import { useOperationContinuity } from "../../hooks/useOperationContinuity.js";
|
|
13
|
+
import type { ContinuousOperationState, GestureAxis } from "../../hooks/gesture/types.js";
|
|
13
14
|
import type { StackDisplayMode } from "./types.js";
|
|
14
15
|
import {
|
|
15
16
|
computeActiveTargetPx,
|
|
@@ -27,11 +28,6 @@ const DEFAULT_ANIMATION_DURATION = 300;
|
|
|
27
28
|
*/
|
|
28
29
|
const STACK_SCALE_FACTOR = 0.05;
|
|
29
30
|
|
|
30
|
-
/**
|
|
31
|
-
* Offset percentage per depth level for "stack" display mode.
|
|
32
|
-
*/
|
|
33
|
-
const STACK_OFFSET_PERCENT = 5;
|
|
34
|
-
|
|
35
31
|
/**
|
|
36
32
|
* Maximum dimming opacity for behind panels in iOS-style navigation.
|
|
37
33
|
*/
|
|
@@ -39,6 +35,9 @@ const MAX_DIM_OPACITY = 0.1;
|
|
|
39
35
|
|
|
40
36
|
/**
|
|
41
37
|
* Props for SwipeStackContent component.
|
|
38
|
+
*
|
|
39
|
+
* This component accepts ContinuousOperationState, meaning it responds uniformly
|
|
40
|
+
* to any continuous operation (whether human gesture or system animation).
|
|
42
41
|
*/
|
|
43
42
|
export type SwipeStackContentProps = {
|
|
44
43
|
/** Panel ID */
|
|
@@ -49,8 +48,8 @@ export type SwipeStackContentProps = {
|
|
|
49
48
|
navigationDepth: number;
|
|
50
49
|
/** Whether this panel is currently active */
|
|
51
50
|
isActive: boolean;
|
|
52
|
-
/**
|
|
53
|
-
|
|
51
|
+
/** Continuous operation state (from gesture input or animation system) */
|
|
52
|
+
operationState: ContinuousOperationState;
|
|
54
53
|
/** Container size in pixels (width for horizontal, height for vertical) */
|
|
55
54
|
containerSize: number;
|
|
56
55
|
/** Gesture axis. @default "horizontal" */
|
|
@@ -96,13 +95,13 @@ const BASE_STYLE: React.CSSProperties = {
|
|
|
96
95
|
};
|
|
97
96
|
|
|
98
97
|
/**
|
|
99
|
-
* Get displacement from
|
|
98
|
+
* Get displacement from operation state for the given axis.
|
|
100
99
|
*/
|
|
101
|
-
const getAxisDisplacement = (
|
|
102
|
-
if (
|
|
100
|
+
const getAxisDisplacement = (state: ContinuousOperationState, axis: GestureAxis): number => {
|
|
101
|
+
if (state.phase === "idle") {
|
|
103
102
|
return 0;
|
|
104
103
|
}
|
|
105
|
-
return axis === "horizontal" ?
|
|
104
|
+
return axis === "horizontal" ? state.displacement.x : state.displacement.y;
|
|
106
105
|
};
|
|
107
106
|
|
|
108
107
|
/**
|
|
@@ -136,7 +135,7 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
136
135
|
depth,
|
|
137
136
|
navigationDepth,
|
|
138
137
|
isActive,
|
|
139
|
-
|
|
138
|
+
operationState,
|
|
140
139
|
containerSize,
|
|
141
140
|
axis = "horizontal",
|
|
142
141
|
behindOffset = DEFAULT_BEHIND_OFFSET,
|
|
@@ -148,23 +147,27 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
148
147
|
children,
|
|
149
148
|
}) => {
|
|
150
149
|
const elementRef = React.useRef<HTMLDivElement>(null);
|
|
151
|
-
const isFirstMountRef = React.useRef<boolean>(true);
|
|
152
150
|
|
|
153
|
-
const displacement = getAxisDisplacement(
|
|
154
|
-
const
|
|
151
|
+
const displacement = getAxisDisplacement(operationState, axis);
|
|
152
|
+
const isOperating = operationState.phase === "operating";
|
|
155
153
|
|
|
156
154
|
// Determine panel role
|
|
157
155
|
const role = determineSwipePanelRole(depth, navigationDepth);
|
|
158
156
|
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
// Maintain role continuity during swipe operations.
|
|
158
|
+
// When navigation changes before the gesture ends (e.g., role changes from
|
|
159
|
+
// "behind" to "active"), we keep using the previous role for position
|
|
160
|
+
// calculations to prevent visual jumps.
|
|
161
|
+
// changedDuringOperation tells us if the role changed during the operation,
|
|
162
|
+
// which we use to skip backward target change animation (over-swipe case).
|
|
163
|
+
const { value: effectiveRole, changedDuringOperation } = useOperationContinuity(
|
|
164
|
+
role,
|
|
165
|
+
displacement > 0,
|
|
166
|
+
);
|
|
164
167
|
|
|
165
|
-
// Compute target position based on role
|
|
168
|
+
// Compute target position based on effective role
|
|
166
169
|
const targetPx = React.useMemo(() => {
|
|
167
|
-
switch (
|
|
170
|
+
switch (effectiveRole) {
|
|
168
171
|
case "active":
|
|
169
172
|
// Active panel rests at 0
|
|
170
173
|
return 0;
|
|
@@ -175,7 +178,7 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
175
178
|
// Hidden panels are off-screen
|
|
176
179
|
return containerSize;
|
|
177
180
|
}
|
|
178
|
-
}, [
|
|
181
|
+
}, [effectiveRole, behindOffset, containerSize]);
|
|
179
182
|
|
|
180
183
|
// Compute displacement for this panel
|
|
181
184
|
const panelDisplacement = React.useMemo(() => {
|
|
@@ -183,7 +186,7 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
183
186
|
return 0;
|
|
184
187
|
}
|
|
185
188
|
|
|
186
|
-
switch (
|
|
189
|
+
switch (effectiveRole) {
|
|
187
190
|
case "active":
|
|
188
191
|
// Active panel follows finger directly
|
|
189
192
|
return computeActiveTargetPx(displacement);
|
|
@@ -196,15 +199,17 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
196
199
|
case "hidden":
|
|
197
200
|
return 0;
|
|
198
201
|
}
|
|
199
|
-
}, [
|
|
202
|
+
}, [effectiveRole, displacement, containerSize, behindOffset]);
|
|
200
203
|
|
|
201
204
|
// Compute initial position for push animation
|
|
202
205
|
// When animateOnMount is true and panel is first mounted as "active",
|
|
203
206
|
// it should animate in from off-screen
|
|
204
207
|
// Root panel (depth=0) should not animate on mount
|
|
208
|
+
// Note: useSwipeContentTransform handles first-mount tracking internally,
|
|
209
|
+
// so we just declare the initial position; the hook consumes it only once.
|
|
205
210
|
const initialPx = React.useMemo(() => {
|
|
206
|
-
if (!
|
|
207
|
-
return undefined;
|
|
211
|
+
if (!animateOnMount) {
|
|
212
|
+
return undefined;
|
|
208
213
|
}
|
|
209
214
|
if (role === "active" && depth > 0) {
|
|
210
215
|
// New active panel (not root): start from off-screen right
|
|
@@ -212,14 +217,14 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
212
217
|
}
|
|
213
218
|
// Root panel or other roles: start at their natural position
|
|
214
219
|
return undefined;
|
|
215
|
-
}, [
|
|
220
|
+
}, [animateOnMount, role, depth, containerSize]);
|
|
216
221
|
|
|
217
222
|
// Use shared transform hook for DOM manipulation
|
|
218
223
|
const { isAnimating } = useSwipeContentTransform({
|
|
219
224
|
elementRef,
|
|
220
225
|
targetPx,
|
|
221
226
|
displacement: panelDisplacement,
|
|
222
|
-
|
|
227
|
+
isOperating,
|
|
223
228
|
axis,
|
|
224
229
|
animationDuration,
|
|
225
230
|
containerSize,
|
|
@@ -227,6 +232,11 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
227
232
|
animateOnTargetChange: true,
|
|
228
233
|
// For push animation: start from off-screen
|
|
229
234
|
initialPx,
|
|
235
|
+
// Skip backward animation if role changed during the operation.
|
|
236
|
+
// This handles over-swipe where panel moves beyond 100% and needs to snap back.
|
|
237
|
+
// useSwipeContentTransform allows forward animations (normal swipe-to-complete)
|
|
238
|
+
// but skips backward animations (over-swipe snap).
|
|
239
|
+
skipTargetChangeAnimation: changedDuringOperation,
|
|
230
240
|
});
|
|
231
241
|
|
|
232
242
|
// Compute visibility
|
|
@@ -234,7 +244,7 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
234
244
|
depth,
|
|
235
245
|
navigationDepth,
|
|
236
246
|
isActive,
|
|
237
|
-
|
|
247
|
+
isOperating,
|
|
238
248
|
isAnimating,
|
|
239
249
|
});
|
|
240
250
|
|
|
@@ -309,7 +319,7 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
309
319
|
|
|
310
320
|
// Compute shadow for active panel
|
|
311
321
|
// Shadow is shown on panels at depth > 0 when they're active or animating
|
|
312
|
-
const shouldShowShadow = showShadow
|
|
322
|
+
const shouldShowShadow = showShadow ? depth > 0 && role === "active" : false;
|
|
313
323
|
|
|
314
324
|
// Static style - transform is handled entirely by useSwipeContentTransform
|
|
315
325
|
// to ensure smooth animations
|
|
@@ -349,7 +359,7 @@ export const SwipeStackContent: React.FC<SwipeStackContentProps> = React.memo(
|
|
|
349
359
|
style={staticStyle}
|
|
350
360
|
>
|
|
351
361
|
{children}
|
|
352
|
-
{dimmingStyle != null
|
|
362
|
+
{dimmingStyle != null ? <div style={dimmingStyle} data-dimming-overlay /> : null}
|
|
353
363
|
</div>
|
|
354
364
|
);
|
|
355
365
|
},
|
|
@@ -3,21 +3,19 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { render } from "@testing-library/react";
|
|
5
5
|
import { SwipeStackOutlet } from "./SwipeStackOutlet.js";
|
|
6
|
-
import type {
|
|
6
|
+
import type { ContinuousOperationState } from "../../hooks/gesture/types.js";
|
|
7
7
|
import type { StackPanel, StackNavigationState } from "./types.js";
|
|
8
8
|
|
|
9
|
-
const IDLE_STATE:
|
|
9
|
+
const IDLE_STATE: ContinuousOperationState = {
|
|
10
10
|
phase: "idle",
|
|
11
11
|
displacement: { x: 0, y: 0 },
|
|
12
12
|
velocity: { x: 0, y: 0 },
|
|
13
|
-
direction: 0,
|
|
14
13
|
};
|
|
15
14
|
|
|
16
|
-
const
|
|
17
|
-
phase: "
|
|
15
|
+
const createOperatingState = (displacementX: number): ContinuousOperationState => ({
|
|
16
|
+
phase: "operating",
|
|
18
17
|
displacement: { x: displacementX, y: 0 },
|
|
19
18
|
velocity: { x: 0.5, y: 0 },
|
|
20
|
-
direction: displacementX > 0 ? 1 : displacementX < 0 ? -1 : 0,
|
|
21
19
|
});
|
|
22
20
|
|
|
23
21
|
const createPanels = (): StackPanel[] => [
|
|
@@ -40,7 +38,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
40
38
|
<SwipeStackOutlet
|
|
41
39
|
panels={createPanels()}
|
|
42
40
|
navigationState={navigationState}
|
|
43
|
-
|
|
41
|
+
operationState={IDLE_STATE}
|
|
44
42
|
containerSize={400}
|
|
45
43
|
/>,
|
|
46
44
|
);
|
|
@@ -61,7 +59,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
61
59
|
<SwipeStackOutlet
|
|
62
60
|
panels={createPanels()}
|
|
63
61
|
navigationState={navigationState}
|
|
64
|
-
|
|
62
|
+
operationState={IDLE_STATE}
|
|
65
63
|
containerSize={400}
|
|
66
64
|
/>,
|
|
67
65
|
);
|
|
@@ -85,7 +83,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
85
83
|
<SwipeStackOutlet
|
|
86
84
|
panels={createPanels()}
|
|
87
85
|
navigationState={navigationState}
|
|
88
|
-
|
|
86
|
+
operationState={IDLE_STATE}
|
|
89
87
|
containerSize={400}
|
|
90
88
|
/>,
|
|
91
89
|
);
|
|
@@ -109,7 +107,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
109
107
|
<SwipeStackOutlet
|
|
110
108
|
panels={createPanels()}
|
|
111
109
|
navigationState={navigationState}
|
|
112
|
-
|
|
110
|
+
operationState={IDLE_STATE}
|
|
113
111
|
containerSize={400}
|
|
114
112
|
/>,
|
|
115
113
|
);
|
|
@@ -131,13 +129,13 @@ describe("SwipeStackOutlet", () => {
|
|
|
131
129
|
revealDepth: null,
|
|
132
130
|
};
|
|
133
131
|
|
|
134
|
-
const swipeState =
|
|
132
|
+
const swipeState = createOperatingState(200);
|
|
135
133
|
|
|
136
134
|
const { container, rerender } = render(
|
|
137
135
|
<SwipeStackOutlet
|
|
138
136
|
panels={createPanels()}
|
|
139
137
|
navigationState={navigationState}
|
|
140
|
-
|
|
138
|
+
operationState={IDLE_STATE}
|
|
141
139
|
containerSize={400}
|
|
142
140
|
/>,
|
|
143
141
|
);
|
|
@@ -147,7 +145,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
147
145
|
<SwipeStackOutlet
|
|
148
146
|
panels={createPanels()}
|
|
149
147
|
navigationState={navigationState}
|
|
150
|
-
|
|
148
|
+
operationState={swipeState}
|
|
151
149
|
containerSize={400}
|
|
152
150
|
/>,
|
|
153
151
|
);
|
|
@@ -185,7 +183,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
185
183
|
<SwipeStackOutlet
|
|
186
184
|
panels={createPanels()}
|
|
187
185
|
navigationState={navigationState}
|
|
188
|
-
|
|
186
|
+
operationState={IDLE_STATE}
|
|
189
187
|
containerSize={400}
|
|
190
188
|
getCachedContent={getCachedContent}
|
|
191
189
|
/>,
|
|
@@ -210,7 +208,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
210
208
|
<SwipeStackOutlet
|
|
211
209
|
panels={createPanels()}
|
|
212
210
|
navigationState={navigationState}
|
|
213
|
-
|
|
211
|
+
operationState={IDLE_STATE}
|
|
214
212
|
containerSize={400}
|
|
215
213
|
getCachedContent={getCachedContent}
|
|
216
214
|
/>,
|
|
@@ -233,7 +231,7 @@ describe("SwipeStackOutlet", () => {
|
|
|
233
231
|
<SwipeStackOutlet
|
|
234
232
|
panels={createPanels()}
|
|
235
233
|
navigationState={navigationState}
|
|
236
|
-
|
|
234
|
+
operationState={IDLE_STATE}
|
|
237
235
|
containerSize={400}
|
|
238
236
|
/>,
|
|
239
237
|
);
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as React from "react";
|
|
8
8
|
import { SwipeStackContent } from "./SwipeStackContent.js";
|
|
9
|
-
import type {
|
|
9
|
+
import type { ContinuousOperationState } from "../../hooks/gesture/types.js";
|
|
10
10
|
import type { StackPanel, StackNavigationState } from "./types.js";
|
|
11
11
|
|
|
12
12
|
const DEFAULT_ANIMATION_DURATION = 300;
|
|
@@ -19,8 +19,8 @@ export type SwipeStackOutletProps = {
|
|
|
19
19
|
panels: ReadonlyArray<StackPanel>;
|
|
20
20
|
/** Current navigation state */
|
|
21
21
|
navigationState: StackNavigationState;
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/** Continuous operation state (from gesture input or animation system) */
|
|
23
|
+
operationState: ContinuousOperationState;
|
|
24
24
|
/** Container size in pixels (width for horizontal swipe) */
|
|
25
25
|
containerSize: number;
|
|
26
26
|
/** Function to get cached content for a panel */
|
|
@@ -121,7 +121,7 @@ function getVisiblePanels(
|
|
|
121
121
|
* <SwipeStackOutlet
|
|
122
122
|
* panels={navigation.panels}
|
|
123
123
|
* navigationState={navigation.state}
|
|
124
|
-
*
|
|
124
|
+
* operationState={toContinuousOperationState(swipeInput.inputState)}
|
|
125
125
|
* containerSize={containerWidth}
|
|
126
126
|
* />
|
|
127
127
|
* </div>
|
|
@@ -132,7 +132,7 @@ export const SwipeStackOutlet: React.FC<SwipeStackOutletProps> = React.memo(
|
|
|
132
132
|
({
|
|
133
133
|
panels,
|
|
134
134
|
navigationState,
|
|
135
|
-
|
|
135
|
+
operationState,
|
|
136
136
|
containerSize,
|
|
137
137
|
getCachedContent,
|
|
138
138
|
behindOffset,
|
|
@@ -202,7 +202,7 @@ export const SwipeStackOutlet: React.FC<SwipeStackOutletProps> = React.memo(
|
|
|
202
202
|
depth={depth}
|
|
203
203
|
navigationDepth={navigationState.depth}
|
|
204
204
|
isActive={isActive}
|
|
205
|
-
|
|
205
|
+
operationState={operationState}
|
|
206
206
|
containerSize={containerSize}
|
|
207
207
|
behindOffset={behindOffset}
|
|
208
208
|
animateOnMount={animateOnMount}
|
|
@@ -106,7 +106,7 @@ describe("computeSwipeVisibility", () => {
|
|
|
106
106
|
depth: 2,
|
|
107
107
|
navigationDepth: 2,
|
|
108
108
|
isActive: true,
|
|
109
|
-
|
|
109
|
+
isOperating: false,
|
|
110
110
|
isAnimating: false,
|
|
111
111
|
}),
|
|
112
112
|
).toBe(true);
|
|
@@ -118,7 +118,7 @@ describe("computeSwipeVisibility", () => {
|
|
|
118
118
|
depth: 1,
|
|
119
119
|
navigationDepth: 2,
|
|
120
120
|
isActive: false,
|
|
121
|
-
|
|
121
|
+
isOperating: true,
|
|
122
122
|
isAnimating: false,
|
|
123
123
|
}),
|
|
124
124
|
).toBe(true);
|
|
@@ -130,7 +130,7 @@ describe("computeSwipeVisibility", () => {
|
|
|
130
130
|
depth: 1,
|
|
131
131
|
navigationDepth: 2,
|
|
132
132
|
isActive: false,
|
|
133
|
-
|
|
133
|
+
isOperating: false,
|
|
134
134
|
isAnimating: true,
|
|
135
135
|
}),
|
|
136
136
|
).toBe(true);
|
|
@@ -142,7 +142,7 @@ describe("computeSwipeVisibility", () => {
|
|
|
142
142
|
depth: 1,
|
|
143
143
|
navigationDepth: 2,
|
|
144
144
|
isActive: false,
|
|
145
|
-
|
|
145
|
+
isOperating: false,
|
|
146
146
|
isAnimating: false,
|
|
147
147
|
}),
|
|
148
148
|
).toBe(false);
|
|
@@ -154,7 +154,7 @@ describe("computeSwipeVisibility", () => {
|
|
|
154
154
|
depth: 0,
|
|
155
155
|
navigationDepth: 2,
|
|
156
156
|
isActive: false,
|
|
157
|
-
|
|
157
|
+
isOperating: true,
|
|
158
158
|
isAnimating: false,
|
|
159
159
|
}),
|
|
160
160
|
).toBe(false);
|
|
@@ -85,7 +85,7 @@ export type ComputeSwipeVisibilityInput = {
|
|
|
85
85
|
/** Whether this panel is currently active */
|
|
86
86
|
isActive: boolean;
|
|
87
87
|
/** Whether swipe gesture is active */
|
|
88
|
-
|
|
88
|
+
isOperating: boolean;
|
|
89
89
|
/** Whether snap-back animation is running */
|
|
90
90
|
isAnimating: boolean;
|
|
91
91
|
};
|
|
@@ -100,7 +100,7 @@ export type ComputeSwipeVisibilityInput = {
|
|
|
100
100
|
* @returns true if panel should be visible
|
|
101
101
|
*/
|
|
102
102
|
export function computeSwipeVisibility(input: ComputeSwipeVisibilityInput): boolean {
|
|
103
|
-
const { depth, navigationDepth, isActive,
|
|
103
|
+
const { depth, navigationDepth, isActive, isOperating, isAnimating } = input;
|
|
104
104
|
|
|
105
105
|
// Active panel is always visible
|
|
106
106
|
if (isActive) {
|
|
@@ -110,7 +110,7 @@ export function computeSwipeVisibility(input: ComputeSwipeVisibilityInput): bool
|
|
|
110
110
|
// Behind panel (one level back) is visible during swipe or animation
|
|
111
111
|
const isBehindPanel = depth === navigationDepth - 1;
|
|
112
112
|
if (isBehindPanel) {
|
|
113
|
-
if (
|
|
113
|
+
if (isOperating) {
|
|
114
114
|
return true;
|
|
115
115
|
}
|
|
116
116
|
if (isAnimating) {
|