@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,372 @@
1
+ 'use client';
2
+ import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, createForOfIteratorHelper as _createForOfIteratorHelper, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import React, { forwardRef, useRef, useState, useId, useCallback, useEffect, useMemo } from 'react';
5
+ import { createPortal } from 'react-dom';
6
+ import { cn } from '../../utils/cn.js';
7
+
8
+ var _excluded = ["position", "trigger", "content", "customTrigger", "children", "open", "defaultOpen", "onChange", "delay", "offset", "textClass", "bgClass", "className", "portal", "id"];
9
+ var NATIVE_FOCUSABLE_TAGS = new Set(["button", "input", "select", "textarea"]);
10
+ /**
11
+ * True when `el` is a single intrinsic element that is keyboard-focusable on
12
+ * its own (an enabled <button>/<input>/<select>/<textarea>, an <a href>, or any
13
+ * element with tabIndex >= 0). In that case the wrapper span must NOT add a
14
+ * second tab stop. Component elements (e.g. <Button>) can't be inspected
15
+ * statically, so they keep the focusable wrapper — use `customTrigger` there.
16
+ * Disabled controls are not focusable, so they also keep the wrapper (that is
17
+ * what makes a tooltip on a disabled button reachable by keyboard).
18
+ */
19
+ var isNativelyFocusable = function isNativelyFocusable(el) {
20
+ if (! /*#__PURE__*/React.isValidElement(el) || typeof el.type !== "string") return false;
21
+ var p = el.props || {};
22
+ if (p.disabled) return false;
23
+ if (p.tabIndex !== undefined && p.tabIndex !== null) {
24
+ return Number(p.tabIndex) >= 0;
25
+ }
26
+ if (el.type === "a") return p.href != null;
27
+ if (el.type === "input") return p.type !== "hidden";
28
+ return NATIVE_FOCUSABLE_TAGS.has(el.type);
29
+ };
30
+ /**
31
+ * Tooltip props
32
+ * - position: 'auto' | 'top' | 'bottom' | 'left' | 'right' (default 'auto')
33
+ * - trigger: 'hover' | 'click' | 'focus' | Array of those (default 'hover')
34
+ * - content: ReactNode | ( { close } ) => ReactNode
35
+ * - customTrigger: ReactElement (rendered in place of children as trigger)
36
+ * - children: ReactNode (trigger content if customTrigger not provided)
37
+ * - open: controlled boolean
38
+ * - defaultOpen: boolean
39
+ * - onChange: (open) => void
40
+ * - delay: number ms for hover open (default 80)
41
+ * - offset: spacing between trigger and tooltip (default 8)
42
+ * - textClass: string (CSS class for text color)
43
+ * - bgClass: string (CSS class for background color)
44
+ * - className: extra classes for tooltip box
45
+ * - portal: boolean (default true) -> render to document.body
46
+ */
47
+ var Tooltip = /*#__PURE__*/forwardRef(function Tooltip(_ref, forwardedRef) {
48
+ var _customTrigger$props$, _customTrigger$props;
49
+ var _ref$position = _ref.position,
50
+ position = _ref$position === void 0 ? "auto" : _ref$position,
51
+ _ref$trigger = _ref.trigger,
52
+ trigger = _ref$trigger === void 0 ? "hover" : _ref$trigger,
53
+ content = _ref.content,
54
+ customTrigger = _ref.customTrigger,
55
+ children = _ref.children,
56
+ controlledOpen = _ref.open,
57
+ _ref$defaultOpen = _ref.defaultOpen,
58
+ defaultOpen = _ref$defaultOpen === void 0 ? false : _ref$defaultOpen,
59
+ onChange = _ref.onChange,
60
+ _ref$delay = _ref.delay,
61
+ delay = _ref$delay === void 0 ? 80 : _ref$delay,
62
+ _ref$offset = _ref.offset,
63
+ offset = _ref$offset === void 0 ? 8 : _ref$offset,
64
+ _ref$textClass = _ref.textClass,
65
+ textClass = _ref$textClass === void 0 ? "text-black" : _ref$textClass,
66
+ _ref$bgClass = _ref.bgClass,
67
+ bgClass = _ref$bgClass === void 0 ? "bg-white" : _ref$bgClass,
68
+ _ref$className = _ref.className,
69
+ className = _ref$className === void 0 ? "" : _ref$className,
70
+ _ref$portal = _ref.portal,
71
+ portal = _ref$portal === void 0 ? true : _ref$portal,
72
+ propsId = _ref.id,
73
+ rest = _objectWithoutProperties(_ref, _excluded);
74
+ var triggerRef = useRef(null);
75
+ var tooltipRef = useRef(null);
76
+ var delayRef = useRef(null);
77
+ var _useState = useState(Boolean(controlledOpen !== null && controlledOpen !== void 0 ? controlledOpen : defaultOpen)),
78
+ _useState2 = _slicedToArray(_useState, 2),
79
+ open = _useState2[0],
80
+ setOpen = _useState2[1];
81
+ var _useState3 = useState("top"),
82
+ _useState4 = _slicedToArray(_useState3, 2),
83
+ setPlacement = _useState4[1];
84
+ var _useState5 = useState({
85
+ left: 0,
86
+ top: 0
87
+ }),
88
+ _useState6 = _slicedToArray(_useState5, 2),
89
+ coords = _useState6[0],
90
+ setCoords = _useState6[1];
91
+ var _useState7 = useState(false),
92
+ _useState8 = _slicedToArray(_useState7, 2),
93
+ mounted = _useState8[0],
94
+ setMounted = _useState8[1];
95
+ var reactId = useId();
96
+ var id = propsId !== null && propsId !== void 0 ? propsId : "tooltip-".concat(reactId);
97
+ var setTriggerRef = useCallback(function (node) {
98
+ triggerRef.current = node;
99
+ if (typeof forwardedRef === "function") forwardedRef(node);else if (forwardedRef) forwardedRef.current = node;
100
+ }, [forwardedRef]);
101
+ // sync controlled (adjust-during-render pattern)
102
+ var _useState9 = useState(controlledOpen),
103
+ _useState0 = _slicedToArray(_useState9, 2),
104
+ prevControlledOpen = _useState0[0],
105
+ setPrevControlledOpen = _useState0[1];
106
+ if (controlledOpen !== prevControlledOpen) {
107
+ setPrevControlledOpen(controlledOpen);
108
+ if (typeof controlledOpen === "boolean") setOpen(controlledOpen);
109
+ }
110
+ useEffect(function () {
111
+ return setMounted(true);
112
+ }, []);
113
+ var notify = useCallback(function (val) {
114
+ if (typeof onChange === "function") onChange(val);
115
+ }, [onChange]);
116
+ var computePosition = useCallback(function () {
117
+ var t = triggerRef.current;
118
+ var el = tooltipRef.current;
119
+ if (!t || !el) return;
120
+ var tr = t.getBoundingClientRect();
121
+ var ttW = el.offsetWidth;
122
+ var ttH = el.offsetHeight;
123
+ var winW = window.innerWidth;
124
+ var winH = window.innerHeight;
125
+ var candidates = ["top", "bottom", "left", "right"];
126
+ var chosen = position === "auto" ? "top" : position;
127
+ if (position === "auto") {
128
+ var _iterator = _createForOfIteratorHelper(candidates),
129
+ _step;
130
+ try {
131
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
132
+ var p = _step.value;
133
+ if (p === "top" && tr.top >= ttH + offset) {
134
+ chosen = "top";
135
+ break;
136
+ }
137
+ if (p === "bottom" && winH - tr.bottom >= ttH + offset) {
138
+ chosen = "bottom";
139
+ break;
140
+ }
141
+ if (p === "right" && winW - tr.right >= ttW + offset) {
142
+ chosen = "right";
143
+ break;
144
+ }
145
+ if (p === "left" && tr.left >= ttW + offset) {
146
+ chosen = "left";
147
+ break;
148
+ }
149
+ }
150
+ } catch (err) {
151
+ _iterator.e(err);
152
+ } finally {
153
+ _iterator.f();
154
+ }
155
+ }
156
+ var left = 0;
157
+ var top = 0;
158
+ switch (chosen) {
159
+ case "top":
160
+ left = tr.left + tr.width / 2 - ttW / 2;
161
+ top = tr.top - ttH - offset;
162
+ break;
163
+ case "bottom":
164
+ left = tr.left + tr.width / 2 - ttW / 2;
165
+ top = tr.bottom + offset;
166
+ break;
167
+ case "left":
168
+ left = tr.left - ttW - offset;
169
+ top = tr.top + tr.height / 2 - ttH / 2;
170
+ break;
171
+ case "right":
172
+ left = tr.right + offset;
173
+ top = tr.top + tr.height / 2 - ttH / 2;
174
+ break;
175
+ }
176
+ var pad = 8;
177
+ left = Math.max(pad, Math.min(left, winW - ttW - pad));
178
+ top = Math.max(pad, Math.min(top, winH - ttH - pad));
179
+ setPlacement(chosen);
180
+ setCoords({
181
+ left: Math.round(left) + window.scrollX,
182
+ top: Math.round(top) + window.scrollY
183
+ });
184
+ }, [offset, position]);
185
+ useEffect(function () {
186
+ if (!open) return;
187
+ computePosition();
188
+ var ro = new ResizeObserver(function () {
189
+ return computePosition();
190
+ });
191
+ if (triggerRef.current) ro.observe(triggerRef.current);
192
+ if (tooltipRef.current) ro.observe(tooltipRef.current);
193
+ var onScroll = function onScroll() {
194
+ return computePosition();
195
+ };
196
+ window.addEventListener("scroll", onScroll, true);
197
+ window.addEventListener("resize", computePosition);
198
+ return function () {
199
+ ro.disconnect();
200
+ window.removeEventListener("scroll", onScroll, true);
201
+ window.removeEventListener("resize", computePosition);
202
+ };
203
+ }, [open, computePosition]);
204
+ // open/close helpers
205
+ var openTooltip = useCallback(function () {
206
+ var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
207
+ clearTimeout(delayRef.current);
208
+ if (immediate || !delay) {
209
+ setOpen(true);
210
+ notify(true);
211
+ } else {
212
+ delayRef.current = setTimeout(function () {
213
+ setOpen(true);
214
+ notify(true);
215
+ }, delay);
216
+ }
217
+ }, [delay, notify]);
218
+ var closeTooltip = useCallback(function () {
219
+ clearTimeout(delayRef.current);
220
+ setOpen(false);
221
+ notify(false);
222
+ }, [notify]);
223
+ // triggers normalization
224
+ var triggers = useMemo(function () {
225
+ return Array.isArray(trigger) ? trigger : [trigger];
226
+ }, [trigger]);
227
+ // hover handlers
228
+ useEffect(function () {
229
+ var t = triggerRef.current;
230
+ if (!t) return;
231
+ if (triggers.includes("hover")) {
232
+ var onMouseEnter = function onMouseEnter() {
233
+ return openTooltip();
234
+ };
235
+ var onMouseLeave = function onMouseLeave() {
236
+ return closeTooltip();
237
+ };
238
+ t.addEventListener("mouseenter", onMouseEnter);
239
+ t.addEventListener("mouseleave", onMouseLeave);
240
+ // also attach to tooltip to prevent flicker
241
+ var tip = function tip() {
242
+ return tooltipRef.current;
243
+ };
244
+ var tryTip = tip();
245
+ if (tryTip) {
246
+ tryTip.addEventListener("mouseenter", onMouseEnter);
247
+ tryTip.addEventListener("mouseleave", onMouseLeave);
248
+ }
249
+ return function () {
250
+ t.removeEventListener("mouseenter", onMouseEnter);
251
+ t.removeEventListener("mouseleave", onMouseLeave);
252
+ if (tryTip) {
253
+ tryTip.removeEventListener("mouseenter", onMouseEnter);
254
+ tryTip.removeEventListener("mouseleave", onMouseLeave);
255
+ }
256
+ };
257
+ }
258
+ }, [triggers, openTooltip, closeTooltip]);
259
+ // click handlers (toggle and outside click)
260
+ useEffect(function () {
261
+ var t = triggerRef.current;
262
+ if (!t) return;
263
+ if (triggers.includes("click")) {
264
+ var onClick = function onClick(e) {
265
+ e.stopPropagation();
266
+ setOpen(function (s) {
267
+ var next = !s;
268
+ notify(next);
269
+ return next;
270
+ });
271
+ };
272
+ var onDocClick = function onDocClick(e) {
273
+ if (!t.contains(e.target) && tooltipRef.current && !tooltipRef.current.contains(e.target)) {
274
+ setOpen(false);
275
+ notify(false);
276
+ }
277
+ };
278
+ t.addEventListener("click", onClick);
279
+ document.addEventListener("click", onDocClick);
280
+ return function () {
281
+ t.removeEventListener("click", onClick);
282
+ document.removeEventListener("click", onDocClick);
283
+ };
284
+ }
285
+ }, [triggers, notify]);
286
+ // focus handlers: use focusin / focusout which bubble and handle inner focusables
287
+ useEffect(function () {
288
+ var t = triggerRef.current;
289
+ if (!t) return;
290
+ if (triggers.includes("focus")) {
291
+ var onFocusIn = function onFocusIn() {
292
+ return openTooltip(true);
293
+ };
294
+ var onFocusOut = function onFocusOut() {
295
+ return closeTooltip();
296
+ };
297
+ t.addEventListener("focusin", onFocusIn);
298
+ t.addEventListener("focusout", onFocusOut);
299
+ return function () {
300
+ t.removeEventListener("focusin", onFocusIn);
301
+ t.removeEventListener("focusout", onFocusOut);
302
+ };
303
+ }
304
+ }, [triggers, openTooltip, closeTooltip]);
305
+ // Escape key closes tooltip
306
+ useEffect(function () {
307
+ if (!open) return;
308
+ var onKey = function onKey(e) {
309
+ if (e.key === "Escape") closeTooltip();
310
+ };
311
+ document.addEventListener("keydown", onKey);
312
+ return function () {
313
+ return document.removeEventListener("keydown", onKey);
314
+ };
315
+ }, [open, closeTooltip]);
316
+ // content renderer
317
+ var renderContent = function renderContent() {
318
+ if (typeof content === "function") return content({
319
+ close: closeTooltip
320
+ });
321
+ return content;
322
+ };
323
+ // A lone natively-focusable child is already a tab stop: don't wrap it in a
324
+ // second one (doubled tab stops in grids/toolbars). It gets the
325
+ // aria-describedby instead, so screen readers still announce the tooltip.
326
+ var focusableChild = !customTrigger && isNativelyFocusable(children) ? children : null;
327
+ // trigger element (attach ref)
328
+ var triggerElement = customTrigger ? (
329
+ /*#__PURE__*/
330
+ // eslint-disable-next-line react-hooks/refs -- setTriggerRef is a callback ref, run by React at commit
331
+ React.cloneElement(customTrigger, {
332
+ ref: setTriggerRef,
333
+ "aria-describedby": id,
334
+ tabIndex: (_customTrigger$props$ = (_customTrigger$props = customTrigger.props) === null || _customTrigger$props === void 0 ? void 0 : _customTrigger$props.tabIndex) !== null && _customTrigger$props$ !== void 0 ? _customTrigger$props$ : 0
335
+ })) : focusableChild ? jsx("span", {
336
+ ref: setTriggerRef,
337
+ className: "inline-flex",
338
+ children: /*#__PURE__*/React.cloneElement(focusableChild, {
339
+ "aria-describedby": [focusableChild.props["aria-describedby"], id].filter(Boolean).join(" ")
340
+ })
341
+ }) : jsx("span", {
342
+ ref: setTriggerRef,
343
+ className: "inline-flex",
344
+ tabIndex: 0,
345
+ "aria-describedby": id,
346
+ children: children
347
+ });
348
+ // Tooltip box element
349
+ var tooltipNode = open ? jsx("div", _objectSpread2(_objectSpread2({
350
+ ref: tooltipRef,
351
+ id: id,
352
+ role: "tooltip"
353
+ }, rest), {}, {
354
+ className: cn("absolute z-50 transform-gpu transition-opacity duration-150", className),
355
+ style: {
356
+ left: coords.left,
357
+ top: coords.top,
358
+ position: "absolute"
359
+ },
360
+ children: jsx("div", {
361
+ className: cn("max-w-xs rounded-md border border-gray-200 px-3 py-2 text-sm shadow-lg shadow-black/5", bgClass, textClass),
362
+ children: renderContent()
363
+ })
364
+ })) : null;
365
+ // Render either inline or as portal
366
+ return jsxs(Fragment, {
367
+ children: [triggerElement, mounted && portal ? /*#__PURE__*/createPortal(tooltipNode, document.body) : tooltipNode]
368
+ });
369
+ });
370
+ Tooltip.displayName = "Tooltip";
371
+
372
+ export { Tooltip as default };
@@ -0,0 +1,96 @@
1
+ 'use client';
2
+ import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import React from 'react';
5
+ import { cn } from '../../utils/cn.js';
6
+ import { Info, AlertTriangle, AlertCircle, CheckCircle, X } from 'lucide-react';
7
+
8
+ var _excluded = ["variant", "title", "children", "dismissible", "onDismiss", "className"];
9
+ var Alert = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
10
+ var _ref$variant = _ref.variant,
11
+ variant = _ref$variant === void 0 ? 'info' : _ref$variant,
12
+ title = _ref.title,
13
+ children = _ref.children,
14
+ _ref$dismissible = _ref.dismissible,
15
+ dismissible = _ref$dismissible === void 0 ? false : _ref$dismissible,
16
+ onDismiss = _ref.onDismiss,
17
+ className = _ref.className,
18
+ props = _objectWithoutProperties(_ref, _excluded);
19
+ var variants = {
20
+ success: {
21
+ container: 'bg-success-50 border-success-200',
22
+ icon: jsx(CheckCircle, {
23
+ className: "h-5 w-5 text-success-500"
24
+ }),
25
+ title: 'text-success-800',
26
+ content: 'text-success-700'
27
+ },
28
+ error: {
29
+ container: 'bg-error-50 border-error-200',
30
+ icon: jsx(AlertCircle, {
31
+ className: "h-5 w-5 text-error-500"
32
+ }),
33
+ title: 'text-error-800',
34
+ content: 'text-error-700'
35
+ },
36
+ warning: {
37
+ container: 'bg-warning-50 border-warning-200',
38
+ icon: jsx(AlertTriangle, {
39
+ className: "h-5 w-5 text-warning-500"
40
+ }),
41
+ title: 'text-warning-800',
42
+ content: 'text-warning-700'
43
+ },
44
+ info: {
45
+ container: 'bg-primary-50 border-primary-200',
46
+ icon: jsx(Info, {
47
+ className: "h-5 w-5 text-primary-500"
48
+ }),
49
+ title: 'text-primary-800',
50
+ content: 'text-primary-700'
51
+ }
52
+ };
53
+ var variantStyles = variants[variant];
54
+ return jsx("div", _objectSpread2(_objectSpread2({
55
+ ref: ref,
56
+ className: cn('rounded-md border p-4', variantStyles.container, className),
57
+ role: "alert"
58
+ }, props), {}, {
59
+ children: jsxs("div", {
60
+ className: "flex",
61
+ children: [jsx("div", {
62
+ className: "flex-shrink-0",
63
+ children: variantStyles.icon
64
+ }), jsxs("div", {
65
+ className: "ml-3 flex-1",
66
+ children: [title && jsx("h3", {
67
+ className: cn('text-sm font-medium', variantStyles.title),
68
+ children: title
69
+ }), jsx("div", {
70
+ className: cn('text-sm', variantStyles.content, {
71
+ 'mt-1': title
72
+ }),
73
+ children: children
74
+ })]
75
+ }), dismissible && jsx("div", {
76
+ className: "ml-auto pl-3",
77
+ children: jsx("button", {
78
+ type: "button",
79
+ className: cn('inline-flex rounded-md p-1.5 focus:outline-none focus:ring-2 focus:ring-offset-2', {
80
+ 'text-success-500 hover:bg-success-100 focus:ring-success-600': variant === 'success',
81
+ 'text-error-500 hover:bg-error-100 focus:ring-error-600': variant === 'error',
82
+ 'text-warning-500 hover:bg-warning-100 focus:ring-warning-600': variant === 'warning',
83
+ 'text-primary-500 hover:bg-primary-100 focus:ring-primary-600': variant === 'info'
84
+ }),
85
+ onClick: onDismiss,
86
+ children: jsx(X, {
87
+ className: "h-4 w-4"
88
+ })
89
+ })
90
+ })]
91
+ })
92
+ }));
93
+ });
94
+ Alert.displayName = 'Alert';
95
+
96
+ export { Alert as default };
@@ -0,0 +1,200 @@
1
+ 'use client';
2
+ import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import React, { useRef, useEffect } from 'react';
5
+ import { createPortal } from 'react-dom';
6
+ import { cn } from '../../utils/cn.js';
7
+ import { X } from 'lucide-react';
8
+ import { useLatestRef } from '../../hooks/useLatestRef.js';
9
+
10
+ var _excluded = ["isOpen", "onClose", "title", "children", "size", "dismissible", "showCloseButton", "footer", "className", "onOpen"],
11
+ _excluded2 = ["children", "className"],
12
+ _excluded3 = ["children", "className"],
13
+ _excluded4 = ["children", "className"];
14
+ // Elements that can receive keyboard focus. Used to drive the focus trap and to
15
+ // pick the first element to focus when the dialog opens (WAI-ARIA APG dialog).
16
+ var FOCUSABLE_SELECTOR = ['a[href]', 'button:not([disabled])', 'textarea:not([disabled])', 'input:not([disabled])', 'select:not([disabled])', '[tabindex]:not([tabindex="-1"])'].join(',');
17
+ var getFocusable = function getFocusable(root) {
18
+ return root ? Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR)).filter(function (el) {
19
+ return el.getAttribute('aria-hidden') !== 'true';
20
+ }) : [];
21
+ };
22
+ // Assign one node to several refs (callback or object). Lets the dialog keep
23
+ // its internal `dialogRef` for the focus trap while still exposing the panel
24
+ // node to a consumer-supplied `ref` (issue #56).
25
+ var setRefs = function setRefs(node) {
26
+ for (var _len = arguments.length, refs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
27
+ refs[_key - 1] = arguments[_key];
28
+ }
29
+ refs.forEach(function (ref) {
30
+ if (!ref) return;
31
+ if (typeof ref === 'function') ref(node);else ref.current = node;
32
+ });
33
+ };
34
+ var Dialog = /*#__PURE__*/React.forwardRef(function (_ref, _ref3) {
35
+ var isOpen = _ref.isOpen,
36
+ onClose = _ref.onClose,
37
+ title = _ref.title,
38
+ children = _ref.children,
39
+ _ref$size = _ref.size,
40
+ size = _ref$size === void 0 ? 'md' : _ref$size,
41
+ _ref$dismissible = _ref.dismissible,
42
+ dismissible = _ref$dismissible === void 0 ? true : _ref$dismissible,
43
+ _ref$showCloseButton = _ref.showCloseButton,
44
+ showCloseButton = _ref$showCloseButton === void 0 ? true : _ref$showCloseButton,
45
+ footer = _ref.footer,
46
+ className = _ref.className,
47
+ onOpen = _ref.onOpen,
48
+ props = _objectWithoutProperties(_ref, _excluded);
49
+ var dialogRef = useRef(null);
50
+ // The element that had focus when the dialog opened, so we can restore it on close.
51
+ var lastFocusedRef = useRef(null);
52
+ // Latest onOpen without re-running the open effect when the prop identity changes.
53
+ var onOpenRef = useLatestRef(onOpen);
54
+ useEffect(function () {
55
+ var _ref2, _focusables$, _onOpenRef$current;
56
+ if (!isOpen) return undefined;
57
+ // Remember the opener so focus can return to it when the dialog closes.
58
+ lastFocusedRef.current = document.activeElement;
59
+ document.body.style.overflow = 'hidden';
60
+ // Move focus into the panel: first focusable descendant, else the panel itself.
61
+ var panel = dialogRef.current;
62
+ var focusables = getFocusable(panel);
63
+ (_ref2 = (_focusables$ = focusables[0]) !== null && _focusables$ !== void 0 ? _focusables$ : panel) === null || _ref2 === void 0 || _ref2.focus();
64
+ (_onOpenRef$current = onOpenRef.current) === null || _onOpenRef$current === void 0 || _onOpenRef$current.call(onOpenRef, {
65
+ dialogRef: panel
66
+ });
67
+ return function () {
68
+ var _lastFocusedRef$curre, _lastFocusedRef$curre2;
69
+ document.body.style.overflow = 'unset';
70
+ // Restore focus to whatever opened the dialog (APG focus-restore requirement).
71
+ (_lastFocusedRef$curre = lastFocusedRef.current) === null || _lastFocusedRef$curre === void 0 || (_lastFocusedRef$curre2 = _lastFocusedRef$curre.focus) === null || _lastFocusedRef$curre2 === void 0 || _lastFocusedRef$curre2.call(_lastFocusedRef$curre);
72
+ };
73
+ }, [isOpen, onOpenRef]);
74
+ // Escape-to-close + Tab focus trap. An aria-modal element must keep keyboard
75
+ // focus inside the panel; without this, Tab walks into the page behind it.
76
+ useEffect(function () {
77
+ if (!isOpen) return undefined;
78
+ var handleKeyDown = function handleKeyDown(e) {
79
+ if (e.key === 'Escape') {
80
+ if (dismissible) onClose === null || onClose === void 0 || onClose();
81
+ return;
82
+ }
83
+ if (e.key !== 'Tab') return;
84
+ var panel = dialogRef.current;
85
+ if (!panel) return;
86
+ var focusables = getFocusable(panel);
87
+ if (focusables.length === 0) {
88
+ // Nothing focusable inside — pin focus to the panel.
89
+ e.preventDefault();
90
+ panel.focus();
91
+ return;
92
+ }
93
+ var first = focusables[0];
94
+ var last = focusables[focusables.length - 1];
95
+ var active = document.activeElement;
96
+ var outside = !panel.contains(active) || active === panel;
97
+ if (e.shiftKey && (active === first || outside)) {
98
+ e.preventDefault();
99
+ last.focus();
100
+ } else if (!e.shiftKey && (active === last || outside)) {
101
+ e.preventDefault();
102
+ first.focus();
103
+ }
104
+ };
105
+ document.addEventListener('keydown', handleKeyDown);
106
+ return function () {
107
+ return document.removeEventListener('keydown', handleKeyDown);
108
+ };
109
+ }, [isOpen, dismissible, onClose]);
110
+ if (!isOpen) return null;
111
+ var sizeClasses = {
112
+ sm: 'max-w-md',
113
+ md: 'max-w-lg',
114
+ lg: 'max-w-2xl',
115
+ xl: 'max-w-4xl',
116
+ full: 'max-w-full mx-4'
117
+ };
118
+ var handleBackdropClick = function handleBackdropClick(e) {
119
+ if (dismissible && e.target === e.currentTarget) {
120
+ onClose === null || onClose === void 0 || onClose();
121
+ }
122
+ };
123
+ return /*#__PURE__*/createPortal(jsx("div", {
124
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4",
125
+ onClick: handleBackdropClick,
126
+ children: jsxs("div", _objectSpread2(_objectSpread2({
127
+ ref: function ref(node) {
128
+ return setRefs(node, dialogRef, _ref3);
129
+ },
130
+ className: cn('w-full rounded-lg bg-white shadow-xl animate-scale-in motion-reduce:animate-none', sizeClasses[size], className),
131
+ tabIndex: -1,
132
+ role: "dialog",
133
+ "aria-modal": "true",
134
+ "aria-labelledby": title ? 'dialog-title' : undefined
135
+ }, props), {}, {
136
+ children: [(title || showCloseButton) && jsxs("div", {
137
+ className: "flex items-center justify-between border-b border-gray-200 px-6 py-4",
138
+ children: [title && jsx("h2", {
139
+ id: "dialog-title",
140
+ className: "text-lg font-semibold text-primary-900",
141
+ children: title
142
+ }), showCloseButton && jsx("button", {
143
+ type: "button",
144
+ className: "rounded-md p-1 text-primary-400 hover:text-primary-600 hover:bg-gray-100",
145
+ onClick: onClose,
146
+ "aria-label": "Close dialog",
147
+ children: jsx(X, {
148
+ className: "h-5 w-5"
149
+ })
150
+ })]
151
+ }), jsx("div", {
152
+ className: "px-6 py-4",
153
+ children: children
154
+ }), footer && jsx("div", {
155
+ className: "flex items-center justify-end gap-3 border-t border-gray-200 px-6 py-4",
156
+ children: footer
157
+ })]
158
+ }))
159
+ }), document.body);
160
+ });
161
+ Dialog.displayName = 'Dialog';
162
+ // Dialog components for composition
163
+ var DialogHeader = function DialogHeader(_ref4) {
164
+ var children = _ref4.children,
165
+ className = _ref4.className,
166
+ props = _objectWithoutProperties(_ref4, _excluded2);
167
+ return jsx("div", _objectSpread2(_objectSpread2({
168
+ className: cn('border-b border-gray-200 px-6 py-4', className)
169
+ }, props), {}, {
170
+ children: children
171
+ }));
172
+ };
173
+ var DialogBody = function DialogBody(_ref5) {
174
+ var children = _ref5.children,
175
+ className = _ref5.className,
176
+ props = _objectWithoutProperties(_ref5, _excluded3);
177
+ return jsx("div", _objectSpread2(_objectSpread2({
178
+ className: cn('px-6 py-4', className)
179
+ }, props), {}, {
180
+ children: children
181
+ }));
182
+ };
183
+ var DialogFooter = function DialogFooter(_ref6) {
184
+ var children = _ref6.children,
185
+ className = _ref6.className,
186
+ props = _objectWithoutProperties(_ref6, _excluded4);
187
+ return jsx("div", _objectSpread2(_objectSpread2({
188
+ className: cn('flex items-center justify-end gap-3 border-t border-gray-200 px-6 py-4', className)
189
+ }, props), {}, {
190
+ children: children
191
+ }));
192
+ };
193
+ DialogHeader.displayName = 'Dialog.Header';
194
+ DialogBody.displayName = 'Dialog.Body';
195
+ DialogFooter.displayName = 'Dialog.Footer';
196
+ Dialog.Header = DialogHeader;
197
+ Dialog.Body = DialogBody;
198
+ Dialog.Footer = DialogFooter;
199
+
200
+ export { Dialog as default };