prime-ui-kit 0.9.1 → 0.9.2

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 (107) hide show
  1. package/README.md +22 -8
  2. package/dist/chunks/{chunk-KCQFOORX.js → chunk-IQELQNMR.js} +1 -1
  3. package/dist/chunks/{chunk-DB2Y3XXA.js → chunk-LXGRKN34.js} +2323 -1500
  4. package/dist/chunks/{chunk-NHOWNIAR.js → chunk-ZEFCDEEQ.js} +790 -536
  5. package/dist/color-picker.js +2 -2
  6. package/dist/components/data-table/DataTable.d.ts +6 -1
  7. package/dist/components/data-table/types.d.ts +5 -0
  8. package/dist/components/dnd/Dnd.d.ts +1 -1
  9. package/dist/components/dnd/dragSession.d.ts +9 -0
  10. package/dist/components/dnd/useDropTarget.d.ts +5 -0
  11. package/dist/components/dnd/useFlipList.d.ts +3 -3
  12. package/dist/components/drawer/Drawer.d.ts +8 -5
  13. package/dist/components/dropdown/Dropdown.d.ts +17 -0
  14. package/dist/components/index.d.ts +5 -1
  15. package/dist/components/kanban/Kanban.d.ts +129 -0
  16. package/dist/components/modal/Modal.d.ts +5 -2
  17. package/dist/components/page-toolbar/PageToolbar.d.ts +53 -0
  18. package/dist/components/segmented-control/SegmentedControl.d.ts +5 -2
  19. package/dist/components/tabs/Tabs.d.ts +5 -2
  20. package/dist/hooks/useEdgeOverflow.d.ts +12 -0
  21. package/dist/hooks/useMediaQuery.d.ts +7 -0
  22. package/dist/hooks/useSwipeDismiss.d.ts +34 -0
  23. package/dist/index.css +2271 -1163
  24. package/dist/index.js +10 -2
  25. package/dist/internal/overlay/FloatingPanel.d.ts +3 -1
  26. package/dist/internal/overlay/useFloatingLayer.d.ts +11 -1
  27. package/dist/internal/touchTarget.d.ts +4 -0
  28. package/dist/layout/app-header/AppHeader.d.ts +110 -0
  29. package/dist/layout/app-shell/AppShell.d.ts +14 -9
  30. package/dist/layout/bottom-nav/BottomNav.d.ts +80 -0
  31. package/dist/layout/index.d.ts +5 -1
  32. package/dist/tokens/primitives.d.ts +4 -0
  33. package/dist/tokens/semantic.d.ts +56 -0
  34. package/dist/tokens/themes/dark.d.ts +4 -0
  35. package/package.json +3 -2
  36. package/src/components/accordion/COMPONENT.md +1 -1
  37. package/src/components/badge/COMPONENT.md +2 -2
  38. package/src/components/banner/COMPONENT.md +1 -1
  39. package/src/components/checkbox/examples/examples.module.css +4 -2
  40. package/src/components/crossfade/COMPONENT.md +1 -1
  41. package/src/components/data-table/COMPONENT.md +19 -6
  42. package/src/components/data-table/examples/columns-visibility.tsx +167 -0
  43. package/src/components/digit-input/COMPONENT.md +10 -10
  44. package/src/components/digit-input/examples/examples.module.css +8 -0
  45. package/src/components/digit-input/examples/in-form.tsx +2 -5
  46. package/src/components/digit-input/examples/sizes.tsx +1 -1
  47. package/src/components/divider/COMPONENT.md +1 -1
  48. package/src/components/dnd/COMPONENT.md +3 -3
  49. package/src/components/drawer/COMPONENT.md +17 -9
  50. package/src/components/drawer/examples/date-sheet.tsx +41 -0
  51. package/src/components/drawer/examples/examples.module.css +5 -0
  52. package/src/components/drawer/examples/placement.tsx +4 -2
  53. package/src/components/dropdown/COMPONENT.md +19 -5
  54. package/src/components/dropdown/examples/checkbox-items.tsx +48 -0
  55. package/src/components/empty-page/COMPONENT.md +1 -1
  56. package/src/components/kanban/COMPONENT.md +181 -0
  57. package/src/components/kanban/examples/controlled.tsx +78 -0
  58. package/src/components/kanban/examples/examples.module.css +31 -0
  59. package/src/components/kanban/examples/limits.tsx +58 -0
  60. package/src/components/kanban/examples/narrow.tsx +76 -0
  61. package/src/components/kanban/examples/overview.tsx +130 -0
  62. package/src/components/kanban/examples/states.tsx +75 -0
  63. package/src/components/kanban/examples/structure.tsx +76 -0
  64. package/src/components/login-form/COMPONENT.md +1 -1
  65. package/src/components/modal/COMPONENT.md +9 -6
  66. package/src/components/notification/COMPONENT.md +2 -2
  67. package/src/components/page-content/COMPONENT.md +1 -1
  68. package/src/components/page-toolbar/COMPONENT.md +142 -0
  69. package/src/components/page-toolbar/examples/examples.module.css +16 -0
  70. package/src/components/page-toolbar/examples/narrow.tsx +103 -0
  71. package/src/components/page-toolbar/examples/overview.tsx +113 -0
  72. package/src/components/page-toolbar/examples/save-changes.tsx +40 -0
  73. package/src/components/page-toolbar/examples/without-search.tsx +60 -0
  74. package/src/components/popover/COMPONENT.md +4 -3
  75. package/src/components/progress-bar/COMPONENT.md +1 -1
  76. package/src/components/progress-circle/COMPONENT.md +1 -1
  77. package/src/components/scroll-container/COMPONENT.md +1 -1
  78. package/src/components/segmented-control/COMPONENT.md +8 -8
  79. package/src/components/segmented-control/examples/full-width.tsx +1 -1
  80. package/src/components/select/COMPONENT.md +2 -1
  81. package/src/components/skeleton/COMPONENT.md +1 -1
  82. package/src/components/smart-filter/COMPONENT.md +2 -0
  83. package/src/components/spinner/COMPONENT.md +1 -1
  84. package/src/components/tabs/COMPONENT.md +11 -8
  85. package/src/components/tabs/examples/closable.tsx +1 -1
  86. package/src/layout/app-header/COMPONENT.md +178 -0
  87. package/src/layout/app-header/examples/breadcrumbs.tsx +36 -0
  88. package/src/layout/app-header/examples/examples.module.css +47 -0
  89. package/src/layout/app-header/examples/in-app-shell.tsx +70 -0
  90. package/src/layout/app-header/examples/narrow.tsx +29 -0
  91. package/src/layout/app-header/examples/overview.tsx +36 -0
  92. package/src/layout/app-shell/COMPONENT.md +27 -21
  93. package/src/layout/app-shell/examples/examples.module.css +15 -0
  94. package/src/layout/app-shell/examples/footer.tsx +59 -0
  95. package/src/layout/app-shell/examples/overview.tsx +19 -8
  96. package/src/layout/bottom-nav/COMPONENT.md +153 -0
  97. package/src/layout/bottom-nav/examples/examples.module.css +39 -0
  98. package/src/layout/bottom-nav/examples/floating.tsx +89 -0
  99. package/src/layout/bottom-nav/examples/icon-only.tsx +41 -0
  100. package/src/layout/bottom-nav/examples/in-app-shell.tsx +64 -0
  101. package/src/layout/bottom-nav/examples/overview.tsx +44 -0
  102. package/src/layout/bottom-nav/examples/router.tsx +31 -0
  103. package/src/layout/bottom-nav/examples/structure.tsx +47 -0
  104. package/src/layout/sidebar/COMPONENT.md +11 -10
  105. package/src/styles/theme-dark.css +3 -0
  106. package/src/styles/theme-light.css +24 -0
  107. package/src/styles/tokens.css +2 -0
@@ -15,11 +15,137 @@ function useControlSize(sizeProp) {
15
15
  return sizeProp ?? host ?? "m";
16
16
  }
17
17
 
18
- // src/components/scroll-container/ScrollContainer.tsx
18
+ // src/components/spinner/Spinner.tsx
19
+ import * as React2 from "react";
20
+
21
+ // src/internal/cx.ts
22
+ function cx(...classNames) {
23
+ return classNames.filter(Boolean).join(" ");
24
+ }
25
+
26
+ // src/internal/data-attributes.ts
27
+ function toDataAttributes(input) {
28
+ const result = {};
29
+ for (const [key, value] of Object.entries(input)) {
30
+ if (value === void 0) {
31
+ continue;
32
+ }
33
+ const attributeName = `data-${key}`;
34
+ result[attributeName] = typeof value === "boolean" ? String(value) : `${value}`;
35
+ }
36
+ return result;
37
+ }
38
+
39
+ // src/internal/iconBox.module.css
40
+ var iconBox_default = {
41
+ box: "iconBox_box",
42
+ xs: "iconBox_xs",
43
+ s: "iconBox_s",
44
+ m: "iconBox_m",
45
+ l: "iconBox_l",
46
+ xl: "iconBox_xl",
47
+ inherit: "iconBox_inherit"
48
+ };
49
+
50
+ // src/internal/iconBox.ts
51
+ function iconBoxClass(size, tier) {
52
+ return cx(iconBox_default.box, iconBox_default[size ?? tier ?? "m"], size === void 0 && iconBox_default.inherit);
53
+ }
54
+
55
+ // src/internal/textTone.module.css
56
+ var textTone_default = {
57
+ tone: "textTone_tone"
58
+ };
59
+
60
+ // src/internal/VisuallyHidden.module.css
61
+ var VisuallyHidden_default = {
62
+ root: "VisuallyHidden_root"
63
+ };
64
+
65
+ // src/internal/VisuallyHidden.tsx
66
+ import { jsx as jsx2 } from "react/jsx-runtime";
67
+ var visuallyHiddenClass = VisuallyHidden_default.root;
68
+ function VisuallyHidden({ className, ...rest }) {
69
+ return /* @__PURE__ */ jsx2("span", { className: cx(VisuallyHidden_default.root, className), ...rest });
70
+ }
71
+
72
+ // src/components/spinner/Spinner.module.css
73
+ var Spinner_default = {
74
+ root: "Spinner_root",
75
+ ring: "Spinner_ring",
76
+ primeSpinnerTurn: "Spinner_primeSpinnerTurn"
77
+ };
78
+
79
+ // src/components/spinner/Spinner.tsx
80
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
81
+ var SPINNER_LABELS = {
82
+ loading: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430"
83
+ };
84
+ function Spinner({
85
+ size: sizeProp,
86
+ tone = "default",
87
+ labels: labelsProp,
88
+ className,
89
+ ...rest
90
+ }) {
91
+ const controlSize = useOptionalControlSize();
92
+ const labels = React2.useMemo(() => ({ ...SPINNER_LABELS, ...labelsProp }), [labelsProp]);
93
+ const size = sizeProp ?? controlSize ?? "m";
94
+ return /* @__PURE__ */ jsxs(
95
+ "span",
96
+ {
97
+ role: "status",
98
+ className: cx(Spinner_default.root, iconBoxClass(sizeProp, controlSize), textTone_default.tone, className),
99
+ ...toDataAttributes({ size, tone: tone === "default" ? void 0 : tone }),
100
+ ...rest,
101
+ children: [
102
+ /* @__PURE__ */ jsx3("span", { className: Spinner_default.ring, "aria-hidden": "true" }),
103
+ /* @__PURE__ */ jsx3(VisuallyHidden, { children: labels.loading })
104
+ ]
105
+ }
106
+ );
107
+ }
108
+
109
+ // src/internal/fieldSurface.module.css
110
+ var fieldSurface_default = {
111
+ surface: "fieldSurface_surface"
112
+ };
113
+
114
+ // src/internal/fieldTier.module.css
115
+ var fieldTier_default = {
116
+ tier: "fieldTier_tier"
117
+ };
118
+
119
+ // src/internal/fieldTrigger.module.css
120
+ var fieldTrigger_default = {
121
+ trigger: "fieldTrigger_trigger"
122
+ };
123
+
124
+ // src/internal/fieldClasses.ts
125
+ var fieldSurfaceClass = fieldSurface_default.surface;
126
+ var fieldTierClass = fieldTier_default.tier;
127
+ var fieldTriggerClass = `${fieldTier_default.tier} ${fieldSurface_default.surface} ${fieldTrigger_default.trigger}`;
128
+
129
+ // src/internal/iconLayout.ts
19
130
  import * as React3 from "react";
131
+ function iconLayout(children, iconType) {
132
+ const content = React3.Children.toArray(children).filter(
133
+ (child) => !(typeof child === "string" && child.trim() === "")
134
+ );
135
+ const isIcon = (child) => React3.isValidElement(child) && child.type === iconType;
136
+ const iconOnly = content.length > 0 && content.every(isIcon);
137
+ return {
138
+ iconOnly,
139
+ leadingIcon: !iconOnly && content.length > 0 && isIcon(content[0]),
140
+ trailingIcon: !iconOnly && content.length > 0 && isIcon(content[content.length - 1])
141
+ };
142
+ }
143
+
144
+ // src/internal/slot.tsx
145
+ import * as React5 from "react";
20
146
 
21
147
  // src/hooks/useMergedRefs.ts
22
- import * as React2 from "react";
148
+ import * as React4 from "react";
23
149
 
24
150
  // src/internal/mergeRefs.ts
25
151
  function mergeRefs(...refs) {
@@ -37,144 +163,182 @@ function mergeRefs(...refs) {
37
163
 
38
164
  // src/hooks/useMergedRefs.ts
39
165
  function useMergedRefs(...refs) {
40
- return React2.useMemo(() => mergeRefs(...refs), refs);
41
- }
42
-
43
- // src/internal/cx.ts
44
- function cx(...classNames) {
45
- return classNames.filter(Boolean).join(" ");
166
+ return React4.useMemo(() => mergeRefs(...refs), refs);
46
167
  }
47
168
 
48
- // src/internal/data-attributes.ts
49
- function toDataAttributes(input) {
50
- const result = {};
51
- for (const [key, value] of Object.entries(input)) {
52
- if (value === void 0) {
53
- continue;
169
+ // src/internal/slot.tsx
170
+ import { Fragment, jsx as jsx4 } from "react/jsx-runtime";
171
+ var isPrevented = (event) => typeof event === "object" && event !== null && event.defaultPrevented === true;
172
+ function mergeProps(slotProps, childProps) {
173
+ const merged = { ...slotProps };
174
+ for (const key of Object.keys(childProps)) {
175
+ const slotValue = slotProps[key];
176
+ const childValue = childProps[key];
177
+ if (key === "ref") continue;
178
+ if (key === "className") {
179
+ if (typeof childValue === "function" && typeof slotValue === "string") {
180
+ const slotClass = slotValue;
181
+ merged[key] = (...args) => {
182
+ const resolved = childValue(...args);
183
+ return [slotClass, resolved].filter(Boolean).join(" ") || void 0;
184
+ };
185
+ } else {
186
+ const parts = [slotValue, childValue].filter(Boolean);
187
+ merged[key] = parts.length > 0 ? parts.join(" ") : void 0;
188
+ }
189
+ } else if (key === "style") {
190
+ merged[key] = slotValue != null && childValue != null ? { ...slotValue, ...childValue } : childValue ?? slotValue;
191
+ } else if (key === "aria-describedby" && slotValue && childValue) {
192
+ merged[key] = `${childValue} ${slotValue}`;
193
+ } else if (key.startsWith("on") && typeof slotValue === "function" && typeof childValue === "function") {
194
+ merged[key] = (...args) => {
195
+ childValue(...args);
196
+ if (!isPrevented(args[0])) slotValue(...args);
197
+ };
198
+ } else if (childValue !== void 0) {
199
+ merged[key] = childValue;
54
200
  }
55
- const attributeName = `data-${key}`;
56
- result[attributeName] = typeof value === "boolean" ? String(value) : `${value}`;
57
201
  }
58
- return result;
202
+ return merged;
59
203
  }
204
+ function blockDisabledClick(event) {
205
+ event.preventDefault();
206
+ event.stopPropagation();
207
+ }
208
+ function Slot({ children, ref, ...slotProps }) {
209
+ const child = React5.isValidElement(children) ? children : null;
210
+ const childRef = child?.props.ref ?? void 0;
211
+ const composedRef = useMergedRefs(ref, childRef);
212
+ if (!child) return /* @__PURE__ */ jsx4(Fragment, { children });
213
+ const merged = mergeProps(slotProps, child.props);
214
+ const disabled = slotProps["aria-disabled"] === true || slotProps["aria-disabled"] === "true";
215
+ if (disabled) merged.onClickCapture = blockDisabledClick;
216
+ return React5.cloneElement(child, { ...merged, ref: composedRef });
217
+ }
218
+ Slot.displayName = "Slot";
60
219
 
61
- // src/components/scroll-container/ScrollContainer.module.css
62
- var ScrollContainer_default = {
63
- root: "ScrollContainer_root",
64
- vertical: "ScrollContainer_vertical",
65
- horizontal: "ScrollContainer_horizontal",
66
- both: "ScrollContainer_both",
67
- overscrollContain: "ScrollContainer_overscrollContain",
68
- overscrollNone: "ScrollContainer_overscrollNone",
69
- scrollbarHidden: "ScrollContainer_scrollbarHidden"
220
+ // src/internal/touchTarget.module.css
221
+ var touchTarget_default = {
222
+ target: "touchTarget_target",
223
+ targetBlock: "touchTarget_targetBlock"
70
224
  };
71
225
 
72
- // src/components/scroll-container/ScrollContainer.tsx
73
- import { jsx as jsx2 } from "react/jsx-runtime";
74
- var axisClass = {
75
- vertical: ScrollContainer_default.vertical,
76
- horizontal: ScrollContainer_default.horizontal,
77
- both: ScrollContainer_default.both
226
+ // src/internal/touchTarget.ts
227
+ var touchTargetClass = touchTarget_default.target;
228
+ var touchTargetBlockClass = touchTarget_default.targetBlock;
229
+
230
+ // src/components/button/Button.module.css
231
+ var Button_default = {
232
+ root: "Button_root",
233
+ icon: "Button_icon",
234
+ spinner: "Button_spinner"
78
235
  };
79
- function useEdgeOverflow(ref, enabled, horizontal) {
80
- const [overflow, setOverflow] = React3.useState({ start: false, end: false });
81
- React3.useLayoutEffect(() => {
82
- const node = ref.current;
83
- if (!enabled || !node) return;
84
- const update = () => {
85
- const position = horizontal ? Math.abs(node.scrollLeft) : node.scrollTop;
86
- const max = horizontal ? node.scrollWidth - node.clientWidth : node.scrollHeight - node.clientHeight;
87
- const start = position > 1;
88
- const end = max - position > 1;
89
- setOverflow((prev) => prev.start === start && prev.end === end ? prev : { start, end });
90
- };
91
- let frame = 0;
92
- const schedule = () => {
93
- if (frame) return;
94
- frame = requestAnimationFrame(() => {
95
- frame = 0;
96
- update();
97
- });
98
- };
99
- update();
100
- node.addEventListener("scroll", schedule, { passive: true });
101
- const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(schedule);
102
- const observeChildren = () => {
103
- for (const child of Array.from(node.children)) resize?.observe(child);
104
- };
105
- resize?.observe(node);
106
- observeChildren();
107
- const mutation = new MutationObserver(() => {
108
- observeChildren();
109
- schedule();
110
- });
111
- mutation.observe(node, { childList: true });
112
- return () => {
113
- cancelAnimationFrame(frame);
114
- node.removeEventListener("scroll", schedule);
115
- resize?.disconnect();
116
- mutation.disconnect();
117
- };
118
- }, [ref, enabled, horizontal]);
119
- return enabled ? overflow : { start: false, end: false };
120
- }
121
- function ScrollContainer({
122
- as: Component = "div",
123
- axis = "vertical",
124
- overscrollBehavior = "contain",
125
- fade = false,
126
- scrollbar = "thin",
236
+
237
+ // src/components/button/Button.tsx
238
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
239
+ function ButtonRoot({
240
+ children,
127
241
  className,
242
+ variant = "solid",
243
+ tone = "accent",
244
+ size: sizeProp,
245
+ fullWidth,
246
+ type = "button",
247
+ loading = false,
248
+ disabled,
249
+ asChild = false,
250
+ onClick: onClick2,
128
251
  ref,
129
252
  ...rest
130
253
  }) {
131
- const innerRef = React3.useRef(null);
132
- const mergedRef = useMergedRefs(innerRef, ref);
133
- const horizontal = axis === "horizontal";
134
- const overflow = useEdgeOverflow(innerRef, fade, horizontal);
135
- return /* @__PURE__ */ jsx2(
136
- Component,
254
+ const size = useControlSize(sizeProp);
255
+ const isDisabled = disabled || loading;
256
+ const layout = iconLayout(children, ButtonIcon);
257
+ const dataAttrs = toDataAttributes({
258
+ variant,
259
+ tone,
260
+ size,
261
+ // `disabled` only: a loading button is busy, not unavailable, and keeps its colors.
262
+ disabled: disabled || void 0,
263
+ loading,
264
+ "full-width": fullWidth,
265
+ "icon-only": layout.iconOnly || void 0,
266
+ "leading-icon": layout.leadingIcon || void 0,
267
+ "trailing-icon": layout.trailingIcon || void 0,
268
+ // Without a leading icon the spinner is centered over the hidden label: width stays put.
269
+ "loading-overlay": loading && !asChild && !layout.leadingIcon && !layout.iconOnly || void 0
270
+ });
271
+ const classes = cx(fieldTierClass, touchTargetClass, Button_default.root, className);
272
+ if (asChild) {
273
+ return /* @__PURE__ */ jsx5(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsx5(
274
+ Slot,
275
+ {
276
+ ...rest,
277
+ ref,
278
+ className: classes,
279
+ "aria-disabled": isDisabled || void 0,
280
+ "aria-busy": loading || void 0,
281
+ onClick: isDisabled ? (event) => event.preventDefault() : onClick2,
282
+ ...dataAttrs,
283
+ children
284
+ }
285
+ ) });
286
+ }
287
+ return /* @__PURE__ */ jsx5(
288
+ "button",
137
289
  {
138
- ref: mergedRef,
139
- className: cx(
140
- ScrollContainer_default.root,
141
- axisClass[axis],
142
- overscrollBehavior === "contain" && ScrollContainer_default.overscrollContain,
143
- overscrollBehavior === "none" && ScrollContainer_default.overscrollNone,
144
- scrollbar === "hidden" && ScrollContainer_default.scrollbarHidden,
145
- className
146
- ),
147
- ...toDataAttributes({
148
- fade: fade ? horizontal ? "horizontal" : "vertical" : void 0,
149
- "overflow-start": overflow.start || void 0,
150
- "overflow-end": overflow.end || void 0
151
- }),
152
- ...rest
290
+ ...rest,
291
+ ref,
292
+ type,
293
+ className: classes,
294
+ disabled: isDisabled,
295
+ "aria-busy": loading || void 0,
296
+ onClick: onClick2,
297
+ ...dataAttrs,
298
+ children: /* @__PURE__ */ jsxs2(ControlSizeProvider, { value: size, children: [
299
+ loading ? /* @__PURE__ */ jsx5(Spinner, { className: Button_default.spinner, "aria-hidden": "true" }) : null,
300
+ children
301
+ ] })
153
302
  }
154
303
  );
155
304
  }
305
+ ButtonRoot.displayName = "Button.Root";
306
+ function ButtonIcon({ children, className, ...rest }) {
307
+ return /* @__PURE__ */ jsx5("span", { className: cx(Button_default.icon, className), "aria-hidden": "true", ...rest, children });
308
+ }
309
+ ButtonIcon.displayName = "Button.Icon";
310
+ var Button = { Root: ButtonRoot, Icon: ButtonIcon };
156
311
 
157
- // src/internal/iconBox.module.css
158
- var iconBox_default = {
159
- box: "iconBox_box",
160
- xs: "iconBox_xs",
161
- s: "iconBox_s",
162
- m: "iconBox_m",
163
- l: "iconBox_l",
164
- xl: "iconBox_xl",
165
- inherit: "iconBox_inherit"
312
+ // src/components/divider/Divider.module.css
313
+ var Divider_default = {
314
+ root: "Divider_root",
315
+ content: "Divider_content"
166
316
  };
167
317
 
168
- // src/internal/iconBox.ts
169
- function iconBoxClass(size, tier) {
170
- return cx(iconBox_default.box, iconBox_default[size ?? tier ?? "m"], size === void 0 && iconBox_default.inherit);
318
+ // src/components/divider/Divider.tsx
319
+ import { jsx as jsx6 } from "react/jsx-runtime";
320
+ function Divider({
321
+ orientation = "horizontal",
322
+ align = "center",
323
+ size = "m",
324
+ children,
325
+ className,
326
+ role = "separator",
327
+ ...rest
328
+ }) {
329
+ return /* @__PURE__ */ jsx6(
330
+ "div",
331
+ {
332
+ ...rest,
333
+ className: cx(Divider_default.root, className),
334
+ role,
335
+ ...orientation === "vertical" ? { "aria-orientation": "vertical" } : {},
336
+ ...toDataAttributes({ orientation, align, size }),
337
+ children: children != null ? /* @__PURE__ */ jsx6(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsx6("span", { className: Divider_default.content, children }) }) : null
338
+ }
339
+ );
171
340
  }
172
341
 
173
- // src/internal/textTone.module.css
174
- var textTone_default = {
175
- tone: "textTone_tone"
176
- };
177
-
178
342
  // src/icons/Icon.module.css
179
343
  var Icon_default = {
180
344
  root: "Icon_root"
@@ -340,7 +504,7 @@ var iconRegistry = {
340
504
  };
341
505
 
342
506
  // src/icons/Icon.tsx
343
- import { jsx as jsx3 } from "react/jsx-runtime";
507
+ import { jsx as jsx7 } from "react/jsx-runtime";
344
508
  function IconSvg({
345
509
  glyph: GlyphSvg,
346
510
  className,
@@ -350,7 +514,7 @@ function IconSvg({
350
514
  ...rest
351
515
  }) {
352
516
  const tier = useOptionalControlSize();
353
- return /* @__PURE__ */ jsx3(
517
+ return /* @__PURE__ */ jsx7(
354
518
  GlyphSvg,
355
519
  {
356
520
  className: cx(Icon_default.root, iconBoxClass(size, tier), textTone_default.tone, className),
@@ -362,236 +526,118 @@ function IconSvg({
362
526
  );
363
527
  }
364
528
  function Icon({ name, ...rest }) {
365
- return /* @__PURE__ */ jsx3(IconSvg, { glyph: iconRegistry[name], ...rest });
529
+ return /* @__PURE__ */ jsx7(IconSvg, { glyph: iconRegistry[name], ...rest });
366
530
  }
367
531
  function createIcon(glyph) {
368
532
  function DomainIcon(props) {
369
- return /* @__PURE__ */ jsx3(IconSvg, { glyph, ...props });
533
+ return /* @__PURE__ */ jsx7(IconSvg, { glyph, ...props });
370
534
  }
371
535
  DomainIcon.displayName = `Icon(${glyph.displayName ?? "Glyph"})`;
372
536
  return DomainIcon;
373
537
  }
374
538
 
375
- // src/components/spinner/Spinner.tsx
376
- import * as React4 from "react";
377
-
378
- // src/internal/VisuallyHidden.module.css
379
- var VisuallyHidden_default = {
380
- root: "VisuallyHidden_root"
381
- };
382
-
383
- // src/internal/VisuallyHidden.tsx
384
- import { jsx as jsx4 } from "react/jsx-runtime";
385
- var visuallyHiddenClass = VisuallyHidden_default.root;
386
- function VisuallyHidden({ className, ...rest }) {
387
- return /* @__PURE__ */ jsx4("span", { className: cx(VisuallyHidden_default.root, className), ...rest });
388
- }
389
-
390
- // src/components/spinner/Spinner.module.css
391
- var Spinner_default = {
392
- root: "Spinner_root",
393
- ring: "Spinner_ring",
394
- primeSpinnerTurn: "Spinner_primeSpinnerTurn"
395
- };
396
-
397
- // src/components/spinner/Spinner.tsx
398
- import { jsx as jsx5, jsxs } from "react/jsx-runtime";
399
- var SPINNER_LABELS = {
400
- loading: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430"
401
- };
402
- function Spinner({
403
- size: sizeProp,
404
- tone = "default",
405
- labels: labelsProp,
406
- className,
407
- ...rest
408
- }) {
409
- const controlSize = useOptionalControlSize();
410
- const labels = React4.useMemo(() => ({ ...SPINNER_LABELS, ...labelsProp }), [labelsProp]);
411
- const size = sizeProp ?? controlSize ?? "m";
412
- return /* @__PURE__ */ jsxs(
413
- "span",
414
- {
415
- role: "status",
416
- className: cx(Spinner_default.root, iconBoxClass(sizeProp, controlSize), textTone_default.tone, className),
417
- ...toDataAttributes({ size, tone: tone === "default" ? void 0 : tone }),
418
- ...rest,
419
- children: [
420
- /* @__PURE__ */ jsx5("span", { className: Spinner_default.ring, "aria-hidden": "true" }),
421
- /* @__PURE__ */ jsx5(VisuallyHidden, { children: labels.loading })
422
- ]
423
- }
424
- );
425
- }
426
-
427
- // src/internal/fieldSurface.module.css
428
- var fieldSurface_default = {
429
- surface: "fieldSurface_surface"
430
- };
431
-
432
- // src/internal/fieldTier.module.css
433
- var fieldTier_default = {
434
- tier: "fieldTier_tier"
435
- };
436
-
437
- // src/internal/fieldTrigger.module.css
438
- var fieldTrigger_default = {
439
- trigger: "fieldTrigger_trigger"
440
- };
441
-
442
- // src/internal/fieldClasses.ts
443
- var fieldSurfaceClass = fieldSurface_default.surface;
444
- var fieldTierClass = fieldTier_default.tier;
445
- var fieldTriggerClass = `${fieldTier_default.tier} ${fieldSurface_default.surface} ${fieldTrigger_default.trigger}`;
446
-
447
- // src/internal/iconLayout.ts
448
- import * as React5 from "react";
449
- function iconLayout(children, iconType) {
450
- const content = React5.Children.toArray(children).filter(
451
- (child) => !(typeof child === "string" && child.trim() === "")
452
- );
453
- const isIcon = (child) => React5.isValidElement(child) && child.type === iconType;
454
- const iconOnly = content.length > 0 && content.every(isIcon);
455
- return {
456
- iconOnly,
457
- leadingIcon: !iconOnly && content.length > 0 && isIcon(content[0]),
458
- trailingIcon: !iconOnly && content.length > 0 && isIcon(content[content.length - 1])
459
- };
460
- }
539
+ // src/components/scroll-container/ScrollContainer.tsx
540
+ import * as React7 from "react";
461
541
 
462
- // src/internal/slot.tsx
542
+ // src/hooks/useEdgeOverflow.ts
463
543
  import * as React6 from "react";
464
- import { Fragment, jsx as jsx6 } from "react/jsx-runtime";
465
- var isPrevented = (event) => typeof event === "object" && event !== null && event.defaultPrevented === true;
466
- function mergeProps(slotProps, childProps) {
467
- const merged = { ...slotProps };
468
- for (const key of Object.keys(childProps)) {
469
- const slotValue = slotProps[key];
470
- const childValue = childProps[key];
471
- if (key === "ref") continue;
472
- if (key === "className") {
473
- if (typeof childValue === "function" && typeof slotValue === "string") {
474
- const slotClass = slotValue;
475
- merged[key] = (...args) => {
476
- const resolved = childValue(...args);
477
- return [slotClass, resolved].filter(Boolean).join(" ") || void 0;
478
- };
479
- } else {
480
- const parts = [slotValue, childValue].filter(Boolean);
481
- merged[key] = parts.length > 0 ? parts.join(" ") : void 0;
482
- }
483
- } else if (key === "style") {
484
- merged[key] = slotValue != null && childValue != null ? { ...slotValue, ...childValue } : childValue ?? slotValue;
485
- } else if (key === "aria-describedby" && slotValue && childValue) {
486
- merged[key] = `${childValue} ${slotValue}`;
487
- } else if (key.startsWith("on") && typeof slotValue === "function" && typeof childValue === "function") {
488
- merged[key] = (...args) => {
489
- childValue(...args);
490
- if (!isPrevented(args[0])) slotValue(...args);
491
- };
492
- } else if (childValue !== void 0) {
493
- merged[key] = childValue;
494
- }
495
- }
496
- return merged;
497
- }
498
- function blockDisabledClick(event) {
499
- event.preventDefault();
500
- event.stopPropagation();
501
- }
502
- function Slot({ children, ref, ...slotProps }) {
503
- const child = React6.isValidElement(children) ? children : null;
504
- const childRef = child?.props.ref ?? void 0;
505
- const composedRef = useMergedRefs(ref, childRef);
506
- if (!child) return /* @__PURE__ */ jsx6(Fragment, { children });
507
- const merged = mergeProps(slotProps, child.props);
508
- const disabled = slotProps["aria-disabled"] === true || slotProps["aria-disabled"] === "true";
509
- if (disabled) merged.onClickCapture = blockDisabledClick;
510
- return React6.cloneElement(child, { ...merged, ref: composedRef });
544
+ var NONE = { start: false, end: false };
545
+ function useEdgeOverflow(ref, enabled, horizontal) {
546
+ const [overflow, setOverflow] = React6.useState(NONE);
547
+ React6.useLayoutEffect(() => {
548
+ const node = ref.current;
549
+ if (!enabled || !node) return;
550
+ const update = () => {
551
+ const position = horizontal ? Math.abs(node.scrollLeft) : node.scrollTop;
552
+ const max = horizontal ? node.scrollWidth - node.clientWidth : node.scrollHeight - node.clientHeight;
553
+ const start = position > 1;
554
+ const end = max - position > 1;
555
+ setOverflow((prev) => prev.start === start && prev.end === end ? prev : { start, end });
556
+ };
557
+ let frame = 0;
558
+ const schedule = () => {
559
+ if (frame) return;
560
+ frame = requestAnimationFrame(() => {
561
+ frame = 0;
562
+ update();
563
+ });
564
+ };
565
+ update();
566
+ node.addEventListener("scroll", schedule, { passive: true });
567
+ const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(schedule);
568
+ const observeChildren = () => {
569
+ for (const child of Array.from(node.children)) resize?.observe(child);
570
+ };
571
+ resize?.observe(node);
572
+ observeChildren();
573
+ const mutation = new MutationObserver(() => {
574
+ observeChildren();
575
+ schedule();
576
+ });
577
+ mutation.observe(node, { childList: true });
578
+ return () => {
579
+ cancelAnimationFrame(frame);
580
+ node.removeEventListener("scroll", schedule);
581
+ resize?.disconnect();
582
+ mutation.disconnect();
583
+ };
584
+ }, [ref, enabled, horizontal]);
585
+ return enabled ? overflow : NONE;
511
586
  }
512
- Slot.displayName = "Slot";
513
587
 
514
- // src/components/button/Button.module.css
515
- var Button_default = {
516
- root: "Button_root",
517
- icon: "Button_icon",
518
- spinner: "Button_spinner"
588
+ // src/components/scroll-container/ScrollContainer.module.css
589
+ var ScrollContainer_default = {
590
+ root: "ScrollContainer_root",
591
+ vertical: "ScrollContainer_vertical",
592
+ horizontal: "ScrollContainer_horizontal",
593
+ both: "ScrollContainer_both",
594
+ overscrollContain: "ScrollContainer_overscrollContain",
595
+ overscrollNone: "ScrollContainer_overscrollNone",
596
+ scrollbarHidden: "ScrollContainer_scrollbarHidden"
519
597
  };
520
598
 
521
- // src/components/button/Button.tsx
522
- import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
523
- function ButtonRoot({
524
- children,
599
+ // src/components/scroll-container/ScrollContainer.tsx
600
+ import { jsx as jsx8 } from "react/jsx-runtime";
601
+ var axisClass = {
602
+ vertical: ScrollContainer_default.vertical,
603
+ horizontal: ScrollContainer_default.horizontal,
604
+ both: ScrollContainer_default.both
605
+ };
606
+ function ScrollContainer({
607
+ as: Component = "div",
608
+ axis = "vertical",
609
+ overscrollBehavior = "contain",
610
+ fade = false,
611
+ scrollbar = "thin",
525
612
  className,
526
- variant = "solid",
527
- tone = "accent",
528
- size: sizeProp,
529
- fullWidth,
530
- type = "button",
531
- loading = false,
532
- disabled,
533
- asChild = false,
534
- onClick: onClick2,
535
613
  ref,
536
614
  ...rest
537
615
  }) {
538
- const size = useControlSize(sizeProp);
539
- const isDisabled = disabled || loading;
540
- const layout = iconLayout(children, ButtonIcon);
541
- const dataAttrs = toDataAttributes({
542
- variant,
543
- tone,
544
- size,
545
- // `disabled` only: a loading button is busy, not unavailable, and keeps its colors.
546
- disabled: disabled || void 0,
547
- loading,
548
- "full-width": fullWidth,
549
- "icon-only": layout.iconOnly || void 0,
550
- "leading-icon": layout.leadingIcon || void 0,
551
- "trailing-icon": layout.trailingIcon || void 0,
552
- // Without a leading icon the spinner is centered over the hidden label: width stays put.
553
- "loading-overlay": loading && !asChild && !layout.leadingIcon && !layout.iconOnly || void 0
554
- });
555
- const classes = cx(fieldTierClass, Button_default.root, className);
556
- if (asChild) {
557
- return /* @__PURE__ */ jsx7(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsx7(
558
- Slot,
559
- {
560
- ...rest,
561
- ref,
562
- className: classes,
563
- "aria-disabled": isDisabled || void 0,
564
- "aria-busy": loading || void 0,
565
- onClick: isDisabled ? (event) => event.preventDefault() : onClick2,
566
- ...dataAttrs,
567
- children
568
- }
569
- ) });
570
- }
571
- return /* @__PURE__ */ jsx7(
572
- "button",
616
+ const innerRef = React7.useRef(null);
617
+ const mergedRef = useMergedRefs(innerRef, ref);
618
+ const horizontal = axis === "horizontal";
619
+ const overflow = useEdgeOverflow(innerRef, fade, horizontal);
620
+ return /* @__PURE__ */ jsx8(
621
+ Component,
573
622
  {
574
- ...rest,
575
- ref,
576
- type,
577
- className: classes,
578
- disabled: isDisabled,
579
- "aria-busy": loading || void 0,
580
- onClick: onClick2,
581
- ...dataAttrs,
582
- children: /* @__PURE__ */ jsxs2(ControlSizeProvider, { value: size, children: [
583
- loading ? /* @__PURE__ */ jsx7(Spinner, { className: Button_default.spinner, "aria-hidden": "true" }) : null,
584
- children
585
- ] })
623
+ ref: mergedRef,
624
+ className: cx(
625
+ ScrollContainer_default.root,
626
+ axisClass[axis],
627
+ overscrollBehavior === "contain" && ScrollContainer_default.overscrollContain,
628
+ overscrollBehavior === "none" && ScrollContainer_default.overscrollNone,
629
+ scrollbar === "hidden" && ScrollContainer_default.scrollbarHidden,
630
+ className
631
+ ),
632
+ ...toDataAttributes({
633
+ fade: fade ? horizontal ? "horizontal" : "vertical" : void 0,
634
+ "overflow-start": overflow.start || void 0,
635
+ "overflow-end": overflow.end || void 0
636
+ }),
637
+ ...rest
586
638
  }
587
639
  );
588
640
  }
589
- ButtonRoot.displayName = "Button.Root";
590
- function ButtonIcon({ children, className, ...rest }) {
591
- return /* @__PURE__ */ jsx7("span", { className: cx(Button_default.icon, className), "aria-hidden": "true", ...rest, children });
592
- }
593
- ButtonIcon.displayName = "Button.Icon";
594
- var Button = { Root: ButtonRoot, Icon: ButtonIcon };
595
641
 
596
642
  // src/internal/states.ts
597
643
  var controlSizes = ["xs", "s", "m", "l", "xl"];
@@ -646,9 +692,9 @@ var Hint_default = {
646
692
  };
647
693
 
648
694
  // src/components/hint/Hint.tsx
649
- import { jsx as jsx8 } from "react/jsx-runtime";
695
+ import { jsx as jsx9 } from "react/jsx-runtime";
650
696
  function HintRoot({ className, size = "m", invalid, disabled, children, ...rest }) {
651
- return /* @__PURE__ */ jsx8(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsx8(
697
+ return /* @__PURE__ */ jsx9(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsx9(
652
698
  "p",
653
699
  {
654
700
  ...rest,
@@ -664,7 +710,7 @@ function HintRoot({ className, size = "m", invalid, disabled, children, ...rest
664
710
  }
665
711
  HintRoot.displayName = "Hint.Root";
666
712
  function HintIcon({ className, ...rest }) {
667
- return /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: cx(Hint_default.icon, className), ...rest });
713
+ return /* @__PURE__ */ jsx9("span", { "aria-hidden": "true", className: cx(Hint_default.icon, className), ...rest });
668
714
  }
669
715
  HintIcon.displayName = "Hint.Icon";
670
716
  var Hint = { Root: HintRoot, Icon: HintIcon };
@@ -679,7 +725,7 @@ var Label_default = {
679
725
  };
680
726
 
681
727
  // src/components/label/Label.tsx
682
- import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
728
+ import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
683
729
  var LABEL_LABELS = { optional: "\u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E" };
684
730
  function LabelRoot({
685
731
  className,
@@ -695,7 +741,7 @@ function LabelRoot({
695
741
  const size = useControlSize(sizeProp);
696
742
  return (
697
743
  // biome-ignore lint/a11y/noLabelWithoutControl: field label primitive; association via htmlFor or wrapping control is caller responsibility
698
- /* @__PURE__ */ jsx9(
744
+ /* @__PURE__ */ jsx10(
699
745
  "label",
700
746
  {
701
747
  ref,
@@ -705,8 +751,8 @@ function LabelRoot({
705
751
  ...toDataAttributes({ disabled: disabled || void 0, size }),
706
752
  children: /* @__PURE__ */ jsxs3(ControlSizeProvider, { value: size, children: [
707
753
  children,
708
- required ? /* @__PURE__ */ jsx9("span", { className: Label_default.asterisk, "aria-hidden": "true", children: "*" }) : null,
709
- optional ? /* @__PURE__ */ jsx9("span", { className: Label_default.optional, children: labels?.optional ?? LABEL_LABELS.optional }) : null
754
+ required ? /* @__PURE__ */ jsx10("span", { className: Label_default.asterisk, "aria-hidden": "true", children: "*" }) : null,
755
+ optional ? /* @__PURE__ */ jsx10("span", { className: Label_default.optional, children: labels?.optional ?? LABEL_LABELS.optional }) : null
710
756
  ] })
711
757
  }
712
758
  )
@@ -714,11 +760,11 @@ function LabelRoot({
714
760
  }
715
761
  LabelRoot.displayName = "Label.Root";
716
762
  function LabelIcon({ className, ...rest }) {
717
- return /* @__PURE__ */ jsx9("span", { className: cx(Label_default.icon, className), "aria-hidden": "true", ...rest });
763
+ return /* @__PURE__ */ jsx10("span", { className: cx(Label_default.icon, className), "aria-hidden": "true", ...rest });
718
764
  }
719
765
  LabelIcon.displayName = "Label.Icon";
720
766
  function LabelDescription({ className, ...rest }) {
721
- return /* @__PURE__ */ jsx9("span", { className: cx(Label_default.description, className), ...rest });
767
+ return /* @__PURE__ */ jsx10("span", { className: cx(Label_default.description, className), ...rest });
722
768
  }
723
769
  LabelDescription.displayName = "Label.Description";
724
770
  var Label = {
@@ -728,21 +774,21 @@ var Label = {
728
774
  };
729
775
 
730
776
  // src/components/checkbox/Checkbox.tsx
731
- import * as React9 from "react";
777
+ import * as React10 from "react";
732
778
 
733
779
  // src/hooks/useControllableState.ts
734
- import * as React7 from "react";
780
+ import * as React8 from "react";
735
781
  function useControllableState({
736
782
  value,
737
783
  defaultValue,
738
784
  onChange
739
785
  }) {
740
- const [internalValue, setInternalValue] = React7.useState(defaultValue);
786
+ const [internalValue, setInternalValue] = React8.useState(defaultValue);
741
787
  const isControlled = value !== void 0;
742
788
  const currentValue = isControlled ? value : internalValue;
743
- const currentValueRef = React7.useRef(currentValue);
789
+ const currentValueRef = React8.useRef(currentValue);
744
790
  currentValueRef.current = currentValue;
745
- const setValue = React7.useCallback(
791
+ const setValue = React8.useCallback(
746
792
  (nextValue) => {
747
793
  const previousValue = currentValueRef.current;
748
794
  const computedValue = typeof nextValue === "function" ? nextValue(previousValue) : nextValue;
@@ -773,7 +819,7 @@ var ChoiceField_default = {
773
819
  };
774
820
 
775
821
  // src/internal/ChoiceField.tsx
776
- import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
822
+ import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
777
823
  var choiceInputClass = ChoiceField_default.input;
778
824
  var choiceVisualClass = ChoiceField_default.visual;
779
825
  var choiceTierClass = ChoiceField_default.tier;
@@ -789,7 +835,7 @@ function ChoiceField({
789
835
  className,
790
836
  children
791
837
  }) {
792
- return /* @__PURE__ */ jsx10(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsxs4(
838
+ return /* @__PURE__ */ jsx11(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsxs4(
793
839
  "div",
794
840
  {
795
841
  className: cx(ChoiceField_default.tier, ChoiceField_default.field, className),
@@ -802,20 +848,20 @@ function ChoiceField({
802
848
  }),
803
849
  children: [
804
850
  /* @__PURE__ */ jsxs4("label", { htmlFor: ids.controlId, className: ChoiceField_default.row, children: [
805
- /* @__PURE__ */ jsx10("span", { className: ChoiceField_default.controlCell, children: control }),
851
+ /* @__PURE__ */ jsx11("span", { className: cx(ChoiceField_default.controlCell, touchTargetClass), children: control }),
806
852
  children
807
853
  ] }),
808
- ids.showError ? /* @__PURE__ */ jsx10(Hint.Root, { id: ids.errorId, size, invalid: true, className: ChoiceField_default.support, children: error }) : ids.showHint ? /* @__PURE__ */ jsx10(Hint.Root, { id: ids.hintId, size, disabled, className: ChoiceField_default.support, children: hint }) : null
854
+ ids.showError ? /* @__PURE__ */ jsx11(Hint.Root, { id: ids.errorId, size, invalid: true, className: ChoiceField_default.support, children: error }) : ids.showHint ? /* @__PURE__ */ jsx11(Hint.Root, { id: ids.hintId, size, disabled, className: ChoiceField_default.support, children: hint }) : null
809
855
  ]
810
856
  }
811
857
  ) });
812
858
  }
813
859
  function ChoiceLabel({ className, ...rest }) {
814
- return /* @__PURE__ */ jsx10("span", { className: cx(ChoiceField_default.text, className), ...rest });
860
+ return /* @__PURE__ */ jsx11("span", { className: cx(ChoiceField_default.text, className), ...rest });
815
861
  }
816
862
 
817
863
  // src/internal/FieldFrame.tsx
818
- import * as React8 from "react";
864
+ import * as React9 from "react";
819
865
 
820
866
  // src/internal/formatLabel.ts
821
867
  function formatLabel(template, values) {
@@ -838,7 +884,7 @@ var FieldFrame_default = {
838
884
  };
839
885
 
840
886
  // src/internal/FieldFrame.tsx
841
- import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
887
+ import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
842
888
  function hasContent(node) {
843
889
  return node != null && node !== false && node !== "";
844
890
  }
@@ -848,7 +894,7 @@ function useFieldFrame(explicitId, {
848
894
  error,
849
895
  invalid
850
896
  }, ariaDescribedBy) {
851
- const generated = React8.useId();
897
+ const generated = React9.useId();
852
898
  const controlId = explicitId ?? generated;
853
899
  const labelId = `${controlId}-label`;
854
900
  const hintId = `${controlId}-hint`;
@@ -888,7 +934,7 @@ function FieldFrame({
888
934
  }) {
889
935
  const { showError, showHint } = ids;
890
936
  const showSupport = showError || showHint || counter != null || reserveSupportRow;
891
- const labelNode = hasContent(label) ? /* @__PURE__ */ jsx11(
937
+ const labelNode = hasContent(label) ? /* @__PURE__ */ jsx12(
892
938
  Label.Root,
893
939
  {
894
940
  id: ids.labelId,
@@ -915,7 +961,7 @@ function FieldFrame({
915
961
  children: [
916
962
  labelEnd != null ? /* @__PURE__ */ jsxs5("div", { className: FieldFrame_default.labelRow, children: [
917
963
  labelNode,
918
- /* @__PURE__ */ jsx11("span", { className: FieldFrame_default.labelEnd, children: labelEnd })
964
+ /* @__PURE__ */ jsx12("span", { className: FieldFrame_default.labelEnd, children: labelEnd })
919
965
  ] }) : labelNode,
920
966
  /* @__PURE__ */ jsxs5("div", { className: FieldFrame_default.body, children: [
921
967
  children,
@@ -925,7 +971,7 @@ function FieldFrame({
925
971
  className: FieldFrame_default.support,
926
972
  ...toDataAttributes({ size, reserve: reserveSupportRow || void 0 }),
927
973
  children: [
928
- showError ? /* @__PURE__ */ jsx11(Hint.Root, { id: ids.errorId, size, invalid: true, className: FieldFrame_default.supportText, children: error }) : showHint ? /* @__PURE__ */ jsx11(
974
+ showError ? /* @__PURE__ */ jsx12(Hint.Root, { id: ids.errorId, size, invalid: true, className: FieldFrame_default.supportText, children: error }) : showHint ? /* @__PURE__ */ jsx12(
929
975
  Hint.Root,
930
976
  {
931
977
  id: ids.hintId,
@@ -934,7 +980,7 @@ function FieldFrame({
934
980
  className: FieldFrame_default.supportText,
935
981
  children: hint
936
982
  }
937
- ) : /* @__PURE__ */ jsx11("span", { className: FieldFrame_default.supportText }),
983
+ ) : /* @__PURE__ */ jsx12("span", { className: FieldFrame_default.supportText }),
938
984
  counter
939
985
  ]
940
986
  }
@@ -959,7 +1005,7 @@ function FieldCounter({ current, max, size, label, className, ...rest }) {
959
1005
  "/",
960
1006
  max
961
1007
  ] }),
962
- /* @__PURE__ */ jsx11(VisuallyHidden, { children: formatLabel(label, { current, max }) })
1008
+ /* @__PURE__ */ jsx12(VisuallyHidden, { children: formatLabel(label, { current, max }) })
963
1009
  ]
964
1010
  }
965
1011
  );
@@ -976,11 +1022,11 @@ var Checkbox_default = {
976
1022
  };
977
1023
 
978
1024
  // src/components/checkbox/Checkbox.tsx
979
- import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
1025
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
980
1026
  function CheckboxMark() {
981
1027
  return /* @__PURE__ */ jsxs6("svg", { viewBox: "0 0 24 24", className: Checkbox_default.svg, "aria-hidden": "true", focusable: "false", children: [
982
- /* @__PURE__ */ jsx12("path", { d: "M5.5 12.5l4.25 4.25L18.5 8", pathLength: 1, className: Checkbox_default.checkPath }),
983
- /* @__PURE__ */ jsx12("path", { d: "M7 12h10", pathLength: 1, className: Checkbox_default.indeterminateLine })
1028
+ /* @__PURE__ */ jsx13("path", { d: "M5.5 12.5l4.25 4.25L18.5 8", pathLength: 1, className: Checkbox_default.checkPath }),
1029
+ /* @__PURE__ */ jsx13("path", { d: "M7 12h10", pathLength: 1, className: Checkbox_default.indeterminateLine })
984
1030
  ] });
985
1031
  }
986
1032
  function CheckboxRoot({
@@ -1008,12 +1054,12 @@ function CheckboxRoot({
1008
1054
  defaultValue: defaultChecked,
1009
1055
  onChange: onCheckedChange
1010
1056
  });
1011
- const internalRef = React9.useRef(null);
1057
+ const internalRef = React10.useRef(null);
1012
1058
  const mergedRef = useMergedRefs(internalRef, ref);
1013
- React9.useEffect(() => {
1059
+ React10.useEffect(() => {
1014
1060
  if (internalRef.current) internalRef.current.indeterminate = indeterminate;
1015
1061
  }, [indeterminate]);
1016
- return /* @__PURE__ */ jsx12(
1062
+ return /* @__PURE__ */ jsx13(
1017
1063
  ChoiceField,
1018
1064
  {
1019
1065
  ids,
@@ -1025,7 +1071,7 @@ function CheckboxRoot({
1025
1071
  error,
1026
1072
  className: cx(Checkbox_default.root, className),
1027
1073
  control: /* @__PURE__ */ jsxs6(Fragment2, { children: [
1028
- /* @__PURE__ */ jsx12(
1074
+ /* @__PURE__ */ jsx13(
1029
1075
  "input",
1030
1076
  {
1031
1077
  ...inputRest,
@@ -1043,7 +1089,7 @@ function CheckboxRoot({
1043
1089
  "aria-describedby": ids.describedBy
1044
1090
  }
1045
1091
  ),
1046
- /* @__PURE__ */ jsx12("span", { className: cx(choiceVisualClass, Checkbox_default.control), "aria-hidden": "true", children: /* @__PURE__ */ jsx12(CheckboxMark, {}) })
1092
+ /* @__PURE__ */ jsx13("span", { className: cx(choiceVisualClass, Checkbox_default.control), "aria-hidden": "true", children: /* @__PURE__ */ jsx13(CheckboxMark, {}) })
1047
1093
  ] }),
1048
1094
  children
1049
1095
  }
@@ -1051,7 +1097,7 @@ function CheckboxRoot({
1051
1097
  }
1052
1098
  CheckboxRoot.displayName = "Checkbox.Root";
1053
1099
  function CheckboxLabel(props) {
1054
- return /* @__PURE__ */ jsx12(ChoiceLabel, { ...props });
1100
+ return /* @__PURE__ */ jsx13(ChoiceLabel, { ...props });
1055
1101
  }
1056
1102
  CheckboxLabel.displayName = "Checkbox.Label";
1057
1103
  function CheckboxIndicator({
@@ -1063,7 +1109,7 @@ function CheckboxIndicator({
1063
1109
  ...rest
1064
1110
  }) {
1065
1111
  const size = useControlSize(sizeProp);
1066
- return /* @__PURE__ */ jsx12(
1112
+ return /* @__PURE__ */ jsx13(
1067
1113
  "span",
1068
1114
  {
1069
1115
  "aria-hidden": "true",
@@ -1080,7 +1126,7 @@ function CheckboxIndicator({
1080
1126
  disabled: disabled || void 0
1081
1127
  }),
1082
1128
  ...rest,
1083
- children: /* @__PURE__ */ jsx12(CheckboxMark, {})
1129
+ children: /* @__PURE__ */ jsx13(CheckboxMark, {})
1084
1130
  }
1085
1131
  );
1086
1132
  }
@@ -1092,7 +1138,7 @@ var Checkbox = {
1092
1138
  };
1093
1139
 
1094
1140
  // src/internal/swatch.tsx
1095
- import * as React10 from "react";
1141
+ import * as React11 from "react";
1096
1142
 
1097
1143
  // src/internal/swatch.module.css
1098
1144
  var swatch_default = {
@@ -1105,7 +1151,7 @@ var swatch_default = {
1105
1151
  };
1106
1152
 
1107
1153
  // src/internal/swatch.tsx
1108
- import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1154
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1109
1155
  var COLOR_PRESETS = [
1110
1156
  { value: "#ef4444", label: "\u041A\u0440\u0430\u0441\u043D\u044B\u0439" },
1111
1157
  { value: "#f97316", label: "\u041E\u0440\u0430\u043D\u0436\u0435\u0432\u044B\u0439" },
@@ -1125,7 +1171,7 @@ var COLOR_PRESETS = [
1125
1171
  { value: "#be185d", label: "\u0422\u0451\u043C\u043D\u043E-\u0440\u043E\u0437\u043E\u0432\u044B\u0439" }
1126
1172
  ];
1127
1173
  function useSwatchOptions(presets, allowEmpty, emptyLabel) {
1128
- return React10.useMemo(
1174
+ return React11.useMemo(
1129
1175
  () => [
1130
1176
  ...presets.map((preset) => ({ ...preset, contrast: markContrast(preset.value) })),
1131
1177
  ...allowEmpty ? [{ value: null, label: emptyLabel, contrast: "dark" }] : []
@@ -1136,17 +1182,17 @@ function useSwatchOptions(presets, allowEmpty, emptyLabel) {
1136
1182
  var swatchClass = swatch_default.swatch;
1137
1183
  var swatchTierClass = swatch_default.tier;
1138
1184
  function SwatchFill({ value }) {
1139
- if (value == null) return /* @__PURE__ */ jsx13("span", { "aria-hidden": true, className: swatch_default.checker });
1140
- return /* @__PURE__ */ jsx13("svg", { className: swatch_default.fill, "aria-hidden": "true", viewBox: "0 0 1 1", preserveAspectRatio: "none", children: /* @__PURE__ */ jsx13("rect", { width: "1", height: "1", fill: value }) });
1185
+ if (value == null) return /* @__PURE__ */ jsx14("span", { "aria-hidden": true, className: swatch_default.checker });
1186
+ return /* @__PURE__ */ jsx14("svg", { className: swatch_default.fill, "aria-hidden": "true", viewBox: "0 0 1 1", preserveAspectRatio: "none", children: /* @__PURE__ */ jsx14("rect", { width: "1", height: "1", fill: value }) });
1141
1187
  }
1142
1188
  function SwatchContent({ value, selected }) {
1143
1189
  return /* @__PURE__ */ jsxs7(Fragment3, { children: [
1144
- /* @__PURE__ */ jsx13(SwatchFill, { value }),
1145
- selected ? /* @__PURE__ */ jsx13(Icon, { name: "action.check", strokeWidth: 3, className: swatch_default.check }) : null
1190
+ /* @__PURE__ */ jsx14(SwatchFill, { value }),
1191
+ selected ? /* @__PURE__ */ jsx14(Icon, { name: "action.check", strokeWidth: 3, className: swatch_default.check }) : null
1146
1192
  ] });
1147
1193
  }
1148
1194
  function SwatchChip({ value, className, ...rest }) {
1149
- return /* @__PURE__ */ jsx13("span", { ...rest, "aria-hidden": true, className: cx(swatch_default.chip, className), children: /* @__PURE__ */ jsx13(SwatchFill, { value }) });
1195
+ return /* @__PURE__ */ jsx14("span", { ...rest, "aria-hidden": true, className: cx(swatch_default.chip, className), children: /* @__PURE__ */ jsx14(SwatchFill, { value }) });
1150
1196
  }
1151
1197
  function sameColor(a, b) {
1152
1198
  return (a ?? "").trim().toLowerCase() === (b ?? "").trim().toLowerCase();
@@ -1190,7 +1236,7 @@ function markContrast(value) {
1190
1236
  }
1191
1237
 
1192
1238
  // src/components/color-swatches/ColorSwatches.tsx
1193
- import * as React11 from "react";
1239
+ import * as React12 from "react";
1194
1240
 
1195
1241
  // src/internal/rovingFocus.ts
1196
1242
  var PREV = {
@@ -1239,7 +1285,7 @@ var ColorSwatches_default = {
1239
1285
  };
1240
1286
 
1241
1287
  // src/components/color-swatches/ColorSwatches.tsx
1242
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1288
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1243
1289
  var COLOR_SWATCHES_LABELS = {
1244
1290
  group: "\u0426\u0432\u0435\u0442",
1245
1291
  empty: "\u0411\u0435\u0437 \u0446\u0432\u0435\u0442\u0430",
@@ -1284,7 +1330,7 @@ function ColorSwatches({
1284
1330
  const options = useSwatchOptions(presets, allowEmpty, labels.empty);
1285
1331
  const selectedIndex = options.findIndex((option) => sameColor(option.value, value));
1286
1332
  const focusIndex = Math.max(0, selectedIndex);
1287
- const itemRefs = React11.useRef([]);
1333
+ const itemRefs = React12.useRef([]);
1288
1334
  const labelledBy = ariaLabelledBy ?? ids.labelledBy;
1289
1335
  const onKeyDown2 = (event) => {
1290
1336
  const current = itemRefs.current.indexOf(document.activeElement);
@@ -1299,7 +1345,7 @@ function ColorSwatches({
1299
1345
  setValue(options[next].value);
1300
1346
  itemRefs.current[next]?.focus();
1301
1347
  };
1302
- return /* @__PURE__ */ jsx14(
1348
+ return /* @__PURE__ */ jsx15(
1303
1349
  FieldFrame,
1304
1350
  {
1305
1351
  ...rest,
@@ -1336,7 +1382,7 @@ function ColorSwatches({
1336
1382
  const selected = index === selectedIndex;
1337
1383
  return (
1338
1384
  // biome-ignore lint/a11y/useSemanticElements: a swatch is a styled button in a roving radiogroup; a native radio cannot carry the color fill and check mark
1339
- /* @__PURE__ */ jsx14(
1385
+ /* @__PURE__ */ jsx15(
1340
1386
  "button",
1341
1387
  {
1342
1388
  ref: (el) => {
@@ -1355,13 +1401,13 @@ function ColorSwatches({
1355
1401
  contrast: option.contrast
1356
1402
  }),
1357
1403
  onClick: () => setValue(option.value),
1358
- children: /* @__PURE__ */ jsx14(SwatchContent, { value: option.value, selected })
1404
+ children: /* @__PURE__ */ jsx15(SwatchContent, { value: option.value, selected })
1359
1405
  },
1360
1406
  option.value ?? "empty"
1361
1407
  )
1362
1408
  );
1363
1409
  }),
1364
- name ? /* @__PURE__ */ jsx14("input", { type: "hidden", name, value: value ?? "" }) : null
1410
+ name ? /* @__PURE__ */ jsx15("input", { type: "hidden", name, value: value ?? "" }) : null
1365
1411
  ]
1366
1412
  }
1367
1413
  )
@@ -1379,7 +1425,7 @@ var EmptyPage_default = {
1379
1425
  };
1380
1426
 
1381
1427
  // src/components/empty-page/EmptyPage.tsx
1382
- import { jsx as jsx15 } from "react/jsx-runtime";
1428
+ import { jsx as jsx16 } from "react/jsx-runtime";
1383
1429
  function EmptyPageRoot({
1384
1430
  size = "m",
1385
1431
  layout = "default",
@@ -1387,31 +1433,31 @@ function EmptyPageRoot({
1387
1433
  children,
1388
1434
  ...rest
1389
1435
  }) {
1390
- return /* @__PURE__ */ jsx15(
1436
+ return /* @__PURE__ */ jsx16(
1391
1437
  "div",
1392
1438
  {
1393
1439
  className: cx(EmptyPage_default.root, layout !== "compact" && enterMotion_default.enterBaseChildren, className),
1394
1440
  ...rest,
1395
1441
  ...toDataAttributes({ size, layout: layout === "default" ? void 0 : layout }),
1396
- children: /* @__PURE__ */ jsx15(ControlSizeProvider, { value: size, children })
1442
+ children: /* @__PURE__ */ jsx16(ControlSizeProvider, { value: size, children })
1397
1443
  }
1398
1444
  );
1399
1445
  }
1400
1446
  EmptyPageRoot.displayName = "EmptyPage.Root";
1401
1447
  function EmptyPageIcon({ tone = "neutral", className, ...rest }) {
1402
- return /* @__PURE__ */ jsx15("div", { className: cx(EmptyPage_default.iconWrap, className), "data-tone": tone, ...rest });
1448
+ return /* @__PURE__ */ jsx16("div", { className: cx(EmptyPage_default.iconWrap, className), "data-tone": tone, ...rest });
1403
1449
  }
1404
1450
  EmptyPageIcon.displayName = "EmptyPage.Icon";
1405
1451
  function EmptyPageTitle({ as: Tag = "h2", className, ref, ...rest }) {
1406
- return /* @__PURE__ */ jsx15(Tag, { ref, className: cx(EmptyPage_default.title, className), ...rest });
1452
+ return /* @__PURE__ */ jsx16(Tag, { ref, className: cx(EmptyPage_default.title, className), ...rest });
1407
1453
  }
1408
1454
  EmptyPageTitle.displayName = "EmptyPage.Title";
1409
1455
  function EmptyPageDescription({ className, ...rest }) {
1410
- return /* @__PURE__ */ jsx15("p", { className: cx(EmptyPage_default.description, className), ...rest });
1456
+ return /* @__PURE__ */ jsx16("p", { className: cx(EmptyPage_default.description, className), ...rest });
1411
1457
  }
1412
1458
  EmptyPageDescription.displayName = "EmptyPage.Description";
1413
1459
  function EmptyPageActions({ className, ...rest }) {
1414
- return /* @__PURE__ */ jsx15("div", { className: cx(EmptyPage_default.actions, className), ...rest });
1460
+ return /* @__PURE__ */ jsx16("div", { className: cx(EmptyPage_default.actions, className), ...rest });
1415
1461
  }
1416
1462
  EmptyPageActions.displayName = "EmptyPage.Actions";
1417
1463
  var EmptyPage = {
@@ -1422,46 +1468,16 @@ var EmptyPage = {
1422
1468
  Actions: EmptyPageActions
1423
1469
  };
1424
1470
 
1425
- // src/components/divider/Divider.module.css
1426
- var Divider_default = {
1427
- root: "Divider_root",
1428
- content: "Divider_content"
1429
- };
1430
-
1431
- // src/components/divider/Divider.tsx
1432
- import { jsx as jsx16 } from "react/jsx-runtime";
1433
- function Divider({
1434
- orientation = "horizontal",
1435
- align = "center",
1436
- size = "m",
1437
- children,
1438
- className,
1439
- role = "separator",
1440
- ...rest
1441
- }) {
1442
- return /* @__PURE__ */ jsx16(
1443
- "div",
1444
- {
1445
- ...rest,
1446
- className: cx(Divider_default.root, className),
1447
- role,
1448
- ...orientation === "vertical" ? { "aria-orientation": "vertical" } : {},
1449
- ...toDataAttributes({ orientation, align, size }),
1450
- children: children != null ? /* @__PURE__ */ jsx16(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsx16("span", { className: Divider_default.content, children }) }) : null
1451
- }
1452
- );
1453
- }
1454
-
1455
1471
  // src/components/input/Input.tsx
1456
- import * as React13 from "react";
1472
+ import * as React14 from "react";
1457
1473
 
1458
1474
  // src/internal/context.ts
1459
- import * as React12 from "react";
1475
+ import * as React13 from "react";
1460
1476
  function createComponentContext(displayName) {
1461
- const Ctx = React12.createContext(null);
1477
+ const Ctx = React13.createContext(null);
1462
1478
  Ctx.displayName = `${displayName}Context`;
1463
1479
  function useComponentContext() {
1464
- const value = React12.useContext(Ctx);
1480
+ const value = React13.useContext(Ctx);
1465
1481
  if (value === null) {
1466
1482
  throw new Error(
1467
1483
  `[prime-ui-kit] \`${displayName}\` sub-component must be used inside \`${displayName}.Root\`.`
@@ -1510,10 +1526,10 @@ function InputRoot({
1510
1526
  }) {
1511
1527
  const size = useControlSize(sizeProp);
1512
1528
  const ids = useFieldFrame(id, { label, hint, error, invalid });
1513
- const labels = React13.useMemo(() => ({ ...INPUT_LABELS, ...labelsProp }), [labelsProp]);
1529
+ const labels = React14.useMemo(() => ({ ...INPUT_LABELS, ...labelsProp }), [labelsProp]);
1514
1530
  const { invalid: isInvalid, controlId: inputId, describedBy } = ids;
1515
- const inputRef = React13.useRef(null);
1516
- const contextValue = React13.useMemo(
1531
+ const inputRef = React14.useRef(null);
1532
+ const contextValue = React14.useMemo(
1517
1533
  () => ({
1518
1534
  size,
1519
1535
  invalid: isInvalid,
@@ -1651,17 +1667,17 @@ var Input = {
1651
1667
  };
1652
1668
 
1653
1669
  // src/internal/imageSlot.tsx
1654
- import * as React15 from "react";
1670
+ import * as React16 from "react";
1655
1671
 
1656
1672
  // src/hooks/useImageStatus.ts
1657
- import * as React14 from "react";
1673
+ import * as React15 from "react";
1658
1674
  function useImageStatus(report, { onLoad, onError } = {}) {
1659
- const [status, setStatus] = React14.useState("loading");
1660
- React14.useLayoutEffect(() => {
1675
+ const [status, setStatus] = React15.useState("loading");
1676
+ React15.useLayoutEffect(() => {
1661
1677
  report("loading");
1662
1678
  return () => report("idle");
1663
1679
  }, [report]);
1664
- const handleLoad = React14.useCallback(
1680
+ const handleLoad = React15.useCallback(
1665
1681
  (event) => {
1666
1682
  setStatus("loaded");
1667
1683
  report("loaded");
@@ -1669,7 +1685,7 @@ function useImageStatus(report, { onLoad, onError } = {}) {
1669
1685
  },
1670
1686
  [onLoad, report]
1671
1687
  );
1672
- const handleError = React14.useCallback(
1688
+ const handleError = React15.useCallback(
1673
1689
  (event) => {
1674
1690
  setStatus("error");
1675
1691
  report("error");
@@ -1685,8 +1701,8 @@ import { jsx as jsx18 } from "react/jsx-runtime";
1685
1701
  function createImageSlot(name, classNames) {
1686
1702
  const [Provider, useSlotContext] = createComponentContext(name);
1687
1703
  function ImageSlotProvider({ children }) {
1688
- const [imageStatus, setImageStatus] = React15.useState("idle");
1689
- const value = React15.useMemo(() => ({ imageStatus, setImageStatus }), [imageStatus]);
1704
+ const [imageStatus, setImageStatus] = React16.useState("idle");
1705
+ const value = React16.useMemo(() => ({ imageStatus, setImageStatus }), [imageStatus]);
1690
1706
  return /* @__PURE__ */ jsx18(Provider, { value, children });
1691
1707
  }
1692
1708
  function ImageInner({ src, alt = "", className, onLoad, onError, ...rest }) {
@@ -1785,10 +1801,10 @@ var Thumbnail = {
1785
1801
  };
1786
1802
 
1787
1803
  // src/components/select/Select.tsx
1788
- import * as React26 from "react";
1804
+ import * as React30 from "react";
1789
1805
 
1790
1806
  // src/internal/listbox.ts
1791
- import * as React16 from "react";
1807
+ import * as React17 from "react";
1792
1808
  var optionDomId = (listboxId, value) => `${listboxId}-opt-${value.replace(/\s+/g, "_")}`;
1793
1809
  function enabledOptions(container) {
1794
1810
  if (!container) return [];
@@ -1813,11 +1829,11 @@ function createStore(initial) {
1813
1829
  };
1814
1830
  }
1815
1831
  function useCreateStore(initial) {
1816
- return React16.useState(() => createStore(initial))[0];
1832
+ return React17.useState(() => createStore(initial))[0];
1817
1833
  }
1818
1834
  function useStoreSlice(store, select) {
1819
1835
  const read = () => select(store.get());
1820
- return React16.useSyncExternalStore(store.subscribe, read, read);
1836
+ return React17.useSyncExternalStore(store.subscribe, read, read);
1821
1837
  }
1822
1838
  function handleListboxKeyDown(event, { items, highlight, onSelect }) {
1823
1839
  if (items.length === 0) return;
@@ -1839,10 +1855,10 @@ function handleListboxKeyDown(event, { items, highlight, onSelect }) {
1839
1855
  }
1840
1856
  var TYPEAHEAD_RESET_MS = 500;
1841
1857
  function useTypeahead() {
1842
- const state = React16.useRef({ buffer: "", timer: 0 });
1843
- React16.useEffect(() => () => window.clearTimeout(state.current.timer), []);
1844
- const isTyping = React16.useCallback(() => state.current.buffer !== "", []);
1845
- const find = React16.useCallback(
1858
+ const state = React17.useRef({ buffer: "", timer: 0 });
1859
+ React17.useEffect(() => () => window.clearTimeout(state.current.timer), []);
1860
+ const isTyping = React17.useCallback(() => state.current.buffer !== "", []);
1861
+ const find = React17.useCallback(
1846
1862
  (key, items, highlighted) => {
1847
1863
  const s = state.current;
1848
1864
  window.clearTimeout(s.timer);
@@ -1864,7 +1880,7 @@ function useTypeahead() {
1864
1880
  }
1865
1881
 
1866
1882
  // src/internal/MenuGroup.tsx
1867
- import * as React17 from "react";
1883
+ import * as React18 from "react";
1868
1884
 
1869
1885
  // src/internal/menu.module.css
1870
1886
  var menu_default = {
@@ -1873,6 +1889,7 @@ var menu_default = {
1873
1889
  item: "menu_item",
1874
1890
  itemIcon: "menu_itemIcon",
1875
1891
  shortcut: "menu_shortcut",
1892
+ check: "menu_check",
1876
1893
  group: "menu_group",
1877
1894
  groupLabel: "menu_groupLabel",
1878
1895
  separator: "menu_separator",
@@ -1883,7 +1900,7 @@ var menu_default = {
1883
1900
  // src/internal/MenuGroup.tsx
1884
1901
  import { jsx as jsx20, jsxs as jsxs9 } from "react/jsx-runtime";
1885
1902
  function MenuGroup({ label, className, children, ...rest }) {
1886
- const labelId = React17.useId();
1903
+ const labelId = React18.useId();
1887
1904
  return (
1888
1905
  // biome-ignore lint/a11y/useSemanticElements: role="group" inside a menu / listbox; <fieldset> is not allowed there
1889
1906
  /* @__PURE__ */ jsxs9(
@@ -1905,13 +1922,17 @@ function MenuGroup({ label, className, children, ...rest }) {
1905
1922
  // src/internal/floatingSurface.module.css
1906
1923
  var floatingSurface_default = {
1907
1924
  surface: "floatingSurface_surface",
1908
- layer: "floatingSurface_layer"
1925
+ layer: "floatingSurface_layer",
1926
+ scrim: "floatingSurface_scrim",
1927
+ sheet: "floatingSurface_sheet",
1928
+ sheetContent: "floatingSurface_sheetContent"
1909
1929
  };
1910
1930
 
1911
1931
  // src/internal/overlayMotion.module.css
1912
1932
  var overlayMotion_default = {
1913
1933
  dialog: "overlayMotion_dialog",
1914
1934
  drawer: "overlayMotion_drawer",
1935
+ sheet: "overlayMotion_sheet",
1915
1936
  floating: "overlayMotion_floating",
1916
1937
  scrim: "overlayMotion_scrim",
1917
1938
  overlayFadeIn: "overlayMotion_overlayFadeIn",
@@ -1927,11 +1948,11 @@ var overlayMotion_default = {
1927
1948
  };
1928
1949
 
1929
1950
  // src/internal/Portal.tsx
1930
- import * as React18 from "react";
1951
+ import * as React19 from "react";
1931
1952
  import { createPortal } from "react-dom";
1932
1953
  function Portal({ children, container }) {
1933
- const [mounted, setMounted] = React18.useState(false);
1934
- React18.useLayoutEffect(() => {
1954
+ const [mounted, setMounted] = React19.useState(false);
1955
+ React19.useLayoutEffect(() => {
1935
1956
  setMounted(true);
1936
1957
  return () => setMounted(false);
1937
1958
  }, []);
@@ -1939,8 +1960,15 @@ function Portal({ children, container }) {
1939
1960
  return createPortal(children, container ?? document.body);
1940
1961
  }
1941
1962
 
1963
+ // src/internal/sheet.module.css
1964
+ var sheet_default = {
1965
+ handle: "sheet_handle",
1966
+ swipeY: "sheet_swipeY",
1967
+ swipeX: "sheet_swipeX"
1968
+ };
1969
+
1942
1970
  // src/internal/overlay/layerStack.ts
1943
- import * as React19 from "react";
1971
+ import * as React20 from "react";
1944
1972
 
1945
1973
  // src/internal/overlay/focus.ts
1946
1974
  var FOCUSABLE = [
@@ -2061,22 +2089,22 @@ function push(entry) {
2061
2089
  if (stack.length === 0) listen(false);
2062
2090
  };
2063
2091
  }
2064
- var LayerContext = React19.createContext(null);
2092
+ var LayerContext = React20.createContext(null);
2065
2093
  var LayerProvider = LayerContext.Provider;
2066
2094
  function useLayer(open, options) {
2067
- const parent = React19.useContext(LayerContext);
2068
- const [entry] = React19.useState(() => ({ parent, trap: false, ...options }));
2095
+ const parent = React20.useContext(LayerContext);
2096
+ const [entry] = React20.useState(() => ({ parent, trap: false, ...options }));
2069
2097
  entry.parent = parent;
2070
2098
  entry.refs = options.refs;
2071
2099
  entry.dismiss = options.dismiss;
2072
2100
  entry.trap = options.trap ?? false;
2073
2101
  entry.onDismiss = options.onDismiss;
2074
- React19.useLayoutEffect(() => open ? push(entry) : void 0, [open, entry]);
2102
+ React20.useLayoutEffect(() => open ? push(entry) : void 0, [open, entry]);
2075
2103
  return entry;
2076
2104
  }
2077
2105
 
2078
2106
  // src/internal/overlay/FloatingPanel.tsx
2079
- import { jsx as jsx21 } from "react/jsx-runtime";
2107
+ import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs10 } from "react/jsx-runtime";
2080
2108
  function FloatingPanel({
2081
2109
  floating,
2082
2110
  size,
@@ -2088,43 +2116,94 @@ function FloatingPanel({
2088
2116
  ref,
2089
2117
  ...rest
2090
2118
  }) {
2091
- const panelRef = useMergedRefs(floating.panelRef, ref);
2119
+ const mergedRef = useMergedRefs(floating.panelRef, ref);
2092
2120
  if (!floating.mounted) return null;
2121
+ const { sheet, presence } = floating;
2122
+ const panelRef = sheet ? ref : mergedRef;
2093
2123
  const props = {
2094
2124
  ...rest,
2095
- className: cx(
2125
+ className: sheet ? cx(floatingSurface_default.sheetContent, className) : cx(
2096
2126
  surface && floatingSurface_default.surface,
2097
2127
  floatingSurface_default.layer,
2098
2128
  overlayMotion_default.floating,
2099
2129
  className
2100
2130
  ),
2101
- "data-state": floating.presence.state,
2102
- "data-side": floating.side,
2103
2131
  "data-size": size,
2104
- onAnimationEnd: floating.presence.onExitEnd,
2132
+ ...sheet ? null : {
2133
+ "data-state": presence.state,
2134
+ "data-side": floating.side,
2135
+ onAnimationEnd: presence.onExitEnd
2136
+ },
2105
2137
  onKeyDown: (event) => {
2106
2138
  onKeyDown2?.(event);
2107
2139
  floating.onKeyDown(event);
2108
2140
  }
2109
2141
  };
2110
- return /* @__PURE__ */ jsx21(Portal, { children: /* @__PURE__ */ jsx21(LayerProvider, { value: floating.layer, children: /* @__PURE__ */ jsx21(ControlSizeProvider, { value: size, children: scroll ? /* @__PURE__ */ jsx21(ScrollContainer, { ...props, ref: panelRef, children }) : /* @__PURE__ */ jsx21("div", { ...props, ref: panelRef, children }) }) }) });
2142
+ const panel = scroll ? /* @__PURE__ */ jsx21(ScrollContainer, { ...props, ref: panelRef, children }) : /* @__PURE__ */ jsx21("div", { ...props, ref: panelRef, children });
2143
+ return /* @__PURE__ */ jsx21(Portal, { children: /* @__PURE__ */ jsx21(LayerProvider, { value: floating.layer, children: /* @__PURE__ */ jsx21(ControlSizeProvider, { value: size, children: sheet ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
2144
+ /* @__PURE__ */ jsx21(
2145
+ "div",
2146
+ {
2147
+ role: "presentation",
2148
+ className: cx(floatingSurface_default.scrim, floatingSurface_default.layer, overlayMotion_default.scrim),
2149
+ "data-state": presence.state
2150
+ }
2151
+ ),
2152
+ /* @__PURE__ */ jsxs10(
2153
+ "div",
2154
+ {
2155
+ ref: floating.panelRef,
2156
+ className: cx(
2157
+ floatingSurface_default.sheet,
2158
+ floatingSurface_default.layer,
2159
+ overlayMotion_default.sheet,
2160
+ sheet_default.swipeY
2161
+ ),
2162
+ "data-state": presence.state,
2163
+ onAnimationEnd: presence.onExitEnd,
2164
+ onPointerDown: floating.onSheetPointerDown,
2165
+ children: [
2166
+ /* @__PURE__ */ jsx21("div", { className: sheet_default.handle, "data-swipe-handle": "", "aria-hidden": "true" }),
2167
+ panel
2168
+ ]
2169
+ }
2170
+ )
2171
+ ] }) : panel }) }) });
2111
2172
  }
2112
2173
  function FloatingTrigger({ triggerProps, children, ...forwarded }) {
2113
2174
  return /* @__PURE__ */ jsx21(Slot, { ...forwarded, children: /* @__PURE__ */ jsx21(Slot, { ...triggerProps, children }) });
2114
2175
  }
2115
2176
 
2116
2177
  // src/internal/overlay/useFloatingLayer.ts
2117
- import * as React23 from "react";
2178
+ import * as React27 from "react";
2118
2179
 
2119
- // src/hooks/usePosition.ts
2180
+ // src/hooks/useMediaQuery.ts
2120
2181
  import * as React21 from "react";
2182
+ var COMPACT_QUERY = "(max-width: 639px)";
2183
+ function useMediaQuery(query, enabled = true) {
2184
+ const subscribe = React21.useCallback(
2185
+ (onChange) => {
2186
+ if (!enabled || typeof window === "undefined" || !window.matchMedia) return () => {
2187
+ };
2188
+ const mq = window.matchMedia(query);
2189
+ mq.addEventListener("change", onChange);
2190
+ return () => mq.removeEventListener("change", onChange);
2191
+ },
2192
+ [enabled, query]
2193
+ );
2194
+ const getSnapshot = () => enabled && typeof window !== "undefined" && !!window.matchMedia ? window.matchMedia(query).matches : false;
2195
+ return React21.useSyncExternalStore(subscribe, getSnapshot, () => false);
2196
+ }
2197
+
2198
+ // src/hooks/usePosition.ts
2199
+ import * as React23 from "react";
2121
2200
 
2122
2201
  // src/internal/AnchorRectContext.tsx
2123
- import * as React20 from "react";
2124
- var AnchorRectContext = React20.createContext(null);
2202
+ import * as React22 from "react";
2203
+ var AnchorRectContext = React22.createContext(null);
2125
2204
  var AnchorRectProvider = AnchorRectContext.Provider;
2126
2205
  function useAnchorRectResolver() {
2127
- return React20.useContext(AnchorRectContext);
2206
+ return React22.useContext(AnchorRectContext);
2128
2207
  }
2129
2208
 
2130
2209
  // src/internal/layoutPxFromPrimitives.ts
@@ -2249,11 +2328,11 @@ function usePosition(enabled, anchorRef, layerRef, {
2249
2328
  offsetToken = "--prime-panel-offset",
2250
2329
  arrowInset
2251
2330
  } = {}) {
2252
- const [attached, setAttached] = React21.useState(false);
2253
- const [resolvedSide, setResolvedSide] = React21.useState(preferredSide);
2331
+ const [attached, setAttached] = React23.useState(false);
2332
+ const [resolvedSide, setResolvedSide] = React23.useState(preferredSide);
2254
2333
  const resolveAnchorRect = useAnchorRectResolver();
2255
- const metricsRef = React21.useRef(null);
2256
- const update = React21.useCallback(
2334
+ const metricsRef = React23.useRef(null);
2335
+ const update = React23.useCallback(
2257
2336
  (remeasure) => {
2258
2337
  const anchor = anchorRef.current;
2259
2338
  const layer = layerRef.current;
@@ -2307,9 +2386,9 @@ function usePosition(enabled, anchorRef, layerRef, {
2307
2386
  resolveAnchorRect
2308
2387
  ]
2309
2388
  );
2310
- const updateRef = React21.useRef(update);
2389
+ const updateRef = React23.useRef(update);
2311
2390
  updateRef.current = update;
2312
- const attachLayer = React21.useCallback(
2391
+ const attachLayer = React23.useCallback(
2313
2392
  (node) => {
2314
2393
  layerRef.current = node;
2315
2394
  setAttached(node !== null);
@@ -2317,10 +2396,10 @@ function usePosition(enabled, anchorRef, layerRef, {
2317
2396
  [layerRef]
2318
2397
  );
2319
2398
  const active = enabled && attached;
2320
- React21.useLayoutEffect(() => {
2399
+ React23.useLayoutEffect(() => {
2321
2400
  if (active) update(true);
2322
2401
  }, [active, update]);
2323
- React21.useLayoutEffect(() => {
2402
+ React23.useLayoutEffect(() => {
2324
2403
  if (!active) return;
2325
2404
  let frame = 0;
2326
2405
  let remeasure = false;
@@ -2355,7 +2434,7 @@ function usePosition(enabled, anchorRef, layerRef, {
2355
2434
  }
2356
2435
 
2357
2436
  // src/hooks/usePresence.ts
2358
- import * as React22 from "react";
2437
+ import * as React24 from "react";
2359
2438
  var DURATION_FALLBACK_MS = {
2360
2439
  fast: 230,
2361
2440
  base: 380,
@@ -2386,23 +2465,177 @@ function exitTimeoutMs(token) {
2386
2465
  }
2387
2466
  function usePresence(open, options = {}) {
2388
2467
  const { exitDuration = "base" } = options;
2389
- const [mounted, setMounted] = React22.useState(open);
2468
+ const [mounted, setMounted] = React24.useState(open);
2390
2469
  if (open && !mounted) setMounted(true);
2391
2470
  if (!open && mounted && prefersReducedMotion()) setMounted(false);
2392
- const openRef = React22.useRef(open);
2471
+ const openRef = React24.useRef(open);
2393
2472
  openRef.current = open;
2394
- React22.useEffect(() => {
2473
+ React24.useEffect(() => {
2395
2474
  if (open || !mounted) return;
2396
2475
  const id = window.setTimeout(() => setMounted(false), exitTimeoutMs(exitDuration));
2397
2476
  return () => window.clearTimeout(id);
2398
2477
  }, [open, mounted, exitDuration]);
2399
- const onExitEnd = React22.useCallback((event) => {
2478
+ const onExitEnd = React24.useCallback((event) => {
2400
2479
  if (event.target !== event.currentTarget) return;
2401
2480
  if (!openRef.current) setMounted(false);
2402
2481
  }, []);
2403
2482
  return { mounted: open || mounted, state: open ? "open" : "closed", onExitEnd };
2404
2483
  }
2405
2484
 
2485
+ // src/hooks/useScrollLock.ts
2486
+ import * as React25 from "react";
2487
+ var lockCount = 0;
2488
+ var saved = null;
2489
+ function lockScroll() {
2490
+ if (lockCount === 0) {
2491
+ const { body, documentElement } = document;
2492
+ const scrollbarWidth = window.innerWidth - documentElement.clientWidth;
2493
+ saved = { overflow: body.style.overflow, paddingRight: body.style.paddingRight };
2494
+ if (scrollbarWidth > 0) {
2495
+ const padding = Number.parseFloat(window.getComputedStyle(body).paddingRight) || 0;
2496
+ body.style.paddingRight = `${padding + scrollbarWidth}px`;
2497
+ }
2498
+ body.style.overflow = "hidden";
2499
+ }
2500
+ lockCount++;
2501
+ }
2502
+ function unlockScroll() {
2503
+ lockCount = Math.max(0, lockCount - 1);
2504
+ if (lockCount === 0 && saved) {
2505
+ document.body.style.overflow = saved.overflow;
2506
+ document.body.style.paddingRight = saved.paddingRight;
2507
+ saved = null;
2508
+ }
2509
+ }
2510
+ function useScrollLock(enabled) {
2511
+ React25.useEffect(() => {
2512
+ if (!enabled) return;
2513
+ lockScroll();
2514
+ return unlockScroll;
2515
+ }, [enabled]);
2516
+ }
2517
+
2518
+ // src/hooks/useSwipeDismiss.ts
2519
+ import * as React26 from "react";
2520
+ var SLOP_PX = 8;
2521
+ var DISTANCE_RATIO = 0.3;
2522
+ var FLICK_VELOCITY = 0.5;
2523
+ var VELOCITY_WINDOW_MS = 100;
2524
+ var NO_DRAG = "input, textarea, select, [contenteditable], [role='slider']";
2525
+ var SWIPE_OFFSET_VAR = "--swipe-offset";
2526
+ var OVERPULL_PX = 24;
2527
+ function rubberBand(distance) {
2528
+ return -OVERPULL_PX * (1 - 1 / (1 + Math.abs(distance) / OVERPULL_PX));
2529
+ }
2530
+ function inCrossScroller(target, panel, horizontal) {
2531
+ for (let node = target; node && node !== panel; node = node.parentElement) {
2532
+ const style = getComputedStyle(node);
2533
+ const overflow = horizontal ? style.overflowX : style.overflowY;
2534
+ const scrolls = horizontal ? node.scrollWidth > node.clientWidth : node.scrollHeight > node.clientHeight;
2535
+ if (scrolls && (overflow === "auto" || overflow === "scroll")) return true;
2536
+ }
2537
+ return false;
2538
+ }
2539
+ function useSwipeDismiss({
2540
+ enabled,
2541
+ direction,
2542
+ onDismiss,
2543
+ handle,
2544
+ touchAnywhere = false,
2545
+ onProgress
2546
+ }) {
2547
+ const optionsRef = React26.useRef({ direction, onDismiss, handle, touchAnywhere, onProgress });
2548
+ optionsRef.current = { direction, onDismiss, handle, touchAnywhere, onProgress };
2549
+ const cleanupRef = React26.useRef(null);
2550
+ React26.useEffect(() => () => cleanupRef.current?.(), []);
2551
+ const onPointerDown2 = React26.useCallback(
2552
+ (event) => {
2553
+ if (!enabled || event.defaultPrevented || !event.isPrimary || event.button !== 0) return;
2554
+ const { direction: direction2, handle: handle2, touchAnywhere: touchAnywhere2 } = optionsRef.current;
2555
+ const panel = event.currentTarget;
2556
+ const target = event.target;
2557
+ if (target.closest(NO_DRAG)) return;
2558
+ const fromHandle = target.closest(handle2) !== null && panel.contains(target.closest(handle2));
2559
+ const horizontal = direction2 !== "down";
2560
+ if (!fromHandle) {
2561
+ if (!touchAnywhere2 || event.pointerType !== "touch") return;
2562
+ if (inCrossScroller(target, panel, horizontal)) return;
2563
+ }
2564
+ cleanupRef.current?.();
2565
+ const pointerId = event.pointerId;
2566
+ const sign = direction2 === "left" ? -1 : 1;
2567
+ const start = horizontal ? event.clientX : event.clientY;
2568
+ const startCross = horizontal ? event.clientY : event.clientX;
2569
+ let dragging = false;
2570
+ let offset = 0;
2571
+ let samples = [];
2572
+ const full = horizontal ? panel.offsetWidth : panel.offsetHeight;
2573
+ const write = (value, progress = full > 0 ? value / full : value > 0 ? 1 : 0) => {
2574
+ panel.style.setProperty(SWIPE_OFFSET_VAR, `${value * sign}px`);
2575
+ optionsRef.current.onProgress?.(Math.min(1, Math.max(0, progress)));
2576
+ };
2577
+ const finish = () => {
2578
+ window.removeEventListener("pointermove", onMove);
2579
+ window.removeEventListener("pointerup", onUp);
2580
+ window.removeEventListener("pointercancel", onCancel);
2581
+ cleanupRef.current = null;
2582
+ };
2583
+ const settle = (dismiss) => {
2584
+ delete panel.dataset.swiping;
2585
+ if (dismiss) {
2586
+ panel.dataset.swipeDismissed = "";
2587
+ write(full, 1);
2588
+ optionsRef.current.onDismiss();
2589
+ } else {
2590
+ write(0);
2591
+ }
2592
+ };
2593
+ const onMove = (move) => {
2594
+ if (move.pointerId !== pointerId) return;
2595
+ const along = ((horizontal ? move.clientX : move.clientY) - start) * sign;
2596
+ const across = (horizontal ? move.clientY : move.clientX) - startCross;
2597
+ if (!dragging) {
2598
+ if (Math.abs(along) < SLOP_PX && Math.abs(across) < SLOP_PX) return;
2599
+ if (Math.abs(across) > Math.abs(along) || !fromHandle && along < 0) {
2600
+ finish();
2601
+ return;
2602
+ }
2603
+ dragging = true;
2604
+ panel.dataset.swiping = "";
2605
+ panel.setPointerCapture?.(pointerId);
2606
+ }
2607
+ move.preventDefault();
2608
+ offset = along > 0 ? along : rubberBand(along);
2609
+ write(offset);
2610
+ const now = move.timeStamp;
2611
+ samples.push({ t: now, d: along });
2612
+ samples = samples.filter((s) => now - s.t <= VELOCITY_WINDOW_MS);
2613
+ };
2614
+ const onUp = (up) => {
2615
+ if (up.pointerId !== pointerId) return;
2616
+ finish();
2617
+ if (!dragging) return;
2618
+ const first = samples[0];
2619
+ const last = samples[samples.length - 1];
2620
+ const elapsed = first && last ? last.t - first.t : 0;
2621
+ const velocity = elapsed > 0 ? (last.d - first.d) / elapsed : 0;
2622
+ settle(offset > full * DISTANCE_RATIO || offset > SLOP_PX && velocity > FLICK_VELOCITY);
2623
+ };
2624
+ const onCancel = (cancel) => {
2625
+ if (cancel.pointerId !== pointerId) return;
2626
+ finish();
2627
+ if (dragging) settle(false);
2628
+ };
2629
+ window.addEventListener("pointermove", onMove, { passive: false });
2630
+ window.addEventListener("pointerup", onUp);
2631
+ window.addEventListener("pointercancel", onCancel);
2632
+ cleanupRef.current = finish;
2633
+ },
2634
+ [enabled]
2635
+ );
2636
+ return { onPointerDown: onPointerDown2 };
2637
+ }
2638
+
2406
2639
  // src/internal/overlay/useFloatingLayer.ts
2407
2640
  function useFloatingLayer({
2408
2641
  open,
@@ -2416,32 +2649,44 @@ function useFloatingLayer({
2416
2649
  tabExit = "none",
2417
2650
  exitDuration = "fast",
2418
2651
  skipExit = false,
2652
+ sheet: sheetOption = false,
2419
2653
  ...positionOptions
2420
2654
  }) {
2421
- const presence = usePresence(open, { exitDuration });
2655
+ const sheet = useMediaQuery(COMPACT_QUERY, sheetOption);
2656
+ const presence = usePresence(open, { exitDuration: sheet ? "base" : exitDuration });
2422
2657
  const mounted = presence.mounted && (open || !skipExit);
2423
- const contentRef = React23.useRef(null);
2424
- const position = usePosition(mounted, triggerRef, contentRef, positionOptions);
2425
- const [panel, setPanel] = React23.useState(null);
2658
+ const contentRef = React27.useRef(null);
2659
+ const position = usePosition(mounted && !sheet, triggerRef, contentRef, positionOptions);
2660
+ useScrollLock(open && sheet);
2661
+ const [panel, setPanel] = React27.useState(null);
2426
2662
  const { attachLayer } = position;
2427
- const panelRef = React23.useCallback(
2663
+ const panelRef = React27.useCallback(
2428
2664
  (node) => {
2429
2665
  attachLayer(node);
2430
2666
  setPanel(node);
2431
2667
  },
2432
2668
  [attachLayer]
2433
2669
  );
2434
- const outsideRef = React23.useRef(false);
2435
- const close = React23.useCallback(() => {
2670
+ const outsideRef = React27.useRef(false);
2671
+ const close = React27.useCallback(() => {
2436
2672
  outsideRef.current = false;
2437
2673
  onOpenChange(false);
2438
2674
  }, [onOpenChange]);
2675
+ const dismissOutside = React27.useCallback(() => {
2676
+ outsideRef.current = true;
2677
+ onOpenChange(false);
2678
+ }, [onOpenChange]);
2679
+ const swipe = useSwipeDismiss({
2680
+ enabled: sheet && open && closeOnOutsideClick,
2681
+ direction: "down",
2682
+ onDismiss: dismissOutside,
2683
+ handle: "[data-swipe-handle]"
2684
+ });
2439
2685
  const onDismiss = (reason) => {
2440
2686
  if (reason === "escape") {
2441
2687
  if (closeOnEscape) close();
2442
2688
  } else if (closeOnOutsideClick) {
2443
- outsideRef.current = true;
2444
- onOpenChange(false);
2689
+ dismissOutside();
2445
2690
  }
2446
2691
  };
2447
2692
  const layer = useLayer(open, {
@@ -2451,7 +2696,7 @@ function useFloatingLayer({
2451
2696
  onDismiss
2452
2697
  });
2453
2698
  const passive = dismiss === "none";
2454
- React23.useEffect(() => {
2699
+ React27.useEffect(() => {
2455
2700
  if (!open || !panel || passive) return;
2456
2701
  outsideRef.current = false;
2457
2702
  if (focusOnOpen) focusInto(panel);
@@ -2482,6 +2727,8 @@ function useFloatingLayer({
2482
2727
  presence,
2483
2728
  mounted,
2484
2729
  side: position.side,
2730
+ sheet,
2731
+ onSheetPointerDown: swipe.onPointerDown,
2485
2732
  panelRef,
2486
2733
  contentRef,
2487
2734
  layer,
@@ -2510,15 +2757,14 @@ var Select_default = {
2510
2757
  itemTitle: "Select_itemTitle",
2511
2758
  itemDescription: "Select_itemDescription",
2512
2759
  itemMeta: "Select_itemMeta",
2513
- media: "Select_media",
2514
- check: "Select_check"
2760
+ media: "Select_media"
2515
2761
  };
2516
2762
 
2517
2763
  // src/components/select/SelectItem.tsx
2518
- import * as React25 from "react";
2764
+ import * as React29 from "react";
2519
2765
 
2520
2766
  // src/internal/HighlightMatch.tsx
2521
- import * as React24 from "react";
2767
+ import * as React28 from "react";
2522
2768
 
2523
2769
  // src/internal/HighlightMatch.module.css
2524
2770
  var HighlightMatch_default = {
@@ -2526,7 +2772,7 @@ var HighlightMatch_default = {
2526
2772
  };
2527
2773
 
2528
2774
  // src/internal/HighlightMatch.tsx
2529
- import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs10 } from "react/jsx-runtime";
2775
+ import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
2530
2776
  function matchIndex(text, query) {
2531
2777
  if (!query) return -1;
2532
2778
  return text.toLowerCase().indexOf(query.toLowerCase());
@@ -2534,8 +2780,8 @@ function matchIndex(text, query) {
2534
2780
  function HighlightMatch({ text, query }) {
2535
2781
  const q = query.trim();
2536
2782
  const at = matchIndex(text, q);
2537
- if (at < 0) return /* @__PURE__ */ jsx22(Fragment4, { children: text });
2538
- return /* @__PURE__ */ jsxs10("span", { children: [
2783
+ if (at < 0) return /* @__PURE__ */ jsx22(Fragment5, { children: text });
2784
+ return /* @__PURE__ */ jsxs11("span", { children: [
2539
2785
  text.slice(0, at),
2540
2786
  /* @__PURE__ */ jsx22("mark", { className: HighlightMatch_default.match, children: text.slice(at, at + q.length) }),
2541
2787
  text.slice(at + q.length)
@@ -2543,7 +2789,7 @@ function HighlightMatch({ text, query }) {
2543
2789
  }
2544
2790
  function highlightChildren(children, query) {
2545
2791
  if (!query.trim()) return children;
2546
- return React24.Children.map(
2792
+ return React28.Children.map(
2547
2793
  children,
2548
2794
  (child) => typeof child === "string" || typeof child === "number" ? /* @__PURE__ */ jsx22(HighlightMatch, { text: String(child), query }) : child
2549
2795
  );
@@ -2579,13 +2825,13 @@ function createItemRegistry() {
2579
2825
  var [SelectProvider, useSelectContext] = createComponentContext("Select");
2580
2826
 
2581
2827
  // src/components/select/SelectItem.tsx
2582
- import { jsx as jsx23, jsxs as jsxs11 } from "react/jsx-runtime";
2828
+ import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
2583
2829
  var MEDIA_SIZE = { xs: "xs", s: "xs", m: "s", l: "s", xl: "m" };
2584
2830
  function textOf(node) {
2585
2831
  if (node == null || typeof node === "boolean") return "";
2586
2832
  if (typeof node === "string" || typeof node === "number") return String(node);
2587
2833
  if (Array.isArray(node)) return node.map(textOf).join("");
2588
- if (React25.isValidElement(node))
2834
+ if (React29.isValidElement(node))
2589
2835
  return textOf(node.props.children);
2590
2836
  return "";
2591
2837
  }
@@ -2593,9 +2839,9 @@ function SelectItemIcon({ className, ...rest }) {
2593
2839
  return /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: cx(menu_default.itemIcon, className), ...rest });
2594
2840
  }
2595
2841
  SelectItemIcon.displayName = "Select.ItemIcon";
2596
- var OptionQueryContext = React25.createContext("");
2842
+ var OptionQueryContext = React29.createContext("");
2597
2843
  function SelectItemText({ children, className, ...rest }) {
2598
- const query = React25.useContext(OptionQueryContext);
2844
+ const query = React29.useContext(OptionQueryContext);
2599
2845
  return /* @__PURE__ */ jsx23("span", { ...rest, className: cx(Select_default.itemTitle, className), children: highlightChildren(children, query) });
2600
2846
  }
2601
2847
  SelectItemText.displayName = "Select.ItemText";
@@ -2604,7 +2850,7 @@ function SelectItemDescription({
2604
2850
  className,
2605
2851
  ...rest
2606
2852
  }) {
2607
- const query = React25.useContext(OptionQueryContext);
2853
+ const query = React29.useContext(OptionQueryContext);
2608
2854
  return /* @__PURE__ */ jsx23("span", { ...rest, className: cx(Select_default.itemDescription, className), children: highlightChildren(children, query) });
2609
2855
  }
2610
2856
  SelectItemDescription.displayName = "Select.ItemDescription";
@@ -2622,11 +2868,11 @@ function splitItemChildren(children) {
2622
2868
  description: ""
2623
2869
  };
2624
2870
  let plain = "";
2625
- for (const child of React25.Children.toArray(children)) {
2626
- if (!React25.isValidElement(child)) {
2871
+ for (const child of React29.Children.toArray(children)) {
2872
+ if (!React29.isValidElement(child)) {
2627
2873
  plain += textOf(child);
2628
2874
  parts.body.push(child);
2629
- } else if (child.type === React25.Fragment) {
2875
+ } else if (child.type === React29.Fragment) {
2630
2876
  const inner = splitItemChildren(child.props.children);
2631
2877
  parts.leading.push(...inner.leading);
2632
2878
  parts.body.push(...inner.body);
@@ -2656,7 +2902,7 @@ function splitItemChildren(children) {
2656
2902
  }
2657
2903
  function sizeMedia(leading, size) {
2658
2904
  return leading.map(
2659
- (node) => React25.isValidElement(node) && node.type === Thumbnail.Root ? React25.cloneElement(node, {
2905
+ (node) => React29.isValidElement(node) && node.type === Thumbnail.Root ? React29.cloneElement(node, {
2660
2906
  size: node.props.size ?? MEDIA_SIZE[size],
2661
2907
  className: cx(Select_default.media, node.props.className),
2662
2908
  "aria-hidden": true
@@ -2678,7 +2924,7 @@ function SelectItem({
2678
2924
  const haystack = normalize(`${resolvedLabel} ${parts.description} ${keywords ?? ""}`);
2679
2925
  const isSelected = selected.includes(value);
2680
2926
  const isHighlighted = useStoreSlice(highlight, (current) => current === value);
2681
- React25.useLayoutEffect(
2927
+ React29.useLayoutEffect(
2682
2928
  () => registry.register(value, resolvedLabel, haystack),
2683
2929
  [registry, value, resolvedLabel, haystack]
2684
2930
  );
@@ -2687,7 +2933,7 @@ function SelectItem({
2687
2933
  return (
2688
2934
  // biome-ignore lint/a11y/useFocusableInteractive: focus stays on the listbox / search (aria-activedescendant)
2689
2935
  // biome-ignore lint/a11y/useKeyWithClickEvents: the keyboard is handled on the listbox
2690
- /* @__PURE__ */ jsxs11(
2936
+ /* @__PURE__ */ jsxs12(
2691
2937
  "div",
2692
2938
  {
2693
2939
  ref,
@@ -2715,7 +2961,7 @@ function SelectItem({
2715
2961
  sizeMedia(parts.leading, size),
2716
2962
  /* @__PURE__ */ jsx23("span", { className: Select_default.itemText, children: /* @__PURE__ */ jsx23(OptionQueryContext.Provider, { value: query, children: highlightChildren(parts.body, query) }) }),
2717
2963
  parts.meta,
2718
- multiple ? null : /* @__PURE__ */ jsx23("span", { className: Select_default.check, "aria-hidden": "true", children: isSelected ? /* @__PURE__ */ jsx23(Icon, { name: "action.check" }) : null })
2964
+ multiple ? null : /* @__PURE__ */ jsx23("span", { className: menu_default.check, "aria-hidden": "true", children: isSelected ? /* @__PURE__ */ jsx23(Icon, { name: "action.check" }) : null })
2719
2965
  ]
2720
2966
  }
2721
2967
  )
@@ -2724,7 +2970,7 @@ function SelectItem({
2724
2970
  SelectItem.displayName = "Select.Item";
2725
2971
 
2726
2972
  // src/components/select/Select.tsx
2727
- import { jsx as jsx24, jsxs as jsxs12 } from "react/jsx-runtime";
2973
+ import { jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
2728
2974
  var SELECT_LABELS = {
2729
2975
  search: "\u041F\u043E\u0438\u0441\u043A",
2730
2976
  empty: "\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E",
@@ -2761,14 +3007,14 @@ function SelectRoot(props) {
2761
3007
  ...rest
2762
3008
  } = props;
2763
3009
  const multiple = props.multiple === true;
2764
- const labels = React26.useMemo(() => ({ ...SELECT_LABELS, ...labelsProp }), [labelsProp]);
3010
+ const labels = React30.useMemo(() => ({ ...SELECT_LABELS, ...labelsProp }), [labelsProp]);
2765
3011
  const ids = useFieldFrame(id, { hint, error, invalid });
2766
3012
  const [value, setValue] = useControllableState({
2767
3013
  value: props.value,
2768
3014
  defaultValue: props.defaultValue ?? (multiple ? [] : void 0),
2769
3015
  onChange: props.onValueChange
2770
3016
  });
2771
- const selected = React26.useMemo(
3017
+ const selected = React30.useMemo(
2772
3018
  () => Array.isArray(value) ? value : value ? [value] : [],
2773
3019
  [value]
2774
3020
  );
@@ -2778,11 +3024,11 @@ function SelectRoot(props) {
2778
3024
  onChange: onOpenChange
2779
3025
  });
2780
3026
  const highlight = useCreateStore(void 0);
2781
- const [registry] = React26.useState(createItemRegistry);
2782
- const [query, setQuery] = React26.useState("");
2783
- const triggerRef = React26.useRef(null);
3027
+ const [registry] = React30.useState(createItemRegistry);
3028
+ const [query, setQuery] = React30.useState("");
3029
+ const triggerRef = React30.useRef(null);
2784
3030
  if (!isOpen && query !== "") setQuery("");
2785
- const pick = React26.useCallback(
3031
+ const pick = React30.useCallback(
2786
3032
  (optionValue) => {
2787
3033
  if (multiple) {
2788
3034
  setValue((prev) => {
@@ -2796,8 +3042,8 @@ function SelectRoot(props) {
2796
3042
  },
2797
3043
  [multiple, setValue, setOpen]
2798
3044
  );
2799
- const clear = React26.useCallback(() => setValue(multiple ? [] : ""), [multiple, setValue]);
2800
- const context = React26.useMemo(
3045
+ const clear = React30.useCallback(() => setValue(multiple ? [] : ""), [multiple, setValue]);
3046
+ const context = React30.useMemo(
2801
3047
  () => ({
2802
3048
  size,
2803
3049
  invalid: ids.invalid,
@@ -2894,7 +3140,7 @@ function SelectTrigger({
2894
3140
  } = useSelectContext();
2895
3141
  const mergedRef = useMergedRefs(triggerRef, ref);
2896
3142
  const showClear = clearable && selected.length > 0 && !disabled && !loading;
2897
- return /* @__PURE__ */ jsxs12(
3143
+ return /* @__PURE__ */ jsxs13(
2898
3144
  "button",
2899
3145
  {
2900
3146
  ...rest,
@@ -2967,7 +3213,7 @@ function SelectValue({ renderValue, className, ...rest }) {
2967
3213
  if (selected.length > 0 && renderValue && !multiple) {
2968
3214
  const value = selected[0] ?? "";
2969
3215
  const parts = splitItemChildren(renderValue({ value, label: text }));
2970
- return /* @__PURE__ */ jsxs12(
3216
+ return /* @__PURE__ */ jsxs13(
2971
3217
  "span",
2972
3218
  {
2973
3219
  ...rest,
@@ -3012,7 +3258,7 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
3012
3258
  labels,
3013
3259
  registry
3014
3260
  } = useSelectContext();
3015
- const listboxRef = React26.useRef(null);
3261
+ const listboxRef = React30.useRef(null);
3016
3262
  const floating = useFloatingLayer({
3017
3263
  open: isOpen,
3018
3264
  onOpenChange: setOpen,
@@ -3021,7 +3267,8 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
3021
3267
  align: "start",
3022
3268
  matchAnchorWidth: true,
3023
3269
  focusOnOpen: true,
3024
- tabExit: "always"
3270
+ tabExit: "always",
3271
+ sheet: true
3025
3272
  });
3026
3273
  const highlighted = useStoreSlice(highlight, (value) => value);
3027
3274
  const isEmpty = useStoreSlice(registry.version, () => !registry.anyMatch(normalize(query)));
@@ -3044,7 +3291,7 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
3044
3291
  };
3045
3292
  if (!floating.mounted) return /* @__PURE__ */ jsx24("div", { hidden: true, children });
3046
3293
  const activeDescendant = isOpen && highlighted !== void 0 ? optionDomId(listboxId, highlighted) : void 0;
3047
- return /* @__PURE__ */ jsxs12(
3294
+ return /* @__PURE__ */ jsxs13(
3048
3295
  FloatingPanel,
3049
3296
  {
3050
3297
  ...rest,
@@ -3056,7 +3303,7 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
3056
3303
  children: [
3057
3304
  searchable ? (
3058
3305
  // The permanent focus of the panel: no ring, the caret is the indicator (foundation §7).
3059
- /* @__PURE__ */ jsxs12("div", { className: cx(menu_default.searchRow, Select_default.search), "data-focus-ring": "false", children: [
3306
+ /* @__PURE__ */ jsxs13("div", { className: cx(menu_default.searchRow, Select_default.search), "data-focus-ring": "false", children: [
3060
3307
  /* @__PURE__ */ jsx24(Icon, { name: "action.search", size: "s" }),
3061
3308
  /* @__PURE__ */ jsx24(
3062
3309
  "input",
@@ -3077,7 +3324,7 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
3077
3324
  )
3078
3325
  ] })
3079
3326
  ) : null,
3080
- loading ? /* @__PURE__ */ jsxs12("div", { className: Select_default.status, role: "status", children: [
3327
+ loading ? /* @__PURE__ */ jsxs13("div", { className: Select_default.status, role: "status", children: [
3081
3328
  /* @__PURE__ */ jsx24(Spinner, { "aria-hidden": "true" }),
3082
3329
  labels.loading
3083
3330
  ] }) : null,
@@ -3097,7 +3344,7 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
3097
3344
  children
3098
3345
  }
3099
3346
  ),
3100
- isEmpty && !loading ? /* @__PURE__ */ jsxs12(EmptyPage.Root, { layout: "compact", role: "status", children: [
3347
+ isEmpty && !loading ? /* @__PURE__ */ jsxs13(EmptyPage.Root, { layout: "compact", role: "status", children: [
3101
3348
  /* @__PURE__ */ jsx24(EmptyPage.Title, { as: "p", children: labels.empty }),
3102
3349
  query !== "" && labels.emptyHint ? /* @__PURE__ */ jsx24(EmptyPage.Description, { children: labels.emptyHint }) : null
3103
3350
  ] }) : null,
@@ -3112,9 +3359,9 @@ function HighlightOnOpen({
3112
3359
  highlight
3113
3360
  }) {
3114
3361
  const { isOpen, query, selected } = useSelectContext();
3115
- const selectedRef = React26.useRef(selected);
3362
+ const selectedRef = React30.useRef(selected);
3116
3363
  selectedRef.current = selected;
3117
- React26.useLayoutEffect(() => {
3364
+ React30.useLayoutEffect(() => {
3118
3365
  if (!isOpen) return;
3119
3366
  const options = enabledOptions(listboxRef.current);
3120
3367
  const first = options.find((item) => selectedRef.current.includes(item.dataset.value ?? ""));
@@ -3122,7 +3369,7 @@ function HighlightOnOpen({
3122
3369
  first?.scrollIntoView?.({ block: "nearest" });
3123
3370
  return () => highlight.set(void 0);
3124
3371
  }, [isOpen, listboxRef, highlight]);
3125
- React26.useLayoutEffect(() => {
3372
+ React30.useLayoutEffect(() => {
3126
3373
  if (query !== "") highlight.set(enabledOptions(listboxRef.current)[0]?.dataset.value);
3127
3374
  }, [query, listboxRef, highlight]);
3128
3375
  return null;
@@ -3154,28 +3401,32 @@ export {
3154
3401
  ControlSizeProvider,
3155
3402
  useOptionalControlSize,
3156
3403
  useControlSize,
3157
- useMergedRefs,
3158
3404
  cx,
3159
3405
  toDataAttributes,
3160
- ScrollContainer,
3161
- createComponentContext,
3162
- createImageSlot,
3163
- palette_default,
3164
- textTone_default,
3165
- Icon,
3166
- createIcon,
3167
3406
  fieldSurfaceClass,
3168
3407
  fieldTierClass,
3169
3408
  fieldTriggerClass,
3170
3409
  iconLayout,
3410
+ useMergedRefs,
3171
3411
  Slot,
3412
+ touchTargetBlockClass,
3413
+ textTone_default,
3172
3414
  visuallyHiddenClass,
3173
3415
  VisuallyHidden,
3174
3416
  Spinner,
3175
3417
  Button,
3418
+ Divider,
3419
+ Icon,
3420
+ createIcon,
3421
+ useEdgeOverflow,
3422
+ ScrollContainer,
3423
+ palette_default,
3424
+ createComponentContext,
3425
+ createImageSlot,
3176
3426
  useControllableState,
3177
3427
  overlayMotion_default,
3178
3428
  Portal,
3429
+ sheet_default,
3179
3430
  focusInto,
3180
3431
  focusBack,
3181
3432
  activeElement,
@@ -3183,6 +3434,8 @@ export {
3183
3434
  useLayer,
3184
3435
  FloatingPanel,
3185
3436
  FloatingTrigger,
3437
+ COMPACT_QUERY,
3438
+ useMediaQuery,
3186
3439
  AnchorRectProvider,
3187
3440
  readCssLengthPx,
3188
3441
  getViewportPadPx,
@@ -3190,6 +3443,8 @@ export {
3190
3443
  motionDurationMs,
3191
3444
  exitTimeoutMs,
3192
3445
  usePresence,
3446
+ useScrollLock,
3447
+ useSwipeDismiss,
3193
3448
  useFloatingLayer,
3194
3449
  rovingIndex,
3195
3450
  gridIndex,
@@ -3232,7 +3487,6 @@ export {
3232
3487
  handleListboxKeyDown,
3233
3488
  menu_default,
3234
3489
  MenuGroup,
3235
- Divider,
3236
3490
  Input,
3237
3491
  Thumbnail,
3238
3492
  Select