@dreamtree-org/twreact-ui 1.3.10 → 2.0.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 (230) hide show
  1. package/README.md +70 -6
  2. package/ai-skills/dreamtree-ui.md +58 -15
  3. package/codemods/v2.cjs +198 -0
  4. package/dist/ai-schema.json +745 -53
  5. package/dist/charts/index.js +195 -66
  6. package/dist/components/blocks/AppShell.d.ts.map +1 -1
  7. package/dist/components/blocks/BottomActionBar.d.ts +6 -0
  8. package/dist/components/blocks/BottomActionBar.d.ts.map +1 -0
  9. package/dist/components/blocks/ConfirmDialog.d.ts.map +1 -1
  10. package/dist/components/blocks/PageHeader.d.ts.map +1 -1
  11. package/dist/components/charts/CartesianChart.d.ts.map +1 -1
  12. package/dist/components/charts/ChartFrame.d.ts.map +1 -1
  13. package/dist/components/charts/useChartLayout.d.ts +25 -0
  14. package/dist/components/charts/useChartLayout.d.ts.map +1 -0
  15. package/dist/components/core/Button.d.ts.map +1 -1
  16. package/dist/components/core/Checkbox.d.ts.map +1 -1
  17. package/dist/components/core/ColorPicker.d.ts.map +1 -1
  18. package/dist/components/core/DatePicker.d.ts.map +1 -1
  19. package/dist/components/core/DateRangePicker.d.ts.map +1 -1
  20. package/dist/components/core/Form.d.ts.map +1 -1
  21. package/dist/components/core/Input.d.ts.map +1 -1
  22. package/dist/components/core/Loader.d.ts.map +1 -1
  23. package/dist/components/core/LocationPicker.d.ts.map +1 -1
  24. package/dist/components/core/Popover.d.ts.map +1 -1
  25. package/dist/components/core/ProgressBar.d.ts.map +1 -1
  26. package/dist/components/core/Radio.d.ts.map +1 -1
  27. package/dist/components/core/Rate.d.ts.map +1 -1
  28. package/dist/components/core/RoundedTag.d.ts.map +1 -1
  29. package/dist/components/core/SearchField.d.ts +9 -0
  30. package/dist/components/core/SearchField.d.ts.map +1 -0
  31. package/dist/components/core/SegmentedControl.d.ts +8 -0
  32. package/dist/components/core/SegmentedControl.d.ts.map +1 -0
  33. package/dist/components/core/Select.d.ts.map +1 -1
  34. package/dist/components/core/Skeleton.d.ts.map +1 -1
  35. package/dist/components/core/Slider.d.ts.map +1 -1
  36. package/dist/components/core/SpeechToText.d.ts.map +1 -1
  37. package/dist/components/core/SwipeableListItem.d.ts +4 -0
  38. package/dist/components/core/SwipeableListItem.d.ts.map +1 -0
  39. package/dist/components/core/SwipeableListItemGesture.d.ts +58 -0
  40. package/dist/components/core/SwipeableListItemGesture.d.ts.map +1 -0
  41. package/dist/components/core/Switch.d.ts.map +1 -1
  42. package/dist/components/core/Table/ActionMenu.d.ts +10 -3
  43. package/dist/components/core/Table/ActionMenu.d.ts.map +1 -1
  44. package/dist/components/core/Table/MobileCard.d.ts +10 -1
  45. package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
  46. package/dist/components/core/Table/MobileFilters.d.ts +8 -2
  47. package/dist/components/core/Table/MobileFilters.d.ts.map +1 -1
  48. package/dist/components/core/Table/Table.d.ts.map +1 -1
  49. package/dist/components/core/Table/TableRow.d.ts +2 -1
  50. package/dist/components/core/Table/TableRow.d.ts.map +1 -1
  51. package/dist/components/core/Tabs.d.ts +5 -8
  52. package/dist/components/core/Tabs.d.ts.map +1 -1
  53. package/dist/components/core/Textarea.d.ts.map +1 -1
  54. package/dist/components/core/ThreeDotPopover.d.ts +10 -22
  55. package/dist/components/core/ThreeDotPopover.d.ts.map +1 -1
  56. package/dist/components/core/Tooltip.d.ts +2 -1
  57. package/dist/components/core/Tooltip.d.ts.map +1 -1
  58. package/dist/components/core/internal/Calendar.d.ts +77 -0
  59. package/dist/components/core/internal/Calendar.d.ts.map +1 -0
  60. package/dist/components/core/menu/ActionMenuSurface.d.ts +42 -0
  61. package/dist/components/core/menu/ActionMenuSurface.d.ts.map +1 -0
  62. package/dist/components/core/menu/ActionSheetMenu.d.ts +17 -0
  63. package/dist/components/core/menu/ActionSheetMenu.d.ts.map +1 -0
  64. package/dist/components/core/menu/MenuPopover.d.ts +21 -0
  65. package/dist/components/core/menu/MenuPopover.d.ts.map +1 -0
  66. package/dist/components/core/menu/menuItems.d.ts +21 -0
  67. package/dist/components/core/menu/menuItems.d.ts.map +1 -0
  68. package/dist/components/core/menu/menuKeyboard.d.ts +16 -0
  69. package/dist/components/core/menu/menuKeyboard.d.ts.map +1 -0
  70. package/dist/components/feedback/ActionSheet.d.ts +4 -0
  71. package/dist/components/feedback/ActionSheet.d.ts.map +1 -0
  72. package/dist/components/feedback/Alert.d.ts.map +1 -1
  73. package/dist/components/feedback/Dialog.d.ts.map +1 -1
  74. package/dist/components/feedback/Drawer.d.ts.map +1 -1
  75. package/dist/components/feedback/Sheet.d.ts +4 -0
  76. package/dist/components/feedback/Sheet.d.ts.map +1 -0
  77. package/dist/components/feedback/Toast.d.ts +4 -3
  78. package/dist/components/feedback/Toast.d.ts.map +1 -1
  79. package/dist/components/feedback/ToastItem.d.ts +47 -0
  80. package/dist/components/feedback/ToastItem.d.ts.map +1 -0
  81. package/dist/components/feedback/ToastStack.d.ts +20 -0
  82. package/dist/components/feedback/ToastStack.d.ts.map +1 -0
  83. package/dist/components/feedback/ToastSwipe.d.ts +22 -0
  84. package/dist/components/feedback/ToastSwipe.d.ts.map +1 -0
  85. package/dist/components/feedback/Tour.d.ts.map +1 -1
  86. package/dist/components/feedback/sheetCore.d.ts +30 -0
  87. package/dist/components/feedback/sheetCore.d.ts.map +1 -0
  88. package/dist/components/navigation/Breadcrumbs.d.ts.map +1 -1
  89. package/dist/components/navigation/FootNav.d.ts.map +1 -1
  90. package/dist/components/navigation/Navbar.d.ts.map +1 -1
  91. package/dist/components/navigation/Sidebar.d.ts +6 -0
  92. package/dist/components/navigation/Sidebar.d.ts.map +1 -1
  93. package/dist/components/rich-text/RichTextEditor.d.ts.map +1 -1
  94. package/dist/components/rich-text/RichTextToolbar.d.ts +6 -2
  95. package/dist/components/rich-text/RichTextToolbar.d.ts.map +1 -1
  96. package/dist/components/utility/Avatar.d.ts +8 -0
  97. package/dist/components/utility/Avatar.d.ts.map +1 -1
  98. package/dist/components/utility/AvatarGroup.d.ts +4 -0
  99. package/dist/components/utility/AvatarGroup.d.ts.map +1 -0
  100. package/dist/components/utility/Badge.d.ts.map +1 -1
  101. package/dist/components/utility/Card.d.ts.map +1 -1
  102. package/dist/components/utility/Carousel.d.ts.map +1 -1
  103. package/dist/components/utility/FileUpload.d.ts.map +1 -1
  104. package/dist/components/utility/Pagination.d.ts.map +1 -1
  105. package/dist/components/utility/PullToRefresh.d.ts +5 -0
  106. package/dist/components/utility/PullToRefresh.d.ts.map +1 -0
  107. package/dist/components/utility/Sortable.d.ts.map +1 -1
  108. package/dist/components/utility/Stepper.d.ts.map +1 -1
  109. package/dist/esm/components/blocks/AppShell.js +97 -90
  110. package/dist/esm/components/blocks/BottomActionBar.js +132 -0
  111. package/dist/esm/components/blocks/ConfirmDialog.js +40 -4
  112. package/dist/esm/components/blocks/EmptyState.js +1 -1
  113. package/dist/esm/components/blocks/ErrorState.js +1 -1
  114. package/dist/esm/components/blocks/LoadingState.js +4 -4
  115. package/dist/esm/components/blocks/PageHeader.js +16 -3
  116. package/dist/esm/components/blocks/StatCard.js +6 -6
  117. package/dist/esm/components/blocks/StatusPill.js +5 -8
  118. package/dist/esm/components/charts/CartesianChart.js +85 -62
  119. package/dist/esm/components/charts/ChartFrame.js +12 -5
  120. package/dist/esm/components/charts/useChartLayout.js +105 -0
  121. package/dist/esm/components/core/Button.js +49 -25
  122. package/dist/esm/components/core/Checkbox.js +72 -57
  123. package/dist/esm/components/core/ColorPicker.js +31 -42
  124. package/dist/esm/components/core/DatePicker.js +117 -304
  125. package/dist/esm/components/core/DateRangePicker.js +260 -308
  126. package/dist/esm/components/core/Form.js +11 -2
  127. package/dist/esm/components/core/Input.js +100 -38
  128. package/dist/esm/components/core/Loader.js +30 -44
  129. package/dist/esm/components/core/LocationPicker.js +82 -16
  130. package/dist/esm/components/core/Popover.js +59 -48
  131. package/dist/esm/components/core/ProgressBar.js +40 -72
  132. package/dist/esm/components/core/Radio.js +10 -12
  133. package/dist/esm/components/core/Rate.js +77 -14
  134. package/dist/esm/components/core/RoundedTag.js +5 -5
  135. package/dist/esm/components/core/SearchField.js +311 -0
  136. package/dist/esm/components/core/SegmentedControl.js +189 -0
  137. package/dist/esm/components/core/Select.js +185 -190
  138. package/dist/esm/components/core/Skeleton.js +13 -14
  139. package/dist/esm/components/core/Slider.js +24 -6
  140. package/dist/esm/components/core/SpeechToText.js +68 -16
  141. package/dist/esm/components/core/SwipeableListItem.js +286 -0
  142. package/dist/esm/components/core/SwipeableListItemGesture.js +219 -0
  143. package/dist/esm/components/core/Switch.js +98 -28
  144. package/dist/esm/components/core/Table/ActionMenu.js +45 -231
  145. package/dist/esm/components/core/Table/ColumnMenu.js +1 -1
  146. package/dist/esm/components/core/Table/MobileCard.js +66 -16
  147. package/dist/esm/components/core/Table/MobileFilters.js +181 -10
  148. package/dist/esm/components/core/Table/Table.js +149 -102
  149. package/dist/esm/components/core/Table/TableRow.js +10 -2
  150. package/dist/esm/components/core/Tabs.js +186 -39
  151. package/dist/esm/components/core/Textarea.js +10 -2
  152. package/dist/esm/components/core/ThreeDotPopover.js +93 -99
  153. package/dist/esm/components/core/Tooltip.js +138 -145
  154. package/dist/esm/components/core/internal/Calendar.js +381 -0
  155. package/dist/esm/components/core/menu/ActionMenuSurface.js +110 -0
  156. package/dist/esm/components/core/menu/ActionSheetMenu.js +140 -0
  157. package/dist/esm/components/core/menu/MenuPopover.js +177 -0
  158. package/dist/esm/components/core/menu/menuItems.js +61 -0
  159. package/dist/esm/components/core/menu/menuKeyboard.js +54 -0
  160. package/dist/esm/components/feedback/ActionSheet.js +55 -0
  161. package/dist/esm/components/feedback/Alert.js +63 -53
  162. package/dist/esm/components/feedback/Dialog.js +141 -53
  163. package/dist/esm/components/feedback/Drawer.js +130 -132
  164. package/dist/esm/components/feedback/Sheet.js +125 -0
  165. package/dist/esm/components/feedback/Toast.js +21 -291
  166. package/dist/esm/components/feedback/ToastItem.js +348 -0
  167. package/dist/esm/components/feedback/ToastStack.js +130 -0
  168. package/dist/esm/components/feedback/ToastSwipe.js +52 -0
  169. package/dist/esm/components/feedback/Tour.js +107 -30
  170. package/dist/esm/components/feedback/sheetCore.js +494 -0
  171. package/dist/esm/components/navigation/Breadcrumbs.js +97 -35
  172. package/dist/esm/components/navigation/Dropdown.js +1 -1
  173. package/dist/esm/components/navigation/FootNav.js +102 -13
  174. package/dist/esm/components/navigation/Navbar.js +172 -37
  175. package/dist/esm/components/navigation/Sidebar.js +263 -111
  176. package/dist/esm/components/rich-text/RichTextEditor.js +9 -3
  177. package/dist/esm/components/rich-text/RichTextToolbar.js +29 -9
  178. package/dist/esm/components/utility/Avatar.js +14 -12
  179. package/dist/esm/components/utility/AvatarGroup.js +56 -0
  180. package/dist/esm/components/utility/Badge.js +43 -23
  181. package/dist/esm/components/utility/Card.js +32 -8
  182. package/dist/esm/components/utility/Carousel.js +139 -29
  183. package/dist/esm/components/utility/FileUpload.js +106 -31
  184. package/dist/esm/components/utility/Pagination.js +31 -13
  185. package/dist/esm/components/utility/Portal.js +31 -0
  186. package/dist/esm/components/utility/PullToRefresh.js +229 -0
  187. package/dist/esm/components/utility/Sortable.js +6 -2
  188. package/dist/esm/components/utility/Stepper.js +110 -47
  189. package/dist/esm/hooks/useFloatingPosition.js +82 -0
  190. package/dist/esm/hooks/useHaptics.js +65 -0
  191. package/dist/esm/hooks/usePresence.js +58 -0
  192. package/dist/esm/hooks/usePresentation.js +21 -0
  193. package/dist/esm/hooks/useSheetDrag.js +220 -0
  194. package/dist/esm/hooks/useSliderValues.js +8 -2
  195. package/dist/esm/hooks/useSortable.js +107 -5
  196. package/dist/esm/index.js +14 -2
  197. package/dist/esm/utils/position.js +10 -63
  198. package/dist/esm/utils/touchTarget.js +4 -1
  199. package/dist/hooks/useFloatingPosition.d.ts +8 -4
  200. package/dist/hooks/useFloatingPosition.d.ts.map +1 -1
  201. package/dist/hooks/useHaptics.d.ts +19 -0
  202. package/dist/hooks/useHaptics.d.ts.map +1 -0
  203. package/dist/hooks/useSheetDrag.d.ts +31 -0
  204. package/dist/hooks/useSheetDrag.d.ts.map +1 -0
  205. package/dist/hooks/useSliderValues.d.ts +6 -2
  206. package/dist/hooks/useSliderValues.d.ts.map +1 -1
  207. package/dist/hooks/useSortable.d.ts +11 -1
  208. package/dist/hooks/useSortable.d.ts.map +1 -1
  209. package/dist/index.css +1 -1
  210. package/dist/index.d.ts +11 -2
  211. package/dist/index.esm.css +1 -1
  212. package/dist/index.esm.js +10645 -3842
  213. package/dist/index.js +10657 -3845
  214. package/dist/rich-text/index.js +41 -11
  215. package/dist/types/blocks.d.ts +32 -2
  216. package/dist/types/blocks.d.ts.map +1 -1
  217. package/dist/types/charts.d.ts +3 -1
  218. package/dist/types/charts.d.ts.map +1 -1
  219. package/dist/types/index.d.ts +409 -26
  220. package/dist/types/index.d.ts.map +1 -1
  221. package/dist/types/rich-text.d.ts +5 -0
  222. package/dist/types/rich-text.d.ts.map +1 -1
  223. package/dist/utils/position.d.ts +0 -15
  224. package/dist/utils/position.d.ts.map +1 -1
  225. package/doc/README.md +16 -0
  226. package/mcp/catalog.snapshot.json +1540 -407
  227. package/package.json +7 -2
  228. package/dist/esm/hooks/useSwipeToClose.js +0 -66
  229. package/dist/hooks/useSwipeToClose.d.ts +0 -24
  230. package/dist/hooks/useSwipeToClose.d.ts.map +0 -1
@@ -1,10 +1,19 @@
1
1
  'use client';
2
2
  import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
- import React, { forwardRef, useState, useRef, useId, useEffect, createContext, useContext } from 'react';
4
+ import React, { forwardRef, useState, useRef, useId, useEffect, createContext, useContext, useLayoutEffect } from 'react';
5
5
  import { cn } from '../../utils/cn.js';
6
6
 
7
- var _excluded = ["children", "defaultIndex", "index", "onChange", "orientation", "size", "variant", "animated", "className"];
7
+ var _excluded = ["children", "defaultIndex", "index", "onChange", "orientation", "size", "variant", "animated", "swipeable", "className"],
8
+ _excluded2 = ["children", "className"];
9
+ // useLayoutEffect warns during SSR; fall back to useEffect on the server.
10
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
11
+ // Minimum horizontal travel (px) for a swipe to change tabs, and how much more
12
+ // horizontal than vertical it must be, so vertical page scrolls never switch tabs.
13
+ var SWIPE_THRESHOLD = 50;
14
+ var SWIPE_DOMINANCE = 1.5;
15
+ // Variants whose active state is drawn by the sliding indicator (horizontal only).
16
+ var INDICATOR_VARIANTS = ["line", "segmented"];
8
17
  /*
9
18
  Tabs.jsx
10
19
  - Default export: Tabs (provider wrapper)
@@ -14,7 +23,10 @@ var _excluded = ["children", "defaultIndex", "index", "onChange", "orientation",
14
23
  - Controlled / uncontrolled usage
15
24
  - Keyboard navigation (Arrow keys, Home, End)
16
25
  - ARIA attributes for accessibility
17
- - Variants: "line" | "pills" | "unstyled"
26
+ - Variants: "line" | "pills" | "segmented" | "unstyled"
27
+ - Horizontal lists scroll with snap; the active tab is kept in view
28
+ - Animated active indicator for "line" / "segmented" (off under reduced motion)
29
+ - Optional `swipeable` panels (touch / pen pointer swipes)
18
30
  - Sizes: "sm" | "md" | "lg"
19
31
  - Simple fade animation
20
32
  - Tailwind CSS only
@@ -60,6 +72,8 @@ var Tabs = /*#__PURE__*/forwardRef(function Tabs(_ref, ref) {
60
72
  variant = _ref$variant === void 0 ? "line" : _ref$variant,
61
73
  _ref$animated = _ref.animated,
62
74
  animated = _ref$animated === void 0 ? true : _ref$animated,
75
+ _ref$swipeable = _ref.swipeable,
76
+ swipeable = _ref$swipeable === void 0 ? false : _ref$swipeable,
63
77
  _ref$className = _ref.className,
64
78
  className = _ref$className === void 0 ? "" : _ref$className,
65
79
  rest = _objectWithoutProperties(_ref, _excluded);
@@ -71,6 +85,12 @@ var Tabs = /*#__PURE__*/forwardRef(function Tabs(_ref, ref) {
71
85
  var activeIndex = isControlled ? controlledIndex : internalIndex;
72
86
  var tabsRef = useRef([]); // DOM refs for keyboard navigation
73
87
  var baseId = useId();
88
+ // Set by TabList once the sliding indicator has been measured; until then
89
+ // (SSR, first paint) tabs draw their own active styling.
90
+ var _useState3 = useState(false),
91
+ _useState4 = _slicedToArray(_useState3, 2),
92
+ indicatorReady = _useState4[0],
93
+ setIndicatorReady = _useState4[1];
74
94
  var changeTab = function changeTab(idx) {
75
95
  if (!isControlled) setActiveIndex(idx);
76
96
  onChange === null || onChange === void 0 || onChange(idx);
@@ -87,7 +107,10 @@ var Tabs = /*#__PURE__*/forwardRef(function Tabs(_ref, ref) {
87
107
  orientation: orientation,
88
108
  size: size,
89
109
  variant: variant,
90
- animated: animated
110
+ animated: animated,
111
+ swipeable: swipeable,
112
+ indicatorReady: indicatorReady,
113
+ setIndicatorReady: setIndicatorReady
91
114
  };
92
115
  return jsx(TabsContext.Provider, {
93
116
  value: value,
@@ -101,33 +124,104 @@ var Tabs = /*#__PURE__*/forwardRef(function Tabs(_ref, ref) {
101
124
  });
102
125
  Tabs.displayName = "Tabs";
103
126
  /* ------------------------- TabList ------------------------- */
104
- function TabList(_ref2) {
127
+ var TabList = /*#__PURE__*/forwardRef(function TabList(_ref2, ref) {
105
128
  var children = _ref2.children,
106
129
  _ref2$className = _ref2.className,
107
- className = _ref2$className === void 0 ? "" : _ref2$className;
130
+ className = _ref2$className === void 0 ? "" : _ref2$className,
131
+ rest = _objectWithoutProperties(_ref2, _excluded2);
108
132
  var _useTabsContext = useTabsContext("Tabs.List"),
109
- orientation = _useTabsContext.orientation;
110
- return jsx("div", {
133
+ orientation = _useTabsContext.orientation,
134
+ variant = _useTabsContext.variant,
135
+ activeIndex = _useTabsContext.activeIndex,
136
+ tabsRef = _useTabsContext.tabsRef,
137
+ indicatorReady = _useTabsContext.indicatorReady,
138
+ setIndicatorReady = _useTabsContext.setIndicatorReady;
139
+ var listRef = useRef(null);
140
+ var _useState5 = useState(null),
141
+ _useState6 = _slicedToArray(_useState5, 2),
142
+ indicator = _useState6[0],
143
+ setIndicator = _useState6[1];
144
+ var horizontal = orientation !== "vertical";
145
+ var hasIndicator = horizontal && INDICATOR_VARIANTS.includes(variant);
146
+ var childCount = React.Children.count(children);
147
+ var setRefs = function setRefs(node) {
148
+ listRef.current = node;
149
+ if (typeof ref === "function") ref(node);else if (ref) ref.current = node;
150
+ };
151
+ // Measure the active tab: position the indicator and scroll the tab into view.
152
+ useIsomorphicLayoutEffect(function () {
153
+ var list = listRef.current;
154
+ var tab = tabsRef.current[activeIndex];
155
+ if (!list || !tab) return undefined;
156
+ var measure = function measure() {
157
+ if (horizontal) {
158
+ var left = tab.offsetLeft;
159
+ var right = left + tab.offsetWidth;
160
+ if (left < list.scrollLeft) list.scrollLeft = left;else if (right > list.scrollLeft + list.clientWidth) list.scrollLeft = right - list.clientWidth;
161
+ }
162
+ // jsdom / display:none report 0; keep the tabs' own active styling then.
163
+ if (!hasIndicator || !tab.offsetWidth) return;
164
+ setIndicator({
165
+ left: tab.offsetLeft,
166
+ top: tab.offsetTop,
167
+ width: tab.offsetWidth,
168
+ height: tab.offsetHeight
169
+ });
170
+ setIndicatorReady(true);
171
+ };
172
+ measure();
173
+ if (typeof ResizeObserver === "undefined") return undefined;
174
+ var ro = new ResizeObserver(measure);
175
+ ro.observe(list);
176
+ ro.observe(tab);
177
+ return function () {
178
+ return ro.disconnect();
179
+ };
180
+ }, [activeIndex, hasIndicator, horizontal, childCount]); // eslint-disable-line react-hooks/exhaustive-deps
181
+ // Leaving an indicator variant hands the active styling back to the tabs.
182
+ useEffect(function () {
183
+ if (!hasIndicator && indicatorReady) setIndicatorReady(false);
184
+ }, [hasIndicator, indicatorReady, setIndicatorReady]);
185
+ var showIndicator = hasIndicator && indicatorReady && indicator;
186
+ return jsxs("div", _objectSpread2(_objectSpread2({
187
+ ref: setRefs,
111
188
  role: "tablist",
112
189
  "aria-orientation": orientation,
113
- className: "flex ".concat(orientation === "vertical" ? "flex-col" : "flex-row", " gap-1 ").concat(className),
114
- children: React.Children.map(children, function (child, i) {
190
+ className: cn("relative flex gap-1", horizontal ?
191
+ // Scroll with snap, scrollbar hidden; native smooth scrolling unless reduced motion.
192
+ "flex-row overflow-x-auto snap-x snap-mandatory scroll-smooth motion-reduce:scroll-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden" : "flex-col", variant === "segmented" && "rounded-lg bg-line p-1", className)
193
+ }, rest), {}, {
194
+ children: [showIndicator && jsx("span", {
195
+ "aria-hidden": "true",
196
+ "data-tabs-indicator": "",
197
+ className: cn("pointer-events-none absolute left-0 top-0", "transition-[transform,width,height] duration-base ease-standard motion-reduce:transition-none", variant === "line" ? "bg-primary-500" : "rounded-md bg-surface shadow-sm"),
198
+ style: variant === "line" ? {
199
+ width: indicator.width,
200
+ height: 2,
201
+ transform: "translate(".concat(indicator.left, "px, ").concat(indicator.top + indicator.height - 2, "px)")
202
+ } : {
203
+ width: indicator.width,
204
+ height: indicator.height,
205
+ transform: "translate(".concat(indicator.left, "px, ").concat(indicator.top, "px)")
206
+ }
207
+ }), React.Children.map(children, function (child, i) {
115
208
  var _child$props$index;
116
209
  if (! /*#__PURE__*/React.isValidElement(child)) return child;
117
210
  return /*#__PURE__*/React.cloneElement(child, {
118
211
  index: (_child$props$index = child.props.index) !== null && _child$props$index !== void 0 ? _child$props$index : i
119
212
  });
120
- })
121
- });
122
- }
213
+ })]
214
+ }));
215
+ });
216
+ TabList.displayName = "Tabs.List";
123
217
  /* ------------------------- Tab ------------------------- */
124
218
  function Tab(_ref3) {
125
219
  var children = _ref3.children,
126
220
  index = _ref3.index,
127
221
  _ref3$className = _ref3.className,
128
222
  className = _ref3$className === void 0 ? "" : _ref3$className,
129
- iconLeft = _ref3.iconLeft,
130
- iconRight = _ref3.iconRight,
223
+ leftIcon = _ref3.leftIcon,
224
+ rightIcon = _ref3.rightIcon,
131
225
  _ref3$disabled = _ref3.disabled,
132
226
  disabled = _ref3$disabled === void 0 ? false : _ref3$disabled,
133
227
  _ref3$tabClassName = _ref3.tabClassName,
@@ -139,32 +233,45 @@ function Tab(_ref3) {
139
233
  tabsRef = _useTabsContext2.tabsRef,
140
234
  baseId = _useTabsContext2.baseId,
141
235
  size = _useTabsContext2.size,
142
- variant = _useTabsContext2.variant;
236
+ variant = _useTabsContext2.variant,
237
+ orientation = _useTabsContext2.orientation,
238
+ indicatorReady = _useTabsContext2.indicatorReady;
143
239
  var internalRef = useRef(null);
144
240
  // If the user didn't provide `index` we derive from DOM position by registering nulls until mount.
145
241
  // However it's recommended to always keep Tabs.Tab order consistent with Panels.
146
- useEffect(function () {
242
+ // Registered from a ref callback (runs at commit, before any layout effect) so
243
+ // Tabs.List can measure the active tab on mount without a flash.
244
+ var setTabRef = function setTabRef(el) {
245
+ internalRef.current = el;
246
+ if (!el) return;
147
247
  // find index in tabsRef if index not provided
148
- var idx = typeof index === "number" ? index : tabsRef.current.findIndex(function (el) {
149
- return el === internalRef.current;
248
+ var slot = typeof index === "number" ? index : tabsRef.current.findIndex(function (node) {
249
+ return node === el;
150
250
  });
151
- if (idx === -1) idx = tabsRef.current.length; // fallback
152
- registerTab(internalRef.current, idx);
153
- // ensure the tab has the correct array slot
154
- }, []); // eslint-disable-line react-hooks/exhaustive-deps
251
+ if (slot === -1) slot = tabsRef.current.length; // fallback
252
+ registerTab(el, slot);
253
+ };
155
254
  // TabList always injects `index`; a Tab rendered outside it is never selected.
156
255
  var idx = typeof index === "number" ? index : -1;
157
256
  var selected = idx === activeIndex;
158
257
  var id = tabId(baseId, idx);
159
- var base = "inline-flex items-center gap-2 outline-none select-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1";
258
+ var horizontal = orientation !== "vertical";
259
+ // Once the sliding indicator is measured it draws the active state; until then
260
+ // (SSR / first paint) the tab draws it itself so nothing flashes.
261
+ var indicatorDraws = indicatorReady && horizontal && INDICATOR_VARIANTS.includes(variant);
262
+ var base = cn("relative inline-flex items-center gap-2 whitespace-nowrap outline-none select-none", "focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1", "transition-colors duration-fast motion-reduce:transition-none", "disabled:cursor-not-allowed disabled:opacity-50",
263
+ // The scrolling list clips outside rings, so horizontal tabs draw theirs inset.
264
+ horizontal && "shrink-0 snap-start focus-visible:ring-inset focus-visible:ring-offset-0");
160
265
  var sizeClasses = {
161
266
  sm: "px-2 py-1 text-sm",
162
267
  md: "px-3 py-2 text-sm",
163
268
  lg: "px-4 py-3 text-base"
164
269
  };
165
270
  var variantClasses = {
166
- line: selected ? "border-b-2 border-primary-500" : "border-b-2 border-transparent hover:border-gray-200",
167
- pills: selected ? "bg-primary-600 text-white rounded-full shadow-sm" : "bg-transparent rounded-full hover:bg-gray-100",
271
+ line: selected ? cn("border-b-2", indicatorDraws ? "border-transparent" : "border-primary-500") : "border-b-2 border-transparent hover:border-gray-200 dark:hover:border-gray-700",
272
+ pills: selected ? "bg-primary-600 text-white rounded-full shadow-sm" : "bg-transparent rounded-full hover:bg-gray-100 dark:hover:bg-gray-800",
273
+ // iOS-style segmented control: equal-width segments on a tinted track.
274
+ segmented: cn("z-10 flex-1 justify-center rounded-md font-medium", selected ? cn("text-foreground", !indicatorDraws && "bg-surface shadow-sm") : "text-muted hover:text-foreground"),
168
275
  unstyled: ""
169
276
  };
170
277
  var computedClass = cn(base, sizeClasses[size] || sizeClasses.md, variantClasses[variant], tabClassName, className);
@@ -208,7 +315,7 @@ function Tab(_ref3) {
208
315
  }
209
316
  };
210
317
  return jsxs("button", {
211
- ref: internalRef,
318
+ ref: setTabRef,
212
319
  id: id,
213
320
  role: "tab",
214
321
  "aria-selected": selected,
@@ -220,14 +327,14 @@ function Tab(_ref3) {
220
327
  return !disabled && changeTab(idx);
221
328
  },
222
329
  onKeyDown: onKeyDown,
223
- children: [iconLeft && jsx("span", {
330
+ children: [leftIcon && jsx("span", {
224
331
  className: "shrink-0",
225
- children: iconLeft
332
+ children: leftIcon
226
333
  }), jsx("span", {
227
334
  children: children
228
- }), iconRight && jsx("span", {
335
+ }), rightIcon && jsx("span", {
229
336
  className: "shrink-0",
230
- children: iconRight
337
+ children: rightIcon
231
338
  })]
232
339
  });
233
340
  }
@@ -237,9 +344,49 @@ function Panels(_ref4) {
237
344
  _ref4$className = _ref4.className,
238
345
  className = _ref4$className === void 0 ? "" : _ref4$className;
239
346
  var _useTabsContext3 = useTabsContext("Tabs.Panels"),
240
- animated = _useTabsContext3.animated;
241
- return jsx("div", {
242
- className: "relative w-full ".concat(className),
347
+ animated = _useTabsContext3.animated,
348
+ swipeable = _useTabsContext3.swipeable,
349
+ activeIndex = _useTabsContext3.activeIndex,
350
+ changeTab = _useTabsContext3.changeTab,
351
+ tabsRef = _useTabsContext3.tabsRef;
352
+ var start = useRef(null);
353
+ // Next enabled tab in `dir`, or -1 at either end (no wrap-around on swipe).
354
+ var neighbour = function neighbour(dir) {
355
+ var tabs = tabsRef.current;
356
+ for (var i = activeIndex + dir; i >= 0 && i < tabs.length; i += dir) {
357
+ if (tabs[i] && !tabs[i].disabled) return i;
358
+ }
359
+ return -1;
360
+ };
361
+ var swipeHandlers = swipeable ? {
362
+ onPointerDown: function onPointerDown(e) {
363
+ // Touch and pen only: a mouse drag selects text instead.
364
+ if (e.pointerType === "mouse" || e.isPrimary === false) return;
365
+ start.current = {
366
+ x: e.clientX,
367
+ y: e.clientY
368
+ };
369
+ },
370
+ onPointerUp: function onPointerUp(e) {
371
+ var from = start.current;
372
+ start.current = null;
373
+ if (!from) return;
374
+ var dx = e.clientX - from.x;
375
+ var dy = e.clientY - from.y;
376
+ if (!Number.isFinite(dx) || !Number.isFinite(dy)) return;
377
+ if (Math.abs(dx) < SWIPE_THRESHOLD || Math.abs(dx) < Math.abs(dy) * SWIPE_DOMINANCE) return;
378
+ // Swipe left -> next tab, swipe right -> previous tab.
379
+ var next = neighbour(dx < 0 ? 1 : -1);
380
+ if (next !== -1) changeTab(next);
381
+ },
382
+ onPointerCancel: function onPointerCancel() {
383
+ start.current = null;
384
+ }
385
+ } : {};
386
+ return jsx("div", _objectSpread2(_objectSpread2({
387
+ // touch-pan-y: the browser keeps vertical scrolling; horizontal moves reach us.
388
+ className: cn("relative w-full", swipeable && "touch-pan-y", className)
389
+ }, swipeHandlers), {}, {
243
390
  children: React.Children.map(children, function (child, i) {
244
391
  var _child$props$index2;
245
392
  // inject index if missing
@@ -249,7 +396,7 @@ function Panels(_ref4) {
249
396
  animated: animated
250
397
  });
251
398
  })
252
- });
399
+ }));
253
400
  }
254
401
  function Panel(_ref5) {
255
402
  var children = _ref5.children,
@@ -262,10 +409,10 @@ function Panel(_ref5) {
262
409
  activeIndex = _useTabsContext4.activeIndex,
263
410
  baseId = _useTabsContext4.baseId;
264
411
  var isActive = index === activeIndex;
265
- var _useState3 = useState(isActive),
266
- _useState4 = _slicedToArray(_useState3, 2),
267
- wasActive = _useState4[0],
268
- setWasActive = _useState4[1];
412
+ var _useState7 = useState(isActive),
413
+ _useState8 = _slicedToArray(_useState7, 2),
414
+ wasActive = _useState8[0],
415
+ setWasActive = _useState8[1];
269
416
  // Remember that the panel has been shown once (adjust-during-render pattern).
270
417
  if (isActive && !wasActive) setWasActive(true);
271
418
  if (!wasActive && !isActive) return null;
@@ -6,7 +6,7 @@ import { AlertCircle } from 'lucide-react';
6
6
  import { cn } from '../../utils/cn.js';
7
7
  import { setRefs } from '../../utils/position.js';
8
8
 
9
- var _excluded = ["id", "className", "label", "error", "helperText", "required", "disabled", "showCount", "maxLength", "autoResize", "rows", "maxRows", "value", "defaultValue", "onChange"];
9
+ var _excluded = ["id", "className", "label", "error", "helperText", "required", "disabled", "showCount", "maxLength", "autoResize", "rows", "maxRows", "value", "defaultValue", "onChange", "size"];
10
10
  var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
11
11
  function fitToContent(el, maxRows) {
12
12
  if (!el) return;
@@ -24,6 +24,12 @@ function fitToContent(el, maxRows) {
24
24
  }
25
25
  el.style.height = "".concat(height, "px");
26
26
  }
27
+ // Padding / text per size; `md` is the original look. Rows set the height.
28
+ var SIZE_CLASSES = {
29
+ sm: "px-2.5 py-1.5 text-xs",
30
+ md: "px-3 py-2 text-sm",
31
+ lg: "px-4 py-2.5 text-base"
32
+ };
27
33
  var Textarea = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
28
34
  var id = _ref.id,
29
35
  className = _ref.className,
@@ -45,6 +51,8 @@ var Textarea = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
45
51
  value = _ref.value,
46
52
  defaultValue = _ref.defaultValue,
47
53
  onChange = _ref.onChange,
54
+ _ref$size = _ref.size,
55
+ size = _ref$size === void 0 ? "md" : _ref$size,
48
56
  rest = _objectWithoutProperties(_ref, _excluded);
49
57
  var reactId = useId();
50
58
  var textareaId = id || "textarea-".concat(reactId);
@@ -93,7 +101,7 @@ var Textarea = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
93
101
  onChange: handleChange,
94
102
  "aria-invalid": error ? true : undefined,
95
103
  "aria-describedby": describedBy,
96
- className: cn("block w-full rounded-md border bg-white px-3 py-2 text-sm text-gray-900 placeholder-gray-400", "focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500", "disabled:cursor-not-allowed disabled:opacity-50", "dark:bg-gray-900 dark:text-gray-100 dark:placeholder-gray-500 dark:focus:ring-offset-gray-900", error ? "border-error-500 focus:ring-error-500" : "border-gray-300 dark:border-gray-600", autoResize ? "resize-none" : "resize-y", className)
104
+ className: cn("block w-full rounded-md border bg-surface text-foreground placeholder-gray-400", SIZE_CLASSES[size] || SIZE_CLASSES.md, "transition-colors duration-fast ease-standard motion-reduce:transition-none", "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-50", "dark:placeholder-gray-500 dark:focus-visible:ring-offset-gray-900", error ? "border-error-500 focus-visible:ring-error-500 dark:border-error-400" : "border-gray-300 focus-visible:ring-primary-500 dark:border-gray-600", autoResize ? "resize-none" : "resize-y", className)
97
105
  })), (error || helperText || showCount && maxLength) && jsxs("div", {
98
106
  className: "mt-1 flex items-start justify-between gap-3 text-sm",
99
107
  children: [jsxs("div", {
@@ -1,37 +1,28 @@
1
1
  'use client';
2
2
  import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
- import React, { forwardRef, useRef, useCallback, useState, useEffect } from 'react';
4
+ import React, { forwardRef, useRef, useState, useCallback, useId } from 'react';
5
5
  import { MoreVertical } from 'lucide-react';
6
6
  import { cn } from '../../utils/cn.js';
7
+ import { TOUCH_TARGET } from '../../utils/touchTarget.js';
8
+ import ActionMenuSurface from './menu/ActionMenuSurface.js';
9
+ import { renderIcon } from './menu/menuItems.js';
7
10
 
8
- var _excluded = ["items", "trigger", "className", "menuClass", "menuItemClass", "closeOnSelect", "ariaLabel", "wrapperClassName"];
11
+ var _excluded = ["items", "trigger", "className", "menuClass", "menuItemClass", "closeOnSelect", "ariaLabel", "wrapperClassName", "presentation", "cancelLabel"];
9
12
  /**
10
- * ThreeDotPopover (Simple)
13
+ * ThreeDotPopover
11
14
  *
12
- * A minimal three-dot popover for your UI library.
15
+ * A kebab (three-dot) button that opens an action menu.
13
16
  *
14
- * Features (simple):
15
- * - Minimal, single-file React component (no animation libs, no portals).
16
- * - Click trigger toggles menu (default three-dot icon or custom trigger node).
17
- * - Close on outside click and Escape key.
18
- * - Menu items: { key, label, icon?, onClick?, disabled?, destructive? }.
17
+ * - Desktop (`presentation="popover"`): a portaled floating `role="menu"`
18
+ * that flips/shifts to stay on screen, with roving focus (ArrowUp/Down,
19
+ * Home/End, typeahead). Escape closes and returns focus to the trigger.
20
+ * - Phones (`presentation="sheet"`): an iOS-style action sheet with a
21
+ * separate Cancel button.
22
+ * - `presentation="auto"` (default) picks the sheet on small touch screens.
19
23
  *
20
- * Props:
21
- * - items: Array of menu item objects (see above)
22
- * - trigger: optional React node to use as trigger (falls back to three-dot button)
23
- * - className: additional class for trigger wrapper
24
- * - menuClass: additional class for menu container
25
- * - menuItemClass: additional class for every menu item
26
- * - closeOnSelect: boolean (default true)
27
- *
28
- * Example:
29
- * const items = [
30
- * { key: 'edit', label: 'Edit', icon: Edit2, onClick: () => {} },
31
- * { key: 'view', label: 'View', icon: Eye, onClick: () => {} },
32
- * { key: 'delete', label: 'Delete', destructive: true, onClick: () => {} },
33
- * ];
34
- * <ThreeDotPopoverSimple items={items} />
24
+ * Items: { key, label, icon?, onClick?, disabled?, destructive?, tone? }.
25
+ * `tone: 'destructive'` and `destructive: true` are equivalent.
35
26
  */
36
27
  var ThreeDotPopoverSimple = /*#__PURE__*/forwardRef(function ThreeDotPopoverSimple(_ref, ref) {
37
28
  var _ref$items = _ref.items,
@@ -50,108 +41,111 @@ var ThreeDotPopoverSimple = /*#__PURE__*/forwardRef(function ThreeDotPopoverSimp
50
41
  ariaLabel = _ref$ariaLabel === void 0 ? "More options" : _ref$ariaLabel,
51
42
  _ref$wrapperClassName = _ref.wrapperClassName,
52
43
  wrapperClassName = _ref$wrapperClassName === void 0 ? "" : _ref$wrapperClassName,
44
+ _ref$presentation = _ref.presentation,
45
+ presentation = _ref$presentation === void 0 ? "auto" : _ref$presentation,
46
+ _ref$cancelLabel = _ref.cancelLabel,
47
+ cancelLabel = _ref$cancelLabel === void 0 ? "Cancel" : _ref$cancelLabel,
53
48
  rest = _objectWithoutProperties(_ref, _excluded);
54
49
  var triggerRef = useRef(null);
55
- // Callback ref for a consumer-supplied trigger: handing a function (not the
56
- // ref object) to cloneElement keeps ref access out of render.
50
+ var _useState = useState(null),
51
+ _useState2 = _slicedToArray(_useState, 2),
52
+ anchorEl = _useState2[0],
53
+ setAnchorEl = _useState2[1];
54
+ // Callback ref for the trigger (default or consumer-supplied): handing a
55
+ // function (not the ref object) to cloneElement keeps ref access out of render.
57
56
  var setTriggerNode = useCallback(function (node) {
58
57
  triggerRef.current = node;
58
+ setAnchorEl(node);
59
59
  }, []);
60
- var menuRef = useRef(null);
61
- var _useState = useState(false),
62
- _useState2 = _slicedToArray(_useState, 2),
63
- open = _useState2[0],
64
- setOpen = _useState2[1];
65
- useEffect(function () {
66
- function onDocClick(e) {
67
- if (!open) return;
68
- if (triggerRef.current && triggerRef.current.contains(e.target)) return;
69
- if (menuRef.current && menuRef.current.contains(e.target)) return;
70
- setOpen(false);
71
- }
72
- function onKey(e) {
73
- if (!open) return;
74
- if (e.key === "Escape") setOpen(false);
75
- }
76
- document.addEventListener("mousedown", onDocClick);
77
- document.addEventListener("keydown", onKey);
78
- return function () {
79
- document.removeEventListener("mousedown", onDocClick);
80
- document.removeEventListener("keydown", onKey);
81
- };
82
- }, [open]);
60
+ var _useState3 = useState(false),
61
+ _useState4 = _slicedToArray(_useState3, 2),
62
+ open = _useState4[0],
63
+ setOpen = _useState4[1];
64
+ var _useState5 = useState("first"),
65
+ _useState6 = _slicedToArray(_useState5, 2),
66
+ initialFocus = _useState6[0],
67
+ setInitialFocus = _useState6[1];
68
+ var menuId = "three-dot-menu-".concat(useId());
83
69
  function toggleOpen(e) {
84
70
  e && e.stopPropagation();
71
+ setInitialFocus("first");
85
72
  setOpen(function (v) {
86
73
  return !v;
87
74
  });
88
75
  }
89
- function handleItemClick(item) {
90
- if (item.disabled) return;
91
- item.onClick && item.onClick(item);
92
- if (closeOnSelect) setOpen(false);
93
- // natural focus behavior: return focus to trigger
94
- triggerRef.current && triggerRef.current.focus();
76
+ function onTriggerKeyDown(e) {
77
+ if (open || e.key !== "ArrowDown" && e.key !== "ArrowUp") return;
78
+ e.preventDefault();
79
+ setInitialFocus(e.key === "ArrowUp" ? "last" : "first");
80
+ setOpen(true);
95
81
  }
96
- var DefaultTrigger = jsx("button", {
97
- type: "button",
98
- "aria-label": ariaLabel,
82
+ var menuItems = (Array.isArray(items) ? items : []).map(function (it, i) {
83
+ var _it$key, _renderIcon;
84
+ return {
85
+ key: (_it$key = it.key) !== null && _it$key !== void 0 ? _it$key : i,
86
+ label: it.label,
87
+ icon: (_renderIcon = renderIcon(it.icon, "w-5 h-5")) !== null && _renderIcon !== void 0 ? _renderIcon : jsx("span", {
88
+ className: "w-5 h-5"
89
+ }),
90
+ disabled: Boolean(it.disabled),
91
+ tone: it.tone,
92
+ destructive: it.destructive,
93
+ onSelect: function onSelect() {
94
+ return it.onClick && it.onClick(it);
95
+ }
96
+ };
97
+ });
98
+ var triggerA11y = {
99
+ "aria-haspopup": "menu",
99
100
  "aria-expanded": open,
100
- ref: triggerRef,
101
+ "aria-controls": open ? menuId : undefined
102
+ };
103
+ var DefaultTrigger = jsx("button", _objectSpread2(_objectSpread2({
104
+ type: "button",
105
+ "aria-label": ariaLabel
106
+ }, triggerA11y), {}, {
107
+ ref: setTriggerNode,
101
108
  onClick: toggleOpen,
102
- className: cn("inline-flex items-center justify-center rounded-md focus:outline-none", className),
103
- children: jsx(MoreVertical, {})
104
- });
109
+ onKeyDown: onTriggerKeyDown,
110
+ className: cn("inline-flex items-center justify-center rounded-md text-muted hover:text-foreground", "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2", TOUCH_TARGET, className),
111
+ children: jsx(MoreVertical, {
112
+ "aria-hidden": "true"
113
+ })
114
+ }));
105
115
  var triggerNode = trigger ?
106
116
  /*#__PURE__*/
107
117
  // eslint-disable-next-line react-hooks/refs -- setTriggerNode is a callback ref, run by React at commit
108
- React.cloneElement(trigger, {
118
+ React.cloneElement(trigger, _objectSpread2({
109
119
  ref: setTriggerNode,
110
120
  onClick: function onClick(e) {
111
121
  trigger.props && trigger.props.onClick && trigger.props.onClick(e);
112
122
  toggleOpen(e);
113
123
  },
114
- "aria-expanded": open,
115
- "aria-haspopup": "menu"
116
- }) : DefaultTrigger;
124
+ onKeyDown: function onKeyDown(e) {
125
+ trigger.props && trigger.props.onKeyDown && trigger.props.onKeyDown(e);
126
+ if (!e.defaultPrevented) onTriggerKeyDown(e);
127
+ }
128
+ }, triggerA11y)) : DefaultTrigger;
117
129
  return jsxs("div", _objectSpread2(_objectSpread2({
118
130
  ref: ref,
119
131
  className: cn("inline-block relative", wrapperClassName)
120
132
  }, rest), {}, {
121
- children: [triggerNode, jsx("div", {
122
- ref: menuRef,
123
- className: cn("absolute left-0 mt-2 min-w-[160px] rounded-lg bg-white border shadow-sm", menuClass),
124
- style: {
125
- display: open ? "block" : "none"
133
+ children: [triggerNode, jsx(ActionMenuSurface, {
134
+ open: open,
135
+ onClose: function onClose() {
136
+ return setOpen(false);
126
137
  },
127
- role: "menu",
128
- "aria-hidden": !open,
129
- children: jsx("ul", {
130
- className: "py-1",
131
- children: items.map(function (it, i) {
132
- var _it$key;
133
- var Icon = it.icon || null;
134
- return jsx("li", {
135
- children: jsxs("button", {
136
- type: "button",
137
- role: "menuitem",
138
- onClick: function onClick() {
139
- return handleItemClick(it);
140
- },
141
- disabled: it.disabled,
142
- className: "w-full text-left px-4 py-3 flex items-center gap-3 text-sm leading-5 ".concat(it.destructive ? "text-error-600" : "text-primary-900", " ").concat(it.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-gray-50", " ").concat(menuItemClass),
143
- children: [Icon ? jsx(Icon, {
144
- className: "w-5 h-5"
145
- }) : jsx("span", {
146
- className: "w-5 h-5"
147
- }), jsx("span", {
148
- className: "flex-1",
149
- children: it.label
150
- })]
151
- })
152
- }, (_it$key = it.key) !== null && _it$key !== void 0 ? _it$key : i);
153
- })
154
- })
138
+ anchorEl: anchorEl,
139
+ items: menuItems,
140
+ presentation: presentation,
141
+ placement: "bottom-start",
142
+ initialFocus: initialFocus,
143
+ closeOnSelect: closeOnSelect,
144
+ id: menuId,
145
+ label: typeof ariaLabel === "string" ? ariaLabel : undefined,
146
+ cancelLabel: cancelLabel,
147
+ menuClassName: menuClass,
148
+ itemClassName: menuItemClass
155
149
  })]
156
150
  }));
157
151
  });