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

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 (146) 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/Carousel/Carousel.d.ts.map +1 -1
  13. package/dist/Carousel/Carousel.js +2 -2
  14. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  15. package/dist/Chat/ChatToolCalls.js +34 -17
  16. package/dist/ContextMenu/ContextMenu.d.ts +14 -3
  17. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  18. package/dist/ContextMenu/ContextMenu.js +149 -26
  19. package/dist/ContextMenu/index.d.ts +1 -0
  20. package/dist/ContextMenu/index.d.ts.map +1 -1
  21. package/dist/DropdownMenu/DropdownMenu.d.ts +24 -5
  22. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  23. package/dist/DropdownMenu/DropdownMenu.js +340 -26
  24. package/dist/DropdownMenu/DropdownMenuContext.d.ts +1 -1
  25. package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
  26. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  27. package/dist/DropdownMenu/DropdownMenuItem.js +1 -1
  28. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +6 -2
  29. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  30. package/dist/DropdownMenu/DropdownMenuSubMenu.js +43 -14
  31. package/dist/DropdownMenu/MenuBottomSheet.d.ts +20 -0
  32. package/dist/DropdownMenu/MenuBottomSheet.d.ts.map +1 -0
  33. package/dist/DropdownMenu/MenuBottomSheet.js +36 -0
  34. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts +10 -0
  35. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -0
  36. package/dist/DropdownMenu/MenuBottomSheetActionList.js +111 -0
  37. package/dist/DropdownMenu/index.d.ts +2 -1
  38. package/dist/DropdownMenu/index.d.ts.map +1 -1
  39. package/dist/DropdownMenu/menuWidth.d.ts +14 -0
  40. package/dist/DropdownMenu/menuWidth.d.ts.map +1 -0
  41. package/dist/DropdownMenu/menuWidth.js +35 -0
  42. package/dist/DropdownMenu/useMenuOverflow.d.ts +10 -0
  43. package/dist/DropdownMenu/useMenuOverflow.d.ts.map +1 -0
  44. package/dist/DropdownMenu/useMenuOverflow.js +60 -0
  45. package/dist/MoreMenu/MoreMenu.d.ts +8 -2
  46. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  47. package/dist/MoreMenu/MoreMenu.js +2 -0
  48. package/dist/MultiSelector/MultiSelector.d.ts +11 -1
  49. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  50. package/dist/MultiSelector/MultiSelector.js +97 -68
  51. package/dist/MultiSelector/index.d.ts +1 -1
  52. package/dist/MultiSelector/index.d.ts.map +1 -1
  53. package/dist/Popover/Popover.d.ts +10 -6
  54. package/dist/Popover/Popover.d.ts.map +1 -1
  55. package/dist/Popover/Popover.js +141 -16
  56. package/dist/Popover/usePopover.d.ts +4 -0
  57. package/dist/Popover/usePopover.d.ts.map +1 -1
  58. package/dist/Popover/usePopover.js +52 -5
  59. package/dist/Selector/Selector.d.ts +10 -0
  60. package/dist/Selector/Selector.d.ts.map +1 -1
  61. package/dist/Selector/Selector.js +106 -80
  62. package/dist/Selector/SelectorBottomSheet.d.ts +21 -0
  63. package/dist/Selector/SelectorBottomSheet.d.ts.map +1 -0
  64. package/dist/Selector/SelectorBottomSheet.js +83 -0
  65. package/dist/Selector/index.d.ts +1 -1
  66. package/dist/Selector/index.d.ts.map +1 -1
  67. package/dist/Selector/selectorPresentation.stylex.d.ts +16 -0
  68. package/dist/Selector/selectorPresentation.stylex.d.ts.map +1 -0
  69. package/dist/Selector/selectorPresentation.stylex.js +21 -0
  70. package/dist/Selector/useSelectorPresentation.d.ts +32 -0
  71. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -0
  72. package/dist/Selector/useSelectorPresentation.js +90 -0
  73. package/dist/Toast/useToastGesture.d.ts.map +1 -1
  74. package/dist/Toast/useToastGesture.js +46 -9
  75. package/dist/astryx.css +19 -1
  76. package/dist/hooks/useAdaptivePresentation.d.ts +5 -0
  77. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -0
  78. package/dist/hooks/useAdaptivePresentation.js +19 -0
  79. package/dist/hooks/useFocusReturnVisibility.d.ts +7 -0
  80. package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -0
  81. package/dist/hooks/useFocusReturnVisibility.js +35 -0
  82. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  83. package/dist/hooks/useFocusTrap.js +12 -0
  84. package/locales/en.json +20 -0
  85. package/locales/pseudo.json +15 -0
  86. package/package.json +2 -2
  87. package/src/BottomSheet/BottomSheet.doc.mjs +6 -0
  88. package/src/BottomSheet/BottomSheet.test.tsx +29 -0
  89. package/src/BottomSheet/BottomSheet.tsx +7 -4
  90. package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +4 -6
  91. package/src/BottomSheet/BottomSheetEdgeTint.tsx +7 -10
  92. package/src/BottomSheet/BottomSheetSwitcher.tsx +1 -2
  93. package/src/Button/Button.doc.mjs +56 -0
  94. package/src/Button/Button.test.tsx +10 -0
  95. package/src/Button/Button.tsx +13 -5
  96. package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
  97. package/src/Carousel/Carousel.test.tsx +83 -0
  98. package/src/Carousel/Carousel.tsx +8 -2
  99. package/src/Chat/ChatToolCalls.test.tsx +44 -0
  100. package/src/Chat/ChatToolCalls.tsx +36 -15
  101. package/src/ContextMenu/ContextMenu.doc.mjs +13 -1
  102. package/src/ContextMenu/ContextMenu.test.tsx +131 -1
  103. package/src/ContextMenu/ContextMenu.tsx +199 -32
  104. package/src/ContextMenu/index.ts +1 -0
  105. package/src/DropdownMenu/DropdownMenu.doc.mjs +201 -40
  106. package/src/DropdownMenu/DropdownMenu.test.tsx +518 -7
  107. package/src/DropdownMenu/DropdownMenu.tsx +459 -28
  108. package/src/DropdownMenu/DropdownMenuContext.tsx +1 -1
  109. package/src/DropdownMenu/DropdownMenuItem.tsx +2 -0
  110. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +4 -2
  111. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +124 -0
  112. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +72 -17
  113. package/src/DropdownMenu/MenuBottomSheet.tsx +46 -0
  114. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +141 -0
  115. package/src/DropdownMenu/index.ts +2 -0
  116. package/src/DropdownMenu/menuWidth.ts +51 -0
  117. package/src/DropdownMenu/useMenuOverflow.ts +77 -0
  118. package/src/IconButton/IconButton.doc.mjs +38 -0
  119. package/src/MoreMenu/MoreMenu.doc.mjs +17 -0
  120. package/src/MoreMenu/MoreMenu.test.tsx +47 -0
  121. package/src/MoreMenu/MoreMenu.tsx +13 -1
  122. package/src/MultiSelector/MultiSelector.doc.mjs +16 -0
  123. package/src/MultiSelector/MultiSelector.test.tsx +127 -0
  124. package/src/MultiSelector/MultiSelector.tsx +121 -73
  125. package/src/MultiSelector/index.ts +1 -0
  126. package/src/Popover/Popover.doc.mjs +11 -11
  127. package/src/Popover/Popover.test.tsx +397 -2
  128. package/src/Popover/Popover.tsx +228 -21
  129. package/src/Popover/usePopover.tsx +92 -15
  130. package/src/ProgressBar/ProgressBar.spec.md +208 -0
  131. package/src/SegmentedControl/SegmentedControl.doc.mjs +56 -0
  132. package/src/Selector/Selector.doc.mjs +12 -0
  133. package/src/Selector/Selector.test.tsx +135 -0
  134. package/src/Selector/Selector.tsx +141 -82
  135. package/src/Selector/SelectorBottomSheet.tsx +97 -0
  136. package/src/Selector/index.ts +1 -0
  137. package/src/Selector/selectorPresentation.stylex.ts +20 -0
  138. package/src/Selector/useSelectorPresentation.ts +147 -0
  139. package/src/Toast/ToastViewport.test.tsx +118 -4
  140. package/src/Toast/useToastGesture.ts +61 -8
  141. package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
  142. package/src/hooks/useAdaptivePresentation.ts +35 -0
  143. package/src/hooks/useFocusReturnVisibility.ts +45 -0
  144. package/src/hooks/useFocusTrap.test.tsx +40 -0
  145. package/src/hooks/useFocusTrap.ts +13 -0
  146. package/src/theme/themingTargets.test.ts +91 -25
@@ -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]
@@ -4,6 +4,7 @@
4
4
  * @position Public API entry point
5
5
  */
6
6
  export { ContextMenu, type ContextMenuProps, type ContextMenuItemData, type ContextMenuDividerData, type ContextMenuSection, type ContextMenuOption, } from './ContextMenu';
7
+ export type { AdaptivePresentation as MenuPresentation } from '../hooks/useAdaptivePresentation';
7
8
  export { DropdownMenuItem as ContextMenuItem, type DropdownMenuItemProps as ContextMenuItemProps, } from '../DropdownMenu/DropdownMenuItem';
8
9
  export { DropdownMenuDivider as ContextMenuDivider, type DropdownMenuDividerProps as ContextMenuDividerProps, } from '../DropdownMenu/DropdownMenuDivider';
9
10
  export { DropdownMenuCheckboxItem as ContextMenuCheckboxItem, type DropdownMenuCheckboxItemProps as ContextMenuCheckboxItemProps, } from '../DropdownMenu/DropdownMenuCheckboxItem';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ContextMenu/index.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,gBAAgB,IAAI,eAAe,EACnC,KAAK,qBAAqB,IAAI,oBAAoB,GACnD,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,mBAAmB,IAAI,kBAAkB,EACzC,KAAK,wBAAwB,IAAI,uBAAuB,GACzD,MAAM,qCAAqC,CAAC;AAI7C,OAAO,EACL,wBAAwB,IAAI,uBAAuB,EACnD,KAAK,6BAA6B,IAAI,4BAA4B,GACnE,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,sBAAsB,IAAI,qBAAqB,EAC/C,KAAK,2BAA2B,IAAI,0BAA0B,GAC/D,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,qBAAqB,IAAI,oBAAoB,EAC7C,KAAK,0BAA0B,IAAI,yBAAyB,GAC7D,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,mBAAmB,IAAI,kBAAkB,EACzC,KAAK,wBAAwB,IAAI,uBAAuB,GACzD,MAAM,qCAAqC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ContextMenu/index.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAC,oBAAoB,IAAI,gBAAgB,EAAC,MAAM,kCAAkC,CAAC;AAE/F,OAAO,EACL,gBAAgB,IAAI,eAAe,EACnC,KAAK,qBAAqB,IAAI,oBAAoB,GACnD,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,mBAAmB,IAAI,kBAAkB,EACzC,KAAK,wBAAwB,IAAI,uBAAuB,GACzD,MAAM,qCAAqC,CAAC;AAI7C,OAAO,EACL,wBAAwB,IAAI,uBAAuB,EACnD,KAAK,6BAA6B,IAAI,4BAA4B,GACnE,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,sBAAsB,IAAI,qBAAqB,EAC/C,KAAK,2BAA2B,IAAI,0BAA0B,GAC/D,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,qBAAqB,IAAI,oBAAoB,EAC7C,KAAK,0BAA0B,IAAI,yBAAyB,GAC7D,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,mBAAmB,IAAI,kBAAkB,EACzC,KAAK,wBAAwB,IAAI,uBAAuB,GACzD,MAAM,qCAAqC,CAAC"}
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * @file DropdownMenu.tsx
3
- * @input Uses React, StyleX, usePopover, Button, Icon, useListFocus
4
- * @output Exports DropdownMenu component
3
+ * @input Uses React, StyleX, usePopover, MenuBottomSheet, Button, List,
4
+ * useListFocus, and the shared viewport-safe menu-width resolver
5
+ * @output Exports DropdownMenu with caller-selected popover or bottom-sheet
6
+ * presentation
5
7
  * @position Core implementation; consumed by index.ts
6
8
  *
7
9
  * Supports two modes with a single keyboard/focus path:
@@ -25,6 +27,7 @@
25
27
  import React, { type ReactNode } from 'react';
26
28
  import { type ButtonProps } from '../Button';
27
29
  import type { DropdownMenuItemProps } from './DropdownMenuItem';
30
+ import { type AdaptivePresentation } from '../hooks/useAdaptivePresentation';
28
31
  import type { LayerAlignment, LayerPlacement } from '../Layer/useLayer';
29
32
  import type { BaseProps } from '../BaseProps';
30
33
  /**
@@ -69,21 +72,29 @@ export interface DropdownMenuSection {
69
72
  }
70
73
  export type DropdownMenuOption = DropdownMenuItemData | DropdownMenuDividerData | DropdownMenuSection;
71
74
  export type DropdownMenuButtonProps = Omit<ButtonProps, 'onClick'>;
75
+ export type DropdownMenuPresentation = AdaptivePresentation;
72
76
  interface DropdownMenuBaseProps extends BaseProps {
73
77
  button?: DropdownMenuButtonProps;
74
78
  isMenuOpen?: boolean;
75
79
  onOpenChange?: (isOpen: boolean) => void;
80
+ /**
81
+ * Minimum popover width. The menu may grow for its content but is capped to
82
+ * the available viewport space. Ignored by bottom-sheet presentation.
83
+ * Defaults to the trigger width.
84
+ */
76
85
  menuWidth?: number | string;
77
86
  onClick?: () => void;
78
87
  hasChevron?: boolean;
79
88
  /**
80
- * Position placement relative to the trigger.
89
+ * Popover position relative to the trigger. Ignored by bottom-sheet
90
+ * presentation.
81
91
  * Uses the same placement values as other Astryx layer-based components.
82
92
  * @default 'below'
83
93
  */
84
94
  placement?: LayerPlacement;
85
95
  /**
86
- * Alignment along the placement axis.
96
+ * Popover alignment along the placement axis. Ignored by bottom-sheet
97
+ * presentation.
87
98
  * Uses the same alignment values as other Astryx layer-based components.
88
99
  * @default 'start'
89
100
  */
@@ -91,15 +102,23 @@ interface DropdownMenuBaseProps extends BaseProps {
91
102
  'data-testid'?: string;
92
103
  }
93
104
  interface DropdownMenuDataProps extends DropdownMenuBaseProps {
105
+ /**
106
+ * Surface used to present the actions. Pass a value selected by product
107
+ * policy (for example, a compact-touch media query) when the presentation
108
+ * should adapt. Bottom-sheet presentation is intended for short action sets.
109
+ * @default 'popover'
110
+ */
111
+ presentation?: DropdownMenuPresentation;
94
112
  items: DropdownMenuOption[];
95
113
  children?: undefined;
96
114
  }
97
115
  interface DropdownMenuCompoundProps extends DropdownMenuBaseProps {
116
+ presentation?: 'popover';
98
117
  items?: undefined;
99
118
  children: ReactNode;
100
119
  }
101
120
  export type DropdownMenuProps = DropdownMenuDataProps | DropdownMenuCompoundProps;
102
- export declare function DropdownMenu({ button: buttonFromProps, isMenuOpen: controlledIsOpen, onOpenChange, menuWidth, onClick, hasChevron, placement, alignment, className, style, xstyle, 'data-testid': testId, ...props }: DropdownMenuProps): React.JSX.Element;
121
+ export declare function DropdownMenu(props: DropdownMenuProps): React.JSX.Element;
103
122
  export declare namespace DropdownMenu {
104
123
  var displayName: string;
105
124
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EAAS,KAAK,WAAW,EAAC,MAAM,WAAW,CAAC;AAInD,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oBAAoB,CAAC;AAa9D,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,mBAAmB,CAAC;AAQtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiC5C;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAChD,qBAAqB,EACnB,MAAM,GACN,SAAS,GACT,YAAY,GACZ,SAAS,GACT,aAAa,GACb,YAAY,GACZ,kBAAkB,CACrB;IACC;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,oBAAoB,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAC5B,oBAAoB,GAAG,uBAAuB,GAAG,mBAAmB,CAAC;AAMvE,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAEnE,UAAU,qBAAsB,SAAQ,SAAS;IAC/C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,qBAAsB,SAAQ,qBAAqB;IAC3D,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,UAAU,yBAA0B,SAAQ,qBAAqB;IAC/D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAC3B,qBAAqB,GAAG,yBAAyB,CAAC;AA+BpD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,gBAAgB,EAC5B,YAAY,EACZ,SAAS,EACT,OAAO,EACP,UAAiB,EACjB,SAAmB,EACnB,SAAmB,EACnB,SAAS,EACT,KAAK,EACL,MAAM,EACN,aAAa,EAAE,MAAM,EACrB,GAAG,KAAK,EACT,EAAE,iBAAiB,qBAkTnB;yBAhUe,YAAY"}
1
+ {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EAAS,KAAK,WAAW,EAAC,MAAM,WAAW,CAAC;AAKnD,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oBAAoB,CAAC;AAe9D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAC;AAI1C,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,mBAAmB,CAAC;AAStE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA8I5C;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAChD,qBAAqB,EACnB,MAAM,GACN,SAAS,GACT,YAAY,GACZ,SAAS,GACT,aAAa,GACb,YAAY,GACZ,kBAAkB,CACrB;IACC;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,oBAAoB,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAC5B,oBAAoB,GAAG,uBAAuB,GAAG,mBAAmB,CAAC;AAMvE,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAEnE,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,CAAC;AAE5D,UAAU,qBAAsB,SAAQ,SAAS;IAC/C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,qBAAsB,SAAQ,qBAAqB;IAC3D;;;;;OAKG;IACH,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,UAAU,yBAA0B,SAAQ,qBAAqB;IAC/D,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAC3B,qBAAqB,GAAG,yBAAyB,CAAC;AA8lBpD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,qBAqCpD;yBArCe,YAAY"}