@astryxdesign/core 0.5.2-canary.c9c8564 → 0.5.2-canary.e4f7677

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 (135) hide show
  1. package/dist/BottomSheet/BottomSheet.d.ts +3 -1
  2. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  3. package/dist/BottomSheet/BottomSheet.js +4 -3
  4. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts +2 -2
  5. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts.map +1 -1
  6. package/dist/BottomSheet/BottomSheetEdgeTint.js +7 -10
  7. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheetSwitcher.js +1 -1
  9. package/dist/Button/Button.d.ts +2 -1
  10. package/dist/Button/Button.d.ts.map +1 -1
  11. package/dist/Button/Button.js +11 -4
  12. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  13. package/dist/Chat/ChatToolCalls.js +34 -17
  14. package/dist/ContextMenu/ContextMenu.d.ts +14 -3
  15. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  16. package/dist/ContextMenu/ContextMenu.js +149 -26
  17. package/dist/ContextMenu/index.d.ts +1 -0
  18. package/dist/ContextMenu/index.d.ts.map +1 -1
  19. package/dist/DropdownMenu/DropdownMenu.d.ts +24 -5
  20. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  21. package/dist/DropdownMenu/DropdownMenu.js +340 -26
  22. package/dist/DropdownMenu/DropdownMenuContext.d.ts +1 -1
  23. package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
  24. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  25. package/dist/DropdownMenu/DropdownMenuItem.js +1 -1
  26. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +6 -2
  27. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  28. package/dist/DropdownMenu/DropdownMenuSubMenu.js +43 -14
  29. package/dist/DropdownMenu/MenuBottomSheet.d.ts +20 -0
  30. package/dist/DropdownMenu/MenuBottomSheet.d.ts.map +1 -0
  31. package/dist/DropdownMenu/MenuBottomSheet.js +36 -0
  32. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts +10 -0
  33. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -0
  34. package/dist/DropdownMenu/MenuBottomSheetActionList.js +111 -0
  35. package/dist/DropdownMenu/index.d.ts +2 -1
  36. package/dist/DropdownMenu/index.d.ts.map +1 -1
  37. package/dist/DropdownMenu/menuWidth.d.ts +14 -0
  38. package/dist/DropdownMenu/menuWidth.d.ts.map +1 -0
  39. package/dist/DropdownMenu/menuWidth.js +35 -0
  40. package/dist/DropdownMenu/useMenuOverflow.d.ts +10 -0
  41. package/dist/DropdownMenu/useMenuOverflow.d.ts.map +1 -0
  42. package/dist/DropdownMenu/useMenuOverflow.js +60 -0
  43. package/dist/MoreMenu/MoreMenu.d.ts +8 -2
  44. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  45. package/dist/MoreMenu/MoreMenu.js +2 -0
  46. package/dist/MultiSelector/MultiSelector.d.ts +11 -1
  47. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  48. package/dist/MultiSelector/MultiSelector.js +97 -68
  49. package/dist/MultiSelector/index.d.ts +1 -1
  50. package/dist/MultiSelector/index.d.ts.map +1 -1
  51. package/dist/Popover/Popover.d.ts +10 -6
  52. package/dist/Popover/Popover.d.ts.map +1 -1
  53. package/dist/Popover/Popover.js +141 -16
  54. package/dist/Popover/usePopover.d.ts +4 -0
  55. package/dist/Popover/usePopover.d.ts.map +1 -1
  56. package/dist/Popover/usePopover.js +52 -5
  57. package/dist/Selector/Selector.d.ts +10 -0
  58. package/dist/Selector/Selector.d.ts.map +1 -1
  59. package/dist/Selector/Selector.js +106 -80
  60. package/dist/Selector/SelectorBottomSheet.d.ts +21 -0
  61. package/dist/Selector/SelectorBottomSheet.d.ts.map +1 -0
  62. package/dist/Selector/SelectorBottomSheet.js +83 -0
  63. package/dist/Selector/index.d.ts +1 -1
  64. package/dist/Selector/index.d.ts.map +1 -1
  65. package/dist/Selector/selectorPresentation.stylex.d.ts +16 -0
  66. package/dist/Selector/selectorPresentation.stylex.d.ts.map +1 -0
  67. package/dist/Selector/selectorPresentation.stylex.js +21 -0
  68. package/dist/Selector/useSelectorPresentation.d.ts +32 -0
  69. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -0
  70. package/dist/Selector/useSelectorPresentation.js +90 -0
  71. package/dist/Toast/useToastGesture.d.ts.map +1 -1
  72. package/dist/Toast/useToastGesture.js +46 -9
  73. package/dist/astryx.css +17 -1
  74. package/dist/hooks/useAdaptivePresentation.d.ts +5 -0
  75. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -0
  76. package/dist/hooks/useAdaptivePresentation.js +19 -0
  77. package/dist/hooks/useFocusReturnVisibility.d.ts +7 -0
  78. package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -0
  79. package/dist/hooks/useFocusReturnVisibility.js +35 -0
  80. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  81. package/dist/hooks/useFocusTrap.js +12 -0
  82. package/locales/en.json +20 -0
  83. package/locales/pseudo.json +15 -0
  84. package/package.json +2 -2
  85. package/src/BottomSheet/BottomSheet.doc.mjs +6 -0
  86. package/src/BottomSheet/BottomSheet.test.tsx +29 -0
  87. package/src/BottomSheet/BottomSheet.tsx +7 -4
  88. package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +4 -6
  89. package/src/BottomSheet/BottomSheetEdgeTint.tsx +7 -10
  90. package/src/BottomSheet/BottomSheetSwitcher.tsx +1 -2
  91. package/src/Button/Button.test.tsx +10 -0
  92. package/src/Button/Button.tsx +13 -5
  93. package/src/Chat/ChatToolCalls.test.tsx +44 -0
  94. package/src/Chat/ChatToolCalls.tsx +36 -15
  95. package/src/ContextMenu/ContextMenu.doc.mjs +13 -1
  96. package/src/ContextMenu/ContextMenu.test.tsx +131 -1
  97. package/src/ContextMenu/ContextMenu.tsx +199 -32
  98. package/src/ContextMenu/index.ts +1 -0
  99. package/src/DropdownMenu/DropdownMenu.doc.mjs +201 -40
  100. package/src/DropdownMenu/DropdownMenu.test.tsx +518 -7
  101. package/src/DropdownMenu/DropdownMenu.tsx +459 -28
  102. package/src/DropdownMenu/DropdownMenuContext.tsx +1 -1
  103. package/src/DropdownMenu/DropdownMenuItem.tsx +2 -0
  104. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +4 -2
  105. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +124 -0
  106. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +72 -17
  107. package/src/DropdownMenu/MenuBottomSheet.tsx +46 -0
  108. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +141 -0
  109. package/src/DropdownMenu/index.ts +2 -0
  110. package/src/DropdownMenu/menuWidth.ts +51 -0
  111. package/src/DropdownMenu/useMenuOverflow.ts +77 -0
  112. package/src/MoreMenu/MoreMenu.doc.mjs +17 -0
  113. package/src/MoreMenu/MoreMenu.test.tsx +47 -0
  114. package/src/MoreMenu/MoreMenu.tsx +13 -1
  115. package/src/MultiSelector/MultiSelector.doc.mjs +16 -0
  116. package/src/MultiSelector/MultiSelector.test.tsx +127 -0
  117. package/src/MultiSelector/MultiSelector.tsx +121 -73
  118. package/src/MultiSelector/index.ts +1 -0
  119. package/src/Popover/Popover.doc.mjs +11 -11
  120. package/src/Popover/Popover.test.tsx +397 -2
  121. package/src/Popover/Popover.tsx +228 -21
  122. package/src/Popover/usePopover.tsx +92 -15
  123. package/src/Selector/Selector.doc.mjs +12 -0
  124. package/src/Selector/Selector.test.tsx +135 -0
  125. package/src/Selector/Selector.tsx +141 -82
  126. package/src/Selector/SelectorBottomSheet.tsx +97 -0
  127. package/src/Selector/index.ts +1 -0
  128. package/src/Selector/selectorPresentation.stylex.ts +20 -0
  129. package/src/Selector/useSelectorPresentation.ts +147 -0
  130. package/src/Toast/ToastViewport.test.tsx +118 -4
  131. package/src/Toast/useToastGesture.ts +61 -8
  132. package/src/hooks/useAdaptivePresentation.ts +35 -0
  133. package/src/hooks/useFocusReturnVisibility.ts +45 -0
  134. package/src/hooks/useFocusTrap.test.tsx +40 -0
  135. package/src/hooks/useFocusTrap.ts +13 -0
@@ -20,7 +20,7 @@
20
20
  * - /apps/storybook/stories/BottomSheet.stories.tsx
21
21
  * - /packages/cli/assets/templates/blocks/components/BottomSheet/BottomSheetShowcase.tsx
22
22
  */
23
- import { type ReactNode } from 'react';
23
+ import { type RefObject, type ReactNode } from 'react';
24
24
  import type { BaseProps } from '../BaseProps';
25
25
  import type { DialogPurpose } from '../Dialog';
26
26
  export type { BottomSheetHeight, BottomSheetSnapPoint } from './BottomSheetPanel';
@@ -56,6 +56,8 @@ interface StandaloneBottomSheetProps extends BottomSheetSharedProps {
56
56
  isOpen: boolean;
57
57
  onOpenChange: (isOpen: boolean) => void;
58
58
  hasScrim?: boolean;
59
+ /** Element that receives focus after the sheet closes. */
60
+ finalFocusRef?: RefObject<HTMLElement | null>;
59
61
  sheetId?: never;
60
62
  }
61
63
  interface SwitcherBottomSheetProps extends BottomSheetSharedProps {
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAe7C,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAyEhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;AA4XxD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BA6BlD;yBA7Be,WAAW"}
1
+ {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAe7C,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAyEhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;AA4XxD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BA6BlD;yBA7Be,WAAW"}
@@ -93,6 +93,7 @@ function StandaloneBottomSheet({
93
93
  height = 'capped',
94
94
  snapPoints,
95
95
  hasScrim = true,
96
+ finalFocusRef,
96
97
  purpose = 'info',
97
98
  xstyle,
98
99
  ...props
@@ -162,9 +163,9 @@ function StandaloneBottomSheet({
162
163
  dialog.close();
163
164
  }
164
165
  setIsPresented(false);
165
- triggerRef.current?.focus();
166
+ (finalFocusRef?.current ?? triggerRef.current)?.focus();
166
167
  triggerRef.current = null;
167
- }, [isOpen]);
168
+ }, [finalFocusRef, isOpen]);
168
169
  useScrollLock(shouldPresent && hasScrim);
169
170
  useDevWarning('BottomSheet', 'requires a non-empty `label` for an accessible name; the open sheet ' + 'has no built-in heading to derive one from.', isOpen && !label);
170
171
  const handleCancel = useCallback(event => {
@@ -274,7 +275,7 @@ function StandaloneBottomSheet({
274
275
  onMotionComplete: handleMotionComplete,
275
276
  children: children
276
277
  })
277
- }), hasScrim ? null : /*#__PURE__*/_jsx(BottomSheetEdgeTint, {})]
278
+ }), /*#__PURE__*/_jsx(BottomSheetEdgeTint, {})]
278
279
  });
279
280
  }
280
281
  function SwitcherBottomSheetItem({
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Colours the iOS Safari toolbar strip below a non-modal sheet. Renders
3
- * nothing visible; see the file header for why it exists.
2
+ * Colours the iOS Safari toolbar strip below a sheet. Renders nothing visible;
3
+ * see the file header for why it exists.
4
4
  */
5
5
  export declare function BottomSheetEdgeTint(): import("react").JSX.Element;
6
6
  //# sourceMappingURL=BottomSheetEdgeTint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheetEdgeTint.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetEdgeTint.tsx"],"names":[],"mappings":"AAqEA;;;GAGG;AACH,wBAAgB,mBAAmB,gCAQlC"}
1
+ {"version":3,"file":"BottomSheetEdgeTint.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetEdgeTint.tsx"],"names":[],"mappings":"AAkEA;;;GAGG;AACH,wBAAgB,mBAAmB,gCAQlC"}
@@ -6,7 +6,7 @@
6
6
  * @file BottomSheetEdgeTint.tsx
7
7
  * @input Uses StyleX and core color tokens
8
8
  * @output Exports BottomSheetEdgeTint, an internal decorative element
9
- * @position Private helper rendered inside a non-modal BottomSheet dialog
9
+ * @position Private helper rendered inside every BottomSheet dialog
10
10
  *
11
11
  * iOS 26 Safari dropped `<meta name="theme-color">` and instead derives the
12
12
  * colour it paints behind its translucent toolbars by sampling the page: it
@@ -14,13 +14,10 @@
14
14
  * `fixed`/`sticky` ancestor, and extends that element's declared
15
15
  * `background-color` into the browser chrome.
16
16
  *
17
- * A modal sheet is served by that heuristic already WebKit has a dedicated
18
- * branch for a dialog's `::backdrop`. A non-modal sheet is not: the nearest
19
- * fixed ancestor of the panel is the sheet's own full-viewport `<dialog>`,
20
- * which is transparent and viewport-sized, and WebKit answers a viewport-sized
21
- * candidate by *keeping the colour it already had* — the host page's. The page
22
- * then shows through behind the address bar while the sheet covers the screen
23
- * above it.
17
+ * WebKit may otherwise extend either the dialog backdrop or the host page into
18
+ * the browser chrome. Which one wins varies with dialog mode and the page's
19
+ * own fixed or sticky edge content, so relying on the backdrop makes otherwise
20
+ * identical BottomSheets produce different toolbar colours.
24
21
  *
25
22
  * This element gives the heuristic something unambiguous to sample: fixed,
26
23
  * full width, flush with the bottom edge, taller than WebKit's 10px minimum
@@ -48,8 +45,8 @@ import { colorVars } from "../theme/tokens.stylex.js";
48
45
  import { jsx as _jsx } from "react/jsx-runtime";
49
46
  const SAMPLE_HEIGHT_PX = 12;
50
47
  /**
51
- * Colours the iOS Safari toolbar strip below a non-modal sheet. Renders
52
- * nothing visible; see the file header for why it exists.
48
+ * Colours the iOS Safari toolbar strip below a sheet. Renders nothing visible;
49
+ * see the file header for why it exists.
53
50
  */
54
51
  export function BottomSheetEdgeTint() {
55
52
  return /*#__PURE__*/_jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheetSwitcher.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetSwitcher.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAQL,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAqI5C,MAAM,WAAW,wBAAyB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC5E,iDAAiD;IACjD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEnC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAE9D;;;;;OAKG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,iEAAiE;IACjE,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAEtD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0DAA0D;IAC1D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,mBAAmB,EACnB,QAAe,EACf,QAAQ,EACR,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,OAAO,EACP,SAAS,EACT,GAAG,KAAK,EACT,EAAE,wBAAwB,+BA+Z1B;yBA5ae,mBAAmB"}
1
+ {"version":3,"file":"BottomSheetSwitcher.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetSwitcher.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAQL,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAqI5C,MAAM,WAAW,wBAAyB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC5E,iDAAiD;IACjD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEnC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAE9D;;;;;OAKG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,iEAAiE;IACjE,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAEtD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0DAA0D;IAC1D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,mBAAmB,EACnB,QAAe,EACf,QAAQ,EACR,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,OAAO,EACP,SAAS,EACT,GAAG,KAAK,EACT,EAAE,wBAAwB,+BA8Z1B;yBA3ae,mBAAmB"}
@@ -410,7 +410,7 @@ export function BottomSheetSwitcher({
410
410
  ...(activeSheetPurpose === 'required' ? {
411
411
  role: 'alertdialog'
412
412
  } : undefined),
413
- children: [children, hasScrim ? null : /*#__PURE__*/_jsx(BottomSheetEdgeTint, {})]
413
+ children: [children, /*#__PURE__*/_jsx(BottomSheetEdgeTint, {})]
414
414
  })
415
415
  });
416
416
  }
@@ -78,7 +78,8 @@ export interface ButtonProps extends BaseProps<HTMLButtonElement> {
78
78
  */
79
79
  isDisabled?: boolean;
80
80
  /**
81
- * Whether the button is in a loading state.
81
+ * Whether the button is in a loading state. Loading prevents interaction
82
+ * without dimming the spinner; explicit disabled states remain dimmed.
82
83
  * @default false
83
84
  */
84
85
  isLoading?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"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"}
@@ -66,16 +66,19 @@ const styles = {
66
66
  $$css: true
67
67
  },
68
68
  pressable: {
69
- k3aq6I: "x3oybdh xk4oym4",
69
+ k3aq6I: "x3oybdh x8ppqj",
70
70
  $$css: true
71
71
  },
72
- disabled: {
72
+ inactive: {
73
73
  kkrTdU: "xt0e3qv",
74
- kSiTet: "xbyyjgo",
75
74
  kKwaWg: "x18o3ruo",
76
75
  k3aq6I: "x1c071of x1pdlv7q",
77
76
  $$css: true
78
77
  },
78
+ disabled: {
79
+ kSiTet: "xbyyjgo",
80
+ $$css: true
81
+ },
79
82
  ariaDisabled: {
80
83
  kKwaWg: "x18o3ruo xuqm82a",
81
84
  $$css: true
@@ -374,6 +377,10 @@ export function Button({
374
377
  // When interruptible, the loading state drives the spinner and aria-busy but
375
378
  // not disabled, so clicks keep landing and can interrupt the in-flight action.
376
379
  const buttonDisabled = isDisabled || groupDisabled || isLoadingState && !isInterruptible;
380
+ // A loading button remains non-interactive, but its spinner communicates an
381
+ // active state and must retain contrast. Only explicitly disabled controls
382
+ // receive the visually dimmed treatment.
383
+ const visuallyDisabled = isDisabled || groupDisabled;
377
384
  // isIconOnly prop is the source of truth for icon-only rendering.
378
385
  // When false (default), label is always rendered as visible text.
379
386
 
@@ -434,7 +441,7 @@ export function Button({
434
441
  } : null;
435
442
 
436
443
  // Shared StyleX props for both button and link rendering
437
- const sharedStylexProps = focusOutlineProps.focusVisible(styles.base, sizeStyles[size], isIconOnly && styles.iconOnly, interactionOverlayStyles.backgroundImage, buttonDisabled && styles.disabled, useAriaDisabled && styles.ariaDisabled, renderAsLink && styles.link, !buttonGroup && styles.pressable, buttonGroup && (buttonGroup.orientation === 'horizontal' ? groupStyles.horizontal : groupStyles.vertical), buttonGroup && (variant === 'primary' || variant === 'destructive') && (buttonGroup.orientation === 'horizontal' ? groupStyles.onSolidHorizontal : groupStyles.onSolidVertical),
444
+ const sharedStylexProps = focusOutlineProps.focusVisible(styles.base, sizeStyles[size], isIconOnly && styles.iconOnly, interactionOverlayStyles.backgroundImage, buttonDisabled && styles.inactive, visuallyDisabled && styles.disabled, useAriaDisabled && styles.ariaDisabled, renderAsLink && styles.link, !buttonGroup && styles.pressable, buttonGroup && (buttonGroup.orientation === 'horizontal' ? groupStyles.horizontal : groupStyles.vertical), buttonGroup && (variant === 'primary' || variant === 'destructive') && (buttonGroup.orientation === 'horizontal' ? groupStyles.onSolidHorizontal : groupStyles.onSolidVertical),
438
445
  // Standalone floating buttons only — a grouped button's elevation is owned
439
446
  // by the ButtonGroup so the shared surface lifts as one unit.
440
447
  !buttonGroup && elevationStyles[elevation], width != null && dynamicStyles.width(width),
@@ -1 +1 @@
1
- {"version":3,"file":"ChatToolCalls.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatToolCalls.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAA+B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC1E,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAwB5C,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,2FAA2F;IAC3F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6FAA6F;IAC7F,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,+BAA+B;IAC/B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AAmaD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,4BA0JtD;yBA1Je,aAAa"}
1
+ {"version":3,"file":"ChatToolCalls.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatToolCalls.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAA+B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC1E,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAwB5C,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,2FAA2F;IAC3F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6FAA6F;IAC7F,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,+BAA+B;IAC/B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AAkbD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,4BAgKtD;yBAhKe,aAAa"}
@@ -102,6 +102,23 @@ const STATUS_STYLES = {
102
102
  complete: styles.colorComplete,
103
103
  error: styles.colorError
104
104
  };
105
+ function getStatusAnnouncement(t, status, errorMessage) {
106
+ if (status === 'error' && errorMessage != null) {
107
+ return t('@astryx.chatToolCalls.error', {
108
+ message: errorMessage
109
+ });
110
+ }
111
+ switch (status) {
112
+ case 'pending':
113
+ return t('@astryx.chatToolCalls.status.pending');
114
+ case 'running':
115
+ return t('@astryx.chatToolCalls.status.running');
116
+ case 'complete':
117
+ return t('@astryx.chatToolCalls.status.complete');
118
+ case 'error':
119
+ return t('@astryx.chatToolCalls.status.error');
120
+ }
121
+ }
105
122
  function getToolCallKey(call) {
106
123
  return getKey(call.key, () => [call.name, call.status ?? 'complete', call.target ?? '', call.node ?? '', call.duration ?? '', call.additions?.toString() ?? '', call.deletions?.toString() ?? '', call.errorMessage ?? ''].join('\u001F'));
107
124
  }
@@ -118,6 +135,7 @@ function CallRow({
118
135
  const hasDetail = call.resultDetail != null;
119
136
  const [isDetailOpen, setIsDetailOpen] = useState(false);
120
137
  const detailId = useId();
138
+ const statusAnnouncement = getStatusAnnouncement(t, status, call.errorMessage);
121
139
  const toggleDetail = hasDetail ? () => setIsDetailOpen(prev => !prev) : undefined;
122
140
  const row = /*#__PURE__*/_jsxs("div", {
123
141
  role: hasDetail ? 'button' : undefined,
@@ -144,10 +162,12 @@ function CallRow({
144
162
  ...stylex.props(styles.statusIcon, STATUS_STYLES[status]),
145
163
  children: [status === 'running' ? /*#__PURE__*/_jsx(Spinner, {
146
164
  size: "sm",
147
- shade: "subtle"
165
+ shade: "subtle",
166
+ "aria-hidden": "true"
148
167
  }) : status === 'pending' ? /*#__PURE__*/_jsx(Spinner, {
149
168
  size: "sm",
150
- shade: "subtle"
169
+ shade: "subtle",
170
+ "aria-hidden": "true"
151
171
  }) : /*#__PURE__*/_jsxs(_Fragment, {
152
172
  children: [/*#__PURE__*/_jsx("span", {
153
173
  ...{
@@ -163,16 +183,8 @@ function CallRow({
163
183
  color: "inherit"
164
184
  })
165
185
  })]
166
- }), status === 'error' && call.errorMessage != null &&
167
- /*#__PURE__*/
168
- // The title attribute above is hover-only; expose the error detail
169
- // as real text so it reaches screen readers, keyboard, and touch
170
- // users. Rendering it inside the row also folds it into the
171
- // accessible name of expandable (role="button") rows.
172
- _jsx(VisuallyHidden, {
173
- children: t('@astryx.chatToolCalls.error', {
174
- message: call.errorMessage ?? ''
175
- })
186
+ }), /*#__PURE__*/_jsx(VisuallyHidden, {
187
+ children: statusAnnouncement
176
188
  })]
177
189
  }), /*#__PURE__*/_jsx("span", {
178
190
  ...{
@@ -304,6 +316,7 @@ export function ChatToolCalls(props) {
304
316
  // Multiple calls: latest call at surface with chevron to expand all
305
317
  const latestCall = calls[calls.length - 1];
306
318
  const latestStatus = latestCall.status ?? 'complete';
319
+ const latestStatusAnnouncement = getStatusAnnouncement(t, latestStatus, latestCall.errorMessage);
307
320
  return /*#__PURE__*/_jsxs("div", {
308
321
  ref: ref,
309
322
  ...mergeProps(themeProps('chat-tool-calls'), stylex.props(styles.root, xstyle), className, style),
@@ -342,14 +355,16 @@ export function ChatToolCalls(props) {
342
355
  })
343
356
  })]
344
357
  }) : /*#__PURE__*/_jsxs(_Fragment, {
345
- children: [/*#__PURE__*/_jsx("span", {
358
+ children: [/*#__PURE__*/_jsxs("span", {
346
359
  ...stylex.props(styles.statusIcon, STATUS_STYLES[latestStatus]),
347
- children: latestStatus === 'running' ? /*#__PURE__*/_jsx(Spinner, {
360
+ children: [latestStatus === 'running' ? /*#__PURE__*/_jsx(Spinner, {
348
361
  size: "sm",
349
- shade: "subtle"
362
+ shade: "subtle",
363
+ "aria-hidden": "true"
350
364
  }) : latestStatus === 'pending' ? /*#__PURE__*/_jsx(Spinner, {
351
365
  size: "sm",
352
- shade: "subtle"
366
+ shade: "subtle",
367
+ "aria-hidden": "true"
353
368
  }) : /*#__PURE__*/_jsxs(_Fragment, {
354
369
  children: [/*#__PURE__*/_jsx("span", {
355
370
  ...{
@@ -365,7 +380,9 @@ export function ChatToolCalls(props) {
365
380
  color: "inherit"
366
381
  })
367
382
  })]
368
- })
383
+ }), /*#__PURE__*/_jsx(VisuallyHidden, {
384
+ children: latestStatusAnnouncement
385
+ })]
369
386
  }), /*#__PURE__*/_jsx("span", {
370
387
  ...{
371
388
  className: "x141an7d x1ltkj2j x9m5x89 x1e4wzip xv1l7n4 xuxw1ft xb3r6kr xlyipyv xs83m0k x13n9wmd"
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * @file ContextMenu.tsx
3
- * @input Uses React, StyleX, useLayer (context mode), useListFocus
4
- * @output Exports ContextMenu component
3
+ * @input Uses React, StyleX, useLayer, BottomSheet, useListFocus, and the
4
+ * shared menu-presentation resolver
5
+ * @output Exports ContextMenu with cursor-popover and touch-sheet presentations
5
6
  * @position Core implementation; consumed by index.ts
6
7
  *
7
8
  * Right-click context menu positioned at the cursor. The cursor point is
@@ -31,6 +32,7 @@ import type { ReactNode } from 'react';
31
32
  import type { BaseProps } from '../BaseProps';
32
33
  import type { StyleXStyles } from '../theme/types';
33
34
  import type { DropdownMenuOption, DropdownMenuItemData, DropdownMenuDividerData, DropdownMenuSection } from '../DropdownMenu/DropdownMenu';
35
+ import { type AdaptivePresentation } from '../hooks/useAdaptivePresentation';
34
36
  export type ContextMenuItemData = DropdownMenuItemData;
35
37
  export type ContextMenuDividerData = DropdownMenuDividerData;
36
38
  export type ContextMenuSection = DropdownMenuSection;
@@ -60,6 +62,15 @@ interface ContextMenuBaseProps extends BaseProps {
60
62
  isDisabled?: boolean;
61
63
  /** Called when the menu opens or closes. */
62
64
  onOpenChange?: (isOpen: boolean) => void;
65
+ /**
66
+ * Presentation policy for the menu.
67
+ * - `popover`: open beside the pointer position.
68
+ * - `bottom-sheet`: open as an action sheet.
69
+ * - `adaptive`: use a BottomSheet on compact coarse-pointer viewports and
70
+ * the cursor-positioned popover elsewhere.
71
+ * @default 'popover'
72
+ */
73
+ presentation?: AdaptivePresentation;
63
74
  'data-testid'?: string;
64
75
  }
65
76
  interface ContextMenuDataProps extends ContextMenuBaseProps {
@@ -96,7 +107,7 @@ export type ContextMenuProps = ContextMenuDataProps | ContextMenuCompoundProps;
96
107
  * </ContextMenu>
97
108
  * ```
98
109
  */
99
- export declare function ContextMenu({ children, menuWidth, size, label: labelFromProps, isDisabled, onOpenChange, ref, className, style, xstyle, triggerXstyle, 'data-testid': testId, ...rest }: ContextMenuProps): React.JSX.Element;
110
+ export declare function ContextMenu({ children, menuWidth, size, label: labelFromProps, isDisabled, onOpenChange, presentation, ref, className, style, xstyle, triggerXstyle, 'data-testid': testId, ...rest }: ContextMenuProps): React.JSX.Element;
100
111
  export declare namespace ContextMenu {
101
112
  var displayName: string;
102
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../src/ContextMenu/ContextMenu.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAON,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AA0BrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,8BAA8B,CAAC;AAsDtC,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AAEvD,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAE7D,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAMnD,UAAU,oBAAqB,SAAQ,SAAS;IAC9C,oDAAoD;IACpD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,EAAE,SAAS,CAAC;IACpB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,wCAAwC;IACxC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,oBAAqB,SAAQ,oBAAoB;IACzD,gDAAgD;IAChD,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,UAAU,wBAAyB,SAAQ,oBAAoB;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,+CAA+C;IAC/C,WAAW,EAAE,SAAS,CAAC;CACxB;AAED,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,wBAAwB,CAAC;AAM/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,SAAS,EACT,IAAW,EACX,KAAK,EAAE,cAAc,EACrB,UAAkB,EAClB,YAAY,EACZ,GAAG,EACH,SAAS,EACT,KAAK,EACL,MAAM,EACN,aAAa,EACb,aAAa,EAAE,MAAM,EACrB,GAAG,IAAI,EACR,EAAE,gBAAgB,qBA0SlB;yBAxTe,WAAW"}
1
+ {"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../src/ContextMenu/ContextMenu.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KASN,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AA8BrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAC;AAuF1C,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AAEvD,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAE7D,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAMnD,UAAU,oBAAqB,SAAQ,SAAS;IAC9C,oDAAoD;IACpD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,EAAE,SAAS,CAAC;IACpB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,wCAAwC;IACxC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,oBAAqB,SAAQ,oBAAoB;IACzD,gDAAgD;IAChD,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,UAAU,wBAAyB,SAAQ,oBAAoB;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,+CAA+C;IAC/C,WAAW,EAAE,SAAS,CAAC;CACxB;AAED,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,wBAAwB,CAAC;AAM/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,SAAS,EACT,IAAW,EACX,KAAK,EAAE,cAAc,EACrB,UAAkB,EAClB,YAAY,EACZ,YAAwB,EACxB,GAAG,EACH,SAAS,EACT,KAAK,EACL,MAAM,EACN,aAAa,EACb,aAAa,EAAE,MAAM,EACrB,GAAG,IAAI,EACR,EAAE,gBAAgB,qBAyZlB;yBAxae,WAAW"}
@@ -3,8 +3,9 @@
3
3
 
4
4
  /**
5
5
  * @file ContextMenu.tsx
6
- * @input Uses React, StyleX, useLayer (context mode), useListFocus
7
- * @output Exports ContextMenu component
6
+ * @input Uses React, StyleX, useLayer, BottomSheet, useListFocus, and the
7
+ * shared menu-presentation resolver
8
+ * @output Exports ContextMenu with cursor-popover and touch-sheet presentations
8
9
  * @position Core implementation; consumed by index.ts
9
10
  *
10
11
  * Right-click context menu positioned at the cursor. The cursor point is
@@ -29,9 +30,13 @@
29
30
  * - /apps/storybook/stories/ContextMenu.stories.tsx
30
31
  * - /packages/cli/assets/templates/blocks/components/ContextMenu/ (showcase blocks)
31
32
  */
32
- import React, { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
33
+ import React, { useCallback, useEffect, useId, lazy, useMemo, useRef, useState, Suspense } from 'react';
33
34
  import * as stylex from '@stylexjs/stylex';
35
+ import { Button } from "../Button/index.js";
36
+ import { Heading } from "../Heading/index.js";
37
+ import { Icon } from "../Icon/index.js";
34
38
  import { useLayer } from "../Layer/useLayer.js";
39
+ import { MenuBottomSheetActionList } from "../DropdownMenu/MenuBottomSheetActionList.js";
35
40
  import { renderDropdownItems } from "../DropdownMenu/renderDropdownItems.js";
36
41
  import { DropdownMenuContext } from "../DropdownMenu/DropdownMenuContext.js";
37
42
  import { MENU_ITEM_ROLES, MENU_ITEM_SELECTOR, MENU_BOUNDARY_SELECTOR } from "../DropdownMenu/menuItemRoles.js";
@@ -41,15 +46,21 @@ import { useLongPress } from "../hooks/useLongPress.js";
41
46
  import { layerAnimations } from "../Layer/layerAnimations.stylex.js";
42
47
  import "../theme/tokens.stylex.js";
43
48
  import { colorVars, spacingVars, radiusVars, durationVars, easeVars, shadowVars } from "../theme/tokens.stylex.js";
44
- import { mergeProps, isImeKeyEvent } from "../utils/index.js";
49
+ import { mergeProps, isImeKeyEvent, rtlStyles } from "../utils/index.js";
45
50
  import { themeProps } from "../utils/themeProps.js";
46
51
  import { useTranslator } from "../i18n/index.js";
47
52
  import { useMergedRefs } from "../hooks/useMergedRefs.js";
53
+ import { useAdaptivePresentation } from "../hooks/useAdaptivePresentation.js";
48
54
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
55
+ const LazyMenuBottomSheet = /*#__PURE__*/lazy(async () => import("../DropdownMenu/MenuBottomSheet.js").then(module => ({
56
+ default: module.MenuBottomSheet
57
+ })));
49
58
  const styles = {
50
59
  trigger: {
51
60
  kVAEAm: "x1n2onr6",
52
61
  k7VYTy: "xpdipgo",
62
+ kO7zv1: "x1winvzj",
63
+ kfSwDN: "x87ps6o",
53
64
  $$css: true
54
65
  },
55
66
  menu: {
@@ -81,7 +92,30 @@ const styles = {
81
92
  $$css: true
82
93
  }, {
83
94
  "--x-minWidth": (val => typeof val === "number" ? val + "px" : val != null ? val : undefined)(typeof width === 'number' ? `${width}px` : width)
84
- }]
95
+ }],
96
+ sheetMenu: {
97
+ kB7OPa: "x9f619",
98
+ k1xSpc: "x78zum5",
99
+ kXwgrk: "xdt5ytf",
100
+ kOIVth: "x1lsbc85",
101
+ kzqmXN: "xh8yej3",
102
+ "--_dropdown-menu-radius": "x1fcsqxe",
103
+ "--_dropdown-menu-padding": "xgory14",
104
+ kmVPX3: "x9epnlk",
105
+ kaIpWk: "x1n97fys",
106
+ kWkggS: "x10xzikg",
107
+ kI3sdo: "x1a2a7pz",
108
+ kfSwDN: "x87ps6o",
109
+ $$css: true
110
+ },
111
+ sheetRootHeading: {
112
+ keTefX: "x6i7dpz",
113
+ $$css: true
114
+ },
115
+ sheetViewHeading: {
116
+ kI3sdo: "x1a2a7pz",
117
+ $$css: true
118
+ }
85
119
  };
86
120
 
87
121
  // =============================================================================
@@ -126,6 +160,7 @@ export function ContextMenu({
126
160
  label: labelFromProps,
127
161
  isDisabled = false,
128
162
  onOpenChange,
163
+ presentation = 'popover',
129
164
  ref,
130
165
  className,
131
166
  style,
@@ -136,6 +171,9 @@ export function ContextMenu({
136
171
  }) {
137
172
  const t = useTranslator();
138
173
  const label = labelFromProps ?? t('@astryx.contextMenu.label');
174
+ const backLabel = t('@astryx.dropdownMenu.back');
175
+ const resolvedPresentation = useAdaptivePresentation(presentation);
176
+ const usesBottomSheet = resolvedPresentation === 'bottom-sheet';
139
177
  // Separate content props (union discriminant) from DOM pass-through attrs.
140
178
  // The union means exactly one of items/menuContent exists in rest; destructure
141
179
  // both so triggerProps contains only DOM-safe attributes.
@@ -160,7 +198,20 @@ export function ContextMenu({
160
198
  // Element focused before the menu opened, restored when it closes so focus
161
199
  // does not fall to <body> after Escape or outside-click dismissal.
162
200
  const triggerFocusRef = useRef(null);
201
+ const sheetHeadingRef = useRef(null);
163
202
  const [isOpen, setIsOpen] = useState(false);
203
+ const [submenuPath, setSubmenuPath] = useState([]);
204
+ const currentSubmenu = submenuPath.at(-1);
205
+ const currentItems = currentSubmenu?.items ?? items;
206
+ const currentTitle = currentSubmenu?.label ?? label;
207
+ const sheetLabel = typeof currentTitle === 'string' ? currentTitle : label;
208
+ const updateOpenState = useCallback(nextIsOpen => {
209
+ if (!nextIsOpen) {
210
+ setSubmenuPath([]);
211
+ }
212
+ setIsOpen(nextIsOpen);
213
+ onOpenChange?.(nextIsOpen);
214
+ }, [onOpenChange]);
164
215
  const layer = useLayer({
165
216
  mode: 'context',
166
217
  onHide: useCallback(() => {
@@ -180,8 +231,32 @@ export function ContextMenu({
180
231
  lightDismiss: false
181
232
  });
182
233
  const closeMenu = useCallback(() => {
183
- layer.hide();
184
- }, [layer]);
234
+ if (usesBottomSheet) {
235
+ updateOpenState(false);
236
+ } else {
237
+ layer.hide();
238
+ }
239
+ }, [layer, updateOpenState, usesBottomSheet]);
240
+ const handleBottomSheetSelect = useCallback(item => {
241
+ if (item.isDisabled) {
242
+ return;
243
+ }
244
+ item.onClick?.();
245
+ if (item.hasCloseOnSelect !== false) {
246
+ closeMenu();
247
+ }
248
+ }, [closeMenu]);
249
+ useEffect(() => {
250
+ if (!isOpen || submenuPath.length === 0) {
251
+ return;
252
+ }
253
+ const frame = requestAnimationFrame(() => {
254
+ sheetHeadingRef.current?.focus({
255
+ preventScroll: true
256
+ });
257
+ });
258
+ return () => cancelAnimationFrame(frame);
259
+ }, [isOpen, submenuPath.length]);
185
260
  const {
186
261
  listRef,
187
262
  handleKeyDown: listNavKeyDown,
@@ -210,7 +285,7 @@ export function ContextMenu({
210
285
  // opening right-click as a dismiss event. Handling it ourselves via
211
286
  // mousedown avoids that race.
212
287
  useEffect(() => {
213
- if (!isOpen) {
288
+ if (!isOpen || usesBottomSheet) {
214
289
  return;
215
290
  }
216
291
  const handleClickOutside = e => {
@@ -223,14 +298,14 @@ export function ContextMenu({
223
298
  return () => {
224
299
  document.removeEventListener('mousedown', handleClickOutside);
225
300
  };
226
- }, [isOpen, closeMenu, listRef]);
301
+ }, [isOpen, closeMenu, listRef, usesBottomSheet]);
227
302
 
228
303
  // Dismiss on Escape from anywhere while open. The menu div's own onKeyDown
229
304
  // only fires when focus is inside the menu; a document-level listener is
230
305
  // kept as a reliable fallback Escape path (e.g. if focus has moved out of
231
306
  // the menu). Guards against IME composition-cancel.
232
307
  useEffect(() => {
233
- if (!isOpen) {
308
+ if (!isOpen || usesBottomSheet) {
234
309
  return;
235
310
  }
236
311
  const handleEscape = e => {
@@ -249,7 +324,7 @@ export function ContextMenu({
249
324
  return () => {
250
325
  document.removeEventListener('keydown', handleEscape);
251
326
  };
252
- }, [isOpen, closeMenu]);
327
+ }, [isOpen, closeMenu, usesBottomSheet]);
253
328
  const listKeyDown = useCallback(e => {
254
329
  // A submenu flyout renders inline inside this menu; its key events bubble
255
330
  // up here. Let that level own them — only handle events from this level.
@@ -298,9 +373,13 @@ export function ContextMenu({
298
373
  // Remember the element focused before opening so we can restore it on
299
374
  // close (Escape or outside-click), instead of dropping focus to <body>.
300
375
  triggerFocusRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : focusEl;
301
- layer.show();
302
- requestAnimationFrame(() => focusFirst());
303
- }, [layer, focusFirst]);
376
+ if (usesBottomSheet) {
377
+ updateOpenState(true);
378
+ } else {
379
+ layer.show();
380
+ requestAnimationFrame(() => focusFirst());
381
+ }
382
+ }, [layer, focusFirst, updateOpenState, usesBottomSheet]);
304
383
  const handleContextMenu = useCallback(e => {
305
384
  if (isDisabled) {
306
385
  return;
@@ -337,6 +416,54 @@ export function ContextMenu({
337
416
  menuSize: size
338
417
  }), [closeMenu, size]);
339
418
  const resolvedMenuContent = itemsProp !== undefined ? renderDropdownItems(items) : menuContent;
419
+ const renderedMenu = /*#__PURE__*/_jsx("div", {
420
+ ref: listRef,
421
+ id: menuId,
422
+ role: "menu",
423
+ "data-autofocus": usesBottomSheet ? '' : undefined,
424
+ tabIndex: usesBottomSheet ? 0 : -1,
425
+ "aria-label": label,
426
+ onKeyDown: listKeyDown,
427
+ onContextMenu: e => e.preventDefault(),
428
+ ...mergeProps(themeProps('context-menu'), stylex.props(usesBottomSheet ? styles.sheetMenu : styles.menu, xstyle), className, style),
429
+ children: /*#__PURE__*/_jsx(DropdownMenuContext, {
430
+ value: contextValue,
431
+ children: resolvedMenuContent
432
+ })
433
+ });
434
+ const renderedBottomSheetContent = itemsProp !== undefined ? /*#__PURE__*/_jsxs("div", {
435
+ ref: listRef,
436
+ "data-autofocus": "",
437
+ tabIndex: 0,
438
+ ...mergeProps(themeProps('context-menu'), stylex.props(styles.sheetMenu, xstyle), className, style),
439
+ children: [/*#__PURE__*/_jsxs("div", {
440
+ ...{
441
+ className: "x78zum5 x1q0g3np x6s0dn4 xzye2dw x1p37lm5"
442
+ },
443
+ children: [submenuPath.length > 0 && /*#__PURE__*/_jsx(Button, {
444
+ label: backLabel,
445
+ variant: "ghost",
446
+ size: "sm",
447
+ icon: /*#__PURE__*/_jsx(Icon, {
448
+ icon: "chevronLeft",
449
+ size: "sm",
450
+ xstyle: rtlStyles.mirror
451
+ }),
452
+ isIconOnly: true,
453
+ onClick: () => setSubmenuPath(path => path.slice(0, -1))
454
+ }), /*#__PURE__*/_jsx(Heading, {
455
+ ref: sheetHeadingRef,
456
+ level: 3,
457
+ tabIndex: -1,
458
+ xstyle: [styles.sheetViewHeading, submenuPath.length === 0 && styles.sheetRootHeading],
459
+ children: currentTitle
460
+ })]
461
+ }), /*#__PURE__*/_jsx(MenuBottomSheetActionList, {
462
+ items: currentItems,
463
+ onSelect: handleBottomSheetSelect,
464
+ onOpenSubmenu: item => setSubmenuPath(path => [...path, item])
465
+ })]
466
+ }) : renderedMenu;
340
467
  return /*#__PURE__*/_jsxs(_Fragment, {
341
468
  children: [/*#__PURE__*/_jsxs("div", {
342
469
  ref: useMergedRefs(ref, triggerRef),
@@ -357,19 +484,15 @@ export function ContextMenu({
357
484
  }
358
485
  })
359
486
  })]
360
- }), layer.render(/*#__PURE__*/_jsx("div", {
361
- ref: listRef,
362
- id: menuId,
363
- role: "menu",
364
- "aria-label": label,
365
- onKeyDown: listKeyDown,
366
- onContextMenu: e => e.preventDefault(),
367
- ...mergeProps(themeProps('context-menu'), stylex.props(styles.menu, xstyle), className, style),
368
- children: /*#__PURE__*/_jsx(DropdownMenuContext, {
369
- value: contextValue,
370
- children: resolvedMenuContent
487
+ }), usesBottomSheet ? /*#__PURE__*/_jsx(Suspense, {
488
+ fallback: null,
489
+ children: /*#__PURE__*/_jsx(LazyMenuBottomSheet, {
490
+ isOpen: isOpen,
491
+ onOpenChange: updateOpenState,
492
+ label: sheetLabel,
493
+ children: renderedBottomSheetContent
371
494
  })
372
- }), {
495
+ }) : layer.render(renderedMenu, {
373
496
  placement: 'below',
374
497
  alignment: 'start',
375
498
  xstyle: [popoverXstyle, layerAnimations.below]