@dreamtree-org/twreact-ui 1.3.0 → 1.3.1

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 (184) hide show
  1. package/README.md +179 -10
  2. package/ai-skills/dreamtree-ui.md +71 -12
  3. package/dist/ai-schema.json +452 -17
  4. package/dist/components/core/Accordion.d.ts.map +1 -1
  5. package/dist/components/core/Button.d.ts.map +1 -1
  6. package/dist/components/core/Checkbox.d.ts.map +1 -1
  7. package/dist/components/core/ColorPicker.d.ts.map +1 -1
  8. package/dist/components/core/DatePicker.d.ts.map +1 -1
  9. package/dist/components/core/DateRangePicker.d.ts.map +1 -1
  10. package/dist/components/core/Form.d.ts.map +1 -1
  11. package/dist/components/core/Input.d.ts.map +1 -1
  12. package/dist/components/core/LocationPicker.d.ts.map +1 -1
  13. package/dist/components/core/Popover.d.ts +4 -0
  14. package/dist/components/core/Popover.d.ts.map +1 -0
  15. package/dist/components/core/PriceRangePicker.d.ts.map +1 -1
  16. package/dist/components/core/ProgressBar.d.ts.map +1 -1
  17. package/dist/components/core/Radio.d.ts.map +1 -1
  18. package/dist/components/core/Rate.d.ts.map +1 -1
  19. package/dist/components/core/Select.d.ts.map +1 -1
  20. package/dist/components/core/Skeleton.d.ts.map +1 -1
  21. package/dist/components/core/Slider.d.ts +4 -0
  22. package/dist/components/core/Slider.d.ts.map +1 -0
  23. package/dist/components/core/SpeechToText.d.ts.map +1 -1
  24. package/dist/components/core/Switch.d.ts.map +1 -1
  25. package/dist/components/core/Table/ActionMenu.d.ts.map +1 -1
  26. package/dist/components/core/Table/ColumnMenu.d.ts +2 -1
  27. package/dist/components/core/Table/ColumnMenu.d.ts.map +1 -1
  28. package/dist/components/core/Table/MobileCard.d.ts +2 -2
  29. package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
  30. package/dist/components/core/Table/Table.d.ts.map +1 -1
  31. package/dist/components/core/Table/TableRow.d.ts +4 -2
  32. package/dist/components/core/Table/TableRow.d.ts.map +1 -1
  33. package/dist/components/core/Tabs.d.ts.map +1 -1
  34. package/dist/components/core/Textarea.d.ts +4 -0
  35. package/dist/components/core/Textarea.d.ts.map +1 -0
  36. package/dist/components/core/ThreeDotPopover.d.ts.map +1 -1
  37. package/dist/components/core/Tooltip.d.ts.map +1 -1
  38. package/dist/components/feedback/Dialog.d.ts.map +1 -1
  39. package/dist/components/feedback/Drawer.d.ts +4 -0
  40. package/dist/components/feedback/Drawer.d.ts.map +1 -0
  41. package/dist/components/feedback/Toast.d.ts +14 -5
  42. package/dist/components/feedback/Toast.d.ts.map +1 -1
  43. package/dist/components/feedback/Tour.d.ts +4 -0
  44. package/dist/components/feedback/Tour.d.ts.map +1 -0
  45. package/dist/components/feedback/TourSpotlight.d.ts +9 -0
  46. package/dist/components/feedback/TourSpotlight.d.ts.map +1 -0
  47. package/dist/components/navigation/Breadcrumbs.d.ts.map +1 -1
  48. package/dist/components/navigation/FootNav.d.ts.map +1 -1
  49. package/dist/components/navigation/Navbar.d.ts.map +1 -1
  50. package/dist/components/navigation/Sidebar.d.ts +8 -2
  51. package/dist/components/navigation/Sidebar.d.ts.map +1 -1
  52. package/dist/components/utility/Badge.d.ts.map +1 -1
  53. package/dist/components/utility/FileUpload.d.ts.map +1 -1
  54. package/dist/components/utility/Sortable.d.ts +4 -0
  55. package/dist/components/utility/Sortable.d.ts.map +1 -0
  56. package/dist/esm/_vendor/object-assign/index.js +99 -0
  57. package/dist/esm/_vendor/prop-types/_vendor/react-is/cjs/react-is.development.js +190 -0
  58. package/dist/esm/_vendor/prop-types/_vendor/react-is/cjs/react-is.production.min.js +26 -0
  59. package/dist/esm/_vendor/prop-types/_vendor/react-is/index.js +19 -0
  60. package/dist/esm/_vendor/prop-types/checkPropTypes.js +115 -0
  61. package/dist/esm/_vendor/prop-types/factoryWithThrowingShims.js +74 -0
  62. package/dist/esm/_vendor/prop-types/factoryWithTypeCheckers.js +625 -0
  63. package/dist/esm/_vendor/prop-types/index.js +30 -0
  64. package/dist/esm/_vendor/prop-types/lib/ReactPropTypesSecret.js +21 -0
  65. package/dist/esm/_vendor/prop-types/lib/has.js +11 -0
  66. package/dist/esm/_virtual/_commonjsHelpers.js +5 -0
  67. package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +329 -0
  68. package/dist/esm/_virtual/index.js +3 -0
  69. package/dist/esm/_virtual/index2.js +3 -0
  70. package/dist/esm/_virtual/react-is.development.js +3 -0
  71. package/dist/esm/_virtual/react-is.production.min.js +3 -0
  72. package/dist/esm/components/blocks/AppShell.js +205 -0
  73. package/dist/esm/components/blocks/ConfirmDialog.js +57 -0
  74. package/dist/esm/components/blocks/EmptyState.js +44 -0
  75. package/dist/esm/components/blocks/ErrorState.js +53 -0
  76. package/dist/esm/components/blocks/LoadingState.js +134 -0
  77. package/dist/esm/components/blocks/PageHeader.js +51 -0
  78. package/dist/esm/components/blocks/StatCard.js +79 -0
  79. package/dist/esm/components/blocks/StatusPill.js +55 -0
  80. package/dist/esm/components/core/Accordion.js +260 -0
  81. package/dist/esm/components/core/Button.js +59 -0
  82. package/dist/esm/components/core/Checkbox.js +188 -0
  83. package/dist/esm/components/core/ColorPicker.js +348 -0
  84. package/dist/esm/components/core/DatePicker.js +436 -0
  85. package/dist/esm/components/core/DateRangePicker.js +494 -0
  86. package/dist/esm/components/core/Form.js +522 -0
  87. package/dist/esm/components/core/Input.js +179 -0
  88. package/dist/esm/components/core/Loader.js +141 -0
  89. package/dist/esm/components/core/LocationPicker.js +161 -0
  90. package/dist/esm/components/core/Popover.js +171 -0
  91. package/dist/esm/components/core/PriceRangePicker.js +376 -0
  92. package/dist/esm/components/core/ProgressBar.js +152 -0
  93. package/dist/esm/components/core/Radio.js +156 -0
  94. package/dist/esm/components/core/Rate.js +197 -0
  95. package/dist/esm/components/core/RoundedTag.js +118 -0
  96. package/dist/esm/components/core/Select.js +857 -0
  97. package/dist/esm/components/core/Skeleton.js +100 -0
  98. package/dist/esm/components/core/Slider.js +134 -0
  99. package/dist/esm/components/core/SpeechToText.js +226 -0
  100. package/dist/esm/components/core/Switch.js +207 -0
  101. package/dist/esm/components/core/Table/ActionMenu.js +251 -0
  102. package/dist/esm/components/core/Table/ColumnMenu.js +55 -0
  103. package/dist/esm/components/core/Table/FieldInput.js +157 -0
  104. package/dist/esm/components/core/Table/MobileCard.js +187 -0
  105. package/dist/esm/components/core/Table/MobileFilters.js +72 -0
  106. package/dist/esm/components/core/Table/Pagination.js +157 -0
  107. package/dist/esm/components/core/Table/Table.js +1533 -0
  108. package/dist/esm/components/core/Table/TableRow.js +254 -0
  109. package/dist/esm/components/core/Table/constants.js +35 -0
  110. package/dist/esm/components/core/Table/helpers.js +124 -0
  111. package/dist/esm/components/core/Table/useClickOutside.js +26 -0
  112. package/dist/esm/components/core/Tabs.js +289 -0
  113. package/dist/esm/components/core/TextToSpeech.js +52 -0
  114. package/dist/esm/components/core/Textarea.js +125 -0
  115. package/dist/esm/components/core/ThreeDotPopover.js +160 -0
  116. package/dist/esm/components/core/Tooltip.js +372 -0
  117. package/dist/esm/components/feedback/Alert.js +96 -0
  118. package/dist/esm/components/feedback/Dialog.js +200 -0
  119. package/dist/esm/components/feedback/Drawer.js +171 -0
  120. package/dist/esm/components/feedback/Toast.js +362 -0
  121. package/dist/esm/components/feedback/Tour.js +214 -0
  122. package/dist/esm/components/feedback/TourSpotlight.js +71 -0
  123. package/dist/esm/components/navigation/Breadcrumbs.js +75 -0
  124. package/dist/esm/components/navigation/Dropdown.js +53 -0
  125. package/dist/esm/components/navigation/FootNav.js +51 -0
  126. package/dist/esm/components/navigation/Navbar.js +437 -0
  127. package/dist/esm/components/navigation/Sidebar.js +567 -0
  128. package/dist/esm/components/utility/Avatar.js +89 -0
  129. package/dist/esm/components/utility/Badge.js +47 -0
  130. package/dist/esm/components/utility/Card.js +85 -0
  131. package/dist/esm/components/utility/Carousel.js +97 -0
  132. package/dist/esm/components/utility/Condition.js +9 -0
  133. package/dist/esm/components/utility/FileUpload.js +177 -0
  134. package/dist/esm/components/utility/Pagination.js +111 -0
  135. package/dist/esm/components/utility/Sortable.js +190 -0
  136. package/dist/esm/components/utility/Stepper.js +101 -0
  137. package/dist/esm/hooks/useApi.js +169 -0
  138. package/dist/esm/hooks/useControllableState.js +32 -0
  139. package/dist/esm/hooks/useFocusTrap.js +85 -0
  140. package/dist/esm/hooks/useLatestRef.js +20 -0
  141. package/dist/esm/hooks/useMixins.js +100 -0
  142. package/dist/esm/hooks/useScrollLock.js +26 -0
  143. package/dist/esm/hooks/useSliderValues.js +135 -0
  144. package/dist/esm/hooks/useSortable.js +188 -0
  145. package/dist/esm/hooks/useTheme.js +53 -0
  146. package/dist/esm/hooks/useTourTarget.js +92 -0
  147. package/dist/esm/index.js +65 -0
  148. package/dist/esm/store/index.js +26 -0
  149. package/dist/esm/store/store.js +107 -0
  150. package/dist/esm/store/storeSlice.js +45 -0
  151. package/dist/esm/utils/cn.js +11 -0
  152. package/dist/esm/utils/emitter.js +169 -0
  153. package/dist/esm/utils/helpers.js +161 -0
  154. package/dist/esm/utils/position.js +134 -0
  155. package/dist/hooks/useApi.d.ts +2 -1
  156. package/dist/hooks/useApi.d.ts.map +1 -1
  157. package/dist/hooks/useControllableState.d.ts +11 -0
  158. package/dist/hooks/useControllableState.d.ts.map +1 -0
  159. package/dist/hooks/useFocusTrap.d.ts +15 -0
  160. package/dist/hooks/useFocusTrap.d.ts.map +1 -0
  161. package/dist/hooks/useLatestRef.d.ts +8 -0
  162. package/dist/hooks/useLatestRef.d.ts.map +1 -0
  163. package/dist/hooks/useMixins.d.ts.map +1 -1
  164. package/dist/hooks/useScrollLock.d.ts +2 -0
  165. package/dist/hooks/useScrollLock.d.ts.map +1 -0
  166. package/dist/hooks/useSliderValues.d.ts +43 -0
  167. package/dist/hooks/useSliderValues.d.ts.map +1 -0
  168. package/dist/hooks/useSortable.d.ts +32 -0
  169. package/dist/hooks/useSortable.d.ts.map +1 -0
  170. package/dist/hooks/useTheme.d.ts.map +1 -1
  171. package/dist/hooks/useTourTarget.d.ts +15 -0
  172. package/dist/hooks/useTourTarget.d.ts.map +1 -0
  173. package/dist/index.css +1 -1
  174. package/dist/index.d.ts +8 -2
  175. package/dist/index.esm.css +1 -1
  176. package/dist/index.esm.js +4800 -2212
  177. package/dist/index.js +4805 -2210
  178. package/dist/types/index.d.ts +193 -5
  179. package/dist/types/index.d.ts.map +1 -1
  180. package/dist/utils/position.d.ts +30 -0
  181. package/dist/utils/position.d.ts.map +1 -0
  182. package/doc/README.md +7 -1
  183. package/mcp/catalog.snapshot.json +911 -212
  184. package/package.json +14 -2
@@ -0,0 +1,251 @@
1
+ 'use client';
2
+ import { slicedToArray as _slicedToArray, toConsumableArray as _toConsumableArray } from '../../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { useRef, useState, useLayoutEffect, useEffect } from 'react';
5
+ import { createPortal } from 'react-dom';
6
+ import { cn } from '../../../utils/cn.js';
7
+ import { useLatestRef } from '../../../hooks/useLatestRef.js';
8
+
9
+ var DEFAULT_MENU_BG = "bg-white border border-gray-100 shadow-xl";
10
+ var DEFAULT_MENU_ITEM_HOVER = "opacity-75 hover:opacity-100 hover:bg-gray-100/80 active:bg-gray-200/80";
11
+ function ActionMenu(_ref) {
12
+ var _theme$menuBg, _theme$menuItemHover;
13
+ var _ref$actions = _ref.actions,
14
+ actions = _ref$actions === void 0 ? [] : _ref$actions,
15
+ row = _ref.row,
16
+ onAction = _ref.onAction,
17
+ onClose = _ref.onClose,
18
+ externalMenuRef = _ref.menuRef,
19
+ anchorEl = _ref.anchorEl,
20
+ theme = _ref.theme;
21
+ var internalRef = useRef(null);
22
+ var menuRef = externalMenuRef || internalRef;
23
+ var _useState = useState(-1),
24
+ _useState2 = _slicedToArray(_useState, 2),
25
+ focusedIndex = _useState2[0],
26
+ setFocusedIndex = _useState2[1];
27
+ var menuBg = (_theme$menuBg = theme === null || theme === void 0 ? void 0 : theme.menuBg) !== null && _theme$menuBg !== void 0 ? _theme$menuBg : DEFAULT_MENU_BG;
28
+ var menuItemHover = (_theme$menuItemHover = theme === null || theme === void 0 ? void 0 : theme.menuItemHover) !== null && _theme$menuItemHover !== void 0 ? _theme$menuItemHover : DEFAULT_MENU_ITEM_HOVER;
29
+ var _useState3 = useState({
30
+ left: 0,
31
+ top: 0,
32
+ transformOrigin: "top right",
33
+ maxHeight: 300,
34
+ width: 190,
35
+ opacity: 0
36
+ }),
37
+ _useState4 = _slicedToArray(_useState3, 2),
38
+ style = _useState4[0],
39
+ setStyle = _useState4[1];
40
+ var menuWidth = 190;
41
+ var maxMenuHeight = 320;
42
+ var minMenuHeight = 80;
43
+ var margin = 8;
44
+ var computePosition = function computePosition() {
45
+ if (!anchorEl || typeof window === "undefined") return;
46
+ var rect = anchorEl.getBoundingClientRect();
47
+ var scrollY = window.scrollY || window.pageYOffset || 0;
48
+ var scrollX = window.scrollX || window.pageXOffset || 0;
49
+ var spaceBelow = window.innerHeight - rect.bottom;
50
+ var spaceAbove = rect.top;
51
+ // Estimate or measure menu height
52
+ var menuEl = menuRef === null || menuRef === void 0 ? void 0 : menuRef.current;
53
+ var actionCount = Array.isArray(actions) && actions.length > 0 ? actions.length : 1;
54
+ var estimatedHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, actionCount * 42 + 16));
55
+ var actualContentHeight = estimatedHeight;
56
+ if (menuEl) {
57
+ actualContentHeight = Math.min(maxMenuHeight, menuEl.scrollHeight || menuEl.offsetHeight || estimatedHeight);
58
+ }
59
+ // Determine placement (top vs bottom) based on available viewport space
60
+ var placement = "bottom";
61
+ if (spaceBelow < actualContentHeight + margin && spaceAbove > spaceBelow) {
62
+ placement = "top";
63
+ }
64
+ var availableSpace = placement === "top" ? spaceAbove - margin : spaceBelow - margin;
65
+ var allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, availableSpace));
66
+ var finalMenuHeight = Math.min(actualContentHeight, allowedMaxHeight);
67
+ // Compute top coordinate based on placement
68
+ var top;
69
+ if (placement === "top") {
70
+ top = rect.top + scrollY - finalMenuHeight - margin;
71
+ } else {
72
+ top = rect.bottom + scrollY + margin;
73
+ }
74
+ // Clamp top within viewport scroll bounds
75
+ var minTop = margin + scrollY;
76
+ var maxTop = window.innerHeight + scrollY - finalMenuHeight - margin;
77
+ if (top < minTop) top = minTop;
78
+ if (top > maxTop) top = maxTop;
79
+ // Compute left coordinate (align right edge to anchor right, fallback to left align if overflow)
80
+ var left = rect.right + scrollX - menuWidth;
81
+ if (left < margin) {
82
+ left = rect.left + scrollX;
83
+ }
84
+ if (left + menuWidth > window.innerWidth - margin) {
85
+ left = Math.max(margin, window.innerWidth - menuWidth - margin);
86
+ }
87
+ var transformOrigin = placement === "bottom" ? "top right" : "bottom right";
88
+ setStyle({
89
+ left: left,
90
+ top: top,
91
+ transformOrigin: transformOrigin,
92
+ maxHeight: allowedMaxHeight,
93
+ width: menuWidth,
94
+ opacity: 1
95
+ });
96
+ };
97
+ // computePosition is rebuilt every render; read it through a ref so the
98
+ // listeners below are only re-bound when the anchor/actions change.
99
+ var computePositionRef = useLatestRef(computePosition);
100
+ useLayoutEffect(function () {
101
+ // Measuring the anchor and positioning the menu before paint is the
102
+ // intended use of a layout effect.
103
+ computePositionRef.current();
104
+ var rafId = window.requestAnimationFrame(function () {
105
+ return computePositionRef.current();
106
+ });
107
+ var handleResize = function handleResize() {
108
+ window.requestAnimationFrame(function () {
109
+ return computePositionRef.current();
110
+ });
111
+ };
112
+ var handleScroll = function handleScroll(e) {
113
+ // If scroll event originates inside the menu container itself,
114
+ // do NOT close the menu! Let the user scroll through options.
115
+ if (menuRef !== null && menuRef !== void 0 && menuRef.current && e.target && e.target instanceof Node && (menuRef.current === e.target || menuRef.current.contains(e.target))) {
116
+ return;
117
+ }
118
+ onClose === null || onClose === void 0 || onClose();
119
+ };
120
+ window.addEventListener("resize", handleResize);
121
+ window.addEventListener("scroll", handleScroll, true);
122
+ return function () {
123
+ window.cancelAnimationFrame(rafId);
124
+ window.removeEventListener("resize", handleResize);
125
+ window.removeEventListener("scroll", handleScroll, true);
126
+ };
127
+ }, [anchorEl, actions, menuRef, onClose, computePositionRef]);
128
+ // Focus management & Keyboard navigation
129
+ useEffect(function () {
130
+ var handleKeyDown = function handleKeyDown(e) {
131
+ if (!Array.isArray(actions) || actions.length === 0) return;
132
+ if (e.key === "Escape") {
133
+ var _anchorEl$focus;
134
+ e.preventDefault();
135
+ onClose === null || onClose === void 0 || onClose();
136
+ anchorEl === null || anchorEl === void 0 || (_anchorEl$focus = anchorEl.focus) === null || _anchorEl$focus === void 0 || _anchorEl$focus.call(anchorEl);
137
+ return;
138
+ }
139
+ if (e.key === "ArrowDown") {
140
+ e.preventDefault();
141
+ setFocusedIndex(function (prev) {
142
+ var next = prev + 1;
143
+ while (next < actions.length && (_actions$next = actions[next]) !== null && _actions$next !== void 0 && _actions$next.disabled) {
144
+ var _actions$next;
145
+ next++;
146
+ }
147
+ return next < actions.length ? next : prev;
148
+ });
149
+ return;
150
+ }
151
+ if (e.key === "ArrowUp") {
152
+ e.preventDefault();
153
+ setFocusedIndex(function (prev) {
154
+ var next = prev - 1;
155
+ while (next >= 0 && (_actions$next2 = actions[next]) !== null && _actions$next2 !== void 0 && _actions$next2.disabled) {
156
+ var _actions$next2;
157
+ next--;
158
+ }
159
+ return next >= 0 ? next : prev;
160
+ });
161
+ return;
162
+ }
163
+ if (e.key === "Home") {
164
+ e.preventDefault();
165
+ var first = actions.findIndex(function (a) {
166
+ return !a.disabled;
167
+ });
168
+ if (first !== -1) setFocusedIndex(first);
169
+ return;
170
+ }
171
+ if (e.key === "End") {
172
+ e.preventDefault();
173
+ var last = _toConsumableArray(actions).reverse().findIndex(function (a) {
174
+ return !a.disabled;
175
+ });
176
+ if (last !== -1) setFocusedIndex(actions.length - 1 - last);
177
+ return;
178
+ }
179
+ };
180
+ window.addEventListener("keydown", handleKeyDown);
181
+ return function () {
182
+ return window.removeEventListener("keydown", handleKeyDown);
183
+ };
184
+ }, [actions, onClose, anchorEl]);
185
+ // Automatically focus focused item
186
+ useEffect(function () {
187
+ if (focusedIndex >= 0 && menuRef !== null && menuRef !== void 0 && menuRef.current) {
188
+ var buttons = menuRef.current.querySelectorAll("button:not([disabled])");
189
+ if (buttons[focusedIndex]) {
190
+ buttons[focusedIndex].focus();
191
+ }
192
+ }
193
+ }, [focusedIndex, menuRef]);
194
+ return /*#__PURE__*/createPortal(jsx("div", {
195
+ ref: menuRef,
196
+ role: "menu",
197
+ "aria-orientation": "vertical",
198
+ style: {
199
+ position: "absolute",
200
+ top: style.top,
201
+ left: style.left,
202
+ width: style.width,
203
+ maxHeight: style.maxHeight,
204
+ transformOrigin: style.transformOrigin,
205
+ opacity: style.opacity
206
+ },
207
+ className: cn("absolute z-50 rounded-xl shadow-xl ring-1 ring-black/10 overflow-y-auto transition-opacity duration-150 ease-out focus:outline-none", menuBg),
208
+ onClick: function onClick(e) {
209
+ return e.stopPropagation();
210
+ },
211
+ children: jsx("div", {
212
+ className: "p-1.5 space-y-0.5",
213
+ children: !Array.isArray(actions) || actions.length === 0 ? jsx("div", {
214
+ className: "px-3 py-2 text-sm text-gray-400 italic",
215
+ children: "No actions"
216
+ }) : actions.map(function (action, idx) {
217
+ var _action$name;
218
+ var isDisabled = !!action.disabled;
219
+ var isFocused = focusedIndex === idx;
220
+ return jsx("div", {
221
+ children: jsx("button", {
222
+ type: "button",
223
+ disabled: isDisabled,
224
+ "aria-disabled": isDisabled || undefined,
225
+ className: cn("w-full text-left px-3 py-2 text-sm flex items-center gap-2.5 rounded-lg transition-colors font-medium", isDisabled ? "opacity-50 cursor-not-allowed text-gray-400" : ["text-gray-700 hover:text-gray-900", menuItemHover, isFocused ? "bg-gray-100 text-gray-900 ring-1 ring-gray-300" : ""]),
226
+ onMouseEnter: function onMouseEnter() {
227
+ return !isDisabled && setFocusedIndex(idx);
228
+ },
229
+ onClick: function onClick(e) {
230
+ e.stopPropagation();
231
+ if (isDisabled) return;
232
+ onAction === null || onAction === void 0 || onAction(action, row);
233
+ onClose === null || onClose === void 0 || onClose();
234
+ },
235
+ children: action.render ? action.render(row) : jsxs(Fragment, {
236
+ children: [action.icon && jsx("span", {
237
+ className: "inline-flex text-gray-500 flex-shrink-0",
238
+ children: action.icon
239
+ }), jsx("span", {
240
+ className: "truncate",
241
+ children: action.label
242
+ })]
243
+ })
244
+ })
245
+ }, (_action$name = action.name) !== null && _action$name !== void 0 ? _action$name : "action-".concat(idx));
246
+ })
247
+ })
248
+ }), document.body);
249
+ }
250
+
251
+ export { ActionMenu as default };
@@ -0,0 +1,55 @@
1
+ 'use client';
2
+ import { defineProperty as _defineProperty } from '../../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import 'react';
5
+ import { cn } from '../../../utils/cn.js';
6
+
7
+ var DEFAULT_ROW_HOVER = "bg-gray-50";
8
+ /**
9
+ * Column visibility toggle menu
10
+ */
11
+ function ColumnMenu(_ref) {
12
+ var _theme$rowHover;
13
+ var id = _ref.id,
14
+ columns = _ref.columns,
15
+ onToggle = _ref.onToggle,
16
+ menuRef = _ref.menuRef,
17
+ theme = _ref.theme;
18
+ var rowHover = (_theme$rowHover = theme === null || theme === void 0 ? void 0 : theme.rowHover) !== null && _theme$rowHover !== void 0 ? _theme$rowHover : DEFAULT_ROW_HOVER;
19
+ return jsxs("div", {
20
+ id: id,
21
+ role: "group",
22
+ "aria-label": "Show / hide columns",
23
+ ref: menuRef,
24
+ className: "absolute right-4 mt-2 w-56 z-50 rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 p-3 lg:block sm:block hidden",
25
+ onClick: function onClick(e) {
26
+ return e.stopPropagation();
27
+ },
28
+ children: [jsx("p", {
29
+ className: "text-sm font-medium text-center mb-2",
30
+ children: "Show / hide columns"
31
+ }), jsx("div", {
32
+ className: "max-h-56 overflow-auto",
33
+ children: columns.map(function (col) {
34
+ return jsxs("label", {
35
+ className: cn(_defineProperty({
36
+ "flex cursor-pointer items-center gap-2 px-2 py-1.5 rounded": true
37
+ }, "hover:" + rowHover, true)),
38
+ children: [jsx("input", {
39
+ type: "checkbox",
40
+ checked: col.isVisible !== false,
41
+ onChange: function onChange() {
42
+ return onToggle(col.key);
43
+ },
44
+ className: "rounded"
45
+ }), jsx("span", {
46
+ className: "text-sm font-normal",
47
+ children: col.label
48
+ })]
49
+ }, col.key);
50
+ })
51
+ })]
52
+ });
53
+ }
54
+
55
+ export { ColumnMenu as default };
@@ -0,0 +1,157 @@
1
+ 'use client';
2
+ import { typeof as _typeof } from '../../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import 'react';
5
+ import { cn } from '../../../utils/cn.js';
6
+
7
+ /**
8
+ * Unified FieldInput component for cell editing and new rows.
9
+ * Reuses existing onRender pattern and supports text, number, select, date, boolean, textarea.
10
+ */
11
+ function FieldInput(_ref) {
12
+ var column = _ref.column,
13
+ value = _ref.value,
14
+ _onChange = _ref.onChange,
15
+ onKeyDown = _ref.onKeyDown,
16
+ _ref$isEditing = _ref.isEditing,
17
+ isEditing = _ref$isEditing === void 0 ? true : _ref$isEditing,
18
+ _ref$row = _ref.row,
19
+ row = _ref$row === void 0 ? {} : _ref$row,
20
+ _ref$rowIndex = _ref.rowIndex,
21
+ rowIndex = _ref$rowIndex === void 0 ? 0 : _ref$rowIndex,
22
+ _ref$className = _ref.className,
23
+ className = _ref$className === void 0 ? "" : _ref$className,
24
+ _ref$autoFocus = _ref.autoFocus,
25
+ autoFocus = _ref$autoFocus === void 0 ? false : _ref$autoFocus;
26
+ var currentValue = value !== null && value !== void 0 ? value : "";
27
+ var inputType = column.type || column.inputType || "text";
28
+ var stopProp = function stopProp(e) {
29
+ e.stopPropagation();
30
+ };
31
+ // Check if custom onRender renderer is provided on the column definition
32
+ if (typeof column.onRender === "function") {
33
+ return jsx("div", {
34
+ onClick: stopProp,
35
+ onMouseDown: stopProp,
36
+ children: column.onRender(row, rowIndex, column, {
37
+ value: currentValue,
38
+ onChange: function onChange(newVal) {
39
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(newVal);
40
+ },
41
+ onKeyDown: onKeyDown,
42
+ isEditing: isEditing
43
+ })
44
+ });
45
+ }
46
+ // Textarea / Longtext
47
+ if (inputType === "textarea" || inputType === "longtext") {
48
+ return jsx("textarea", {
49
+ autoFocus: autoFocus,
50
+ rows: 2,
51
+ value: currentValue,
52
+ onChange: function onChange(e) {
53
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.value);
54
+ },
55
+ onKeyDown: onKeyDown,
56
+ onClick: stopProp,
57
+ onMouseDown: stopProp,
58
+ placeholder: "Enter ".concat(column.label || column.key, "..."),
59
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none transition-all focus:ring-2 focus:ring-primary-500 bg-white resize-y min-h-[2.5rem]", className)
60
+ });
61
+ }
62
+ // Select / Dropdown
63
+ if (inputType === "select" || inputType === "dropdown") {
64
+ var options = Array.isArray(column.options) ? column.options.map(function (opt) {
65
+ return _typeof(opt) === "object" ? opt : {
66
+ label: opt,
67
+ value: opt
68
+ };
69
+ }) : [];
70
+ return jsxs("select", {
71
+ autoFocus: autoFocus,
72
+ value: currentValue,
73
+ onChange: function onChange(e) {
74
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.value);
75
+ },
76
+ onKeyDown: onKeyDown,
77
+ onClick: stopProp,
78
+ onMouseDown: stopProp,
79
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className),
80
+ children: [jsxs("option", {
81
+ value: "",
82
+ children: ["Select ", column.label || column.key]
83
+ }), options.map(function (opt) {
84
+ return jsx("option", {
85
+ value: opt.value,
86
+ children: opt.label
87
+ }, String(opt.value));
88
+ })]
89
+ });
90
+ }
91
+ // Checkbox / Boolean
92
+ if (inputType === "checkbox" || inputType === "boolean") {
93
+ var checked = Boolean(currentValue);
94
+ return jsx("div", {
95
+ className: cn("flex items-center justify-center py-1", className),
96
+ onClick: stopProp,
97
+ onMouseDown: stopProp,
98
+ children: jsx("input", {
99
+ type: "checkbox",
100
+ autoFocus: autoFocus,
101
+ checked: checked,
102
+ onChange: function onChange(e) {
103
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.checked);
104
+ },
105
+ onKeyDown: onKeyDown,
106
+ className: "w-4 h-4 text-primary-600 border-gray-300 rounded focus:ring-primary-500 cursor-pointer"
107
+ })
108
+ });
109
+ }
110
+ // Date
111
+ if (inputType === "date") {
112
+ return jsx("input", {
113
+ type: "date",
114
+ autoFocus: autoFocus,
115
+ value: currentValue,
116
+ onChange: function onChange(e) {
117
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.value);
118
+ },
119
+ onKeyDown: onKeyDown,
120
+ onClick: stopProp,
121
+ onMouseDown: stopProp,
122
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className)
123
+ });
124
+ }
125
+ // Number
126
+ if (inputType === "number") {
127
+ return jsx("input", {
128
+ type: "number",
129
+ autoFocus: autoFocus,
130
+ value: currentValue,
131
+ onChange: function onChange(e) {
132
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.value === "" ? "" : Number(e.target.value));
133
+ },
134
+ onKeyDown: onKeyDown,
135
+ onClick: stopProp,
136
+ onMouseDown: stopProp,
137
+ placeholder: "Enter ".concat(column.label || column.key, "..."),
138
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className)
139
+ });
140
+ }
141
+ // Default: Text
142
+ return jsx("input", {
143
+ type: "text",
144
+ autoFocus: autoFocus,
145
+ value: currentValue,
146
+ onChange: function onChange(e) {
147
+ return _onChange === null || _onChange === void 0 ? void 0 : _onChange(e.target.value);
148
+ },
149
+ onKeyDown: onKeyDown,
150
+ onClick: stopProp,
151
+ onMouseDown: stopProp,
152
+ placeholder: "Enter ".concat(column.label || column.key, "..."),
153
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className)
154
+ });
155
+ }
156
+
157
+ export { FieldInput as default };
@@ -0,0 +1,187 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import React from 'react';
4
+ import { cn } from '../../../utils/cn.js';
5
+ import { MoreVertical } from 'lucide-react';
6
+ import ActionMenu from './ActionMenu.js';
7
+ import { getRowKey, resolveActions, rowHasDetails, getActionLabelText } from './helpers.js';
8
+
9
+ /**
10
+ * Mobile card view for a single table row
11
+ */
12
+ function MobileCard(_ref) {
13
+ var row = _ref.row,
14
+ rowIndexInPage = _ref.rowIndexInPage,
15
+ startIndex = _ref.startIndex,
16
+ selectedRows = _ref.selectedRows,
17
+ expandedRows = _ref.expandedRows,
18
+ rowClass = _ref.rowClass,
19
+ stripedRows = _ref.stripedRows,
20
+ stripedColors = _ref.stripedColors,
21
+ theme = _ref.theme,
22
+ onRowClick = _ref.onRowClick,
23
+ hasDetails = _ref.hasDetails,
24
+ selectable = _ref.selectable,
25
+ showSerial = _ref.showSerial,
26
+ withAction = _ref.withAction,
27
+ visibleColumns = _ref.visibleColumns,
28
+ cellClass = _ref.cellClass,
29
+ DetailsComponent = _ref.DetailsComponent,
30
+ actionsToUse = _ref.actionsToUse,
31
+ activeActionRowKey = _ref.activeActionRowKey,
32
+ activeAnchorEl = _ref.activeAnchorEl,
33
+ registerActionButton = _ref.registerActionButton,
34
+ actionMenuRef = _ref.actionMenuRef,
35
+ toggleExpandRow = _ref.toggleExpandRow,
36
+ handleSelectRow = _ref.handleSelectRow,
37
+ toggleActions = _ref.toggleActions,
38
+ handleOnAction = _ref.handleOnAction,
39
+ closeActionMenu = _ref.closeActionMenu,
40
+ renderCell = _ref.renderCell;
41
+ var globalIndex = startIndex + rowIndexInPage;
42
+ var key = getRowKey(row, globalIndex);
43
+ var actionCellKey = "actions-".concat(key);
44
+ var isSelected = selectedRows.has(key);
45
+ var isExpanded = expandedRows.has(key);
46
+ var _React$useMemo = React.useMemo(function () {
47
+ return resolveActions(actionsToUse, row, globalIndex);
48
+ }, [actionsToUse, row, globalIndex]),
49
+ inlineActions = _React$useMemo.inlineActions,
50
+ menuActions = _React$useMemo.menuActions;
51
+ // Unlike the desktop row there is no column grid to keep aligned, so a
52
+ // non-qualifying row simply renders no toggle and no placeholder.
53
+ var showDetailsToggle = rowHasDetails(hasDetails, row, globalIndex);
54
+ var extraRowClass = typeof rowClass === "function" ? rowClass({
55
+ row: row,
56
+ rowIndex: globalIndex
57
+ }) : "";
58
+ var safeExtraRowClass = typeof extraRowClass === "string" ? extraRowClass.trim() : "";
59
+ // The header strip only renders when it has something to hold; otherwise a
60
+ // card would open with an empty grey band above its first field.
61
+ var hasActions = withAction && (inlineActions.length > 0 || menuActions.length > 0);
62
+ var showHeader = showDetailsToggle || selectable || showSerial || hasActions;
63
+ var stripeBg = stripedRows && !isSelected && Array.isArray(stripedColors) && stripedColors.length > 0 ? stripedColors[globalIndex % stripedColors.length] : undefined;
64
+ return jsxs("div", {
65
+ style: stripeBg ? {
66
+ backgroundColor: stripeBg
67
+ } : undefined,
68
+ className: cn("border rounded-lg mb-3 shadow-sm overflow-hidden transition-all duration-200", {
69
+ "cursor-pointer": !!onRowClick,
70
+ "bg-primary-50 border-primary-200": isSelected,
71
+ "hover:shadow-md": !isSelected
72
+ }, safeExtraRowClass),
73
+ onClick: function onClick() {
74
+ return onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row, globalIndex);
75
+ },
76
+ children: [showHeader && jsxs("div", {
77
+ className: "flex items-center justify-between p-4 border-b bg-gray-50",
78
+ children: [jsxs("div", {
79
+ className: "flex items-center gap-3",
80
+ children: [showDetailsToggle && jsx("button", {
81
+ type: "button",
82
+ onClick: function onClick(e) {
83
+ e.stopPropagation();
84
+ toggleExpandRow(row, rowIndexInPage);
85
+ },
86
+ "aria-expanded": isExpanded,
87
+ "aria-label": isExpanded ? "Collapse row details" : "Expand row details",
88
+ className: "p-1 rounded hover:bg-gray-200",
89
+ children: isExpanded ? "▾" : "▸"
90
+ }), selectable && jsx("input", {
91
+ type: "checkbox",
92
+ className: "rounded border-gray-300 h-4 w-4",
93
+ checked: isSelected,
94
+ onChange: function onChange(e) {
95
+ e.stopPropagation();
96
+ handleSelectRow(row, rowIndexInPage);
97
+ },
98
+ onClick: function onClick(e) {
99
+ return e.stopPropagation();
100
+ }
101
+ }), showSerial && jsxs("span", {
102
+ className: "text-sm font-medium",
103
+ children: ["#", globalIndex + 1]
104
+ })]
105
+ }), hasActions && jsxs("div", {
106
+ className: "flex items-center gap-1",
107
+ children: [inlineActions.map(function (action, idx) {
108
+ var _action$icon, _action$name;
109
+ var actionLabel = getActionLabelText(action);
110
+ return jsx("button", {
111
+ type: "button",
112
+ title: actionLabel,
113
+ "aria-label": actionLabel,
114
+ disabled: action.disabled,
115
+ onClick: function onClick(e) {
116
+ // The card root binds onRowClick and there is no stopping
117
+ // ancestor here, unlike the desktop actions <td>.
118
+ e.stopPropagation();
119
+ if (action.disabled) return;
120
+ handleOnAction(action, row);
121
+ },
122
+ className: cn("p-1.5 rounded", action.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-gray-200"),
123
+ children: action.render ? action.render(row) : (_action$icon = action.icon) !== null && _action$icon !== void 0 ? _action$icon : jsx("span", {
124
+ className: "text-xs",
125
+ children: actionLabel
126
+ })
127
+ }, (_action$name = action.name) !== null && _action$name !== void 0 ? _action$name : "inline-".concat(idx));
128
+ }), menuActions.length > 0 && jsxs("div", {
129
+ className: "relative",
130
+ children: [jsx("button", {
131
+ ref: function ref(el) {
132
+ return registerActionButton === null || registerActionButton === void 0 ? void 0 : registerActionButton(actionCellKey, el);
133
+ },
134
+ onClick: function onClick(e) {
135
+ return toggleActions(e, actionCellKey, row);
136
+ },
137
+ "aria-expanded": activeActionRowKey === actionCellKey,
138
+ className: "p-1.5 rounded hover:bg-gray-200",
139
+ title: "Actions",
140
+ children: jsx(MoreVertical, {
141
+ className: "h-4 w-4"
142
+ })
143
+ }), activeActionRowKey === actionCellKey && jsx(ActionMenu, {
144
+ actions: menuActions,
145
+ row: row,
146
+ onAction: function onAction(action) {
147
+ return handleOnAction(action, row);
148
+ },
149
+ menuRef: actionMenuRef,
150
+ anchorEl: activeAnchorEl,
151
+ onClose: closeActionMenu,
152
+ theme: theme
153
+ })]
154
+ })]
155
+ })]
156
+ }), jsx("div", {
157
+ className: "p-4",
158
+ children: visibleColumns.map(function (column, colIndex) {
159
+ var extraCellClass = typeof cellClass === "function" ? cellClass({
160
+ row: row,
161
+ rowIndex: globalIndex,
162
+ column: column,
163
+ columnIndex: colIndex
164
+ }) : "";
165
+ var safeExtraCellClass = typeof extraCellClass === "string" ? extraCellClass.trim() : "";
166
+ return jsxs("div", {
167
+ className: cn("flex justify-between items-center flex-row py-2 border-b last:border-b-0", safeExtraCellClass),
168
+ children: [jsx("div", {
169
+ className: "text-xs font-medium text-primary-500 uppercase tracking-wide mb-1 sm:mb-0 sm:w-1/3 sm:pr-2",
170
+ children: column.label
171
+ }), jsx("div", {
172
+ className: "text-sm text-primary-900 sm:w-2/3 sm:pl-2 break-words",
173
+ children: renderCell(column, row, globalIndex)
174
+ })]
175
+ }, column.key);
176
+ })
177
+ }), showDetailsToggle && isExpanded && DetailsComponent && jsx("div", {
178
+ className: "border-t bg-gray-50 p-4",
179
+ children: jsx(DetailsComponent, {
180
+ row: row,
181
+ index: globalIndex
182
+ })
183
+ })]
184
+ }, key);
185
+ }
186
+
187
+ export { MobileCard as default };