react-panel-layout 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-Bw2djgpz.js +1542 -0
- package/dist/FloatingWindow-Bw2djgpz.js.map +1 -0
- package/dist/FloatingWindow-Cvyokf0m.cjs +2 -0
- package/dist/FloatingWindow-Cvyokf0m.cjs.map +1 -0
- package/dist/GridLayout-B4aCqSyd.js +947 -0
- package/dist/{GridLayout-BltqeCPK.js.map → GridLayout-B4aCqSyd.js.map} +1 -1
- package/dist/GridLayout-DNOClFzz.cjs +2 -0
- package/dist/{GridLayout-B4VRsC0r.cjs.map → GridLayout-DNOClFzz.cjs.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-B8Igvnb2.cjs +3 -0
- package/dist/PanelSystem-B8Igvnb2.cjs.map +1 -0
- package/dist/{PanelSystem-Dr1TBhxM.js → PanelSystem-DDUSFjXD.js} +209 -248
- package/dist/PanelSystem-DDUSFjXD.js.map +1 -0
- 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 +4 -1
- package/dist/components/window/DrawerLayers.d.ts +1 -1
- package/dist/components/window/DrawerRevealContext.d.ts +61 -0
- package/dist/components/window/drawerRevealAnimationUtils.d.ts +212 -0
- package/dist/components/window/drawerStyles.d.ts +74 -0
- package/dist/components/window/drawerSwipeConfig.d.ts +29 -0
- package/dist/components/window/useDrawerSwipeTransform.d.ts +29 -0
- package/dist/components/window/useDrawerTransform.d.ts +68 -0
- package/dist/components/window/useRevealDrawerTransform.d.ts +56 -0
- package/dist/config.cjs +1 -1
- package/dist/config.cjs.map +1 -1
- package/dist/config.js +9 -8
- package/dist/config.js.map +1 -1
- 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/drawerStateMachine.d.ts +168 -0
- package/dist/modules/drawer/revealDrawerConstants.d.ts +33 -0
- package/dist/modules/drawer/revealDrawerStateMachine.d.ts +146 -0
- package/dist/modules/drawer/strategies/index.d.ts +8 -0
- package/dist/modules/drawer/strategies/overlayStrategy.d.ts +12 -0
- package/dist/modules/drawer/strategies/revealStrategy.d.ts +12 -0
- package/dist/modules/drawer/strategies/types.d.ts +116 -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 +480 -780
- 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 +30 -0
- package/dist/useAnimationFrame-BZ6D2lMq.cjs +2 -0
- package/dist/useAnimationFrame-BZ6D2lMq.cjs.map +1 -0
- package/dist/useAnimationFrame-Bg4e-H8O.js +394 -0
- package/dist/useAnimationFrame-Bg4e-H8O.js.map +1 -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/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 +70 -0
- package/src/components/grid/GridLayout.tsx +110 -38
- package/src/components/window/Drawer.tsx +353 -162
- package/src/components/window/DrawerLayers.tsx +54 -11
- package/src/components/window/DrawerRevealContext.spec.ts +20 -0
- package/src/components/window/DrawerRevealContext.tsx +99 -0
- package/src/components/window/drawerRevealAnimationUtils.spec.ts +375 -0
- package/src/components/window/drawerRevealAnimationUtils.ts +415 -0
- package/src/components/window/drawerStyles.spec.ts +302 -0
- package/src/components/window/drawerStyles.ts +252 -0
- package/src/components/window/drawerSwipeConfig.spec.ts +131 -0
- package/src/components/window/drawerSwipeConfig.ts +112 -0
- package/src/components/window/useDrawerSwipeTransform.ts +67 -0
- package/src/components/window/useDrawerTransform.ts +505 -0
- package/src/components/window/useRevealDrawerTransform.spec.ts +1936 -0
- package/src/components/window/useRevealDrawerTransform.ts +105 -0
- package/src/constants/styles.ts +19 -0
- package/src/demo/components/FullscreenDemoPage.tsx +47 -0
- package/src/demo/fullscreenRoutes.tsx +32 -0
- package/src/demo/index.tsx +5 -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 +219 -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/DrawerBasics.module.css +6 -1
- package/src/demo/pages/Drawer/components/DrawerBasics.tsx +14 -4
- package/src/demo/pages/Drawer/components/DrawerReveal.module.css +157 -0
- package/src/demo/pages/Drawer/components/DrawerReveal.tsx +128 -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/reveal/index.tsx +17 -0
- package/src/demo/pages/Drawer/reveal-fullscreen/index.tsx +135 -0
- package/src/demo/pages/Drawer/reveal-fullscreen/styles.module.css +233 -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 +156 -0
- package/src/demo/pages/Stack/components/StackBasics.tsx +179 -95
- package/src/demo/pages/Stack/components/StackTablet.spec.tsx +110 -0
- package/src/demo/pages/Stack/components/StackTablet.tsx +42 -21
- package/src/demo/routes.tsx +24 -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 +113 -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 +99 -31
- package/src/hooks/gesture/useNativeGestureGuard.ts +3 -1
- package/src/hooks/gesture/utils.ts +102 -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 +394 -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 +354 -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 +252 -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 +339 -0
- package/src/modules/dialog/useDialogContainer.ts +150 -0
- package/src/modules/dialog/useDialogSwipeInput.spec.ts +178 -0
- package/src/modules/dialog/useDialogSwipeInput.ts +350 -0
- package/src/modules/dialog/useDialogTransform.spec.ts +403 -0
- package/src/modules/dialog/useDialogTransform.ts +407 -0
- package/src/modules/drawer/drawerStateMachine.ts +500 -0
- package/src/modules/drawer/revealDrawerConstants.ts +38 -0
- package/src/modules/drawer/revealDrawerStateMachine.spec.ts +558 -0
- package/src/modules/drawer/revealDrawerStateMachine.ts +197 -0
- package/src/modules/drawer/strategies/index.ts +9 -0
- package/src/modules/drawer/strategies/overlayStrategy.ts +133 -0
- package/src/modules/drawer/strategies/revealStrategy.ts +111 -0
- package/src/modules/drawer/strategies/types.ts +160 -0
- package/src/modules/drawer/types.ts +102 -0
- package/src/modules/drawer/useDrawerSwipeInput.spec.ts +566 -0
- package/src/modules/drawer/useDrawerSwipeInput.ts +402 -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 +66 -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 +33 -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/GridLayout-BltqeCPK.js +0 -927
- package/dist/PanelSystem-Bs8bQwQF.cjs +0 -3
- package/dist/PanelSystem-Bs8bQwQF.cjs.map +0 -1
- package/dist/PanelSystem-Dr1TBhxM.js.map +0 -1
- 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
package/dist/window.js
CHANGED
|
@@ -1,149 +1,160 @@
|
|
|
1
|
-
import { D as
|
|
1
|
+
import { D as A, b as G, F as K, P as T, S as W, d as q } from "./FloatingWindow-Bw2djgpz.js";
|
|
2
2
|
import { jsx as m } from "react/jsx-runtime";
|
|
3
|
-
import * as
|
|
4
|
-
import { u as p } from "./
|
|
5
|
-
import { u as
|
|
6
|
-
import { D as
|
|
7
|
-
import { u as
|
|
8
|
-
const
|
|
3
|
+
import * as c from "react";
|
|
4
|
+
import { u as p } from "./useDocumentPointerEvents-DXxw3qWj.js";
|
|
5
|
+
import { u as x } from "./useIsomorphicLayoutEffect-DhmEnmZ_.js";
|
|
6
|
+
import { D as z } from "./styles-NkjuMOVS.js";
|
|
7
|
+
import { u as J } from "./useFloatingState-tEfA_wbc.js";
|
|
8
|
+
const D = () => typeof window > "u" ? { width: 0, height: 0 } : {
|
|
9
9
|
width: window.innerWidth,
|
|
10
10
|
height: window.innerHeight
|
|
11
|
-
}, O = (e,
|
|
12
|
-
const
|
|
13
|
-
return { x:
|
|
14
|
-
}, b = /* @__PURE__ */ new Map(),
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
17
|
-
return
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return this.#e.set(r, s), this.#t.observe(r, e), () => {
|
|
28
|
-
this.#e.delete(r), this.#t.unobserve(r);
|
|
11
|
+
}, O = (e, t, n, o, r) => {
|
|
12
|
+
const s = e + n > r.width ? Math.max(0, r.width - n) : e, i = t + o > r.height ? Math.max(0, r.height - o) : t;
|
|
13
|
+
return { x: s, y: i };
|
|
14
|
+
}, b = /* @__PURE__ */ new Map(), R = (e) => {
|
|
15
|
+
const t = `resize-box:${e}`, n = b.get(t);
|
|
16
|
+
if (n)
|
|
17
|
+
return n;
|
|
18
|
+
const o = /* @__PURE__ */ new Map(), r = new ResizeObserver((i) => {
|
|
19
|
+
for (const a of i) {
|
|
20
|
+
const u = o.get(a.target);
|
|
21
|
+
u && u(a);
|
|
22
|
+
}
|
|
23
|
+
}), s = {
|
|
24
|
+
observe(i, a) {
|
|
25
|
+
return o.set(i, a), r.observe(i, { box: e }), () => {
|
|
26
|
+
o.delete(i), r.unobserve(i);
|
|
29
27
|
};
|
|
30
28
|
}
|
|
31
|
-
}
|
|
32
|
-
return b.set(t,
|
|
29
|
+
};
|
|
30
|
+
return b.set(t, s), s;
|
|
31
|
+
}, E = (e) => {
|
|
32
|
+
const t = e.getBoundingClientRect();
|
|
33
|
+
return {
|
|
34
|
+
target: e,
|
|
35
|
+
contentRect: t,
|
|
36
|
+
borderBoxSize: [{ inlineSize: t.width, blockSize: t.height }],
|
|
37
|
+
contentBoxSize: [{ inlineSize: t.width, blockSize: t.height }],
|
|
38
|
+
devicePixelContentBoxSize: []
|
|
39
|
+
};
|
|
40
|
+
}, M = (e) => {
|
|
41
|
+
if (e.borderBoxSize?.length > 0) {
|
|
42
|
+
const t = e.borderBoxSize[0];
|
|
43
|
+
return new DOMRect(0, 0, t.inlineSize, t.blockSize);
|
|
44
|
+
}
|
|
45
|
+
return e.contentRect;
|
|
33
46
|
};
|
|
34
|
-
function
|
|
35
|
-
const [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return null;
|
|
42
|
-
if (t.borderBoxSize?.length > 0) {
|
|
43
|
-
const s = t.borderBoxSize[0];
|
|
44
|
-
return new DOMRect(0, 0, s.inlineSize, s.blockSize);
|
|
47
|
+
function C(e, { box: t = "content-box" }) {
|
|
48
|
+
const [n, o] = c.useState(null);
|
|
49
|
+
x(() => {
|
|
50
|
+
const s = e.current;
|
|
51
|
+
if (!s) {
|
|
52
|
+
o(null);
|
|
53
|
+
return;
|
|
45
54
|
}
|
|
46
|
-
return t.
|
|
47
|
-
}, [t]);
|
|
48
|
-
|
|
55
|
+
return o(E(s)), R(t).observe(s, o);
|
|
56
|
+
}, [e, t]);
|
|
57
|
+
const r = c.useMemo(() => n ? M(n) : null, [n]);
|
|
58
|
+
return { entry: n, rect: r };
|
|
49
59
|
}
|
|
50
|
-
const
|
|
60
|
+
const P = {
|
|
51
61
|
border: "none",
|
|
52
62
|
padding: 0,
|
|
53
63
|
background: "transparent"
|
|
54
|
-
},
|
|
64
|
+
}, k = {
|
|
55
65
|
position: "fixed",
|
|
56
|
-
zIndex:
|
|
57
|
-
},
|
|
66
|
+
zIndex: z
|
|
67
|
+
}, B = typeof window < "u" && typeof document < "u", L = ({
|
|
58
68
|
anchor: e,
|
|
59
|
-
onClose:
|
|
60
|
-
children:
|
|
61
|
-
contentClassName:
|
|
62
|
-
contentStyle:
|
|
63
|
-
dataAttributes:
|
|
64
|
-
onKeyDown:
|
|
65
|
-
onPositionChange:
|
|
69
|
+
onClose: t,
|
|
70
|
+
children: n,
|
|
71
|
+
contentClassName: o,
|
|
72
|
+
contentStyle: r,
|
|
73
|
+
dataAttributes: s,
|
|
74
|
+
onKeyDown: i,
|
|
75
|
+
onPositionChange: a
|
|
66
76
|
}) => {
|
|
67
|
-
const
|
|
68
|
-
const f =
|
|
69
|
-
return O(e.x, e.y,
|
|
70
|
-
}, [e.x, e.y, d?.width, d?.height]), h = p(
|
|
71
|
-
|
|
77
|
+
const u = c.useRef(null), { rect: d } = C(u, { box: "border-box" }), l = c.useMemo(() => {
|
|
78
|
+
const f = D(), g = d?.width ?? 0, w = d?.height ?? 0;
|
|
79
|
+
return O(e.x, e.y, g, w, f);
|
|
80
|
+
}, [e.x, e.y, d?.width, d?.height]), h = p(a);
|
|
81
|
+
c.useEffect(() => {
|
|
72
82
|
h?.(l);
|
|
73
83
|
}, [l]);
|
|
74
|
-
const y = p(
|
|
75
|
-
|
|
76
|
-
const f = (
|
|
77
|
-
|
|
84
|
+
const y = p(t);
|
|
85
|
+
c.useEffect(() => {
|
|
86
|
+
const f = (g) => {
|
|
87
|
+
g.target instanceof Node && u.current && !u.current.contains(g.target) && y();
|
|
78
88
|
};
|
|
79
89
|
return document.addEventListener("pointerdown", f), () => document.removeEventListener("pointerdown", f);
|
|
80
90
|
}, []);
|
|
81
|
-
const
|
|
91
|
+
const v = c.useMemo(
|
|
82
92
|
() => ({
|
|
83
|
-
...
|
|
84
|
-
...
|
|
93
|
+
...k,
|
|
94
|
+
...r,
|
|
85
95
|
left: l.x,
|
|
86
96
|
top: l.y
|
|
87
97
|
}),
|
|
88
|
-
[
|
|
89
|
-
),
|
|
98
|
+
[r, l.x, l.y]
|
|
99
|
+
), S = c.useMemo(() => s ? Object.entries(s).reduce((f, [g, w]) => (w == null || (f[`data-${g}`] = w), f), {}) : {}, [s]);
|
|
90
100
|
return /* @__PURE__ */ m(
|
|
91
101
|
"div",
|
|
92
102
|
{
|
|
93
|
-
ref:
|
|
94
|
-
className:
|
|
95
|
-
style:
|
|
96
|
-
onKeyDown:
|
|
97
|
-
...
|
|
98
|
-
children:
|
|
103
|
+
ref: u,
|
|
104
|
+
className: o,
|
|
105
|
+
style: v,
|
|
106
|
+
onKeyDown: i,
|
|
107
|
+
...S,
|
|
108
|
+
children: n
|
|
99
109
|
}
|
|
100
110
|
);
|
|
101
111
|
}, I = ({
|
|
102
112
|
visible: e,
|
|
103
|
-
onClose:
|
|
104
|
-
anchor:
|
|
105
|
-
children:
|
|
106
|
-
contentClassName:
|
|
107
|
-
contentStyle:
|
|
108
|
-
dataAttributes:
|
|
109
|
-
onKeyDown:
|
|
110
|
-
onPositionChange:
|
|
113
|
+
onClose: t,
|
|
114
|
+
anchor: n,
|
|
115
|
+
children: o,
|
|
116
|
+
contentClassName: r,
|
|
117
|
+
contentStyle: s,
|
|
118
|
+
dataAttributes: i,
|
|
119
|
+
onKeyDown: a,
|
|
120
|
+
onPositionChange: u
|
|
111
121
|
}) => {
|
|
112
|
-
const d =
|
|
113
|
-
|
|
122
|
+
const d = c.useRef(null);
|
|
123
|
+
x(() => {
|
|
114
124
|
if (!d.current)
|
|
115
125
|
return;
|
|
116
126
|
const h = d.current;
|
|
117
127
|
e ? h.showModal() : h.open && h.close();
|
|
118
128
|
}, [e]);
|
|
119
|
-
const l =
|
|
129
|
+
const l = c.useCallback(
|
|
120
130
|
(h) => {
|
|
121
|
-
h.preventDefault(),
|
|
131
|
+
h.preventDefault(), t();
|
|
122
132
|
},
|
|
123
|
-
[
|
|
133
|
+
[t]
|
|
124
134
|
);
|
|
125
|
-
return /* @__PURE__ */ m("dialog", { ref: d, style:
|
|
135
|
+
return /* @__PURE__ */ m("dialog", { ref: d, style: P, onCancel: l, children: /* @__PURE__ */ m(c.Activity, { mode: e ? "visible" : "hidden", children: /* @__PURE__ */ m(
|
|
126
136
|
L,
|
|
127
137
|
{
|
|
128
|
-
anchor:
|
|
129
|
-
onClose:
|
|
130
|
-
contentClassName:
|
|
131
|
-
contentStyle:
|
|
132
|
-
dataAttributes:
|
|
133
|
-
onKeyDown:
|
|
134
|
-
onPositionChange:
|
|
135
|
-
children:
|
|
138
|
+
anchor: n,
|
|
139
|
+
onClose: t,
|
|
140
|
+
contentClassName: r,
|
|
141
|
+
contentStyle: s,
|
|
142
|
+
dataAttributes: i,
|
|
143
|
+
onKeyDown: a,
|
|
144
|
+
onPositionChange: u,
|
|
145
|
+
children: o
|
|
136
146
|
}
|
|
137
147
|
) }) });
|
|
138
|
-
},
|
|
139
|
-
|
|
148
|
+
}, N = (e) => B ? /* @__PURE__ */ m(I, { ...e }) : null;
|
|
149
|
+
N.displayName = "DialogOverlay";
|
|
140
150
|
export {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
W as
|
|
147
|
-
q as
|
|
151
|
+
N as DialogOverlay,
|
|
152
|
+
A as Drawer,
|
|
153
|
+
G as DrawerLayers,
|
|
154
|
+
K as FloatingWindow,
|
|
155
|
+
T as PopupLayerPortal,
|
|
156
|
+
W as SwipeSafeZone,
|
|
157
|
+
q as useDrawerState,
|
|
158
|
+
J as useFloatingState
|
|
148
159
|
};
|
|
149
160
|
//# sourceMappingURL=window.js.map
|
package/dist/window.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"window.js","sources":["../src/utils/dialogUtils.ts","../src/hooks/useResizeObserver.tsx","../src/components/window/DialogOverlay.tsx"],"sourcesContent":["/**\n * @file Dialog positioning utilities\n */\n\nexport type ViewportInfo = {\n width: number;\n height: number;\n};\n\n/**\n * Get viewport dimensions\n */\nexport const getViewportInfo = (): ViewportInfo => {\n if (typeof window === \"undefined\") {\n return { width: 0, height: 0 };\n }\n\n return {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n};\n\n/**\n * Calculate context menu position to keep it within viewport\n */\nexport const calculateContextMenuPosition = (\n anchorX: number,\n anchorY: number,\n menuWidth: number,\n menuHeight: number,\n viewport: ViewportInfo,\n): { x: number; y: number } => {\n // Adjust horizontal position if menu would overflow\n const x =\n anchorX + menuWidth > viewport.width ? Math.max(0, viewport.width - menuWidth) : anchorX;\n\n // Adjust vertical position if menu would overflow\n const y =\n anchorY + menuHeight > viewport.height ? Math.max(0, viewport.height - menuHeight) : anchorY;\n\n return { x, y };\n};\n","/**\n * @file Shared useResizeObserver hook with cached observer instances.\n */\nimport * as React from \"react\";\n\ntype Unobserve = () => void;\ntype Callback = (entry: ResizeObserverEntry, observer: ResizeObserver) => void;\ntype SharedObserver = {\n observe: (target: Element, callback: Callback) => Unobserve;\n};\nconst observerCache = new Map<string, SharedObserver>();\nconst getSharedObserver = (options: ResizeObserverOptions) => {\n const { box = \"content-box\" } = options;\n const observerKey = `resize-box:${box}`;\n const cached = observerCache.get(observerKey);\n if (cached) {\n return cached;\n }\n const observer = new (class {\n #callbackMap = new Map<Element, Callback>();\n #resizeObserver = new ResizeObserver((entries, observer) => {\n entries.forEach((entry) => {\n const callback = this.#callbackMap.get(entry.target);\n if (callback) {\n callback(entry, observer);\n }\n });\n });\n observe(target: Element, callback: Callback) {\n this.#callbackMap.set(target, callback);\n this.#resizeObserver.observe(target, options);\n return () => {\n this.#callbackMap.delete(target);\n this.#resizeObserver.unobserve(target);\n };\n }\n })();\n observerCache.set(observerKey, observer);\n\n return observer;\n};\n/**\n * Observe size changes for a given element reference using shared resize observers.\n *\n * @param ref - Ref holding the element whose size to monitor.\n * @param options - Resize observer configuration.\n * @returns Latest resize entry and a derived DOMRect snapshot.\n */\nexport function useResizeObserver<T extends HTMLElement>(\n ref: React.RefObject<T | null>,\n { box }: ResizeObserverOptions,\n) {\n const [entry, setEntry] = React.useState<ResizeObserverEntry | null>(null);\n const target = ref.current;\n\n React.useEffect(() => {\n if (!target) {\n return;\n }\n\n const observer = getSharedObserver({ box });\n return observer.observe(target, (nextEntry) => {\n setEntry(nextEntry);\n });\n }, [box, target]);\n\n const rect = React.useMemo(() => {\n if (!entry) {\n return null;\n }\n\n if (entry.borderBoxSize?.length > 0) {\n const size = entry.borderBoxSize[0];\n return new DOMRect(0, 0, size.inlineSize, size.blockSize);\n }\n\n return entry.contentRect;\n }, [entry]);\n\n return { entry, rect };\n}\n","/**\n * @file Dialog-based overlay component with automatic positioning\n */\nimport * as React from \"react\";\nimport type { Position } from \"../../types\";\nimport { calculateContextMenuPosition, getViewportInfo } from \"../../utils/dialogUtils\";\nimport { ensureDialogPolyfill } from \"../../utils/polyfills/createDialogPolyfill\";\nimport { useEffectEvent } from \"../../hooks/useEffectEvent\";\nimport { useIsomorphicLayoutEffect } from \"../../hooks/useIsomorphicLayoutEffect\";\nimport { useResizeObserver } from \"../../hooks/useResizeObserver\";\nimport { DIALOG_OVERLAY_Z_INDEX } from \"../../constants/styles\";\n\nconst contextDialogStyle: React.CSSProperties = {\n border: \"none\",\n padding: 0,\n background: \"transparent\",\n};\n\nconst contextContentStyle: React.CSSProperties = {\n position: \"fixed\",\n zIndex: DIALOG_OVERLAY_Z_INDEX,\n};\n\ntype DataAttributes = Record<string, string | number | boolean>;\n\nexport type DialogOverlayProps = {\n anchor: Position;\n visible: boolean;\n onClose: () => void;\n children: React.ReactNode;\n contentClassName?: string;\n contentStyle?: React.CSSProperties;\n dataAttributes?: Record<string, string | number | boolean | null | undefined>;\n onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;\n onPositionChange?: (position: Position) => void;\n};\n\nconst isBrowser = typeof window !== \"undefined\" && typeof document !== \"undefined\";\n\nensureDialogPolyfill();\n\nconst DialogOverlayContent: React.FC<Omit<DialogOverlayProps, \"visible\">> = ({\n anchor,\n onClose,\n children,\n contentClassName,\n contentStyle,\n dataAttributes,\n onKeyDown,\n onPositionChange,\n}) => {\n const contentRef = React.useRef<HTMLDivElement>(null);\n const { rect } = useResizeObserver(contentRef, { box: \"border-box\" });\n\n const computedPosition = React.useMemo(() => {\n const viewport = getViewportInfo();\n const width = rect?.width ?? 0;\n const height = rect?.height ?? 0;\n return calculateContextMenuPosition(anchor.x, anchor.y, width, height, viewport);\n }, [anchor.x, anchor.y, rect?.width, rect?.height]);\n\n const handlePositionChange = useEffectEvent(onPositionChange);\n\n React.useEffect(() => {\n handlePositionChange?.(computedPosition);\n }, [computedPosition]);\n\n const handleClose = useEffectEvent(onClose);\n\n React.useEffect(() => {\n const handlePointerDown = (event: PointerEvent) => {\n if (!(event.target instanceof Node)) {\n return;\n }\n if (contentRef.current && !contentRef.current.contains(event.target)) {\n handleClose();\n }\n };\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, []);\n\n const mergedStyle: React.CSSProperties = React.useMemo(\n () => ({\n ...contextContentStyle,\n ...contentStyle,\n left: computedPosition.x,\n top: computedPosition.y,\n }),\n [contentStyle, computedPosition.x, computedPosition.y],\n );\n\n const dataProps = React.useMemo<DataAttributes>(() => {\n if (!dataAttributes) {\n return {};\n }\n return Object.entries(dataAttributes).reduce<DataAttributes>((acc, [key, value]) => {\n if (value === null || value === undefined) {\n return acc;\n }\n acc[`data-${key}`] = value;\n return acc;\n }, {});\n }, [dataAttributes]);\n\n return (\n <div\n ref={contentRef}\n className={contentClassName}\n style={mergedStyle}\n onKeyDown={onKeyDown}\n {...dataProps}\n >\n {children}\n </div>\n );\n};\n\nconst DialogOverlayImpl: React.FC<DialogOverlayProps> = ({\n visible,\n onClose,\n anchor,\n children,\n contentClassName,\n contentStyle,\n dataAttributes,\n onKeyDown,\n onPositionChange,\n}) => {\n const dialogRef = React.useRef<HTMLDialogElement>(null);\n\n useIsomorphicLayoutEffect(() => {\n if (!dialogRef.current) {\n return;\n }\n\n const dialog = dialogRef.current;\n if (visible) {\n dialog.showModal();\n } else if (dialog.open) {\n dialog.close();\n }\n }, [visible]);\n\n const handleCancel = React.useCallback(\n (event: React.SyntheticEvent) => {\n event.preventDefault();\n onClose();\n },\n [onClose],\n );\n\n return (\n <dialog ref={dialogRef} style={contextDialogStyle} onCancel={handleCancel}>\n <React.Activity mode={visible ? \"visible\" : \"hidden\"}>\n <DialogOverlayContent\n anchor={anchor}\n onClose={onClose}\n contentClassName={contentClassName}\n contentStyle={contentStyle}\n dataAttributes={dataAttributes}\n onKeyDown={onKeyDown}\n onPositionChange={onPositionChange}\n >\n {children}\n </DialogOverlayContent>\n </React.Activity>\n </dialog>\n );\n};\n\nexport const DialogOverlay: React.FC<DialogOverlayProps> = (props) => {\n if (!isBrowser) {\n return null;\n }\n return <DialogOverlayImpl {...props} />;\n};\n\nDialogOverlay.displayName = \"DialogOverlay\";\n"],"names":["getViewportInfo","calculateContextMenuPosition","anchorX","anchorY","menuWidth","menuHeight","viewport","x","y","observerCache","getSharedObserver","options","box","observerKey","cached","observer","#callbackMap","#resizeObserver","entries","entry","callback","target","useResizeObserver","ref","setEntry","React","nextEntry","rect","size","contextDialogStyle","contextContentStyle","DIALOG_OVERLAY_Z_INDEX","isBrowser","DialogOverlayContent","anchor","onClose","children","contentClassName","contentStyle","dataAttributes","onKeyDown","onPositionChange","contentRef","computedPosition","width","height","handlePositionChange","useEffectEvent","handleClose","handlePointerDown","event","mergedStyle","dataProps","acc","key","value","jsx","DialogOverlayImpl","visible","dialogRef","useIsomorphicLayoutEffect","dialog","handleCancel","DialogOverlay","props"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"window.js","sources":["../src/utils/dialogUtils.ts","../src/hooks/useResizeObserver.tsx","../src/components/window/DialogOverlay.tsx"],"sourcesContent":["/**\n * @file Dialog positioning utilities\n */\n\nexport type ViewportInfo = {\n width: number;\n height: number;\n};\n\n/**\n * Get viewport dimensions\n */\nexport const getViewportInfo = (): ViewportInfo => {\n if (typeof window === \"undefined\") {\n return { width: 0, height: 0 };\n }\n\n return {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n};\n\n/**\n * Calculate context menu position to keep it within viewport\n */\nexport const calculateContextMenuPosition = (\n anchorX: number,\n anchorY: number,\n menuWidth: number,\n menuHeight: number,\n viewport: ViewportInfo,\n): { x: number; y: number } => {\n // Adjust horizontal position if menu would overflow\n const x =\n anchorX + menuWidth > viewport.width ? Math.max(0, viewport.width - menuWidth) : anchorX;\n\n // Adjust vertical position if menu would overflow\n const y =\n anchorY + menuHeight > viewport.height ? Math.max(0, viewport.height - menuHeight) : anchorY;\n\n return { x, y };\n};\n","/**\n * @file Shared useResizeObserver hook with cached observer instances.\n *\n * Provides element size observation with shared observers for memory efficiency.\n * Size becomes available after the first useLayoutEffect cycle completes.\n *\n * Note: Due to React's effect execution order (children before parents),\n * child components may see containerSize=0 on their first effect run.\n * This is a React constraint, not a bug. Consumers should check for\n * valid size before using it for calculations like animation positions.\n */\nimport * as React from \"react\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect.js\";\n\n/**\n * Shared ResizeObserver that can observe multiple elements.\n */\ntype SharedObserver = {\n observe: (target: Element, callback: (entry: ResizeObserverEntry) => void) => () => void;\n};\n\n/** Cache of shared observers per box option */\nconst observerCache = new Map<string, SharedObserver>();\n\n/**\n * Get or create a shared ResizeObserver for the given box option.\n */\nconst getSharedObserver = (box: ResizeObserverBoxOptions): SharedObserver => {\n const observerKey = `resize-box:${box}`;\n const cached = observerCache.get(observerKey);\n if (cached) {\n return cached;\n }\n\n const callbacks = new Map<Element, (entry: ResizeObserverEntry) => void>();\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const callback = callbacks.get(entry.target);\n if (callback) {\n callback(entry);\n }\n }\n });\n\n const sharedObserver: SharedObserver = {\n observe(target, callback) {\n callbacks.set(target, callback);\n resizeObserver.observe(target, { box });\n\n return () => {\n callbacks.delete(target);\n resizeObserver.unobserve(target);\n };\n },\n };\n\n observerCache.set(observerKey, sharedObserver);\n return sharedObserver;\n};\n\n/**\n * Create a ResizeObserverEntry from getBoundingClientRect.\n */\nconst measureElement = (target: Element): ResizeObserverEntry => {\n const rect = target.getBoundingClientRect();\n return {\n target,\n contentRect: rect,\n borderBoxSize: [{ inlineSize: rect.width, blockSize: rect.height }],\n contentBoxSize: [{ inlineSize: rect.width, blockSize: rect.height }],\n devicePixelContentBoxSize: [],\n };\n};\n\n/**\n * Extract DOMRect from ResizeObserverEntry.\n */\nconst entryToRect = (entry: ResizeObserverEntry): DOMRect => {\n if (entry.borderBoxSize?.length > 0) {\n const size = entry.borderBoxSize[0];\n return new DOMRect(0, 0, size.inlineSize, size.blockSize);\n }\n return entry.contentRect;\n};\n\n/**\n * Clear observer cache. Exported for testing purposes.\n */\nexport function clearObserverCache(): void {\n observerCache.clear();\n}\n\n/**\n * Observe size changes for a given element reference using shared resize observers.\n *\n * @param ref - Ref holding the element whose size to monitor.\n * @param options - Resize observer configuration.\n * @returns Latest resize entry and a derived DOMRect snapshot.\n *\n * @remarks\n * The `rect` will be `null` on the first render. After the initial\n * useLayoutEffect runs and triggers a re-render, `rect` will contain\n * the measured size.\n *\n * Due to React's effect execution order, child components' effects run\n * before parent effects. If you pass `rect.width` to a child as a prop,\n * the child's first effect will see `0` (or whatever default you use).\n * This is expected React behavior.\n *\n * @example\n * ```tsx\n * const containerRef = useRef<HTMLDivElement>(null);\n * const { rect } = useResizeObserver(containerRef, { box: \"border-box\" });\n * const width = rect?.width ?? 0;\n *\n * // Check if size is ready before using for calculations\n * const isReady = rect !== null;\n * ```\n */\nexport function useResizeObserver<T extends HTMLElement>(\n ref: React.RefObject<T | null>,\n { box = \"content-box\" }: ResizeObserverOptions,\n) {\n const [entry, setEntry] = React.useState<ResizeObserverEntry | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n const target = ref.current;\n if (!target) {\n setEntry(null);\n return;\n }\n\n // Measure immediately\n setEntry(measureElement(target));\n\n // Set up ResizeObserver for subsequent updates\n const observer = getSharedObserver(box);\n return observer.observe(target, setEntry);\n }, [ref, box]);\n\n const rect = React.useMemo(() => {\n if (!entry) {\n return null;\n }\n return entryToRect(entry);\n }, [entry]);\n\n return { entry, rect };\n}\n","/**\n * @file Dialog-based overlay component with automatic positioning\n */\nimport * as React from \"react\";\nimport type { Position } from \"../../types\";\nimport { calculateContextMenuPosition, getViewportInfo } from \"../../utils/dialogUtils\";\nimport { ensureDialogPolyfill } from \"../../utils/polyfills/createDialogPolyfill\";\nimport { useEffectEvent } from \"../../hooks/useEffectEvent\";\nimport { useIsomorphicLayoutEffect } from \"../../hooks/useIsomorphicLayoutEffect\";\nimport { useResizeObserver } from \"../../hooks/useResizeObserver\";\nimport { DIALOG_OVERLAY_Z_INDEX } from \"../../constants/styles\";\n\nconst contextDialogStyle: React.CSSProperties = {\n border: \"none\",\n padding: 0,\n background: \"transparent\",\n};\n\nconst contextContentStyle: React.CSSProperties = {\n position: \"fixed\",\n zIndex: DIALOG_OVERLAY_Z_INDEX,\n};\n\ntype DataAttributes = Record<string, string | number | boolean>;\n\nexport type DialogOverlayProps = {\n anchor: Position;\n visible: boolean;\n onClose: () => void;\n children: React.ReactNode;\n contentClassName?: string;\n contentStyle?: React.CSSProperties;\n dataAttributes?: Record<string, string | number | boolean | null | undefined>;\n onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;\n onPositionChange?: (position: Position) => void;\n};\n\nconst isBrowser = typeof window !== \"undefined\" && typeof document !== \"undefined\";\n\nensureDialogPolyfill();\n\nconst DialogOverlayContent: React.FC<Omit<DialogOverlayProps, \"visible\">> = ({\n anchor,\n onClose,\n children,\n contentClassName,\n contentStyle,\n dataAttributes,\n onKeyDown,\n onPositionChange,\n}) => {\n const contentRef = React.useRef<HTMLDivElement>(null);\n const { rect } = useResizeObserver(contentRef, { box: \"border-box\" });\n\n const computedPosition = React.useMemo(() => {\n const viewport = getViewportInfo();\n const width = rect?.width ?? 0;\n const height = rect?.height ?? 0;\n return calculateContextMenuPosition(anchor.x, anchor.y, width, height, viewport);\n }, [anchor.x, anchor.y, rect?.width, rect?.height]);\n\n const handlePositionChange = useEffectEvent(onPositionChange);\n\n React.useEffect(() => {\n handlePositionChange?.(computedPosition);\n }, [computedPosition]);\n\n const handleClose = useEffectEvent(onClose);\n\n React.useEffect(() => {\n const handlePointerDown = (event: PointerEvent) => {\n if (!(event.target instanceof Node)) {\n return;\n }\n if (contentRef.current && !contentRef.current.contains(event.target)) {\n handleClose();\n }\n };\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, []);\n\n const mergedStyle: React.CSSProperties = React.useMemo(\n () => ({\n ...contextContentStyle,\n ...contentStyle,\n left: computedPosition.x,\n top: computedPosition.y,\n }),\n [contentStyle, computedPosition.x, computedPosition.y],\n );\n\n const dataProps = React.useMemo<DataAttributes>(() => {\n if (!dataAttributes) {\n return {};\n }\n return Object.entries(dataAttributes).reduce<DataAttributes>((acc, [key, value]) => {\n if (value === null || value === undefined) {\n return acc;\n }\n acc[`data-${key}`] = value;\n return acc;\n }, {});\n }, [dataAttributes]);\n\n return (\n <div\n ref={contentRef}\n className={contentClassName}\n style={mergedStyle}\n onKeyDown={onKeyDown}\n {...dataProps}\n >\n {children}\n </div>\n );\n};\n\nconst DialogOverlayImpl: React.FC<DialogOverlayProps> = ({\n visible,\n onClose,\n anchor,\n children,\n contentClassName,\n contentStyle,\n dataAttributes,\n onKeyDown,\n onPositionChange,\n}) => {\n const dialogRef = React.useRef<HTMLDialogElement>(null);\n\n useIsomorphicLayoutEffect(() => {\n if (!dialogRef.current) {\n return;\n }\n\n const dialog = dialogRef.current;\n if (visible) {\n dialog.showModal();\n } else if (dialog.open) {\n dialog.close();\n }\n }, [visible]);\n\n const handleCancel = React.useCallback(\n (event: React.SyntheticEvent) => {\n event.preventDefault();\n onClose();\n },\n [onClose],\n );\n\n return (\n <dialog ref={dialogRef} style={contextDialogStyle} onCancel={handleCancel}>\n <React.Activity mode={visible ? \"visible\" : \"hidden\"}>\n <DialogOverlayContent\n anchor={anchor}\n onClose={onClose}\n contentClassName={contentClassName}\n contentStyle={contentStyle}\n dataAttributes={dataAttributes}\n onKeyDown={onKeyDown}\n onPositionChange={onPositionChange}\n >\n {children}\n </DialogOverlayContent>\n </React.Activity>\n </dialog>\n );\n};\n\nexport const DialogOverlay: React.FC<DialogOverlayProps> = (props) => {\n if (!isBrowser) {\n return null;\n }\n return <DialogOverlayImpl {...props} />;\n};\n\nDialogOverlay.displayName = \"DialogOverlay\";\n"],"names":["getViewportInfo","calculateContextMenuPosition","anchorX","anchorY","menuWidth","menuHeight","viewport","x","y","observerCache","getSharedObserver","box","observerKey","cached","callbacks","resizeObserver","entries","entry","callback","sharedObserver","target","measureElement","rect","entryToRect","size","useResizeObserver","ref","setEntry","React","useIsomorphicLayoutEffect","contextDialogStyle","contextContentStyle","DIALOG_OVERLAY_Z_INDEX","isBrowser","DialogOverlayContent","anchor","onClose","children","contentClassName","contentStyle","dataAttributes","onKeyDown","onPositionChange","contentRef","computedPosition","width","height","handlePositionChange","useEffectEvent","handleClose","handlePointerDown","event","mergedStyle","dataProps","acc","key","value","jsx","DialogOverlayImpl","visible","dialogRef","dialog","handleCancel","DialogOverlay","props"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-panel-layout",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "Unlicense",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -62,6 +62,11 @@
|
|
|
62
62
|
"import": "./dist/panels.js",
|
|
63
63
|
"require": "./dist/panels.cjs"
|
|
64
64
|
},
|
|
65
|
+
"./dialog": {
|
|
66
|
+
"types": "./dist/dialog/index.d.ts",
|
|
67
|
+
"import": "./dist/dialog.js",
|
|
68
|
+
"require": "./dist/dialog.cjs"
|
|
69
|
+
},
|
|
65
70
|
"./package.json": "./package.json"
|
|
66
71
|
},
|
|
67
72
|
"files": [
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file SwipeSafeZone component
|
|
3
|
+
*
|
|
4
|
+
* A wrapper component that marks an area as exempt from swipe gesture detection.
|
|
5
|
+
* Content inside this zone will not trigger swipe-to-close or other swipe gestures.
|
|
6
|
+
*
|
|
7
|
+
* Use this for:
|
|
8
|
+
* - Scrollable content areas
|
|
9
|
+
* - Input fields and text areas
|
|
10
|
+
* - Interactive elements that need drag/swipe for their own purposes
|
|
11
|
+
*/
|
|
12
|
+
import * as React from "react";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Data attribute used to identify swipe-safe zones.
|
|
16
|
+
* Swipe gesture handlers should check for this attribute on target elements.
|
|
17
|
+
*/
|
|
18
|
+
export const SWIPE_SAFE_ZONE_ATTR = "data-swipe-safe-zone";
|
|
19
|
+
|
|
20
|
+
export type SwipeSafeZoneProps = {
|
|
21
|
+
/** Content to render inside the safe zone */
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
/** Additional CSS class name */
|
|
24
|
+
className?: string;
|
|
25
|
+
/** Additional inline styles */
|
|
26
|
+
style?: React.CSSProperties;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* SwipeSafeZone marks an area where swipe gestures should not be triggered.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <SwipeSafeZone>
|
|
35
|
+
* <ScrollableList items={items} />
|
|
36
|
+
* </SwipeSafeZone>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export const SwipeSafeZone: React.FC<SwipeSafeZoneProps> = ({
|
|
40
|
+
children,
|
|
41
|
+
className,
|
|
42
|
+
style,
|
|
43
|
+
}) => {
|
|
44
|
+
return (
|
|
45
|
+
<div
|
|
46
|
+
className={className}
|
|
47
|
+
style={style}
|
|
48
|
+
data-swipe-safe-zone="true"
|
|
49
|
+
>
|
|
50
|
+
{children}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if an element is inside a SwipeSafeZone.
|
|
57
|
+
*/
|
|
58
|
+
export function isInSwipeSafeZone(element: HTMLElement, container: HTMLElement): boolean {
|
|
59
|
+
// eslint-disable-next-line no-restricted-syntax -- loop variable requires let
|
|
60
|
+
let current: HTMLElement | null = element;
|
|
61
|
+
|
|
62
|
+
while (current && current !== container) {
|
|
63
|
+
if (current.hasAttribute(SWIPE_SAFE_ZONE_ATTR)) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
current = current.parentElement;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
@@ -5,6 +5,7 @@ import * as React from "react";
|
|
|
5
5
|
import { useIntersectionObserver } from "../../hooks/useIntersectionObserver";
|
|
6
6
|
import type { LayerDefinition, PanelLayoutConfig } from "../../types";
|
|
7
7
|
import { DrawerLayers } from "../window/DrawerLayers";
|
|
8
|
+
import { DrawerRevealProvider, useDrawerReveal, isRevealMode } from "../window/DrawerRevealContext";
|
|
8
9
|
import { GridLayerList } from "./GridLayerList";
|
|
9
10
|
import { GridTrackResizeHandle } from "./GridTrackResizeHandle";
|
|
10
11
|
import { PanelSystemProvider, usePanelSystem } from "../../PanelSystemContext";
|
|
@@ -18,6 +19,7 @@ const gridLayoutBaseStyle: React.CSSProperties = {
|
|
|
18
19
|
width: "100%",
|
|
19
20
|
height: "100%",
|
|
20
21
|
overflow: "hidden",
|
|
22
|
+
position: "relative",
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
const gridLayoutDraggingStyle: React.CSSProperties = {
|
|
@@ -55,7 +57,9 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ config, layers, style: s
|
|
|
55
57
|
|
|
56
58
|
return (
|
|
57
59
|
<PanelSystemProvider config={config} layers={layers} style={styleProp}>
|
|
58
|
-
<
|
|
60
|
+
<DrawerRevealProvider>
|
|
61
|
+
<GridLayoutInner gridRef={gridRef} isIntersecting={isIntersecting} isRoot={root} />
|
|
62
|
+
</DrawerRevealProvider>
|
|
59
63
|
</PanelSystemProvider>
|
|
60
64
|
);
|
|
61
65
|
};
|
|
@@ -74,6 +78,15 @@ const GridLayoutInner: React.FC<{
|
|
|
74
78
|
isRootLevel: isRoot,
|
|
75
79
|
});
|
|
76
80
|
|
|
81
|
+
// Register gridRef in reveal context for inline mode drawers
|
|
82
|
+
const { setGridRef } = useDrawerReveal();
|
|
83
|
+
React.useLayoutEffect(() => {
|
|
84
|
+
setGridRef(gridRef);
|
|
85
|
+
return () => {
|
|
86
|
+
setGridRef(null);
|
|
87
|
+
};
|
|
88
|
+
}, [gridRef, setGridRef]);
|
|
89
|
+
|
|
77
90
|
const isDraggingOrResizing = draggingLayerId ? true : Boolean(resizingLayerId);
|
|
78
91
|
const combinedStyle = React.useMemo(() => {
|
|
79
92
|
const baseStyle = resolveGridBaseStyle(isRoot);
|
|
@@ -84,45 +97,104 @@ const GridLayoutInner: React.FC<{
|
|
|
84
97
|
};
|
|
85
98
|
}, [gridStyle, isDraggingOrResizing, isRoot]);
|
|
86
99
|
|
|
100
|
+
// Split drawer layers for proper rendering context:
|
|
101
|
+
// - Overlay inline drawers: inside grid container (for proper absolute positioning)
|
|
102
|
+
// - Reveal inline drawers: grid sibling in wrapper (drawer stays fixed while grid transforms)
|
|
103
|
+
// - Non-inline drawers: outside wrapper (viewport-relative fixed positioning)
|
|
104
|
+
const overlayInlineDrawerLayers = React.useMemo(
|
|
105
|
+
() => visibleLayers.filter((layer) => {
|
|
106
|
+
if (!layer.drawer?.inline) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return !isRevealMode(layer.drawer.animationMode);
|
|
110
|
+
}),
|
|
111
|
+
[visibleLayers],
|
|
112
|
+
);
|
|
113
|
+
const revealInlineDrawerLayers = React.useMemo(
|
|
114
|
+
() => visibleLayers.filter((layer) => {
|
|
115
|
+
if (!layer.drawer?.inline) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return isRevealMode(layer.drawer.animationMode);
|
|
119
|
+
}),
|
|
120
|
+
[visibleLayers],
|
|
121
|
+
);
|
|
122
|
+
const nonInlineDrawerLayers = React.useMemo(
|
|
123
|
+
() => visibleLayers.filter((layer) => {
|
|
124
|
+
if (!layer.drawer) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
return !layer.drawer.inline;
|
|
128
|
+
}),
|
|
129
|
+
[visibleLayers],
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const hasRevealInlineDrawers = revealInlineDrawerLayers.length > 0;
|
|
133
|
+
|
|
134
|
+
// Grid container element
|
|
135
|
+
const gridElement = (
|
|
136
|
+
<div
|
|
137
|
+
ref={gridRef}
|
|
138
|
+
style={combinedStyle}
|
|
139
|
+
data-dragging={Boolean(draggingLayerId)}
|
|
140
|
+
data-resizing={Boolean(resizingLayerId)}
|
|
141
|
+
data-visible={isIntersecting}
|
|
142
|
+
>
|
|
143
|
+
<GridLayoutProvider value={providerValue}>
|
|
144
|
+
<GridLayerList layers={regularLayers} />
|
|
145
|
+
</GridLayoutProvider>
|
|
146
|
+
|
|
147
|
+
{columnHandles.map(({ trackIndex, align, span }) => (
|
|
148
|
+
<GridTrackResizeHandle
|
|
149
|
+
key={`col-${trackIndex}:${align}`}
|
|
150
|
+
direction="col"
|
|
151
|
+
trackIndex={trackIndex}
|
|
152
|
+
align={align}
|
|
153
|
+
gap={gapSizes.columnGap}
|
|
154
|
+
span={span}
|
|
155
|
+
onResize={handleResize}
|
|
156
|
+
/>
|
|
157
|
+
))}
|
|
158
|
+
|
|
159
|
+
{rowHandles.map(({ trackIndex, align, span }) => (
|
|
160
|
+
<GridTrackResizeHandle
|
|
161
|
+
key={`row-${trackIndex}:${align}`}
|
|
162
|
+
direction="row"
|
|
163
|
+
trackIndex={trackIndex}
|
|
164
|
+
align={align}
|
|
165
|
+
gap={gapSizes.rowGap}
|
|
166
|
+
span={span}
|
|
167
|
+
onResize={handleResize}
|
|
168
|
+
/>
|
|
169
|
+
))}
|
|
170
|
+
|
|
171
|
+
{/* Inline overlay drawers rendered inside grid container for proper absolute positioning */}
|
|
172
|
+
<DrawerLayers layers={overlayInlineDrawerLayers} />
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// For reveal inline drawers, wrap grid and drawer in a container
|
|
177
|
+
// so drawer can be positioned relative to the container (not viewport)
|
|
178
|
+
// while grid transforms without affecting drawer position
|
|
179
|
+
if (hasRevealInlineDrawers) {
|
|
180
|
+
return (
|
|
181
|
+
<>
|
|
182
|
+
<div style={{ position: "relative", width: "100%", height: "100%" }}>
|
|
183
|
+
{gridElement}
|
|
184
|
+
{/* Reveal inline drawers as grid siblings - stay fixed while grid transforms */}
|
|
185
|
+
<DrawerLayers layers={revealInlineDrawerLayers} />
|
|
186
|
+
</div>
|
|
187
|
+
{/* Non-inline drawers outside wrapper for viewport-relative positioning */}
|
|
188
|
+
<DrawerLayers layers={nonInlineDrawerLayers} />
|
|
189
|
+
</>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
87
193
|
return (
|
|
88
194
|
<>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
data-dragging={Boolean(draggingLayerId)}
|
|
93
|
-
data-resizing={Boolean(resizingLayerId)}
|
|
94
|
-
data-visible={isIntersecting}
|
|
95
|
-
>
|
|
96
|
-
<GridLayoutProvider value={providerValue}>
|
|
97
|
-
<GridLayerList layers={regularLayers} />
|
|
98
|
-
</GridLayoutProvider>
|
|
99
|
-
|
|
100
|
-
{columnHandles.map(({ trackIndex, align, span }) => (
|
|
101
|
-
<GridTrackResizeHandle
|
|
102
|
-
key={`col-${trackIndex}:${align}`}
|
|
103
|
-
direction="col"
|
|
104
|
-
trackIndex={trackIndex}
|
|
105
|
-
align={align}
|
|
106
|
-
gap={gapSizes.columnGap}
|
|
107
|
-
span={span}
|
|
108
|
-
onResize={handleResize}
|
|
109
|
-
/>
|
|
110
|
-
))}
|
|
111
|
-
|
|
112
|
-
{rowHandles.map(({ trackIndex, align, span }) => (
|
|
113
|
-
<GridTrackResizeHandle
|
|
114
|
-
key={`row-${trackIndex}:${align}`}
|
|
115
|
-
direction="row"
|
|
116
|
-
trackIndex={trackIndex}
|
|
117
|
-
align={align}
|
|
118
|
-
gap={gapSizes.rowGap}
|
|
119
|
-
span={span}
|
|
120
|
-
onResize={handleResize}
|
|
121
|
-
/>
|
|
122
|
-
))}
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
|
-
<DrawerLayers layers={visibleLayers} />
|
|
195
|
+
{gridElement}
|
|
196
|
+
{/* Non-inline drawers for viewport-relative positioning */}
|
|
197
|
+
<DrawerLayers layers={nonInlineDrawerLayers} />
|
|
126
198
|
</>
|
|
127
199
|
);
|
|
128
200
|
};
|