@assure-one/design-system 1.38.0 → 1.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +63 -28
  2. package/codemods/README.md +76 -25
  3. package/codemods/lib/entry-map.mjs +315 -0
  4. package/codemods/lib/registry.mjs +28 -0
  5. package/codemods/lib/runner.mjs +8 -3
  6. package/codemods/run.mjs +27 -5
  7. package/codemods/transforms/cm-01-entry-imports.mjs +202 -0
  8. package/codemods/transforms/cm-15-dom-selectors.mjs +16 -9
  9. package/dist/brand-scope-BOHId6BY.d.ts +58 -0
  10. package/dist/brand-theme-ZYM867Jz.d.ts +59 -0
  11. package/dist/chunk-2MKLYYIY.js +3754 -0
  12. package/dist/chunk-2MKLYYIY.js.map +1 -0
  13. package/dist/chunk-6S2R2VWN.js +5527 -0
  14. package/dist/chunk-6S2R2VWN.js.map +1 -0
  15. package/dist/chunk-7U3ADR2Q.js +4336 -0
  16. package/dist/chunk-7U3ADR2Q.js.map +1 -0
  17. package/dist/chunk-CPOGSNXS.js +389 -0
  18. package/dist/chunk-CPOGSNXS.js.map +1 -0
  19. package/dist/chunk-EUHGZA6Q.js +313 -0
  20. package/dist/chunk-EUHGZA6Q.js.map +1 -0
  21. package/dist/chunk-KQBYTTAN.js +1829 -0
  22. package/dist/chunk-KQBYTTAN.js.map +1 -0
  23. package/dist/chunk-X76J4QSJ.js +164 -0
  24. package/dist/chunk-X76J4QSJ.js.map +1 -0
  25. package/dist/css/components.css +1 -1
  26. package/dist/css/legacy-aliases.css +2 -0
  27. package/dist/css/tailwind.css +2 -0
  28. package/dist/css/tokens.css +8 -6
  29. package/dist/data-table-view-ep8al7P9.d.ts +1132 -0
  30. package/dist/design-system-provider-CfD2g2lY.d.ts +142 -0
  31. package/dist/icons/index.d.ts +441 -3
  32. package/dist/icons/index.js +2 -1835
  33. package/dist/icons/index.js.map +1 -1
  34. package/dist/index.d.ts +404 -3847
  35. package/dist/index.js +8728 -24213
  36. package/dist/index.js.map +1 -1
  37. package/dist/legacy/index.d.ts +1464 -0
  38. package/dist/legacy/index.js +7 -0
  39. package/dist/legacy/index.js.map +1 -0
  40. package/dist/next/index.d.ts +2 -1
  41. package/dist/reference-BkDbrPIB.d.ts +310 -0
  42. package/dist/styles.css +2 -1
  43. package/dist/suite/index.d.ts +989 -0
  44. package/dist/suite/index.js +8 -0
  45. package/dist/suite/index.js.map +1 -0
  46. package/dist/{system-CyAVbHhM.d.ts → system-DfJIVBlJ.d.ts} +1 -310
  47. package/dist/testing/index.cjs +3 -2
  48. package/dist/testing/index.js +3 -2
  49. package/dist/tokens/index.d.ts +3 -61
  50. package/dist/tokens/index.js +3 -856
  51. package/dist/tokens/index.js.map +1 -1
  52. package/dist/{design-system-provider-B5MbvbRc.d.ts → types-Coqw8iaS.d.ts} +36 -142
  53. package/dist/vocab-DornLJbW.d.ts +76 -0
  54. package/docs/components.md +54 -52
  55. package/docs/components.registry.json +22 -8
  56. package/docs/for-ai-agents.md +12 -6
  57. package/package.json +17 -4
  58. package/public/brand/assure-audit-mark.svg +6 -0
  59. package/public/brand/assure-audit.svg +8 -0
  60. package/public/brand/assure-books-mark.svg +6 -0
  61. package/public/brand/assure-books.svg +8 -0
  62. package/public/brand/assure-pro-mark.svg +6 -0
  63. package/public/brand/assure-pro.svg +8 -0
  64. package/public/brand/assure-tax-mark.svg +6 -0
  65. package/public/brand/assure-tax.svg +8 -0
  66. package/public/brand/mycpe-teams-mark.svg +36 -0
  67. package/public/brand/mycpe-teams.svg +66 -0
  68. package/dist/index-vztxMSfl.d.ts +0 -512
@@ -0,0 +1,3754 @@
1
+ import { cn, LoaderIcon, ChevronDownIcon, ChevronUpIcon, CheckIcon, MinusIcon, ChevronRightIcon, CircleIcon, FileTextIcon, EyeOffIcon, EyeIcon, XIcon, AlertTriangleIcon, UploadIcon } from './chunk-KQBYTTAN.js';
2
+ import * as React7 from 'react';
3
+ import { createContext, forwardRef, useMemo, useState, useRef, useCallback, useEffect, useContext, useId as useId$1, useLayoutEffect } from 'react';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+ import { cva } from 'class-variance-authority';
6
+ import { Slot, Slottable } from '@radix-ui/react-slot';
7
+ export { Slot } from '@radix-ui/react-slot';
8
+ import * as AvatarPrimitive from '@radix-ui/react-avatar';
9
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
10
+ import { createPortal } from 'react-dom';
11
+ import * as SelectPrimitive from '@radix-ui/react-select';
12
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
13
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
14
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
15
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
16
+
17
+ var ThemeScopeContext = createContext(null);
18
+ function useThemeScope() {
19
+ return useContext(ThemeScopeContext);
20
+ }
21
+ function mergeScopes(parent, own) {
22
+ const merged = { ...parent };
23
+ if (own.scheme !== void 0) merged.scheme = own.scheme;
24
+ if (own.brand !== void 0) merged.brand = own.brand;
25
+ if (own.density !== void 0) merged.density = own.density;
26
+ if (own.dir !== void 0) merged.dir = own.dir;
27
+ if (own.brandTheme !== void 0) merged.brandTheme = own.brandTheme;
28
+ return merged;
29
+ }
30
+ function themeScopeAttributes(scope) {
31
+ return {
32
+ "data-ds-scheme": scope.scheme,
33
+ "data-ds-brand": scope.brand,
34
+ "data-ds-density": scope.density,
35
+ dir: scope.dir
36
+ };
37
+ }
38
+ function ThemeScopeProvider({
39
+ value,
40
+ children
41
+ }) {
42
+ const parent = useThemeScope();
43
+ const merged = useMemo(() => mergeScopes(parent, value), [parent, value]);
44
+ return /* @__PURE__ */ jsx(ThemeScopeContext, { value: merged, children });
45
+ }
46
+ var ThemeScope = forwardRef(function ThemeScope2({ scheme, brand, density, dir, brandTheme, style, children, ...props }, ref) {
47
+ const value = useMemo(
48
+ () => ({ scheme, brand, density, dir, brandTheme }),
49
+ [scheme, brand, density, dir, brandTheme]
50
+ );
51
+ return /* @__PURE__ */ jsx(ThemeScopeProvider, { value, children: /* @__PURE__ */ jsx(
52
+ "div",
53
+ {
54
+ ref,
55
+ ...themeScopeAttributes(value),
56
+ style: brandTheme ? { ...brandTheme, ...style } : style,
57
+ ...props,
58
+ children
59
+ }
60
+ ) });
61
+ });
62
+ ThemeScope.displayName = "ThemeScope";
63
+
64
+ // src/lib/micro-interactions.ts
65
+ var microInteractions = {
66
+ control: "ds:transition-[color,background-color,border-color,box-shadow] ds:duration-[var(--motion-duration-feedback)] ds:ease-[var(--motion-ease-enter)] ds:motion-reduce:transition-none",
67
+ pressable: "ds:transition-[color,background-color,border-color,box-shadow,transform] ds:[transition-duration:var(--motion-duration-feedback),var(--motion-duration-feedback),var(--motion-duration-feedback),var(--motion-duration-feedback),var(--motion-duration-press)] ds:ease-[var(--motion-ease-enter)] ds:active:scale-[0.98] ds:motion-reduce:transform-none ds:motion-reduce:transition-none",
68
+ selection: "ds:transition-[color,background-color,border-color,box-shadow] ds:duration-[var(--motion-duration-press)] ds:ease-[var(--motion-ease-enter)] ds:motion-reduce:transition-none",
69
+ disclosure: "ds:transition-[grid-template-rows,opacity,transform] ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transform-none ds:motion-reduce:transition-none",
70
+ overlay: "ds:transition-[opacity,transform] ds:duration-[var(--motion-duration-overlay)] ds:ease-[var(--motion-ease-enter)] ds:motion-reduce:transform-none ds:motion-reduce:transition-none",
71
+ progress: "ds:transition-[width,height,stroke-dashoffset,background-color] ds:duration-[var(--motion-duration-deliberate)] ds:ease-[var(--motion-ease-enter)] ds:motion-reduce:transition-none",
72
+ reveal: "ds:transition-[opacity,transform] ds:duration-[var(--motion-duration-feedback)] ds:ease-[var(--motion-ease-enter)] ds:motion-reduce:transform-none ds:motion-reduce:transition-none"
73
+ };
74
+
75
+ // src/primitives/behavior/button-base.ts
76
+ var LEGACY_BUTTON_VARIANTS = {
77
+ primary: { variant: "solid", intent: "brand" },
78
+ secondary: { variant: "soft", intent: "neutral" },
79
+ destructive: { variant: "solid", intent: "danger" },
80
+ success: { variant: "solid", intent: "success" },
81
+ dashed: { variant: "outline", intent: "neutral", look: "dashed" }
82
+ };
83
+ var DEFAULT_BUTTON_INTENT = {
84
+ solid: "brand",
85
+ soft: "neutral",
86
+ outline: "neutral",
87
+ ghost: "neutral",
88
+ link: "brand"
89
+ };
90
+ var isLegacyVariant = (value) => Object.hasOwn(LEGACY_BUTTON_VARIANTS, value);
91
+ function resolveButtonStyle({
92
+ variant,
93
+ intent
94
+ }) {
95
+ const requested = intent === "destructive" ? "danger" : intent ?? void 0;
96
+ const word = variant ?? "primary";
97
+ if (isLegacyVariant(word)) {
98
+ const legacy = LEGACY_BUTTON_VARIANTS[word];
99
+ const resolvedIntent2 = requested ?? legacy.intent;
100
+ const look = legacy.look && resolvedIntent2 === legacy.intent ? legacy.look : `${legacy.variant}/${resolvedIntent2}`;
101
+ return { variant: legacy.variant, intent: resolvedIntent2, look };
102
+ }
103
+ const resolvedIntent = requested ?? DEFAULT_BUTTON_INTENT[word];
104
+ return { variant: word, intent: resolvedIntent, look: `${word}/${resolvedIntent}` };
105
+ }
106
+ var BUTTON_LOOKS = {
107
+ // solid — filled with the intent colour, contrasting foreground
108
+ "solid/brand": "ds:bg-brand ds:text-fg-on-brand ds:hover:bg-brand-hover ds:active:bg-brand-active",
109
+ "solid/neutral": "ds:bg-fg-2 ds:text-bg ds:hover:bg-fg ds:active:bg-fg",
110
+ "solid/success": "ds:bg-success-fg ds:text-fg-on-success ds:hover:bg-success-fg-hover ds:active:bg-success-fg-active",
111
+ "solid/danger": "ds:bg-danger-fg ds:text-fg-on-danger ds:hover:bg-danger-fg-hover ds:active:bg-danger-fg-active",
112
+ // soft — tinted background, intent-coloured foreground, a hairline that shows on hover
113
+ "soft/brand": "ds:bg-brand-bg ds:text-brand ds:border ds:border-transparent ds:hover:bg-brand-bg-hover ds:hover:border-brand-line",
114
+ "soft/neutral": "ds:bg-control-secondary-bg ds:text-control-fg ds:border ds:border-control-border ds:hover:bg-control-active-bg ds:hover:border-control-border-strong",
115
+ "soft/success": "ds:bg-success-bg ds:text-success-fg ds:border ds:border-transparent ds:hover:border-success-line",
116
+ "soft/danger": "ds:bg-danger-bg ds:text-danger-fg ds:border ds:border-transparent ds:hover:border-danger-line",
117
+ // outline — border only, transparent background
118
+ "outline/brand": "ds:border ds:border-brand-line ds:bg-control-bg ds:text-brand ds:hover:bg-brand-bg",
119
+ "outline/neutral": "ds:border ds:border-control-border-strong ds:bg-control-bg ds:text-control-fg ds:hover:bg-control-hover-bg ds:hover:border-control-border-hover",
120
+ "outline/success": "ds:border ds:border-success-line ds:bg-control-bg ds:text-success-fg ds:hover:bg-success-bg",
121
+ "outline/danger": "ds:border ds:border-danger-line ds:bg-control-bg ds:text-danger-fg ds:hover:bg-danger-bg",
122
+ // ghost — nothing until hovered
123
+ "ghost/brand": "ds:bg-control-bg ds:text-brand ds:hover:bg-brand-bg",
124
+ "ghost/neutral": "ds:bg-control-bg ds:text-control-fg ds:hover:bg-control-hover-bg ds:hover:text-control-hover-fg",
125
+ "ghost/success": "ds:bg-control-bg ds:text-success-fg ds:hover:bg-success-bg",
126
+ "ghost/danger": "ds:bg-control-bg ds:text-control-destructive-fg ds:hover:bg-control-destructive-hover-bg",
127
+ // link — inline text, underlined on hover; no box of its own
128
+ "link/brand": "ds:bg-transparent ds:text-accent ds:underline-offset-4 ds:hover:underline ds:p-0 ds:h-auto ds:active:scale-100",
129
+ "link/neutral": "ds:bg-transparent ds:text-fg ds:underline-offset-4 ds:hover:underline ds:p-0 ds:h-auto ds:active:scale-100",
130
+ "link/success": "ds:bg-transparent ds:text-success-fg ds:underline-offset-4 ds:hover:underline ds:p-0 ds:h-auto ds:active:scale-100",
131
+ "link/danger": "ds:bg-transparent ds:text-danger-fg ds:underline-offset-4 ds:hover:underline ds:p-0 ds:h-auto ds:active:scale-100",
132
+ // legacy-only look (ADR-007 §4)
133
+ dashed: "ds:border-2 ds:border-dashed ds:border-control-border ds:bg-control-bg ds:text-control-muted-fg ds:hover:border-control-border-hover ds:hover:bg-control-hover-bg ds:hover:text-control-hover-fg"
134
+ };
135
+ var BUTTON_SIZES = {
136
+ // Shared scale rows (A1): height, horizontal padding, label size, gap and
137
+ // glyph size all from `--control-*-<size>`.
138
+ xs: "ds:h-(--control-height-xs) ds:px-(--control-padding-x-xs) ds:text-(length:--control-font-size-xs) ds:gap-(--control-gap-xs) ds:[&_svg]:size-(--control-icon-xs)",
139
+ // `sm` renders 16px glyphs today (the base `[&_svg]:size-4`), not the
140
+ // scale's 14, so the glyph column is left to the base until D5.
141
+ sm: "ds:h-(--control-height-sm) ds:px-(--control-padding-x-sm) ds:text-(length:--control-font-size-sm) ds:gap-(--control-gap-sm)",
142
+ xl: "ds:h-(--control-height-xl) ds:px-(--control-padding-x-xl) ds:text-(length:--control-font-size-xl) ds:gap-(--control-gap-xl) ds:[&_svg]:size-(--control-icon-xl)",
143
+ // A1 mismatches (D5): today's pixels through the compat height tokens.
144
+ md: "ds:h-(--button-height-md) ds:px-4 ds:text-sm ds:gap-2",
145
+ lg: "ds:h-(--button-height-lg) ds:px-6 ds:text-base ds:gap-2",
146
+ // Icon-only sizes: square, today's pixels through the compat tokens
147
+ // (C-BTN-SIZE-ICON). Hit target ≥ 24px (WCAG 2.5.5 floor); `icon-xs` /
148
+ // `icon-sm` are for dense in-row action stacks where `icon` (40×40) would
149
+ // visually crowd the row. `IconButton` (W3-09) takes over the geometry.
150
+ "icon-xs": "ds:size-(--button-height-icon-xs) ds:[&_svg]:size-3.5",
151
+ "icon-sm": "ds:size-(--button-height-icon-sm) ds:[&_svg]:size-4",
152
+ icon: "ds:size-(--button-height-icon)"
153
+ };
154
+ var buttonBase = cva(
155
+ cn(
156
+ "ds:inline-flex ds:items-center ds:justify-center ds:rounded-btn ds:font-medium ds:whitespace-nowrap ds:cursor-pointer",
157
+ microInteractions.pressable,
158
+ "ds:focus-visible:outline-none ds:focus-visible:[box-shadow:var(--shadow-focus-ring)]",
159
+ "ds:disabled:pointer-events-none ds:[&:disabled:not([data-loading=true])]:bg-bg-disabled ds:[&:disabled:not([data-loading=true])]:text-fg-disabled",
160
+ "ds:data-[loading=true]:cursor-wait",
161
+ "ds:[&_svg]:size-4 ds:[&_svg]:shrink-0"
162
+ ),
163
+ {
164
+ variants: {
165
+ look: BUTTON_LOOKS,
166
+ size: BUTTON_SIZES
167
+ },
168
+ defaultVariants: {
169
+ look: "solid/brand",
170
+ size: "md"
171
+ }
172
+ }
173
+ );
174
+ function buttonVariants({
175
+ variant,
176
+ intent,
177
+ size,
178
+ class: classProp,
179
+ className
180
+ } = {}) {
181
+ const { look } = resolveButtonStyle({ variant, intent });
182
+ return buttonBase({ look, size, class: cn(classProp, className) || void 0 });
183
+ }
184
+ function resolveButtonIcons({ iconStart, iconEnd, iconLeft, iconRight }, component = "Button") {
185
+ if (process.env.NODE_ENV !== "production") {
186
+ if (iconStart !== void 0 && iconLeft !== void 0) {
187
+ throw new Error(
188
+ `[${component}] \`iconStart\` and \`iconLeft\` are the same slot; pass one of them (\`iconLeft\` is the deprecated alias).`
189
+ );
190
+ }
191
+ if (iconEnd !== void 0 && iconRight !== void 0) {
192
+ throw new Error(
193
+ `[${component}] \`iconEnd\` and \`iconRight\` are the same slot; pass one of them (\`iconRight\` is the deprecated alias).`
194
+ );
195
+ }
196
+ }
197
+ return { start: iconStart ?? iconLeft, end: iconEnd ?? iconRight };
198
+ }
199
+
200
+ // src/foundation/messages/en.ts
201
+ var EN_MESSAGES = {
202
+ select: { clear: "Clear selection", placeholder: "Select..." },
203
+ searchInput: { clear: "Clear search", placeholder: "Search..." },
204
+ combobox: {
205
+ empty: "No results",
206
+ loading: "Loading\u2026",
207
+ create: (query) => `Create \u201C${query}\u201D`,
208
+ clear: "Clear",
209
+ toggle: "Show options",
210
+ remove: (label) => `Remove ${label}`
211
+ },
212
+ field: { optional: "optional" },
213
+ fileUpload: {
214
+ prompt: "Click to upload",
215
+ dragHint: " or drag and drop",
216
+ accepted: (accept) => `Accepted: ${accept}`,
217
+ maxSize: (size) => `Max size: ${size}`
218
+ },
219
+ confirm: {
220
+ confirm: "Confirm",
221
+ cancel: "Cancel",
222
+ failed: "Something went wrong. Please try again."
223
+ },
224
+ overlay: { close: "Close" },
225
+ toast: { region: "Notifications", dismiss: "Dismiss" },
226
+ commandPalette: {
227
+ name: "Command palette",
228
+ instructions: "Search and run commands",
229
+ search: "Type a command or search...",
230
+ empty: "No results found.",
231
+ navigate: "Navigate",
232
+ select: "Select",
233
+ close: "Close",
234
+ escapeKey: "esc"
235
+ },
236
+ keyboardShortcuts: {
237
+ name: "Keyboard Shortcuts",
238
+ general: "General",
239
+ commandPalette: "Command palette",
240
+ focusSearch: "Focus search",
241
+ keyboardShortcuts: "Keyboard shortcuts",
242
+ closeOrBack: "Close / go back",
243
+ then: "then",
244
+ hintPrefix: "Press",
245
+ hintSuffix: "anytime to toggle this dialog"
246
+ },
247
+ pagination: {
248
+ region: (page, total) => `Pagination, page ${page} of ${total}`,
249
+ range: (start, end, total) => `${start}\u2013${end} of ${total}`,
250
+ page: (page, total) => `Page ${page} of ${total}`,
251
+ previous: "Previous page",
252
+ next: "Next page",
253
+ rowsPerPage: "Rows per page"
254
+ },
255
+ copyButton: { copy: "Copy to clipboard", copied: "Copied" },
256
+ loadingRows: { loading: "Loading" },
257
+ progress: { progress: "Progress" },
258
+ segmentedProgress: { step: (filled, steps) => `Step ${filled} of ${steps}` },
259
+ breadcrumb: { region: "Breadcrumb" },
260
+ input: { showPassword: "Show password", hidePassword: "Hide password" },
261
+ avatar: {
262
+ image: "Avatar",
263
+ unknownUser: "Unknown user",
264
+ status: (status) => `${status} status`
265
+ },
266
+ avatarGroup: {
267
+ overflow: (count) => `+${count}`,
268
+ overflowLabel: (count) => `${count} more`
269
+ },
270
+ otpInput: { name: "One-time password" },
271
+ datePicker: {
272
+ openCalendar: "Open calendar",
273
+ pickYear: "Pick a year",
274
+ previousDecade: "Previous decade",
275
+ nextDecade: "Next decade"
276
+ },
277
+ dateRangePicker: { name: "Date range", placeholder: "Select date range" },
278
+ dismissibleChip: {
279
+ remove: "Remove filter",
280
+ removeNamed: (label) => `Remove ${label} filter`
281
+ },
282
+ multiFilterPill: {
283
+ clear: (label) => `Clear ${label} filter`,
284
+ clearSelection: "Clear selection"
285
+ },
286
+ searchSelect: {
287
+ placeholder: "Search...",
288
+ createNew: "Create new",
289
+ all: "All",
290
+ remove: (label) => `Remove ${label}`,
291
+ empty: "No results found.",
292
+ noOptions: "No options available.",
293
+ clear: "Clear",
294
+ clearNamed: (label) => `Clear ${label}`,
295
+ toggle: "Show options",
296
+ changeNamed: (label) => `Change ${label}`
297
+ },
298
+ phoneField: {
299
+ country: "Country",
300
+ searchCountries: "Search countries",
301
+ noCountries: "No countries found"
302
+ },
303
+ phoneCountryInput: {
304
+ selectCountry: "Select country code",
305
+ searchCountries: "Search country or code...",
306
+ noCountries: "No countries found"
307
+ },
308
+ starRating: {
309
+ rating: (rating, max) => `${rating} out of ${max} stars`,
310
+ half: "half"
311
+ },
312
+ fileTypeBadge: { file: (code) => `${code} file` },
313
+ attachmentChip: {
314
+ view: (name) => `View ${name}`,
315
+ download: (name) => `Download ${name}`
316
+ },
317
+ masterDetailLayout: { back: "Back" },
318
+ sidebar: {
319
+ collapse: "Collapse sidebar",
320
+ expand: "Expand sidebar",
321
+ pin: "Pin sidebar",
322
+ unpin: "Unpin sidebar",
323
+ collapseSection: "Collapse section",
324
+ expandSection: "Expand section",
325
+ navigation: "Navigation"
326
+ },
327
+ shell: { content: "Page content" },
328
+ bottomNav: { region: "Primary" },
329
+ dashGrid: { reorder: "Reorder widget" },
330
+ folderTree: {
331
+ collapse: (name) => `Collapse ${name}`,
332
+ expand: (name) => `Expand ${name}`
333
+ },
334
+ appHeader: { search: "Search\u2026" },
335
+ bulkActionBar: { clearSelection: "Clear selection" },
336
+ errorState: {
337
+ title: "Something went wrong",
338
+ retry: "Try again",
339
+ showDetails: "Show details",
340
+ hideDetails: "Hide details"
341
+ },
342
+ dataTable: {
343
+ search: "Search\u2026",
344
+ of: "of",
345
+ searchLabel: "Search",
346
+ columns: "Columns",
347
+ filterAll: "All",
348
+ selectAll: "Select all rows",
349
+ selectRow: "Select row"
350
+ },
351
+ tableStates: { loading: "Loading", empty: "No results" },
352
+ table: { region: "Scrollable table" },
353
+ stackedBarChart: { region: "Scrollable chart" },
354
+ pdfPreview: { region: "PDF preview" },
355
+ spreadsheetPreview: { region: "Spreadsheet preview" },
356
+ peoplePicker: { assignToMe: "Assign to me" },
357
+ comingSoon: { eyebrow: "Coming soon", badge: "In Development" }
358
+ };
359
+
360
+ // src/foundation/provider/context.tsx
361
+ var DesignSystemContext = createContext(null);
362
+ function useDsMessages(namespace, override) {
363
+ const provided = useContext(DesignSystemContext)?.messages?.[namespace];
364
+ return useMemo(
365
+ () => ({ ...EN_MESSAGES[namespace], ...stripUndefined(provided), ...stripUndefined(override) }),
366
+ [namespace, provided, override]
367
+ );
368
+ }
369
+ function stripUndefined(value) {
370
+ if (!value) return {};
371
+ const out = {};
372
+ for (const key of Object.keys(value)) {
373
+ if (value[key] !== void 0) out[key] = value[key];
374
+ }
375
+ return out;
376
+ }
377
+ function useLinkComponent() {
378
+ return useContext(DesignSystemContext)?.linkComponent;
379
+ }
380
+ function useImageComponent() {
381
+ return useContext(DesignSystemContext)?.imageComponent;
382
+ }
383
+ var TOOLTIP_DEFAULT_DELAY_MS = 300;
384
+ function useSharedTooltipProvider() {
385
+ return useContext(DesignSystemContext)?.sharedTooltipProvider ?? false;
386
+ }
387
+ var SPINNER_TONE_TO_INTENT = {
388
+ current: void 0,
389
+ muted: "neutral",
390
+ accent: "info",
391
+ success: "success",
392
+ warning: "warning",
393
+ destructive: "danger"
394
+ };
395
+ var spinnerCva = cva(
396
+ "ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center ds:[&_svg]:motion-reduce:animate-none",
397
+ {
398
+ variants: {
399
+ size: {
400
+ xs: "ds:[&_svg]:size-3",
401
+ sm: "ds:[&_svg]:size-4",
402
+ md: "ds:[&_svg]:size-5",
403
+ lg: "ds:[&_svg]:size-6"
404
+ },
405
+ // The six intents plus the inherit case; `intent` (public) never says `current`.
406
+ ink: {
407
+ // No `intent` inherits `currentColor` (what `tone="current"` rendered).
408
+ current: "ds:text-current",
409
+ neutral: "ds:text-fg-3",
410
+ brand: "ds:text-brand",
411
+ info: "ds:text-accent",
412
+ success: "ds:text-success-fg",
413
+ warning: "ds:text-warning-fg",
414
+ danger: "ds:text-danger-fg"
415
+ }
416
+ },
417
+ defaultVariants: {
418
+ size: "md",
419
+ ink: "current"
420
+ }
421
+ }
422
+ );
423
+ var resolveSpinnerIntent = (intent, tone) => intent ?? (tone ? SPINNER_TONE_TO_INTENT[tone] : void 0);
424
+ function spinnerVariants({ intent, tone, size } = {}) {
425
+ return spinnerCva({ ink: resolveSpinnerIntent(intent, tone), size });
426
+ }
427
+ var Spinner = forwardRef(function Spinner2({ intent, tone, size, label, className, ...props }, ref) {
428
+ return /* @__PURE__ */ jsxs(
429
+ "span",
430
+ {
431
+ ref,
432
+ role: label ? "status" : void 0,
433
+ "aria-live": label ? "polite" : void 0,
434
+ className: cn(spinnerVariants({ intent, tone, size }), className),
435
+ ...props,
436
+ children: [
437
+ /* @__PURE__ */ jsx(LoaderIcon, { className: "ds:animate-spinner", "aria-hidden": "true" }),
438
+ label && /* @__PURE__ */ jsx("span", { className: "ds:sr-only", children: label })
439
+ ]
440
+ }
441
+ );
442
+ });
443
+ Spinner.displayName = "Spinner";
444
+
445
+ // src/foundation/anatomy/define.ts
446
+ var ROOT_PART = "root";
447
+ var NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
448
+ var registry = /* @__PURE__ */ new Map();
449
+ function assertName(value, what) {
450
+ if (!NAME_PATTERN.test(value)) {
451
+ throw new TypeError(
452
+ `anatomy: ${what} must be lower-case kebab-case, received ${JSON.stringify(value)}`
453
+ );
454
+ }
455
+ }
456
+ function defineAnatomy(name, parts) {
457
+ assertName(name, "component name");
458
+ if (parts.length === 0) {
459
+ throw new TypeError(`anatomy: ${name} must declare at least one part`);
460
+ }
461
+ const seen = /* @__PURE__ */ new Set();
462
+ for (const part of parts) {
463
+ assertName(part, `part name of ${name}`);
464
+ if (seen.has(part)) {
465
+ throw new TypeError(`anatomy: ${name} declares the part ${JSON.stringify(part)} twice`);
466
+ }
467
+ seen.add(part);
468
+ }
469
+ if (registry.has(name)) {
470
+ throw new TypeError(`anatomy: ${name} is already registered`);
471
+ }
472
+ const attr = (part) => part === ROOT_PART ? name : `${name}-${String(part)}`;
473
+ const anatomy = {
474
+ name,
475
+ parts: [...parts],
476
+ attrs: parts.map((part) => attr(part)),
477
+ attr,
478
+ has: (part) => seen.has(part)
479
+ };
480
+ registry.set(name, anatomy);
481
+ return anatomy;
482
+ }
483
+
484
+ // src/foundation/anatomy/slots.ts
485
+ defineAnatomy("agreement-viewer", ["root"]);
486
+ defineAnatomy("message-composer", [
487
+ "root",
488
+ "header",
489
+ "chips",
490
+ "editor",
491
+ "below-editor",
492
+ "footer"
493
+ ]);
494
+ var codeAnatomy = defineAnatomy("code", ["root", "content"]);
495
+ var kbdAnatomy = defineAnatomy("kbd", ["root"]);
496
+ var pressableAnatomy = defineAnatomy("pressable", ["root"]);
497
+ var buttonAnatomy = defineAnatomy("button", ["root", "icon-start", "icon-end", "spinner"]);
498
+ var linkButtonAnatomy = defineAnatomy("link-button", ["root", "icon-start", "icon-end"]);
499
+ var badgeAnatomy = defineAnatomy("badge", ["root", "dot", "icon"]);
500
+ var inputAnatomy = defineAnatomy("input", [
501
+ "root",
502
+ "label",
503
+ "icon-start",
504
+ "icon-end",
505
+ "password-toggle",
506
+ "description",
507
+ "error"
508
+ ]);
509
+ var textareaAnatomy = defineAnatomy("textarea", [
510
+ "root",
511
+ "label",
512
+ "description",
513
+ "error",
514
+ "count"
515
+ ]);
516
+ var searchInputAnatomy = defineAnatomy("search-input", [
517
+ "root",
518
+ "control",
519
+ "icon",
520
+ "clear"
521
+ ]);
522
+ var selectAnatomy = defineAnatomy("select", [
523
+ "root",
524
+ "trigger",
525
+ "value",
526
+ "icon",
527
+ "clear",
528
+ "content",
529
+ "viewport",
530
+ "item",
531
+ "item-indicator",
532
+ "label",
533
+ "separator",
534
+ "scroll-up-button",
535
+ "scroll-down-button"
536
+ ]);
537
+ var checkboxAnatomy = defineAnatomy("checkbox", ["root", "indicator", "label"]);
538
+ var radioGroupAnatomy = defineAnatomy("radio-group", [
539
+ "root",
540
+ "item",
541
+ "indicator",
542
+ "label",
543
+ "card",
544
+ "description"
545
+ ]);
546
+ var switchAnatomy = defineAnatomy("switch", ["root", "thumb", "label"]);
547
+ var labelAnatomy = defineAnatomy("label", ["root", "required"]);
548
+ var numberInputAnatomy = defineAnatomy("number-input", ["root"]);
549
+ var phoneFieldAnatomy = defineAnatomy("phone-field", [
550
+ "root",
551
+ "country",
552
+ "number",
553
+ "flag"
554
+ ]);
555
+ var fileUploadAnatomy = defineAnatomy("file-upload", [
556
+ "root",
557
+ "dropzone",
558
+ "input",
559
+ "error"
560
+ ]);
561
+ var commandAnatomy = defineAnatomy("command", [
562
+ "overlay",
563
+ "content",
564
+ "title",
565
+ "description",
566
+ "root",
567
+ "input",
568
+ "list",
569
+ "empty",
570
+ "group",
571
+ "item",
572
+ "footer"
573
+ ]);
574
+ var dialogAnatomy = defineAnatomy("dialog", [
575
+ "overlay",
576
+ "content",
577
+ "header",
578
+ "title",
579
+ "description",
580
+ "body",
581
+ "footer",
582
+ "close"
583
+ ]);
584
+ var alertDialogAnatomy = defineAnatomy("alert-dialog", [
585
+ "overlay",
586
+ "content",
587
+ "header",
588
+ "title",
589
+ "description",
590
+ "footer",
591
+ "action",
592
+ "cancel"
593
+ ]);
594
+ var sheetAnatomy = defineAnatomy("sheet", [
595
+ "overlay",
596
+ "content",
597
+ "header",
598
+ "title",
599
+ "description",
600
+ "body",
601
+ "footer",
602
+ "close"
603
+ ]);
604
+ var sideDrawerAnatomy = defineAnatomy("side-drawer", [
605
+ "overlay",
606
+ "root",
607
+ "header",
608
+ "heading",
609
+ "subtitle",
610
+ "close",
611
+ "body",
612
+ "footer"
613
+ ]);
614
+ var popoverAnatomy = defineAnatomy("popover", ["content"]);
615
+ var dropdownMenuAnatomy = defineAnatomy("dropdown-menu", [
616
+ "content",
617
+ "item",
618
+ "checkbox-item",
619
+ "radio-item",
620
+ "item-indicator",
621
+ "label",
622
+ "separator",
623
+ "shortcut",
624
+ "sub-trigger",
625
+ "sub-content"
626
+ ]);
627
+ var contextMenuAnatomy = defineAnatomy("context-menu", [
628
+ "content",
629
+ "item",
630
+ "checkbox-item",
631
+ "radio-item",
632
+ "item-indicator",
633
+ "label",
634
+ "separator",
635
+ "shortcut",
636
+ "sub-trigger",
637
+ "sub-content"
638
+ ]);
639
+ var tooltipAnatomy = defineAnatomy("tooltip", ["content"]);
640
+ var toastAnatomy = defineAnatomy("toast", [
641
+ "region",
642
+ "root",
643
+ "icon",
644
+ "title",
645
+ "description",
646
+ "action",
647
+ "close"
648
+ ]);
649
+ var tableAnatomy = defineAnatomy("table", [
650
+ "root",
651
+ "wrapper",
652
+ "header",
653
+ "body",
654
+ "footer",
655
+ "row",
656
+ "head",
657
+ "cell",
658
+ "caption",
659
+ "sort",
660
+ "sort-indicator"
661
+ ]);
662
+ var dataTableAnatomy = defineAnatomy("data-table", [
663
+ "root",
664
+ "toolbar",
665
+ "spacer",
666
+ "results-count",
667
+ "header",
668
+ "body",
669
+ "row",
670
+ "head",
671
+ "head-button",
672
+ "head-indicator",
673
+ "cell",
674
+ "checkbox-cell",
675
+ "search",
676
+ "filters",
677
+ "columns-menu",
678
+ "content",
679
+ "bulk-actions",
680
+ "pagination"
681
+ ]);
682
+ var paginationAnatomy = defineAnatomy("pagination", [
683
+ "root",
684
+ "label",
685
+ "page-size",
686
+ "pages",
687
+ "previous",
688
+ "next",
689
+ "page",
690
+ "ellipsis"
691
+ ]);
692
+ var shellAnatomy = defineAnatomy("shell", ["root", "main", "content"]);
693
+ var sidebarAnatomy = defineAnatomy("sidebar", [
694
+ "root",
695
+ "trigger",
696
+ "pin",
697
+ "brand",
698
+ "brand-text",
699
+ "section",
700
+ "section-header",
701
+ "section-label",
702
+ "link",
703
+ "link-label",
704
+ "link-action",
705
+ "link-badge",
706
+ "group",
707
+ "group-link",
708
+ "group-trigger",
709
+ "group-content",
710
+ "footer",
711
+ "user",
712
+ "user-name",
713
+ "user-subtitle"
714
+ ]);
715
+ var sidebarBrandSwitcherAnatomy = defineAnatomy("sidebar-brand-switcher", [
716
+ "root",
717
+ "trigger",
718
+ "icon"
719
+ ]);
720
+ var textAnatomy = defineAnatomy("text", ["root"]);
721
+ var headingAnatomy = defineAnatomy("heading", ["root"]);
722
+ var stackAnatomy = defineAnatomy("stack", ["root"]);
723
+ var inlineAnatomy = defineAnatomy("inline", ["root"]);
724
+ var surfaceAnatomy = defineAnatomy("surface", ["root"]);
725
+ var avatarAnatomy = defineAnatomy("avatar", [
726
+ "root",
727
+ "frame",
728
+ "image",
729
+ "fallback",
730
+ "status"
731
+ ]);
732
+ var cardAnatomy = defineAnatomy("card", [
733
+ "root",
734
+ "header",
735
+ "title",
736
+ "description",
737
+ "action",
738
+ "content",
739
+ "footer"
740
+ ]);
741
+ var statusBadgeAnatomy = defineAnatomy("status-badge", ["root", "indicator", "label"]);
742
+ var iconButtonAnatomy = defineAnatomy("icon-button", ["root", "icon", "spinner"]);
743
+ var chipAnatomy = defineAnatomy("chip", ["root", "icon", "label", "count", "remove"]);
744
+ var fieldAnatomy = defineAnatomy("field", [
745
+ "root",
746
+ "label",
747
+ "required",
748
+ "optional",
749
+ "description",
750
+ "error"
751
+ ]);
752
+ var fieldsetAnatomy = defineAnatomy("fieldset", ["root", "legend"]);
753
+ var comboboxAnatomy = defineAnatomy("combobox", [
754
+ "root",
755
+ "control",
756
+ "value",
757
+ "chips",
758
+ "input",
759
+ "icon",
760
+ "clear",
761
+ "toggle",
762
+ "content",
763
+ "header",
764
+ "list",
765
+ "group",
766
+ "group-heading",
767
+ "item",
768
+ "item-indicator",
769
+ "create",
770
+ "empty",
771
+ "loading",
772
+ "footer"
773
+ ]);
774
+
775
+ // src/foundation/anatomy/slot.ts
776
+ function slot(anatomy, part) {
777
+ return { "data-slot": anatomy.attr(part) };
778
+ }
779
+ var BOOLEAN_STATES = ["disabled", "invalid", "loading", "selected", "pressed"];
780
+ var VALUE_STATES = ["state", "size", "variant", "intent", "orientation"];
781
+ function stateAttributes(input) {
782
+ const attributes = {};
783
+ for (const key of BOOLEAN_STATES) {
784
+ if (input[key]) attributes[`data-${key}`] = "";
785
+ }
786
+ for (const key of VALUE_STATES) {
787
+ const value = input[key];
788
+ if (value !== void 0) attributes[`data-${key}`] = value;
789
+ }
790
+ return attributes;
791
+ }
792
+
793
+ // src/foundation/deprecate.ts
794
+ var PREFIX = "[@assure-one/design-system]";
795
+ var warned = /* @__PURE__ */ new Set();
796
+ function devWarningsEnabled() {
797
+ return process.env.NODE_ENV !== "production" && process.env.NODE_ENV !== "test";
798
+ }
799
+ function warnOnce(id, key, message) {
800
+ return printOnce("warn", id, key, message);
801
+ }
802
+ function errorOnce(id, key, message) {
803
+ return printOnce("error", id, key, message);
804
+ }
805
+ function printOnce(level, id, key, message) {
806
+ if (!devWarningsEnabled()) return false;
807
+ const dedupeKey = `${id}:${key}`;
808
+ if (warned.has(dedupeKey)) return false;
809
+ warned.add(dedupeKey);
810
+ console[level](`${PREFIX} ${id}: ${message}`);
811
+ return true;
812
+ }
813
+ function deprecate(id, key, message) {
814
+ return false;
815
+ }
816
+ var ICON_SIZES = /* @__PURE__ */ new Set(["icon-xs", "icon-sm", "icon"]);
817
+ function warnLegacyButtonProps(component, { variant, size, iconLeft, iconRight }) {
818
+ if (size && ICON_SIZES.has(size)) ;
819
+ }
820
+
821
+ // src/primitives/behavior/inert.ts
822
+ var INERT_ATTRIBUTES = { "aria-disabled": true, tabIndex: -1 };
823
+ var INERT_CLASSES = "ds:pointer-events-none";
824
+ var DISABLED_LOOK_CLASSES = "ds:bg-bg-disabled ds:text-fg-disabled";
825
+ var isActivationKey = (key) => key === "Enter" || key === " ";
826
+ function inertHandlers(inert, handlers) {
827
+ return {
828
+ onClick(event) {
829
+ if (inert) {
830
+ event.preventDefault();
831
+ event.stopPropagation();
832
+ return;
833
+ }
834
+ handlers.onClick?.(event);
835
+ },
836
+ onKeyDown(event) {
837
+ if (inert) {
838
+ if (isActivationKey(event.key)) {
839
+ event.preventDefault();
840
+ event.stopPropagation();
841
+ }
842
+ return;
843
+ }
844
+ handlers.onKeyDown?.(event);
845
+ }
846
+ };
847
+ }
848
+ var Button = forwardRef(function Button2({
849
+ variant,
850
+ intent,
851
+ size,
852
+ asChild = false,
853
+ loading,
854
+ fullWidth,
855
+ pressed,
856
+ iconStart,
857
+ iconEnd,
858
+ iconLeft,
859
+ iconRight,
860
+ disabled,
861
+ onClick,
862
+ onKeyDown,
863
+ children,
864
+ className,
865
+ ...props
866
+ }, ref) {
867
+ warnLegacyButtonProps("Button", { variant, size, iconLeft, iconRight });
868
+ const icons = resolveButtonIcons({ iconStart, iconEnd, iconLeft, iconRight });
869
+ const inert = Boolean(disabled || loading);
870
+ const resolvedVariant = variant ?? "primary";
871
+ const resolvedSize = size ?? "md";
872
+ const state = stateAttributes({
873
+ variant: resolvedVariant,
874
+ intent: intent ?? void 0,
875
+ size: resolvedSize,
876
+ disabled: inert,
877
+ pressed
878
+ });
879
+ const start = loading ? /* @__PURE__ */ jsx(Spinner, { size: "sm", ...slot(buttonAnatomy, "spinner") }) : icons.start && /* @__PURE__ */ jsx(
880
+ "span",
881
+ {
882
+ ...slot(buttonAnatomy, "icon-start"),
883
+ className: "ds:inline-flex ds:shrink-0",
884
+ "aria-hidden": "true",
885
+ children: icons.start
886
+ }
887
+ );
888
+ const end = icons.end && !loading && /* @__PURE__ */ jsx(
889
+ "span",
890
+ {
891
+ ...slot(buttonAnatomy, "icon-end"),
892
+ className: "ds:inline-flex ds:shrink-0",
893
+ "aria-hidden": "true",
894
+ children: icons.end
895
+ }
896
+ );
897
+ if (asChild) {
898
+ const guarded = inertHandlers(inert, { onClick, onKeyDown });
899
+ const root = {
900
+ ref,
901
+ ...slot(buttonAnatomy, "root"),
902
+ ...state,
903
+ "aria-pressed": pressed,
904
+ "aria-busy": loading || void 0,
905
+ "data-loading": loading || void 0,
906
+ ...inert ? INERT_ATTRIBUTES : {},
907
+ className: cn(
908
+ buttonVariants({ variant, intent, size }),
909
+ fullWidth && "ds:w-full",
910
+ inert && INERT_CLASSES,
911
+ disabled && !loading && DISABLED_LOOK_CLASSES,
912
+ className
913
+ ),
914
+ ...props,
915
+ ...guarded
916
+ };
917
+ if (!start && !end) return /* @__PURE__ */ jsx(Slot, { ...root, children });
918
+ return /* @__PURE__ */ jsxs(Slot, { ...root, children: [
919
+ start,
920
+ /* @__PURE__ */ jsx(Slottable, { children }),
921
+ end
922
+ ] });
923
+ }
924
+ return /* @__PURE__ */ jsxs(
925
+ "button",
926
+ {
927
+ ref,
928
+ disabled: disabled || loading,
929
+ "aria-busy": loading || void 0,
930
+ "data-loading": loading || void 0,
931
+ ...slot(buttonAnatomy, "root"),
932
+ ...state,
933
+ "aria-pressed": pressed,
934
+ className: cn(buttonVariants({ variant, intent, size }), fullWidth && "ds:w-full", className),
935
+ onClick,
936
+ onKeyDown,
937
+ ...props,
938
+ type: props.type ?? "button",
939
+ children: [
940
+ start,
941
+ children,
942
+ end
943
+ ]
944
+ }
945
+ );
946
+ });
947
+ Button.displayName = "Button";
948
+
949
+ // src/foundation/anatomy/class-names.ts
950
+ function slotClassName(classNames, part) {
951
+ return classNames?.[part];
952
+ }
953
+ var avatarVariants = cva(
954
+ cn(
955
+ "ds:relative ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center ds:overflow-hidden ds:rounded-full",
956
+ "ds:font-mono ds:font-medium"
957
+ ),
958
+ {
959
+ variants: {
960
+ size: {
961
+ xs: "ds:size-(--avatar-size-xs) ds:text-[9px]",
962
+ sm: "ds:size-(--avatar-size-sm) ds:text-[10px]",
963
+ md: "ds:size-(--avatar-size-md) ds:text-[11px]",
964
+ lg: "ds:size-(--avatar-size-lg) ds:text-sm",
965
+ xl: "ds:size-(--avatar-size-xl) ds:text-base"
966
+ },
967
+ variant: {
968
+ initials: "ds:bg-bg-3 ds:text-fg-2",
969
+ branded: "ds:border ds:border-[#D8CFFF] ds:bg-pro-bg ds:text-pro-fg"
970
+ }
971
+ },
972
+ defaultVariants: {
973
+ size: "md",
974
+ variant: "initials"
975
+ }
976
+ }
977
+ );
978
+ var statusStyles = {
979
+ online: "ds:bg-success-fg",
980
+ away: "ds:bg-warning-fg",
981
+ busy: "ds:bg-danger-fg",
982
+ offline: "ds:bg-fg-4"
983
+ };
984
+ var statusDotSizes = {
985
+ xs: "ds:size-1.5",
986
+ sm: "ds:size-2",
987
+ md: "ds:size-2.5",
988
+ lg: "ds:size-3",
989
+ xl: "ds:size-3.5"
990
+ };
991
+ function getInitials(name) {
992
+ return name.split(" ").map((part) => part[0]).filter(Boolean).slice(0, 2).join("").toUpperCase();
993
+ }
994
+ var Avatar = React7.forwardRef(
995
+ function Avatar2({ src, alt, name, size = "md", variant = "initials", status, className, classNames, ...props }, ref) {
996
+ const messages = useDsMessages("avatar");
997
+ const initials = name ? getInitials(name) : "?";
998
+ const resolvedSize = size ?? "md";
999
+ const resolvedVariant = variant ?? "initials";
1000
+ return /* @__PURE__ */ jsxs(
1001
+ "span",
1002
+ {
1003
+ ...slot(avatarAnatomy, "root"),
1004
+ ...stateAttributes({ size: resolvedSize, variant: resolvedVariant }),
1005
+ className: cn("ds:relative ds:inline-flex", slotClassName(classNames, "root")),
1006
+ children: [
1007
+ /* @__PURE__ */ jsxs(
1008
+ AvatarPrimitive.Root,
1009
+ {
1010
+ ref,
1011
+ ...slot(avatarAnatomy, "frame"),
1012
+ className: cn(
1013
+ avatarVariants({ size: resolvedSize, variant: resolvedVariant }),
1014
+ slotClassName(classNames, "frame"),
1015
+ className
1016
+ ),
1017
+ ...props,
1018
+ children: [
1019
+ src ? /* @__PURE__ */ jsx(
1020
+ AvatarPrimitive.Image,
1021
+ {
1022
+ ...slot(avatarAnatomy, "image"),
1023
+ src,
1024
+ alt: alt ?? name ?? messages.image,
1025
+ className: cn(
1026
+ "ds:aspect-square ds:size-full ds:object-cover",
1027
+ slotClassName(classNames, "image")
1028
+ )
1029
+ }
1030
+ ) : null,
1031
+ /* @__PURE__ */ jsx(
1032
+ AvatarPrimitive.Fallback,
1033
+ {
1034
+ ...slot(avatarAnatomy, "fallback"),
1035
+ delayMs: src ? 200 : 0,
1036
+ className: cn(
1037
+ "ds:flex ds:size-full ds:items-center ds:justify-center",
1038
+ slotClassName(classNames, "fallback")
1039
+ ),
1040
+ "aria-label": name || messages.unknownUser,
1041
+ children: initials
1042
+ }
1043
+ )
1044
+ ]
1045
+ }
1046
+ ),
1047
+ status && /* @__PURE__ */ jsx(
1048
+ "span",
1049
+ {
1050
+ ...slot(avatarAnatomy, "status"),
1051
+ className: cn(
1052
+ "ds:ring-bg ds:absolute ds:right-0 ds:bottom-0 ds:block ds:rounded-full ds:ring-2",
1053
+ statusDotSizes[resolvedSize],
1054
+ statusStyles[status],
1055
+ slotClassName(classNames, "status")
1056
+ ),
1057
+ role: "img",
1058
+ "aria-label": messages.status(status)
1059
+ }
1060
+ )
1061
+ ]
1062
+ }
1063
+ );
1064
+ }
1065
+ );
1066
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
1067
+ function useId(explicit, prefix = "ds") {
1068
+ const generated = useId$1();
1069
+ return explicit ? explicit : `${prefix}-${generated}`;
1070
+ }
1071
+ function partId(base, part) {
1072
+ return `${base}-${part}`;
1073
+ }
1074
+ function joinIds(...ids) {
1075
+ const seen = /* @__PURE__ */ new Set();
1076
+ for (const value of ids) {
1077
+ if (!value) continue;
1078
+ for (const id of value.split(/\s+/)) {
1079
+ if (id) seen.add(id);
1080
+ }
1081
+ }
1082
+ return seen.size > 0 ? [...seen].join(" ") : void 0;
1083
+ }
1084
+
1085
+ // src/primitives/field/internal/accessible-name.ts
1086
+ var LABELABLE = "button, input, meter, output, progress, select, textarea";
1087
+ var NAMED_FROM_CONTENT = /* @__PURE__ */ new Set([
1088
+ "button",
1089
+ "checkbox",
1090
+ "link",
1091
+ "menuitem",
1092
+ "menuitemcheckbox",
1093
+ "menuitemradio",
1094
+ "option",
1095
+ "radio",
1096
+ "switch",
1097
+ "tab",
1098
+ "treeitem"
1099
+ ]);
1100
+ function text(value) {
1101
+ return typeof value === "string" && value.trim().length > 0;
1102
+ }
1103
+ function contributesText(element) {
1104
+ if (text(element.getAttribute("aria-label"))) return true;
1105
+ if (text(element.textContent)) return true;
1106
+ const value = element.value;
1107
+ return typeof value === "string" && text(value);
1108
+ }
1109
+ function isLabelable(element) {
1110
+ if (!element.matches(LABELABLE)) return false;
1111
+ return !(element instanceof HTMLInputElement && element.type === "hidden");
1112
+ }
1113
+ function isHiddenFromAssistiveTech(element) {
1114
+ if (element.closest('[aria-hidden="true"]')) return true;
1115
+ if (element.closest("[hidden]")) return true;
1116
+ return element instanceof HTMLInputElement && element.type === "hidden";
1117
+ }
1118
+ function hasAccessibleName(element) {
1119
+ const labelledBy = element.getAttribute("aria-labelledby");
1120
+ if (text(labelledBy)) {
1121
+ const root = element.ownerDocument;
1122
+ const named = labelledBy.split(/\s+/).filter(Boolean).some((id) => {
1123
+ const target = root.getElementById(id);
1124
+ return target !== null && contributesText(target);
1125
+ });
1126
+ if (named) return true;
1127
+ }
1128
+ if (text(element.getAttribute("aria-label"))) return true;
1129
+ const labels = element.labels;
1130
+ if (labels && labels.length > 0) {
1131
+ for (const label of Array.from(labels)) {
1132
+ if (text(label.textContent)) return true;
1133
+ }
1134
+ }
1135
+ const wrapping = element.closest("label");
1136
+ if (wrapping && text(wrapping.textContent)) return true;
1137
+ if (text(element.getAttribute("title"))) return true;
1138
+ if (text(element.getAttribute("placeholder"))) return true;
1139
+ const role = element.getAttribute("role") ?? implicitRole(element);
1140
+ if (role === "listbox" && element.id && isComboboxPopup(element)) return true;
1141
+ if (role && NAMED_FROM_CONTENT.has(role)) {
1142
+ if (text(element.textContent)) return true;
1143
+ if (element instanceof HTMLInputElement && text(element.value)) return true;
1144
+ }
1145
+ return false;
1146
+ }
1147
+ function isComboboxPopup(listbox) {
1148
+ const id = listbox.id;
1149
+ return Array.from(
1150
+ listbox.ownerDocument.querySelectorAll(
1151
+ "[role=combobox][aria-controls], [role=combobox][aria-owns]"
1152
+ )
1153
+ ).some((combobox) => {
1154
+ const refs = `${combobox.getAttribute("aria-controls") ?? ""} ${combobox.getAttribute("aria-owns") ?? ""}`;
1155
+ return refs.split(/\s+/).includes(id);
1156
+ });
1157
+ }
1158
+ function implicitRole(element) {
1159
+ const tag = element.tagName.toLowerCase();
1160
+ if (tag === "button") return "button";
1161
+ if (tag === "a" && element.hasAttribute("href")) return "link";
1162
+ if (tag === "input") {
1163
+ const type = element.type;
1164
+ if (type === "checkbox" || type === "radio") return type;
1165
+ if (type === "button" || type === "submit" || type === "reset") return "button";
1166
+ }
1167
+ return null;
1168
+ }
1169
+ var FIELD_PARTS = ["label", "description", "error"];
1170
+ var FieldContext = createContext(null);
1171
+ function useFieldContext() {
1172
+ return useContext(FieldContext);
1173
+ }
1174
+
1175
+ // src/primitives/field/use-field-control.ts
1176
+ function useFieldControl(props = {}) {
1177
+ const field = useFieldContext();
1178
+ const generatedId = useId(props.id, "ds-control");
1179
+ const native = props.native ?? true;
1180
+ const id = props.id ?? field?.ids.control ?? generatedId;
1181
+ const invalid = props.invalid ?? field?.invalid ?? false;
1182
+ const required = props.required ?? field?.required ?? false;
1183
+ const disabled = props.disabled ?? field?.disabled;
1184
+ const readOnly = props.readOnly ?? field?.readOnly;
1185
+ const describedBy = joinIds(
1186
+ field?.mounted.description && field.ids.description,
1187
+ field?.mounted.error && field.ids.error,
1188
+ props["aria-describedby"]
1189
+ );
1190
+ const labelledBy = props["aria-labelledby"] ?? (!native && field?.mounted.label ? field.ids.label : void 0);
1191
+ const element = useRef(null);
1192
+ const ref = useCallback((node) => {
1193
+ element.current = node;
1194
+ }, []);
1195
+ useEffect(() => {
1196
+ if (process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test") return;
1197
+ const timer = setTimeout(() => {
1198
+ const node = element.current;
1199
+ if (!node || !node.isConnected || isHiddenFromAssistiveTech(node)) return;
1200
+ if (hasAccessibleName(node)) return;
1201
+ const tag = node.tagName.toLowerCase();
1202
+ const key = `${tag}#${node.getAttribute("name") ?? id}`;
1203
+ errorOnce(
1204
+ "Field",
1205
+ key,
1206
+ `the <${tag}${node.id ? ` id="${node.id}"` : ""}> control has no accessible name. Put it inside a <Field> with a <Label>, or give it aria-label / aria-labelledby.`
1207
+ );
1208
+ }, 0);
1209
+ return () => clearTimeout(timer);
1210
+ }, [id, labelledBy, native]);
1211
+ return {
1212
+ id,
1213
+ name: props.name ?? field?.name,
1214
+ "aria-labelledby": labelledBy,
1215
+ "aria-describedby": describedBy,
1216
+ "aria-invalid": invalid ? true : void 0,
1217
+ // Native controls express it with the `required` attribute; the rest mirror
1218
+ // it in ARIA because a button cannot be `required`.
1219
+ "aria-required": required && !native ? true : void 0,
1220
+ required: required && native ? true : void 0,
1221
+ disabled,
1222
+ readOnly,
1223
+ "data-invalid": invalid ? "" : void 0,
1224
+ "data-disabled": disabled ? "" : void 0,
1225
+ ref
1226
+ };
1227
+ }
1228
+ var PortalContainerContext = createContext(void 0);
1229
+ function usePortalContainerContext() {
1230
+ return useContext(PortalContainerContext) ?? void 0;
1231
+ }
1232
+ var WRAPPER_ATTRIBUTE = "data-ds-portal";
1233
+ function stampScope(wrapper, scope) {
1234
+ const attributes = themeScopeAttributes(scope);
1235
+ for (const [name, value] of Object.entries(attributes)) {
1236
+ if (value === void 0) wrapper.removeAttribute(name);
1237
+ else wrapper.setAttribute(name, value);
1238
+ }
1239
+ wrapper.removeAttribute("style");
1240
+ wrapper.style.display = "contents";
1241
+ if (scope.brandTheme) {
1242
+ for (const [property, value] of Object.entries(scope.brandTheme)) {
1243
+ wrapper.style.setProperty(property, value);
1244
+ }
1245
+ }
1246
+ }
1247
+ function usePortalContainer(container) {
1248
+ const provided = usePortalContainerContext();
1249
+ const scope = useThemeScope();
1250
+ const wrap = container === void 0 && scope !== null;
1251
+ const [wrapper, setWrapper] = useState(null);
1252
+ useLayoutEffect(() => {
1253
+ if (!wrap || !scope) {
1254
+ setWrapper(null);
1255
+ return;
1256
+ }
1257
+ const element = document.createElement("div");
1258
+ element.setAttribute(WRAPPER_ATTRIBUTE, "");
1259
+ stampScope(element, scope);
1260
+ (provided ?? document.body).appendChild(element);
1261
+ setWrapper(element);
1262
+ return () => element.remove();
1263
+ }, [wrap, scope, provided]);
1264
+ if (container !== void 0) return container ?? void 0;
1265
+ if (wrap) return wrapper ?? void 0;
1266
+ return provided;
1267
+ }
1268
+ function withPortalContainer(RadixPortal) {
1269
+ function Portal7(props) {
1270
+ const container = usePortalContainer(props.container);
1271
+ const merged = { ...props, container };
1272
+ return /* @__PURE__ */ jsx(RadixPortal, { ...merged });
1273
+ }
1274
+ Portal7.displayName = RadixPortal.displayName ?? "Portal";
1275
+ return Portal7;
1276
+ }
1277
+ function Portal({ children, container }) {
1278
+ const resolved = usePortalContainer(container);
1279
+ const [mounted, setMounted] = useState(false);
1280
+ useLayoutEffect(() => setMounted(true), []);
1281
+ const target = resolved ?? (mounted ? document.body : null);
1282
+ return target ? createPortal(children, target) : null;
1283
+ }
1284
+ var PRESENCE_ATTRIBUTE = "data-ds-presence";
1285
+ function presence(motion) {
1286
+ return { [PRESENCE_ATTRIBUTE]: motion };
1287
+ }
1288
+ function useExitPresence(ref, open, onExited) {
1289
+ const onExitedRef = React7.useRef(onExited);
1290
+ onExitedRef.current = onExited;
1291
+ React7.useLayoutEffect(() => {
1292
+ if (open) return void 0;
1293
+ const node = ref.current;
1294
+ const running = node && typeof node.getAnimations === "function" ? node.getAnimations().filter((animation) => animation.playState !== "finished") : [];
1295
+ if (running.length === 0) {
1296
+ onExitedRef.current();
1297
+ return void 0;
1298
+ }
1299
+ let active = true;
1300
+ const exit = () => {
1301
+ if (!active) return;
1302
+ active = false;
1303
+ onExitedRef.current();
1304
+ };
1305
+ Promise.allSettled(running.map((animation) => animation.finished)).then(exit);
1306
+ const guard = setTimeout(exit, remainingTime(running) + EXIT_GUARD_GRACE_MS);
1307
+ return () => {
1308
+ active = false;
1309
+ clearTimeout(guard);
1310
+ };
1311
+ }, [open, ref]);
1312
+ }
1313
+ var EXIT_GUARD_GRACE_MS = 50;
1314
+ function remainingTime(animations) {
1315
+ let longest = 0;
1316
+ for (const animation of animations) {
1317
+ const timing = animation.effect?.getComputedTiming();
1318
+ const end = typeof timing?.endTime === "number" ? timing.endTime : 0;
1319
+ const current = typeof animation.currentTime === "number" ? animation.currentTime : 0;
1320
+ longest = Math.max(longest, end - current);
1321
+ }
1322
+ return Number.isFinite(longest) ? longest : 0;
1323
+ }
1324
+ var TooltipProvider = TooltipPrimitive.Provider;
1325
+ var TooltipTrigger = TooltipPrimitive.Trigger;
1326
+ var TooltipPortal = withPortalContainer(TooltipPrimitive.Portal);
1327
+ var Tooltip = ({ delayMs, delayDuration, children, ...props }) => {
1328
+ const shared = useSharedTooltipProvider();
1329
+ const requested = delayDuration ?? delayMs;
1330
+ if (shared) {
1331
+ return /* @__PURE__ */ jsx(
1332
+ TooltipPrimitive.Root,
1333
+ {
1334
+ ...requested !== void 0 && { delayDuration: requested },
1335
+ ...props,
1336
+ children
1337
+ }
1338
+ );
1339
+ }
1340
+ const resolvedDelay = requested ?? TOOLTIP_DEFAULT_DELAY_MS;
1341
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { delayDuration: resolvedDelay, children: /* @__PURE__ */ jsx(TooltipPrimitive.Root, { delayDuration: resolvedDelay, ...props, children }) });
1342
+ };
1343
+ Tooltip.displayName = "Tooltip";
1344
+ var TOOLTIP_MAX_WIDTH = {
1345
+ xs: "ds:max-w-xs",
1346
+ sm: "ds:max-w-sm",
1347
+ md: "ds:max-w-md",
1348
+ none: "ds:max-w-none"
1349
+ };
1350
+ var TooltipContent = React7.forwardRef(({ className, sideOffset = 6, maxWidth = "xs", ...props }, ref) => /* @__PURE__ */ jsx(TooltipPortal, { children: /* @__PURE__ */ jsx(
1351
+ TooltipPrimitive.Content,
1352
+ {
1353
+ ref,
1354
+ sideOffset,
1355
+ ...slot(tooltipAnatomy, "content"),
1356
+ ...presence("floating"),
1357
+ className: cn(
1358
+ "ds:rounded-input ds:border-rule-strong ds:bg-surface ds:z-[var(--z-tooltip)]",
1359
+ TOOLTIP_MAX_WIDTH[maxWidth],
1360
+ "ds:border ds:px-2.5 ds:py-1.5",
1361
+ "ds:font-body ds:text-fg ds:shadow-pop ds:text-xs ds:leading-tight",
1362
+ className
1363
+ ),
1364
+ ...props
1365
+ }
1366
+ ) }));
1367
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
1368
+
1369
+ // src/primitives/behavior/control-size.ts
1370
+ var CONTROL_SIZE_CLASSES = {
1371
+ xs: "ds:h-(--control-height-xs) ds:px-(--control-padding-x-xs) ds:text-(length:--control-font-size-xs) ds:gap-(--control-gap-xs) ds:[&_svg]:size-(--control-icon-xs)",
1372
+ sm: "ds:h-(--control-height-sm) ds:px-(--control-padding-x-sm) ds:text-(length:--control-font-size-sm) ds:gap-(--control-gap-sm) ds:[&_svg]:size-(--control-icon-sm)",
1373
+ md: "ds:h-(--control-height-md) ds:px-(--control-padding-x-md) ds:text-(length:--control-font-size-md) ds:gap-(--control-gap-md) ds:[&_svg]:size-(--control-icon-md)",
1374
+ lg: "ds:h-(--control-height-lg) ds:px-(--control-padding-x-lg) ds:text-(length:--control-font-size-lg) ds:gap-(--control-gap-lg) ds:[&_svg]:size-(--control-icon-lg)",
1375
+ xl: "ds:h-(--control-height-xl) ds:px-(--control-padding-x-xl) ds:text-(length:--control-font-size-xl) ds:gap-(--control-gap-xl) ds:[&_svg]:size-(--control-icon-xl)"
1376
+ };
1377
+ var SQUARE_CONTROL_SIZE_CLASSES = {
1378
+ xs: "ds:size-(--control-height-xs) ds:[&_svg]:size-(--control-icon-xs)",
1379
+ sm: "ds:size-(--control-height-sm) ds:[&_svg]:size-(--control-icon-sm)",
1380
+ md: "ds:size-(--control-height-md) ds:[&_svg]:size-(--control-icon-md)",
1381
+ lg: "ds:size-(--control-height-lg) ds:[&_svg]:size-(--control-icon-lg)",
1382
+ xl: "ds:size-(--control-height-xl) ds:[&_svg]:size-(--control-icon-xl)"
1383
+ };
1384
+ var CONTROL_GAP_CLASSES = {
1385
+ xs: "ds:gap-(--control-gap-xs)",
1386
+ sm: "ds:gap-(--control-gap-sm)",
1387
+ md: "ds:gap-(--control-gap-md)",
1388
+ lg: "ds:gap-(--control-gap-lg)",
1389
+ xl: "ds:gap-(--control-gap-xl)"
1390
+ };
1391
+ function iconButtonVariants({
1392
+ variant,
1393
+ intent,
1394
+ size = "md",
1395
+ className
1396
+ } = {}) {
1397
+ const { look } = resolveButtonStyle({ variant, intent });
1398
+ return cn(
1399
+ buttonBase({ look, size: null }),
1400
+ "ds:shrink-0 ds:p-0",
1401
+ SQUARE_CONTROL_SIZE_CLASSES[size ?? "md"],
1402
+ className
1403
+ );
1404
+ }
1405
+ var IconButton = forwardRef(function IconButton2({
1406
+ label,
1407
+ icon,
1408
+ children,
1409
+ variant,
1410
+ intent,
1411
+ size = "md",
1412
+ tooltip = true,
1413
+ tooltipSide,
1414
+ asChild = false,
1415
+ loading,
1416
+ pressed,
1417
+ disabled,
1418
+ className,
1419
+ ...props
1420
+ }, ref) {
1421
+ if (process.env.NODE_ENV !== "production" && typeof label !== "string") {
1422
+ throw new Error(
1423
+ "[IconButton] `label` is required: it is the accessible name of an icon-only control (and its default tooltip)."
1424
+ );
1425
+ }
1426
+ const style = resolveButtonStyle({ variant, intent });
1427
+ const state = stateAttributes({
1428
+ variant: style.variant,
1429
+ intent: style.intent,
1430
+ size,
1431
+ disabled: asChild ? void 0 : disabled || loading,
1432
+ loading: asChild ? void 0 : loading,
1433
+ pressed
1434
+ });
1435
+ const classes = iconButtonVariants({ variant, intent, size, className });
1436
+ const glyph = icon ?? children;
1437
+ const control = asChild ? /* @__PURE__ */ jsx(
1438
+ Slot,
1439
+ {
1440
+ ref,
1441
+ "aria-label": label,
1442
+ "aria-pressed": pressed,
1443
+ ...slot(iconButtonAnatomy, "root"),
1444
+ ...state,
1445
+ className: classes,
1446
+ ...props,
1447
+ children: glyph
1448
+ }
1449
+ ) : /* @__PURE__ */ jsx(
1450
+ "button",
1451
+ {
1452
+ ref,
1453
+ type: "button",
1454
+ "aria-label": label,
1455
+ "aria-pressed": pressed,
1456
+ "aria-busy": loading || void 0,
1457
+ disabled: disabled || loading,
1458
+ ...slot(iconButtonAnatomy, "root"),
1459
+ ...state,
1460
+ className: classes,
1461
+ ...props,
1462
+ children: loading ? (
1463
+ // `size={null}`: the glyph box is the button's `--ds-control-icon-*`.
1464
+ /* @__PURE__ */ jsx(Spinner, { size: null, ...slot(iconButtonAnatomy, "spinner") })
1465
+ ) : /* @__PURE__ */ jsx(
1466
+ "span",
1467
+ {
1468
+ ...slot(iconButtonAnatomy, "icon"),
1469
+ className: "ds:inline-flex ds:shrink-0",
1470
+ "aria-hidden": "true",
1471
+ children: glyph
1472
+ }
1473
+ )
1474
+ }
1475
+ );
1476
+ if (tooltip === false || tooltip === null || tooltip === void 0) return control;
1477
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
1478
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: control }),
1479
+ /* @__PURE__ */ jsx(TooltipContent, { ...tooltipSide !== void 0 && { side: tooltipSide }, children: tooltip === true ? label : tooltip })
1480
+ ] });
1481
+ });
1482
+ IconButton.displayName = "IconButton";
1483
+ function useControllableState({
1484
+ prop,
1485
+ defaultProp,
1486
+ onChange
1487
+ }) {
1488
+ const [uncontrolled, setUncontrolled] = useState(defaultProp);
1489
+ const isControlled = prop !== void 0;
1490
+ const value = isControlled ? prop : uncontrolled;
1491
+ const latest = useRef({ value, isControlled, onChange });
1492
+ latest.current = { value, isControlled, onChange };
1493
+ const setValue = useCallback((next) => {
1494
+ const current = latest.current;
1495
+ const resolved = typeof next === "function" ? next(current.value) : next;
1496
+ if (Object.is(resolved, current.value)) return;
1497
+ if (!current.isControlled) setUncontrolled(resolved);
1498
+ latest.current = { ...current, value: resolved };
1499
+ current.onChange?.(resolved);
1500
+ }, []);
1501
+ return [value, setValue];
1502
+ }
1503
+
1504
+ // src/primitives/behavior/collection/item-attributes.ts
1505
+ function itemSlot(anatomy) {
1506
+ return slot(anatomy, "item");
1507
+ }
1508
+ function listItemAttributes(anatomy, { id, highlighted, selected, disabled, cmdkCompat } = {}) {
1509
+ const attributes = {
1510
+ ...itemSlot(anatomy),
1511
+ role: "option",
1512
+ "aria-selected": selected === true
1513
+ };
1514
+ if (id !== void 0) attributes.id = id;
1515
+ if (disabled) attributes["aria-disabled"] = true;
1516
+ if (highlighted) attributes["data-highlighted"] = "";
1517
+ if (selected) attributes["data-selected"] = "";
1518
+ if (disabled) attributes["data-disabled"] = "";
1519
+ if (cmdkCompat) attributes["cmdk-item"] = "";
1520
+ return attributes;
1521
+ }
1522
+ function optionElementId(listId, value) {
1523
+ return `${listId}-option-${encodeURIComponent(value)}`;
1524
+ }
1525
+
1526
+ // src/primitives/behavior/collection/item-recipe.ts
1527
+ var LIST_ITEM_BOX = {
1528
+ select: "ds:rounded-surface-sm ds:relative ds:flex ds:w-full ds:cursor-default ds:items-center ds:gap-2 ds:py-1.5 ds:pr-8 ds:pl-2",
1529
+ menu: "ds:rounded-surface-sm ds:relative ds:flex ds:cursor-default ds:items-center ds:gap-2 ds:px-2 ds:py-1.5",
1530
+ "menu-indicator": "ds:rounded-surface-sm ds:relative ds:flex ds:cursor-default ds:items-center ds:gap-2 ds:py-1.5 ds:pr-2 ds:pl-8"
1531
+ };
1532
+ var LIST_ITEM_INTERACTION = "ds:outline-none ds:select-none";
1533
+ var LIST_ITEM_INK = {
1534
+ neutral: "ds:text-fg-2",
1535
+ menu: "ds:text-menu-item-fg"
1536
+ };
1537
+ var LIST_ITEM_MOTION = "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none";
1538
+ var LIST_ITEM_HIGHLIGHTED = {
1539
+ neutral: {
1540
+ focus: "ds:focus:bg-bg-2 ds:focus:text-fg",
1541
+ cmdk: "ds:data-[selected=true]:bg-bg-2 ds:data-[selected=true]:text-fg",
1542
+ "data-highlighted": "ds:data-[highlighted]:bg-bg-2 ds:data-[highlighted]:text-fg"
1543
+ },
1544
+ menu: {
1545
+ focus: "ds:focus:bg-menu-item-hover-bg ds:focus:text-menu-item-hover-fg"
1546
+ }
1547
+ };
1548
+ var LIST_ITEM_SELECTED = {
1549
+ "radix-checked": "ds:data-[state=checked]:bg-brand-bg ds:data-[state=checked]:text-brand",
1550
+ "aria-selected": "ds:aria-selected:bg-brand-bg ds:aria-selected:text-brand",
1551
+ none: ""
1552
+ };
1553
+ var LIST_ITEM_DISABLED = "ds:data-[disabled]:text-fg-disabled ds:data-[disabled]:pointer-events-none";
1554
+ var LIST_ITEM_GLYPH = "ds:[&_svg]:size-4 ds:[&_svg]:shrink-0";
1555
+ var LIST_ITEM_INDICATOR_WELL = {
1556
+ end: "ds:absolute ds:right-2 ds:flex ds:size-4 ds:items-center ds:justify-center",
1557
+ start: "ds:absolute ds:left-2 ds:flex ds:size-4 ds:items-center ds:justify-center"
1558
+ };
1559
+ var LIST_GROUP_HEADING_INK = {
1560
+ neutral: "ds:text-fg-3",
1561
+ menu: "ds:text-menu-label-fg"
1562
+ };
1563
+ var LIST_GROUP_HEADING_BOX = "ds:px-2 ds:py-1.5 ds:font-mono";
1564
+ var LIST_GROUP_HEADING_TYPE = "ds:tracking-wider ds:uppercase";
1565
+ function groupHeadingClasses({
1566
+ palette,
1567
+ labelSize
1568
+ }) {
1569
+ return [
1570
+ LIST_GROUP_HEADING_INK[palette],
1571
+ LIST_GROUP_HEADING_BOX,
1572
+ labelSize,
1573
+ LIST_GROUP_HEADING_TYPE
1574
+ ].join(" ");
1575
+ }
1576
+ var LIST_SEPARATOR = {
1577
+ neutral: "ds:bg-rule ds:-mx-1 ds:my-1 ds:h-px",
1578
+ menu: "ds:bg-menu-border ds:-mx-1 ds:my-1 ds:h-px"
1579
+ };
1580
+ function listItemClasses({
1581
+ frame,
1582
+ labelSize,
1583
+ palette,
1584
+ highlight,
1585
+ selected,
1586
+ glyph = true
1587
+ }) {
1588
+ const highlighted = LIST_ITEM_HIGHLIGHTED[palette][highlight];
1589
+ if (highlighted === void 0) {
1590
+ throw new TypeError(
1591
+ `collection: no highlighted row for palette ${JSON.stringify(palette)} with ${JSON.stringify(highlight)}; write the literal in item-recipe.ts`
1592
+ );
1593
+ }
1594
+ return [
1595
+ LIST_ITEM_BOX[frame],
1596
+ labelSize,
1597
+ LIST_ITEM_INTERACTION,
1598
+ LIST_ITEM_INK[palette],
1599
+ LIST_ITEM_MOTION,
1600
+ highlighted,
1601
+ LIST_ITEM_SELECTED[selected],
1602
+ LIST_ITEM_DISABLED,
1603
+ glyph ? LIST_ITEM_GLYPH : ""
1604
+ ].filter(Boolean).join(" ");
1605
+ }
1606
+
1607
+ // src/primitives/behavior/button-type.ts
1608
+ function describeForm(form) {
1609
+ const id = form.getAttribute("id");
1610
+ if (id) return `form#${id}`;
1611
+ const name = form.getAttribute("name");
1612
+ if (name) return `form[name="${name}"]`;
1613
+ const label = form.getAttribute("aria-label");
1614
+ if (label) return `form[aria-label="${label}"]`;
1615
+ const action = form.getAttribute("action");
1616
+ if (action) return `form[action="${action}"]`;
1617
+ return "form";
1618
+ }
1619
+ var FORM_BRIDGE_DUPLICATE_ID = "C-HIDDEN-MIRRORS";
1620
+ function serializeFormValue(value, { submitEmpty = true } = {}) {
1621
+ if (Array.isArray(value)) return [...value];
1622
+ if (value == null || value === "") return submitEmpty ? [""] : [];
1623
+ return [value];
1624
+ }
1625
+ var PROXY_STYLE = {
1626
+ position: "absolute",
1627
+ width: 1,
1628
+ height: 1,
1629
+ padding: 0,
1630
+ margin: -1,
1631
+ overflow: "hidden",
1632
+ clip: "rect(0, 0, 0, 0)",
1633
+ whiteSpace: "nowrap",
1634
+ border: 0,
1635
+ opacity: 0,
1636
+ pointerEvents: "none"
1637
+ };
1638
+ var noop = () => {
1639
+ };
1640
+ var forwardFocus = (target) => {
1641
+ const element = target?.current;
1642
+ if (element && element.ownerDocument.activeElement !== element) element.focus();
1643
+ };
1644
+ function FormBridge({
1645
+ name,
1646
+ value,
1647
+ submitEmpty = true,
1648
+ form,
1649
+ disabled = false,
1650
+ required = false,
1651
+ focusTarget,
1652
+ onReset
1653
+ }) {
1654
+ const instance = useId$1();
1655
+ const anchorRef = useRef(null);
1656
+ const values = name ? serializeFormValue(value, { submitEmpty }) : [];
1657
+ const filled = values.some((entry) => entry !== "");
1658
+ useFormReset(anchorRef, onReset, name, form);
1659
+ useDuplicateNameWarning(anchorRef, instance, name, form, disabled ? 0 : values.length);
1660
+ if (!name) return null;
1661
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1662
+ values.map((entry, index) => /* @__PURE__ */ jsx(
1663
+ "input",
1664
+ {
1665
+ ref: index === 0 ? anchorRef : void 0,
1666
+ type: "hidden",
1667
+ name,
1668
+ value: entry,
1669
+ form,
1670
+ disabled,
1671
+ "data-form-bridge": instance
1672
+ },
1673
+ index
1674
+ )),
1675
+ values.length === 0 && // Resolves the form for the reset listener and the duplicate check;
1676
+ // disabled and unnamed, so it is never submitted.
1677
+ /* @__PURE__ */ jsx("input", { ref: anchorRef, type: "hidden", form, disabled: true, "data-form-bridge": instance }),
1678
+ required && !disabled && /* @__PURE__ */ jsx(
1679
+ "input",
1680
+ {
1681
+ type: "text",
1682
+ "aria-hidden": "true",
1683
+ tabIndex: -1,
1684
+ required: true,
1685
+ form,
1686
+ value: filled ? "filled" : "",
1687
+ onChange: noop,
1688
+ onInvalid: () => forwardFocus(focusTarget),
1689
+ onFocus: () => forwardFocus(focusTarget),
1690
+ style: PROXY_STYLE,
1691
+ "data-form-bridge-validation": instance
1692
+ }
1693
+ )
1694
+ ] });
1695
+ }
1696
+ function useFormReset(anchorRef, onReset, name, form) {
1697
+ const latest = useRef(onReset);
1698
+ latest.current = onReset;
1699
+ useEffect(() => {
1700
+ const owner = anchorRef.current?.form;
1701
+ if (!owner || !name) return;
1702
+ const handle = () => latest.current?.();
1703
+ owner.addEventListener("reset", handle);
1704
+ return () => owner.removeEventListener("reset", handle);
1705
+ }, [anchorRef, name, form]);
1706
+ }
1707
+ function useDuplicateNameWarning(anchorRef, instance, name, form, ownCount) {
1708
+ useEffect(() => {
1709
+ if (!name || ownCount === 0 || !devWarningsEnabled()) return;
1710
+ const owner = anchorRef.current?.form;
1711
+ if (!owner) return;
1712
+ const others = Array.from(owner.elements).filter((element) => {
1713
+ const control = element;
1714
+ return control.name === name && control.getAttribute("data-form-bridge") !== instance && !control.matches(":disabled");
1715
+ });
1716
+ if (others.length === 0) return;
1717
+ const where = describeForm(owner);
1718
+ warnOnce(
1719
+ FORM_BRIDGE_DUPLICATE_ID,
1720
+ `${where}::${name}`,
1721
+ `field "${name}" in ${where} is also submitted by ${others.length} other control${others.length === 1 ? "" : "s"} with the same name (a hidden <input> mirror, most likely), so FormData carries it twice and formData.get("${name}") returns whichever comes first in DOM order. Remove the mirror, or drop \`name\` from the design-system control.`
1722
+ );
1723
+ }, [anchorRef, instance, name, form, ownCount]);
1724
+ }
1725
+ var SelectRoot = SelectPrimitive.Root;
1726
+ var SelectGroup = SelectPrimitive.Group;
1727
+ var SelectValue = SelectPrimitive.Value;
1728
+ function useTriggerOpen(node) {
1729
+ const [open, setOpen] = React7.useState(false);
1730
+ React7.useEffect(() => {
1731
+ if (!node) return;
1732
+ const sync = () => setOpen(node.getAttribute("data-state") === "open");
1733
+ sync();
1734
+ const observer = new MutationObserver(sync);
1735
+ observer.observe(node, { attributes: true, attributeFilter: ["data-state"] });
1736
+ return () => observer.disconnect();
1737
+ }, [node]);
1738
+ return open;
1739
+ }
1740
+ var SelectTrigger = React7.forwardRef(({ className, children, tabIndex, size, classNames, ...props }, ref) => {
1741
+ const [node, setNode] = React7.useState(null);
1742
+ const open = useTriggerOpen(node);
1743
+ const composedRef = React7.useCallback(
1744
+ (element) => {
1745
+ setNode(element);
1746
+ if (typeof ref === "function") ref(element);
1747
+ else if (ref) ref.current = element;
1748
+ },
1749
+ [ref]
1750
+ );
1751
+ return /* @__PURE__ */ jsxs(
1752
+ SelectPrimitive.Trigger,
1753
+ {
1754
+ ref: composedRef,
1755
+ tabIndex: open ? -1 : tabIndex,
1756
+ ...slot(selectAnatomy, "trigger"),
1757
+ ...stateAttributes({ size: size ?? void 0 }),
1758
+ className: cn(
1759
+ // The legacy geometry row (`h-9 gap-2 px-3 py-2 text-[13px]`) is the
1760
+ // scale's `md` in pixels; it stays inline, byte for byte, until D5
1761
+ // settles the size numbers. A `size` swaps it for the token row.
1762
+ size == null ? "ds:rounded-input ds:border-field-border ds:bg-surface ds:font-body ds:text-fg ds:flex ds:h-9 ds:w-full ds:items-center ds:justify-between ds:gap-2 ds:border ds:px-3 ds:py-2 ds:text-[13px]" : cn(
1763
+ "ds:rounded-input ds:border-field-border ds:bg-surface ds:font-body ds:text-fg ds:flex ds:w-full ds:items-center ds:justify-between ds:border ds:py-2",
1764
+ CONTROL_SIZE_CLASSES[size]
1765
+ ),
1766
+ "ds:transition-[color,background-color,border-color,box-shadow] ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)]",
1767
+ "ds:motion-reduce:transition-none",
1768
+ "ds:placeholder:text-fg-4",
1769
+ "ds:not-disabled:hover:border-field-border-hover",
1770
+ "ds:focus-visible:[border-color:var(--focus-ring-border)] ds:focus-visible:[box-shadow:var(--shadow-focus-ring-field)] ds:focus-visible:outline-none",
1771
+ "ds:disabled:bg-bg-disabled ds:disabled:text-fg-disabled ds:disabled:cursor-not-allowed",
1772
+ "ds:data-[placeholder]:text-fg-4",
1773
+ "ds:aria-[invalid=true]:border-field-border-invalid ds:aria-[invalid=true]:focus-visible:border-danger-fg",
1774
+ "ds:aria-[invalid=true]:focus-visible:[box-shadow:0_0_0_2px_var(--color-danger-bg)]",
1775
+ "ds:[&>span]:line-clamp-1 ds:[&>span]:text-left",
1776
+ className
1777
+ ),
1778
+ ...props,
1779
+ children: [
1780
+ classNames?.value !== void 0 ? /* @__PURE__ */ jsx("span", { ...slot(selectAnatomy, "value"), className: classNames.value, children }) : children,
1781
+ /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(
1782
+ ChevronDownIcon,
1783
+ {
1784
+ ...slot(selectAnatomy, "icon"),
1785
+ className: cn(
1786
+ "ds:text-fg-3 ds:size-4 ds:shrink-0 ds:translate-y-px ds:transition-transform ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:data-[state=open]:rotate-180 ds:motion-reduce:transition-none",
1787
+ classNames?.icon
1788
+ ),
1789
+ "aria-hidden": "true"
1790
+ }
1791
+ ) })
1792
+ ]
1793
+ }
1794
+ );
1795
+ });
1796
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
1797
+ var SelectScrollUpButton = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1798
+ SelectPrimitive.ScrollUpButton,
1799
+ {
1800
+ ref,
1801
+ ...slot(selectAnatomy, "scroll-up-button"),
1802
+ className: cn(
1803
+ "ds:text-fg-3 ds:flex ds:cursor-default ds:items-center ds:justify-center ds:py-1",
1804
+ className
1805
+ ),
1806
+ ...props,
1807
+ children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "ds:size-4", "aria-hidden": "true" })
1808
+ }
1809
+ ));
1810
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
1811
+ var SelectScrollDownButton = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1812
+ SelectPrimitive.ScrollDownButton,
1813
+ {
1814
+ ref,
1815
+ ...slot(selectAnatomy, "scroll-down-button"),
1816
+ className: cn(
1817
+ "ds:text-fg-3 ds:flex ds:cursor-default ds:items-center ds:justify-center ds:py-1",
1818
+ className
1819
+ ),
1820
+ ...props,
1821
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "ds:size-4", "aria-hidden": "true" })
1822
+ }
1823
+ ));
1824
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
1825
+ var SelectPortal = withPortalContainer(SelectPrimitive.Portal);
1826
+ var SelectContent = React7.forwardRef(({ className, children, position = "popper", classNames, ...props }, ref) => /* @__PURE__ */ jsx(SelectPortal, { children: /* @__PURE__ */ jsxs(
1827
+ SelectPrimitive.Content,
1828
+ {
1829
+ ref,
1830
+ position,
1831
+ ...slot(selectAnatomy, "content"),
1832
+ className: cn(
1833
+ "ds:rounded-card ds:border-rule ds:bg-surface ds:text-fg ds:shadow-pop ds:relative ds:z-[var(--z-dropdown)] ds:max-h-(--radix-select-content-available-height) ds:min-w-[8rem] ds:overflow-hidden ds:border",
1834
+ "ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out",
1835
+ "ds:data-[state=closed]:fade-out-0 ds:data-[state=open]:fade-in-0",
1836
+ "ds:data-[state=closed]:zoom-out-95 ds:data-[state=open]:zoom-in-95",
1837
+ "ds:data-[side=bottom]:slide-in-from-top-2 ds:data-[side=left]:slide-in-from-right-2",
1838
+ "ds:data-[side=right]:slide-in-from-left-2 ds:data-[side=top]:slide-in-from-bottom-2",
1839
+ "ds:motion-reduce:transition-none",
1840
+ position === "popper" && "ds:data-[side=bottom]:translate-y-1 ds:data-[side=left]:-translate-x-1 ds:data-[side=right]:translate-x-1 ds:data-[side=top]:-translate-y-1",
1841
+ className
1842
+ ),
1843
+ ...props,
1844
+ children: [
1845
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
1846
+ /* @__PURE__ */ jsx(
1847
+ SelectPrimitive.Viewport,
1848
+ {
1849
+ ...slot(selectAnatomy, "viewport"),
1850
+ className: cn(
1851
+ "ds:p-1",
1852
+ position === "popper" && "ds:h-(--radix-select-trigger-height) ds:w-full ds:min-w-(--radix-select-trigger-width)",
1853
+ classNames?.viewport
1854
+ ),
1855
+ children
1856
+ }
1857
+ ),
1858
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
1859
+ ]
1860
+ }
1861
+ ) }));
1862
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
1863
+ var SelectLabel = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1864
+ SelectPrimitive.Label,
1865
+ {
1866
+ ref,
1867
+ ...slot(selectAnatomy, "label"),
1868
+ className: cn(
1869
+ groupHeadingClasses({ palette: "neutral", labelSize: "ds:text-[11px]" }),
1870
+ className
1871
+ ),
1872
+ ...props
1873
+ }
1874
+ ));
1875
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
1876
+ var SelectItem = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1877
+ SelectPrimitive.Item,
1878
+ {
1879
+ ref,
1880
+ ...itemSlot(selectAnatomy),
1881
+ className: cn(
1882
+ // Radix focuses the highlighted row and stamps `data-state="checked"`
1883
+ // on the selected one, so those are the selectors the rows read. The
1884
+ // label size is the scale's `md` (13px, the row's size since 1.0):
1885
+ // W4-08 took it from the control tokens with zero diff
1886
+ // (`tests/browser/select-form.test.tsx`).
1887
+ listItemClasses({
1888
+ frame: "select",
1889
+ labelSize: "ds:text-(length:--control-font-size-md)",
1890
+ palette: "neutral",
1891
+ highlight: "focus",
1892
+ selected: "radix-checked"
1893
+ }),
1894
+ className
1895
+ ),
1896
+ ...props,
1897
+ children: [
1898
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children }),
1899
+ /* @__PURE__ */ jsx("span", { className: LIST_ITEM_INDICATOR_WELL.end, children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { ...slot(selectAnatomy, "item-indicator"), children: /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-3.5", "aria-hidden": "true" }) }) })
1900
+ ]
1901
+ }
1902
+ ));
1903
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
1904
+ var SelectSeparator = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1905
+ SelectPrimitive.Separator,
1906
+ {
1907
+ ref,
1908
+ ...slot(selectAnatomy, "separator"),
1909
+ className: cn(LIST_SEPARATOR.neutral, className),
1910
+ ...props
1911
+ }
1912
+ ));
1913
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
1914
+ var CONTROL_SIZES = /* @__PURE__ */ new Set(["xs", "sm", "md", "lg", "xl"]);
1915
+ function fieldControlSize(size) {
1916
+ return size !== void 0 && CONTROL_SIZES.has(size) ? size : void 0;
1917
+ }
1918
+ function Select({
1919
+ options,
1920
+ value: valueProp,
1921
+ defaultValue: defaultValueProp,
1922
+ onValueChange,
1923
+ placeholder: placeholderProp,
1924
+ disabled: disabledProp,
1925
+ name: nameProp,
1926
+ required: requiredProp,
1927
+ form,
1928
+ id: idProp,
1929
+ size: sizeProp,
1930
+ clearable = false,
1931
+ className,
1932
+ classNames,
1933
+ messages,
1934
+ triggerClassName,
1935
+ contentClassName,
1936
+ "aria-invalid": ariaInvalid,
1937
+ "aria-label": ariaLabel,
1938
+ "aria-labelledby": ariaLabelledBy,
1939
+ "aria-describedby": ariaDescribedBy
1940
+ }) {
1941
+ const resolvedMessages = useDsMessages("select", messages);
1942
+ const placeholder = placeholderProp ?? resolvedMessages.placeholder;
1943
+ const defaultValue = defaultValueProp ?? "";
1944
+ const [value, setValue] = useControllableState({
1945
+ prop: valueProp === null ? "" : valueProp,
1946
+ defaultProp: defaultValue,
1947
+ onChange: onValueChange
1948
+ });
1949
+ const field = useFieldContext();
1950
+ const wiring = useFieldControl({
1951
+ id: idProp,
1952
+ name: nameProp,
1953
+ invalid: ariaInvalid,
1954
+ required: requiredProp,
1955
+ disabled: disabledProp,
1956
+ "aria-labelledby": ariaLabelledBy,
1957
+ "aria-describedby": ariaDescribedBy,
1958
+ native: false
1959
+ });
1960
+ const disabled = wiring.disabled ?? false;
1961
+ const required = wiring["aria-required"] === true;
1962
+ const size = sizeProp ?? fieldControlSize(field?.size);
1963
+ const triggerRef = React7.useRef(null);
1964
+ const fieldRef = wiring.ref;
1965
+ const composedTriggerRef = React7.useCallback(
1966
+ (node) => {
1967
+ triggerRef.current = node;
1968
+ fieldRef(node);
1969
+ },
1970
+ [fieldRef]
1971
+ );
1972
+ const clear = () => {
1973
+ setValue("");
1974
+ triggerRef.current?.focus();
1975
+ };
1976
+ const showClear = clearable && value !== "" && !disabled;
1977
+ const wrapValue = clearable || classNames?.value !== void 0;
1978
+ const trigger = /* @__PURE__ */ jsx(
1979
+ SelectTrigger,
1980
+ {
1981
+ ref: composedTriggerRef,
1982
+ id: wiring.id,
1983
+ size,
1984
+ "aria-invalid": wiring["aria-invalid"],
1985
+ "aria-required": wiring["aria-required"],
1986
+ "aria-labelledby": wiring["aria-labelledby"],
1987
+ "aria-describedby": wiring["aria-describedby"],
1988
+ "aria-label": ariaLabel ?? (wiring["aria-labelledby"] ? void 0 : placeholder),
1989
+ "data-invalid": wiring["data-invalid"],
1990
+ className: cn(triggerClassName, classNames?.trigger, clearable ? void 0 : className),
1991
+ classNames: classNames?.icon !== void 0 ? { icon: classNames.icon } : void 0,
1992
+ children: wrapValue ? /* @__PURE__ */ jsx(
1993
+ "span",
1994
+ {
1995
+ ...slot(selectAnatomy, "value"),
1996
+ className: cn(clearable && "ds:mr-8", classNames?.value),
1997
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
1998
+ }
1999
+ ) : /* @__PURE__ */ jsx(SelectValue, { placeholder })
2000
+ }
2001
+ );
2002
+ return /* @__PURE__ */ jsxs(
2003
+ SelectRoot,
2004
+ {
2005
+ value,
2006
+ onValueChange: setValue,
2007
+ disabled,
2008
+ ...form !== void 0 && { form },
2009
+ children: [
2010
+ clearable ? /* @__PURE__ */ jsxs(
2011
+ "span",
2012
+ {
2013
+ ...slot(selectAnatomy, "root"),
2014
+ className: cn("ds:relative ds:flex ds:w-full", classNames?.root, className),
2015
+ children: [
2016
+ trigger,
2017
+ showClear && /* @__PURE__ */ jsx(
2018
+ IconButton,
2019
+ {
2020
+ label: resolvedMessages.clear,
2021
+ icon: /* @__PURE__ */ jsx(XIcon, {}),
2022
+ variant: "ghost",
2023
+ intent: "neutral",
2024
+ size: "xs",
2025
+ tooltip: false,
2026
+ onClick: clear,
2027
+ ...slot(selectAnatomy, "clear"),
2028
+ className: cn(
2029
+ // Left of the chevron box (1px border + 12px padding + 16px glyph), 3px of air.
2030
+ "ds:absolute ds:top-1/2 ds:right-8 ds:-translate-y-1/2 ds:text-fg-4 ds:hover:text-fg",
2031
+ classNames?.clear
2032
+ )
2033
+ }
2034
+ )
2035
+ ]
2036
+ }
2037
+ ) : trigger,
2038
+ /* @__PURE__ */ jsx(
2039
+ SelectContent,
2040
+ {
2041
+ className: cn(contentClassName, classNames?.content),
2042
+ classNames: classNames?.viewport !== void 0 ? { viewport: classNames.viewport } : void 0,
2043
+ children: options.map((opt) => /* @__PURE__ */ jsx(
2044
+ SelectItem,
2045
+ {
2046
+ value: opt.value,
2047
+ ...opt.disabled !== void 0 && { disabled: opt.disabled },
2048
+ className: classNames?.item,
2049
+ children: /* @__PURE__ */ jsxs("span", { className: "ds:flex ds:min-w-0 ds:items-center ds:gap-1.5", children: [
2050
+ /* @__PURE__ */ jsx("span", { className: "ds:line-clamp-1", children: opt.label }),
2051
+ opt.labelSuffix
2052
+ ] })
2053
+ },
2054
+ opt.value
2055
+ ))
2056
+ }
2057
+ ),
2058
+ /* @__PURE__ */ jsx(
2059
+ FormBridge,
2060
+ {
2061
+ name: wiring.name,
2062
+ value,
2063
+ form,
2064
+ disabled,
2065
+ required,
2066
+ focusTarget: triggerRef,
2067
+ onReset: () => setValue(defaultValue)
2068
+ }
2069
+ )
2070
+ ]
2071
+ }
2072
+ );
2073
+ }
2074
+ Select.displayName = "Select";
2075
+ function setRef(ref, value) {
2076
+ if (typeof ref === "function") {
2077
+ const result = ref(value);
2078
+ return typeof result === "function" ? result : void 0;
2079
+ }
2080
+ if (ref !== null && ref !== void 0) {
2081
+ ref.current = value;
2082
+ }
2083
+ return void 0;
2084
+ }
2085
+ function mergeRefs(...refs) {
2086
+ return (value) => {
2087
+ const cleanups = refs.map((ref) => setRef(ref, value));
2088
+ return () => {
2089
+ refs.forEach((ref, index) => {
2090
+ const cleanup = cleanups[index];
2091
+ if (cleanup) cleanup();
2092
+ else setRef(ref, null);
2093
+ });
2094
+ };
2095
+ };
2096
+ }
2097
+ function useMergedRefs(...refs) {
2098
+ return useMemo(() => mergeRefs(...refs), refs);
2099
+ }
2100
+ var FieldsetContext = createContext(null);
2101
+ function useFieldsetContext() {
2102
+ return useContext(FieldsetContext);
2103
+ }
2104
+ function useFieldsetState({
2105
+ id,
2106
+ disabled = false,
2107
+ invalid = false
2108
+ }) {
2109
+ const base = useId(id, "ds-fieldset");
2110
+ const [legends, setLegends] = useState(0);
2111
+ const registerLegend = useCallback(() => {
2112
+ setLegends((count) => count + 1);
2113
+ let released = false;
2114
+ return () => {
2115
+ if (released) return;
2116
+ released = true;
2117
+ setLegends((count) => Math.max(0, count - 1));
2118
+ };
2119
+ }, []);
2120
+ return useMemo(
2121
+ () => ({
2122
+ legendId: partId(base, "legend"),
2123
+ legendMounted: legends > 0,
2124
+ registerLegend,
2125
+ disabled,
2126
+ invalid
2127
+ }),
2128
+ [base, legends, registerLegend, disabled, invalid]
2129
+ );
2130
+ }
2131
+ function useFieldsetLegend(explicitId) {
2132
+ const fieldset = useFieldsetContext();
2133
+ const registerLegend = fieldset?.registerLegend;
2134
+ useEffect(() => {
2135
+ if (!registerLegend) return;
2136
+ return registerLegend();
2137
+ }, [registerLegend]);
2138
+ return explicitId ?? fieldset?.legendId;
2139
+ }
2140
+ var Checkbox = React7.forwardRef(function Checkbox2({
2141
+ label,
2142
+ indeterminate,
2143
+ checked,
2144
+ defaultChecked,
2145
+ shape = "square",
2146
+ className,
2147
+ id,
2148
+ name,
2149
+ invalid,
2150
+ required,
2151
+ disabled,
2152
+ "aria-labelledby": ariaLabelledBy,
2153
+ "aria-describedby": ariaDescribedBy,
2154
+ "aria-invalid": ariaInvalid,
2155
+ ...props
2156
+ }, ref) {
2157
+ const fieldset = useFieldsetContext();
2158
+ const wiring = useFieldControl({
2159
+ id,
2160
+ name,
2161
+ invalid,
2162
+ required,
2163
+ disabled: disabled ?? (fieldset?.disabled ? true : void 0),
2164
+ "aria-labelledby": ariaLabelledBy,
2165
+ "aria-describedby": ariaDescribedBy
2166
+ });
2167
+ const rootRef = useMergedRefs(ref, wiring.ref);
2168
+ const resolvedChecked = indeterminate ? "indeterminate" : checked;
2169
+ return /* @__PURE__ */ jsxs("div", { className: "ds:inline-flex ds:items-center ds:gap-2", children: [
2170
+ /* @__PURE__ */ jsx(
2171
+ CheckboxPrimitive.Root,
2172
+ {
2173
+ ref: rootRef,
2174
+ id: wiring.id,
2175
+ name: wiring.name,
2176
+ ...wiring.required !== void 0 && { required: wiring.required },
2177
+ disabled: wiring.disabled,
2178
+ ...resolvedChecked !== void 0 && { checked: resolvedChecked },
2179
+ ...defaultChecked !== void 0 && { defaultChecked },
2180
+ "aria-labelledby": wiring["aria-labelledby"],
2181
+ "aria-describedby": wiring["aria-describedby"],
2182
+ "aria-invalid": ariaInvalid ?? wiring["aria-invalid"],
2183
+ "data-invalid": wiring["data-invalid"],
2184
+ ...slot(checkboxAnatomy, "root"),
2185
+ className: cn(
2186
+ "ds:peer ds:border-rule-strong ds:bg-surface ds:text-brand ds:flex ds:size-4 ds:shrink-0 ds:items-center ds:justify-center ds:border",
2187
+ shape === "circle" ? "ds:rounded-full" : "ds:rounded-[4px]",
2188
+ microInteractions.selection,
2189
+ "ds:hover:border-fg-4",
2190
+ "ds:focus-visible:[border-color:var(--focus-ring-border)] ds:focus-visible:[box-shadow:var(--shadow-focus-ring-field)] ds:focus-visible:outline-none",
2191
+ "ds:data-[state=checked]:border-brand ds:data-[state=checked]:bg-brand-bg",
2192
+ "ds:data-[state=indeterminate]:border-brand ds:data-[state=indeterminate]:bg-brand-bg",
2193
+ "ds:disabled:bg-bg-disabled ds:disabled:border-rule ds:disabled:text-fg-disabled ds:disabled:cursor-not-allowed",
2194
+ "ds:aria-[invalid=true]:border-danger-line",
2195
+ className
2196
+ ),
2197
+ ...props,
2198
+ children: /* @__PURE__ */ jsx(
2199
+ CheckboxPrimitive.Indicator,
2200
+ {
2201
+ ...slot(checkboxAnatomy, "indicator"),
2202
+ className: "ds:flex ds:items-center ds:justify-center ds:text-current",
2203
+ children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx(MinusIcon, { className: "ds:size-3", strokeWidth: 3, "aria-hidden": "true" }) : shape === "circle" ? /* @__PURE__ */ jsx("span", { className: "ds:size-1.5 ds:rounded-full ds:bg-current", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-3", strokeWidth: 3, "aria-hidden": "true" })
2204
+ }
2205
+ )
2206
+ }
2207
+ ),
2208
+ label && /* @__PURE__ */ jsx(
2209
+ "label",
2210
+ {
2211
+ htmlFor: wiring.id,
2212
+ ...slot(checkboxAnatomy, "label"),
2213
+ className: "ds:text-fg ds:peer-disabled:text-fg-disabled ds:cursor-pointer ds:text-[13px] ds:leading-none ds:select-none ds:peer-disabled:cursor-not-allowed",
2214
+ children: label
2215
+ }
2216
+ )
2217
+ ] });
2218
+ });
2219
+ Checkbox.displayName = CheckboxPrimitive.Root.displayName;
2220
+ var Pressable = forwardRef(function Pressable2({
2221
+ asChild = false,
2222
+ pressed,
2223
+ disabled,
2224
+ type,
2225
+ className,
2226
+ onClick,
2227
+ onKeyDown,
2228
+ onKeyUp,
2229
+ children,
2230
+ ...props
2231
+ }, ref) {
2232
+ const state = stateAttributes({ disabled, pressed });
2233
+ const handleClick = (event) => {
2234
+ if (disabled) {
2235
+ event.preventDefault();
2236
+ event.stopPropagation();
2237
+ return;
2238
+ }
2239
+ onClick?.(event);
2240
+ };
2241
+ const handleKeyDown = (event) => {
2242
+ onKeyDown?.(event);
2243
+ if (event.defaultPrevented) return;
2244
+ const element = event.currentTarget;
2245
+ if (disabled) {
2246
+ if (event.key === "Enter" || event.key === " ") event.preventDefault();
2247
+ return;
2248
+ }
2249
+ if (isNativeButton(element)) return;
2250
+ if (event.key === " ") {
2251
+ event.preventDefault();
2252
+ return;
2253
+ }
2254
+ if (event.key === "Enter" && !isLink(element)) {
2255
+ event.preventDefault();
2256
+ element.click();
2257
+ }
2258
+ };
2259
+ const handleKeyUp = (event) => {
2260
+ onKeyUp?.(event);
2261
+ if (event.defaultPrevented || disabled) return;
2262
+ const element = event.currentTarget;
2263
+ if (event.key === " " && !isNativeButton(element)) {
2264
+ event.preventDefault();
2265
+ element.click();
2266
+ }
2267
+ };
2268
+ const shared = {
2269
+ ...slot(pressableAnatomy, "root"),
2270
+ ...state,
2271
+ "aria-pressed": pressed,
2272
+ className: cn(PRESSABLE_CLASSES, className),
2273
+ onClick: handleClick,
2274
+ onKeyDown: handleKeyDown,
2275
+ onKeyUp: handleKeyUp
2276
+ };
2277
+ if (asChild) {
2278
+ return /* @__PURE__ */ jsx(
2279
+ Slot,
2280
+ {
2281
+ ref,
2282
+ ...shared,
2283
+ ...disabled ? { "aria-disabled": true, tabIndex: -1 } : {},
2284
+ ...type === void 0 ? {} : { type },
2285
+ ...props,
2286
+ children
2287
+ }
2288
+ );
2289
+ }
2290
+ return /* @__PURE__ */ jsx(
2291
+ "button",
2292
+ {
2293
+ ref,
2294
+ type: type ?? "button",
2295
+ disabled,
2296
+ ...shared,
2297
+ ...props,
2298
+ children
2299
+ }
2300
+ );
2301
+ });
2302
+ Pressable.displayName = "Pressable";
2303
+ var PRESSABLE_CLASSES = "ds:cursor-pointer ds:focus-visible:outline-none ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:data-[disabled]:pointer-events-none";
2304
+ function isNativeButton(element) {
2305
+ if (element.tagName === "BUTTON") return true;
2306
+ if (element.tagName !== "INPUT") return false;
2307
+ const type = element.type;
2308
+ return type === "button" || type === "submit" || type === "reset";
2309
+ }
2310
+ function isLink(element) {
2311
+ return element.tagName === "A" && element.hasAttribute("href");
2312
+ }
2313
+
2314
+ // src/primitives/behavior/overlay/recipes.ts
2315
+ var BACKDROP_BOX = "ds:bg-overlay ds:fixed ds:inset-0 ds:z-[var(--z-overlay)] ds:backdrop-blur-[4px]";
2316
+ function backdropClasses(_motion, className) {
2317
+ return cn(BACKDROP_BOX, className);
2318
+ }
2319
+ var CENTER_BOX = "ds:fixed ds:top-1/2 ds:left-1/2 ds:z-[var(--z-modal)] ds:w-full";
2320
+ var CENTER_SCROLL = "ds:scrollbar-thin ds:max-h-[calc(100vh-6rem)] ds:overflow-y-auto";
2321
+ var CENTER_CHROME = "ds:rounded-card ds:border-rule ds:bg-surface ds:shadow-overlay ds:border ds:p-6";
2322
+ var CENTER_INK = "ds:font-body ds:text-fg";
2323
+ var CENTER_PLACE = "ds:-translate-x-1/2 ds:-translate-y-1/2";
2324
+ var PANEL_BASE = "ds:fixed ds:z-[var(--z-modal)] ds:flex ds:flex-col ds:gap-4 ds:bg-surface ds:text-fg ds:shadow-overlay";
2325
+ var SPOTLIGHT_BOX = "ds:fixed ds:top-[20vh] ds:left-1/2 ds:z-[var(--z-modal)] ds:w-full";
2326
+ var SPOTLIGHT_SHIFT = "ds:-translate-x-1/2";
2327
+ var SPOTLIGHT_CHROME = "ds:rounded-card ds:border-rule ds:bg-surface ds:shadow-overlay ds:overflow-hidden ds:border";
2328
+ var PANEL_SIDE = {
2329
+ top: "ds:inset-x-0 ds:top-0 ds:border-b ds:border-rule",
2330
+ bottom: "ds:inset-x-0 ds:bottom-0 ds:border-t ds:border-rule ds:max-h-[85vh] ds:pb-[env(safe-area-inset-bottom)]",
2331
+ left: "ds:inset-y-0 ds:left-0 ds:h-full ds:w-[var(--ds-sheet-width,75%)] ds:max-w-[min(var(--ds-sheet-width,24rem),95vw)] ds:border-r ds:border-rule",
2332
+ right: "ds:inset-y-0 ds:right-0 ds:h-full ds:w-[var(--ds-sheet-width,75%)] ds:max-w-[min(var(--ds-sheet-width,24rem),95vw)] ds:border-l ds:border-rule"
2333
+ };
2334
+ var RESPONSIVE_BOX = cn(
2335
+ "ds:fixed ds:inset-x-0 ds:bottom-0 ds:z-[var(--z-modal)] ds:w-full",
2336
+ "ds:sm:top-1/2 ds:sm:right-auto ds:sm:bottom-auto ds:sm:left-1/2"
2337
+ );
2338
+ var RESPONSIVE_SCROLL = "ds:scrollbar-thin ds:max-h-[85vh] ds:overflow-y-auto ds:sm:max-h-[calc(100vh-6rem)]";
2339
+ var RESPONSIVE_CHROME = cn(
2340
+ "ds:rounded-t-card ds:border-rule ds:bg-surface ds:shadow-overlay ds:border-t ds:p-6",
2341
+ "ds:pb-[calc(1.5rem+env(safe-area-inset-bottom))]",
2342
+ "ds:sm:rounded-card ds:sm:border ds:sm:pb-6"
2343
+ );
2344
+ var RESPONSIVE_PLACE = "ds:sm:-translate-x-1/2 ds:sm:-translate-y-1/2";
2345
+ function overlaySurfaceClasses(placement, _motion, { width, rows = [] } = {}, className) {
2346
+ if (placement === "center") {
2347
+ return cn(
2348
+ CENTER_BOX,
2349
+ width,
2350
+ CENTER_SCROLL,
2351
+ CENTER_CHROME,
2352
+ CENTER_INK,
2353
+ CENTER_PLACE,
2354
+ ...rows,
2355
+ className
2356
+ );
2357
+ }
2358
+ if (placement === "responsive") {
2359
+ return cn(
2360
+ RESPONSIVE_BOX,
2361
+ width,
2362
+ RESPONSIVE_SCROLL,
2363
+ RESPONSIVE_CHROME,
2364
+ CENTER_INK,
2365
+ RESPONSIVE_PLACE,
2366
+ ...rows,
2367
+ className
2368
+ );
2369
+ }
2370
+ if (placement === "spotlight") {
2371
+ return cn(SPOTLIGHT_BOX, width, SPOTLIGHT_SHIFT, SPOTLIGHT_CHROME, CENTER_INK, ...rows, className);
2372
+ }
2373
+ return cn(PANEL_BASE, PANEL_SIDE[placement], ...rows, className);
2374
+ }
2375
+ var FLOATING_CHROME = "ds:rounded-card ds:border-rule ds:bg-surface ds:text-fg ds:shadow-pop ds:z-[var(--z-dropdown)]";
2376
+ var FLOATING_WIDTH = {
2377
+ popover: {
2378
+ auto: "",
2379
+ trigger: "ds:w-(--radix-popover-trigger-width)",
2380
+ sm: "ds:w-64",
2381
+ md: "ds:w-72",
2382
+ lg: "ds:w-96"
2383
+ },
2384
+ "hover-card": {
2385
+ auto: "",
2386
+ trigger: "ds:w-(--radix-hover-card-trigger-width)",
2387
+ sm: "ds:w-64",
2388
+ md: "ds:w-72",
2389
+ lg: "ds:w-96"
2390
+ }
2391
+ };
2392
+ var FLOATING_PADDING = {
2393
+ none: "",
2394
+ sm: "ds:p-3",
2395
+ md: "ds:p-4"
2396
+ };
2397
+ function floatingSurfaceClasses(_motion, { width, padding, rows = [] } = {}, className) {
2398
+ return cn(FLOATING_CHROME, width, "ds:border", padding, "ds:outline-none", ...rows, className);
2399
+ }
2400
+ var DISMISS_BUTTON_CLASSES = cn(
2401
+ "ds:absolute ds:top-4 ds:right-4 ds:inline-flex ds:size-7 ds:items-center ds:justify-center",
2402
+ "ds:rounded-icon ds:text-fg-4 ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
2403
+ "ds:hover:bg-overlay-hover ds:hover:text-fg",
2404
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
2405
+ "ds:disabled:pointer-events-none"
2406
+ );
2407
+ var DISMISS_GLYPH_CLASSES = "ds:size-4";
2408
+ var HEADER_COLUMN = "ds:flex ds:flex-col ds:gap-1.5";
2409
+ function overlayHeaderClasses(layout, dismissGutter, className) {
2410
+ return layout === "inset" ? cn("ds:mb-4", HEADER_COLUMN, dismissGutter && "ds:pr-8", className) : cn(HEADER_COLUMN, "ds:p-6", dismissGutter && "ds:pr-12", "ds:pb-0", className);
2411
+ }
2412
+ var OVERLAY_TITLE_CLASSES = "ds:font-display ds:text-fg ds:text-base ds:leading-tight ds:font-medium ds:tracking-tight";
2413
+ var OVERLAY_DESCRIPTION_CLASSES = "ds:text-fg-3 ds:text-sm";
2414
+ var FOOTER_ROW = "ds:flex ds:flex-col-reverse ds:gap-2";
2415
+ var FOOTER_RESPONSIVE = "ds:sm:flex-row ds:sm:items-center ds:sm:justify-end";
2416
+ function overlayFooterClasses(layout, className) {
2417
+ return layout === "inset" ? cn("ds:mt-6", FOOTER_ROW, FOOTER_RESPONSIVE, className) : cn(
2418
+ "ds:border-rule ds:mt-auto",
2419
+ FOOTER_ROW,
2420
+ "ds:border-t ds:p-6",
2421
+ FOOTER_RESPONSIVE,
2422
+ className
2423
+ );
2424
+ }
2425
+ var BODY_SCROLL = "ds:scrollbar-thin ds:min-h-0 ds:flex-1 ds:overflow-y-auto";
2426
+ var BODY_PADDING = {
2427
+ inset: {
2428
+ none: "",
2429
+ sm: "ds:p-4",
2430
+ md: "ds:p-6",
2431
+ lg: "ds:p-8"
2432
+ },
2433
+ padded: {
2434
+ none: "",
2435
+ sm: "ds:px-4",
2436
+ md: "ds:px-6",
2437
+ lg: "ds:px-8"
2438
+ }
2439
+ };
2440
+ function overlayBodyClasses(layout, padding, className) {
2441
+ return cn(BODY_SCROLL, BODY_PADDING[layout][padding], className);
2442
+ }
2443
+ function Backdrop({
2444
+ as: Component,
2445
+ anatomy,
2446
+ motion,
2447
+ className,
2448
+ ...props
2449
+ }) {
2450
+ return /* @__PURE__ */ jsx(
2451
+ Component,
2452
+ {
2453
+ ...slot(anatomy, "overlay"),
2454
+ ...presence("fade"),
2455
+ className: backdropClasses(motion, className),
2456
+ ...props
2457
+ }
2458
+ );
2459
+ }
2460
+ var SURFACE_PRESENCE = {
2461
+ center: "modal",
2462
+ top: "sheet-top",
2463
+ right: "sheet-right",
2464
+ bottom: "sheet-bottom",
2465
+ left: "sheet-left",
2466
+ responsive: "responsive",
2467
+ spotlight: "spotlight"
2468
+ };
2469
+ function OverlaySurface({
2470
+ as: Component,
2471
+ anatomy,
2472
+ placement,
2473
+ motion,
2474
+ width,
2475
+ rows,
2476
+ className,
2477
+ ...props
2478
+ }) {
2479
+ return /* @__PURE__ */ jsx(
2480
+ Component,
2481
+ {
2482
+ ...slot(anatomy, "content"),
2483
+ ...presence(SURFACE_PRESENCE[placement]),
2484
+ className: overlaySurfaceClasses(placement, motion, { width, rows }, className),
2485
+ ...props
2486
+ }
2487
+ );
2488
+ }
2489
+ var DEFAULT_OVERLAY_MESSAGES = EN_MESSAGES.overlay;
2490
+ function DismissButton({
2491
+ as: Component,
2492
+ anatomy,
2493
+ label,
2494
+ className,
2495
+ children,
2496
+ ...props
2497
+ }) {
2498
+ return /* @__PURE__ */ jsx(
2499
+ Component,
2500
+ {
2501
+ ...slot(anatomy, "close"),
2502
+ className: cn(DISMISS_BUTTON_CLASSES, className),
2503
+ "aria-label": label,
2504
+ ...props,
2505
+ children
2506
+ }
2507
+ );
2508
+ }
2509
+ function OverlayHeader({
2510
+ as: Component = "div",
2511
+ anatomy,
2512
+ layout,
2513
+ dismissGutter,
2514
+ className,
2515
+ ...props
2516
+ }) {
2517
+ return /* @__PURE__ */ jsx(
2518
+ Component,
2519
+ {
2520
+ ...slot(anatomy, "header"),
2521
+ className: overlayHeaderClasses(layout, dismissGutter, className),
2522
+ ...props
2523
+ }
2524
+ );
2525
+ }
2526
+ function OverlayTitle({ as: Component, anatomy, className, ...props }) {
2527
+ return /* @__PURE__ */ jsx(
2528
+ Component,
2529
+ {
2530
+ ...slot(anatomy, "title"),
2531
+ className: cn(OVERLAY_TITLE_CLASSES, className),
2532
+ ...props
2533
+ }
2534
+ );
2535
+ }
2536
+ function OverlayDescription({ as: Component, anatomy, className, ...props }) {
2537
+ return /* @__PURE__ */ jsx(
2538
+ Component,
2539
+ {
2540
+ ...slot(anatomy, "description"),
2541
+ className: cn(OVERLAY_DESCRIPTION_CLASSES, className),
2542
+ ...props
2543
+ }
2544
+ );
2545
+ }
2546
+ function OverlayBody({
2547
+ as: Component = "div",
2548
+ anatomy,
2549
+ layout,
2550
+ padding,
2551
+ className,
2552
+ ...props
2553
+ }) {
2554
+ return /* @__PURE__ */ jsx(
2555
+ Component,
2556
+ {
2557
+ ...slot(anatomy, "body"),
2558
+ className: overlayBodyClasses(layout, padding, className),
2559
+ ...props
2560
+ }
2561
+ );
2562
+ }
2563
+ function OverlayFooter({
2564
+ as: Component = "div",
2565
+ anatomy,
2566
+ layout,
2567
+ className,
2568
+ ...props
2569
+ }) {
2570
+ return /* @__PURE__ */ jsx(
2571
+ Component,
2572
+ {
2573
+ ...slot(anatomy, "footer"),
2574
+ className: overlayFooterClasses(layout, className),
2575
+ ...props
2576
+ }
2577
+ );
2578
+ }
2579
+ var ModalRoot = DialogPrimitive.Root;
2580
+ var ModalPortal = DialogPrimitive.Portal;
2581
+ var ModalOverlay = DialogPrimitive.Overlay;
2582
+ var ModalContent = DialogPrimitive.Content;
2583
+ var ModalTitle = DialogPrimitive.Title;
2584
+ var ModalDescription = DialogPrimitive.Description;
2585
+ var PopoverTriggerIdContext = React7.createContext(null);
2586
+ var Popover = ({
2587
+ open: openProp,
2588
+ defaultOpen,
2589
+ onOpenChange,
2590
+ ...props
2591
+ }) => {
2592
+ const [uncontrolledOpen, setUncontrolledOpen] = React7.useState(defaultOpen ?? false);
2593
+ const open = openProp ?? uncontrolledOpen;
2594
+ const handleOpenChange = React7.useCallback(
2595
+ (next) => {
2596
+ setUncontrolledOpen(next);
2597
+ onOpenChange?.(next);
2598
+ },
2599
+ [onOpenChange]
2600
+ );
2601
+ const [triggerId, setTriggerId] = React7.useState(void 0);
2602
+ const value = React7.useMemo(() => ({ open, triggerId, setTriggerId }), [open, triggerId]);
2603
+ return /* @__PURE__ */ jsx(PopoverTriggerIdContext.Provider, { value, children: /* @__PURE__ */ jsx(
2604
+ PopoverPrimitive.Root,
2605
+ {
2606
+ ...openProp !== void 0 ? { open: openProp } : {},
2607
+ ...defaultOpen !== void 0 ? { defaultOpen } : {},
2608
+ onOpenChange: handleOpenChange,
2609
+ ...props
2610
+ }
2611
+ ) });
2612
+ };
2613
+ Popover.displayName = "Popover";
2614
+ var PopoverTrigger = React7.forwardRef(({ id, ...props }, forwardedRef) => {
2615
+ const context = React7.useContext(PopoverTriggerIdContext);
2616
+ const generatedId = React7.useId();
2617
+ const node = React7.useRef(null);
2618
+ const ref = React7.useCallback(
2619
+ (element) => {
2620
+ node.current = element;
2621
+ if (typeof forwardedRef === "function") forwardedRef(element);
2622
+ else if (forwardedRef) forwardedRef.current = element;
2623
+ },
2624
+ [forwardedRef]
2625
+ );
2626
+ const setTriggerId = context?.setTriggerId;
2627
+ React7.useEffect(() => {
2628
+ setTriggerId?.(node.current?.id || void 0);
2629
+ });
2630
+ React7.useEffect(() => () => setTriggerId?.(void 0), [setTriggerId]);
2631
+ return /* @__PURE__ */ jsx(
2632
+ PopoverPrimitive.Trigger,
2633
+ {
2634
+ ref,
2635
+ id: id ?? (context?.open ? generatedId : void 0),
2636
+ ...props
2637
+ }
2638
+ );
2639
+ });
2640
+ PopoverTrigger.displayName = PopoverPrimitive.Trigger.displayName;
2641
+ var PopoverAnchor = PopoverPrimitive.Anchor;
2642
+ var PopoverPortal = withPortalContainer(PopoverPrimitive.Portal);
2643
+ var PopoverClose = PopoverPrimitive.Close;
2644
+ var PopoverContent = React7.forwardRef(
2645
+ ({
2646
+ className,
2647
+ align = "center",
2648
+ side = "bottom",
2649
+ sideOffset = 8,
2650
+ width = "md",
2651
+ padding = "md",
2652
+ ...props
2653
+ }, ref) => {
2654
+ const triggerId = React7.useContext(PopoverTriggerIdContext)?.triggerId;
2655
+ const named = Boolean(props["aria-label"] || props["aria-labelledby"]);
2656
+ return /* @__PURE__ */ jsx(PopoverPortal, { children: /* @__PURE__ */ jsx(
2657
+ PopoverPrimitive.Content,
2658
+ {
2659
+ ref,
2660
+ "aria-labelledby": named ? void 0 : triggerId,
2661
+ align,
2662
+ side,
2663
+ sideOffset,
2664
+ ...slot(popoverAnatomy, "content"),
2665
+ ...presence("floating"),
2666
+ className: floatingSurfaceClasses(
2667
+ "tokens",
2668
+ { width: FLOATING_WIDTH.popover[width], padding: FLOATING_PADDING[padding] },
2669
+ className
2670
+ ),
2671
+ ...props
2672
+ }
2673
+ ) });
2674
+ }
2675
+ );
2676
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
2677
+
2678
+ // src/primitives/behavior/menu/content.ts
2679
+ var DROPDOWN_MENU_WIDTH = {
2680
+ auto: "",
2681
+ trigger: "ds:w-(--radix-dropdown-menu-trigger-width)",
2682
+ sm: "ds:w-48",
2683
+ md: "ds:w-64"
2684
+ };
2685
+
2686
+ // src/primitives/behavior/menu/item-recipe.ts
2687
+ var MENU_ITEM_LABEL_SIZE = "ds:text-sm";
2688
+ var MENU_INSET = "ds:pl-8";
2689
+ var MENU_ITEM_DANGER = {
2690
+ menu: "ds:text-menu-item-destructive-fg ds:focus:bg-menu-item-destructive-hover-bg ds:focus:text-menu-item-destructive-hover-fg",
2691
+ neutral: "ds:text-danger-fg ds:focus:bg-danger-bg ds:focus:text-danger-fg"
2692
+ };
2693
+ var MENU_SUB_TRIGGER_OPEN = {
2694
+ menu: "ds:data-[state=open]:bg-menu-item-hover-bg ds:data-[state=open]:text-menu-item-hover-fg",
2695
+ neutral: "ds:data-[state=open]:bg-bg-2 ds:data-[state=open]:text-fg"
2696
+ };
2697
+ var MENU_SUB_TRIGGER_BOX = "ds:rounded-surface-sm ds:flex ds:cursor-default ds:items-center ds:gap-2 ds:px-2 ds:py-1.5";
2698
+ var MENU_SUB_TRIGGER_CHEVRON = "ds:text-fg-3 ds:ml-auto ds:size-4 ds:-translate-x-px";
2699
+ var MENU_INDICATOR_WELL = LIST_ITEM_INDICATOR_WELL.start;
2700
+ var MENU_CHECK_GLYPH = "ds:size-3.5";
2701
+ var MENU_RADIO_GLYPH = "ds:size-2 ds:fill-current";
2702
+ var MENU_SHORTCUT_INK = {
2703
+ menu: "ds:text-menu-shortcut-fg",
2704
+ neutral: "ds:text-fg-4"
2705
+ };
2706
+ var MENU_SHORTCUT_BOX = "ds:ml-auto ds:font-mono";
2707
+ var MENU_SHORTCUT_TYPE = "ds:tracking-wider";
2708
+ function menuItemClasses(palette) {
2709
+ return listItemClasses({
2710
+ frame: "menu",
2711
+ labelSize: MENU_ITEM_LABEL_SIZE,
2712
+ palette,
2713
+ highlight: "focus",
2714
+ selected: "none"
2715
+ });
2716
+ }
2717
+ function menuIndicatorItemClasses(palette) {
2718
+ return listItemClasses({
2719
+ frame: "menu-indicator",
2720
+ labelSize: MENU_ITEM_LABEL_SIZE,
2721
+ palette,
2722
+ highlight: "focus",
2723
+ selected: "none",
2724
+ glyph: false
2725
+ });
2726
+ }
2727
+ function menuSubTriggerClasses(palette) {
2728
+ const highlighted = LIST_ITEM_HIGHLIGHTED[palette].focus;
2729
+ if (highlighted === void 0) {
2730
+ throw new TypeError(
2731
+ `menu: no focus row for palette ${JSON.stringify(palette)}; write the literal in collection/item-recipe.ts`
2732
+ );
2733
+ }
2734
+ return [
2735
+ MENU_SUB_TRIGGER_BOX,
2736
+ MENU_ITEM_LABEL_SIZE,
2737
+ LIST_ITEM_INTERACTION,
2738
+ LIST_ITEM_INK[palette],
2739
+ LIST_ITEM_MOTION,
2740
+ highlighted,
2741
+ MENU_SUB_TRIGGER_OPEN[palette],
2742
+ LIST_ITEM_DISABLED
2743
+ ].join(" ");
2744
+ }
2745
+ function menuLabelClasses(palette, labelSize) {
2746
+ return groupHeadingClasses({ palette, labelSize });
2747
+ }
2748
+ function menuSeparatorClasses(palette) {
2749
+ return LIST_SEPARATOR[palette];
2750
+ }
2751
+ function menuShortcutClasses(palette, labelSize) {
2752
+ return [MENU_SHORTCUT_INK[palette], MENU_SHORTCUT_BOX, labelSize, MENU_SHORTCUT_TYPE].join(" ");
2753
+ }
2754
+ var PALETTE = "menu";
2755
+ var DropdownMenu = DropdownMenuPrimitive.Root;
2756
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
2757
+ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
2758
+ var DropdownMenuPortal = withPortalContainer(DropdownMenuPrimitive.Portal);
2759
+ var DropdownMenuSub = DropdownMenuPrimitive.Sub;
2760
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
2761
+ var DropdownMenuSubTrigger = React7.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
2762
+ DropdownMenuPrimitive.SubTrigger,
2763
+ {
2764
+ ref,
2765
+ ...slot(dropdownMenuAnatomy, "sub-trigger"),
2766
+ className: cn(menuSubTriggerClasses(PALETTE), inset && MENU_INSET, className),
2767
+ ...props,
2768
+ children: [
2769
+ children,
2770
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: MENU_SUB_TRIGGER_CHEVRON, "aria-hidden": "true" })
2771
+ ]
2772
+ }
2773
+ ));
2774
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
2775
+ var DropdownMenuSubContent = React7.forwardRef(({ className, ...props }, ref) => (
2776
+ // Portal the sub-content to the body. The parent Content is transformed
2777
+ // while its presence keyframes run, which makes it the containing block for
2778
+ // `position: fixed` descendants — and its `overflow-hidden` would then clip
2779
+ // this Popper-positioned flyout to nothing. Portaling escapes both.
2780
+ /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(
2781
+ DropdownMenuPrimitive.SubContent,
2782
+ {
2783
+ ref,
2784
+ ...slot(dropdownMenuAnatomy, "sub-content"),
2785
+ ...presence("floating"),
2786
+ className: cn(
2787
+ "ds:rounded-card ds:border-menu-border ds:bg-menu-bg ds:text-menu-fg ds:shadow-pop ds:z-[var(--z-dropdown)] ds:min-w-[8rem] ds:overflow-hidden ds:border ds:p-1",
2788
+ className
2789
+ ),
2790
+ ...props
2791
+ }
2792
+ ) })
2793
+ ));
2794
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
2795
+ var DropdownMenuContent = React7.forwardRef(({ className, sideOffset = 6, align = "start", width = "auto", ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(
2796
+ DropdownMenuPrimitive.Content,
2797
+ {
2798
+ ref,
2799
+ ...slot(dropdownMenuAnatomy, "content"),
2800
+ ...presence("floating"),
2801
+ sideOffset,
2802
+ align,
2803
+ className: cn(
2804
+ "ds:rounded-card ds:border-menu-border ds:bg-menu-bg ds:text-menu-fg ds:shadow-pop ds:z-[var(--z-dropdown)] ds:min-w-[10rem] ds:overflow-hidden ds:border ds:p-1",
2805
+ DROPDOWN_MENU_WIDTH[width],
2806
+ className
2807
+ ),
2808
+ ...props
2809
+ }
2810
+ ) }));
2811
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
2812
+ var DropdownMenuItem = React7.forwardRef(({ className, destructive, inset, ...props }, ref) => /* @__PURE__ */ jsx(
2813
+ DropdownMenuPrimitive.Item,
2814
+ {
2815
+ ref,
2816
+ ...slot(dropdownMenuAnatomy, "item"),
2817
+ className: cn(
2818
+ menuItemClasses(PALETTE),
2819
+ inset && MENU_INSET,
2820
+ destructive && MENU_ITEM_DANGER[PALETTE],
2821
+ className
2822
+ ),
2823
+ ...props
2824
+ }
2825
+ ));
2826
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
2827
+ var DropdownMenuCheckboxItem = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
2828
+ DropdownMenuPrimitive.CheckboxItem,
2829
+ {
2830
+ ref,
2831
+ ...slot(dropdownMenuAnatomy, "checkbox-item"),
2832
+ className: cn(menuIndicatorItemClasses(PALETTE), className),
2833
+ ...props,
2834
+ children: [
2835
+ /* @__PURE__ */ jsx("span", { className: MENU_INDICATOR_WELL, children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { ...slot(dropdownMenuAnatomy, "item-indicator"), children: /* @__PURE__ */ jsx(CheckIcon, { className: MENU_CHECK_GLYPH, "aria-hidden": "true" }) }) }),
2836
+ children
2837
+ ]
2838
+ }
2839
+ ));
2840
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
2841
+ var DropdownMenuRadioItem = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
2842
+ DropdownMenuPrimitive.RadioItem,
2843
+ {
2844
+ ref,
2845
+ ...slot(dropdownMenuAnatomy, "radio-item"),
2846
+ className: cn(menuIndicatorItemClasses(PALETTE), className),
2847
+ ...props,
2848
+ children: [
2849
+ /* @__PURE__ */ jsx("span", { className: MENU_INDICATOR_WELL, children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { ...slot(dropdownMenuAnatomy, "item-indicator"), children: /* @__PURE__ */ jsx(CircleIcon, { className: MENU_RADIO_GLYPH, "aria-hidden": "true" }) }) }),
2850
+ children
2851
+ ]
2852
+ }
2853
+ ));
2854
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
2855
+ var DropdownMenuLabel = React7.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
2856
+ DropdownMenuPrimitive.Label,
2857
+ {
2858
+ ref,
2859
+ ...slot(dropdownMenuAnatomy, "label"),
2860
+ className: cn(menuLabelClasses(PALETTE, "ds:text-[11px]"), inset && MENU_INSET, className),
2861
+ ...props
2862
+ }
2863
+ ));
2864
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
2865
+ var DropdownMenuSeparator = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2866
+ DropdownMenuPrimitive.Separator,
2867
+ {
2868
+ ref,
2869
+ ...slot(dropdownMenuAnatomy, "separator"),
2870
+ className: cn(menuSeparatorClasses(PALETTE), className),
2871
+ ...props
2872
+ }
2873
+ ));
2874
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
2875
+ var DropdownMenuShortcut = ({ className, ...props }) => /* @__PURE__ */ jsx(
2876
+ "span",
2877
+ {
2878
+ ...slot(dropdownMenuAnatomy, "shortcut"),
2879
+ className: cn(menuShortcutClasses(PALETTE, "ds:text-[11px]"), className),
2880
+ ...props
2881
+ }
2882
+ );
2883
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
2884
+ var kindTile = {
2885
+ doc: "ds:bg-danger-bg ds:text-danger-fg",
2886
+ sheet: "ds:bg-success-bg ds:text-success-fg",
2887
+ image: "ds:bg-accent-tint ds:text-accent",
2888
+ generic: "ds:bg-bg-3 ds:text-fg-3"
2889
+ };
2890
+ var FileChip = forwardRef(function FileChip2({ name, meta, kind = "doc", icon, action, className, ...props }, ref) {
2891
+ return /* @__PURE__ */ jsxs(
2892
+ "div",
2893
+ {
2894
+ ref,
2895
+ className: cn(
2896
+ "ds:border-rule ds:bg-surface ds:flex ds:items-center ds:gap-3 ds:rounded-[var(--radius-input)] ds:border ds:p-2.5",
2897
+ className
2898
+ ),
2899
+ ...props,
2900
+ children: [
2901
+ /* @__PURE__ */ jsx(
2902
+ "span",
2903
+ {
2904
+ "aria-hidden": "true",
2905
+ className: cn(
2906
+ "ds:flex ds:size-9 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-[var(--radius-icon)] ds:[&_svg]:size-4.5",
2907
+ kindTile[kind]
2908
+ ),
2909
+ children: icon ?? /* @__PURE__ */ jsx(FileTextIcon, {})
2910
+ }
2911
+ ),
2912
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0 ds:flex-1", children: [
2913
+ /* @__PURE__ */ jsx("p", { className: "ds:text-fg ds:truncate ds:text-sm ds:font-medium", children: name }),
2914
+ meta != null && /* @__PURE__ */ jsx("p", { className: "ds:text-fg-3 ds:truncate ds:text-xs", children: meta })
2915
+ ] }),
2916
+ action && /* @__PURE__ */ jsx("div", { className: "ds:shrink-0", children: action })
2917
+ ]
2918
+ }
2919
+ );
2920
+ });
2921
+ FileChip.displayName = "FileChip";
2922
+ var DROPZONE_LAYOUT = {
2923
+ default: "ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-2",
2924
+ compact: "ds:flex ds:flex-row ds:items-center ds:justify-start ds:gap-3"
2925
+ };
2926
+ var DROPZONE_SPACING = {
2927
+ default: "ds:font-body ds:p-8 ds:text-center",
2928
+ compact: "ds:font-body ds:p-3 ds:text-left"
2929
+ };
2930
+ function assignFiles(input, files) {
2931
+ try {
2932
+ const transfer = new DataTransfer();
2933
+ for (const file of files) transfer.items.add(file);
2934
+ input.files = transfer.files;
2935
+ } catch {
2936
+ input.value = "";
2937
+ }
2938
+ }
2939
+ function FileUpload({
2940
+ accept,
2941
+ maxSize,
2942
+ multiple,
2943
+ onFilesSelected,
2944
+ disabled,
2945
+ name,
2946
+ form,
2947
+ required,
2948
+ variant = "default",
2949
+ classNames,
2950
+ inputRef: inputRefProp,
2951
+ messages: messagesProp,
2952
+ className,
2953
+ children,
2954
+ ...props
2955
+ }) {
2956
+ const messages = useDsMessages("fileUpload", messagesProp);
2957
+ const inputRef = useRef(null);
2958
+ const [isDragOver, setIsDragOver] = useState(false);
2959
+ const [error, setError] = useState(null);
2960
+ const wiring = useFieldControl({
2961
+ name,
2962
+ required,
2963
+ disabled,
2964
+ invalid: error ? true : void 0,
2965
+ "aria-describedby": props["aria-describedby"]
2966
+ });
2967
+ const inputId = wiring.id;
2968
+ const isDisabled = wiring.disabled;
2969
+ const ownsFiles = wiring.name !== void 0;
2970
+ const wrapperOwnsFocus = props.tabIndex !== void 0 || props.role !== void 0;
2971
+ const validateFiles = useCallback(
2972
+ (files) => {
2973
+ setError(null);
2974
+ const acceptTypes = accept ? accept.split(",").map((t) => t.trim()) : null;
2975
+ const valid = files.filter((file) => {
2976
+ if (acceptTypes) {
2977
+ const ext = `.${file.name.split(".").pop()?.toLowerCase()}`;
2978
+ const matchesType = acceptTypes.some(
2979
+ (type) => type === ext || type === file.type || type.endsWith("/*") && file.type.startsWith(type.replace("/*", "/"))
2980
+ );
2981
+ if (!matchesType) {
2982
+ setError(`File type not accepted: ${file.name}`);
2983
+ return false;
2984
+ }
2985
+ }
2986
+ if (maxSize && file.size > maxSize) {
2987
+ setError(`File too large: ${file.name} (max ${formatBytes(maxSize)})`);
2988
+ return false;
2989
+ }
2990
+ return true;
2991
+ });
2992
+ return valid;
2993
+ },
2994
+ [accept, maxSize]
2995
+ );
2996
+ function handleFiles(fileList, source) {
2997
+ const files = Array.from(fileList);
2998
+ const considered = multiple ? files : files.slice(0, 1);
2999
+ const valid = validateFiles(considered);
3000
+ const input = inputRef.current;
3001
+ if (input) {
3002
+ if (!ownsFiles) {
3003
+ input.value = "";
3004
+ } else if (source === "drop" || valid.length !== files.length) {
3005
+ assignFiles(input, valid);
3006
+ }
3007
+ }
3008
+ if (valid.length > 0) onFilesSelected?.(valid);
3009
+ }
3010
+ function handleDrop(e) {
3011
+ e.preventDefault();
3012
+ setIsDragOver(false);
3013
+ if (isDisabled) return;
3014
+ handleFiles(e.dataTransfer.files, "drop");
3015
+ }
3016
+ const defaultCopy = /* @__PURE__ */ jsxs(Fragment, { children: [
3017
+ /* @__PURE__ */ jsxs("div", { className: "ds:text-fg-3 ds:text-sm", children: [
3018
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:font-medium", children: messages.prompt }),
3019
+ messages.dragHint
3020
+ ] }),
3021
+ accept && /* @__PURE__ */ jsx("p", { className: "ds:text-fg-4 ds:font-mono ds:text-[10.5px]", children: messages.accepted(accept) }),
3022
+ maxSize && /* @__PURE__ */ jsx("p", { className: "ds:text-fg-4 ds:font-mono ds:text-[10.5px]", children: messages.maxSize(formatBytes(maxSize)) })
3023
+ ] });
3024
+ return /* @__PURE__ */ jsxs(
3025
+ "div",
3026
+ {
3027
+ ...slot(fileUploadAnatomy, "root"),
3028
+ ...stateAttributes({
3029
+ disabled: isDisabled,
3030
+ invalid: !!error,
3031
+ // Only when it is not the default: the default DOM is frozen (C-DOM-04).
3032
+ variant: variant === "default" ? void 0 : variant
3033
+ }),
3034
+ className: cn("ds:w-full", className),
3035
+ ...props,
3036
+ children: [
3037
+ /* @__PURE__ */ jsxs(
3038
+ "label",
3039
+ {
3040
+ htmlFor: inputId,
3041
+ ...slot(fileUploadAnatomy, "dropzone"),
3042
+ ...stateAttributes({ disabled: isDisabled, state: isDragOver ? "drag-over" : void 0 }),
3043
+ onDragOver: (e) => {
3044
+ e.preventDefault();
3045
+ if (!isDisabled) setIsDragOver(true);
3046
+ },
3047
+ onDragLeave: () => setIsDragOver(false),
3048
+ onDrop: handleDrop,
3049
+ className: cn(
3050
+ DROPZONE_LAYOUT[variant],
3051
+ "ds:rounded-card ds:border-rule-strong ds:bg-surface ds:border ds:border-dashed",
3052
+ DROPZONE_SPACING[variant],
3053
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)]",
3054
+ "ds:motion-reduce:transition-none",
3055
+ // Hover (when not disabled)
3056
+ !isDisabled && "ds:hover:border-brand-line ds:hover:bg-brand-bg/40",
3057
+ // Drag-over → Pro purple highlight
3058
+ isDragOver && "ds:border-brand-line ds:bg-brand-bg",
3059
+ isDisabled && "ds:border-rule ds:bg-bg-disabled ds:text-fg-disabled ds:cursor-not-allowed",
3060
+ !isDisabled && "ds:cursor-pointer",
3061
+ // Keyboard focus lands on the (visually hidden) file input.
3062
+ "ds:has-[input:focus-visible]:[box-shadow:var(--shadow-focus-ring)]",
3063
+ slotClassName(classNames, "dropzone")
3064
+ ),
3065
+ children: [
3066
+ /* @__PURE__ */ jsx(
3067
+ "input",
3068
+ {
3069
+ ref: mergeRefs(inputRef, inputRefProp, wiring.ref),
3070
+ id: inputId,
3071
+ name: wiring.name,
3072
+ form,
3073
+ type: "file",
3074
+ ...slot(fileUploadAnatomy, "input"),
3075
+ accept,
3076
+ multiple,
3077
+ onChange: (e) => {
3078
+ if (e.target.files) handleFiles(e.target.files, "input");
3079
+ },
3080
+ className: cn(
3081
+ "ds:fixed ds:-top-[9999px] ds:-left-[9999px] ds:opacity-0",
3082
+ slotClassName(classNames, "input")
3083
+ ),
3084
+ onKeyDown: (e) => {
3085
+ if (e.key !== "Enter" && e.key !== " ") return;
3086
+ e.preventDefault();
3087
+ e.currentTarget.click();
3088
+ },
3089
+ disabled: isDisabled,
3090
+ required: wiring.required,
3091
+ "aria-invalid": wiring["aria-invalid"],
3092
+ "aria-describedby": wiring["aria-describedby"],
3093
+ tabIndex: wrapperOwnsFocus ? -1 : void 0
3094
+ }
3095
+ ),
3096
+ children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
3097
+ /* @__PURE__ */ jsx(
3098
+ "div",
3099
+ {
3100
+ className: cn(
3101
+ "ds:rounded-icon ds:flex ds:size-10 ds:items-center ds:justify-center ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
3102
+ variant === "compact" && "ds:shrink-0",
3103
+ isDragOver ? "ds:bg-brand ds:text-fg-on-brand" : "ds:bg-brand-bg ds:text-brand"
3104
+ ),
3105
+ "aria-hidden": "true",
3106
+ children: /* @__PURE__ */ jsx(UploadIcon, { className: "ds:size-5" })
3107
+ }
3108
+ ),
3109
+ variant === "compact" ? /* @__PURE__ */ jsx("div", { className: "ds:flex ds:min-w-0 ds:flex-col ds:gap-0.5", children: defaultCopy }) : defaultCopy
3110
+ ] })
3111
+ ]
3112
+ }
3113
+ ),
3114
+ error && /* @__PURE__ */ jsx(
3115
+ "p",
3116
+ {
3117
+ role: "alert",
3118
+ ...slot(fileUploadAnatomy, "error"),
3119
+ className: cn("ds:text-danger-fg ds:mt-2 ds:text-sm", slotClassName(classNames, "error")),
3120
+ children: error
3121
+ }
3122
+ )
3123
+ ]
3124
+ }
3125
+ );
3126
+ }
3127
+ function formatBytes(bytes) {
3128
+ if (bytes < 1024) return `${bytes} B`;
3129
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
3130
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
3131
+ }
3132
+ var CONTROL_CHROME = [
3133
+ "ds:flex ds:w-full ds:rounded-input ds:border ds:bg-surface ds:font-body ds:text-fg",
3134
+ microInteractions.control,
3135
+ "ds:placeholder:text-fg-4",
3136
+ "ds:focus-visible:outline-none ds:focus-visible:[border-color:var(--focus-ring-border)]",
3137
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring-field)]",
3138
+ "ds:disabled:cursor-not-allowed ds:disabled:bg-bg-disabled ds:disabled:text-fg-disabled",
3139
+ "ds:aria-[invalid=true]:border-field-border-invalid ds:aria-[invalid=true]:focus-visible:border-danger-fg",
3140
+ "ds:aria-[invalid=true]:focus-visible:[box-shadow:0_0_0_2px_var(--color-danger-bg)]"
3141
+ ].join(" ");
3142
+ var CONTROL_CHROME_VARIANTS = {
3143
+ default: "ds:border-field-border ds:not-disabled:hover:border-field-border-hover",
3144
+ ghost: "ds:border-transparent ds:bg-transparent ds:focus-visible:bg-surface"
3145
+ };
3146
+ var controlChrome = cva(CONTROL_CHROME, {
3147
+ variants: {
3148
+ variant: CONTROL_CHROME_VARIANTS,
3149
+ size: CONTROL_SIZE_CLASSES
3150
+ },
3151
+ defaultVariants: {
3152
+ variant: "default",
3153
+ size: "md"
3154
+ }
3155
+ });
3156
+ var INPUT_FILE_RESET = "ds:file:border-0 ds:file:bg-transparent ds:file:text-sm ds:file:font-medium";
3157
+ var isScaleRowSize = (size) => size === "xs" || size === "xl";
3158
+ var INPUT_SIZE_ROWS = {
3159
+ sm: "ds:h-(--control-height-sm) ds:px-2.5 ds:py-1 ds:text-xs",
3160
+ md: "ds:h-(--control-height-md) ds:px-3 ds:py-2 ds:text-(length:--control-font-size-md)",
3161
+ lg: "ds:h-(--input-height-lg) ds:px-3.5 ds:py-2.5 ds:text-sm",
3162
+ compact: "ds:h-(--control-height-sm) ds:px-2.5 ds:py-1 ds:text-(length:--control-font-size-md)",
3163
+ default: "ds:h-(--control-height-lg) ds:px-3 ds:py-2 ds:text-sm",
3164
+ comfortable: "ds:h-(--control-height-xl) ds:px-3.5 ds:py-2.5 ds:text-base"
3165
+ };
3166
+ function inputVariants({
3167
+ variant,
3168
+ size,
3169
+ inputSize,
3170
+ class: classProp,
3171
+ className
3172
+ } = {}) {
3173
+ const LEGACY_ROWS = {
3174
+ // The `inputSize` rows: today's classes, byte for byte (W2-03 compat).
3175
+ sm: "ds:h-8 ds:px-2.5 ds:py-1 ds:text-xs",
3176
+ md: "ds:h-9 ds:px-3 ds:py-2 ds:text-[13px]",
3177
+ lg: "ds:h-11 ds:px-3.5 ds:py-2.5 ds:text-sm",
3178
+ compact: "ds:h-8 ds:px-2.5 ds:py-1 ds:text-[13px]",
3179
+ default: "ds:h-10 ds:px-3 ds:py-2 ds:text-sm",
3180
+ comfortable: "ds:h-12 ds:px-3.5 ds:py-2.5 ds:text-base"
3181
+ };
3182
+ const resolved = size ?? inputSize ?? "md";
3183
+ const scale = isScaleRowSize(resolved);
3184
+ const row = scale ? null : size ? INPUT_SIZE_ROWS[resolved] : LEGACY_ROWS[resolved];
3185
+ return controlChrome({
3186
+ variant,
3187
+ size: scale ? resolved : null,
3188
+ class: cn(INPUT_FILE_RESET, row, classProp, className) || void 0
3189
+ });
3190
+ }
3191
+ var floatingLabelSize = {
3192
+ sm: "ds:text-xs",
3193
+ md: "ds:text-[13px]",
3194
+ lg: "ds:text-sm",
3195
+ compact: "ds:text-[13px]",
3196
+ default: "ds:text-sm",
3197
+ comfortable: "ds:text-base",
3198
+ xs: "ds:text-(length:--control-font-size-xs)",
3199
+ xl: "ds:text-(length:--control-font-size-xl)"
3200
+ };
3201
+ var Input = forwardRef(function Input2({
3202
+ label,
3203
+ floatingLabel,
3204
+ description,
3205
+ error,
3206
+ invalid,
3207
+ prefixIcon,
3208
+ suffixIcon,
3209
+ variant,
3210
+ size,
3211
+ inputSize,
3212
+ type = "text",
3213
+ className,
3214
+ classNames,
3215
+ rootClassName,
3216
+ id: providedId,
3217
+ name,
3218
+ required,
3219
+ disabled,
3220
+ readOnly,
3221
+ placeholder,
3222
+ onChange,
3223
+ onValueChange,
3224
+ onWheel,
3225
+ "aria-describedby": ariaDescribedBy,
3226
+ "aria-labelledby": ariaLabelledBy,
3227
+ ...props
3228
+ }, ref) {
3229
+ const field = useFieldContext();
3230
+ const wiring = useFieldControl({
3231
+ id: providedId,
3232
+ name,
3233
+ invalid: error ? true : invalid,
3234
+ required,
3235
+ disabled,
3236
+ readOnly,
3237
+ "aria-labelledby": ariaLabelledBy,
3238
+ "aria-describedby": ariaDescribedBy
3239
+ });
3240
+ const { ref: wiringRef, "aria-describedby": wiredDescribedBy, ...control } = wiring;
3241
+ const id = control.id;
3242
+ const isInvalid = control["aria-invalid"] === true;
3243
+ const descriptionId = partId(id, "description");
3244
+ const errorId = partId(id, "error");
3245
+ const describedBy = joinIds(description && descriptionId, error && errorId, wiredDescribedBy);
3246
+ const inputRef = useMergedRefs(ref, wiringRef);
3247
+ const messages = useDsMessages("input");
3248
+ const [showPassword, setShowPassword] = useState(false);
3249
+ const isPassword = type === "password";
3250
+ const inputType = isPassword && showPassword ? "text" : type;
3251
+ const isFloating = !!floatingLabel && !!label;
3252
+ const fieldSize = field?.size;
3253
+ const recipe = size ? { variant, size } : inputSize ? { variant, inputSize } : fieldSize ? { variant, size: fieldSize } : { variant, inputSize: "md" };
3254
+ const resolvedSize = size ?? inputSize ?? fieldSize ?? "md";
3255
+ const resolvedPlaceholder = isFloating ? placeholder ?? " " : placeholder;
3256
+ const handleWheel = inputType === "number" ? (event) => {
3257
+ onWheel?.(event);
3258
+ if (!event.defaultPrevented) event.currentTarget.blur();
3259
+ } : onWheel;
3260
+ const handleChange = onValueChange ? (event) => {
3261
+ onChange?.(event);
3262
+ onValueChange(event.target.value);
3263
+ } : onChange;
3264
+ return /* @__PURE__ */ jsxs("div", { className: cn("ds:w-full", rootClassName), children: [
3265
+ label && !isFloating && /* @__PURE__ */ jsx(
3266
+ "label",
3267
+ {
3268
+ htmlFor: id,
3269
+ id: partId(id, "label"),
3270
+ ...slot(inputAnatomy, "label"),
3271
+ className: cn(
3272
+ "ds:text-fg ds:mb-1.5 ds:block ds:text-[13px] ds:leading-none ds:font-medium",
3273
+ classNames?.label
3274
+ ),
3275
+ children: label
3276
+ }
3277
+ ),
3278
+ /* @__PURE__ */ jsxs("div", { className: "ds:relative", children: [
3279
+ prefixIcon && /* @__PURE__ */ jsx(
3280
+ "span",
3281
+ {
3282
+ ...slot(inputAnatomy, "icon-start"),
3283
+ className: cn(
3284
+ "ds:text-fg-4 ds:pointer-events-none ds:absolute ds:top-1/2 ds:left-3 ds:-translate-y-1/2 ds:[&>svg]:size-4",
3285
+ classNames?.["icon-start"]
3286
+ ),
3287
+ "aria-hidden": "true",
3288
+ children: prefixIcon
3289
+ }
3290
+ ),
3291
+ /* @__PURE__ */ jsx(
3292
+ "input",
3293
+ {
3294
+ ref: inputRef,
3295
+ type: inputType,
3296
+ placeholder: resolvedPlaceholder,
3297
+ ...control,
3298
+ "aria-describedby": describedBy,
3299
+ ...slot(inputAnatomy, "root"),
3300
+ ...stateAttributes({
3301
+ variant: variant ?? "default",
3302
+ size: resolvedSize,
3303
+ disabled: control.disabled,
3304
+ invalid: isInvalid
3305
+ }),
3306
+ className: cn(
3307
+ inputVariants(recipe),
3308
+ prefixIcon && "ds:pl-9",
3309
+ (suffixIcon || isPassword) && "ds:pr-9",
3310
+ isFloating && "ds:peer ds:focus:placeholder:text-fg-4 ds:placeholder:text-transparent",
3311
+ className
3312
+ ),
3313
+ onWheel: handleWheel,
3314
+ onChange: handleChange,
3315
+ ...props
3316
+ }
3317
+ ),
3318
+ isFloating && // Rendered after the input because `peer-*` compiles to a sibling
3319
+ // combinator; absolute positioning keeps the visual order intact.
3320
+ /* @__PURE__ */ jsx(
3321
+ "label",
3322
+ {
3323
+ htmlFor: id,
3324
+ id: partId(id, "label"),
3325
+ ...slot(inputAnatomy, "label"),
3326
+ className: cn(
3327
+ "ds:pointer-events-none ds:absolute ds:left-3 ds:origin-left ds:px-1 ds:leading-none",
3328
+ "ds:bg-surface ds:text-fg-4",
3329
+ "ds:top-1/2 ds:-translate-y-1/2",
3330
+ "ds:transition-[top,transform,color] ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)]",
3331
+ "ds:motion-reduce:transition-none",
3332
+ // Floated by focus or by content. Both branches declare the same
3333
+ // values, so their relative order in the emitted CSS is moot.
3334
+ "ds:peer-focus:top-0 ds:peer-focus:scale-[0.85]",
3335
+ "ds:peer-[:not(:placeholder-shown)]:top-0 ds:peer-[:not(:placeholder-shown)]:scale-[0.85]",
3336
+ // Colours are split on `:not(:focus)` so the two rules can never
3337
+ // both match, which would otherwise be an ordering coin flip.
3338
+ "ds:peer-focus:text-brand",
3339
+ "ds:peer-[:not(:placeholder-shown):not(:focus)]:text-fg-3",
3340
+ floatingLabelSize[resolvedSize],
3341
+ prefixIcon && "ds:left-9",
3342
+ classNames?.label
3343
+ ),
3344
+ children: label
3345
+ }
3346
+ ),
3347
+ isPassword && /* @__PURE__ */ jsx(
3348
+ "button",
3349
+ {
3350
+ type: "button",
3351
+ onClick: () => setShowPassword((prev) => !prev),
3352
+ ...slot(inputAnatomy, "password-toggle"),
3353
+ className: cn(
3354
+ "ds:text-fg-4 ds:hover:text-fg ds:absolute ds:top-1/2 ds:right-2.5 ds:-translate-y-1/2 ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none ds:motion-reduce:transition-none",
3355
+ classNames?.["password-toggle"]
3356
+ ),
3357
+ "aria-label": showPassword ? messages.hidePassword : messages.showPassword,
3358
+ children: showPassword ? /* @__PURE__ */ jsx(EyeOffIcon, { className: "ds:size-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(EyeIcon, { className: "ds:size-4", "aria-hidden": "true" })
3359
+ }
3360
+ ),
3361
+ suffixIcon && !isPassword && /* @__PURE__ */ jsx(
3362
+ "span",
3363
+ {
3364
+ ...slot(inputAnatomy, "icon-end"),
3365
+ className: cn(
3366
+ "ds:text-fg-4 ds:pointer-events-none ds:absolute ds:top-1/2 ds:right-3 ds:-translate-y-1/2 ds:[&>svg]:size-4",
3367
+ classNames?.["icon-end"]
3368
+ ),
3369
+ "aria-hidden": "true",
3370
+ children: suffixIcon
3371
+ }
3372
+ )
3373
+ ] }),
3374
+ description && /* @__PURE__ */ jsx(
3375
+ "p",
3376
+ {
3377
+ id: descriptionId,
3378
+ ...slot(inputAnatomy, "description"),
3379
+ className: cn("ds:text-fg-3 ds:mt-1.5 ds:text-xs", classNames?.description),
3380
+ children: description
3381
+ }
3382
+ ),
3383
+ error && /* @__PURE__ */ jsx(
3384
+ "p",
3385
+ {
3386
+ id: errorId,
3387
+ role: "alert",
3388
+ ...slot(inputAnatomy, "error"),
3389
+ className: cn("ds:text-danger-fg ds:mt-1.5 ds:text-xs", classNames?.error),
3390
+ children: error
3391
+ }
3392
+ )
3393
+ ] });
3394
+ });
3395
+ Input.displayName = "Input";
3396
+ var TEXTAREA_SIZE_ROWS = {
3397
+ sm: "ds:min-h-(--textarea-min-height-sm) ds:px-2.5 ds:py-1.5 ds:text-xs",
3398
+ md: "ds:min-h-(--textarea-min-height-md) ds:px-3 ds:py-2 ds:text-(length:--control-font-size-md)",
3399
+ lg: "ds:min-h-(--textarea-min-height-lg) ds:px-3.5 ds:py-2.5 ds:text-sm"
3400
+ };
3401
+ function textareaVariants({
3402
+ variant,
3403
+ size,
3404
+ inputSize,
3405
+ class: classProp,
3406
+ className
3407
+ } = {}) {
3408
+ const LEGACY_ROWS = {
3409
+ sm: "ds:min-h-16 ds:px-2.5 ds:py-1.5 ds:text-xs",
3410
+ md: "ds:min-h-20 ds:px-3 ds:py-2 ds:text-[13px]",
3411
+ lg: "ds:min-h-24 ds:px-3.5 ds:py-2.5 ds:text-sm"
3412
+ };
3413
+ const row = size ? TEXTAREA_SIZE_ROWS[size] : LEGACY_ROWS[inputSize ?? "md"];
3414
+ return controlChrome({
3415
+ variant,
3416
+ size: null,
3417
+ class: cn(row, classProp, className) || void 0
3418
+ });
3419
+ }
3420
+ var Textarea = forwardRef(function Textarea2({
3421
+ label,
3422
+ description,
3423
+ error,
3424
+ invalid,
3425
+ showCount,
3426
+ autoResize,
3427
+ variant,
3428
+ size,
3429
+ inputSize,
3430
+ maxLength,
3431
+ value,
3432
+ defaultValue,
3433
+ className,
3434
+ classNames,
3435
+ rootClassName,
3436
+ id: providedId,
3437
+ name,
3438
+ required,
3439
+ disabled,
3440
+ readOnly,
3441
+ onChange,
3442
+ onValueChange,
3443
+ "aria-describedby": ariaDescribedBy,
3444
+ "aria-labelledby": ariaLabelledBy,
3445
+ ...props
3446
+ }, ref) {
3447
+ const field = useFieldContext();
3448
+ const wiring = useFieldControl({
3449
+ id: providedId,
3450
+ name,
3451
+ invalid: error ? true : invalid,
3452
+ required,
3453
+ disabled,
3454
+ readOnly,
3455
+ "aria-labelledby": ariaLabelledBy,
3456
+ "aria-describedby": ariaDescribedBy
3457
+ });
3458
+ const { ref: wiringRef, "aria-describedby": wiredDescribedBy, ...control } = wiring;
3459
+ const id = control.id;
3460
+ const isInvalid = control["aria-invalid"] === true;
3461
+ const descriptionId = partId(id, "description");
3462
+ const errorId = partId(id, "error");
3463
+ const describedBy = joinIds(description && descriptionId, error && errorId, wiredDescribedBy);
3464
+ const internalRef = useRef(null);
3465
+ const setRefs = useMergedRefs(ref, wiringRef, internalRef);
3466
+ const adjustHeight = useCallback(() => {
3467
+ if (!autoResize || !internalRef.current) return;
3468
+ const el = internalRef.current;
3469
+ el.style.height = "auto";
3470
+ el.style.height = `${el.scrollHeight}px`;
3471
+ }, [autoResize]);
3472
+ useEffect(() => {
3473
+ adjustHeight();
3474
+ }, [value, adjustHeight]);
3475
+ const fieldSize = field?.size;
3476
+ const recipe = size ? { variant, size } : inputSize ? { variant, inputSize } : fieldSize && fieldSize in TEXTAREA_SIZE_ROWS ? { variant, size: fieldSize } : { variant, inputSize: "md" };
3477
+ const resolvedSize = recipe.size ?? recipe.inputSize ?? "md";
3478
+ const currentLength = typeof value === "string" ? value.length : typeof defaultValue === "string" ? defaultValue.length : 0;
3479
+ return /* @__PURE__ */ jsxs("div", { className: cn("ds:w-full", rootClassName), children: [
3480
+ label && /* @__PURE__ */ jsx(
3481
+ "label",
3482
+ {
3483
+ htmlFor: id,
3484
+ id: partId(id, "label"),
3485
+ ...slot(textareaAnatomy, "label"),
3486
+ className: cn(
3487
+ "ds:text-fg ds:mb-1.5 ds:block ds:text-[13px] ds:leading-none ds:font-medium",
3488
+ classNames?.label
3489
+ ),
3490
+ children: label
3491
+ }
3492
+ ),
3493
+ /* @__PURE__ */ jsx(
3494
+ "textarea",
3495
+ {
3496
+ ref: setRefs,
3497
+ value,
3498
+ defaultValue,
3499
+ maxLength,
3500
+ ...control,
3501
+ "aria-describedby": describedBy,
3502
+ ...slot(textareaAnatomy, "root"),
3503
+ ...stateAttributes({
3504
+ variant: variant ?? "default",
3505
+ size: resolvedSize,
3506
+ disabled: control.disabled,
3507
+ invalid: isInvalid
3508
+ }),
3509
+ onChange: (e) => {
3510
+ onChange?.(e);
3511
+ onValueChange?.(e.target.value);
3512
+ adjustHeight();
3513
+ },
3514
+ className: cn(
3515
+ textareaVariants(recipe),
3516
+ autoResize && "ds:resize-none ds:overflow-hidden",
3517
+ className
3518
+ ),
3519
+ ...props
3520
+ }
3521
+ ),
3522
+ description && /* @__PURE__ */ jsx(
3523
+ "p",
3524
+ {
3525
+ id: descriptionId,
3526
+ ...slot(textareaAnatomy, "description"),
3527
+ className: cn("ds:text-fg-3 ds:mt-1.5 ds:text-xs", classNames?.description),
3528
+ children: description
3529
+ }
3530
+ ),
3531
+ (error || showCount && maxLength) && /* @__PURE__ */ jsxs("div", { className: "ds:mt-1.5 ds:flex ds:items-center ds:justify-between ds:gap-2", children: [
3532
+ error ? /* @__PURE__ */ jsx(
3533
+ "p",
3534
+ {
3535
+ id: errorId,
3536
+ role: "alert",
3537
+ ...slot(textareaAnatomy, "error"),
3538
+ className: cn("ds:text-danger-fg ds:text-xs", classNames?.error),
3539
+ children: error
3540
+ }
3541
+ ) : /* @__PURE__ */ jsx("span", {}),
3542
+ showCount && maxLength && /* @__PURE__ */ jsxs(
3543
+ "span",
3544
+ {
3545
+ ...slot(textareaAnatomy, "count"),
3546
+ className: cn(
3547
+ "ds:text-fg-4 ds:ml-auto ds:font-mono ds:text-[11px]",
3548
+ classNames?.count
3549
+ ),
3550
+ children: [
3551
+ currentLength,
3552
+ "/",
3553
+ maxLength
3554
+ ]
3555
+ }
3556
+ )
3557
+ ] })
3558
+ ] });
3559
+ });
3560
+ Textarea.displayName = "Textarea";
3561
+ var DocumentDetailPanel = forwardRef(
3562
+ function DocumentDetailPanel2({ className, ...props }, ref) {
3563
+ return /* @__PURE__ */ jsx(
3564
+ "aside",
3565
+ {
3566
+ ref,
3567
+ className: cn(
3568
+ "ds:bg-surface ds:text-fg ds:border-rule ds:flex ds:h-full ds:min-h-0 ds:flex-col ds:border-l",
3569
+ className
3570
+ ),
3571
+ ...props
3572
+ }
3573
+ );
3574
+ }
3575
+ );
3576
+ DocumentDetailPanel.displayName = "DocumentDetailPanel";
3577
+ var DocumentDetailHeader = forwardRef(
3578
+ function DocumentDetailHeader2({ tags, status, onClose, className, children, ...props }, ref) {
3579
+ const showControls = Boolean(status || onClose);
3580
+ const tagsClearance = !showControls ? void 0 : status ? "ds:pr-32" : "ds:pr-12";
3581
+ const titleClearance = !showControls || tags ? void 0 : status ? "ds:[&>:first-child]:pr-32" : "ds:[&>:first-child]:pr-12";
3582
+ return /* @__PURE__ */ jsxs(
3583
+ "div",
3584
+ {
3585
+ ref,
3586
+ className: cn("ds:border-rule ds:relative ds:shrink-0 ds:space-y-3 ds:border-b ds:px-5 ds:py-4", className),
3587
+ ...props,
3588
+ children: [
3589
+ showControls && /* @__PURE__ */ jsxs("div", { className: "ds:absolute ds:top-4 ds:right-5 ds:z-[calc(var(--z-base)+10)] ds:flex ds:shrink-0 ds:items-center ds:gap-2", children: [
3590
+ status,
3591
+ onClose && /* @__PURE__ */ jsx(
3592
+ "button",
3593
+ {
3594
+ type: "button",
3595
+ onClick: onClose,
3596
+ "aria-label": "Close",
3597
+ className: cn(
3598
+ "ds:inline-flex ds:size-7 ds:shrink-0 ds:items-center ds:justify-center",
3599
+ "ds:rounded-icon ds:text-fg-4 ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
3600
+ "ds:hover:bg-overlay-hover ds:hover:text-fg",
3601
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none"
3602
+ ),
3603
+ children: /* @__PURE__ */ jsx(XIcon, { className: "ds:size-4", "aria-hidden": "true" })
3604
+ }
3605
+ )
3606
+ ] }),
3607
+ tags && /* @__PURE__ */ jsx("div", { className: cn("ds:flex ds:min-w-0 ds:flex-wrap ds:items-center ds:gap-1.5", tagsClearance), children: tags }),
3608
+ /* @__PURE__ */ jsx("div", { className: cn("ds:space-y-3", titleClearance), children })
3609
+ ]
3610
+ }
3611
+ );
3612
+ }
3613
+ );
3614
+ DocumentDetailHeader.displayName = "DocumentDetailHeader";
3615
+ var DocumentDetailTitle = forwardRef(
3616
+ function DocumentDetailTitle2({ className, children, ...props }, ref) {
3617
+ return /* @__PURE__ */ jsx(
3618
+ "h2",
3619
+ {
3620
+ ref,
3621
+ className: cn(
3622
+ "ds:font-display ds:text-fg ds:text-lg ds:leading-snug ds:font-semibold ds:tracking-tight",
3623
+ className
3624
+ ),
3625
+ ...props,
3626
+ children
3627
+ }
3628
+ );
3629
+ }
3630
+ );
3631
+ DocumentDetailTitle.displayName = "DocumentDetailTitle";
3632
+ var DocumentDetailRequester = forwardRef(
3633
+ function DocumentDetailRequester2({ avatar, org, requestedBy, time, className, ...props }, ref) {
3634
+ const isImageSrc = /^(https?:|data:|\/)/i.test(avatar);
3635
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("ds:flex ds:items-center ds:gap-2.5", className), ...props, children: [
3636
+ /* @__PURE__ */ jsx(Avatar, { size: "sm", src: isImageSrc ? avatar : void 0, name: isImageSrc ? org : avatar }),
3637
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0", children: [
3638
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:line-clamp-1 ds:text-sm ds:font-medium", children: org }),
3639
+ /* @__PURE__ */ jsxs("div", { className: "ds:text-fg-4 ds:text-xs", children: [
3640
+ "Requested by ",
3641
+ requestedBy,
3642
+ " \xB7 ",
3643
+ time
3644
+ ] })
3645
+ ] })
3646
+ ] });
3647
+ }
3648
+ );
3649
+ DocumentDetailRequester.displayName = "DocumentDetailRequester";
3650
+ var DocumentDetailMetaRow = forwardRef(
3651
+ function DocumentDetailMetaRow2({ className, ...props }, ref) {
3652
+ return /* @__PURE__ */ jsx(
3653
+ "div",
3654
+ {
3655
+ ref,
3656
+ className: cn("ds:flex ds:items-center ds:justify-between ds:gap-3", className),
3657
+ ...props
3658
+ }
3659
+ );
3660
+ }
3661
+ );
3662
+ DocumentDetailMetaRow.displayName = "DocumentDetailMetaRow";
3663
+ var DocumentDetailActions = forwardRef(
3664
+ function DocumentDetailActions2({ className, ...props }, ref) {
3665
+ return /* @__PURE__ */ jsx(
3666
+ "div",
3667
+ {
3668
+ ref,
3669
+ className: cn("ds:flex ds:flex-wrap ds:items-center ds:gap-2 ds:[&>*]:flex-1", className),
3670
+ ...props
3671
+ }
3672
+ );
3673
+ }
3674
+ );
3675
+ DocumentDetailActions.displayName = "DocumentDetailActions";
3676
+ var DocumentDetailBody = forwardRef(
3677
+ function DocumentDetailBody2({ className, ...props }, ref) {
3678
+ return /* @__PURE__ */ jsx(
3679
+ "div",
3680
+ {
3681
+ ref,
3682
+ className: cn("ds:scrollbar-thin ds:min-h-0 ds:flex-1 ds:overflow-y-auto ds:px-5 ds:py-4", className),
3683
+ ...props
3684
+ }
3685
+ );
3686
+ }
3687
+ );
3688
+ DocumentDetailBody.displayName = "DocumentDetailBody";
3689
+ var DocumentList = forwardRef(function DocumentList2({ className, ...props }, ref) {
3690
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("ds:space-y-5", className), ...props });
3691
+ });
3692
+ DocumentList.displayName = "DocumentList";
3693
+ var DocumentListSection = forwardRef(
3694
+ function DocumentListSection2({ label, count, action, className, children, ...props }, ref) {
3695
+ return /* @__PURE__ */ jsxs("section", { ref, className: cn("ds:space-y-1", className), ...props, children: [
3696
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-center ds:justify-between ds:gap-2 ds:px-2.5 ds:py-1", children: [
3697
+ /* @__PURE__ */ jsxs("div", { className: "ds:text-fg-3 ds:flex ds:items-center ds:gap-1.5 ds:text-xs ds:font-medium", children: [
3698
+ /* @__PURE__ */ jsx("span", { children: label }),
3699
+ count != null && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-4 ds:tabular-nums", children: count })
3700
+ ] }),
3701
+ action
3702
+ ] }),
3703
+ /* @__PURE__ */ jsx("div", { className: "ds:space-y-0.5", children })
3704
+ ] });
3705
+ }
3706
+ );
3707
+ DocumentListSection.displayName = "DocumentListSection";
3708
+ var DocumentRow = forwardRef(function DocumentRow2({ fileName, meta, icon, approved, rejected, actions, className, ...props }, ref) {
3709
+ return /* @__PURE__ */ jsxs(
3710
+ "div",
3711
+ {
3712
+ ref,
3713
+ className: cn(
3714
+ "ds:group/row ds:rounded-card ds:flex ds:items-center ds:gap-3 ds:px-2.5 ds:py-2",
3715
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
3716
+ "ds:hover:bg-overlay-hover",
3717
+ className
3718
+ ),
3719
+ ...props,
3720
+ children: [
3721
+ /* @__PURE__ */ jsx(
3722
+ "span",
3723
+ {
3724
+ "aria-hidden": "true",
3725
+ className: cn(
3726
+ "ds:rounded-icon ds:inline-flex ds:size-9 ds:shrink-0 ds:items-center ds:justify-center",
3727
+ approved ? "ds:bg-success-bg ds:text-success-fg" : rejected ? "ds:bg-danger-bg ds:text-danger-fg" : "ds:bg-bg-2 ds:text-fg-3"
3728
+ ),
3729
+ children: icon ?? /* @__PURE__ */ jsx(FileTextIcon, { className: "ds:size-4.5" })
3730
+ }
3731
+ ),
3732
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0 ds:flex-1", children: [
3733
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:min-w-0 ds:items-center ds:gap-1.5", children: [
3734
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:line-clamp-1 ds:min-w-0 ds:text-sm ds:font-medium", children: fileName }),
3735
+ approved ? /* @__PURE__ */ jsxs("span", { className: "ds:bg-success-bg ds:text-success-fg ds:inline-flex ds:shrink-0 ds:items-center ds:gap-1 ds:rounded-md ds:px-1.5 ds:py-0.5 ds:text-[10.5px] ds:font-semibold", children: [
3736
+ /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-3", "aria-hidden": "true" }),
3737
+ "Approved"
3738
+ ] }) : rejected ? /* @__PURE__ */ jsxs("span", { className: "ds:bg-danger-bg ds:text-danger-fg ds:inline-flex ds:shrink-0 ds:items-center ds:gap-1 ds:rounded-md ds:px-1.5 ds:py-0.5 ds:text-[10.5px] ds:font-semibold", children: [
3739
+ /* @__PURE__ */ jsx(AlertTriangleIcon, { className: "ds:size-3", "aria-hidden": "true" }),
3740
+ "Rejected"
3741
+ ] }) : null
3742
+ ] }),
3743
+ meta && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:line-clamp-1 ds:text-xs", children: meta })
3744
+ ] }),
3745
+ actions && /* @__PURE__ */ jsx("div", { className: "ds:flex ds:shrink-0 ds:items-center ds:gap-0.5", children: actions })
3746
+ ]
3747
+ }
3748
+ );
3749
+ });
3750
+ DocumentRow.displayName = "DocumentRow";
3751
+
3752
+ export { Avatar, Backdrop, Button, CONTROL_GAP_CLASSES, CONTROL_SIZE_CLASSES, Checkbox, DEFAULT_OVERLAY_MESSAGES, DISABLED_LOOK_CLASSES, DISMISS_GLYPH_CLASSES, DesignSystemContext, DismissButton, DocumentDetailActions, DocumentDetailBody, DocumentDetailHeader, DocumentDetailMetaRow, DocumentDetailPanel, DocumentDetailRequester, DocumentDetailTitle, DocumentList, DocumentListSection, DocumentRow, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EN_MESSAGES, FIELD_PARTS, FLOATING_PADDING, FLOATING_WIDTH, FieldContext, FieldsetContext, FileChip, FileUpload, FormBridge, INERT_ATTRIBUTES, INERT_CLASSES, IconButton, Input, LIST_ITEM_INDICATOR_WELL, LIST_SEPARATOR, MENU_CHECK_GLYPH, MENU_INDICATOR_WELL, MENU_INSET, MENU_ITEM_DANGER, MENU_RADIO_GLYPH, MENU_SUB_TRIGGER_CHEVRON, ModalContent, ModalDescription, ModalOverlay, ModalPortal, ModalRoot, ModalTitle, OverlayBody, OverlayDescription, OverlayFooter, OverlayHeader, OverlaySurface, OverlayTitle, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverPortal, PopoverTrigger, Portal, PortalContainerContext, Pressable, SPINNER_TONE_TO_INTENT, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Spinner, TOOLTIP_DEFAULT_DELAY_MS, Textarea, ThemeScope, Tooltip, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger, alertDialogAnatomy, badgeAnatomy, buttonBase, buttonVariants, cardAnatomy, chipAnatomy, codeAnatomy, comboboxAnatomy, commandAnatomy, contextMenuAnatomy, controlChrome, dataTableAnatomy, deprecate, dialogAnatomy, errorOnce, fieldAnatomy, fieldsetAnatomy, floatingSurfaceClasses, groupHeadingClasses, headingAnatomy, iconButtonVariants, inertHandlers, inlineAnatomy, inputVariants, isLabelable, joinIds, kbdAnatomy, labelAnatomy, linkButtonAnatomy, listItemAttributes, listItemClasses, menuIndicatorItemClasses, menuItemClasses, menuLabelClasses, menuSeparatorClasses, menuShortcutClasses, menuSubTriggerClasses, mergeRefs, microInteractions, numberInputAnatomy, optionElementId, paginationAnatomy, partId, phoneFieldAnatomy, presence, radioGroupAnatomy, resolveButtonIcons, resolveButtonStyle, searchInputAnatomy, sheetAnatomy, shellAnatomy, sideDrawerAnatomy, sidebarAnatomy, sidebarBrandSwitcherAnatomy, slot, spinnerVariants, stackAnatomy, stateAttributes, statusBadgeAnatomy, surfaceAnatomy, switchAnatomy, tableAnatomy, textAnatomy, textareaVariants, toastAnatomy, useControllableState, useDsMessages, useExitPresence, useFieldContext, useFieldControl, useFieldsetContext, useFieldsetLegend, useFieldsetState, useFormReset, useId, useImageComponent, useLinkComponent, useMergedRefs, warnLegacyButtonProps, withPortalContainer };
3753
+ //# sourceMappingURL=chunk-2MKLYYIY.js.map
3754
+ //# sourceMappingURL=chunk-2MKLYYIY.js.map