@multiplatform.one/forms 7.21.0 → 7.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/cjs/FloatingPanel/index.cjs +85 -29
  2. package/dist/cjs/FloatingPanel/index.native.js +108 -11
  3. package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
  4. package/dist/cjs/FloatingPanel/pointAnchor.cjs +88 -0
  5. package/dist/cjs/FloatingPanel/pointAnchor.native.js +98 -0
  6. package/dist/cjs/FloatingPanel/pointAnchor.native.js.map +1 -0
  7. package/dist/cjs/FloatingPanel/useFloatingPanel.cjs +4 -3
  8. package/dist/cjs/FloatingPanel/useFloatingPanel.native.js +4 -3
  9. package/dist/cjs/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  10. package/dist/esm/FloatingPanel/index.mjs +86 -30
  11. package/dist/esm/FloatingPanel/index.mjs.map +1 -1
  12. package/dist/esm/FloatingPanel/index.native.js +107 -10
  13. package/dist/esm/FloatingPanel/index.native.js.map +1 -1
  14. package/dist/esm/FloatingPanel/pointAnchor.mjs +59 -0
  15. package/dist/esm/FloatingPanel/pointAnchor.mjs.map +1 -0
  16. package/dist/esm/FloatingPanel/pointAnchor.native.js +66 -0
  17. package/dist/esm/FloatingPanel/pointAnchor.native.js.map +1 -0
  18. package/dist/esm/FloatingPanel/useFloatingPanel.mjs +4 -3
  19. package/dist/esm/FloatingPanel/useFloatingPanel.mjs.map +1 -1
  20. package/dist/esm/FloatingPanel/useFloatingPanel.native.js +4 -3
  21. package/dist/esm/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  22. package/dist/jsx/FloatingPanel/index.mjs +86 -30
  23. package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
  24. package/dist/jsx/FloatingPanel/index.native.js +108 -11
  25. package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
  26. package/dist/jsx/FloatingPanel/pointAnchor.mjs +59 -0
  27. package/dist/jsx/FloatingPanel/pointAnchor.mjs.map +1 -0
  28. package/dist/jsx/FloatingPanel/pointAnchor.native.js +98 -0
  29. package/dist/jsx/FloatingPanel/pointAnchor.native.js.map +1 -0
  30. package/dist/jsx/FloatingPanel/useFloatingPanel.mjs +4 -3
  31. package/dist/jsx/FloatingPanel/useFloatingPanel.mjs.map +1 -1
  32. package/dist/jsx/FloatingPanel/useFloatingPanel.native.js +4 -3
  33. package/dist/jsx/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  34. package/package.json +8 -8
  35. package/src/FloatingPanel/FloatingPanel.pointMenu.native.spec.tsx +126 -0
  36. package/src/FloatingPanel/index.native.tsx +199 -81
  37. package/src/FloatingPanel/index.tsx +130 -42
  38. package/src/FloatingPanel/pointAnchor.spec.ts +141 -0
  39. package/src/FloatingPanel/pointAnchor.ts +122 -0
  40. package/src/FloatingPanel/useFloatingPanel.ts +9 -2
  41. package/types/FloatingPanel/index.d.ts +4 -1
  42. package/types/FloatingPanel/index.d.ts.map +1 -1
  43. package/types/FloatingPanel/index.native.d.ts +5 -0
  44. package/types/FloatingPanel/index.native.d.ts.map +1 -1
  45. package/types/FloatingPanel/pointAnchor.d.ts +66 -0
  46. package/types/FloatingPanel/pointAnchor.d.ts.map +1 -0
  47. package/types/FloatingPanel/useFloatingPanel.d.ts +7 -1
  48. package/types/FloatingPanel/useFloatingPanel.d.ts.map +1 -1
@@ -0,0 +1,141 @@
1
+ import { OVERLAY_ANCHOR_GAP } from "@multiplatform.one/theme";
2
+ import { describe, expect, it } from "vitest";
3
+ import {
4
+ contextMenuPoint,
5
+ placeAtPoint,
6
+ pointOpensUp,
7
+ pointPanelLeft,
8
+ type PanelBounds,
9
+ } from "./pointAnchor";
10
+
11
+ const bounds: PanelBounds = { top: 10, left: 10, right: 1014, bottom: 758 };
12
+ const gap = OVERLAY_ANCHOR_GAP;
13
+
14
+ describe("pointPanelLeft", () => {
15
+ it("puts the panel's start edge on the point when it fits", () => {
16
+ expect(pointPanelLeft({ x: 300, y: 0 }, 200, bounds)).toEqual({ left: 300, alignEnd: false });
17
+ });
18
+
19
+ it("flips to open toward the start when the end side would overflow", () => {
20
+ expect(pointPanelLeft({ x: 900, y: 0 }, 200, bounds)).toEqual({ left: 700, alignEnd: true });
21
+ });
22
+
23
+ it("clamps into the bounds when neither side fits", () => {
24
+ const narrow: PanelBounds = { top: 10, left: 10, right: 310, bottom: 758 };
25
+ expect(pointPanelLeft({ x: 200, y: 0 }, 250, narrow)).toEqual({ left: 60, alignEnd: false });
26
+ });
27
+
28
+ it("pins to the start bound when the panel is wider than the bounds", () => {
29
+ const narrow: PanelBounds = { top: 10, left: 10, right: 110, bottom: 758 };
30
+ expect(pointPanelLeft({ x: 50, y: 0 }, 400, narrow).left).toBe(10);
31
+ });
32
+
33
+ it("opens toward the left from the point in RTL and flips right at the left edge", () => {
34
+ expect(pointPanelLeft({ x: 600, y: 0 }, 200, bounds, true)).toEqual({
35
+ left: 400,
36
+ alignEnd: false,
37
+ });
38
+ expect(pointPanelLeft({ x: 100, y: 0 }, 200, bounds, true)).toEqual({
39
+ left: 100,
40
+ alignEnd: true,
41
+ });
42
+ });
43
+ });
44
+
45
+ describe("pointOpensUp", () => {
46
+ it("opens down whenever the panel fits below the point", () => {
47
+ expect(pointOpensUp({ x: 0, y: 600 }, 150, bounds, gap)).toBe(false);
48
+ });
49
+
50
+ it("flips up when only the space above fits", () => {
51
+ expect(pointOpensUp({ x: 0, y: 700 }, 150, bounds, gap)).toBe(true);
52
+ });
53
+
54
+ it("takes the roomier side when neither fits", () => {
55
+ expect(pointOpensUp({ x: 0, y: 300 }, 700, bounds, gap)).toBe(false);
56
+ expect(pointOpensUp({ x: 0, y: 500 }, 700, bounds, gap)).toBe(true);
57
+ });
58
+ });
59
+
60
+ describe("placeAtPoint", () => {
61
+ it("sits OVERLAY_ANCHOR_GAP below the point, start edge on the point", () => {
62
+ expect(
63
+ placeAtPoint({ point: { x: 300, y: 200 }, width: 180, height: 120, bounds, gap }),
64
+ ).toEqual({
65
+ left: 300,
66
+ top: 200 + gap,
67
+ maxHeight: 758 - (200 + gap),
68
+ dropup: false,
69
+ alignEnd: false,
70
+ });
71
+ });
72
+
73
+ it("flips both ways in the bottom-right corner, bottom edge gap above the point", () => {
74
+ const placement = placeAtPoint({
75
+ point: { x: 1000, y: 740 },
76
+ width: 180,
77
+ height: 120,
78
+ bounds,
79
+ gap,
80
+ });
81
+ expect(placement.left).toBe(1000 - 180);
82
+ expect(placement.top).toBe(740 - gap - 120);
83
+ expect(placement.dropup).toBe(true);
84
+ expect(placement.alignEnd).toBe(true);
85
+ });
86
+
87
+ it("caps the height at the chosen side's room, so a tall menu scrolls inside the bounds", () => {
88
+ const placement = placeAtPoint({
89
+ point: { x: 300, y: 500 },
90
+ width: 180,
91
+ height: 900,
92
+ bounds,
93
+ gap,
94
+ });
95
+ expect(placement.dropup).toBe(true);
96
+ expect(placement.maxHeight).toBe(500 - gap - 10);
97
+ expect(placement.top).toBe(10);
98
+ });
99
+ });
100
+
101
+ describe("contextMenuPoint", () => {
102
+ const reference = {
103
+ getBoundingClientRect: () => ({ left: 40, right: 240, top: 100, bottom: 144 }),
104
+ };
105
+
106
+ it("takes the pointer's viewport coordinates from a mouse right-click", () => {
107
+ expect(
108
+ contextMenuPoint({ clientX: 120, clientY: 130, button: 2, pointerType: "mouse" }, reference),
109
+ ).toEqual({ x: 120, y: 130 });
110
+ });
111
+
112
+ it("takes the press point from a touch long-press", () => {
113
+ expect(
114
+ contextMenuPoint({ clientX: 90, clientY: 110, button: 0, pointerType: "touch" }, reference),
115
+ ).toEqual({ x: 90, y: 110 });
116
+ });
117
+
118
+ it("takes a right-click's coordinates when the event is a plain MouseEvent", () => {
119
+ expect(contextMenuPoint({ clientX: 150, clientY: 120, button: 2 }, reference)).toEqual({
120
+ x: 150,
121
+ y: 120,
122
+ });
123
+ });
124
+
125
+ it("anchors a keyboard open (Shift+F10, the Menu key) to the target's bottom start corner", () => {
126
+ expect(
127
+ contextMenuPoint({ clientX: 0, clientY: 0, button: 0, pointerType: "" }, reference),
128
+ ).toEqual({ x: 40, y: 144 });
129
+ expect(contextMenuPoint({ clientX: 0, clientY: 0, button: 0 }, reference)).toEqual({
130
+ x: 40,
131
+ y: 144,
132
+ });
133
+ expect(
134
+ contextMenuPoint({ clientX: 0, clientY: 0, button: 0, pointerType: "" }, reference, true),
135
+ ).toEqual({ x: 240, y: 144 });
136
+ });
137
+
138
+ it("has no point without a pointer or a reference", () => {
139
+ expect(contextMenuPoint({ clientX: 0, clientY: 0, button: 0 }, null)).toBeNull();
140
+ });
141
+ });
@@ -0,0 +1,122 @@
1
+ import { OVERLAY_ANCHOR_GAP } from "@multiplatform.one/theme";
2
+
3
+ /**
4
+ * A panel opened at a POINT rather than from a trigger's box: the ContextMenu
5
+ * gesture (MPO-21 G5). layoutTokens.ts files a pointer-positioned context menu
6
+ * as a FREE overlay: content-sized, `OVERLAY_ANCHOR_GAP` from its anchor,
7
+ * flipping at the viewport edges instead of overflowing. The anchor here is a
8
+ * zero-size box at the point, so "start-aligned to the anchor" puts the
9
+ * panel's start edge on the pointer's x.
10
+ */
11
+ export interface PanelPoint {
12
+ x: number;
13
+ y: number;
14
+ }
15
+
16
+ /** The box a panel must stay inside, already inset by padding and safe area. */
17
+ export interface PanelBounds {
18
+ top: number;
19
+ right: number;
20
+ bottom: number;
21
+ left: number;
22
+ }
23
+
24
+ export function pointPanelLeft(
25
+ point: PanelPoint,
26
+ width: number,
27
+ bounds: PanelBounds,
28
+ rtl = false,
29
+ ): { left: number; alignEnd: boolean } {
30
+ const towardEnd = rtl ? point.x - width : point.x;
31
+ const towardStart = rtl ? point.x : point.x - width;
32
+ const fits = (left: number) => left >= bounds.left && left + width <= bounds.right;
33
+ const alignEnd = !fits(towardEnd) && fits(towardStart);
34
+ const raw = alignEnd ? towardStart : towardEnd;
35
+ return { left: Math.max(bounds.left, Math.min(raw, bounds.right - width)), alignEnd };
36
+ }
37
+
38
+ /** Below when it fits, above when only that fits, else the roomier side. */
39
+ export function pointOpensUp(
40
+ point: PanelPoint,
41
+ height: number,
42
+ bounds: PanelBounds,
43
+ gap: number = OVERLAY_ANCHOR_GAP,
44
+ ): boolean {
45
+ const below = bounds.bottom - (point.y + gap);
46
+ const above = point.y - gap - bounds.top;
47
+ if (height <= below) return false;
48
+ if (height <= above) return true;
49
+ return above > below;
50
+ }
51
+
52
+ export interface PointPlacement {
53
+ left: number;
54
+ top: number;
55
+ maxHeight: number;
56
+ dropup: boolean;
57
+ alignEnd: boolean;
58
+ }
59
+
60
+ export function placeAtPoint({
61
+ point,
62
+ width,
63
+ height,
64
+ bounds,
65
+ gap = OVERLAY_ANCHOR_GAP,
66
+ rtl = false,
67
+ }: {
68
+ point: PanelPoint;
69
+ width: number;
70
+ height: number;
71
+ bounds: PanelBounds;
72
+ gap?: number;
73
+ rtl?: boolean;
74
+ }): PointPlacement {
75
+ const { left, alignEnd } = pointPanelLeft(point, width, bounds, rtl);
76
+ const dropup = pointOpensUp(point, height, bounds, gap);
77
+ const maxHeight = Math.max(
78
+ 0,
79
+ dropup ? point.y - gap - bounds.top : bounds.bottom - (point.y + gap),
80
+ );
81
+ const top = dropup ? point.y - gap - Math.min(height, maxHeight) : point.y + gap;
82
+ return { left, top, maxHeight, dropup, alignEnd };
83
+ }
84
+
85
+ export interface ContextMenuEventLike {
86
+ clientX: number;
87
+ clientY: number;
88
+ button?: number;
89
+ pointerType?: string;
90
+ }
91
+
92
+ /**
93
+ * Where a `contextmenu` event asks the menu to open. A mouse right-click or a
94
+ * touch long-press carries the pointer's viewport coordinates. A keyboard open
95
+ * (Shift+F10, the Menu key) has no pointer: Chromium sends a PointerEvent with
96
+ * an empty `pointerType` aimed at the focused element's centre
97
+ * (`EventHandler::ShowNonLocatedContextMenu`). It opens from the target's
98
+ * bottom start corner. A plain MouseEvent counts as a pointer only when it is
99
+ * a right-click or carries coordinates.
100
+ */
101
+ export function contextMenuPoint(
102
+ event: ContextMenuEventLike,
103
+ reference: PointReference | null,
104
+ rtl = false,
105
+ ): PanelPoint | null {
106
+ const fromPointer =
107
+ event.pointerType !== undefined
108
+ ? event.pointerType !== ""
109
+ : event.button === 2 || event.clientX !== 0 || event.clientY !== 0;
110
+ if (fromPointer) return { x: event.clientX, y: event.clientY };
111
+ return reference ? referenceCornerPoint(reference, rtl) : null;
112
+ }
113
+
114
+ export interface PointReference {
115
+ getBoundingClientRect(): { left: number; right: number; bottom: number };
116
+ }
117
+
118
+ /** The target's bottom start corner: where a menu with no pointer opens. */
119
+ export function referenceCornerPoint(reference: PointReference, rtl = false): PanelPoint {
120
+ const rect = reference.getBoundingClientRect();
121
+ return { x: rtl ? rect.right : rect.left, y: rect.bottom };
122
+ }
@@ -104,6 +104,12 @@ export interface UseFloatingPanelOptions {
104
104
  * at the compact space step.
105
105
  */
106
106
  compact?: boolean;
107
+ /**
108
+ * The panel opens at a point, not from the trigger's box (ContextMenu). It
109
+ * shares no corner with the trigger, so its radius stays the CONTAINER-CAP
110
+ * value instead of dropping to the trigger's drawn arc.
111
+ */
112
+ freeOverlay?: boolean;
107
113
  }
108
114
 
109
115
  /** One place that resolves the deprecated boolean onto the three modes, so
@@ -225,6 +231,7 @@ export function useFloatingPanel({
225
231
  widthMode: widthModeProp,
226
232
  fitContent,
227
233
  compact,
234
+ freeOverlay = false,
228
235
  }: UseFloatingPanelOptions): UseFloatingPanelReturn {
229
236
  const widthMode = resolvePanelWidthMode(widthModeProp, fitContent);
230
237
  const { knobProps } = useResolvedKnobs({ compact });
@@ -295,14 +302,14 @@ export function useFloatingPanel({
295
302
  const setupForOpen = useCallback(() => {
296
303
  computePlacement();
297
304
  if (canUseDom && triggerRef.current) {
298
- setMeasuredRadius(measureDrawnRadius(triggerRef.current));
305
+ setMeasuredRadius(freeOverlay ? null : measureDrawnRadius(triggerRef.current));
299
306
  }
300
307
  onBeforeOpenRef.current?.();
301
308
  if (closingTimerRef.current) clearTimeout(closingTimerRef.current);
302
309
  floatingStyleRef.current = {};
303
310
  initializingRef.current = true;
304
311
  setMounted(true);
305
- }, [computePlacement]);
312
+ }, [computePlacement, freeOverlay]);
306
313
 
307
314
  // ── Lifecycle effect ──────────────────────────────────────
308
315
 
@@ -112,7 +112,10 @@ export interface FloatingPanelProps {
112
112
  * How the trigger opens the panel. `"press"` (default) is click/tap.
113
113
  * `"contextmenu"` is the ContextMenu gesture: web `contextmenu` (right-click
114
114
  * / Shift+F10), native long-press. Primary click does not open. Same overlay
115
- * stack — not a second positioning engine.
115
+ * stack — not a second positioning engine. The floating panel opens AT the
116
+ * gesture's point as a free overlay (`OVERLAY_ANCHOR_GAP` from it, flipping
117
+ * at the viewport edges); a keyboard open has no point and opens from the
118
+ * trigger's bottom start corner.
116
119
  */
117
120
  openOn?: "press" | "contextmenu";
118
121
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;AAsB3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOzD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAI5B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,2FAA2F;IAC3F,kBAAkB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,EAAE,SAAS,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C;;;;;OAKG;IACH,WAAW,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;CAClC;AA4GD,wBAAgB,eAAe,YAE9B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CAWtD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;AAuB3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAezD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAI5B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,2FAA2F;IAC3F,kBAAkB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,EAAE,SAAS,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C;;;;;OAKG;IACH,WAAW,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;CAClC;AAuHD,wBAAgB,eAAe,YAE9B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CAWtD"}
@@ -43,6 +43,11 @@
43
43
  * and the sheet never appears. Fields should not also toggle open on native.
44
44
  * - Opening a Modal under the same finger can synthesize a backdrop press;
45
45
  * backdrop dismiss is armed a short delay after the present begins.
46
+ *
47
+ * ContextMenu (`openOn="contextmenu"`): long-press opens it. On a window wider
48
+ * than OVERLAY_BREAKPOINT (a tablet) it opens at the long-press point, the
49
+ * same free overlay the web draws at the pointer; a phone keeps the sheet,
50
+ * as web does at ≤640.
46
51
  */
47
52
  import type { FloatingPanelProps } from "./index";
48
53
  export { useFloatingPanel, panelAnimationDuration, panelGrowDuration, panelTransition, panelViewportPadding, } from "./useFloatingPanel";
@@ -1 +1 @@
1
- {"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/index.native.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AA4BH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAKlD,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,uFAAuF;AACvF,wBAAgB,eAAe,YAE9B;AAmBD,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,UAAU,EACV,aAAyB,EACzB,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,cAA0B,EAC1B,MAAM,EACN,eAAe,EACf,WAAW,EACX,SAAS,EACT,MAAgB,GACjB,EAAE,kBAAkB,2CA+bpB"}
1
+ {"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/index.native.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AA+BH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAOlD,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,uFAAuF;AACvF,wBAAgB,eAAe,YAE9B;AAmBD,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,UAAU,EACV,aAAyB,EACzB,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,cAA0B,EAC1B,MAAM,EACN,eAAe,EACf,WAAW,EACX,SAAS,EACT,MAAgB,GACjB,EAAE,kBAAkB,2CAiepB"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * A panel opened at a POINT rather than from a trigger's box: the ContextMenu
3
+ * gesture (MPO-21 G5). layoutTokens.ts files a pointer-positioned context menu
4
+ * as a FREE overlay: content-sized, `OVERLAY_ANCHOR_GAP` from its anchor,
5
+ * flipping at the viewport edges instead of overflowing. The anchor here is a
6
+ * zero-size box at the point, so "start-aligned to the anchor" puts the
7
+ * panel's start edge on the pointer's x.
8
+ */
9
+ export interface PanelPoint {
10
+ x: number;
11
+ y: number;
12
+ }
13
+ /** The box a panel must stay inside, already inset by padding and safe area. */
14
+ export interface PanelBounds {
15
+ top: number;
16
+ right: number;
17
+ bottom: number;
18
+ left: number;
19
+ }
20
+ export declare function pointPanelLeft(point: PanelPoint, width: number, bounds: PanelBounds, rtl?: boolean): {
21
+ left: number;
22
+ alignEnd: boolean;
23
+ };
24
+ /** Below when it fits, above when only that fits, else the roomier side. */
25
+ export declare function pointOpensUp(point: PanelPoint, height: number, bounds: PanelBounds, gap?: number): boolean;
26
+ export interface PointPlacement {
27
+ left: number;
28
+ top: number;
29
+ maxHeight: number;
30
+ dropup: boolean;
31
+ alignEnd: boolean;
32
+ }
33
+ export declare function placeAtPoint({ point, width, height, bounds, gap, rtl, }: {
34
+ point: PanelPoint;
35
+ width: number;
36
+ height: number;
37
+ bounds: PanelBounds;
38
+ gap?: number;
39
+ rtl?: boolean;
40
+ }): PointPlacement;
41
+ export interface ContextMenuEventLike {
42
+ clientX: number;
43
+ clientY: number;
44
+ button?: number;
45
+ pointerType?: string;
46
+ }
47
+ /**
48
+ * Where a `contextmenu` event asks the menu to open. A mouse right-click or a
49
+ * touch long-press carries the pointer's viewport coordinates. A keyboard open
50
+ * (Shift+F10, the Menu key) has no pointer: Chromium sends a PointerEvent with
51
+ * an empty `pointerType` aimed at the focused element's centre
52
+ * (`EventHandler::ShowNonLocatedContextMenu`). It opens from the target's
53
+ * bottom start corner. A plain MouseEvent counts as a pointer only when it is
54
+ * a right-click or carries coordinates.
55
+ */
56
+ export declare function contextMenuPoint(event: ContextMenuEventLike, reference: PointReference | null, rtl?: boolean): PanelPoint | null;
57
+ export interface PointReference {
58
+ getBoundingClientRect(): {
59
+ left: number;
60
+ right: number;
61
+ bottom: number;
62
+ };
63
+ }
64
+ /** The target's bottom start corner: where a menu with no pointer opens. */
65
+ export declare function referenceCornerPoint(reference: PointReference, rtl?: boolean): PanelPoint;
66
+ //# sourceMappingURL=pointAnchor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointAnchor.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/pointAnchor.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,GAAG,UAAQ,GACV;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAOrC;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAC1B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,GAAG,GAAE,MAA2B,GAC/B,OAAO,CAMT;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,KAAK,EACL,MAAM,EACN,MAAM,EACN,GAAwB,EACxB,GAAW,GACZ,EAAE;IACD,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,GAAG,cAAc,CASjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,cAAc,GAAG,IAAI,EAChC,GAAG,UAAQ,GACV,UAAU,GAAG,IAAI,CAOnB;AAED,MAAM,WAAW,cAAc;IAC7B,qBAAqB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1E;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,UAAQ,GAAG,UAAU,CAGvF"}
@@ -65,6 +65,12 @@ export interface UseFloatingPanelOptions {
65
65
  * at the compact space step.
66
66
  */
67
67
  compact?: boolean;
68
+ /**
69
+ * The panel opens at a point, not from the trigger's box (ContextMenu). It
70
+ * shares no corner with the trigger, so its radius stays the CONTAINER-CAP
71
+ * value instead of dropping to the trigger's drawn arc.
72
+ */
73
+ freeOverlay?: boolean;
68
74
  }
69
75
  /** One place that resolves the deprecated boolean onto the three modes, so
70
76
  * the hook and the component cannot disagree about what a consumer meant. */
@@ -111,5 +117,5 @@ export interface UseFloatingPanelReturn {
111
117
  * declared, so the only way to lock it is to feed it real boxes.
112
118
  */
113
119
  export declare function measureDrawnRadius(el: HTMLElement): number | null;
114
- export declare function useFloatingPanel({ open, onOpenChange, disabled, onBeforeOpen, repositionRef, scrollBoundaryRef, middleware: middlewareProp, useAutoUpdate: useAutoUpdateProp, wheelGrowRef, widthMode: widthModeProp, fitContent, compact, }: UseFloatingPanelOptions): UseFloatingPanelReturn;
120
+ export declare function useFloatingPanel({ open, onOpenChange, disabled, onBeforeOpen, repositionRef, scrollBoundaryRef, middleware: middlewareProp, useAutoUpdate: useAutoUpdateProp, wheelGrowRef, widthMode: widthModeProp, fitContent, compact, freeOverlay, }: UseFloatingPanelOptions): UseFloatingPanelReturn;
115
121
  //# sourceMappingURL=useFloatingPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useFloatingPanel.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/useFloatingPanel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useFloatingPanel.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/useFloatingPanel.ts"],"names":[],"mappings":"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"}