@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
@@ -0,0 +1,494 @@
1
+ 'use client';
2
+ import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, toConsumableArray as _toConsumableArray, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import React, { useId, useRef, useState, useCallback, useMemo, useEffect, useSyncExternalStore, createContext } from 'react';
5
+ import { X } from 'lucide-react';
6
+ import { cn } from '../../utils/cn.js';
7
+ import { setRefs } from '../../utils/position.js';
8
+ import { TOUCH_TARGET } from '../../utils/touchTarget.js';
9
+ import Portal from '../utility/Portal.js';
10
+ import { getFocusable, useFocusTrap } from '../../hooks/useFocusTrap.js';
11
+ import { useScrollLock } from '../../hooks/useScrollLock.js';
12
+ import { usePresence } from '../../hooks/usePresence.js';
13
+ import { useReducedMotion } from '../../hooks/useReducedMotion.js';
14
+ import { useLatestRef } from '../../hooks/useLatestRef.js';
15
+ import { useSheetDrag, rubberBand, FLICK_VELOCITY } from '../../hooks/useSheetDrag.js';
16
+
17
+ var _excluded = ["open", "onClose", "placement", "snapPoints", "activeSnap", "defaultSnap", "onSnapChange", "dismissible", "dragEnabled", "handle", "scaleBackground", "initialFocus", "hasTitle", "hasDescription", "idPrefix", "testIdPrefix", "panelClassName", "handleBarClassName", "renderHeader", "children", "className", "style"];
18
+ // Internal (not exported from the package). The shared sheet core behind
19
+ // `Sheet` and `Drawer` (ADR 0001 §1): portal, backdrop, presence (enter/exit
20
+ // motion), drag to dismiss + snap points, focus trap, scroll lock,
21
+ // keyboard-aware sizing and the optional background scale. The public
22
+ // components only decide their chrome: panel classes, header and labels.
23
+ var SHEET_PLACEMENTS = ["bottom", "top", "left", "right"];
24
+ var EXIT_MS = 200; // matches `animate-sheet-out` / duration-base
25
+ var DISMISS_DISTANCE = 80; // px past the resting (or lowest) position
26
+ var FLICK_MIN_DISTANCE = 16; // px; a flick shorter than this is a tap
27
+ var UPWARD_STRETCH = 24; // px; rubber band limit when pulling a content-height sheet away from its edge
28
+ var VIEWPORT_GAP = 16; // px kept free above a full-height sheet (1rem)
29
+ // Off-screen resting transform for the enter/exit transition.
30
+ var OFFSCREEN = {
31
+ bottom: "translate-y-full",
32
+ top: "-translate-y-full",
33
+ right: "translate-x-full",
34
+ left: "-translate-x-full"
35
+ };
36
+ // Classes put on the consumer's [data-sheet-background] wrapper while open.
37
+ var BACKGROUND_CLASSES = ["origin-top", "scale-[0.94]", "rounded-sheet", "overflow-hidden", "transition-transform", "duration-slow", "ease-emphasized"];
38
+ var translateFor = function translateFor(side, px) {
39
+ if (!px) return undefined;
40
+ if (side === "bottom") return "translateY(".concat(px, "px)");
41
+ if (side === "top") return "translateY(".concat(-px, "px)");
42
+ if (side === "right") return "translateX(".concat(px, "px)");
43
+ return "translateX(".concat(-px, "px)");
44
+ };
45
+ function readViewport() {
46
+ if (typeof window === "undefined") return {
47
+ height: 0,
48
+ offset: 0
49
+ };
50
+ var inner = window.innerHeight || 0;
51
+ var vv = window.visualViewport;
52
+ if (!vv) return {
53
+ height: inner,
54
+ offset: 0
55
+ };
56
+ // `offset` is the part of the layout viewport the on-screen keyboard covers.
57
+ var offset = Math.max(0, Math.round(inner - vv.height - (vv.offsetTop || 0)));
58
+ return {
59
+ height: vv.height || inner,
60
+ offset: offset
61
+ };
62
+ }
63
+ var isTextEntry = function isTextEntry(el) {
64
+ return !!el && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName || ""));
65
+ };
66
+ var SERVER_VIEWPORT = {
67
+ height: 0,
68
+ offset: 0
69
+ };
70
+ var viewportCache = SERVER_VIEWPORT;
71
+ // Stable snapshot for useSyncExternalStore: a new object only when it changes.
72
+ function getViewportSnapshot() {
73
+ var next = readViewport();
74
+ if (next.height !== viewportCache.height || next.offset !== viewportCache.offset) viewportCache = next;
75
+ return viewportCache;
76
+ }
77
+ var getServerViewport = function getServerViewport() {
78
+ return SERVER_VIEWPORT;
79
+ };
80
+ /**
81
+ * Tracks the visual viewport (keyboard-aware) while `active`. On resize it
82
+ * also keeps a focused field inside `panel` scrolled into view.
83
+ */
84
+ function useViewport(active, panel) {
85
+ var subscribe = useCallback(function (onChange) {
86
+ var _vv$addEventListener, _vv$addEventListener2;
87
+ if (!active || typeof window === "undefined") return function () {};
88
+ var vv = window.visualViewport;
89
+ var update = function update() {
90
+ onChange();
91
+ var focused = document.activeElement;
92
+ if (isTextEntry(focused) && panel !== null && panel !== void 0 && panel.contains(focused)) {
93
+ var _focused$scrollIntoVi;
94
+ (_focused$scrollIntoVi = focused.scrollIntoView) === null || _focused$scrollIntoVi === void 0 || _focused$scrollIntoVi.call(focused, {
95
+ block: "nearest"
96
+ });
97
+ }
98
+ };
99
+ vv === null || vv === void 0 || (_vv$addEventListener = vv.addEventListener) === null || _vv$addEventListener === void 0 || _vv$addEventListener.call(vv, "resize", update);
100
+ vv === null || vv === void 0 || (_vv$addEventListener2 = vv.addEventListener) === null || _vv$addEventListener2 === void 0 || _vv$addEventListener2.call(vv, "scroll", update);
101
+ window.addEventListener("resize", update);
102
+ return function () {
103
+ var _vv$removeEventListen, _vv$removeEventListen2;
104
+ vv === null || vv === void 0 || (_vv$removeEventListen = vv.removeEventListener) === null || _vv$removeEventListen === void 0 || _vv$removeEventListen.call(vv, "resize", update);
105
+ vv === null || vv === void 0 || (_vv$removeEventListen2 = vv.removeEventListener) === null || _vv$removeEventListen2 === void 0 || _vv$removeEventListen2.call(vv, "scroll", update);
106
+ window.removeEventListener("resize", update);
107
+ };
108
+ }, [active, panel]);
109
+ return useSyncExternalStore(subscribe, getViewportSnapshot, getServerViewport);
110
+ }
111
+ /** Opt-in iOS-style background scale (ADR 0001 §4). No-op under reduced motion. */
112
+ function useScaleBackground(active) {
113
+ useEffect(function () {
114
+ var _el$classList;
115
+ if (!active || typeof document === "undefined") return undefined;
116
+ var el = document.querySelector("[data-sheet-background]");
117
+ if (!el) return undefined;
118
+ var added = BACKGROUND_CLASSES.filter(function (c) {
119
+ return !el.classList.contains(c);
120
+ });
121
+ (_el$classList = el.classList).add.apply(_el$classList, _toConsumableArray(added));
122
+ el.setAttribute("data-sheet-scaled", "true");
123
+ return function () {
124
+ var _el$classList2;
125
+ (_el$classList2 = el.classList).remove.apply(_el$classList2, _toConsumableArray(added));
126
+ el.removeAttribute("data-sheet-scaled");
127
+ };
128
+ }, [active]);
129
+ }
130
+ /** Calls the consumer's handler first, then ours. */
131
+ function mergeHandlers(ours, theirs) {
132
+ var merged = {};
133
+ Object.keys(ours).forEach(function (key) {
134
+ merged[key] = function (e) {
135
+ var _theirs$key;
136
+ (_theirs$key = theirs[key]) === null || _theirs$key === void 0 || _theirs$key.call(theirs, e);
137
+ ours[key](e);
138
+ };
139
+ });
140
+ return merged;
141
+ }
142
+ /**
143
+ * Context for parts rendered inside the core: drag handlers for the grab zone
144
+ * (header) and the scrolling body, ids, and `requestClose(reason)`.
145
+ */
146
+ var SheetContext = /*#__PURE__*/createContext(null);
147
+ /**
148
+ * The shared sheet core. Internal: `Sheet` and `Drawer` wrap it.
149
+ *
150
+ * Beyond Sheet's own props it takes the chrome its wrappers vary:
151
+ * - `dragEnabled` (default true): turns the drag gesture on.
152
+ * - `hasTitle` / `hasDescription`: wire `aria-labelledby` / `aria-describedby`.
153
+ * - `idPrefix`, `testIdPrefix`: ids (`<prefix>-title-…`) and test ids
154
+ * (`<prefix>-backdrop`, `<prefix>-handle`).
155
+ * - `panelClassName`: base + placement + size classes for the panel.
156
+ * - `handleBarClassName`: the grab handle's bar.
157
+ * - `renderHeader({ titleId, descriptionId, requestClose, showHandle, side })`:
158
+ * rendered before `children`, inside the context.
159
+ */
160
+ var SheetCore = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
161
+ var open = _ref.open,
162
+ onClose = _ref.onClose,
163
+ _ref$placement = _ref.placement,
164
+ placement = _ref$placement === void 0 ? "bottom" : _ref$placement,
165
+ snapPoints = _ref.snapPoints,
166
+ activeSnap = _ref.activeSnap,
167
+ _ref$defaultSnap = _ref.defaultSnap,
168
+ defaultSnap = _ref$defaultSnap === void 0 ? 0 : _ref$defaultSnap,
169
+ onSnapChange = _ref.onSnapChange,
170
+ _ref$dismissible = _ref.dismissible,
171
+ dismissible = _ref$dismissible === void 0 ? true : _ref$dismissible,
172
+ _ref$dragEnabled = _ref.dragEnabled,
173
+ dragEnabled = _ref$dragEnabled === void 0 ? true : _ref$dragEnabled,
174
+ handle = _ref.handle,
175
+ _ref$scaleBackground = _ref.scaleBackground,
176
+ scaleBackground = _ref$scaleBackground === void 0 ? false : _ref$scaleBackground,
177
+ initialFocus = _ref.initialFocus,
178
+ _ref$hasTitle = _ref.hasTitle,
179
+ hasTitle = _ref$hasTitle === void 0 ? false : _ref$hasTitle,
180
+ _ref$hasDescription = _ref.hasDescription,
181
+ hasDescription = _ref$hasDescription === void 0 ? false : _ref$hasDescription,
182
+ _ref$idPrefix = _ref.idPrefix,
183
+ idPrefix = _ref$idPrefix === void 0 ? "sheet" : _ref$idPrefix,
184
+ _ref$testIdPrefix = _ref.testIdPrefix,
185
+ testIdPrefix = _ref$testIdPrefix === void 0 ? "sheet" : _ref$testIdPrefix,
186
+ panelClassName = _ref.panelClassName,
187
+ _ref$handleBarClassNa = _ref.handleBarClassName,
188
+ handleBarClassName = _ref$handleBarClassNa === void 0 ? "bg-muted/40" : _ref$handleBarClassNa,
189
+ renderHeader = _ref.renderHeader,
190
+ children = _ref.children,
191
+ className = _ref.className,
192
+ style = _ref.style,
193
+ props = _objectWithoutProperties(_ref, _excluded);
194
+ var shown = Boolean(open);
195
+ var side = SHEET_PLACEMENTS.includes(placement) ? placement : "bottom";
196
+ var vertical = side === "bottom" || side === "top";
197
+ var snaps = vertical && Array.isArray(snapPoints) && snapPoints.length > 0 ? snapPoints : null;
198
+ var showHandle = handle !== null && handle !== void 0 ? handle : side === "bottom";
199
+ var id = useId();
200
+ var titleId = "".concat(idPrefix, "-title-").concat(id);
201
+ var descriptionId = "".concat(idPrefix, "-description-").concat(id);
202
+ var panelRef = useRef(null);
203
+ var _useState = useState(null),
204
+ _useState2 = _slicedToArray(_useState, 2),
205
+ bodyEl = _useState2[0],
206
+ setBodyEl = _useState2[1];
207
+ var _useState3 = useState(false),
208
+ _useState4 = _slicedToArray(_useState3, 2),
209
+ closedByDrag = _useState4[0],
210
+ setClosedByDrag = _useState4[1];
211
+ // The panel node, once the Portal has rendered it (never on the server).
212
+ // Focus management waits for it.
213
+ var _useState5 = useState(null),
214
+ _useState6 = _slicedToArray(_useState5, 2),
215
+ panelEl = _useState6[0],
216
+ setPanelEl = _useState6[1];
217
+ var onCloseRef = useLatestRef(onClose);
218
+ var reducedMotion = useReducedMotion();
219
+ var presence = usePresence(shown, {
220
+ duration: EXIT_MS
221
+ });
222
+ var panelCallbackRef = useCallback(function (node) {
223
+ return setRefs(node, panelRef, ref, setPanelEl);
224
+ }, [ref]);
225
+ var ready = panelEl != null;
226
+ var visible = presence.mounted;
227
+ // Snap index: controlled via `activeSnap`, else internal (reset on reopen).
228
+ var _useState7 = useState(defaultSnap),
229
+ _useState8 = _slicedToArray(_useState7, 2),
230
+ internalSnap = _useState8[0],
231
+ setInternalSnap = _useState8[1];
232
+ var _useState9 = useState(shown),
233
+ _useState0 = _slicedToArray(_useState9, 2),
234
+ prevShown = _useState0[0],
235
+ setPrevShown = _useState0[1];
236
+ var _useState1 = useState(false),
237
+ _useState10 = _slicedToArray(_useState1, 2),
238
+ entered = _useState10[0],
239
+ setEntered = _useState10[1];
240
+ if (prevShown !== shown) {
241
+ setPrevShown(shown);
242
+ if (shown) {
243
+ setInternalSnap(defaultSnap);
244
+ setClosedByDrag(false);
245
+ } else {
246
+ setEntered(false);
247
+ }
248
+ }
249
+ var rawSnap = activeSnap !== null && activeSnap !== void 0 ? activeSnap : internalSnap;
250
+ var snapIndex = snaps ? Math.min(Math.max(0, Number(rawSnap) || 0), snaps.length - 1) : 0;
251
+ var setSnap = function setSnap(next) {
252
+ if (!snaps || next === snapIndex || next < 0 || next >= snaps.length) return;
253
+ if (activeSnap === undefined) setInternalSnap(next);
254
+ onSnapChange === null || onSnapChange === void 0 || onSnapChange(next);
255
+ };
256
+ var requestClose = function requestClose(reason) {
257
+ var _onCloseRef$current;
258
+ setClosedByDrag(reason === "drag");
259
+ (_onCloseRef$current = onCloseRef.current) === null || _onCloseRef$current === void 0 || _onCloseRef$current.call(onCloseRef, reason);
260
+ };
261
+ var viewport = useViewport(ready, panelEl);
262
+ var vh = viewport.height;
263
+ var cap = Math.max(0, vh - VIEWPORT_GAP);
264
+ var heights = snaps ? snaps.map(function (f) {
265
+ return Math.min(cap, Math.max(0, Number(f) || 0) * vh);
266
+ }) : null;
267
+ var minHeight = heights ? Math.min.apply(Math, _toConsumableArray(heights)) : 0;
268
+ var maxHeight = heights ? Math.max.apply(Math, _toConsumableArray(heights)) : 0;
269
+ // Snap indexes ordered from smallest to largest height.
270
+ var order = heights ? heights.map(function (h, i) {
271
+ return [h, i];
272
+ }).sort(function (a, b) {
273
+ return a[0] - b[0];
274
+ }).map(function (_ref2) {
275
+ var _ref3 = _slicedToArray(_ref2, 2),
276
+ i = _ref3[1];
277
+ return i;
278
+ }) : [];
279
+ var panelSize = function panelSize() {
280
+ var _panelEl$getBoundingC;
281
+ var rect = panelEl === null || panelEl === void 0 || (_panelEl$getBoundingC = panelEl.getBoundingClientRect) === null || _panelEl$getBoundingC === void 0 ? void 0 : _panelEl$getBoundingC.call(panelEl);
282
+ var size = rect ? vertical ? rect.height : rect.width : 0;
283
+ return size > 0 ? size : DISMISS_DISTANCE * 2;
284
+ };
285
+ var onRelease = function onRelease(_ref4) {
286
+ var delta = _ref4.delta,
287
+ velocity = _ref4.velocity;
288
+ var flick = velocity >= FLICK_VELOCITY && delta > FLICK_MIN_DISTANCE;
289
+ if (!heights) {
290
+ var threshold = Math.min(DISMISS_DISTANCE, panelSize() / 2);
291
+ if (dismissible && (flick || delta >= threshold)) requestClose("drag");
292
+ return; // otherwise the sheet springs back to rest
293
+ }
294
+ var target = heights[snapIndex] - delta;
295
+ var below = minHeight - target;
296
+ if (dismissible && (flick || below >= Math.min(DISMISS_DISTANCE, minHeight / 2))) {
297
+ requestClose("drag");
298
+ return;
299
+ }
300
+ var nearest = snapIndex;
301
+ heights.forEach(function (h, i) {
302
+ if (Math.abs(h - target) < Math.abs(heights[nearest] - target)) nearest = i;
303
+ });
304
+ setSnap(nearest);
305
+ };
306
+ var canDrag = dragEnabled && ready && shown;
307
+ var drag = useSheetDrag({
308
+ edge: side,
309
+ enabled: canDrag,
310
+ onRelease: onRelease,
311
+ bodyEl: bodyEl
312
+ });
313
+ // Where the panel sits while dragging: height (snap sheets) + translate.
314
+ var height = heights ? heights[snapIndex] : undefined;
315
+ var translate = 0;
316
+ if (drag.dragging) {
317
+ var d = drag.delta;
318
+ if (heights) {
319
+ var target = heights[snapIndex] - d;
320
+ if (target > maxHeight) {
321
+ height = maxHeight + rubberBand(target - maxHeight, vh || maxHeight);
322
+ } else if (target < minHeight) {
323
+ height = minHeight;
324
+ translate = dismissible ? minHeight - target : rubberBand(minHeight - target, minHeight);
325
+ } else {
326
+ height = target;
327
+ }
328
+ } else if (d > 0) {
329
+ translate = dismissible ? d : rubberBand(d, panelSize());
330
+ } else {
331
+ translate = -rubberBand(-d, UPWARD_STRETCH);
332
+ }
333
+ }
334
+ useScrollLock(shown);
335
+ var focusTarget = useMemo(function () {
336
+ return {
337
+ get current() {
338
+ var _getFocusable$find;
339
+ if (initialFocus !== null && initialFocus !== void 0 && initialFocus.current) return initialFocus.current;
340
+ var panel = panelRef.current;
341
+ return (_getFocusable$find = getFocusable(panel).find(function (el) {
342
+ return !el.hasAttribute("data-sheet-handle");
343
+ })) !== null && _getFocusable$find !== void 0 ? _getFocusable$find : panel;
344
+ }
345
+ };
346
+ }, [initialFocus]);
347
+ useFocusTrap(panelRef, {
348
+ active: shown && ready,
349
+ initialFocusRef: focusTarget,
350
+ onEscape: function onEscape() {
351
+ if (dismissible) requestClose("escape");
352
+ }
353
+ });
354
+ useScaleBackground(scaleBackground && shown && ready && !reducedMotion);
355
+ // Transform-based enter for top/left/right (bottom uses animate-sheet-in):
356
+ // render off-screen once, then let the transition bring it in.
357
+ useEffect(function () {
358
+ if (!ready || !shown || entered) return undefined;
359
+ if (typeof window.requestAnimationFrame !== "function") {
360
+ var timer = setTimeout(function () {
361
+ return setEntered(true);
362
+ }, 16);
363
+ return function () {
364
+ return clearTimeout(timer);
365
+ };
366
+ }
367
+ var frame = window.requestAnimationFrame(function () {
368
+ return setEntered(true);
369
+ });
370
+ return function () {
371
+ var _window$cancelAnimati, _window;
372
+ return (_window$cancelAnimati = (_window = window).cancelAnimationFrame) === null || _window$cancelAnimati === void 0 ? void 0 : _window$cancelAnimati.call(_window, frame);
373
+ };
374
+ }, [ready, shown, entered]);
375
+ var exiting = presence.state === "exiting";
376
+ var useKeyframes = side === "bottom" && !closedByDrag;
377
+ var motionClass = "";
378
+ if (!reducedMotion) {
379
+ if (side === "bottom" && presence.state === "entering") motionClass = "animate-sheet-in motion-reduce:animate-none";else if (exiting && useKeyframes) motionClass = "animate-sheet-out motion-reduce:animate-none";else if (exiting || side !== "bottom" && !entered) motionClass = OFFSCREEN[side];
380
+ }
381
+ var panelStyle = _objectSpread2({}, style);
382
+ if (height !== undefined) panelStyle.height = "".concat(height, "px");
383
+ var transform = translateFor(side, translate);
384
+ if (transform) panelStyle.transform = transform;
385
+ if (viewport.offset > 0) {
386
+ var room = "calc(".concat(vh, "px - env(safe-area-inset-top, 0px) - 1rem)");
387
+ if (side === "bottom") {
388
+ panelStyle.bottom = "".concat(viewport.offset, "px");
389
+ panelStyle.maxHeight = room;
390
+ } else if (side === "top") {
391
+ panelStyle.maxHeight = room;
392
+ } else {
393
+ panelStyle.height = "".concat(vh, "px");
394
+ }
395
+ }
396
+ var onHandleKeyDown = function onHandleKeyDown(e) {
397
+ if (!snaps) return;
398
+ var grow = side === "bottom" ? "ArrowUp" : "ArrowDown";
399
+ var shrink = side === "bottom" ? "ArrowDown" : "ArrowUp";
400
+ if (e.key !== grow && e.key !== shrink) return;
401
+ e.preventDefault();
402
+ var pos = order.indexOf(snapIndex);
403
+ var next = order[pos + (e.key === grow ? 1 : -1)];
404
+ if (next !== undefined) setSnap(next);
405
+ };
406
+ var grabClass = canDrag ? "touch-none cursor-grab" : "";
407
+ var context = {
408
+ titleId: titleId,
409
+ descriptionId: descriptionId,
410
+ grabClass: grabClass,
411
+ headerDragProps: drag.dragProps,
412
+ bodyDragProps: drag.bodyDragProps,
413
+ setBodyEl: setBodyEl,
414
+ requestClose: requestClose
415
+ };
416
+ var handleBar = jsx("span", {
417
+ "aria-hidden": "true",
418
+ className: cn("h-1.5 w-10 rounded-pill", handleBarClassName)
419
+ });
420
+ var handleNode = showHandle ? snaps ? jsx("button", _objectSpread2(_objectSpread2({
421
+ type: "button",
422
+ "aria-label": "Resize sheet",
423
+ "aria-keyshortcuts": "ArrowUp ArrowDown",
424
+ "data-sheet-handle": "",
425
+ "data-testid": "".concat(testIdPrefix, "-handle"),
426
+ onKeyDown: onHandleKeyDown
427
+ }, drag.dragProps), {}, {
428
+ className: cn("flex w-full shrink-0 justify-center pb-1 pt-3 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500", side === "top" && "pb-3 pt-1", grabClass),
429
+ children: handleBar
430
+ })) : jsx("div", _objectSpread2(_objectSpread2({
431
+ "aria-hidden": "true",
432
+ "data-sheet-handle": "",
433
+ "data-testid": "".concat(testIdPrefix, "-handle")
434
+ }, drag.dragProps), {}, {
435
+ className: cn("flex shrink-0 justify-center pb-1 pt-3", side === "top" && "pb-3 pt-1", grabClass),
436
+ children: handleBar
437
+ })) : null;
438
+ return jsx(Portal, {
439
+ children: visible && jsx(SheetContext.Provider, {
440
+ value: context,
441
+ children: jsxs("div", {
442
+ className: cn("fixed inset-0 z-modal", exiting && "pointer-events-none"),
443
+ children: [jsx("div", {
444
+ "aria-hidden": "true",
445
+ "data-testid": "".concat(testIdPrefix, "-backdrop"),
446
+ className: cn("absolute inset-0 bg-black/50 motion-reduce:animate-none", exiting ? "animate-fade-out" : "animate-fade-in"),
447
+ onClick: function onClick() {
448
+ return dismissible && requestClose("backdrop");
449
+ }
450
+ }), jsxs("div", _objectSpread2(_objectSpread2({
451
+ ref: panelCallbackRef,
452
+ role: "dialog",
453
+ "aria-modal": "true",
454
+ "aria-labelledby": hasTitle ? titleId : undefined,
455
+ "aria-describedby": hasDescription ? descriptionId : undefined,
456
+ tabIndex: -1,
457
+ "data-placement": side,
458
+ "data-state": presence.state,
459
+ "data-snap": snaps ? snapIndex : undefined,
460
+ "data-dragging": drag.dragging ? "" : undefined,
461
+ className: cn("absolute flex flex-col overflow-hidden shadow-overlay focus:outline-none", panelClassName, !drag.dragging && "transition-[transform,height] duration-base ease-standard motion-reduce:transition-none", motionClass, className),
462
+ style: panelStyle
463
+ }, props), {}, {
464
+ children: [side !== "top" && handleNode, renderHeader === null || renderHeader === void 0 ? void 0 : renderHeader({
465
+ titleId: titleId,
466
+ descriptionId: descriptionId,
467
+ requestClose: requestClose,
468
+ showHandle: showHandle,
469
+ side: side
470
+ }), children, side === "top" && handleNode]
471
+ }))]
472
+ })
473
+ })
474
+ });
475
+ });
476
+ SheetCore.displayName = "SheetCore";
477
+ /** The shared close (X) button: token colours, 44×44px touch target on coarse pointers. */
478
+ var SheetCloseButton = function SheetCloseButton(_ref5) {
479
+ var onClick = _ref5.onClick,
480
+ label = _ref5.label,
481
+ className = _ref5.className;
482
+ return jsx("button", {
483
+ type: "button",
484
+ onClick: onClick,
485
+ "aria-label": label,
486
+ className: cn("inline-flex shrink-0 items-center justify-center rounded-control p-1 text-muted", "hover:bg-line/50 hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500", TOUCH_TARGET, className),
487
+ children: jsx(X, {
488
+ className: "h-5 w-5",
489
+ "aria-hidden": "true"
490
+ })
491
+ });
492
+ };
493
+
494
+ export { SHEET_PLACEMENTS, SheetCloseButton, SheetContext, SheetCore, mergeHandlers };
@@ -44,7 +44,7 @@ var Dropdown = function Dropdown(_ref) {
44
44
  },
45
45
  children: trigger
46
46
  }), isOpen && jsx("div", {
47
- className: "absolute z-50 bg-surface text-foreground border border-line rounded-md shadow-lg ".concat(placementClasses[placement], " min-w-48"),
47
+ className: "absolute z-dropdown bg-surface text-foreground border border-line rounded-md shadow-lg ".concat(placementClasses[placement], " min-w-48"),
48
48
  children: children
49
49
  })]
50
50
  }));