@dreamtree-org/twreact-ui 1.3.11 → 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 (164) hide show
  1. package/README.md +40 -6
  2. package/ai-skills/dreamtree-ui.md +47 -9
  3. package/codemods/v2.cjs +198 -0
  4. package/dist/ai-schema.json +609 -33
  5. package/dist/components/blocks/AppShell.d.ts.map +1 -1
  6. package/dist/components/blocks/BottomActionBar.d.ts +6 -0
  7. package/dist/components/blocks/BottomActionBar.d.ts.map +1 -0
  8. package/dist/components/blocks/ConfirmDialog.d.ts.map +1 -1
  9. package/dist/components/blocks/PageHeader.d.ts.map +1 -1
  10. package/dist/components/core/Checkbox.d.ts.map +1 -1
  11. package/dist/components/core/DatePicker.d.ts.map +1 -1
  12. package/dist/components/core/DateRangePicker.d.ts.map +1 -1
  13. package/dist/components/core/Form.d.ts.map +1 -1
  14. package/dist/components/core/Input.d.ts.map +1 -1
  15. package/dist/components/core/Popover.d.ts.map +1 -1
  16. package/dist/components/core/ProgressBar.d.ts.map +1 -1
  17. package/dist/components/core/Rate.d.ts.map +1 -1
  18. package/dist/components/core/SearchField.d.ts +9 -0
  19. package/dist/components/core/SearchField.d.ts.map +1 -0
  20. package/dist/components/core/SegmentedControl.d.ts +8 -0
  21. package/dist/components/core/SegmentedControl.d.ts.map +1 -0
  22. package/dist/components/core/Select.d.ts.map +1 -1
  23. package/dist/components/core/SwipeableListItem.d.ts +4 -0
  24. package/dist/components/core/SwipeableListItem.d.ts.map +1 -0
  25. package/dist/components/core/SwipeableListItemGesture.d.ts +58 -0
  26. package/dist/components/core/SwipeableListItemGesture.d.ts.map +1 -0
  27. package/dist/components/core/Switch.d.ts.map +1 -1
  28. package/dist/components/core/Table/ActionMenu.d.ts +10 -3
  29. package/dist/components/core/Table/ActionMenu.d.ts.map +1 -1
  30. package/dist/components/core/Table/MobileCard.d.ts +10 -1
  31. package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
  32. package/dist/components/core/Table/MobileFilters.d.ts +8 -2
  33. package/dist/components/core/Table/MobileFilters.d.ts.map +1 -1
  34. package/dist/components/core/Table/Table.d.ts.map +1 -1
  35. package/dist/components/core/Table/TableRow.d.ts +2 -1
  36. package/dist/components/core/Table/TableRow.d.ts.map +1 -1
  37. package/dist/components/core/Tabs.d.ts +3 -3
  38. package/dist/components/core/Tabs.d.ts.map +1 -1
  39. package/dist/components/core/ThreeDotPopover.d.ts +10 -22
  40. package/dist/components/core/ThreeDotPopover.d.ts.map +1 -1
  41. package/dist/components/core/Tooltip.d.ts +2 -1
  42. package/dist/components/core/Tooltip.d.ts.map +1 -1
  43. package/dist/components/core/internal/Calendar.d.ts +77 -0
  44. package/dist/components/core/internal/Calendar.d.ts.map +1 -0
  45. package/dist/components/core/menu/ActionMenuSurface.d.ts +42 -0
  46. package/dist/components/core/menu/ActionMenuSurface.d.ts.map +1 -0
  47. package/dist/components/core/menu/ActionSheetMenu.d.ts +17 -0
  48. package/dist/components/core/menu/ActionSheetMenu.d.ts.map +1 -0
  49. package/dist/components/core/menu/MenuPopover.d.ts +21 -0
  50. package/dist/components/core/menu/MenuPopover.d.ts.map +1 -0
  51. package/dist/components/core/menu/menuItems.d.ts +21 -0
  52. package/dist/components/core/menu/menuItems.d.ts.map +1 -0
  53. package/dist/components/core/menu/menuKeyboard.d.ts +16 -0
  54. package/dist/components/core/menu/menuKeyboard.d.ts.map +1 -0
  55. package/dist/components/feedback/ActionSheet.d.ts +4 -0
  56. package/dist/components/feedback/ActionSheet.d.ts.map +1 -0
  57. package/dist/components/feedback/Alert.d.ts.map +1 -1
  58. package/dist/components/feedback/Dialog.d.ts.map +1 -1
  59. package/dist/components/feedback/Drawer.d.ts.map +1 -1
  60. package/dist/components/feedback/Sheet.d.ts +4 -0
  61. package/dist/components/feedback/Sheet.d.ts.map +1 -0
  62. package/dist/components/feedback/Toast.d.ts +4 -3
  63. package/dist/components/feedback/Toast.d.ts.map +1 -1
  64. package/dist/components/feedback/ToastItem.d.ts +47 -0
  65. package/dist/components/feedback/ToastItem.d.ts.map +1 -0
  66. package/dist/components/feedback/ToastStack.d.ts +20 -0
  67. package/dist/components/feedback/ToastStack.d.ts.map +1 -0
  68. package/dist/components/feedback/ToastSwipe.d.ts +22 -0
  69. package/dist/components/feedback/ToastSwipe.d.ts.map +1 -0
  70. package/dist/components/feedback/Tour.d.ts.map +1 -1
  71. package/dist/components/feedback/sheetCore.d.ts +30 -0
  72. package/dist/components/feedback/sheetCore.d.ts.map +1 -0
  73. package/dist/components/navigation/Navbar.d.ts.map +1 -1
  74. package/dist/components/navigation/Sidebar.d.ts +6 -0
  75. package/dist/components/navigation/Sidebar.d.ts.map +1 -1
  76. package/dist/components/rich-text/RichTextEditor.d.ts.map +1 -1
  77. package/dist/components/rich-text/RichTextToolbar.d.ts +6 -2
  78. package/dist/components/rich-text/RichTextToolbar.d.ts.map +1 -1
  79. package/dist/components/utility/PullToRefresh.d.ts +5 -0
  80. package/dist/components/utility/PullToRefresh.d.ts.map +1 -0
  81. package/dist/esm/components/blocks/AppShell.js +97 -90
  82. package/dist/esm/components/blocks/BottomActionBar.js +132 -0
  83. package/dist/esm/components/blocks/ConfirmDialog.js +40 -4
  84. package/dist/esm/components/blocks/PageHeader.js +16 -3
  85. package/dist/esm/components/core/Checkbox.js +13 -24
  86. package/dist/esm/components/core/DatePicker.js +117 -304
  87. package/dist/esm/components/core/DateRangePicker.js +260 -308
  88. package/dist/esm/components/core/Form.js +11 -2
  89. package/dist/esm/components/core/Input.js +13 -18
  90. package/dist/esm/components/core/Popover.js +59 -48
  91. package/dist/esm/components/core/ProgressBar.js +36 -64
  92. package/dist/esm/components/core/Rate.js +5 -10
  93. package/dist/esm/components/core/SearchField.js +311 -0
  94. package/dist/esm/components/core/SegmentedControl.js +189 -0
  95. package/dist/esm/components/core/Select.js +185 -190
  96. package/dist/esm/components/core/SwipeableListItem.js +286 -0
  97. package/dist/esm/components/core/SwipeableListItemGesture.js +219 -0
  98. package/dist/esm/components/core/Switch.js +11 -13
  99. package/dist/esm/components/core/Table/ActionMenu.js +45 -231
  100. package/dist/esm/components/core/Table/ColumnMenu.js +1 -1
  101. package/dist/esm/components/core/Table/MobileCard.js +66 -16
  102. package/dist/esm/components/core/Table/MobileFilters.js +181 -10
  103. package/dist/esm/components/core/Table/Table.js +149 -102
  104. package/dist/esm/components/core/Table/TableRow.js +10 -2
  105. package/dist/esm/components/core/Tabs.js +7 -7
  106. package/dist/esm/components/core/ThreeDotPopover.js +93 -99
  107. package/dist/esm/components/core/Tooltip.js +138 -145
  108. package/dist/esm/components/core/internal/Calendar.js +381 -0
  109. package/dist/esm/components/core/menu/ActionMenuSurface.js +110 -0
  110. package/dist/esm/components/core/menu/ActionSheetMenu.js +140 -0
  111. package/dist/esm/components/core/menu/MenuPopover.js +177 -0
  112. package/dist/esm/components/core/menu/menuItems.js +61 -0
  113. package/dist/esm/components/core/menu/menuKeyboard.js +54 -0
  114. package/dist/esm/components/feedback/ActionSheet.js +55 -0
  115. package/dist/esm/components/feedback/Alert.js +63 -53
  116. package/dist/esm/components/feedback/Dialog.js +141 -53
  117. package/dist/esm/components/feedback/Drawer.js +130 -132
  118. package/dist/esm/components/feedback/Sheet.js +125 -0
  119. package/dist/esm/components/feedback/Toast.js +21 -291
  120. package/dist/esm/components/feedback/ToastItem.js +348 -0
  121. package/dist/esm/components/feedback/ToastStack.js +130 -0
  122. package/dist/esm/components/feedback/ToastSwipe.js +52 -0
  123. package/dist/esm/components/feedback/Tour.js +107 -30
  124. package/dist/esm/components/feedback/sheetCore.js +494 -0
  125. package/dist/esm/components/navigation/Dropdown.js +1 -1
  126. package/dist/esm/components/navigation/Navbar.js +172 -37
  127. package/dist/esm/components/navigation/Sidebar.js +263 -111
  128. package/dist/esm/components/rich-text/RichTextEditor.js +9 -3
  129. package/dist/esm/components/rich-text/RichTextToolbar.js +29 -9
  130. package/dist/esm/components/utility/Portal.js +31 -0
  131. package/dist/esm/components/utility/PullToRefresh.js +229 -0
  132. package/dist/esm/hooks/useFloatingPosition.js +82 -0
  133. package/dist/esm/hooks/useHaptics.js +65 -0
  134. package/dist/esm/hooks/usePresence.js +58 -0
  135. package/dist/esm/hooks/usePresentation.js +21 -0
  136. package/dist/esm/hooks/useSheetDrag.js +220 -0
  137. package/dist/esm/index.js +13 -2
  138. package/dist/esm/utils/position.js +10 -63
  139. package/dist/hooks/useFloatingPosition.d.ts +8 -4
  140. package/dist/hooks/useFloatingPosition.d.ts.map +1 -1
  141. package/dist/hooks/useHaptics.d.ts +19 -0
  142. package/dist/hooks/useHaptics.d.ts.map +1 -0
  143. package/dist/hooks/useSheetDrag.d.ts +31 -0
  144. package/dist/hooks/useSheetDrag.d.ts.map +1 -0
  145. package/dist/index.css +1 -1
  146. package/dist/index.d.ts +9 -1
  147. package/dist/index.esm.css +1 -1
  148. package/dist/index.esm.js +8851 -3198
  149. package/dist/index.js +8856 -3195
  150. package/dist/rich-text/index.js +41 -11
  151. package/dist/types/blocks.d.ts +32 -2
  152. package/dist/types/blocks.d.ts.map +1 -1
  153. package/dist/types/index.d.ts +353 -19
  154. package/dist/types/index.d.ts.map +1 -1
  155. package/dist/types/rich-text.d.ts +5 -0
  156. package/dist/types/rich-text.d.ts.map +1 -1
  157. package/dist/utils/position.d.ts +0 -15
  158. package/dist/utils/position.d.ts.map +1 -1
  159. package/doc/README.md +15 -0
  160. package/mcp/catalog.snapshot.json +1398 -464
  161. package/package.json +7 -2
  162. package/dist/esm/hooks/useSwipeToClose.js +0 -66
  163. package/dist/hooks/useSwipeToClose.d.ts +0 -24
  164. package/dist/hooks/useSwipeToClose.d.ts.map +0 -1
@@ -142,13 +142,22 @@ var Form = /*#__PURE__*/forwardRef(function Form(_ref2, ref) {
142
142
  onChange = _ref3$field.onChange,
143
143
  value = _ref3$field.value,
144
144
  ref = _ref3$field.ref;
145
- return jsx(Input, _objectSpread2({
145
+ return jsx(Input, _objectSpread2(_objectSpread2({
146
146
  type: type,
147
147
  value: value || "",
148
148
  onChange: onChange,
149
149
  ref: ref,
150
150
  helperText: helperText
151
- }, commonProps));
151
+ }, commonProps), {}, {
152
+ // Input's clear no longer fires a synthetic onChange (2.0), so a
153
+ // clearable field resets the form value here, then calls the
154
+ // field's own onClear.
155
+ onClear: function onClear() {
156
+ var _commonProps$onClear;
157
+ onChange("");
158
+ (_commonProps$onClear = commonProps.onClear) === null || _commonProps$onClear === void 0 || _commonProps$onClear.call(commonProps);
159
+ }
160
+ }));
152
161
  }
153
162
  }, name);
154
163
  case "select":
@@ -6,7 +6,7 @@ import { Search, EyeOff, Eye, X } from 'lucide-react';
6
6
  import { cn } from '../../utils/cn.js';
7
7
  import { TOUCH_TARGET } from '../../utils/touchTarget.js';
8
8
 
9
- var _excluded = ["id", "className", "type", "label", "placeholder", "error", "success", "helperText", "disabled", "required", "clearable", "icon", "iconPosition", "onClear", "showCount", "maxLength", "readOnly", "onChange", "value", "defaultValue", "size", "floatingLabel", "otp"];
9
+ var _excluded = ["id", "className", "type", "label", "placeholder", "error", "success", "helperText", "disabled", "required", "clearable", "leftIcon", "rightIcon", "onClear", "showCount", "maxLength", "readOnly", "onChange", "value", "defaultValue", "size", "floatingLabel", "otp"];
10
10
  // Field heights. `md` keeps its 40px desktop look and grows to the 44px touch
11
11
  // target on coarse pointers (same rule as Select); `lg` is 44px everywhere.
12
12
  var SIZE_CLASSES = {
@@ -63,9 +63,8 @@ var Input = /*#__PURE__*/forwardRef(function (props, forwardedRef) {
63
63
  required = _props$required === void 0 ? false : _props$required,
64
64
  _props$clearable = props.clearable,
65
65
  clearable = _props$clearable === void 0 ? false : _props$clearable,
66
- icon = props.icon,
67
- _props$iconPosition = props.iconPosition,
68
- iconPosition = _props$iconPosition === void 0 ? "left" : _props$iconPosition,
66
+ leftIcon = props.leftIcon,
67
+ rightIcon = props.rightIcon,
69
68
  onClear = props.onClear,
70
69
  _props$showCount = props.showCount,
71
70
  showCount = _props$showCount === void 0 ? false : _props$showCount,
@@ -125,27 +124,23 @@ var Input = /*#__PURE__*/forwardRef(function (props, forwardedRef) {
125
124
  if (!isControlled) setUncontrolledLength(val.length);
126
125
  onChange === null || onChange === void 0 || onChange(e);
127
126
  };
127
+ // Clear (2.0, DTUI-65): no synthetic `onChange` event any more. Controlled
128
+ // fields clear their own `value` in `onClear`; uncontrolled fields clear the
129
+ // DOM value themselves.
128
130
  var handleClear = function handleClear(e) {
129
131
  var _localRef$current, _localRef$current$foc;
130
132
  e === null || e === void 0 || e.preventDefault();
131
- if (isControlled) {
132
- // controlled — notify parent
133
- onChange === null || onChange === void 0 || onChange({
134
- target: {
135
- value: ""
136
- }
137
- });
138
- } else if (localRef.current) {
133
+ if (!isControlled && localRef.current) {
139
134
  localRef.current.value = "";
140
- // update local state
141
135
  setUncontrolledLength(0);
142
136
  }
143
137
  (_localRef$current = localRef.current) === null || _localRef$current === void 0 || (_localRef$current$foc = _localRef$current.focus) === null || _localRef$current$foc === void 0 || _localRef$current$foc.call(_localRef$current);
144
138
  onClear === null || onClear === void 0 || onClear();
145
139
  };
146
140
  // padding logic: left and right padding depend on icons/buttons visible
147
- var leftHasIcon = Boolean(icon && iconPosition === "left") || isSearch;
148
- var rightHasIcon = Boolean(icon && iconPosition === "right") || isPassword || clearable && currentLength > 0;
141
+ var leftHasIcon = Boolean(leftIcon) || isSearch;
142
+ var showRightIcon = Boolean(rightIcon) && !isPassword && !(clearable && currentLength > 0);
143
+ var rightHasIcon = showRightIcon || isPassword || clearable && currentLength > 0;
149
144
  var paddingClass = cn(leftHasIcon ? "pl-10" : "pl-3", rightHasIcon ? "pr-12" : "pr-3");
150
145
  var baseClasses = cn("w-full rounded-md border bg-surface text-foreground placeholder-gray-400 dark:placeholder-gray-500", "transition-colors duration-fast ease-standard motion-reduce:transition-none", "disabled:cursor-not-allowed disabled:opacity-50", isFloating ? FLOATING_SIZE_CLASSES[size] : SIZE_CLASSES[size],
151
146
  // The floated label replaces the placeholder until the field is focused.
@@ -171,7 +166,7 @@ var Input = /*#__PURE__*/forwardRef(function (props, forwardedRef) {
171
166
  className: "h-4 w-4 text-primary-400"
172
167
  }) : jsx("span", {
173
168
  className: "text-primary-400",
174
- children: icon
169
+ children: leftIcon
175
170
  })
176
171
  }), jsx("input", _objectSpread2(_objectSpread2({
177
172
  id: inputId,
@@ -194,9 +189,9 @@ var Input = /*#__PURE__*/forwardRef(function (props, forwardedRef) {
194
189
  "data-floating-label": "",
195
190
  className: cn("pointer-events-none absolute top-1 origin-left text-xs font-medium text-muted", leftHasIcon ? "left-10" : "left-3", "transition-[top,transform,font-size,color] duration-fast ease-standard motion-reduce:transition-none", "peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:text-sm", "peer-focus:top-1 peer-focus:translate-y-0 peer-focus:text-xs peer-focus:text-primary-600 dark:peer-focus:text-primary-400"),
196
191
  children: labelContent
197
- }), icon && iconPosition === "right" && !isPassword && !(clearable && currentLength > 0) && jsx("div", {
192
+ }), showRightIcon && jsx("div", {
198
193
  className: "absolute right-3 top-1/2 transform -translate-y-1/2 pointer-events-none text-primary-400",
199
- children: icon
194
+ children: rightIcon
200
195
  }), isPassword && jsx("button", {
201
196
  type: "button",
202
197
  className: ADORNMENT_BUTTON,
@@ -1,53 +1,23 @@
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, Fragment } from 'react/jsx-runtime';
4
- import React, { useRef, useId, useCallback, useEffect, useLayoutEffect } from 'react';
4
+ import React, { useRef, useId, useCallback, useEffect } from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import { cn } from '../../utils/cn.js';
7
- import { setRefs, computePosition } from '../../utils/position.js';
7
+ import { setRefs } from '../../utils/position.js';
8
8
  import { useFocusTrap, getFocusable } from '../../hooks/useFocusTrap.js';
9
9
  import { useControllableState } from '../../hooks/useControllableState.js';
10
+ import { useFloatingPosition } from '../../hooks/useFloatingPosition.js';
11
+ import { usePresentation } from '../../hooks/usePresentation.js';
12
+ import Sheet from '../feedback/Sheet.js';
10
13
 
11
- var _excluded = ["trigger", "children", "open", "defaultOpen", "onOpenChange", "placement", "offset", "title", "initialFocusRef", "disabled", "id", "className"];
12
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
13
- function usePopoverPosition(open, anchorRef, panelRef, placement, offset) {
14
- useIsomorphicLayoutEffect(function () {
15
- if (!open) return undefined;
16
- var update = function update() {
17
- var _anchorRef$current;
18
- var anchor = ((_anchorRef$current = anchorRef.current) === null || _anchorRef$current === void 0 ? void 0 : _anchorRef$current.firstElementChild) || anchorRef.current;
19
- var panel = panelRef.current;
20
- if (!anchor || !panel) return;
21
- var size = {
22
- width: panel.offsetWidth,
23
- height: panel.offsetHeight
24
- };
25
- var _computePosition = computePosition(anchor.getBoundingClientRect(), size, {
26
- placement: placement,
27
- offset: offset
28
- }),
29
- top = _computePosition.top,
30
- left = _computePosition.left,
31
- side = _computePosition.side;
32
- panel.style.top = "".concat(top, "px");
33
- panel.style.left = "".concat(left, "px");
34
- panel.setAttribute("data-side", side);
35
- };
36
- update();
37
- window.addEventListener("resize", update);
38
- window.addEventListener("scroll", update, true);
39
- return function () {
40
- window.removeEventListener("resize", update);
41
- window.removeEventListener("scroll", update, true);
42
- };
43
- }, [open, placement, offset, anchorRef, panelRef]);
44
- }
14
+ var _excluded = ["trigger", "children", "open", "defaultOpen", "onOpenChange", "placement", "offset", "title", "initialFocusRef", "disabled", "presentation", "id", "className", "style"];
45
15
  function useOutsideClose(open, anchorRef, panelRef, close) {
46
16
  useEffect(function () {
47
17
  if (!open) return undefined;
48
18
  var onDown = function onDown(e) {
49
- var _panelRef$current, _anchorRef$current2;
50
- if ((_panelRef$current = panelRef.current) !== null && _panelRef$current !== void 0 && _panelRef$current.contains(e.target) || (_anchorRef$current2 = anchorRef.current) !== null && _anchorRef$current2 !== void 0 && _anchorRef$current2.contains(e.target)) return;
19
+ var _panelRef$current, _anchorRef$current;
20
+ if ((_panelRef$current = panelRef.current) !== null && _panelRef$current !== void 0 && _panelRef$current.contains(e.target) || (_anchorRef$current = anchorRef.current) !== null && _anchorRef$current !== void 0 && _anchorRef$current.contains(e.target)) return;
51
21
  close();
52
22
  };
53
23
  document.addEventListener("mousedown", onDown);
@@ -74,8 +44,11 @@ var Popover = /*#__PURE__*/React.forwardRef(function (_ref, _ref2) {
74
44
  initialFocusRef = _ref.initialFocusRef,
75
45
  _ref$disabled = _ref.disabled,
76
46
  disabled = _ref$disabled === void 0 ? false : _ref$disabled,
47
+ _ref$presentation = _ref.presentation,
48
+ presentation = _ref$presentation === void 0 ? "auto" : _ref$presentation,
77
49
  idProp = _ref.id,
78
50
  className = _ref.className,
51
+ style = _ref.style,
79
52
  props = _objectWithoutProperties(_ref, _excluded);
80
53
  var anchorRef = useRef(null);
81
54
  var panelRef = useRef(null);
@@ -90,6 +63,18 @@ var Popover = /*#__PURE__*/React.forwardRef(function (_ref, _ref2) {
90
63
  _useControllableState2 = _slicedToArray(_useControllableState, 2),
91
64
  open = _useControllableState2[0],
92
65
  setOpen = _useControllableState2[1];
66
+ var asSheet = usePresentation(presentation) === "sheet";
67
+ var popoverOpen = open && !asSheet;
68
+ var _useFloatingPosition = useFloatingPosition({
69
+ placement: placement,
70
+ offset: offset,
71
+ open: popoverOpen
72
+ }),
73
+ refs = _useFloatingPosition.refs,
74
+ floatingStyles = _useFloatingPosition.floatingStyles,
75
+ resolvedPlacement = _useFloatingPosition.placement;
76
+ var setReference = refs.setReference,
77
+ setFloating = refs.setFloating;
93
78
  var close = useCallback(function () {
94
79
  return setOpen(false);
95
80
  }, [setOpen]);
@@ -97,10 +82,9 @@ var Popover = /*#__PURE__*/React.forwardRef(function (_ref, _ref2) {
97
82
  var _getFocusable$;
98
83
  return (_getFocusable$ = getFocusable(anchorRef.current)[0]) === null || _getFocusable$ === void 0 ? void 0 : _getFocusable$.focus();
99
84
  };
100
- usePopoverPosition(open, anchorRef, panelRef, placement, offset);
101
- useOutsideClose(open, anchorRef, panelRef, close);
85
+ useOutsideClose(popoverOpen, anchorRef, panelRef, close);
102
86
  useFocusTrap(panelRef, {
103
- active: open,
87
+ active: popoverOpen,
104
88
  trap: false,
105
89
  initialFocusRef: initialFocusRef,
106
90
  onEscape: function onEscape() {
@@ -142,21 +126,48 @@ var Popover = /*#__PURE__*/React.forwardRef(function (_ref, _ref2) {
142
126
  var content = typeof children === "function" ? children({
143
127
  close: close
144
128
  }) : children;
129
+ var anchor = jsx("span", {
130
+ ref: function ref(node) {
131
+ return setRefs(node, anchorRef, setReference);
132
+ },
133
+ className: "inline-flex",
134
+ children: triggerNode
135
+ });
136
+ // Phones (ADR 0001): the same content in a bottom sheet. Sheet owns the
137
+ // backdrop, the modal focus trap, Escape and focus return.
138
+ if (asSheet) {
139
+ return jsxs(Fragment, {
140
+ children: [anchor, jsx(Sheet, _objectSpread2(_objectSpread2({
141
+ ref: _ref2,
142
+ open: open,
143
+ onClose: close,
144
+ title: title,
145
+ initialFocus: initialFocusRef,
146
+ id: panelId,
147
+ className: className,
148
+ style: style,
149
+ "data-presentation": "sheet"
150
+ }, props), {}, {
151
+ children: jsx(Sheet.Body, {
152
+ children: content
153
+ })
154
+ }))]
155
+ });
156
+ }
145
157
  return jsxs(Fragment, {
146
- children: [jsx("span", {
147
- ref: anchorRef,
148
- className: "inline-flex",
149
- children: triggerNode
150
- }), open && typeof document !== "undefined" && /*#__PURE__*/createPortal(jsxs("div", _objectSpread2(_objectSpread2({
158
+ children: [anchor, open && typeof document !== "undefined" && /*#__PURE__*/createPortal(jsxs("div", _objectSpread2(_objectSpread2({
151
159
  ref: function ref(node) {
152
- return setRefs(node, panelRef, _ref2);
160
+ return setRefs(node, panelRef, _ref2, setFloating);
153
161
  },
154
162
  id: panelId,
155
163
  role: "dialog",
156
164
  "aria-labelledby": title ? titleId : undefined,
157
165
  tabIndex: -1,
158
166
  onKeyDown: handlePanelKeyDown,
159
- className: cn("fixed left-0 top-0 z-50 min-w-[12rem] max-w-sm rounded-lg border border-gray-200 bg-white p-4 text-sm text-gray-900 shadow-lg focus:outline-none", "dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100", "animate-fade-in motion-reduce:animate-none", className)
167
+ "data-side": resolvedPlacement.split("-")[0],
168
+ "data-presentation": "popover",
169
+ className: cn("z-popover min-w-[12rem] max-w-sm rounded-lg border border-gray-200 bg-white p-4 text-sm text-gray-900 shadow-lg focus:outline-none", "dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100", "animate-fade-in motion-reduce:animate-none", className),
170
+ style: _objectSpread2(_objectSpread2({}, floatingStyles), style)
160
171
  }, props), {}, {
161
172
  children: [title && jsx("h2", {
162
173
  id: titleId,
@@ -4,50 +4,41 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { forwardRef } from 'react';
5
5
  import { cn } from '../../utils/cn.js';
6
6
 
7
- var _excluded = ["value", "max", "size", "showValue", "rounded", "color", "bgColor", "valueColor", "striped", "animated", "label", "ariaLabel", "className", "style"];
8
- // ProgressBar. Without colour props it uses the primary token classes, so it follows the brand (STUDIO-59).
9
- // color, bgColor and valueColor still accept HEX for backwards compatibility (deprecated).
7
+ var _excluded = ["value", "max", "size", "showValue", "rounded", "variant", "striped", "animated", "label", "ariaLabel", "className", "style"];
8
+ // ProgressBar. Colours come only from role tokens, so it follows the brand and
9
+ // dark mode (STUDIO-59). The HEX props `color` / `bgColor` / `valueColor` were
10
+ // removed in 2.0.0 (DTUI-65); pick a token tone with `variant` instead.
10
11
  var SIZE_MAP = {
11
12
  xs: "h-1",
12
13
  sm: "h-2",
13
14
  md: "h-3",
14
15
  lg: "h-5"
15
16
  };
16
- function isHexColor(str) {
17
- return typeof str === "string" && /^#([0-9A-F]{3}){1,2}$/i.test(str);
18
- }
19
- function hexToRgb(hex) {
20
- if (!isHexColor(hex)) return null;
21
- var h = hex.replace('#', '');
22
- if (h.length === 3) h = h.split('').map(function (ch) {
23
- return ch + ch;
24
- }).join('');
25
- var bigint = parseInt(h, 16);
26
- return {
27
- r: bigint >> 16 & 255,
28
- g: bigint >> 8 & 255,
29
- b: bigint & 255
30
- };
31
- }
32
- function luminance(hex) {
33
- var rgb = hexToRgb(hex);
34
- if (!rgb) return 0;
35
- // relative luminance
36
- var srgb = [rgb.r, rgb.g, rgb.b].map(function (v) {
37
- var s = v / 255;
38
- return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
39
- });
40
- return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
41
- }
42
- function readableTextColor(bgHex, preferred) {
43
- // If preferred is provided and valid, use it; otherwise pick black/white based on contrast
44
- if (isHexColor(preferred)) return preferred;
45
- var L = luminance(bgHex);
46
- // WCAG suggests threshold around 0.179 for black/white contrast — we'll use 0.179
47
- return L > 0.179 ? '#000000' : '#ffffff';
48
- }
17
+ // Static class strings (no runtime-built Tailwind classes) per token tone.
18
+ var VARIANT_MAP = {
19
+ primary: {
20
+ fill: "bg-primary-600",
21
+ track: "bg-primary-100 dark:bg-primary-900/40"
22
+ },
23
+ secondary: {
24
+ fill: "bg-secondary-600",
25
+ track: "bg-secondary-100 dark:bg-secondary-900/40"
26
+ },
27
+ success: {
28
+ fill: "bg-success-600",
29
+ track: "bg-success-100 dark:bg-success-900/40"
30
+ },
31
+ warning: {
32
+ fill: "bg-warning-600",
33
+ track: "bg-warning-100 dark:bg-warning-900/40"
34
+ },
35
+ destructive: {
36
+ fill: "bg-error-600",
37
+ track: "bg-error-100 dark:bg-error-900/40"
38
+ }
39
+ };
49
40
  var ProgressBar = /*#__PURE__*/forwardRef(function ProgressBar(_ref, ref) {
50
- var _SIZE_MAP$size;
41
+ var _VARIANT_MAP$variant, _SIZE_MAP$size;
51
42
  var _ref$value = _ref.value,
52
43
  value = _ref$value === void 0 ? 0 : _ref$value,
53
44
  _ref$max = _ref.max,
@@ -58,12 +49,8 @@ var ProgressBar = /*#__PURE__*/forwardRef(function ProgressBar(_ref, ref) {
58
49
  showValue = _ref$showValue === void 0 ? false : _ref$showValue,
59
50
  _ref$rounded = _ref.rounded,
60
51
  rounded = _ref$rounded === void 0 ? true : _ref$rounded,
61
- _ref$color = _ref.color,
62
- color = _ref$color === void 0 ? undefined : _ref$color,
63
- _ref$bgColor = _ref.bgColor,
64
- bgColor = _ref$bgColor === void 0 ? undefined : _ref$bgColor,
65
- _ref$valueColor = _ref.valueColor,
66
- valueColor = _ref$valueColor === void 0 ? undefined : _ref$valueColor,
52
+ _ref$variant = _ref.variant,
53
+ variant = _ref$variant === void 0 ? 'primary' : _ref$variant,
67
54
  _ref$striped = _ref.striped,
68
55
  striped = _ref$striped === void 0 ? false : _ref$striped,
69
56
  _ref$animated = _ref.animated,
@@ -81,13 +68,7 @@ var ProgressBar = /*#__PURE__*/forwardRef(function ProgressBar(_ref, ref) {
81
68
  var safeValue = typeof value === 'number' ? value : 0;
82
69
  var clamped = Math.max(0, Math.min(safeValue, safeMax));
83
70
  var percent = safeMax === 0 ? 0 : clamped / safeMax * 100;
84
- // A valid HEX override is applied inline; anything else falls back to the token classes.
85
- var fillHex = isHexColor(color) ? color : null;
86
- var trackHex = isHexColor(bgColor) ? bgColor : null;
87
- var textHex = isHexColor(valueColor) ? valueColor : fillHex ? readableTextColor(fillHex, undefined) : null;
88
- var fillClass = fillHex ? '' : 'bg-primary-600';
89
- var trackClass = trackHex ? '' : 'bg-primary-100 dark:bg-primary-900/40';
90
- var textClass = textHex ? '' : 'text-white';
71
+ var tone = (_VARIANT_MAP$variant = VARIANT_MAP[variant]) !== null && _VARIANT_MAP$variant !== void 0 ? _VARIANT_MAP$variant : VARIANT_MAP.primary;
91
72
  // height class or inline style
92
73
  var heightClass = typeof size === 'number' ? '' : (_SIZE_MAP$size = SIZE_MAP[size]) !== null && _SIZE_MAP$size !== void 0 ? _SIZE_MAP$size : SIZE_MAP['md'];
93
74
  var heightStyle = typeof size === 'number' ? {
@@ -104,13 +85,9 @@ var ProgressBar = /*#__PURE__*/forwardRef(function ProgressBar(_ref, ref) {
104
85
  // Stripe motion is a Tailwind animation (DTUI-48) — no per-instance <style> tag —
105
86
  // and stops under prefers-reduced-motion, as does the width transition.
106
87
  var animatedClass = animated ? 'animate-progress-stripes motion-reduce:animate-none' : '';
107
- var finalFillStyle = _objectSpread2(_objectSpread2(_objectSpread2({
88
+ var finalFillStyle = _objectSpread2({
108
89
  width: "".concat(percent, "%")
109
- }, fillHex ? {
110
- backgroundColor: fillHex
111
- } : {}), textHex ? {
112
- color: textHex
113
- } : {}), stripeStyle);
90
+ }, stripeStyle);
114
91
  return jsxs("div", _objectSpread2(_objectSpread2({
115
92
  ref: ref,
116
93
  className: cn("w-full", className),
@@ -120,23 +97,18 @@ var ProgressBar = /*#__PURE__*/forwardRef(function ProgressBar(_ref, ref) {
120
97
  className: "mb-2 text-sm font-medium",
121
98
  children: label
122
99
  }) : null, jsx("div", {
123
- className: cn('w-full relative overflow-hidden', trackRadiusClass, trackClass),
124
- style: _objectSpread2(_objectSpread2({}, trackHex ? {
125
- backgroundColor: trackHex
126
- } : {}), heightStyle),
100
+ className: cn('w-full relative overflow-hidden', trackRadiusClass, tone.track),
101
+ style: heightStyle,
127
102
  role: "progressbar",
128
103
  "aria-label": ariaLabel,
129
104
  "aria-valuemin": 0,
130
105
  "aria-valuemax": safeMax,
131
106
  "aria-valuenow": clamped,
132
107
  children: jsx("div", {
133
- className: cn(radiusClass, heightClass, fillClass, textClass, 'flex items-center justify-center text-sm font-medium', 'transition-[width] duration-300 ease-out motion-reduce:transition-none', animatedClass),
108
+ className: cn(radiusClass, heightClass, tone.fill, 'text-white', 'flex items-center justify-center text-sm font-medium', 'transition-[width] duration-300 ease-out motion-reduce:transition-none', animatedClass),
134
109
  style: finalFillStyle,
135
110
  children: showValue ? jsxs("div", {
136
111
  className: "px-2 whitespace-nowrap truncate",
137
- style: textHex ? {
138
- color: textHex
139
- } : undefined,
140
112
  children: [Math.round(percent), "%"]
141
113
  }) : null
142
114
  })
@@ -5,7 +5,7 @@ import { forwardRef, useState, useRef } from 'react';
5
5
  import { cn } from '../../utils/cn.js';
6
6
  import { TOUCH_TARGET } from '../../utils/touchTarget.js';
7
7
 
8
- var _excluded = ["count", "value", "defaultValue", "readOnly", "icon", "toggledIcon", "activeColor", "inactiveColor", "size", "onChange", "onClick", "text", "className", "id", "name"];
8
+ var _excluded = ["count", "value", "defaultValue", "readOnly", "icon", "toggledIcon", "size", "onChange", "onClick", "text", "className", "id", "name"];
9
9
  function StarFilled(_ref) {
10
10
  var _ref$size = _ref.size,
11
11
  size = _ref$size === void 0 ? 20 : _ref$size;
@@ -50,8 +50,6 @@ var Rate = /*#__PURE__*/forwardRef(function Rate(_ref3, ref) {
50
50
  readOnly = _ref3$readOnly === void 0 ? false : _ref3$readOnly,
51
51
  icon = _ref3.icon,
52
52
  toggledIcon = _ref3.toggledIcon,
53
- activeColor = _ref3.activeColor,
54
- inactiveColor = _ref3.inactiveColor,
55
53
  _ref3$size = _ref3.size,
56
54
  size = _ref3$size === void 0 ? 20 : _ref3$size,
57
55
  onChange = _ref3.onChange,
@@ -208,9 +206,9 @@ var Rate = /*#__PURE__*/forwardRef(function Rate(_ref3, ref) {
208
206
  var starNumber = i + 1;
209
207
  var filled = starNumber <= (displayValue || 0);
210
208
  var checked = starNumber === selectedValue;
211
- var color = filled ? activeColor : inactiveColor;
212
- // Token classes unless a colour override is passed, so brands and dark mode apply (STUDIO-59).
213
- var colorClass = color ? "" : filled ? " text-warning-400" : " text-gray-200";
209
+ // Token classes only, so brands and dark mode apply (STUDIO-59). The inline
210
+ // activeColor / inactiveColor overrides were removed in 2.0.0 (DTUI-65).
211
+ var colorClass = filled ? "text-warning-400" : "text-gray-200";
214
212
  return jsx("button", {
215
213
  ref: function ref(el) {
216
214
  starRefs.current[i] = el;
@@ -234,10 +232,7 @@ var Rate = /*#__PURE__*/forwardRef(function Rate(_ref3, ref) {
234
232
  },
235
233
  disabled: readOnly,
236
234
  title: "".concat(starNumber, " of ").concat(count),
237
- className: cn("p-0 m-0 bg-transparent border-0 inline-flex items-center justify-center leading-0 rounded", "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500", "transition-colors motion-reduce:transition-none", TOUCH_TARGET, colorClass.trim()),
238
- style: color ? {
239
- color: color
240
- } : undefined,
235
+ className: cn("p-0 m-0 bg-transparent border-0 inline-flex items-center justify-center leading-0 rounded", "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500", "transition-colors motion-reduce:transition-none", TOUCH_TARGET, colorClass),
241
236
  children: filled ? ActiveIcon : InactiveIcon
242
237
  }, i);
243
238
  })