@dreamtree-org/twreact-ui 1.3.10 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +70 -6
  2. package/ai-skills/dreamtree-ui.md +58 -15
  3. package/codemods/v2.cjs +198 -0
  4. package/dist/ai-schema.json +745 -53
  5. package/dist/charts/index.js +195 -66
  6. package/dist/components/blocks/AppShell.d.ts.map +1 -1
  7. package/dist/components/blocks/BottomActionBar.d.ts +6 -0
  8. package/dist/components/blocks/BottomActionBar.d.ts.map +1 -0
  9. package/dist/components/blocks/ConfirmDialog.d.ts.map +1 -1
  10. package/dist/components/blocks/PageHeader.d.ts.map +1 -1
  11. package/dist/components/charts/CartesianChart.d.ts.map +1 -1
  12. package/dist/components/charts/ChartFrame.d.ts.map +1 -1
  13. package/dist/components/charts/useChartLayout.d.ts +25 -0
  14. package/dist/components/charts/useChartLayout.d.ts.map +1 -0
  15. package/dist/components/core/Button.d.ts.map +1 -1
  16. package/dist/components/core/Checkbox.d.ts.map +1 -1
  17. package/dist/components/core/ColorPicker.d.ts.map +1 -1
  18. package/dist/components/core/DatePicker.d.ts.map +1 -1
  19. package/dist/components/core/DateRangePicker.d.ts.map +1 -1
  20. package/dist/components/core/Form.d.ts.map +1 -1
  21. package/dist/components/core/Input.d.ts.map +1 -1
  22. package/dist/components/core/Loader.d.ts.map +1 -1
  23. package/dist/components/core/LocationPicker.d.ts.map +1 -1
  24. package/dist/components/core/Popover.d.ts.map +1 -1
  25. package/dist/components/core/ProgressBar.d.ts.map +1 -1
  26. package/dist/components/core/Radio.d.ts.map +1 -1
  27. package/dist/components/core/Rate.d.ts.map +1 -1
  28. package/dist/components/core/RoundedTag.d.ts.map +1 -1
  29. package/dist/components/core/SearchField.d.ts +9 -0
  30. package/dist/components/core/SearchField.d.ts.map +1 -0
  31. package/dist/components/core/SegmentedControl.d.ts +8 -0
  32. package/dist/components/core/SegmentedControl.d.ts.map +1 -0
  33. package/dist/components/core/Select.d.ts.map +1 -1
  34. package/dist/components/core/Skeleton.d.ts.map +1 -1
  35. package/dist/components/core/Slider.d.ts.map +1 -1
  36. package/dist/components/core/SpeechToText.d.ts.map +1 -1
  37. package/dist/components/core/SwipeableListItem.d.ts +4 -0
  38. package/dist/components/core/SwipeableListItem.d.ts.map +1 -0
  39. package/dist/components/core/SwipeableListItemGesture.d.ts +58 -0
  40. package/dist/components/core/SwipeableListItemGesture.d.ts.map +1 -0
  41. package/dist/components/core/Switch.d.ts.map +1 -1
  42. package/dist/components/core/Table/ActionMenu.d.ts +10 -3
  43. package/dist/components/core/Table/ActionMenu.d.ts.map +1 -1
  44. package/dist/components/core/Table/MobileCard.d.ts +10 -1
  45. package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
  46. package/dist/components/core/Table/MobileFilters.d.ts +8 -2
  47. package/dist/components/core/Table/MobileFilters.d.ts.map +1 -1
  48. package/dist/components/core/Table/Table.d.ts.map +1 -1
  49. package/dist/components/core/Table/TableRow.d.ts +2 -1
  50. package/dist/components/core/Table/TableRow.d.ts.map +1 -1
  51. package/dist/components/core/Tabs.d.ts +5 -8
  52. package/dist/components/core/Tabs.d.ts.map +1 -1
  53. package/dist/components/core/Textarea.d.ts.map +1 -1
  54. package/dist/components/core/ThreeDotPopover.d.ts +10 -22
  55. package/dist/components/core/ThreeDotPopover.d.ts.map +1 -1
  56. package/dist/components/core/Tooltip.d.ts +2 -1
  57. package/dist/components/core/Tooltip.d.ts.map +1 -1
  58. package/dist/components/core/internal/Calendar.d.ts +77 -0
  59. package/dist/components/core/internal/Calendar.d.ts.map +1 -0
  60. package/dist/components/core/menu/ActionMenuSurface.d.ts +42 -0
  61. package/dist/components/core/menu/ActionMenuSurface.d.ts.map +1 -0
  62. package/dist/components/core/menu/ActionSheetMenu.d.ts +17 -0
  63. package/dist/components/core/menu/ActionSheetMenu.d.ts.map +1 -0
  64. package/dist/components/core/menu/MenuPopover.d.ts +21 -0
  65. package/dist/components/core/menu/MenuPopover.d.ts.map +1 -0
  66. package/dist/components/core/menu/menuItems.d.ts +21 -0
  67. package/dist/components/core/menu/menuItems.d.ts.map +1 -0
  68. package/dist/components/core/menu/menuKeyboard.d.ts +16 -0
  69. package/dist/components/core/menu/menuKeyboard.d.ts.map +1 -0
  70. package/dist/components/feedback/ActionSheet.d.ts +4 -0
  71. package/dist/components/feedback/ActionSheet.d.ts.map +1 -0
  72. package/dist/components/feedback/Alert.d.ts.map +1 -1
  73. package/dist/components/feedback/Dialog.d.ts.map +1 -1
  74. package/dist/components/feedback/Drawer.d.ts.map +1 -1
  75. package/dist/components/feedback/Sheet.d.ts +4 -0
  76. package/dist/components/feedback/Sheet.d.ts.map +1 -0
  77. package/dist/components/feedback/Toast.d.ts +4 -3
  78. package/dist/components/feedback/Toast.d.ts.map +1 -1
  79. package/dist/components/feedback/ToastItem.d.ts +47 -0
  80. package/dist/components/feedback/ToastItem.d.ts.map +1 -0
  81. package/dist/components/feedback/ToastStack.d.ts +20 -0
  82. package/dist/components/feedback/ToastStack.d.ts.map +1 -0
  83. package/dist/components/feedback/ToastSwipe.d.ts +22 -0
  84. package/dist/components/feedback/ToastSwipe.d.ts.map +1 -0
  85. package/dist/components/feedback/Tour.d.ts.map +1 -1
  86. package/dist/components/feedback/sheetCore.d.ts +30 -0
  87. package/dist/components/feedback/sheetCore.d.ts.map +1 -0
  88. package/dist/components/navigation/Breadcrumbs.d.ts.map +1 -1
  89. package/dist/components/navigation/FootNav.d.ts.map +1 -1
  90. package/dist/components/navigation/Navbar.d.ts.map +1 -1
  91. package/dist/components/navigation/Sidebar.d.ts +6 -0
  92. package/dist/components/navigation/Sidebar.d.ts.map +1 -1
  93. package/dist/components/rich-text/RichTextEditor.d.ts.map +1 -1
  94. package/dist/components/rich-text/RichTextToolbar.d.ts +6 -2
  95. package/dist/components/rich-text/RichTextToolbar.d.ts.map +1 -1
  96. package/dist/components/utility/Avatar.d.ts +8 -0
  97. package/dist/components/utility/Avatar.d.ts.map +1 -1
  98. package/dist/components/utility/AvatarGroup.d.ts +4 -0
  99. package/dist/components/utility/AvatarGroup.d.ts.map +1 -0
  100. package/dist/components/utility/Badge.d.ts.map +1 -1
  101. package/dist/components/utility/Card.d.ts.map +1 -1
  102. package/dist/components/utility/Carousel.d.ts.map +1 -1
  103. package/dist/components/utility/FileUpload.d.ts.map +1 -1
  104. package/dist/components/utility/Pagination.d.ts.map +1 -1
  105. package/dist/components/utility/PullToRefresh.d.ts +5 -0
  106. package/dist/components/utility/PullToRefresh.d.ts.map +1 -0
  107. package/dist/components/utility/Sortable.d.ts.map +1 -1
  108. package/dist/components/utility/Stepper.d.ts.map +1 -1
  109. package/dist/esm/components/blocks/AppShell.js +97 -90
  110. package/dist/esm/components/blocks/BottomActionBar.js +132 -0
  111. package/dist/esm/components/blocks/ConfirmDialog.js +40 -4
  112. package/dist/esm/components/blocks/EmptyState.js +1 -1
  113. package/dist/esm/components/blocks/ErrorState.js +1 -1
  114. package/dist/esm/components/blocks/LoadingState.js +4 -4
  115. package/dist/esm/components/blocks/PageHeader.js +16 -3
  116. package/dist/esm/components/blocks/StatCard.js +6 -6
  117. package/dist/esm/components/blocks/StatusPill.js +5 -8
  118. package/dist/esm/components/charts/CartesianChart.js +85 -62
  119. package/dist/esm/components/charts/ChartFrame.js +12 -5
  120. package/dist/esm/components/charts/useChartLayout.js +105 -0
  121. package/dist/esm/components/core/Button.js +49 -25
  122. package/dist/esm/components/core/Checkbox.js +72 -57
  123. package/dist/esm/components/core/ColorPicker.js +31 -42
  124. package/dist/esm/components/core/DatePicker.js +117 -304
  125. package/dist/esm/components/core/DateRangePicker.js +260 -308
  126. package/dist/esm/components/core/Form.js +11 -2
  127. package/dist/esm/components/core/Input.js +100 -38
  128. package/dist/esm/components/core/Loader.js +30 -44
  129. package/dist/esm/components/core/LocationPicker.js +82 -16
  130. package/dist/esm/components/core/Popover.js +59 -48
  131. package/dist/esm/components/core/ProgressBar.js +40 -72
  132. package/dist/esm/components/core/Radio.js +10 -12
  133. package/dist/esm/components/core/Rate.js +77 -14
  134. package/dist/esm/components/core/RoundedTag.js +5 -5
  135. package/dist/esm/components/core/SearchField.js +311 -0
  136. package/dist/esm/components/core/SegmentedControl.js +189 -0
  137. package/dist/esm/components/core/Select.js +185 -190
  138. package/dist/esm/components/core/Skeleton.js +13 -14
  139. package/dist/esm/components/core/Slider.js +24 -6
  140. package/dist/esm/components/core/SpeechToText.js +68 -16
  141. package/dist/esm/components/core/SwipeableListItem.js +286 -0
  142. package/dist/esm/components/core/SwipeableListItemGesture.js +219 -0
  143. package/dist/esm/components/core/Switch.js +98 -28
  144. package/dist/esm/components/core/Table/ActionMenu.js +45 -231
  145. package/dist/esm/components/core/Table/ColumnMenu.js +1 -1
  146. package/dist/esm/components/core/Table/MobileCard.js +66 -16
  147. package/dist/esm/components/core/Table/MobileFilters.js +181 -10
  148. package/dist/esm/components/core/Table/Table.js +149 -102
  149. package/dist/esm/components/core/Table/TableRow.js +10 -2
  150. package/dist/esm/components/core/Tabs.js +186 -39
  151. package/dist/esm/components/core/Textarea.js +10 -2
  152. package/dist/esm/components/core/ThreeDotPopover.js +93 -99
  153. package/dist/esm/components/core/Tooltip.js +138 -145
  154. package/dist/esm/components/core/internal/Calendar.js +381 -0
  155. package/dist/esm/components/core/menu/ActionMenuSurface.js +110 -0
  156. package/dist/esm/components/core/menu/ActionSheetMenu.js +140 -0
  157. package/dist/esm/components/core/menu/MenuPopover.js +177 -0
  158. package/dist/esm/components/core/menu/menuItems.js +61 -0
  159. package/dist/esm/components/core/menu/menuKeyboard.js +54 -0
  160. package/dist/esm/components/feedback/ActionSheet.js +55 -0
  161. package/dist/esm/components/feedback/Alert.js +63 -53
  162. package/dist/esm/components/feedback/Dialog.js +141 -53
  163. package/dist/esm/components/feedback/Drawer.js +130 -132
  164. package/dist/esm/components/feedback/Sheet.js +125 -0
  165. package/dist/esm/components/feedback/Toast.js +21 -291
  166. package/dist/esm/components/feedback/ToastItem.js +348 -0
  167. package/dist/esm/components/feedback/ToastStack.js +130 -0
  168. package/dist/esm/components/feedback/ToastSwipe.js +52 -0
  169. package/dist/esm/components/feedback/Tour.js +107 -30
  170. package/dist/esm/components/feedback/sheetCore.js +494 -0
  171. package/dist/esm/components/navigation/Breadcrumbs.js +97 -35
  172. package/dist/esm/components/navigation/Dropdown.js +1 -1
  173. package/dist/esm/components/navigation/FootNav.js +102 -13
  174. package/dist/esm/components/navigation/Navbar.js +172 -37
  175. package/dist/esm/components/navigation/Sidebar.js +263 -111
  176. package/dist/esm/components/rich-text/RichTextEditor.js +9 -3
  177. package/dist/esm/components/rich-text/RichTextToolbar.js +29 -9
  178. package/dist/esm/components/utility/Avatar.js +14 -12
  179. package/dist/esm/components/utility/AvatarGroup.js +56 -0
  180. package/dist/esm/components/utility/Badge.js +43 -23
  181. package/dist/esm/components/utility/Card.js +32 -8
  182. package/dist/esm/components/utility/Carousel.js +139 -29
  183. package/dist/esm/components/utility/FileUpload.js +106 -31
  184. package/dist/esm/components/utility/Pagination.js +31 -13
  185. package/dist/esm/components/utility/Portal.js +31 -0
  186. package/dist/esm/components/utility/PullToRefresh.js +229 -0
  187. package/dist/esm/components/utility/Sortable.js +6 -2
  188. package/dist/esm/components/utility/Stepper.js +110 -47
  189. package/dist/esm/hooks/useFloatingPosition.js +82 -0
  190. package/dist/esm/hooks/useHaptics.js +65 -0
  191. package/dist/esm/hooks/usePresence.js +58 -0
  192. package/dist/esm/hooks/usePresentation.js +21 -0
  193. package/dist/esm/hooks/useSheetDrag.js +220 -0
  194. package/dist/esm/hooks/useSliderValues.js +8 -2
  195. package/dist/esm/hooks/useSortable.js +107 -5
  196. package/dist/esm/index.js +14 -2
  197. package/dist/esm/utils/position.js +10 -63
  198. package/dist/esm/utils/touchTarget.js +4 -1
  199. package/dist/hooks/useFloatingPosition.d.ts +8 -4
  200. package/dist/hooks/useFloatingPosition.d.ts.map +1 -1
  201. package/dist/hooks/useHaptics.d.ts +19 -0
  202. package/dist/hooks/useHaptics.d.ts.map +1 -0
  203. package/dist/hooks/useSheetDrag.d.ts +31 -0
  204. package/dist/hooks/useSheetDrag.d.ts.map +1 -0
  205. package/dist/hooks/useSliderValues.d.ts +6 -2
  206. package/dist/hooks/useSliderValues.d.ts.map +1 -1
  207. package/dist/hooks/useSortable.d.ts +11 -1
  208. package/dist/hooks/useSortable.d.ts.map +1 -1
  209. package/dist/index.css +1 -1
  210. package/dist/index.d.ts +11 -2
  211. package/dist/index.esm.css +1 -1
  212. package/dist/index.esm.js +10645 -3842
  213. package/dist/index.js +10657 -3845
  214. package/dist/rich-text/index.js +41 -11
  215. package/dist/types/blocks.d.ts +32 -2
  216. package/dist/types/blocks.d.ts.map +1 -1
  217. package/dist/types/charts.d.ts +3 -1
  218. package/dist/types/charts.d.ts.map +1 -1
  219. package/dist/types/index.d.ts +409 -26
  220. package/dist/types/index.d.ts.map +1 -1
  221. package/dist/types/rich-text.d.ts +5 -0
  222. package/dist/types/rich-text.d.ts.map +1 -1
  223. package/dist/utils/position.d.ts +0 -15
  224. package/dist/utils/position.d.ts.map +1 -1
  225. package/doc/README.md +16 -0
  226. package/mcp/catalog.snapshot.json +1540 -407
  227. package/package.json +7 -2
  228. package/dist/esm/hooks/useSwipeToClose.js +0 -66
  229. package/dist/hooks/useSwipeToClose.d.ts +0 -24
  230. package/dist/hooks/useSwipeToClose.d.ts.map +0 -1
@@ -0,0 +1,348 @@
1
+ 'use client';
2
+ import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2, defineProperty as _defineProperty } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import { forwardRef, useState, useRef, useCallback, useEffect } from 'react';
5
+ import { createPortal } from 'react-dom';
6
+ import { cn } from '../../utils/cn.js';
7
+ import { Bell, Info, AlertTriangle, XCircle, CheckCircle2, X } from 'lucide-react';
8
+ import { TOUCH_TARGET } from '../../utils/touchTarget.js';
9
+ import { usePresentation } from '../../hooks/usePresentation.js';
10
+ import { useToastSwipe } from './ToastSwipe.js';
11
+
12
+ var _excluded = ["id", "title", "message", "description", "type", "duration", "onClose", "position", "statusIcon", "actions", "color", "footerNote", "showFooterNote", "portal", "paused", "swipeToDismiss", "mobilePosition", "mobileOffset", "closeLabel", "className", "style", "onMouseEnter", "onMouseLeave", "onFocus", "onBlur", "onPointerDown", "onPointerUp", "onPointerCancel"];
13
+ // The single toast card. Re-exported as `Toast` from ./Toast.jsx, which also
14
+ // holds the provider / hook; the stack lives in ./ToastStack.jsx.
15
+ // Errors interrupt (role="alert", assertive); everything else waits for the
16
+ // screen reader to finish (role="status", polite). Consumers can still pass
17
+ // their own role / aria-live, which win because ...props spreads last.
18
+ var liveRegionProps = function liveRegionProps(type) {
19
+ return type === 'error' ? {
20
+ role: 'alert',
21
+ 'aria-live': 'assertive',
22
+ 'aria-atomic': 'true'
23
+ } : {
24
+ role: 'status',
25
+ 'aria-live': 'polite',
26
+ 'aria-atomic': 'true'
27
+ };
28
+ };
29
+ var STATUS_CONFIG = {
30
+ success: {
31
+ icon: CheckCircle2,
32
+ iconClass: 'text-success-600 dark:text-success-400',
33
+ progressClass: 'bg-success-500 dark:bg-success-400'
34
+ },
35
+ error: {
36
+ icon: XCircle,
37
+ iconClass: 'text-error-600 dark:text-error-400',
38
+ progressClass: 'bg-error-500 dark:bg-error-400'
39
+ },
40
+ warning: {
41
+ icon: AlertTriangle,
42
+ iconClass: 'text-warning-600 dark:text-warning-400',
43
+ progressClass: 'bg-warning-500 dark:bg-warning-400'
44
+ },
45
+ info: {
46
+ icon: Info,
47
+ iconClass: 'text-info-600 dark:text-info-400',
48
+ progressClass: 'bg-info-500 dark:bg-info-400'
49
+ },
50
+ "default": {
51
+ icon: Bell,
52
+ iconClass: 'text-primary-600 dark:text-primary-400',
53
+ progressClass: 'bg-primary-500 dark:bg-primary-400'
54
+ }
55
+ };
56
+ // Phone offset above the bottom edge (default 5rem, clearing a FootNav, in the
57
+ // classes below); `mobileOffset` sets this CSS variable.
58
+ var MOBILE_OFFSET_VAR = '--dt-toast-mobile-offset';
59
+ /** CSS length for `mobileOffset`: numbers are px, strings pass through. */
60
+ var toCssLength = function toCssLength(value) {
61
+ return typeof value === 'number' ? "".concat(value, "px") : value;
62
+ };
63
+ var STANDALONE_POSITION_CLASSES = {
64
+ 'top-right': 'top-4 right-4',
65
+ 'top-left': 'top-4 left-4',
66
+ 'bottom-right': 'bottom-4 right-4',
67
+ 'bottom-left': 'bottom-4 left-4',
68
+ 'top-center': 'top-4 left-1/2 transform -translate-x-1/2',
69
+ 'bottom-center': 'bottom-4 left-1/2 transform -translate-x-1/2'
70
+ };
71
+ // Phone placement for a standalone (portaled) toast: full width inside a 1rem
72
+ // gutter, above the safe area and the FootNav.
73
+ var STANDALONE_MOBILE_CLASSES = {
74
+ 'bottom-center': 'inset-x-4 bottom-[calc(var(--dt-toast-mobile-offset,5rem)+env(safe-area-inset-bottom,0px))]',
75
+ 'top-center': 'inset-x-4 top-[calc(1rem+env(safe-area-inset-top,0px))]'
76
+ };
77
+ var ACTION_BASE = 'inline-flex items-center justify-center px-3 py-1.5 text-xs font-medium rounded-control border shadow-xs transition-colors motion-reduce:transition-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1 focus-visible:ring-offset-surface';
78
+ var ACTION_PRIMARY = 'bg-primary-600 hover:bg-primary-700 text-white border-primary-600 dark:bg-primary-500 dark:hover:bg-primary-400 dark:border-primary-500';
79
+ var ACTION_SECONDARY = 'bg-line/40 text-foreground border-line hover:bg-line/70 dark:bg-line/30 dark:hover:bg-line/60';
80
+ var callAll = function callAll() {
81
+ for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {
82
+ fns[_key] = arguments[_key];
83
+ }
84
+ return function (e) {
85
+ return fns.forEach(function (fn) {
86
+ return fn === null || fn === void 0 ? void 0 : fn(e);
87
+ });
88
+ };
89
+ };
90
+ // Pausing the auto-dismiss timer: hover, focus inside, a touch press, a swipe,
91
+ // the "Click to stop." footer link, or the `paused` prop (the stack pauses
92
+ // every toast while the user interacts with it).
93
+ function usePauseReasons() {
94
+ var _useState = useState({}),
95
+ _useState2 = _slicedToArray(_useState, 2),
96
+ reasons = _useState2[0],
97
+ setReasons = _useState2[1];
98
+ var set = useCallback(function (reason, on) {
99
+ setReasons(function (prev) {
100
+ return Boolean(prev[reason]) === on ? prev : _objectSpread2(_objectSpread2({}, prev), {}, _defineProperty({}, reason, on));
101
+ });
102
+ }, []);
103
+ return [Object.values(reasons).some(Boolean), set];
104
+ }
105
+ var Toast = /*#__PURE__*/forwardRef(function (_ref, ref) {
106
+ var id = _ref.id,
107
+ title = _ref.title,
108
+ message = _ref.message,
109
+ description = _ref.description,
110
+ _ref$type = _ref.type,
111
+ type = _ref$type === void 0 ? 'info' : _ref$type,
112
+ _ref$duration = _ref.duration,
113
+ duration = _ref$duration === void 0 ? 5000 : _ref$duration,
114
+ onClose = _ref.onClose,
115
+ _ref$position = _ref.position,
116
+ position = _ref$position === void 0 ? 'top-right' : _ref$position,
117
+ statusIcon = _ref.statusIcon,
118
+ _ref$actions = _ref.actions,
119
+ actions = _ref$actions === void 0 ? [] : _ref$actions,
120
+ color = _ref.color,
121
+ footerNote = _ref.footerNote,
122
+ _ref$showFooterNote = _ref.showFooterNote,
123
+ showFooterNote = _ref$showFooterNote === void 0 ? false : _ref$showFooterNote,
124
+ _ref$portal = _ref.portal,
125
+ portal = _ref$portal === void 0 ? true : _ref$portal,
126
+ _ref$paused = _ref.paused,
127
+ paused = _ref$paused === void 0 ? false : _ref$paused,
128
+ _ref$swipeToDismiss = _ref.swipeToDismiss,
129
+ swipeToDismiss = _ref$swipeToDismiss === void 0 ? true : _ref$swipeToDismiss,
130
+ _ref$mobilePosition = _ref.mobilePosition,
131
+ mobilePosition = _ref$mobilePosition === void 0 ? 'bottom-center' : _ref$mobilePosition,
132
+ mobileOffset = _ref.mobileOffset,
133
+ _ref$closeLabel = _ref.closeLabel,
134
+ closeLabel = _ref$closeLabel === void 0 ? 'Close notification' : _ref$closeLabel,
135
+ _ref$className = _ref.className,
136
+ className = _ref$className === void 0 ? '' : _ref$className,
137
+ style = _ref.style,
138
+ onMouseEnter = _ref.onMouseEnter,
139
+ onMouseLeave = _ref.onMouseLeave,
140
+ onFocus = _ref.onFocus,
141
+ onBlur = _ref.onBlur,
142
+ onPointerDown = _ref.onPointerDown,
143
+ onPointerUp = _ref.onPointerUp,
144
+ onPointerCancel = _ref.onPointerCancel,
145
+ props = _objectWithoutProperties(_ref, _excluded);
146
+ var _useState3 = useState(true),
147
+ _useState4 = _slicedToArray(_useState3, 2),
148
+ isVisible = _useState4[0],
149
+ setIsVisible = _useState4[1];
150
+ var _useState5 = useState(false),
151
+ _useState6 = _slicedToArray(_useState5, 2),
152
+ isLeaving = _useState6[0],
153
+ setIsLeaving = _useState6[1];
154
+ var _usePauseReasons = usePauseReasons(),
155
+ _usePauseReasons2 = _slicedToArray(_usePauseReasons, 2),
156
+ selfPaused = _usePauseReasons2[0],
157
+ setPaused = _usePauseReasons2[1];
158
+ var isPaused = paused || selfPaused;
159
+ var isPhone = usePresentation('auto') === 'sheet';
160
+ var progressBarRef = useRef(null);
161
+ var timerTextRef = useRef(null);
162
+ var startTimeRef = useRef(null);
163
+ var remainingRef = useRef(duration);
164
+ var timerRef = useRef(null);
165
+ var animFrameRef = useRef(null);
166
+ var handleClose = useCallback(function () {
167
+ if (isLeaving) return;
168
+ setIsLeaving(true);
169
+ setTimeout(function () {
170
+ setIsVisible(false);
171
+ onClose === null || onClose === void 0 || onClose(id);
172
+ }, 300);
173
+ }, [id, onClose, isLeaving]);
174
+ var swipe = useToastSwipe({
175
+ enabled: swipeToDismiss && !isLeaving,
176
+ onDismiss: handleClose
177
+ });
178
+ var handleStopTimer = useCallback(function (e) {
179
+ e === null || e === void 0 || e.stopPropagation();
180
+ setPaused('stopped', true);
181
+ if (timerRef.current) clearTimeout(timerRef.current);
182
+ if (animFrameRef.current) cancelAnimationFrame(animFrameRef.current);
183
+ }, [setPaused]);
184
+ // Direct DOM-based progress updates to prevent 60 FPS React re-renders and glitches
185
+ useEffect(function () {
186
+ if (duration <= 0) return;
187
+ if (isPaused) {
188
+ if (timerRef.current) clearTimeout(timerRef.current);
189
+ if (animFrameRef.current) cancelAnimationFrame(animFrameRef.current);
190
+ return;
191
+ }
192
+ startTimeRef.current = Date.now();
193
+ timerRef.current = setTimeout(function () {
194
+ handleClose();
195
+ }, remainingRef.current);
196
+ var _updateProgress = function updateProgress() {
197
+ var elapsed = startTimeRef.current ? Date.now() - startTimeRef.current : 0;
198
+ var currentRemaining = Math.max(0, remainingRef.current - elapsed);
199
+ var pct = currentRemaining / duration * 100;
200
+ if (progressBarRef.current) {
201
+ progressBarRef.current.style.width = "".concat(pct, "%");
202
+ }
203
+ if (timerTextRef.current) {
204
+ var secs = Math.ceil(currentRemaining / 1000);
205
+ timerTextRef.current.textContent = "This message will close in ".concat(secs, " seconds. ");
206
+ }
207
+ if (currentRemaining > 0 && !isPaused) {
208
+ animFrameRef.current = requestAnimationFrame(_updateProgress);
209
+ }
210
+ };
211
+ animFrameRef.current = requestAnimationFrame(_updateProgress);
212
+ return function () {
213
+ if (timerRef.current) clearTimeout(timerRef.current);
214
+ if (animFrameRef.current) cancelAnimationFrame(animFrameRef.current);
215
+ if (!isPaused && startTimeRef.current) {
216
+ var elapsed = Date.now() - startTimeRef.current;
217
+ remainingRef.current = Math.max(0, remainingRef.current - elapsed);
218
+ }
219
+ };
220
+ }, [duration, isPaused, handleClose]);
221
+ if (!isVisible) return null;
222
+ var statusStyle = STATUS_CONFIG[type] || STATUS_CONFIG.info;
223
+ var StatusIconComponent = statusStyle.icon;
224
+ var bodyText = description || message;
225
+ var mobileClass = portal && isPhone && mobilePosition ? STANDALONE_MOBILE_CLASSES[mobilePosition] : null;
226
+ var positionClass = mobileClass || STANDALONE_POSITION_CLASSES[position] || STANDALONE_POSITION_CLASSES['top-right'];
227
+ // Swipe: follow the finger, fade with distance, then leave the way it went.
228
+ // A centred standalone toast keeps its -50% shift under the inline transform.
229
+ var rootStyle = _objectSpread2({}, style);
230
+ if (mobileClass && mobileOffset != null) rootStyle[MOBILE_OFFSET_VAR] = toCssLength(mobileOffset);
231
+ var centerShift = portal && !mobileClass && /-center$/.test(position) ? 'translateX(-50%) ' : '';
232
+ if (swipe.swipedOut) {
233
+ rootStyle.transform = "".concat(centerShift, "translateX(").concat(swipe.swipedOut * 110, "%)");
234
+ rootStyle.opacity = 0;
235
+ } else if (swipe.offset) {
236
+ rootStyle.transform = "".concat(centerShift, "translateX(").concat(swipe.offset, "px)");
237
+ rootStyle.opacity = Math.max(0.2, 1 - Math.abs(swipe.offset) / 240);
238
+ }
239
+ var onTouchPress = function onTouchPress(e) {
240
+ if (e.pointerType && e.pointerType !== 'mouse') setPaused('touch', true);
241
+ };
242
+ var onTouchRelease = function onTouchRelease() {
243
+ return setPaused('touch', false);
244
+ };
245
+ var toastContent = jsxs("div", _objectSpread2(_objectSpread2(_objectSpread2({
246
+ ref: ref,
247
+ "data-swiping": swipe.dragging ? '' : undefined,
248
+ "data-swipe-out": swipe.swipedOut ? swipe.swipedOut > 0 ? 'right' : 'left' : undefined,
249
+ onMouseEnter: callAll(function () {
250
+ return setPaused('hover', true);
251
+ }, onMouseEnter),
252
+ onMouseLeave: callAll(function () {
253
+ return setPaused('hover', false);
254
+ }, onMouseLeave),
255
+ onFocus: callAll(function () {
256
+ return setPaused('focus', true);
257
+ }, onFocus),
258
+ onBlur: callAll(function (e) {
259
+ if (!e.currentTarget.contains(e.relatedTarget)) setPaused('focus', false);
260
+ }, onBlur),
261
+ onPointerDown: callAll(onTouchPress, swipe.dragProps.onPointerDown, onPointerDown),
262
+ onPointerMove: swipe.dragProps.onPointerMove,
263
+ onPointerUp: callAll(onTouchRelease, swipe.dragProps.onPointerUp, onPointerUp),
264
+ onPointerCancel: callAll(onTouchRelease, swipe.dragProps.onPointerCancel, onPointerCancel),
265
+ className: cn('relative overflow-hidden rounded-card border border-line bg-surface text-foreground shadow-overlay', 'dark:border-line dark:bg-surface dark:text-foreground', 'max-w-md w-full touch-pan-y select-none', !swipe.dragging && 'transition-[opacity,transform] duration-base ease-standard motion-reduce:transition-none', isLeaving && !swipe.swipedOut ? 'opacity-0 scale-95 translate-y-1 motion-reduce:scale-100 motion-reduce:translate-y-0' : 'animate-slide-up motion-reduce:animate-none', portal ? ['fixed z-toast', positionClass, mobileClass && 'w-auto max-w-none'] : '', className),
266
+ style: rootStyle
267
+ }, liveRegionProps(type)), props), {}, {
268
+ children: [jsx("div", {
269
+ className: "p-4",
270
+ children: jsxs("div", {
271
+ className: "flex items-start gap-3 justify-between",
272
+ children: [jsx("span", {
273
+ className: "flex-shrink-0 mt-0.5",
274
+ "aria-hidden": "true",
275
+ children: statusIcon ? statusIcon : jsx(StatusIconComponent, {
276
+ className: cn('h-5 w-5', statusStyle.iconClass)
277
+ })
278
+ }), jsxs("div", {
279
+ className: "flex-1 min-w-0 select-text",
280
+ children: [title && jsx("h4", {
281
+ className: "text-sm font-semibold text-foreground leading-snug",
282
+ children: title
283
+ }), bodyText && jsx("p", {
284
+ className: "mt-1 text-xs text-muted leading-relaxed whitespace-pre-line",
285
+ children: bodyText
286
+ }), actions && actions.length > 0 && jsx("div", {
287
+ className: "mt-3 flex items-center gap-2 flex-wrap",
288
+ children: actions.map(function (actItem, idx) {
289
+ return jsx("button", {
290
+ type: "button",
291
+ onClick: function onClick(e) {
292
+ var _actItem$onClick;
293
+ (_actItem$onClick = actItem.onClick) === null || _actItem$onClick === void 0 || _actItem$onClick.call(actItem, e);
294
+ if (actItem.dismiss !== false) {
295
+ handleClose();
296
+ }
297
+ },
298
+ className: cn(ACTION_BASE, actItem.variant === 'primary' ? ACTION_PRIMARY : ACTION_SECONDARY, actItem.className),
299
+ children: actItem.label
300
+ }, actItem.id || actItem.label || "act-".concat(idx));
301
+ })
302
+ })]
303
+ }), jsx("button", {
304
+ type: "button",
305
+ "aria-label": closeLabel,
306
+ className: cn('inline-flex h-11 w-11 -mr-2.5 -mt-2.5 flex-shrink-0 items-center justify-center rounded-control text-muted hover:text-foreground hover:bg-line/50 transition-colors motion-reduce:transition-none outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500', TOUCH_TARGET),
307
+ onClick: handleClose,
308
+ children: jsx(X, {
309
+ className: "h-4 w-4",
310
+ "aria-hidden": "true"
311
+ })
312
+ })]
313
+ })
314
+ }), (showFooterNote || footerNote) && duration > 0 && jsx("div", {
315
+ className: "px-4 py-2 bg-line/20 border-t border-line text-[11px] text-muted flex items-center justify-between",
316
+ children: jsx("span", {
317
+ children: footerNote ? footerNote : jsxs(Fragment, {
318
+ children: [jsxs("span", {
319
+ ref: timerTextRef,
320
+ children: ["This message will close in ", Math.ceil(duration / 1000), " seconds.", ' ']
321
+ }), jsx("button", {
322
+ type: "button",
323
+ onClick: handleStopTimer,
324
+ className: "font-medium text-foreground hover:underline inline rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500",
325
+ children: "Click to stop."
326
+ })]
327
+ })
328
+ })
329
+ }), duration > 0 && jsx("div", {
330
+ className: "absolute bottom-0 left-0 right-0 h-0.5 bg-line/60 overflow-hidden rounded-b-card",
331
+ children: jsx("div", {
332
+ ref: progressBarRef,
333
+ className: cn('h-full', color ? '' : statusStyle.progressClass),
334
+ style: {
335
+ width: '100%',
336
+ backgroundColor: color || undefined
337
+ }
338
+ })
339
+ })]
340
+ }));
341
+ if (portal) {
342
+ return /*#__PURE__*/createPortal(toastContent, document.body);
343
+ }
344
+ return toastContent;
345
+ });
346
+ Toast.displayName = 'Toast';
347
+
348
+ export { MOBILE_OFFSET_VAR, STATUS_CONFIG, Toast as default, toCssLength };
@@ -0,0 +1,130 @@
1
+ 'use client';
2
+ import { slicedToArray as _slicedToArray, defineProperty as _defineProperty, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import { useRef, useState } from 'react';
5
+ import { createPortal } from 'react-dom';
6
+ import { cn } from '../../utils/cn.js';
7
+ import { usePresentation } from '../../hooks/usePresentation.js';
8
+ import { useClickOutside } from '../../hooks/useClickOutside.js';
9
+ import Toast, { toCssLength, MOBILE_OFFSET_VAR } from './ToastItem.js';
10
+
11
+ // Internal (not exported). The stack behind <ToastContainer> and
12
+ // <ToastProvider>. Up to `visibleToasts` toasts list normally; past that the
13
+ // stack collapses Sonner-style (newest in front, older ones peeking behind)
14
+ // and expands while the pointer is over it, focus is inside it, or after a
15
+ // tap — pausing every timer meanwhile.
16
+ var POSITION_CLASSES = {
17
+ 'top-right': 'top-4 right-4 items-end',
18
+ 'top-left': 'top-4 left-4 items-start',
19
+ 'bottom-right': 'bottom-4 right-4 items-end',
20
+ 'bottom-left': 'bottom-4 left-4 items-start',
21
+ 'top-center': 'top-4 left-1/2 transform -translate-x-1/2 items-center',
22
+ 'bottom-center': 'bottom-4 left-1/2 transform -translate-x-1/2 items-center'
23
+ };
24
+ // Phones: full width inside a 1rem gutter, clear of the safe area and the FootNav.
25
+ var MOBILE_POSITION_CLASSES = {
26
+ 'bottom-center': 'inset-x-0 bottom-[var(--dt-toast-mobile-offset,5rem)] px-4 pt-2 pb-safe items-stretch',
27
+ 'top-center': 'inset-x-0 top-2 px-4 pb-2 pt-safe items-stretch'
28
+ };
29
+ var PEEK_PX = 14; // how far each older toast shows behind the front one
30
+ var PEEK_SCALE = 0.05; // how much smaller each older toast is
31
+ /** Inline transform for a collapsed toast `depth` steps behind the front one. */
32
+ function collapsedStyle(depth, fromBottom, visibleToasts) {
33
+ return {
34
+ transform: "translateY(".concat((fromBottom ? -1 : 1) * depth * PEEK_PX, "px) scale(").concat(1 - depth * PEEK_SCALE, ")"),
35
+ transformOrigin: fromBottom ? 'bottom center' : 'top center',
36
+ zIndex: 1000 - depth,
37
+ opacity: depth >= visibleToasts ? 0 : 1
38
+ };
39
+ }
40
+ var ToastStack = function ToastStack(_ref) {
41
+ var _ref$toasts = _ref.toasts,
42
+ toasts = _ref$toasts === void 0 ? [] : _ref$toasts,
43
+ _ref$position = _ref.position,
44
+ position = _ref$position === void 0 ? 'top-right' : _ref$position,
45
+ onRemove = _ref.onRemove,
46
+ _ref$className = _ref.className,
47
+ className = _ref$className === void 0 ? '' : _ref$className,
48
+ expand = _ref.expand,
49
+ _ref$visibleToasts = _ref.visibleToasts,
50
+ visibleToasts = _ref$visibleToasts === void 0 ? 3 : _ref$visibleToasts,
51
+ _ref$mobilePosition = _ref.mobilePosition,
52
+ mobilePosition = _ref$mobilePosition === void 0 ? 'bottom-center' : _ref$mobilePosition,
53
+ mobileOffset = _ref.mobileOffset;
54
+ var listRef = useRef(null);
55
+ var _useState = useState(false),
56
+ _useState2 = _slicedToArray(_useState, 2),
57
+ hovered = _useState2[0],
58
+ setHovered = _useState2[1];
59
+ var _useState3 = useState(false),
60
+ _useState4 = _slicedToArray(_useState3, 2),
61
+ focused = _useState4[0],
62
+ setFocused = _useState4[1];
63
+ var _useState5 = useState(false),
64
+ _useState6 = _slicedToArray(_useState5, 2),
65
+ tapped = _useState6[0],
66
+ setTapped = _useState6[1];
67
+ var isPhone = usePresentation('auto') === 'sheet';
68
+ useClickOutside(listRef, function () {
69
+ return setTapped(false);
70
+ }, {
71
+ enabled: tapped
72
+ });
73
+ if (!toasts || toasts.length === 0) {
74
+ return null;
75
+ }
76
+ var mobile = Boolean(isPhone && MOBILE_POSITION_CLASSES[mobilePosition]);
77
+ var placement = mobile ? mobilePosition : position;
78
+ var fromBottom = placement.startsWith('bottom');
79
+ var posClass = mobile ? MOBILE_POSITION_CLASSES[mobilePosition] : ['p-2', POSITION_CLASSES[position] || POSITION_CLASSES['top-right']];
80
+ var count = toasts.length;
81
+ var limit = Math.max(1, Number(visibleToasts) || 3);
82
+ var collapsible = expand === true ? false : count > (expand === false ? 1 : limit);
83
+ var interacting = hovered || focused || tapped;
84
+ var collapsed = collapsible && !interacting;
85
+ var style = mobile && mobileOffset != null ? _defineProperty({}, MOBILE_OFFSET_VAR, toCssLength(mobileOffset)) : undefined;
86
+ return /*#__PURE__*/createPortal(jsx("div", {
87
+ role: "region",
88
+ "aria-label": "Notifications",
89
+ "data-expanded": collapsed ? 'false' : 'true',
90
+ className: cn('fixed z-toast flex flex-col max-h-[calc(100dvh-2rem)] pointer-events-none', collapsed ? 'overflow-visible' : 'overflow-y-auto overflow-x-hidden [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden', posClass, className),
91
+ style: style,
92
+ children: jsx("div", {
93
+ ref: listRef,
94
+ "data-toast-list": "",
95
+ className: cn(collapsed ? 'grid grid-cols-1 grid-rows-1' : 'flex flex-col gap-3', 'w-full', mobile ? '' : 'max-w-md'),
96
+ onMouseEnter: function onMouseEnter() {
97
+ return setHovered(true);
98
+ },
99
+ onMouseLeave: function onMouseLeave() {
100
+ return setHovered(false);
101
+ },
102
+ onFocus: function onFocus() {
103
+ return setFocused(true);
104
+ },
105
+ onBlur: function onBlur(e) {
106
+ if (!e.currentTarget.contains(e.relatedTarget)) setFocused(false);
107
+ },
108
+ onPointerDown: function onPointerDown(e) {
109
+ if (collapsible && e.pointerType && e.pointerType !== 'mouse') setTapped(true);
110
+ },
111
+ children: toasts.map(function (t, i) {
112
+ var depth = count - 1 - i;
113
+ return jsx("div", {
114
+ "data-toast-depth": depth,
115
+ className: cn('pointer-events-auto w-full', mobile ? 'max-w-none' : 'max-w-md', collapsible && 'transition-[transform,opacity] duration-base ease-standard motion-reduce:transition-none', collapsed && ['col-start-1 row-start-1', fromBottom ? 'self-end' : 'self-start'], collapsed && depth >= limit && 'pointer-events-none'),
116
+ style: collapsed ? collapsedStyle(depth, fromBottom, limit) : undefined,
117
+ children: jsx(Toast, _objectSpread2(_objectSpread2({}, t), {}, {
118
+ portal: false,
119
+ position: position,
120
+ paused: collapsible && interacting ? true : t.paused,
121
+ className: cn(mobile && 'max-w-none', t.className),
122
+ onClose: onRemove
123
+ }))
124
+ }, t.id);
125
+ })
126
+ })
127
+ }), document.body);
128
+ };
129
+
130
+ export { collapsedStyle, ToastStack as default };
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+ import { slicedToArray as _slicedToArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { useState } from 'react';
4
+ import { useSheetDrag } from '../../hooks/useSheetDrag.js';
5
+
6
+ // Internal (not exported). Horizontal swipe-to-dismiss for a Toast, built on
7
+ // the Sheet's pointer-drag core: a press only becomes a swipe past a small
8
+ // slop, so taps on the toast's buttons still click. Pair the root with
9
+ // `touch-pan-y` so vertical page scroll keeps working on touch screens.
10
+ var SWIPE_DISTANCE = 64; // px past which a release dismisses
11
+ var SWIPE_FLICK_VELOCITY = 0.5; // px per ms
12
+ var SWIPE_FLICK_MIN = 16; // px a flick must travel
13
+ /**
14
+ * @param {{ enabled?: boolean, onDismiss: (direction: 1 | -1) => void }} options
15
+ * @returns {{
16
+ * offset: number, // px to translate the toast by (0 at rest)
17
+ * dragging: boolean,
18
+ * swipedOut: 0 | 1 | -1, // direction the toast left in, 0 while it stays
19
+ * dragProps: object, // pointer handlers for the toast root
20
+ * }}
21
+ */
22
+ function useToastSwipe(_ref) {
23
+ var _ref$enabled = _ref.enabled,
24
+ enabled = _ref$enabled === void 0 ? true : _ref$enabled,
25
+ onDismiss = _ref.onDismiss;
26
+ var _useState = useState(0),
27
+ _useState2 = _slicedToArray(_useState, 2),
28
+ swipedOut = _useState2[0],
29
+ setSwipedOut = _useState2[1];
30
+ var onRelease = function onRelease(_ref2) {
31
+ var delta = _ref2.delta,
32
+ velocity = _ref2.velocity;
33
+ var flick = Math.abs(velocity) >= SWIPE_FLICK_VELOCITY && Math.abs(delta) > SWIPE_FLICK_MIN;
34
+ if (!flick && Math.abs(delta) < SWIPE_DISTANCE) return; // spring back
35
+ var direction = delta < 0 ? -1 : 1;
36
+ setSwipedOut(direction);
37
+ onDismiss(direction);
38
+ };
39
+ var drag = useSheetDrag({
40
+ edge: 'right',
41
+ enabled: enabled && swipedOut === 0,
42
+ onRelease: onRelease
43
+ });
44
+ return {
45
+ offset: drag.dragging ? drag.delta : 0,
46
+ dragging: drag.dragging,
47
+ swipedOut: swipedOut,
48
+ dragProps: drag.dragProps
49
+ };
50
+ }
51
+
52
+ export { SWIPE_DISTANCE, SWIPE_FLICK_VELOCITY, useToastSwipe };