@multiplatform.one/forms 7.45.1 → 7.46.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 (43) hide show
  1. package/dist/cjs/FloatingPanel/index.cjs +158 -40
  2. package/dist/cjs/shared/focusManagement.cjs +3 -3
  3. package/dist/cjs/shared/focusManagement.native.js +3 -3
  4. package/dist/cjs/shared/focusManagement.native.js.map +1 -1
  5. package/dist/cjs/shared/useSheetEscapeDismiss.cjs +5 -4
  6. package/dist/cjs/shared/useSheetEscapeDismiss.native.js +5 -3
  7. package/dist/cjs/shared/useSheetEscapeDismiss.native.js.map +1 -1
  8. package/dist/esm/FloatingPanel/index.mjs +160 -42
  9. package/dist/esm/FloatingPanel/index.mjs.map +1 -1
  10. package/dist/esm/shared/focusManagement.mjs +3 -3
  11. package/dist/esm/shared/focusManagement.mjs.map +1 -1
  12. package/dist/esm/shared/focusManagement.native.js +3 -3
  13. package/dist/esm/shared/focusManagement.native.js.map +1 -1
  14. package/dist/esm/shared/useSheetEscapeDismiss.mjs +5 -4
  15. package/dist/esm/shared/useSheetEscapeDismiss.mjs.map +1 -1
  16. package/dist/esm/shared/useSheetEscapeDismiss.native.js +5 -3
  17. package/dist/esm/shared/useSheetEscapeDismiss.native.js.map +1 -1
  18. package/dist/jsx/FloatingPanel/index.mjs +160 -42
  19. package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
  20. package/dist/jsx/shared/focusManagement.mjs +3 -3
  21. package/dist/jsx/shared/focusManagement.mjs.map +1 -1
  22. package/dist/jsx/shared/focusManagement.native.js +3 -3
  23. package/dist/jsx/shared/focusManagement.native.js.map +1 -1
  24. package/dist/jsx/shared/useSheetEscapeDismiss.mjs +5 -4
  25. package/dist/jsx/shared/useSheetEscapeDismiss.mjs.map +1 -1
  26. package/dist/jsx/shared/useSheetEscapeDismiss.native.js +5 -3
  27. package/dist/jsx/shared/useSheetEscapeDismiss.native.js.map +1 -1
  28. package/package.json +8 -8
  29. package/src/FloatingPanel/FloatingPanel.coverTrigger.spec.tsx +184 -0
  30. package/src/FloatingPanel/FloatingPanel.spec.tsx +3 -5
  31. package/src/FloatingPanel/FloatingPanel.stories.tsx +26 -0
  32. package/src/FloatingPanel/index.tsx +255 -59
  33. package/src/FloatingPanel/useFloatingPanel.spec.tsx +4 -2
  34. package/src/shared/focusManagement.spec.tsx +11 -1
  35. package/src/shared/focusManagement.ts +16 -7
  36. package/src/shared/interactionHooks.spec.tsx +13 -0
  37. package/src/shared/useSheetEscapeDismiss.ts +9 -4
  38. package/types/FloatingPanel/index.d.ts +9 -1
  39. package/types/FloatingPanel/index.d.ts.map +1 -1
  40. package/types/shared/focusManagement.d.ts +10 -5
  41. package/types/shared/focusManagement.d.ts.map +1 -1
  42. package/types/shared/useSheetEscapeDismiss.d.ts +1 -1
  43. package/types/shared/useSheetEscapeDismiss.d.ts.map +1 -1
@@ -61,6 +61,19 @@ describe("useSheetEscapeDismiss", () => {
61
61
  expect(second).toHaveBeenCalledTimes(1);
62
62
  });
63
63
 
64
+ it("listens on document when asked, so a document-level stopPropagation cannot block it", () => {
65
+ const onDismiss = vi.fn();
66
+ const stop = (event: Event) => event.stopPropagation();
67
+ document.addEventListener("keydown", stop);
68
+ try {
69
+ renderHook(() => useSheetEscapeDismiss(true, onDismiss, "document"));
70
+ document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true }));
71
+ expect(onDismiss).toHaveBeenCalledTimes(1);
72
+ } finally {
73
+ document.removeEventListener("keydown", stop);
74
+ }
75
+ });
76
+
64
77
  it("detaches the listener on unmount", () => {
65
78
  const onDismiss = vi.fn();
66
79
  const { unmount } = renderHook(() => useSheetEscapeDismiss(true, onDismiss));
@@ -11,7 +11,11 @@ import { isWeb } from "tamagui";
11
11
  * comboboxes) that own Escape call stopPropagation()/preventDefault() and
12
12
  * keep the sheet open.
13
13
  */
14
- export function useSheetEscapeDismiss(enabled: boolean, onDismiss: () => void) {
14
+ export function useSheetEscapeDismiss(
15
+ enabled: boolean,
16
+ onDismiss: () => void,
17
+ target: "window" | "document" = "window",
18
+ ) {
15
19
  const onDismissRef = useRef(onDismiss);
16
20
  onDismissRef.current = onDismiss;
17
21
  useEffect(() => {
@@ -20,7 +24,8 @@ export function useSheetEscapeDismiss(enabled: boolean, onDismiss: () => void) {
20
24
  if (event.key !== "Escape" || event.defaultPrevented) return;
21
25
  onDismissRef.current();
22
26
  };
23
- window.addEventListener("keydown", onKeyDown);
24
- return () => window.removeEventListener("keydown", onKeyDown);
25
- }, [enabled]);
27
+ const node = target === "document" ? document : window;
28
+ node.addEventListener("keydown", onKeyDown as EventListener);
29
+ return () => node.removeEventListener("keydown", onKeyDown as EventListener);
30
+ }, [enabled, target]);
26
31
  }
@@ -11,6 +11,14 @@ export interface FloatingPanelProps {
11
11
  /** Suppress delayed trigger focus when a consumer handles close focus itself. Web only. */
12
12
  skipReturnFocusRef?: RefObject<boolean>;
13
13
  trigger: ReactNode;
14
+ anchorMode?: "cover-trigger" | "attach";
15
+ triggerRow?: ReactNode;
16
+ anchorRect?: {
17
+ x: number;
18
+ y: number;
19
+ width: number;
20
+ height: number;
21
+ };
14
22
  triggerEcho?: boolean;
15
23
  /**
16
24
  * Optional control rendered beside the trigger but OUTSIDE the native press
@@ -117,7 +125,7 @@ export interface FloatingPanelProps {
117
125
  * COVER-TRIGGER (LC-105): the panel's top edge sits on the trigger's TOP
118
126
  * edge instead of attaching below it, so the trigger becomes the panel's
119
127
  * first row by default. Set triggerEcho=false for a custom first row. The panel scales from
120
- * the trigger's top start corner. Dropping up, the bottom edges coincide.
128
+ * the trigger's top start corner. Viewport collisions use the bottom sheet.
121
129
  * Enabled by default. Web float only; the native and narrow-web sheet is unchanged.
122
130
  */
123
131
  cover?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;AAwB3D,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,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;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;;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;IACjC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA2LD,wBAAgB,eAAe,YAE9B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CActD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FloatingPanel/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;AA2B3D,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,UAAU,CAAC,EAAE,eAAe,GAAG,QAAQ,CAAC;IACxC,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,UAAU,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;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;;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;IACjC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAgPD,wBAAgB,eAAe,YAE9B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CAkBtD"}
@@ -6,9 +6,9 @@
6
6
  * only remembers a `Dialog.Trigger` mounted inside the Dialog. These hooks
7
7
  * close that gap:
8
8
  *
9
- * - `useReturnFocusOnClose(open)` — capture the focused element when `open`
10
- * flips true; when it flips false, return focus to it IF focus was dropped
11
- * (on body, or stranded inside a hidden/removed overlay). Never steals
9
+ * - `useReturnFocusOnClose(open, skip?, insideRef?)` — capture the focused
10
+ * element when `open` flips true; when it flips false, return focus to it
11
+ * IF focus was dropped (on body, or stranded inside the closing overlay). Never steals
12
12
  * focus the user deliberately moved elsewhere (outside-click onto another
13
13
  * control).
14
14
  * - `useSheetModalFocus(open, frameRef)` — sheet-mode complement: also moves
@@ -34,8 +34,13 @@
34
34
  * Web-only; both are no-ops on native.
35
35
  */
36
36
  import { type RefObject } from "react";
37
- /** Restore focus to the element focused at open time, on close (web only). */
38
- export declare function useReturnFocusOnClose(open: boolean, skipReturnFocusRef?: RefObject<boolean>): void;
37
+ /**
38
+ * Restore focus to the element focused at open time, on close (web only).
39
+ * `insideRef` is the closing overlay's frame: focus still inside it counts as
40
+ * dropped, because it falls to <body> when the frame unmounts after the exit
41
+ * and no retry runs that late.
42
+ */
43
+ export declare function useReturnFocusOnClose(open: boolean, skipReturnFocusRef?: RefObject<boolean>, insideRef?: RefObject<HTMLElement | null>): void;
39
44
  /**
40
45
  * Sheet-mode modal focus: on open, move focus into the frame (frame itself is
41
46
  * the target — it must carry `tabIndex={-1}`); while open, trap Tab inside;
@@ -1 +1 @@
1
- {"version":3,"file":"focusManagement.d.ts","sourceRoot":"","sources":["../../src/shared/focusManagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AA8D1D,8EAA8E;AAC9E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,kBAAkB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,QAgB3F;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACvC,kBAAkB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,QA+DxC;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,QAWzE;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,EAC9B,eAAe,GAChB,EAAE;IACD,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACzC,GAAG,IAAI,CAGP"}
1
+ {"version":3,"file":"focusManagement.d.ts","sourceRoot":"","sources":["../../src/shared/focusManagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AA8D1D;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,OAAO,EACb,kBAAkB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,EACvC,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,QAiB1C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACvC,kBAAkB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,QA+DxC;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,QAWzE;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,EAC9B,eAAe,GAChB,EAAE;IACD,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACzC,GAAG,IAAI,CAGP"}
@@ -8,5 +8,5 @@
8
8
  * comboboxes) that own Escape call stopPropagation()/preventDefault() and
9
9
  * keep the sheet open.
10
10
  */
11
- export declare function useSheetEscapeDismiss(enabled: boolean, onDismiss: () => void): void;
11
+ export declare function useSheetEscapeDismiss(enabled: boolean, onDismiss: () => void, target?: "window" | "document"): void;
12
12
  //# sourceMappingURL=useSheetEscapeDismiss.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSheetEscapeDismiss.d.ts","sourceRoot":"","sources":["../../src/shared/useSheetEscapeDismiss.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,QAY5E"}
1
+ {"version":3,"file":"useSheetEscapeDismiss.d.ts","sourceRoot":"","sources":["../../src/shared/useSheetEscapeDismiss.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,IAAI,EACrB,MAAM,GAAE,QAAQ,GAAG,UAAqB,QAczC"}