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
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Tests for drawerStyles utilities.
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
getPlacementStyle,
|
|
6
|
+
getOpenTransform,
|
|
7
|
+
getClosedTransform,
|
|
8
|
+
computeTransitionValue,
|
|
9
|
+
computeBackdropTransition,
|
|
10
|
+
isHorizontalPlacement,
|
|
11
|
+
formatDimension,
|
|
12
|
+
computeEdgeZoneStyle,
|
|
13
|
+
} from "./drawerStyles.js";
|
|
14
|
+
|
|
15
|
+
describe("drawerStyles", () => {
|
|
16
|
+
describe("getPlacementStyle", () => {
|
|
17
|
+
it("returns correct style for left placement", () => {
|
|
18
|
+
const style = getPlacementStyle("left");
|
|
19
|
+
expect(style.left).toBe(0);
|
|
20
|
+
expect(style.top).toBe(0);
|
|
21
|
+
expect(style.bottom).toBe(0);
|
|
22
|
+
expect(style.transform).toBe("translateX(-100%)");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("returns correct style for right placement", () => {
|
|
26
|
+
const style = getPlacementStyle("right");
|
|
27
|
+
expect(style.right).toBe(0);
|
|
28
|
+
expect(style.top).toBe(0);
|
|
29
|
+
expect(style.bottom).toBe(0);
|
|
30
|
+
expect(style.transform).toBe("translateX(100%)");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("returns correct style for top placement", () => {
|
|
34
|
+
const style = getPlacementStyle("top");
|
|
35
|
+
expect(style.top).toBe(0);
|
|
36
|
+
expect(style.left).toBe(0);
|
|
37
|
+
expect(style.right).toBe(0);
|
|
38
|
+
expect(style.transform).toBe("translateY(-100%)");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("returns correct style for bottom placement", () => {
|
|
42
|
+
const style = getPlacementStyle("bottom");
|
|
43
|
+
expect(style.bottom).toBe(0);
|
|
44
|
+
expect(style.left).toBe(0);
|
|
45
|
+
expect(style.right).toBe(0);
|
|
46
|
+
expect(style.transform).toBe("translateY(100%)");
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("getOpenTransform", () => {
|
|
51
|
+
it("returns translateX(0) for horizontal placements", () => {
|
|
52
|
+
expect(getOpenTransform("left")).toBe("translateX(0)");
|
|
53
|
+
expect(getOpenTransform("right")).toBe("translateX(0)");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("returns translateY(0) for vertical placements", () => {
|
|
57
|
+
expect(getOpenTransform("top")).toBe("translateY(0)");
|
|
58
|
+
expect(getOpenTransform("bottom")).toBe("translateY(0)");
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("getClosedTransform", () => {
|
|
63
|
+
it("returns correct closed transform for each placement", () => {
|
|
64
|
+
expect(getClosedTransform("left")).toBe("translateX(-100%)");
|
|
65
|
+
expect(getClosedTransform("right")).toBe("translateX(100%)");
|
|
66
|
+
expect(getClosedTransform("top")).toBe("translateY(-100%)");
|
|
67
|
+
expect(getClosedTransform("bottom")).toBe("translateY(100%)");
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("computeTransitionValue", () => {
|
|
72
|
+
it("returns undefined when mode is none", () => {
|
|
73
|
+
expect(computeTransitionValue("none", undefined, undefined)).toBeUndefined();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("returns transition with defaults when no values provided", () => {
|
|
77
|
+
const result = computeTransitionValue(undefined, undefined, undefined);
|
|
78
|
+
expect(result).toContain("transform");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("uses provided duration and easing", () => {
|
|
82
|
+
const result = computeTransitionValue("css", "300ms", "ease-in-out");
|
|
83
|
+
expect(result).toBe("transform 300ms ease-in-out");
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe("computeBackdropTransition", () => {
|
|
88
|
+
it("returns undefined when mode is none", () => {
|
|
89
|
+
expect(computeBackdropTransition("none", undefined)).toBeUndefined();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("returns opacity transition with defaults", () => {
|
|
93
|
+
const result = computeBackdropTransition(undefined, undefined);
|
|
94
|
+
expect(result).toContain("opacity");
|
|
95
|
+
expect(result).toContain("220ms");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("uses provided duration", () => {
|
|
99
|
+
const result = computeBackdropTransition("css", "400ms");
|
|
100
|
+
expect(result).toBe("opacity 400ms ease");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe("isHorizontalPlacement", () => {
|
|
105
|
+
it("returns true for left and right", () => {
|
|
106
|
+
expect(isHorizontalPlacement("left")).toBe(true);
|
|
107
|
+
expect(isHorizontalPlacement("right")).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("returns false for top and bottom", () => {
|
|
111
|
+
expect(isHorizontalPlacement("top")).toBe(false);
|
|
112
|
+
expect(isHorizontalPlacement("bottom")).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("formatDimension", () => {
|
|
117
|
+
it("returns undefined for undefined input", () => {
|
|
118
|
+
expect(formatDimension(undefined)).toBeUndefined();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("returns number with px suffix", () => {
|
|
122
|
+
expect(formatDimension(100)).toBe("100px");
|
|
123
|
+
expect(formatDimension(0)).toBe("0px");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("returns string as-is", () => {
|
|
127
|
+
expect(formatDimension("50%")).toBe("50%");
|
|
128
|
+
expect(formatDimension("auto")).toBe("auto");
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe("computeEdgeZoneStyle", () => {
|
|
133
|
+
describe("positioning context", () => {
|
|
134
|
+
it("uses fixed positioning when inline is false", () => {
|
|
135
|
+
const style = computeEdgeZoneStyle({
|
|
136
|
+
placement: "left",
|
|
137
|
+
inline: false,
|
|
138
|
+
edgeWidth: 20,
|
|
139
|
+
zIndex: 1000,
|
|
140
|
+
});
|
|
141
|
+
expect(style.position).toBe("fixed");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("uses absolute positioning when inline is true", () => {
|
|
145
|
+
const style = computeEdgeZoneStyle({
|
|
146
|
+
placement: "left",
|
|
147
|
+
inline: true,
|
|
148
|
+
edgeWidth: 20,
|
|
149
|
+
zIndex: 1000,
|
|
150
|
+
});
|
|
151
|
+
expect(style.position).toBe("absolute");
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe("left placement", () => {
|
|
156
|
+
it("positions at left edge with correct dimensions", () => {
|
|
157
|
+
const style = computeEdgeZoneStyle({
|
|
158
|
+
placement: "left",
|
|
159
|
+
inline: false,
|
|
160
|
+
edgeWidth: 20,
|
|
161
|
+
zIndex: 1000,
|
|
162
|
+
});
|
|
163
|
+
expect(style.left).toBe(0);
|
|
164
|
+
expect(style.top).toBe(0);
|
|
165
|
+
expect(style.bottom).toBe(0);
|
|
166
|
+
expect(style.width).toBe(20);
|
|
167
|
+
expect(style.right).toBeUndefined();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe("right placement", () => {
|
|
172
|
+
it("positions at right edge with correct dimensions", () => {
|
|
173
|
+
const style = computeEdgeZoneStyle({
|
|
174
|
+
placement: "right",
|
|
175
|
+
inline: false,
|
|
176
|
+
edgeWidth: 30,
|
|
177
|
+
zIndex: 2000,
|
|
178
|
+
});
|
|
179
|
+
expect(style.right).toBe(0);
|
|
180
|
+
expect(style.top).toBe(0);
|
|
181
|
+
expect(style.bottom).toBe(0);
|
|
182
|
+
expect(style.width).toBe(30);
|
|
183
|
+
expect(style.left).toBeUndefined();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe("top placement", () => {
|
|
188
|
+
it("positions at top edge with correct dimensions", () => {
|
|
189
|
+
const style = computeEdgeZoneStyle({
|
|
190
|
+
placement: "top",
|
|
191
|
+
inline: false,
|
|
192
|
+
edgeWidth: 25,
|
|
193
|
+
zIndex: 1000,
|
|
194
|
+
});
|
|
195
|
+
expect(style.top).toBe(0);
|
|
196
|
+
expect(style.left).toBe(0);
|
|
197
|
+
expect(style.right).toBe(0);
|
|
198
|
+
expect(style.height).toBe(25);
|
|
199
|
+
expect(style.bottom).toBeUndefined();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe("bottom placement", () => {
|
|
204
|
+
it("positions at bottom edge with correct dimensions", () => {
|
|
205
|
+
const style = computeEdgeZoneStyle({
|
|
206
|
+
placement: "bottom",
|
|
207
|
+
inline: false,
|
|
208
|
+
edgeWidth: 40,
|
|
209
|
+
zIndex: 1000,
|
|
210
|
+
});
|
|
211
|
+
expect(style.bottom).toBe(0);
|
|
212
|
+
expect(style.left).toBe(0);
|
|
213
|
+
expect(style.right).toBe(0);
|
|
214
|
+
expect(style.height).toBe(40);
|
|
215
|
+
expect(style.top).toBeUndefined();
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe("zIndex handling", () => {
|
|
220
|
+
it("sets zIndex to provided value minus 2", () => {
|
|
221
|
+
const style = computeEdgeZoneStyle({
|
|
222
|
+
placement: "left",
|
|
223
|
+
inline: false,
|
|
224
|
+
edgeWidth: 20,
|
|
225
|
+
zIndex: 1000,
|
|
226
|
+
});
|
|
227
|
+
expect(style.zIndex).toBe(998);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("uses default zIndex of 1000 when zIndex is undefined", () => {
|
|
231
|
+
const style = computeEdgeZoneStyle({
|
|
232
|
+
placement: "left",
|
|
233
|
+
inline: false,
|
|
234
|
+
edgeWidth: 20,
|
|
235
|
+
zIndex: undefined,
|
|
236
|
+
});
|
|
237
|
+
expect(style.zIndex).toBe(1000);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
describe("common properties", () => {
|
|
242
|
+
it("has transparent background", () => {
|
|
243
|
+
const style = computeEdgeZoneStyle({
|
|
244
|
+
placement: "left",
|
|
245
|
+
inline: false,
|
|
246
|
+
edgeWidth: 20,
|
|
247
|
+
zIndex: 1000,
|
|
248
|
+
});
|
|
249
|
+
expect(style.background).toBe("transparent");
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("has pointer events enabled", () => {
|
|
253
|
+
const style = computeEdgeZoneStyle({
|
|
254
|
+
placement: "left",
|
|
255
|
+
inline: false,
|
|
256
|
+
edgeWidth: 20,
|
|
257
|
+
zIndex: 1000,
|
|
258
|
+
});
|
|
259
|
+
expect(style.pointerEvents).toBe("auto");
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
});
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Drawer style computation utilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides pure functions for computing drawer styles based on configuration.
|
|
5
|
+
*/
|
|
6
|
+
import type * as React from "react";
|
|
7
|
+
import type { DrawerBehavior } from "../../types.js";
|
|
8
|
+
import {
|
|
9
|
+
COLOR_DRAWER_BACKDROP,
|
|
10
|
+
DRAWER_TRANSITION_DURATION,
|
|
11
|
+
DRAWER_TRANSITION_EASING,
|
|
12
|
+
} from "../../constants/styles.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Base backdrop style shared by backdrop and edge zone.
|
|
16
|
+
*/
|
|
17
|
+
export const DRAWER_BACKDROP_BASE_STYLE: React.CSSProperties = {
|
|
18
|
+
position: "fixed",
|
|
19
|
+
inset: 0,
|
|
20
|
+
background: COLOR_DRAWER_BACKDROP,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Base drawer panel style.
|
|
25
|
+
*/
|
|
26
|
+
export const DRAWER_PANEL_BASE_STYLE: React.CSSProperties = {
|
|
27
|
+
willChange: "transform",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Placement-specific styles for drawer positioning.
|
|
32
|
+
*/
|
|
33
|
+
export type DrawerPlacement = "left" | "right" | "top" | "bottom";
|
|
34
|
+
|
|
35
|
+
const PLACEMENT_STYLES: Record<DrawerPlacement, React.CSSProperties> = {
|
|
36
|
+
left: {
|
|
37
|
+
top: 0,
|
|
38
|
+
bottom: 0,
|
|
39
|
+
left: 0,
|
|
40
|
+
transform: "translateX(-100%)",
|
|
41
|
+
},
|
|
42
|
+
right: {
|
|
43
|
+
top: 0,
|
|
44
|
+
bottom: 0,
|
|
45
|
+
right: 0,
|
|
46
|
+
transform: "translateX(100%)",
|
|
47
|
+
},
|
|
48
|
+
top: {
|
|
49
|
+
top: 0,
|
|
50
|
+
left: 0,
|
|
51
|
+
right: 0,
|
|
52
|
+
transform: "translateY(-100%)",
|
|
53
|
+
},
|
|
54
|
+
bottom: {
|
|
55
|
+
bottom: 0,
|
|
56
|
+
left: 0,
|
|
57
|
+
right: 0,
|
|
58
|
+
transform: "translateY(100%)",
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const OPEN_TRANSFORMS: Record<DrawerPlacement, string> = {
|
|
63
|
+
left: "translateX(0)",
|
|
64
|
+
right: "translateX(0)",
|
|
65
|
+
top: "translateY(0)",
|
|
66
|
+
bottom: "translateY(0)",
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get placement-specific style.
|
|
71
|
+
*/
|
|
72
|
+
export function getPlacementStyle(placement: DrawerPlacement): React.CSSProperties {
|
|
73
|
+
return PLACEMENT_STYLES[placement];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get transform value for open state.
|
|
78
|
+
*/
|
|
79
|
+
export function getOpenTransform(placement: DrawerPlacement): string {
|
|
80
|
+
return OPEN_TRANSFORMS[placement];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get closed transform value.
|
|
85
|
+
*/
|
|
86
|
+
export function getClosedTransform(placement: DrawerPlacement): string {
|
|
87
|
+
return PLACEMENT_STYLES[placement].transform as string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Compute CSS transition value.
|
|
92
|
+
*/
|
|
93
|
+
export function computeTransitionValue(
|
|
94
|
+
mode: DrawerBehavior["transitionMode"] | undefined,
|
|
95
|
+
duration: DrawerBehavior["transitionDuration"],
|
|
96
|
+
easing: DrawerBehavior["transitionEasing"],
|
|
97
|
+
): string | undefined {
|
|
98
|
+
if (mode === "none") {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const durationValue = duration ?? DRAWER_TRANSITION_DURATION;
|
|
103
|
+
const easingValue = easing ?? DRAWER_TRANSITION_EASING;
|
|
104
|
+
|
|
105
|
+
return `transform ${durationValue} ${easingValue}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Compute backdrop transition value.
|
|
110
|
+
*/
|
|
111
|
+
export function computeBackdropTransition(
|
|
112
|
+
mode: DrawerBehavior["transitionMode"] | undefined,
|
|
113
|
+
duration: DrawerBehavior["transitionDuration"],
|
|
114
|
+
): string | undefined {
|
|
115
|
+
if (mode === "none") {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
return `opacity ${duration ?? "220ms"} ease`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Check if placement is horizontal (left/right).
|
|
123
|
+
*/
|
|
124
|
+
export function isHorizontalPlacement(placement: DrawerPlacement): boolean {
|
|
125
|
+
return placement === "left" || placement === "right";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Format dimension value to CSS string.
|
|
130
|
+
*/
|
|
131
|
+
export function formatDimension(value: string | number | undefined): string | undefined {
|
|
132
|
+
if (value === undefined) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
if (typeof value === "number") {
|
|
136
|
+
return `${value}px`;
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ============================================================================
|
|
142
|
+
// Edge Zone Styles
|
|
143
|
+
// ============================================================================
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Options for computing edge zone style.
|
|
147
|
+
*/
|
|
148
|
+
export type EdgeZoneStyleOptions = {
|
|
149
|
+
placement: DrawerPlacement;
|
|
150
|
+
inline: boolean;
|
|
151
|
+
edgeWidth: number;
|
|
152
|
+
zIndex: number | undefined;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Compute edge zone style based on placement and positioning context.
|
|
157
|
+
*
|
|
158
|
+
* The edge zone is positioned at the edge where the drawer appears from:
|
|
159
|
+
* - left drawer: left edge of the container
|
|
160
|
+
* - right drawer: right edge of the container
|
|
161
|
+
* - top drawer: top edge of the container
|
|
162
|
+
* - bottom drawer: bottom edge of the container
|
|
163
|
+
*
|
|
164
|
+
* When inline=true, uses absolute positioning (relative to parent container).
|
|
165
|
+
* When inline=false, uses fixed positioning (relative to viewport).
|
|
166
|
+
*/
|
|
167
|
+
export function computeEdgeZoneStyle(options: EdgeZoneStyleOptions): React.CSSProperties {
|
|
168
|
+
const { placement, inline, edgeWidth, zIndex } = options;
|
|
169
|
+
const position = inline ? "absolute" : "fixed";
|
|
170
|
+
const computedZIndex = zIndex !== undefined ? zIndex - 2 : 1000;
|
|
171
|
+
|
|
172
|
+
return getEdgeZoneStyleByPlacement(placement, position, edgeWidth, computedZIndex);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function getEdgeZoneStyleByPlacement(
|
|
176
|
+
placement: DrawerPlacement,
|
|
177
|
+
position: "absolute" | "fixed",
|
|
178
|
+
edgeWidth: number,
|
|
179
|
+
zIndex: number,
|
|
180
|
+
): React.CSSProperties {
|
|
181
|
+
// Common base style
|
|
182
|
+
const base: React.CSSProperties = {
|
|
183
|
+
position,
|
|
184
|
+
zIndex,
|
|
185
|
+
background: "transparent",
|
|
186
|
+
pointerEvents: "auto",
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Placement-specific positioning
|
|
190
|
+
if (placement === "left") {
|
|
191
|
+
return {
|
|
192
|
+
...base,
|
|
193
|
+
top: 0,
|
|
194
|
+
bottom: 0,
|
|
195
|
+
left: 0,
|
|
196
|
+
width: edgeWidth,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (placement === "right") {
|
|
201
|
+
return {
|
|
202
|
+
...base,
|
|
203
|
+
top: 0,
|
|
204
|
+
bottom: 0,
|
|
205
|
+
right: 0,
|
|
206
|
+
width: edgeWidth,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (placement === "top") {
|
|
211
|
+
return {
|
|
212
|
+
...base,
|
|
213
|
+
top: 0,
|
|
214
|
+
left: 0,
|
|
215
|
+
right: 0,
|
|
216
|
+
height: edgeWidth,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// bottom
|
|
221
|
+
return {
|
|
222
|
+
...base,
|
|
223
|
+
bottom: 0,
|
|
224
|
+
left: 0,
|
|
225
|
+
right: 0,
|
|
226
|
+
height: edgeWidth,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Tests for drawerSwipeConfig utilities.
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
parseSwipeGesturesConfig,
|
|
6
|
+
resolvePlacement,
|
|
7
|
+
shouldShowEdgeZone,
|
|
8
|
+
} from "./drawerSwipeConfig.js";
|
|
9
|
+
|
|
10
|
+
describe("drawerSwipeConfig", () => {
|
|
11
|
+
describe("parseSwipeGesturesConfig", () => {
|
|
12
|
+
it("returns disabled config for false", () => {
|
|
13
|
+
const config = parseSwipeGesturesConfig(false);
|
|
14
|
+
expect(config.enabled).toBe(false);
|
|
15
|
+
expect(config.edgeSwipeOpen).toBe(false);
|
|
16
|
+
expect(config.swipeClose).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("returns disabled config for undefined", () => {
|
|
20
|
+
const config = parseSwipeGesturesConfig(undefined);
|
|
21
|
+
expect(config.enabled).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("returns enabled defaults for true", () => {
|
|
25
|
+
const config = parseSwipeGesturesConfig(true);
|
|
26
|
+
expect(config.enabled).toBe(true);
|
|
27
|
+
expect(config.edgeSwipeOpen).toBe(true);
|
|
28
|
+
expect(config.swipeClose).toBe(true);
|
|
29
|
+
expect(config.edgeWidth).toBe(20);
|
|
30
|
+
expect(config.dismissThreshold).toBe(0.3);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("parses object config with defaults", () => {
|
|
34
|
+
const config = parseSwipeGesturesConfig({});
|
|
35
|
+
expect(config.enabled).toBe(true);
|
|
36
|
+
expect(config.edgeSwipeOpen).toBe(true);
|
|
37
|
+
expect(config.swipeClose).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("respects object config overrides", () => {
|
|
41
|
+
const config = parseSwipeGesturesConfig({
|
|
42
|
+
edgeSwipeOpen: false,
|
|
43
|
+
swipeClose: true,
|
|
44
|
+
edgeWidth: 40,
|
|
45
|
+
dismissThreshold: 0.5,
|
|
46
|
+
});
|
|
47
|
+
expect(config.enabled).toBe(true);
|
|
48
|
+
expect(config.edgeSwipeOpen).toBe(false);
|
|
49
|
+
expect(config.swipeClose).toBe(true);
|
|
50
|
+
expect(config.edgeWidth).toBe(40);
|
|
51
|
+
expect(config.dismissThreshold).toBe(0.5);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("resolvePlacement", () => {
|
|
56
|
+
it("returns anchor if provided", () => {
|
|
57
|
+
expect(resolvePlacement("left", undefined)).toBe("left");
|
|
58
|
+
expect(resolvePlacement("right", { left: 0 })).toBe("right");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("returns right as default when no anchor or position", () => {
|
|
62
|
+
expect(resolvePlacement(undefined, undefined)).toBe("right");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("infers left from position.left", () => {
|
|
66
|
+
expect(resolvePlacement(undefined, { left: 0 })).toBe("left");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("infers right from position.right", () => {
|
|
70
|
+
expect(resolvePlacement(undefined, { right: 0 })).toBe("right");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("infers top from position.top", () => {
|
|
74
|
+
expect(resolvePlacement(undefined, { top: 0 })).toBe("top");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("infers bottom from position.bottom", () => {
|
|
78
|
+
expect(resolvePlacement(undefined, { bottom: 0 })).toBe("bottom");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("prioritizes left over other positions", () => {
|
|
82
|
+
expect(resolvePlacement(undefined, { left: 0, right: 0 })).toBe("left");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("shouldShowEdgeZone", () => {
|
|
87
|
+
const enabledConfig = {
|
|
88
|
+
enabled: true,
|
|
89
|
+
edgeSwipeOpen: true,
|
|
90
|
+
swipeClose: true,
|
|
91
|
+
edgeWidth: 20,
|
|
92
|
+
dismissThreshold: 0.3,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const disabledConfig = {
|
|
96
|
+
enabled: false,
|
|
97
|
+
edgeSwipeOpen: false,
|
|
98
|
+
swipeClose: false,
|
|
99
|
+
edgeWidth: 20,
|
|
100
|
+
dismissThreshold: 0.3,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const noEdgeSwipeConfig = {
|
|
104
|
+
enabled: true,
|
|
105
|
+
edgeSwipeOpen: false,
|
|
106
|
+
swipeClose: true,
|
|
107
|
+
edgeWidth: 20,
|
|
108
|
+
dismissThreshold: 0.3,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
it("returns false when config is disabled", () => {
|
|
112
|
+
expect(shouldShowEdgeZone(disabledConfig, false, false)).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("returns false when edgeSwipeOpen is disabled", () => {
|
|
116
|
+
expect(shouldShowEdgeZone(noEdgeSwipeConfig, false, false)).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("returns true when drawer is closed", () => {
|
|
120
|
+
expect(shouldShowEdgeZone(enabledConfig, false, false)).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("returns true when actively opening", () => {
|
|
124
|
+
expect(shouldShowEdgeZone(enabledConfig, true, true)).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("returns false when drawer is open and not opening", () => {
|
|
128
|
+
expect(shouldShowEdgeZone(enabledConfig, true, false)).toBe(false);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|