@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,4336 @@
1
+ import { stateAttributes, slot, chipAnatomy, Pressable, CONTROL_GAP_CLASSES, EN_MESSAGES, microInteractions, listItemClasses, groupHeadingClasses, useDsMessages, withPortalContainer, Backdrop, sheetAnatomy, deprecate, OverlaySurface, DismissButton, DEFAULT_OVERLAY_MESSAGES, DISMISS_GLYPH_CLASSES, OverlayBody, OverlayTitle, OverlayDescription, Input, Textarea, Select, FileUpload, FileChip, Button, Checkbox, Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, sidebarAnatomy, Slot, Avatar, DropdownMenu, DropdownMenuTrigger, sidebarBrandSwitcherAnatomy, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem, buttonBase, CONTROL_SIZE_CLASSES, useFieldControl, useId as useId$1, useControllableState, useMergedRefs, Popover, PopoverAnchor, comboboxAnatomy, Spinner, IconButton, PopoverContent, LIST_SEPARATOR, listItemAttributes, optionElementId, FormBridge, useLinkComponent, useImageComponent, OverlayHeader, OverlayFooter, LIST_ITEM_INDICATOR_WELL } from './chunk-2MKLYYIY.js';
2
+ import { cn, XIcon, CheckIcon, EyeIcon, DownloadIcon, PhoneIcon, MailIcon, GlobeIcon, HomeIcon, ChevronLeftIcon, ChevronRightIcon, ReceiptIcon, RotateCcwIcon, CreditCardIcon, LockIcon, FileTextIcon, PlayIcon, InfoIcon, ClockIcon, PenSignIcon, TrashIcon, PlusIcon, CheckCircleSolidIcon, HelpCircleIcon, MinusIcon, PanelLeftCloseIcon, PanelLeftIcon, ChevronDownIcon } from './chunk-KQBYTTAN.js';
3
+ import { parseHexColor, contrastRatio, WHITE, formatHexColor, darkenUntilContrast } from './chunk-EUHGZA6Q.js';
4
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
5
+ import * as React6 from 'react';
6
+ import { forwardRef, useId, useState, Fragment as Fragment$1, createContext, useContext } from 'react';
7
+ import { RemoveScroll } from 'react-remove-scroll';
8
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
9
+ import * as SheetPrimitive from '@radix-ui/react-dialog';
10
+ import { cva } from 'class-variance-authority';
11
+
12
+ var BRAND_BASE_FILL = "#070707";
13
+ var BRAND_BASE_PATH = "M43.8298 23.829C46.9635 23.7428 50.7456 23.9675 54.0114 23.9437L91.3493 23.8048C97.6806 23.7927 101.727 24.9883 106.302 29.5107C107.671 30.864 108.443 32.0751 109.418 33.7063C112.332 38.5806 112.037 42.6442 112.003 48.0679L112.02 56.4922C108.427 57.4911 101.053 57.2229 96.9953 57.2944C87.0232 57.47 76.9072 57.2055 66.9345 57.4014C66.7192 66.474 66.9079 75.8103 66.8438 84.9327C66.7469 92.0668 67.2878 101.738 66.6431 108.599C60.7359 108.871 54.5467 108.479 48.6135 108.641C40.5834 108.86 34.2651 108.559 28.1575 102.692C20.618 95.4486 21.8015 86.9701 21.8025 77.474L21.8166 59.8481L21.8312 49.597C21.8372 47.075 21.7515 43.5009 22.2502 41.142C22.9069 38.0359 25.4258 33.4304 27.6724 31.1548C32.4002 26.3658 37.1772 24.0905 43.8298 23.829Z";
14
+ var BRAND_ACCENT_PATH = "M83.7555 72.8376C85.3789 72.6548 90.5991 72.7708 92.4304 72.7692L100.779 72.7802C102.529 72.7903 104.546 72.7296 106.26 73.0259C108.43 73.422 111.61 75.5699 111.737 77.9539C112.107 84.8649 111.986 91.8555 111.974 98.7715C111.969 101.35 111.928 103.109 110.232 105.149C108.61 107.101 107.07 108.323 104.518 108.621C99.7602 108.503 95.0005 108.467 90.2413 108.513C87.5612 108.531 84.6034 108.799 81.9937 108.434C78.4024 107.933 76.1145 105.214 76.0317 101.618C75.9281 97.1186 75.8903 92.669 75.9646 88.174C76.0209 84.7695 75.8279 81.2851 76.3134 77.921C76.3993 77.3266 77.1785 76.1903 77.6286 75.7193C79.6145 73.6412 80.9496 73.0158 83.7555 72.8376Z";
15
+ function BrandIcon({
16
+ size = 24,
17
+ accent,
18
+ title,
19
+ className,
20
+ ...props
21
+ }) {
22
+ return /* @__PURE__ */ jsxs(
23
+ "svg",
24
+ {
25
+ width: size,
26
+ height: size,
27
+ viewBox: "0 0 136 137",
28
+ fill: "none",
29
+ xmlns: "http://www.w3.org/2000/svg",
30
+ className: cn("ds:shrink-0", className),
31
+ role: "img",
32
+ "aria-label": title,
33
+ ...props,
34
+ children: [
35
+ /* @__PURE__ */ jsx("path", { d: BRAND_BASE_PATH, fill: BRAND_BASE_FILL }),
36
+ /* @__PURE__ */ jsx("path", { d: BRAND_ACCENT_PATH, fill: accent })
37
+ ]
38
+ }
39
+ );
40
+ }
41
+ function AssureProBrandIcon({ size = 24, ...props }) {
42
+ return /* @__PURE__ */ jsx(BrandIcon, { size, accent: "var(--ds-ref-brand-pro-seed, var(--color-brand-pro))", title: "Assure Pro", ...props });
43
+ }
44
+ function AssureAuditBrandIcon({ size = 24, ...props }) {
45
+ return /* @__PURE__ */ jsx(BrandIcon, { size, accent: "var(--ds-ref-brand-audit-seed, var(--color-brand-audit))", title: "Assure Audit", ...props });
46
+ }
47
+ function AssureBooksBrandIcon({ size = 24, ...props }) {
48
+ return /* @__PURE__ */ jsx(BrandIcon, { size, accent: "var(--ds-ref-brand-books-seed, var(--color-brand-books))", title: "Assure Books", ...props });
49
+ }
50
+ function AssureTaxBrandIcon({ size = 24, ...props }) {
51
+ return /* @__PURE__ */ jsx(BrandIcon, { size, accent: "var(--ds-ref-brand-tax-seed, var(--color-brand-tax))", title: "Assure Tax", ...props });
52
+ }
53
+ function chipVariants({
54
+ variant,
55
+ intent,
56
+ size,
57
+ pressed,
58
+ className
59
+ } = {}) {
60
+ const { look } = resolveChipStyle({ variant, intent, pressed });
61
+ return cn(
62
+ buttonBase({ look, size: null }),
63
+ "ds:rounded-full ds:shrink-0",
64
+ CONTROL_SIZE_CLASSES[size ?? "sm"],
65
+ className
66
+ );
67
+ }
68
+ function resolveChipStyle({
69
+ variant,
70
+ intent,
71
+ pressed
72
+ }) {
73
+ const emphasis = variant ?? "soft";
74
+ const requested = intent === "destructive" ? "danger" : intent;
75
+ const family = requested ?? (pressed ? "brand" : "neutral");
76
+ return { variant: emphasis, intent: family, look: `${emphasis}/${family}` };
77
+ }
78
+ var REMOVE_HOVER = {
79
+ brand: "ds:hover:bg-brand-bg-active",
80
+ neutral: "ds:hover:bg-control-active-bg",
81
+ success: "ds:hover:bg-success-line",
82
+ danger: "ds:hover:bg-danger-line"
83
+ };
84
+ var Chip = forwardRef(function Chip2({
85
+ children,
86
+ icon,
87
+ count,
88
+ variant,
89
+ intent,
90
+ size = "sm",
91
+ pressed,
92
+ onPressedChange,
93
+ onClick,
94
+ onRemove,
95
+ removeLabel,
96
+ disabled,
97
+ className,
98
+ ...props
99
+ }, ref) {
100
+ const isToggle = pressed !== void 0 || onPressedChange !== void 0;
101
+ const pressedValue = isToggle ? Boolean(pressed) : void 0;
102
+ const interactive = isToggle || onClick !== void 0;
103
+ const style = resolveChipStyle({ variant, intent, pressed: pressedValue });
104
+ const resolvedRemoveLabel = removeLabel ?? (typeof children === "string" ? `Remove ${children}` : void 0);
105
+ if (process.env.NODE_ENV !== "production" && onRemove && resolvedRemoveLabel === void 0) {
106
+ throw new Error(
107
+ "[Chip] `removeLabel` is required when `onRemove` is set and the label is not a string: the remove button needs an accessible name."
108
+ );
109
+ }
110
+ const handleClick = (event) => {
111
+ onClick?.(event);
112
+ if (event.defaultPrevented) return;
113
+ if (isToggle) onPressedChange?.(!pressedValue);
114
+ };
115
+ const state = stateAttributes({
116
+ variant: style.variant,
117
+ intent: style.intent,
118
+ size,
119
+ disabled,
120
+ pressed: pressedValue
121
+ });
122
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
123
+ icon && /* @__PURE__ */ jsx(
124
+ "span",
125
+ {
126
+ ...slot(chipAnatomy, "icon"),
127
+ className: "ds:inline-flex ds:shrink-0",
128
+ "aria-hidden": "true",
129
+ children: icon
130
+ }
131
+ ),
132
+ /* @__PURE__ */ jsx("span", { ...slot(chipAnatomy, "label"), children }),
133
+ typeof count === "number" && /* @__PURE__ */ jsx("span", { ...slot(chipAnatomy, "count"), className: "ds:font-normal ds:tabular-nums", children: count })
134
+ ] });
135
+ if (!onRemove) {
136
+ return /* @__PURE__ */ jsx(
137
+ Pressable,
138
+ {
139
+ ref,
140
+ pressed: pressedValue,
141
+ disabled,
142
+ onClick: handleClick,
143
+ ...slot(chipAnatomy, "root"),
144
+ ...state,
145
+ className: chipVariants({ variant, intent, size, pressed: pressedValue, className }),
146
+ ...props,
147
+ children: content
148
+ }
149
+ );
150
+ }
151
+ return /* @__PURE__ */ jsxs(
152
+ "span",
153
+ {
154
+ ref,
155
+ "aria-disabled": disabled || void 0,
156
+ ...slot(chipAnatomy, "root"),
157
+ ...state,
158
+ className: cn(
159
+ chipVariants({ variant, intent, size, pressed: pressedValue }),
160
+ // The remove button ends the row in its own 24px box (a hit target of
161
+ // its own, WCAG 2.5.8), so the end padding is the box's, not the text's.
162
+ "ds:pe-1",
163
+ !interactive && "ds:cursor-default",
164
+ disabled && "ds:pointer-events-none ds:bg-bg-disabled ds:text-fg-disabled",
165
+ className
166
+ ),
167
+ ...props,
168
+ children: [
169
+ interactive ? /* @__PURE__ */ jsx(
170
+ Pressable,
171
+ {
172
+ pressed: pressedValue,
173
+ disabled,
174
+ onClick: handleClick,
175
+ className: cn(
176
+ "ds:inline-flex ds:h-full ds:min-w-0 ds:items-center ds:rounded-full ds:bg-transparent ds:p-0 ds:text-inherit",
177
+ CONTROL_GAP_CLASSES[size]
178
+ ),
179
+ children: content
180
+ }
181
+ ) : /* @__PURE__ */ jsx(
182
+ "span",
183
+ {
184
+ className: cn("ds:inline-flex ds:min-w-0 ds:items-center", CONTROL_GAP_CLASSES[size]),
185
+ children: content
186
+ }
187
+ ),
188
+ /* @__PURE__ */ jsx(
189
+ Pressable,
190
+ {
191
+ ...slot(chipAnatomy, "remove"),
192
+ "aria-label": resolvedRemoveLabel,
193
+ disabled,
194
+ onClick: onRemove,
195
+ className: cn(
196
+ "ds:inline-flex ds:size-6 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-full ds:bg-transparent ds:p-0 ds:text-inherit",
197
+ "ds:transition-colors ds:duration-[var(--motion-duration-feedback)] ds:motion-reduce:transition-none",
198
+ REMOVE_HOVER[style.intent]
199
+ ),
200
+ children: /* @__PURE__ */ jsx(XIcon, { "aria-hidden": "true" })
201
+ }
202
+ )
203
+ ]
204
+ }
205
+ );
206
+ });
207
+ Chip.displayName = "Chip";
208
+
209
+ // src/primitives/behavior/collection/option.ts
210
+ function isOption(item) {
211
+ return typeof item === "object" && item !== null && typeof item.value === "string" && typeof item.label === "string";
212
+ }
213
+ var optionAccessors = {
214
+ getOptionValue: (option) => option.value,
215
+ getOptionLabel: (option) => option.label,
216
+ getOptionDisabled: (option) => option.disabled === true,
217
+ getOptionGroup: (option) => option.group,
218
+ getOptionKeywords: (option) => option.keywords
219
+ };
220
+ var stringOptionAccessors = {
221
+ getOptionValue: (item) => item,
222
+ getOptionLabel: (item) => item
223
+ };
224
+ function resolveAccessors(item, accessors) {
225
+ if (accessors !== void 0) return accessors;
226
+ if (typeof item === "string") {
227
+ return stringOptionAccessors;
228
+ }
229
+ if (isOption(item)) {
230
+ return optionAccessors;
231
+ }
232
+ throw new TypeError(
233
+ "collection: an item that is neither a string nor an Option needs accessors (getOptionValue/getOptionLabel)"
234
+ );
235
+ }
236
+ function toOption(item, accessors) {
237
+ const read = resolveAccessors(item, accessors);
238
+ if (accessors === void 0 && isOption(item)) {
239
+ return item;
240
+ }
241
+ const base = isOption(item) ? { ...item } : { value: read.getOptionValue(item), label: read.getOptionLabel(item) };
242
+ base.value = read.getOptionValue(item);
243
+ base.label = read.getOptionLabel(item);
244
+ const disabled = read.getOptionDisabled?.(item);
245
+ if (disabled !== void 0) base.disabled = disabled;
246
+ const group = read.getOptionGroup?.(item);
247
+ if (group !== void 0) base.group = group;
248
+ const keywords = read.getOptionKeywords?.(item);
249
+ if (keywords !== void 0) base.keywords = keywords;
250
+ if (!isOption(item) && typeof item !== "string") base.meta = item;
251
+ return base;
252
+ }
253
+ function toOptions(items, accessors) {
254
+ const options = items.map((item) => toOption(item, accessors));
255
+ if (process.env.NODE_ENV !== "production") {
256
+ const seen = /* @__PURE__ */ new Set();
257
+ for (const option of options) {
258
+ if (option.value === "") {
259
+ throw new TypeError(
260
+ `collection: option ${JSON.stringify(option.label)} has an empty value; emptiness is value === null on the control, not a row`
261
+ );
262
+ }
263
+ if (seen.has(option.value)) {
264
+ throw new TypeError(
265
+ `collection: option value ${JSON.stringify(option.value)} appears twice; values must be unique`
266
+ );
267
+ }
268
+ seen.add(option.value);
269
+ }
270
+ }
271
+ return options;
272
+ }
273
+ function findOption(options, value) {
274
+ if (value === null || value === void 0) return void 0;
275
+ return options.find((option) => option.value === value);
276
+ }
277
+ function groupOptions(options) {
278
+ const buckets = /* @__PURE__ */ new Map();
279
+ const ordered = [];
280
+ for (const option of options) {
281
+ let bucket = buckets.get(option.group);
282
+ if (!bucket) {
283
+ bucket = { group: option.group, options: [] };
284
+ buckets.set(option.group, bucket);
285
+ ordered.push(bucket);
286
+ }
287
+ bucket.options.push(option);
288
+ }
289
+ return ordered;
290
+ }
291
+ function foldForMatch(text) {
292
+ return text.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/\s+/g, " ").trim();
293
+ }
294
+ function optionMatches(option, query) {
295
+ const needle = foldForMatch(query);
296
+ if (needle === "") return true;
297
+ if (foldForMatch(option.label).includes(needle)) return true;
298
+ if (option.group !== void 0 && foldForMatch(option.group).includes(needle)) return true;
299
+ return option.keywords?.some((keyword) => foldForMatch(keyword).includes(needle)) ?? false;
300
+ }
301
+ function filterOptions(options, query) {
302
+ return options.filter((option) => optionMatches(option, query));
303
+ }
304
+ function normalizeSingleValue(value) {
305
+ return value === void 0 || value === null || value === "" ? null : value;
306
+ }
307
+ function normalizeMultipleValue(value) {
308
+ if (value === void 0 || value === null) return [];
309
+ return value.filter((entry) => entry !== "");
310
+ }
311
+ function toggleValue(selection, optionValue) {
312
+ return selection.includes(optionValue) ? selection.filter((entry) => entry !== optionValue) : [...selection, optionValue];
313
+ }
314
+
315
+ // src/primitives/behavior/collection/keyboard.ts
316
+ function firstEnabledIndex(rows, from = 0) {
317
+ for (let index = Math.max(0, from); index < rows.length; index += 1) {
318
+ if (!rows[index]?.disabled) return index;
319
+ }
320
+ return null;
321
+ }
322
+ function lastEnabledIndex(rows, from = rows.length - 1) {
323
+ for (let index = Math.min(rows.length - 1, from); index >= 0; index -= 1) {
324
+ if (!rows[index]?.disabled) return index;
325
+ }
326
+ return null;
327
+ }
328
+ function stepEnabledIndex(rows, from, direction, { loop = false, steps = 1 } = {}) {
329
+ if (rows.length === 0) return null;
330
+ if (from === null) {
331
+ return direction === 1 ? firstEnabledIndex(rows) : lastEnabledIndex(rows);
332
+ }
333
+ let current = from;
334
+ for (let taken = 0; taken < steps; taken += 1) {
335
+ const candidate = direction === 1 ? firstEnabledIndex(rows, current + 1) : lastEnabledIndex(rows, current - 1);
336
+ if (candidate === null) {
337
+ if (loop && taken === 0) {
338
+ const wrapped = direction === 1 ? firstEnabledIndex(rows) : lastEnabledIndex(rows);
339
+ return wrapped ?? from;
340
+ }
341
+ break;
342
+ }
343
+ current = candidate;
344
+ }
345
+ return current;
346
+ }
347
+ var NAVIGATION_KEYS = /* @__PURE__ */ new Set([
348
+ "ArrowDown",
349
+ "ArrowUp",
350
+ "ArrowRight",
351
+ "ArrowLeft",
352
+ "Home",
353
+ "End",
354
+ "PageDown",
355
+ "PageUp"
356
+ ]);
357
+ function isListNavigationKey(key, orientation = "vertical") {
358
+ if (!NAVIGATION_KEYS.has(key)) return false;
359
+ if (orientation === "vertical") return key !== "ArrowRight" && key !== "ArrowLeft";
360
+ return key !== "ArrowDown" && key !== "ArrowUp";
361
+ }
362
+ function nextHighlightedIndex(rows, highlighted, key, { loop = false, pageSize = 10, orientation = "vertical" } = {}) {
363
+ if (!isListNavigationKey(key, orientation)) return void 0;
364
+ switch (key) {
365
+ case "ArrowDown":
366
+ case "ArrowRight":
367
+ return stepEnabledIndex(rows, highlighted, 1, { loop });
368
+ case "ArrowUp":
369
+ case "ArrowLeft":
370
+ return stepEnabledIndex(rows, highlighted, -1, { loop });
371
+ case "Home":
372
+ return firstEnabledIndex(rows);
373
+ case "End":
374
+ return lastEnabledIndex(rows);
375
+ case "PageDown":
376
+ return stepEnabledIndex(rows, highlighted, 1, { steps: pageSize });
377
+ case "PageUp":
378
+ return stepEnabledIndex(rows, highlighted, -1, { steps: pageSize });
379
+ default:
380
+ return void 0;
381
+ }
382
+ }
383
+ function reconcileHighlight(rows, highlightedValue, fallback = "first") {
384
+ if (highlightedValue !== null) {
385
+ const kept = rows.find((row) => row.value === highlightedValue && !row.disabled);
386
+ if (kept) return kept.value;
387
+ }
388
+ if (fallback === "none") return null;
389
+ const first = firstEnabledIndex(rows);
390
+ return first === null ? null : rows[first]?.value ?? null;
391
+ }
392
+ function indexOfValue(rows, value) {
393
+ if (value === null) return null;
394
+ const index = rows.findIndex((row) => row.value === value);
395
+ return index === -1 ? null : index;
396
+ }
397
+ function activeDescendantId(listId, rows, highlighted) {
398
+ if (highlighted === null || highlighted < 0 || highlighted >= rows.length) return void 0;
399
+ const row = rows[highlighted];
400
+ return row ? optionElementId(listId, row.value) : void 0;
401
+ }
402
+ function NestedScrollLock({
403
+ active = true,
404
+ children
405
+ }) {
406
+ if (!active) return /* @__PURE__ */ jsx(Fragment, { children });
407
+ return /* @__PURE__ */ jsx(RemoveScroll, { removeScrollBar: false, className: "ds:contents", children });
408
+ }
409
+ var DEFAULT_COMBOBOX_MESSAGES = EN_MESSAGES.combobox;
410
+ var CONTROL_SIZE = {
411
+ xs: "ds:min-h-(--control-height-xs) ds:ps-(--control-padding-x-xs) ds:text-(length:--control-font-size-xs) ds:gap-(--control-gap-xs) ds:[&_svg]:size-(--control-icon-xs)",
412
+ sm: "ds:min-h-(--control-height-sm) ds:ps-(--control-padding-x-sm) ds:text-(length:--control-font-size-sm) ds:gap-(--control-gap-sm) ds:[&_svg]:size-(--control-icon-sm)",
413
+ md: "ds:min-h-(--control-height-md) ds:ps-(--control-padding-x-md) ds:text-(length:--control-font-size-md) ds:gap-(--control-gap-md) ds:[&_svg]:size-(--control-icon-md)",
414
+ lg: "ds:min-h-(--control-height-lg) ds:ps-(--control-padding-x-lg) ds:text-(length:--control-font-size-lg) ds:gap-(--control-gap-lg) ds:[&_svg]:size-(--control-icon-lg)",
415
+ xl: "ds:min-h-(--control-height-xl) ds:ps-(--control-padding-x-xl) ds:text-(length:--control-font-size-xl) ds:gap-(--control-gap-xl) ds:[&_svg]:size-(--control-icon-xl)"
416
+ };
417
+ var BUTTON_SIZE = {
418
+ xs: "xs",
419
+ sm: "xs",
420
+ md: "xs",
421
+ lg: "sm",
422
+ xl: "md"
423
+ };
424
+ var CONTROL_FRAME = [
425
+ "ds:relative ds:flex ds:w-full ds:flex-wrap ds:items-center ds:rounded-input ds:border ds:border-field-border ds:bg-surface ds:font-body ds:text-fg ds:pe-1",
426
+ microInteractions.control,
427
+ "ds:not-data-disabled:hover:border-field-border-hover",
428
+ "ds:focus-within:[border-color:var(--focus-ring-border)] ds:focus-within:[box-shadow:var(--shadow-focus-ring-field)]",
429
+ "ds:data-[invalid]:border-field-border-invalid ds:data-[invalid]:focus-within:border-danger-fg",
430
+ "ds:data-[invalid]:focus-within:[box-shadow:0_0_0_2px_var(--color-danger-bg)]",
431
+ "ds:data-[disabled]:cursor-not-allowed ds:data-[disabled]:bg-bg-disabled ds:data-[disabled]:text-fg-disabled"
432
+ ].join(" ");
433
+ var INPUT_CLASSES = "ds:min-w-16 ds:flex-1 ds:self-stretch ds:bg-transparent ds:py-0 ds:text-inherit ds:outline-none ds:placeholder:text-fg-4 ds:disabled:cursor-not-allowed ds:read-only:cursor-default";
434
+ var LABEL_SIZE = "ds:text-(length:--control-font-size-md)";
435
+ var SMALL_TEXT = "ds:text-(length:--control-font-size-xs)";
436
+ var ITEM_CLASSES = listItemClasses({
437
+ frame: "select",
438
+ labelSize: LABEL_SIZE,
439
+ palette: "neutral",
440
+ highlight: "data-highlighted",
441
+ selected: "aria-selected"
442
+ });
443
+ var CREATE_ITEM_CLASSES = cn(
444
+ ITEM_CLASSES,
445
+ "ds:text-brand ds:data-[highlighted]:bg-brand-bg ds:data-[highlighted]:text-brand"
446
+ );
447
+ var GROUP_HEADING_CLASSES = groupHeadingClasses({ palette: "neutral", labelSize: SMALL_TEXT });
448
+ var STATE_CLASSES = cn("ds:text-fg-3 ds:px-3 ds:py-2", SMALL_TEXT);
449
+ var CREATE_ROW = "\0create";
450
+ var CmdkCompatContext = React6.createContext(false);
451
+ function Combobox(props) {
452
+ const {
453
+ options: items,
454
+ getOptionValue,
455
+ getOptionLabel,
456
+ getOptionDisabled,
457
+ getOptionGroup,
458
+ getOptionKeywords,
459
+ id: idProp,
460
+ name: nameProp,
461
+ form,
462
+ required: requiredProp,
463
+ disabled: disabledProp,
464
+ readOnly: readOnlyProp,
465
+ invalid: invalidProp,
466
+ "aria-label": ariaLabel,
467
+ "aria-labelledby": ariaLabelledBy,
468
+ "aria-describedby": ariaDescribedBy,
469
+ placeholder,
470
+ size = "md",
471
+ icon,
472
+ clearable = true,
473
+ openOnFocus = false,
474
+ avoidCollisions = true,
475
+ open: openProp,
476
+ defaultOpen = false,
477
+ onOpenChange,
478
+ search: searchProp,
479
+ defaultSearch = "",
480
+ onSearchChange,
481
+ shouldFilter = true,
482
+ loading = false,
483
+ emptyState,
484
+ loadingState,
485
+ header,
486
+ footer,
487
+ onCreate,
488
+ renderOption,
489
+ messages: messagesProp,
490
+ className,
491
+ classNames,
492
+ ref
493
+ } = props;
494
+ const multiple = props.multiple === true;
495
+ const closeOnSelect = props.closeOnSelect ?? !multiple;
496
+ const hideSelected = props.multiple === true && props.hideSelected === true;
497
+ const messages = useDsMessages("combobox", messagesProp);
498
+ const accessors = React6.useMemo(() => {
499
+ if (!getOptionValue || !getOptionLabel) return void 0;
500
+ return {
501
+ getOptionValue,
502
+ getOptionLabel,
503
+ getOptionDisabled,
504
+ getOptionGroup,
505
+ getOptionKeywords
506
+ };
507
+ }, [getOptionValue, getOptionLabel, getOptionDisabled, getOptionGroup, getOptionKeywords]);
508
+ const options = React6.useMemo(() => toOptions(items, accessors), [items, accessors]);
509
+ const wiring = useFieldControl({
510
+ id: idProp,
511
+ name: nameProp,
512
+ invalid: invalidProp,
513
+ required: requiredProp,
514
+ disabled: disabledProp,
515
+ readOnly: readOnlyProp,
516
+ "aria-labelledby": ariaLabelledBy,
517
+ "aria-describedby": ariaDescribedBy,
518
+ native: false
519
+ });
520
+ const disabled = wiring.disabled ?? false;
521
+ const readOnly = wiring.readOnly ?? false;
522
+ const inert = disabled || readOnly;
523
+ const listId = useId$1(void 0, `${wiring.id}-list`);
524
+ const toSelection = (raw) => {
525
+ if (raw === void 0) return void 0;
526
+ if (multiple) return normalizeMultipleValue(raw);
527
+ const single = normalizeSingleValue(raw);
528
+ return single === null ? [] : [single];
529
+ };
530
+ const defaultSelection = React6.useMemo(
531
+ () => toSelection(props.defaultValue) ?? [],
532
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- read once, like a default should be
533
+ []
534
+ );
535
+ const [selection, setSelectionState] = useControllableState({
536
+ prop: toSelection(props.value),
537
+ defaultProp: defaultSelection
538
+ });
539
+ const value = multiple ? null : selection[0] ?? null;
540
+ const [openState, setOpenState] = useControllableState({
541
+ prop: openProp,
542
+ defaultProp: defaultOpen,
543
+ onChange: onOpenChange
544
+ });
545
+ const open = openState && !inert;
546
+ const [search, setSearchState] = useControllableState({
547
+ prop: searchProp,
548
+ defaultProp: defaultSearch,
549
+ onChange: onSearchChange
550
+ });
551
+ const selectedOption = React6.useMemo(() => findOption(options, value), [options, value]);
552
+ const selectedOptions = React6.useMemo(
553
+ () => selection.map((entry) => findOption(options, entry)).filter((option) => option !== void 0),
554
+ [options, selection]
555
+ );
556
+ const inputRef = React6.useRef(null);
557
+ const controlRef = React6.useRef(null);
558
+ const mergedInputRef = useMergedRefs(inputRef, ref, wiring.ref);
559
+ const commitSelection = React6.useCallback(
560
+ (next, option) => {
561
+ setSelectionState(next);
562
+ const changed = next.length !== selection.length || next.some((entry, index) => entry !== selection[index]);
563
+ if (!changed) return;
564
+ if (props.multiple === true) props.onValueChange?.(next, { option });
565
+ else props.onValueChange?.(next[0] ?? null, { option });
566
+ },
567
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- `props` is read for the discriminant
568
+ [setSelectionState, selection, props.multiple, props.onValueChange]
569
+ );
570
+ const setValue = React6.useCallback(
571
+ (next) => commitSelection(next === null ? [] : [next], findOption(options, next) ?? null),
572
+ [commitSelection, options]
573
+ );
574
+ const removeValue = React6.useCallback(
575
+ (entry) => commitSelection(
576
+ selection.filter((current) => current !== entry),
577
+ findOption(options, entry) ?? null
578
+ ),
579
+ [commitSelection, selection, options]
580
+ );
581
+ const setOpen = React6.useCallback(
582
+ (next) => {
583
+ if (next && inert) return;
584
+ setOpenState(next);
585
+ if (!next) setSearchState("");
586
+ },
587
+ [inert, setOpenState, setSearchState]
588
+ );
589
+ const trimmed = search.trim();
590
+ const visibleOptions = React6.useMemo(() => {
591
+ const filtered = shouldFilter ? filterOptions(options, search) : options;
592
+ return hideSelected ? filtered.filter((option) => !selection.includes(option.value)) : filtered;
593
+ }, [options, search, shouldFilter, hideSelected, selection]);
594
+ const showCreate = onCreate !== void 0 && trimmed.length > 0 && !options.some((option) => foldForMatch(option.label) === foldForMatch(trimmed));
595
+ const groups = React6.useMemo(() => groupOptions(visibleOptions), [visibleOptions]);
596
+ const hasGroups = groups.some((group) => group.group !== void 0);
597
+ const rows = React6.useMemo(() => {
598
+ const list = groups.flatMap((group) => group.options);
599
+ if (showCreate) list.push({ value: CREATE_ROW, label: messages.create(trimmed) });
600
+ return list;
601
+ }, [groups, showCreate, messages, trimmed]);
602
+ const [highlightedValue, setHighlightedValue] = React6.useState(null);
603
+ const highlightedIndex = indexOfValue(rows, highlightedValue);
604
+ React6.useEffect(() => {
605
+ if (!open) return;
606
+ setHighlightedValue((current) => reconcileHighlight(rows, current, "first"));
607
+ }, [open, rows]);
608
+ const openList = React6.useCallback(() => {
609
+ if (open) return;
610
+ setHighlightedValue(value !== null && findOption(rows, value) ? value : null);
611
+ setOpen(true);
612
+ }, [open, rows, setOpen, value]);
613
+ const scrollHighlightedIntoView = React6.useCallback(() => {
614
+ const id = activeDescendantId(listId, rows, highlightedIndex);
615
+ if (!id) return;
616
+ document.getElementById(id)?.scrollIntoView({ block: "nearest" });
617
+ }, [listId, rows, highlightedIndex]);
618
+ React6.useEffect(() => {
619
+ if (open) scrollHighlightedIntoView();
620
+ }, [open, scrollHighlightedIntoView]);
621
+ const focusInput = () => inputRef.current?.focus();
622
+ const activateRow = React6.useCallback(
623
+ (option) => {
624
+ if (option.disabled) return;
625
+ if (option.value === CREATE_ROW) {
626
+ onCreate?.(trimmed);
627
+ setOpen(false);
628
+ return;
629
+ }
630
+ if (multiple) commitSelection(toggleValue(selection, option.value), option);
631
+ else setValue(clearable && option.value === value ? null : option.value);
632
+ if (closeOnSelect) setOpen(false);
633
+ else setSearchState("");
634
+ },
635
+ [
636
+ onCreate,
637
+ trimmed,
638
+ setOpen,
639
+ multiple,
640
+ commitSelection,
641
+ selection,
642
+ setValue,
643
+ clearable,
644
+ value,
645
+ closeOnSelect,
646
+ setSearchState
647
+ ]
648
+ );
649
+ const clear = () => {
650
+ commitSelection([], null);
651
+ setSearchState("");
652
+ focusInput();
653
+ };
654
+ const onKeyDown = (event) => {
655
+ if (inert) return;
656
+ if (event.key === "Escape") {
657
+ if (!open) return;
658
+ event.preventDefault();
659
+ event.stopPropagation();
660
+ setOpen(false);
661
+ return;
662
+ }
663
+ if (event.key === "Tab") {
664
+ if (open) setOpen(false);
665
+ return;
666
+ }
667
+ if (event.key === "Backspace" && multiple && event.currentTarget.value === "") {
668
+ const last = selection[selection.length - 1];
669
+ if (last !== void 0) {
670
+ event.preventDefault();
671
+ removeValue(last);
672
+ }
673
+ return;
674
+ }
675
+ if (event.key === "Enter") {
676
+ if (!open) return;
677
+ event.preventDefault();
678
+ const row = highlightedIndex === null ? void 0 : rows[highlightedIndex];
679
+ if (row) activateRow(row);
680
+ return;
681
+ }
682
+ if (!open && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
683
+ event.preventDefault();
684
+ openList();
685
+ return;
686
+ }
687
+ if (!open) return;
688
+ const next = nextHighlightedIndex(rows, highlightedIndex, event.key);
689
+ if (next === void 0) return;
690
+ event.preventDefault();
691
+ setHighlightedValue(next === null ? null : rows[next]?.value ?? null);
692
+ };
693
+ const displayValue = open || multiple ? search : selectedOption?.label ?? "";
694
+ const singleRenderValue = props.multiple === true ? void 0 : props.renderValue;
695
+ const showValueNode = !open && !multiple && selectedOption !== void 0 && singleRenderValue !== void 0;
696
+ const chips = props.multiple === true ? props.renderValue ? props.renderValue(selectedOptions, { remove: removeValue }) : selectedOptions.map((option) => /* @__PURE__ */ jsx(
697
+ Chip,
698
+ {
699
+ size: "xs",
700
+ disabled,
701
+ className: classNames?.chip,
702
+ removeLabel: messages.remove(option.label),
703
+ onRemove: readOnly ? void 0 : () => removeValue(option.value),
704
+ children: option.label
705
+ },
706
+ option.value
707
+ )) : null;
708
+ const hasChips = props.multiple === true && selectedOptions.length > 0;
709
+ const cmdkCompat = React6.useContext(CmdkCompatContext);
710
+ const buttonSize = BUTTON_SIZE[size];
711
+ const indexByValue = new Map(rows.map((row, index) => [row.value, index]));
712
+ const renderRow = (option) => {
713
+ const index = indexByValue.get(option.value) ?? -1;
714
+ const highlighted = highlightedIndex === index;
715
+ const selected = selection.includes(option.value);
716
+ const isDisabled = option.disabled === true;
717
+ const attributes = listItemAttributes(comboboxAnatomy, {
718
+ id: optionElementId(listId, option.value),
719
+ highlighted,
720
+ selected,
721
+ disabled: isDisabled,
722
+ cmdkCompat
723
+ });
724
+ return (
725
+ // The row is `role="option"` (in `attributes`), operated from the input
726
+ // through `aria-activedescendant`: it is never a focus stop of its own.
727
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
728
+ /* @__PURE__ */ jsxs(
729
+ "div",
730
+ {
731
+ ...attributes,
732
+ className: cn(ITEM_CLASSES, classNames?.item),
733
+ onPointerMove: () => {
734
+ if (!isDisabled && highlightedValue !== option.value) setHighlightedValue(option.value);
735
+ },
736
+ onMouseDown: (event) => event.preventDefault(),
737
+ onClick: () => activateRow(option),
738
+ children: [
739
+ renderOption ? renderOption(option, { selected, highlighted, disabled: isDisabled }) : /* @__PURE__ */ jsxs(Fragment, { children: [
740
+ option.icon !== void 0 && /* @__PURE__ */ jsx("span", { className: "ds:inline-flex ds:shrink-0", "aria-hidden": "true", children: option.icon }),
741
+ /* @__PURE__ */ jsxs("span", { className: "ds:min-w-0 ds:flex-1", children: [
742
+ /* @__PURE__ */ jsx("span", { className: "ds:block ds:truncate", children: option.label }),
743
+ option.description !== void 0 && /* @__PURE__ */ jsx("span", { className: cn("ds:text-fg-4 ds:block ds:truncate", SMALL_TEXT), children: option.description })
744
+ ] })
745
+ ] }),
746
+ selected && /* @__PURE__ */ jsx(
747
+ "span",
748
+ {
749
+ ...slot(comboboxAnatomy, "item-indicator"),
750
+ className: LIST_ITEM_INDICATOR_WELL.end,
751
+ children: /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": "true" })
752
+ }
753
+ )
754
+ ]
755
+ },
756
+ option.value
757
+ )
758
+ );
759
+ };
760
+ const createIndex = rows.length - 1;
761
+ const createHighlighted = showCreate && highlightedIndex === createIndex;
762
+ return /* @__PURE__ */ jsxs(
763
+ "div",
764
+ {
765
+ ...slot(comboboxAnatomy, "root"),
766
+ ...stateAttributes({
767
+ state: open ? "open" : "closed",
768
+ disabled,
769
+ invalid: wiring["aria-invalid"] === true,
770
+ size
771
+ }),
772
+ className: cn("ds:relative ds:w-full", className, classNames?.root),
773
+ children: [
774
+ /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
775
+ /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs(
776
+ "div",
777
+ {
778
+ ref: controlRef,
779
+ ...slot(comboboxAnatomy, "control"),
780
+ className: cn(CONTROL_FRAME, CONTROL_SIZE[size], classNames?.control),
781
+ onPointerDown: (event) => {
782
+ const target = event.target;
783
+ if (inert || target === inputRef.current || target.closest("button")) return;
784
+ event.preventDefault();
785
+ focusInput();
786
+ openList();
787
+ },
788
+ children: [
789
+ icon !== void 0 && /* @__PURE__ */ jsx(
790
+ "span",
791
+ {
792
+ ...slot(comboboxAnatomy, "icon"),
793
+ className: "ds:text-fg-4 ds:inline-flex ds:shrink-0",
794
+ "aria-hidden": "true",
795
+ children: icon
796
+ }
797
+ ),
798
+ showValueNode && // The custom value takes the input's place in the row; the input
799
+ // keeps the label as its value for assistive technology and
800
+ // collapses to a point until the list opens.
801
+ /* @__PURE__ */ jsx(
802
+ "span",
803
+ {
804
+ ...slot(comboboxAnatomy, "value"),
805
+ className: "ds:pointer-events-none ds:flex ds:min-w-0 ds:flex-1 ds:items-center ds:gap-2 ds:truncate",
806
+ "aria-hidden": "true",
807
+ children: singleRenderValue(selectedOption)
808
+ }
809
+ ),
810
+ hasChips && chips !== null && /* @__PURE__ */ jsx(
811
+ "span",
812
+ {
813
+ ...slot(comboboxAnatomy, "chips"),
814
+ className: "ds:flex ds:min-w-0 ds:flex-wrap ds:items-center ds:gap-1 ds:py-1",
815
+ children: chips
816
+ }
817
+ ),
818
+ /* @__PURE__ */ jsx(
819
+ "input",
820
+ {
821
+ ...slot(comboboxAnatomy, "input"),
822
+ ref: mergedInputRef,
823
+ id: wiring.id,
824
+ type: "text",
825
+ role: "combobox",
826
+ autoComplete: "off",
827
+ spellCheck: false,
828
+ "aria-autocomplete": "list",
829
+ "aria-expanded": open,
830
+ "aria-controls": open ? listId : void 0,
831
+ "aria-activedescendant": open ? activeDescendantId(listId, rows, highlightedIndex) : void 0,
832
+ "aria-label": ariaLabel,
833
+ "aria-labelledby": wiring["aria-labelledby"],
834
+ "aria-describedby": wiring["aria-describedby"],
835
+ "aria-invalid": wiring["aria-invalid"],
836
+ "aria-required": wiring["aria-required"],
837
+ "aria-busy": loading || void 0,
838
+ "data-invalid": wiring["data-invalid"],
839
+ "data-disabled": wiring["data-disabled"],
840
+ disabled,
841
+ readOnly,
842
+ placeholder: selectedOption || hasChips ? void 0 : placeholder,
843
+ value: displayValue,
844
+ className: cn(
845
+ INPUT_CLASSES,
846
+ showValueNode && "ds:absolute ds:size-px ds:min-w-0 ds:flex-none ds:opacity-0",
847
+ classNames?.input
848
+ ),
849
+ onChange: (event) => {
850
+ if (inert) return;
851
+ setSearchState(event.target.value);
852
+ if (!open) openList();
853
+ },
854
+ onFocus: () => {
855
+ if (openOnFocus) openList();
856
+ },
857
+ onClick: () => openList(),
858
+ onKeyDown
859
+ }
860
+ ),
861
+ loading && /* @__PURE__ */ jsx(Spinner, { size: "xs", intent: "neutral", "aria-hidden": "true" }),
862
+ clearable && selection.length > 0 && !inert && /* @__PURE__ */ jsx(
863
+ IconButton,
864
+ {
865
+ ...slot(comboboxAnatomy, "clear"),
866
+ label: messages.clear,
867
+ tooltip: false,
868
+ variant: "ghost",
869
+ intent: "neutral",
870
+ size: buttonSize,
871
+ icon: /* @__PURE__ */ jsx(XIcon, {}),
872
+ onClick: clear
873
+ }
874
+ ),
875
+ /* @__PURE__ */ jsx(
876
+ IconButton,
877
+ {
878
+ ...slot(comboboxAnatomy, "toggle"),
879
+ label: messages.toggle,
880
+ tooltip: false,
881
+ variant: "ghost",
882
+ intent: "neutral",
883
+ size: buttonSize,
884
+ tabIndex: -1,
885
+ "aria-expanded": open,
886
+ "aria-controls": open ? listId : void 0,
887
+ disabled: inert,
888
+ icon: /* @__PURE__ */ jsx(
889
+ ChevronDownIcon,
890
+ {
891
+ className: cn(
892
+ "ds:transition-transform ds:duration-[var(--motion-duration-feedback)] ds:motion-reduce:transition-none",
893
+ open && "ds:rotate-180"
894
+ )
895
+ }
896
+ ),
897
+ onMouseDown: (event) => event.preventDefault(),
898
+ onClick: () => {
899
+ focusInput();
900
+ if (open) setOpen(false);
901
+ else openList();
902
+ }
903
+ }
904
+ )
905
+ ]
906
+ }
907
+ ) }),
908
+ /* @__PURE__ */ jsx(
909
+ PopoverContent,
910
+ {
911
+ ...slot(comboboxAnatomy, "content"),
912
+ role: "presentation",
913
+ align: "start",
914
+ sideOffset: 4,
915
+ avoidCollisions,
916
+ onOpenAutoFocus: (event) => event.preventDefault(),
917
+ onCloseAutoFocus: (event) => event.preventDefault(),
918
+ onInteractOutside: (event) => {
919
+ if (controlRef.current?.contains(event.target)) event.preventDefault();
920
+ },
921
+ style: {
922
+ width: "var(--radix-popover-trigger-width)",
923
+ maxHeight: "var(--radix-popover-content-available-height)"
924
+ },
925
+ className: cn(
926
+ "ds:flex ds:min-w-48 ds:flex-col ds:overflow-hidden ds:p-0",
927
+ classNames?.content
928
+ ),
929
+ children: /* @__PURE__ */ jsxs(NestedScrollLock, { children: [
930
+ header !== void 0 && /* @__PURE__ */ jsx(
931
+ "div",
932
+ {
933
+ ...slot(comboboxAnatomy, "header"),
934
+ className: "ds:border-rule ds:shrink-0 ds:border-b",
935
+ children: header
936
+ }
937
+ ),
938
+ /* @__PURE__ */ jsxs(
939
+ "div",
940
+ {
941
+ ...slot(comboboxAnatomy, "list"),
942
+ id: listId,
943
+ role: "listbox",
944
+ "aria-multiselectable": multiple || void 0,
945
+ "aria-labelledby": wiring["aria-labelledby"],
946
+ "aria-label": wiring["aria-labelledby"] ? void 0 : ariaLabel,
947
+ className: cn(
948
+ "ds:scrollbar-thin ds:min-h-0 ds:flex-1 ds:max-h-[min(20rem,60vh)] ds:overflow-y-auto ds:p-1",
949
+ classNames?.list
950
+ ),
951
+ children: [
952
+ hasGroups ? groups.map((group, groupIndex) => {
953
+ const headingId = group.group === void 0 ? void 0 : `${listId}-group-${groupIndex}`;
954
+ return /* @__PURE__ */ jsxs(
955
+ "div",
956
+ {
957
+ ...slot(comboboxAnatomy, "group"),
958
+ role: "group",
959
+ "aria-labelledby": headingId,
960
+ children: [
961
+ group.group !== void 0 && /* @__PURE__ */ jsx(
962
+ "div",
963
+ {
964
+ ...slot(comboboxAnatomy, "group-heading"),
965
+ id: headingId,
966
+ role: "presentation",
967
+ className: GROUP_HEADING_CLASSES,
968
+ children: group.group
969
+ }
970
+ ),
971
+ group.options.map(renderRow)
972
+ ]
973
+ },
974
+ group.group ?? `ungrouped-${groupIndex}`
975
+ );
976
+ }) : visibleOptions.map(renderRow),
977
+ showCreate && /* @__PURE__ */ jsxs(Fragment, { children: [
978
+ visibleOptions.length > 0 && /* @__PURE__ */ jsx("div", { className: LIST_SEPARATOR.neutral, role: "presentation" }),
979
+ /* @__PURE__ */ jsxs(
980
+ "div",
981
+ {
982
+ ...listItemAttributes(comboboxAnatomy, {
983
+ id: optionElementId(listId, CREATE_ROW),
984
+ highlighted: createHighlighted,
985
+ selected: false,
986
+ cmdkCompat
987
+ }),
988
+ ...slot(comboboxAnatomy, "create"),
989
+ className: CREATE_ITEM_CLASSES,
990
+ onPointerMove: () => {
991
+ if (highlightedValue !== CREATE_ROW)
992
+ setHighlightedValue(CREATE_ROW);
993
+ },
994
+ onMouseDown: (event) => event.preventDefault(),
995
+ onClick: () => {
996
+ const row = rows[createIndex];
997
+ if (row) activateRow(row);
998
+ },
999
+ children: [
1000
+ /* @__PURE__ */ jsx(PlusIcon, { "aria-hidden": "true" }),
1001
+ /* @__PURE__ */ jsx("span", { className: "ds:min-w-0 ds:flex-1 ds:truncate", children: messages.create(trimmed) })
1002
+ ]
1003
+ }
1004
+ )
1005
+ ] })
1006
+ ]
1007
+ }
1008
+ ),
1009
+ loading && /* @__PURE__ */ jsx("div", { ...slot(comboboxAnatomy, "loading"), role: "status", className: STATE_CLASSES, children: loadingState ?? messages.loading }),
1010
+ !loading && rows.length === 0 && /* @__PURE__ */ jsx("div", { ...slot(comboboxAnatomy, "empty"), role: "status", className: STATE_CLASSES, children: emptyState ?? messages.empty }),
1011
+ footer !== void 0 && /* @__PURE__ */ jsx(
1012
+ "div",
1013
+ {
1014
+ ...slot(comboboxAnatomy, "footer"),
1015
+ className: "ds:border-rule ds:shrink-0 ds:border-t",
1016
+ children: footer
1017
+ }
1018
+ )
1019
+ ] })
1020
+ }
1021
+ )
1022
+ ] }),
1023
+ /* @__PURE__ */ jsx(
1024
+ FormBridge,
1025
+ {
1026
+ name: wiring.name,
1027
+ value: multiple ? selection : value,
1028
+ form,
1029
+ disabled,
1030
+ required: wiring["aria-required"] === true,
1031
+ focusTarget: inputRef,
1032
+ onReset: () => commitSelection(defaultSelection, null)
1033
+ }
1034
+ )
1035
+ ]
1036
+ }
1037
+ );
1038
+ }
1039
+ Combobox.displayName = "Combobox";
1040
+ function ClientSelect({
1041
+ clients,
1042
+ value,
1043
+ onChange,
1044
+ name = "client_id",
1045
+ error,
1046
+ className,
1047
+ placeholder = "Select a client..."
1048
+ }) {
1049
+ const options = React6.useMemo(
1050
+ () => clients.map((client) => ({
1051
+ value: client.id,
1052
+ label: client.label,
1053
+ keywords: client.email ? [client.email] : void 0,
1054
+ meta: client
1055
+ })),
1056
+ [clients]
1057
+ );
1058
+ return /* @__PURE__ */ jsxs("div", { className: cn("ds:relative ds:w-full", className), children: [
1059
+ /* @__PURE__ */ jsx(
1060
+ Combobox,
1061
+ {
1062
+ options,
1063
+ name,
1064
+ value,
1065
+ onValueChange: (next) => onChange(next),
1066
+ "aria-label": placeholder,
1067
+ placeholder,
1068
+ invalid: Boolean(error),
1069
+ messages: clients.length === 0 ? { empty: "No clients yet" } : void 0,
1070
+ renderValue: (option) => option.label,
1071
+ renderOption: (option) => {
1072
+ const email = option.meta?.email;
1073
+ return /* @__PURE__ */ jsxs("span", { className: "ds:flex ds:min-w-0 ds:flex-col", children: [
1074
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:line-clamp-1 ds:text-[13px] ds:font-medium", children: option.label }),
1075
+ email && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:line-clamp-1 ds:text-xs", children: email })
1076
+ ] });
1077
+ }
1078
+ }
1079
+ ),
1080
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "ds:text-danger-fg ds:mt-1.5 ds:text-xs", children: error })
1081
+ ] });
1082
+ }
1083
+ ClientSelect.displayName = "ClientSelect";
1084
+ var Collapsible = React6.forwardRef(function Collapsible2({ className, ...props }, ref) {
1085
+ return /* @__PURE__ */ jsx(CollapsiblePrimitive.Root, { ref, className: cn(className), ...props });
1086
+ });
1087
+ Collapsible.displayName = CollapsiblePrimitive.Root.displayName;
1088
+ var CollapsibleTrigger = React6.forwardRef(function CollapsibleTrigger2({ className, ...props }, ref) {
1089
+ return /* @__PURE__ */ jsx(
1090
+ CollapsiblePrimitive.Trigger,
1091
+ {
1092
+ ref,
1093
+ className: cn(
1094
+ "ds:flex ds:w-full ds:items-center",
1095
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
1096
+ className
1097
+ ),
1098
+ ...props
1099
+ }
1100
+ );
1101
+ });
1102
+ CollapsibleTrigger.displayName = CollapsiblePrimitive.Trigger.displayName;
1103
+ var CollapsibleContent = React6.forwardRef(function CollapsibleContent2({ className, ...props }, ref) {
1104
+ return /* @__PURE__ */ jsx(
1105
+ CollapsiblePrimitive.Content,
1106
+ {
1107
+ ref,
1108
+ className: cn(
1109
+ "ds:overflow-hidden",
1110
+ "ds:data-[state=closed]:animate-[collapsible-up_var(--duration-overlay)_var(--ease-out-quart)]",
1111
+ "ds:data-[state=open]:animate-[collapsible-down_var(--duration-overlay)_var(--ease-out-quart)]",
1112
+ "ds:motion-reduce:animate-none",
1113
+ className
1114
+ ),
1115
+ ...props
1116
+ }
1117
+ );
1118
+ });
1119
+ CollapsibleContent.displayName = CollapsiblePrimitive.Content.displayName;
1120
+ var ComingSoon = forwardRef(function ComingSoon2({ icon, title, description, features, className, messages: messagesProp, ...props }, ref) {
1121
+ const messages = useDsMessages("comingSoon", messagesProp);
1122
+ return /* @__PURE__ */ jsx(
1123
+ "div",
1124
+ {
1125
+ ref,
1126
+ className: cn("ds:flex ds:items-center ds:justify-center ds:px-6 ds:py-16", className),
1127
+ ...props,
1128
+ children: /* @__PURE__ */ jsxs(
1129
+ "div",
1130
+ {
1131
+ className: cn(
1132
+ "ds:rounded-card ds:border-rule-strong ds:w-full ds:max-w-lg ds:border ds:border-dashed",
1133
+ "ds:bg-surface ds:shadow-quiet ds:p-10 ds:text-center"
1134
+ ),
1135
+ children: [
1136
+ /* @__PURE__ */ jsx("div", { className: "ds:text-brand ds:mb-5 ds:font-mono ds:text-[11px] ds:font-normal ds:tracking-[0.14em] ds:uppercase", children: messages.eyebrow }),
1137
+ /* @__PURE__ */ jsx(
1138
+ "div",
1139
+ {
1140
+ className: cn(
1141
+ "ds:mx-auto ds:mb-4 ds:flex ds:size-12 ds:items-center ds:justify-center",
1142
+ "ds:rounded-icon ds:bg-brand-bg ds:text-brand ds:[&>svg]:size-6"
1143
+ ),
1144
+ children: icon
1145
+ }
1146
+ ),
1147
+ /* @__PURE__ */ jsx("h1", { className: "ds:font-display ds:text-fg ds:text-xl ds:font-medium ds:tracking-[-0.022em]", children: title }),
1148
+ /* @__PURE__ */ jsx("p", { className: "ds:text-fg-3 ds:mt-1.5 ds:text-sm", children: description }),
1149
+ /* @__PURE__ */ jsx("ul", { className: "ds:mt-6 ds:space-y-2 ds:text-left", children: features.map((feature) => /* @__PURE__ */ jsxs("li", { className: "ds:text-fg-2 ds:flex ds:items-center ds:gap-2 ds:text-sm", children: [
1150
+ /* @__PURE__ */ jsx(
1151
+ CheckIcon,
1152
+ {
1153
+ className: "ds:text-success-fg ds:size-3.5 ds:shrink-0",
1154
+ strokeWidth: 2.5,
1155
+ "aria-hidden": "true"
1156
+ }
1157
+ ),
1158
+ feature
1159
+ ] }, feature)) }),
1160
+ /* @__PURE__ */ jsx("div", { className: "ds:mt-6", children: /* @__PURE__ */ jsx(
1161
+ "span",
1162
+ {
1163
+ className: cn(
1164
+ "ds:rounded-pill ds:inline-flex ds:items-center ds:border ds:px-2.5 ds:py-0.5",
1165
+ "ds:text-xs ds:font-medium",
1166
+ "ds:bg-brand-bg ds:text-brand ds:border-[color:var(--color-brand-bg-active)]"
1167
+ ),
1168
+ children: messages.badge
1169
+ }
1170
+ ) })
1171
+ ]
1172
+ }
1173
+ )
1174
+ }
1175
+ );
1176
+ });
1177
+ ComingSoon.displayName = "ComingSoon";
1178
+
1179
+ // src/lib/asset-base.ts
1180
+ var basePath = "/";
1181
+ function setAssetBasePath(base) {
1182
+ const trimmed = (base ?? "").replace(/\/+$/, "");
1183
+ basePath = trimmed === "" ? "/" : `${trimmed.startsWith("/") ? "" : "/"}${trimmed}/`;
1184
+ }
1185
+ function getAssetBasePath() {
1186
+ return basePath;
1187
+ }
1188
+ function assetPath(path) {
1189
+ return `${basePath}${path.replace(/^\/+/, "")}`;
1190
+ }
1191
+ function PlainLink({ ref, children, ...props }) {
1192
+ return /* @__PURE__ */ jsx("a", { ref, ...props, children });
1193
+ }
1194
+ function PlainImage({ priority, alt, ...props }) {
1195
+ return /* @__PURE__ */ jsx(
1196
+ "img",
1197
+ {
1198
+ alt,
1199
+ ...priority ? { loading: "eager", fetchPriority: "high" } : {},
1200
+ ...props
1201
+ }
1202
+ );
1203
+ }
1204
+ var sizeStyles = {
1205
+ sm: { icon: 20, text: "ds:text-sm", gap: "ds:gap-2", assetHeight: 24 },
1206
+ md: { icon: 24, text: "ds:text-[17px]", gap: "ds:gap-2.5", assetHeight: 30 },
1207
+ lg: { icon: 32, text: "ds:text-xl", gap: "ds:gap-3", assetHeight: 40 },
1208
+ xl: { icon: 40, text: "ds:text-2xl", gap: "ds:gap-3.5", assetHeight: 48 }
1209
+ };
1210
+ var productLogoAssets = {
1211
+ Pro: { src: "/brand/assure-pro.svg", width: 384, height: 90 },
1212
+ Audit: { src: "/brand/assure-audit.svg", width: 441, height: 90 },
1213
+ Books: { src: "/brand/assure-books.svg", width: 470, height: 90 },
1214
+ Tax: { src: "/brand/assure-tax.svg", width: 374, height: 90 },
1215
+ Teams: { src: "/brand/mycpe-teams.svg", width: 221, height: 49 }
1216
+ };
1217
+ var productMarkAssets = {
1218
+ Pro: { src: "/brand/assure-pro-mark.svg", width: 55, height: 48 },
1219
+ Audit: { src: "/brand/assure-audit-mark.svg", width: 55, height: 48 },
1220
+ Books: { src: "/brand/assure-books-mark.svg", width: 55, height: 48 },
1221
+ Tax: { src: "/brand/assure-tax-mark.svg", width: 55, height: 48 },
1222
+ Teams: { src: "/brand/mycpe-teams-mark.svg", width: 26, height: 31 }
1223
+ };
1224
+ var productGlyphs = {
1225
+ Pro: AssureProBrandIcon,
1226
+ Audit: AssureAuditBrandIcon,
1227
+ Books: AssureBooksBrandIcon,
1228
+ Tax: AssureTaxBrandIcon
1229
+ };
1230
+ var standaloneBrands = {
1231
+ Teams: "myCPE Teams"
1232
+ };
1233
+ function Logo({
1234
+ size = "md",
1235
+ href = "/",
1236
+ showText = true,
1237
+ className,
1238
+ iconClassName,
1239
+ textClassName,
1240
+ productName = "Pro",
1241
+ inverted = false
1242
+ }) {
1243
+ const RouterLink = useLinkComponent() ?? PlainLink;
1244
+ const Img = useImageComponent() ?? PlainImage;
1245
+ const [artworkFailed, setArtworkFailed] = React6.useState(false);
1246
+ const s = sizeStyles[size];
1247
+ const standaloneLabel = productName ? standaloneBrands[productName] : void 0;
1248
+ const isStandalone = Boolean(standaloneLabel);
1249
+ const ariaLabel = standaloneLabel ?? (productName ? `Assure ${productName}` : "Assure");
1250
+ const asset = productName ? productLogoAssets[productName] : void 0;
1251
+ const markAsset = productName ? productMarkAssets[productName] : void 0;
1252
+ const Glyph = productName ? productGlyphs[productName] : void 0;
1253
+ const wordmark = artworkFailed || !showText ? void 0 : asset;
1254
+ const mark = artworkFailed || wordmark ? void 0 : markAsset;
1255
+ const wrapperClassName = cn("ds:inline-flex ds:items-center", s.gap, className);
1256
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1257
+ wordmark ? /* @__PURE__ */ jsx(
1258
+ Img,
1259
+ {
1260
+ src: assetPath(wordmark.src),
1261
+ alt: "",
1262
+ width: wordmark.width,
1263
+ height: wordmark.height,
1264
+ priority: true,
1265
+ onError: () => setArtworkFailed(true),
1266
+ className: cn(
1267
+ "ds:h-auto ds:flex-shrink-0",
1268
+ inverted && "ds:brightness-0 ds:invert",
1269
+ iconClassName
1270
+ ),
1271
+ style: { width: Math.round(wordmark.width / wordmark.height * s.assetHeight) }
1272
+ }
1273
+ ) : mark ? /* @__PURE__ */ jsx(
1274
+ Img,
1275
+ {
1276
+ src: assetPath(mark.src),
1277
+ alt: "",
1278
+ width: mark.width,
1279
+ height: mark.height,
1280
+ priority: true,
1281
+ onError: () => setArtworkFailed(true),
1282
+ className: cn(
1283
+ "ds:h-auto ds:flex-shrink-0",
1284
+ inverted && "ds:brightness-0 ds:invert",
1285
+ iconClassName
1286
+ ),
1287
+ style: { width: Math.round(mark.width / mark.height * s.icon) }
1288
+ }
1289
+ ) : /* @__PURE__ */ jsx(Fragment, { children: Glyph ? /* @__PURE__ */ jsx(Glyph, { size: s.icon, "aria-hidden": "true", className: iconClassName }) : /* @__PURE__ */ jsx(
1290
+ "span",
1291
+ {
1292
+ "aria-hidden": "true",
1293
+ className: cn(
1294
+ "ds:bg-pro-fg ds:grid ds:shrink-0 ds:place-items-center ds:rounded-[5px] ds:text-[10px] ds:font-bold ds:text-white",
1295
+ iconClassName
1296
+ ),
1297
+ style: { width: s.icon, height: s.icon },
1298
+ children: "A"
1299
+ }
1300
+ ) }),
1301
+ showText && /* @__PURE__ */ jsx(
1302
+ "span",
1303
+ {
1304
+ className: cn(
1305
+ "ds:font-display ds:font-semibold ds:tracking-[-0.025em]",
1306
+ s.text,
1307
+ inverted ? "ds:text-white" : "ds:text-fg",
1308
+ wordmark && "ds:sr-only",
1309
+ textClassName
1310
+ ),
1311
+ children: isStandalone ? /* @__PURE__ */ jsx("span", { children: standaloneLabel }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1312
+ /* @__PURE__ */ jsx("span", { children: "Assure" }),
1313
+ productName && /* @__PURE__ */ jsxs(Fragment, { children: [
1314
+ " ",
1315
+ /* @__PURE__ */ jsx(
1316
+ "span",
1317
+ {
1318
+ className: cn(
1319
+ "ds:font-medium",
1320
+ inverted ? "ds:text-[#d8cfff]" : "ds:text-pro-fg"
1321
+ ),
1322
+ children: productName
1323
+ }
1324
+ )
1325
+ ] })
1326
+ ] })
1327
+ }
1328
+ )
1329
+ ] });
1330
+ if (href === null) {
1331
+ return /* @__PURE__ */ jsx("span", { className: wrapperClassName, children: content });
1332
+ }
1333
+ return /* @__PURE__ */ jsx(RouterLink, { href, className: wrapperClassName, "aria-label": ariaLabel, children: content });
1334
+ }
1335
+ var SheetSideContext = React6.createContext({});
1336
+ var Sheet = ({ side, children, ...props }) => /* @__PURE__ */ jsx(SheetPrimitive.Root, { ...props, children: /* @__PURE__ */ jsx(SheetSideContext, { value: { side }, children }) });
1337
+ Sheet.displayName = "Sheet";
1338
+ var SheetTrigger = SheetPrimitive.Trigger;
1339
+ var SheetClose = SheetPrimitive.Close;
1340
+ var SheetPortal = withPortalContainer(SheetPrimitive.Portal);
1341
+ var SheetOverlay = React6.forwardRef((props, ref) => /* @__PURE__ */ jsx(
1342
+ Backdrop,
1343
+ {
1344
+ as: SheetPrimitive.Overlay,
1345
+ anatomy: sheetAnatomy,
1346
+ motion: "legacy",
1347
+ ref,
1348
+ ...props
1349
+ }
1350
+ ));
1351
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
1352
+ var SHEET_SIZES = {
1353
+ sm: "ds:w-[95vw] ds:max-w-[95vw] ds:sm:w-[var(--ds-sheet-width,420px)]",
1354
+ md: "ds:w-[95vw] ds:max-w-[95vw] ds:sm:w-[var(--ds-sheet-width,520px)]",
1355
+ lg: "ds:w-[95vw] ds:max-w-[95vw] ds:sm:w-[var(--ds-sheet-width,640px)]",
1356
+ xl: "ds:w-[95vw] ds:max-w-[95vw] ds:sm:w-[var(--ds-sheet-width,760px)]",
1357
+ full: "ds:w-full ds:max-w-none"
1358
+ };
1359
+ var SheetContent = React6.forwardRef(
1360
+ ({
1361
+ side,
1362
+ size,
1363
+ width,
1364
+ customWidth,
1365
+ className,
1366
+ children,
1367
+ showCloseButton = true,
1368
+ closeLabel,
1369
+ messages,
1370
+ style,
1371
+ ...props
1372
+ }, ref) => {
1373
+ const ctx = React6.use(SheetSideContext);
1374
+ const resolvedSide = side ?? ctx.side ?? "right";
1375
+ const supportsWidth = resolvedSide === "left" || resolvedSide === "right";
1376
+ if (width !== void 0) {
1377
+ deprecate(
1378
+ "C-SHEET-WIDTH",
1379
+ "width",
1380
+ "SheetContent `width` is deprecated; pass `size` (the same steps) instead."
1381
+ );
1382
+ }
1383
+ if (customWidth !== void 0) {
1384
+ deprecate(
1385
+ "C-SHEET-WIDTH",
1386
+ "customWidth",
1387
+ "SheetContent `customWidth` is deprecated; set the `--ds-sheet-width` custom property instead."
1388
+ );
1389
+ }
1390
+ const resolvedSize = size ?? (width === void 0 || width === "default" ? void 0 : width);
1391
+ const sizeRow = supportsWidth && resolvedSize ? SHEET_SIZES[resolvedSize] : null;
1392
+ const widthStyle = supportsWidth && customWidth ? { width: customWidth, maxWidth: "95vw", ...style } : style;
1393
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
1394
+ /* @__PURE__ */ jsx(SheetOverlay, {}),
1395
+ /* @__PURE__ */ jsxs(
1396
+ OverlaySurface,
1397
+ {
1398
+ as: SheetPrimitive.Content,
1399
+ anatomy: sheetAnatomy,
1400
+ placement: resolvedSide,
1401
+ motion: "legacy",
1402
+ ref,
1403
+ ...stateAttributes({ size: resolvedSize ?? "default" }),
1404
+ rows: [sizeRow],
1405
+ className,
1406
+ style: widthStyle,
1407
+ ...props,
1408
+ children: [
1409
+ children,
1410
+ showCloseButton && /* @__PURE__ */ jsx(
1411
+ DismissButton,
1412
+ {
1413
+ as: SheetPrimitive.Close,
1414
+ anatomy: sheetAnatomy,
1415
+ label: closeLabel ?? messages?.close ?? DEFAULT_OVERLAY_MESSAGES.close,
1416
+ children: /* @__PURE__ */ jsx(XIcon, { className: DISMISS_GLYPH_CLASSES, "aria-hidden": "true" })
1417
+ }
1418
+ )
1419
+ ]
1420
+ }
1421
+ )
1422
+ ] });
1423
+ }
1424
+ );
1425
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
1426
+ var SheetHeader = (props) => /* @__PURE__ */ jsx(OverlayHeader, { anatomy: sheetAnatomy, layout: "padded", dismissGutter: true, ...props });
1427
+ SheetHeader.displayName = "SheetHeader";
1428
+ var SheetBody = React6.forwardRef(
1429
+ ({ padding = "md", ...props }, ref) => /* @__PURE__ */ jsx(OverlayBody, { anatomy: sheetAnatomy, layout: "padded", padding, ref, ...props })
1430
+ );
1431
+ SheetBody.displayName = "SheetBody";
1432
+ var SheetFooter = (props) => /* @__PURE__ */ jsx(OverlayFooter, { anatomy: sheetAnatomy, layout: "padded", ...props });
1433
+ SheetFooter.displayName = "SheetFooter";
1434
+ var SheetTitle = React6.forwardRef((props, ref) => /* @__PURE__ */ jsx(OverlayTitle, { as: SheetPrimitive.Title, anatomy: sheetAnatomy, ref, ...props }));
1435
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
1436
+ var SheetDescription = React6.forwardRef((props, ref) => /* @__PURE__ */ jsx(OverlayDescription, { as: SheetPrimitive.Description, anatomy: sheetAnatomy, ref, ...props }));
1437
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
1438
+ var ICON_BTN = cn(
1439
+ "ds:inline-flex ds:size-9 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-[9px]",
1440
+ "ds:border-rule-strong ds:bg-surface ds:text-fg-3 ds:border",
1441
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1442
+ "ds:hover:bg-surface-hover ds:hover:text-fg",
1443
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none"
1444
+ );
1445
+ var MIN_ACCENT_CONTRAST = 4.5;
1446
+ function legibleAccent(accent) {
1447
+ const rgb = parseHexColor(accent);
1448
+ if (!rgb || contrastRatio(rgb, WHITE) >= MIN_ACCENT_CONTRAST) return accent;
1449
+ return formatHexColor(darkenUntilContrast(rgb, WHITE, MIN_ACCENT_CONTRAST));
1450
+ }
1451
+ var AgreementViewer = forwardRef(
1452
+ function AgreementViewer2({
1453
+ title,
1454
+ overline = "Signed agreement",
1455
+ steps,
1456
+ firm,
1457
+ status = "signed",
1458
+ banner,
1459
+ accent,
1460
+ coverRail = true,
1461
+ step,
1462
+ defaultStep = 0,
1463
+ onStepChange,
1464
+ onDownload,
1465
+ onClose,
1466
+ headerActions,
1467
+ nextDisabled = false,
1468
+ nextDisabledReason,
1469
+ footer,
1470
+ className
1471
+ }, ref) {
1472
+ const reasonId = useId();
1473
+ const [internalStep, setInternalStep] = useState(defaultStep);
1474
+ const current = step ?? internalStep;
1475
+ const isControlled = step !== void 0;
1476
+ const lastIndex = steps.length - 1;
1477
+ const goTo = (n) => {
1478
+ if (n < 0 || n > lastIndex || n === current) return;
1479
+ if (!isControlled) setInternalStep(n);
1480
+ onStepChange?.(n);
1481
+ };
1482
+ const isCover = current === 0;
1483
+ const monogram = firm.initials ?? firm.name.charAt(0);
1484
+ const bannerContent = banner === void 0 ? status === "signed" ? "Showing the services your client accepted, at the prices locked in at signing." : "Review each section at your pace, then sign whenever you're ready." : banner;
1485
+ return /* @__PURE__ */ jsxs(
1486
+ "div",
1487
+ {
1488
+ ref,
1489
+ "data-slot": "agreement-viewer",
1490
+ "data-status": status,
1491
+ "data-view": isCover ? "cover" : "inner",
1492
+ style: accent ? { "--av-accent": legibleAccent(accent) } : void 0,
1493
+ className: cn(
1494
+ // Fills its container's height so the content pane scrolls internally
1495
+ // while the header, rail, and footer stay fixed — give the parent a
1496
+ // height (e.g. h-screen / a fixed card height). Falls back to a 600px
1497
+ // floor so it never collapses when dropped in an unsized container.
1498
+ // Responsive via CONTAINER queries (@container/agreement), not viewport:
1499
+ // the side rails + generous padding only appear when the viewer's own
1500
+ // container is wide (≥64rem). In a phone frame or a narrow panel it
1501
+ // collapses to the single-column compact layout regardless of the
1502
+ // browser viewport.
1503
+ "ds:group/agreement ds:@container/agreement ds:bg-bg ds:text-fg ds:flex ds:h-full ds:min-h-[600px] ds:flex-col ds:font-sans",
1504
+ className
1505
+ ),
1506
+ children: [
1507
+ /* @__PURE__ */ jsxs("header", { className: "ds:flex ds:items-center ds:gap-2.5 ds:px-4 ds:pt-4 ds:pb-3 ds:@5xl/agreement:gap-3.5 ds:@5xl/agreement:px-7", children: [
1508
+ /* @__PURE__ */ jsx(
1509
+ "span",
1510
+ {
1511
+ "aria-hidden": "true",
1512
+ className: "ds:rounded-icon ds:flex ds:size-9 ds:shrink-0 ds:items-center ds:justify-center ds:bg-[var(--av-accent-tint)] ds:text-[var(--av-accent)]",
1513
+ children: /* @__PURE__ */ jsx(EyeIcon, { className: "ds:size-4.5" })
1514
+ }
1515
+ ),
1516
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:min-w-0 ds:flex-col", children: [
1517
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:text-[11.5px] ds:leading-tight ds:font-semibold", children: overline }),
1518
+ /* @__PURE__ */ jsx("span", { className: "ds:font-display ds:text-fg ds:truncate ds:text-[17px] ds:leading-tight ds:font-semibold ds:tracking-tight", children: title })
1519
+ ] }),
1520
+ /* @__PURE__ */ jsxs("div", { className: "ds:ml-auto ds:flex ds:items-center ds:gap-2", children: [
1521
+ !isCover && /* @__PURE__ */ jsxs("span", { className: "ds:border-rule ds:bg-bg-2 ds:text-fg-2 ds:shrink-0 ds:rounded-md ds:border ds:px-2.5 ds:py-1 ds:text-xs ds:font-semibold ds:whitespace-nowrap", children: [
1522
+ "Step ",
1523
+ current + 1,
1524
+ " of ",
1525
+ steps.length
1526
+ ] }),
1527
+ headerActions,
1528
+ onDownload && /* @__PURE__ */ jsxs(
1529
+ "button",
1530
+ {
1531
+ type: "button",
1532
+ onClick: onDownload,
1533
+ "aria-label": "Download PDF",
1534
+ className: cn(
1535
+ "ds:inline-flex ds:h-9 ds:shrink-0 ds:items-center ds:gap-1.5 ds:rounded-[9px] ds:px-2.5 ds:text-[13px] ds:font-medium ds:whitespace-nowrap ds:@5xl/agreement:px-3.5",
1536
+ "ds:border-rule-strong ds:bg-surface ds:text-fg ds:border",
1537
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1538
+ "ds:hover:bg-surface-hover",
1539
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none"
1540
+ ),
1541
+ children: [
1542
+ /* @__PURE__ */ jsx(DownloadIcon, { className: "ds:size-4", "aria-hidden": "true" }),
1543
+ /* @__PURE__ */ jsx("span", { className: "ds:hidden ds:@5xl/agreement:inline", children: "Download PDF" })
1544
+ ]
1545
+ }
1546
+ ),
1547
+ onClose && /* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, "aria-label": "Close", className: ICON_BTN, children: /* @__PURE__ */ jsx(XIcon, { className: "ds:size-4", "aria-hidden": "true" }) })
1548
+ ] })
1549
+ ] }),
1550
+ bannerContent != null && /* @__PURE__ */ jsxs(
1551
+ "div",
1552
+ {
1553
+ className: cn(
1554
+ "ds:mx-4 ds:flex ds:items-center ds:gap-2.5 ds:rounded-[11px] ds:border ds:px-4 ds:py-2.5 ds:text-[13.5px] ds:font-medium ds:@5xl/agreement:mx-7",
1555
+ status === "signed" ? "ds:border-success-line ds:bg-success-bg ds:text-success-fg" : "ds:border-[var(--av-accent-tint2)] ds:bg-[var(--av-accent-tint)] ds:text-[var(--av-accent-soft)]"
1556
+ ),
1557
+ children: [
1558
+ /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-4 ds:shrink-0", "aria-hidden": "true" }),
1559
+ /* @__PURE__ */ jsx("span", { children: bannerContent })
1560
+ ]
1561
+ }
1562
+ ),
1563
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:min-h-0 ds:flex-1 ds:flex-col ds:px-4 ds:pt-3 ds:pb-5 ds:@5xl/agreement:px-7 ds:@5xl/agreement:pb-8", children: [
1564
+ /* @__PURE__ */ jsxs("div", { className: "ds:border-rule ds:bg-surface ds:shadow-card ds:flex ds:min-h-0 ds:flex-1 ds:overflow-hidden ds:rounded-[18px] ds:border", children: [
1565
+ coverRail && /* @__PURE__ */ jsxs(
1566
+ "aside",
1567
+ {
1568
+ className: "ds:hidden ds:w-[340px] ds:shrink-0 ds:flex-col ds:overflow-y-auto ds:p-8 ds:text-white ds:@5xl/agreement:group-data-[view=cover]/agreement:flex",
1569
+ style: {
1570
+ backgroundImage: "linear-gradient(166deg, var(--av-accent-light) 0%, var(--av-accent) 50%, var(--av-accent-deep) 100%)"
1571
+ },
1572
+ children: [
1573
+ /* @__PURE__ */ jsx(
1574
+ "span",
1575
+ {
1576
+ "aria-hidden": "true",
1577
+ className: "ds:rounded-card ds:flex ds:size-[54px] ds:items-center ds:justify-center ds:bg-white ds:text-[17px] ds:font-semibold ds:text-[var(--av-accent)] ds:shadow-raised",
1578
+ children: monogram
1579
+ }
1580
+ ),
1581
+ /* @__PURE__ */ jsx("div", { className: "ds:mt-4 ds:text-[21px] ds:leading-tight ds:font-semibold", children: firm.name }),
1582
+ firm.tagline && /* @__PURE__ */ jsx("div", { className: "ds:mt-1.5 ds:text-[13px] ds:leading-snug ds:text-white/80", children: firm.tagline }),
1583
+ firm.contact && /* @__PURE__ */ jsxs("div", { className: "ds:mt-auto ds:pt-7", children: [
1584
+ /* @__PURE__ */ jsx("div", { className: "ds:mb-4 ds:h-px ds:bg-white/20" }),
1585
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:flex-col ds:gap-3 ds:text-[12.5px] ds:text-white/90", children: [
1586
+ firm.contact.phone && /* @__PURE__ */ jsxs("span", { className: "ds:flex ds:items-center ds:gap-2.5", children: [
1587
+ /* @__PURE__ */ jsx(PhoneIcon, { className: "ds:size-4 ds:shrink-0 ds:opacity-85", "aria-hidden": "true" }),
1588
+ firm.contact.phone
1589
+ ] }),
1590
+ firm.contact.email && /* @__PURE__ */ jsxs("span", { className: "ds:flex ds:items-center ds:gap-2.5", children: [
1591
+ /* @__PURE__ */ jsx(MailIcon, { className: "ds:size-4 ds:shrink-0 ds:opacity-85", "aria-hidden": "true" }),
1592
+ firm.contact.email
1593
+ ] }),
1594
+ firm.contact.website && /* @__PURE__ */ jsxs("span", { className: "ds:flex ds:items-center ds:gap-2.5", children: [
1595
+ /* @__PURE__ */ jsx(GlobeIcon, { className: "ds:size-4 ds:shrink-0 ds:opacity-85", "aria-hidden": "true" }),
1596
+ firm.contact.website
1597
+ ] })
1598
+ ] })
1599
+ ] })
1600
+ ]
1601
+ }
1602
+ ),
1603
+ /* @__PURE__ */ jsxs("aside", { className: "ds:border-rule ds:bg-surface-2 ds:hidden ds:w-[300px] ds:shrink-0 ds:flex-col ds:overflow-y-auto ds:border-r ds:px-6 ds:py-7 ds:@5xl/agreement:group-data-[view=inner]/agreement:flex", children: [
1604
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-center ds:gap-3", children: [
1605
+ /* @__PURE__ */ jsx(
1606
+ "span",
1607
+ {
1608
+ "aria-hidden": "true",
1609
+ className: "ds:rounded-icon ds:flex ds:size-10 ds:shrink-0 ds:items-center ds:justify-center ds:bg-[var(--av-accent)] ds:text-[13px] ds:font-bold ds:text-[var(--av-accent-contrast)]",
1610
+ children: monogram
1611
+ }
1612
+ ),
1613
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0", children: [
1614
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:truncate ds:text-sm ds:font-semibold", children: firm.name }),
1615
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:text-[11.5px]", children: firm.subtitle ?? "Your proposal" })
1616
+ ] })
1617
+ ] }),
1618
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:mt-6 ds:text-[11.5px] ds:font-semibold ds:tracking-wide", children: "Sections" }),
1619
+ /* @__PURE__ */ jsx("nav", { "aria-label": "Agreement sections", className: "ds:mt-3 ds:flex ds:flex-col ds:gap-0.5", children: steps.map((s, i) => {
1620
+ const on = i === current;
1621
+ const done = status === "signed" ? i !== current && i !== 0 : i < current;
1622
+ return /* @__PURE__ */ jsxs(
1623
+ "button",
1624
+ {
1625
+ type: "button",
1626
+ onClick: () => goTo(i),
1627
+ "aria-current": on ? "step" : void 0,
1628
+ "data-on": on || void 0,
1629
+ "data-done": done || void 0,
1630
+ "data-first": i === 0 || void 0,
1631
+ className: cn(
1632
+ "ds:group/step ds:text-fg-3 ds:relative ds:z-[calc(var(--z-base)+1)] ds:flex ds:w-full ds:items-center ds:gap-3.5 ds:rounded-[12px] ds:py-2.5 ds:pr-3.5 ds:pl-2 ds:text-left ds:text-[13.5px] ds:font-medium",
1633
+ "ds:transition-colors ds:duration-[var(--duration-normal)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1634
+ "ds:hover:bg-surface-hover",
1635
+ "ds:data-[on]:bg-[var(--av-accent-tint)] ds:data-[on]:font-semibold ds:data-[on]:text-[var(--av-accent-soft)]",
1636
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none"
1637
+ ),
1638
+ children: [
1639
+ /* @__PURE__ */ jsx(
1640
+ "span",
1641
+ {
1642
+ "aria-hidden": "true",
1643
+ className: cn(
1644
+ "ds:relative ds:flex ds:size-7 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-full ds:border-[1.5px] ds:text-[12.5px] ds:font-semibold",
1645
+ "ds:border-[var(--av-accent-tint2)] ds:bg-[var(--color-surface)] ds:text-[var(--av-accent)]",
1646
+ "ds:transition-colors ds:duration-[var(--duration-normal)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1647
+ // connector to the node above (skipped on the first step)
1648
+ "ds:before:absolute ds:before:bottom-full ds:before:left-1/2 ds:before:h-[18px] ds:before:w-[2.5px] ds:before:-translate-x-1/2 ds:before:rounded-full ds:before:bg-[var(--av-accent-tint2)] ds:before:transition-colors ds:before:content-['']",
1649
+ "ds:group-data-[first]/step:before:hidden",
1650
+ "ds:group-data-[done]/step:border-[var(--av-accent)] ds:group-data-[done]/step:bg-[var(--av-accent)] ds:group-data-[done]/step:text-[var(--av-accent-contrast)] ds:group-data-[done]/step:before:bg-[var(--av-accent)]",
1651
+ "ds:group-data-[on]/step:border-[var(--av-accent)] ds:group-data-[on]/step:bg-[var(--av-accent)] ds:group-data-[on]/step:text-[var(--av-accent-contrast)] ds:group-data-[on]/step:before:bg-[var(--av-accent)]"
1652
+ ),
1653
+ children: s.icon ?? (i === 0 ? /* @__PURE__ */ jsx(HomeIcon, { className: "ds:size-3.5" }) : done ? /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-3.5" }) : i)
1654
+ }
1655
+ ),
1656
+ /* @__PURE__ */ jsx("span", { className: "ds:truncate", children: s.label })
1657
+ ]
1658
+ },
1659
+ s.id
1660
+ );
1661
+ }) })
1662
+ ] }),
1663
+ /* @__PURE__ */ jsx(
1664
+ "section",
1665
+ {
1666
+ "data-bleed": steps[current]?.bleed || void 0,
1667
+ className: cn(
1668
+ "ds:@container/pane ds:scrollbar-thin ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:overflow-y-auto",
1669
+ // `bleed` steps own their own padding so a cover can reach the
1670
+ // card edges — this replaces the app-side
1671
+ // `*:has(> [data-esign-cover]) { padding: 0 }` global rule.
1672
+ steps[current]?.bleed ? "ds:p-0" : "ds:px-5 ds:py-7 ds:@5xl/agreement:px-[52px] ds:@5xl/agreement:py-11"
1673
+ ),
1674
+ children: steps[current]?.content
1675
+ }
1676
+ )
1677
+ ] }),
1678
+ /* @__PURE__ */ jsxs("div", { className: "ds:mt-4 ds:flex ds:items-center ds:justify-between", children: [
1679
+ /* @__PURE__ */ jsxs(
1680
+ "button",
1681
+ {
1682
+ type: "button",
1683
+ onClick: () => goTo(current - 1),
1684
+ disabled: current === 0,
1685
+ className: cn(
1686
+ "ds:inline-flex ds:h-[42px] ds:items-center ds:gap-1.5 ds:rounded-[11px] ds:px-4 ds:text-sm ds:font-medium",
1687
+ "ds:border-rule-strong ds:bg-surface ds:text-fg-2 ds:border",
1688
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1689
+ "ds:hover:bg-surface-hover",
1690
+ "ds:disabled:border-rule ds:disabled:text-fg-disabled ds:disabled:cursor-default ds:disabled:bg-transparent",
1691
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none"
1692
+ ),
1693
+ children: [
1694
+ /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "ds:size-4", "aria-hidden": "true" }),
1695
+ "Previous"
1696
+ ]
1697
+ }
1698
+ ),
1699
+ /* @__PURE__ */ jsx("div", { className: "ds:flex ds:items-center ds:gap-1.5", children: steps.map((s, i) => /* @__PURE__ */ jsx(
1700
+ "button",
1701
+ {
1702
+ type: "button",
1703
+ onClick: () => goTo(i),
1704
+ "aria-label": `Go to ${s.label}`,
1705
+ "aria-current": i === current ? "step" : void 0,
1706
+ className: cn(
1707
+ "ds:bg-rule-strong ds:h-2 ds:rounded-full",
1708
+ "ds:transition-[width,background-color] ds:duration-[var(--duration-normal)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1709
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
1710
+ i === current ? "ds:w-[22px] ds:bg-[var(--av-accent)]" : "ds:w-2"
1711
+ )
1712
+ },
1713
+ s.id
1714
+ )) }),
1715
+ /* @__PURE__ */ jsxs(
1716
+ "button",
1717
+ {
1718
+ type: "button",
1719
+ onClick: () => goTo(current + 1),
1720
+ disabled: nextDisabled,
1721
+ "aria-describedby": nextDisabled && nextDisabledReason != null ? reasonId : void 0,
1722
+ style: current === lastIndex ? { visibility: "hidden" } : void 0,
1723
+ className: cn(
1724
+ "ds:inline-flex ds:h-[42px] ds:items-center ds:gap-2 ds:rounded-[11px] ds:px-5 ds:text-sm ds:font-semibold",
1725
+ "ds:bg-[var(--av-accent)] ds:text-[var(--av-accent-contrast)]",
1726
+ "ds:transition-[filter] ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1727
+ "ds:hover:brightness-105",
1728
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
1729
+ "ds:disabled:border-rule ds:disabled:bg-bg-disabled ds:disabled:text-fg-disabled ds:disabled:cursor-not-allowed ds:disabled:border ds:disabled:hover:brightness-100"
1730
+ ),
1731
+ children: [
1732
+ "Next",
1733
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ds:size-4", "aria-hidden": "true" })
1734
+ ]
1735
+ }
1736
+ )
1737
+ ] }),
1738
+ footer && /* @__PURE__ */ jsx("div", { className: "ds:mt-4", children: footer }),
1739
+ nextDisabledReason != null && /* @__PURE__ */ jsx(
1740
+ "p",
1741
+ {
1742
+ id: reasonId,
1743
+ role: "status",
1744
+ "aria-live": "polite",
1745
+ "aria-atomic": "true",
1746
+ className: "ds:text-fg-3 ds:mt-1.5 ds:min-h-5 ds:text-right ds:text-sm",
1747
+ children: nextDisabled ? nextDisabledReason : null
1748
+ }
1749
+ )
1750
+ ] })
1751
+ ]
1752
+ }
1753
+ );
1754
+ }
1755
+ );
1756
+ AgreementViewer.displayName = "AgreementViewer";
1757
+ var AgreementPaneHeading = forwardRef(
1758
+ function AgreementPaneHeading2({ overline, title, subtitle, className, ...props }, ref) {
1759
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("ds:mb-6", className), ...props, children: [
1760
+ overline && /* @__PURE__ */ jsx("div", { className: "ds:mb-1.5 ds:text-xs ds:font-semibold ds:tracking-wide ds:text-[var(--av-accent-soft)]", children: overline }),
1761
+ /* @__PURE__ */ jsx("h2", { className: "ds:font-display ds:text-fg ds:text-[27px] ds:leading-tight ds:font-bold ds:tracking-tight", children: title }),
1762
+ subtitle && /* @__PURE__ */ jsx("p", { className: "ds:text-fg-3 ds:mt-2 ds:text-sm ds:leading-relaxed", children: subtitle })
1763
+ ] });
1764
+ }
1765
+ );
1766
+ AgreementPaneHeading.displayName = "AgreementPaneHeading";
1767
+ var ProposalServiceRow = forwardRef(
1768
+ function ProposalServiceRow2({ name, description, price, originalPrice, marker = "check", className, ...props }, ref) {
1769
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("ds:flex ds:items-start ds:gap-2.5 ds:py-1.5", className), ...props, children: [
1770
+ marker === "check" && /* @__PURE__ */ jsx(
1771
+ CheckIcon,
1772
+ {
1773
+ className: "ds:mt-0.5 ds:size-3.5 ds:shrink-0 ds:text-[var(--av-accent,var(--color-accent))]",
1774
+ "aria-hidden": "true"
1775
+ }
1776
+ ),
1777
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0 ds:flex-1", children: [
1778
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg-2 ds:text-[12.5px] ds:leading-snug", children: name }),
1779
+ description && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:mt-0.5 ds:text-[11.5px] ds:leading-snug", children: description })
1780
+ ] }),
1781
+ (price != null || originalPrice != null) && /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:shrink-0 ds:items-baseline ds:gap-1.5 ds:text-xs", children: [
1782
+ originalPrice != null && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-4 ds:line-through", children: originalPrice }),
1783
+ price != null && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:tabular", children: price })
1784
+ ] })
1785
+ ] });
1786
+ }
1787
+ );
1788
+ ProposalServiceRow.displayName = "ProposalServiceRow";
1789
+ var CONTROL_LABEL = {
1790
+ choice: ["Selected", "Select package"],
1791
+ addon: ["Added", "Add to proposal"],
1792
+ included: ["Included", "Included"]
1793
+ };
1794
+ var ProposalPackageCard = forwardRef(
1795
+ function ProposalPackageCard2({
1796
+ name,
1797
+ summary,
1798
+ price,
1799
+ priceCaption,
1800
+ originalPrice,
1801
+ savings,
1802
+ mode = "choice",
1803
+ selected = false,
1804
+ badge,
1805
+ servicesLabel = "Included services",
1806
+ children,
1807
+ servicesMaxHeight,
1808
+ onSelect,
1809
+ disabled = false,
1810
+ className,
1811
+ ...props
1812
+ }, ref) {
1813
+ const interactive = mode !== "included" && !!onSelect;
1814
+ const [onLabel, offLabel] = CONTROL_LABEL[mode];
1815
+ const servicesLabelId = useId();
1816
+ return /* @__PURE__ */ jsxs(
1817
+ "div",
1818
+ {
1819
+ ref,
1820
+ "data-selected": selected || void 0,
1821
+ className: cn(
1822
+ "ds:border-rule ds:bg-surface ds:relative ds:flex ds:flex-col ds:rounded-[14px] ds:border ds:p-4",
1823
+ "ds:data-[selected]:border-[var(--av-accent,var(--color-accent))] ds:data-[selected]:shadow-[0_0_0_1px_var(--av-accent,var(--color-accent))]",
1824
+ className
1825
+ ),
1826
+ ...props,
1827
+ children: [
1828
+ (badge || selected) && /* @__PURE__ */ jsxs("span", { className: "ds:rounded-pill ds:absolute ds:-top-2.5 ds:left-4 ds:flex ds:items-center ds:gap-1 ds:bg-[var(--av-accent,var(--color-accent))] ds:px-2 ds:py-1 ds:text-[10px] ds:font-bold ds:tracking-wide ds:text-[var(--av-accent-contrast,var(--color-fg-on-accent))]", children: [
1829
+ selected && /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-3", "aria-hidden": "true" }),
1830
+ badge ?? (selected ? onLabel : null)
1831
+ ] }),
1832
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:text-[15px] ds:font-semibold", children: name }),
1833
+ summary && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:mt-0.5 ds:text-xs", children: summary }),
1834
+ price != null && /* @__PURE__ */ jsxs("div", { className: "ds:mt-2.5", children: [
1835
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-baseline ds:gap-2", children: [
1836
+ originalPrice != null && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-4 ds:text-base ds:line-through", children: originalPrice }),
1837
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-[23px] ds:font-bold ds:tracking-tight ds:tabular", children: price })
1838
+ ] }),
1839
+ priceCaption && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:text-[11.5px]", children: priceCaption }),
1840
+ savings && /* @__PURE__ */ jsx("div", { className: "ds:text-success-fg ds:mt-1 ds:text-[11.5px] ds:font-semibold", children: savings })
1841
+ ] }),
1842
+ children && /* @__PURE__ */ jsxs(Fragment, { children: [
1843
+ /* @__PURE__ */ jsx(
1844
+ "div",
1845
+ {
1846
+ id: servicesLabelId,
1847
+ className: "ds:text-fg-3 ds:mt-4 ds:mb-1 ds:text-[11.5px] ds:font-semibold ds:tracking-wide",
1848
+ children: servicesLabel
1849
+ }
1850
+ ),
1851
+ /* @__PURE__ */ jsx(
1852
+ "div",
1853
+ {
1854
+ ...servicesMaxHeight ? { role: "region", "aria-labelledby": servicesLabelId, tabIndex: 0 } : {},
1855
+ className: cn(
1856
+ servicesMaxHeight && [
1857
+ "ds:min-h-0 ds:overflow-y-auto",
1858
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
1859
+ // pr-3 keeps the rail off the service text; -mr-1 gives that
1860
+ // padding back to the card so the rail still sits near its
1861
+ // edge rather than floating in from it.
1862
+ "ds:-mr-1 ds:pr-3",
1863
+ // A 2px hairline. `scrollbar-thin` is 8px, and on
1864
+ // Chrome-for-Windows an unstyled bar also carries stepper
1865
+ // arrows, which is most of what made it read as heavy.
1866
+ "ds:[scrollbar-width:thin]",
1867
+ "ds:[&::-webkit-scrollbar]:w-[2px]",
1868
+ "ds:[&::-webkit-scrollbar-button]:hidden",
1869
+ "ds:[&::-webkit-scrollbar-track]:bg-transparent",
1870
+ "ds:[&::-webkit-scrollbar-thumb]:rounded-full",
1871
+ "ds:[&::-webkit-scrollbar-thumb]:bg-rule-strong"
1872
+ ]
1873
+ ),
1874
+ style: servicesMaxHeight ? { maxHeight: servicesMaxHeight } : void 0,
1875
+ children
1876
+ }
1877
+ )
1878
+ ] }),
1879
+ /* @__PURE__ */ jsx("div", { className: "ds:mt-auto ds:pt-4", children: interactive ? /* @__PURE__ */ jsx(
1880
+ "button",
1881
+ {
1882
+ type: "button",
1883
+ role: mode === "addon" ? "checkbox" : "radio",
1884
+ "aria-checked": selected,
1885
+ disabled,
1886
+ onClick: onSelect,
1887
+ className: cn(
1888
+ "ds:rounded-input ds:flex ds:h-10 ds:w-full ds:items-center ds:justify-center ds:text-[13.5px] ds:font-semibold",
1889
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1890
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
1891
+ selected ? "ds:bg-[var(--av-accent,var(--color-accent))] ds:text-[var(--av-accent-contrast,var(--color-fg-on-accent))]" : "ds:border-rule-strong ds:text-fg ds:hover:bg-surface-hover ds:border",
1892
+ "ds:disabled:cursor-not-allowed ds:disabled:opacity-60"
1893
+ ),
1894
+ children: selected ? onLabel : offLabel
1895
+ }
1896
+ ) : /* @__PURE__ */ jsxs(
1897
+ "div",
1898
+ {
1899
+ className: cn(
1900
+ "ds:rounded-input ds:flex ds:h-10 ds:w-full ds:items-center ds:justify-center ds:gap-1.5 ds:text-[13.5px] ds:font-semibold",
1901
+ mode === "included" ? "ds:bg-[var(--av-accent-tint,var(--color-accent-tint))] ds:text-[var(--av-accent-soft,var(--color-accent-2))]" : "ds:border-rule ds:text-fg-3 ds:border"
1902
+ ),
1903
+ children: [
1904
+ mode === "included" && /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-3.5", "aria-hidden": "true" }),
1905
+ selected ? onLabel : offLabel
1906
+ ]
1907
+ }
1908
+ ) })
1909
+ ]
1910
+ }
1911
+ );
1912
+ }
1913
+ );
1914
+ ProposalPackageCard.displayName = "ProposalPackageCard";
1915
+ var BILLING_ICON = {
1916
+ now: CreditCardIcon,
1917
+ auto: RotateCcwIcon,
1918
+ review: EyeIcon,
1919
+ manual: ReceiptIcon,
1920
+ onetime: CheckIcon
1921
+ };
1922
+ var ProposalBillingTerms = forwardRef(
1923
+ function ProposalBillingTerms2({ title = "How billing works", rows, locked = true, className, ...props }, ref) {
1924
+ return /* @__PURE__ */ jsxs(
1925
+ "div",
1926
+ {
1927
+ ref,
1928
+ className: cn("ds:border-rule ds:overflow-hidden ds:rounded-[14px] ds:border", className),
1929
+ ...props,
1930
+ children: [
1931
+ title && /* @__PURE__ */ jsx("div", { className: "ds:border-rule ds:bg-surface-2 ds:text-fg ds:border-b ds:px-5 ds:py-3 ds:text-[13px] ds:font-semibold", children: title }),
1932
+ /* @__PURE__ */ jsx("div", { className: "ds:divide-rule-soft ds:divide-y", children: rows.map((r, i) => {
1933
+ const Icon = BILLING_ICON[r.mode ?? "now"];
1934
+ return /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-start ds:gap-3.5 ds:px-5 ds:py-3.5", children: [
1935
+ /* @__PURE__ */ jsx(
1936
+ "span",
1937
+ {
1938
+ "aria-hidden": "true",
1939
+ className: "ds:rounded-icon ds:mt-0.5 ds:flex ds:size-9 ds:shrink-0 ds:items-center ds:justify-center ds:bg-[var(--av-accent-tint,var(--color-accent-tint))] ds:text-[var(--av-accent,var(--color-accent))]",
1940
+ children: /* @__PURE__ */ jsx(Icon, { className: "ds:size-4.5" })
1941
+ }
1942
+ ),
1943
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0 ds:flex-1", children: [
1944
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-baseline ds:justify-between ds:gap-3", children: [
1945
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-sm ds:font-semibold", children: r.label }),
1946
+ r.amount != null && /* @__PURE__ */ jsxs("span", { className: "ds:text-fg ds:shrink-0 ds:text-sm ds:font-semibold ds:tabular", children: [
1947
+ r.amount,
1948
+ r.cadence && /* @__PURE__ */ jsx("small", { className: "ds:text-fg-4 ds:ml-0.5 ds:text-xs ds:font-medium", children: r.cadence })
1949
+ ] })
1950
+ ] }),
1951
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg-3 ds:mt-0.5 ds:text-[13px] ds:leading-snug", children: r.detail })
1952
+ ] })
1953
+ ] }, i);
1954
+ }) }),
1955
+ locked && /* @__PURE__ */ jsxs("div", { className: "ds:border-rule ds:bg-surface-2 ds:text-fg-4 ds:flex ds:items-center ds:gap-2 ds:border-t ds:px-5 ds:py-2.5 ds:text-[12px]", children: [
1956
+ /* @__PURE__ */ jsx(LockIcon, { className: "ds:size-3.5 ds:shrink-0", "aria-hidden": "true" }),
1957
+ "Set by your firm \u2014 you can review these terms, but not change them."
1958
+ ] })
1959
+ ]
1960
+ }
1961
+ );
1962
+ }
1963
+ );
1964
+ ProposalBillingTerms.displayName = "ProposalBillingTerms";
1965
+ var ProposalAddOn = forwardRef(
1966
+ function ProposalAddOn2({ name, description, price, cadence, selected = false, onToggle, disabled, className, ...props }, ref) {
1967
+ return /* @__PURE__ */ jsxs(
1968
+ "button",
1969
+ {
1970
+ ref,
1971
+ type: "button",
1972
+ role: "checkbox",
1973
+ "aria-checked": selected,
1974
+ disabled,
1975
+ onClick: onToggle,
1976
+ "data-selected": selected || void 0,
1977
+ className: cn(
1978
+ "ds:group/addon ds:flex ds:w-full ds:items-center ds:gap-3.5 ds:rounded-[12px] ds:border ds:p-4 ds:text-left",
1979
+ "ds:border-rule ds:bg-surface",
1980
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
1981
+ "ds:hover:bg-surface-hover",
1982
+ "ds:data-[selected]:border-[var(--av-accent,var(--color-accent))] ds:data-[selected]:bg-[var(--av-accent-tint,var(--color-accent-tint))]",
1983
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
1984
+ "ds:disabled:cursor-not-allowed ds:disabled:opacity-60",
1985
+ className
1986
+ ),
1987
+ ...props,
1988
+ children: [
1989
+ /* @__PURE__ */ jsx(
1990
+ "span",
1991
+ {
1992
+ "aria-hidden": "true",
1993
+ className: cn(
1994
+ "ds:flex ds:size-5 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-md ds:border-[1.5px] ds:text-transparent",
1995
+ "ds:border-rule-strong",
1996
+ "ds:group-data-[selected]/addon:border-[var(--av-accent,var(--color-accent))] ds:group-data-[selected]/addon:bg-[var(--av-accent,var(--color-accent))] ds:group-data-[selected]/addon:text-[var(--av-accent-contrast,var(--color-fg-on-accent))]"
1997
+ ),
1998
+ children: /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-3.5" })
1999
+ }
2000
+ ),
2001
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0 ds:flex-1", children: [
2002
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:text-sm ds:font-semibold", children: name }),
2003
+ description && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:group-data-[selected]/addon:text-fg-3 ds:text-xs", children: description })
2004
+ ] }),
2005
+ (price != null || cadence != null) && /* @__PURE__ */ jsxs("div", { className: "ds:shrink-0 ds:text-right", children: [
2006
+ price != null && /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:text-[15px] ds:font-bold ds:tabular", children: price }),
2007
+ cadence != null && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:group-data-[selected]/addon:text-fg-3 ds:text-[11.5px]", children: cadence })
2008
+ ] })
2009
+ ]
2010
+ }
2011
+ );
2012
+ }
2013
+ );
2014
+ ProposalAddOn.displayName = "ProposalAddOn";
2015
+ var ProposalPricingSummary = forwardRef(
2016
+ function ProposalPricingSummary2({
2017
+ children,
2018
+ billing,
2019
+ savings,
2020
+ tax,
2021
+ taxLabel = "Tax",
2022
+ originalTotal,
2023
+ total,
2024
+ cadence,
2025
+ totalLabel = "Total due",
2026
+ schedule,
2027
+ className,
2028
+ ...props
2029
+ }, ref) {
2030
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("ds:@container/summary ds:flex ds:flex-col", className), ...props, children: [
2031
+ children && /* @__PURE__ */ jsx("div", { className: "ds:border-rule ds:grid ds:grid-cols-1 ds:gap-x-6 ds:gap-y-1 ds:rounded-[14px] ds:border ds:p-6 ds:@md/summary:grid-cols-2", children }),
2032
+ billing && /* @__PURE__ */ jsxs("div", { className: "ds:mt-4 ds:rounded-[14px] ds:border ds:border-[var(--av-accent-tint2,var(--color-accent-tint))] ds:bg-[var(--av-accent-tint,var(--color-accent-tint))] ds:p-5", children: [
2033
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-center ds:justify-between", children: [
2034
+ /* @__PURE__ */ jsx("b", { className: "ds:text-[13.5px] ds:font-semibold ds:text-[var(--av-accent-soft,var(--color-accent-2))]", children: billing.title ?? "Billing schedule" }),
2035
+ billing.caption && /* @__PURE__ */ jsx("span", { className: "ds:text-[11.5px] ds:text-[var(--av-accent-soft,var(--color-accent-2))]", children: billing.caption })
2036
+ ] }),
2037
+ billing.rows?.map((r, i) => /* @__PURE__ */ jsxs(
2038
+ "div",
2039
+ {
2040
+ className: "ds:text-fg-2 ds:mt-2.5 ds:flex ds:items-center ds:justify-between ds:gap-3 ds:text-[13.5px]",
2041
+ children: [
2042
+ /* @__PURE__ */ jsx("span", { children: r.label }),
2043
+ /* @__PURE__ */ jsx("b", { className: "ds:font-semibold ds:tabular", children: r.value })
2044
+ ]
2045
+ },
2046
+ i
2047
+ ))
2048
+ ] }),
2049
+ (savings || tax != null) && /* @__PURE__ */ jsxs("div", { className: "ds:mt-4 ds:space-y-2", children: [
2050
+ savings && /* @__PURE__ */ jsxs("div", { className: "ds:text-success-fg ds:flex ds:items-center ds:justify-between ds:text-[13.5px] ds:font-medium", children: [
2051
+ /* @__PURE__ */ jsx("span", { children: "Discount" }),
2052
+ /* @__PURE__ */ jsx("span", { className: "ds:tabular", children: savings })
2053
+ ] }),
2054
+ tax != null && /* @__PURE__ */ jsxs("div", { className: "ds:text-fg-3 ds:flex ds:items-center ds:justify-between ds:text-[13.5px]", children: [
2055
+ /* @__PURE__ */ jsx("span", { children: taxLabel }),
2056
+ /* @__PURE__ */ jsx("span", { className: "ds:tabular", children: tax })
2057
+ ] })
2058
+ ] }),
2059
+ schedule ? /* @__PURE__ */ jsxs("div", { className: "ds:border-rule ds:mt-4 ds:border-t ds:pt-4", children: [
2060
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-baseline ds:justify-between ds:gap-3", children: [
2061
+ /* @__PURE__ */ jsxs("div", { children: [
2062
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:text-[15px] ds:font-semibold", children: schedule.dueTodayLabel ?? "Due today" }),
2063
+ schedule.dueTodayCaption && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:text-xs", children: schedule.dueTodayCaption })
2064
+ ] }),
2065
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-[26px] ds:font-bold ds:tabular", children: schedule.dueToday })
2066
+ ] }),
2067
+ schedule.then && schedule.then.length > 0 && /* @__PURE__ */ jsx("div", { className: "ds:border-rule-soft ds:mt-3 ds:space-y-1.5 ds:border-t ds:pt-3", children: schedule.then.map((t, i) => /* @__PURE__ */ jsxs(
2068
+ "div",
2069
+ {
2070
+ className: "ds:text-fg-3 ds:flex ds:items-baseline ds:justify-between ds:gap-3 ds:text-[13.5px]",
2071
+ children: [
2072
+ /* @__PURE__ */ jsx("span", { children: t.label ?? "Then" }),
2073
+ /* @__PURE__ */ jsxs("span", { className: "ds:tabular", children: [
2074
+ /* @__PURE__ */ jsx("b", { className: "ds:text-fg-2 ds:font-semibold", children: t.amount }),
2075
+ t.cadence && /* @__PURE__ */ jsx("small", { className: "ds:text-fg-4 ds:ml-1 ds:text-[12px] ds:font-medium", children: t.cadence })
2076
+ ] })
2077
+ ]
2078
+ },
2079
+ i
2080
+ )) })
2081
+ ] }) : total != null && /* @__PURE__ */ jsxs("div", { className: "ds:border-rule ds:mt-4 ds:flex ds:items-center ds:justify-between ds:border-t ds:pt-4", children: [
2082
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-[15px] ds:font-semibold", children: totalLabel }),
2083
+ /* @__PURE__ */ jsxs("span", { className: "ds:flex ds:items-baseline ds:gap-2", children: [
2084
+ originalTotal != null && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-4 ds:text-base ds:line-through", children: originalTotal }),
2085
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-[22px] ds:font-bold ds:tabular", children: total }),
2086
+ cadence && /* @__PURE__ */ jsx("small", { className: "ds:text-fg-4 ds:text-[13px] ds:font-medium", children: cadence })
2087
+ ] })
2088
+ ] })
2089
+ ] });
2090
+ }
2091
+ );
2092
+ ProposalPricingSummary.displayName = "ProposalPricingSummary";
2093
+ var KIND_META = {
2094
+ video: { label: "Video", icon: PlayIcon },
2095
+ pdf: { label: "Document", icon: FileTextIcon },
2096
+ text: { label: "Read", icon: FileTextIcon }
2097
+ };
2098
+ var ProposalCustomPage = forwardRef(
2099
+ function ProposalCustomPage2({ kind, title, caption, label, poster, onPlay, children, className, ...props }, ref) {
2100
+ const meta = KIND_META[kind];
2101
+ const Icon = meta.icon;
2102
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("ds:flex ds:flex-col", className), ...props, children: [
2103
+ /* @__PURE__ */ jsxs("div", { className: "ds:mb-1.5 ds:flex ds:items-center ds:gap-1.5 ds:text-xs ds:font-semibold ds:tracking-wide ds:text-[var(--av-accent-soft,var(--color-accent-2))]", children: [
2104
+ /* @__PURE__ */ jsx(Icon, { className: "ds:size-3.5", "aria-hidden": "true" }),
2105
+ label ?? meta.label
2106
+ ] }),
2107
+ /* @__PURE__ */ jsx("h2", { className: "ds:font-display ds:text-fg ds:text-[27px] ds:leading-tight ds:font-bold ds:tracking-tight", children: title }),
2108
+ caption && /* @__PURE__ */ jsx("p", { className: "ds:text-fg-3 ds:mt-2 ds:text-sm ds:leading-relaxed", children: caption }),
2109
+ /* @__PURE__ */ jsx("div", { className: "ds:mt-5", children: kind === "video" && !children ? /* @__PURE__ */ jsx(PlayablePoster, { poster, onPlay, title }) : children })
2110
+ ] });
2111
+ }
2112
+ );
2113
+ ProposalCustomPage.displayName = "ProposalCustomPage";
2114
+ function PlayablePoster({
2115
+ poster,
2116
+ onPlay,
2117
+ title
2118
+ }) {
2119
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
2120
+ /* @__PURE__ */ jsx(
2121
+ "span",
2122
+ {
2123
+ "aria-hidden": "true",
2124
+ className: "ds:bg-bg-3 ds:absolute ds:inset-0 ds:bg-cover ds:bg-center",
2125
+ style: poster ? { backgroundImage: `url(${poster})` } : void 0
2126
+ }
2127
+ ),
2128
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ds:absolute ds:inset-0 ds:bg-black/15" }),
2129
+ /* @__PURE__ */ jsx(
2130
+ "span",
2131
+ {
2132
+ "aria-hidden": "true",
2133
+ className: "ds:rounded-full ds:relative ds:flex ds:size-16 ds:items-center ds:justify-center ds:bg-white/90 ds:text-[var(--av-accent,var(--color-accent))] ds:shadow-raised",
2134
+ children: /* @__PURE__ */ jsx(PlayIcon, { className: "ds:size-7" })
2135
+ }
2136
+ )
2137
+ ] });
2138
+ const cls = "ds:relative ds:flex ds:aspect-video ds:w-full ds:items-center ds:justify-center ds:overflow-hidden ds:rounded-[14px] ds:border-rule ds:border";
2139
+ return onPlay ? /* @__PURE__ */ jsx(
2140
+ "button",
2141
+ {
2142
+ type: "button",
2143
+ onClick: onPlay,
2144
+ "aria-label": typeof title === "string" ? `Play ${title}` : "Play video",
2145
+ className: cn(
2146
+ cls,
2147
+ "ds:transition-[filter] ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none ds:hover:brightness-105",
2148
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none"
2149
+ ),
2150
+ children: inner
2151
+ }
2152
+ ) : /* @__PURE__ */ jsx("div", { className: cls, children: inner });
2153
+ }
2154
+ var ProposalNote = forwardRef(
2155
+ function ProposalNote2({ title, children, tone = "accent", icon, className, ...props }, ref) {
2156
+ return /* @__PURE__ */ jsxs(
2157
+ "div",
2158
+ {
2159
+ ref,
2160
+ className: cn(
2161
+ "ds:flex ds:gap-3 ds:rounded-[12px] ds:border ds:p-4 ds:text-[13.5px] ds:leading-relaxed",
2162
+ tone === "accent" ? "ds:border-[var(--av-accent-tint2,var(--color-accent-tint))] ds:bg-[var(--av-accent-tint,var(--color-accent-tint))] ds:text-[var(--av-accent-soft,var(--color-accent-2))]" : "ds:border-rule ds:bg-bg-2 ds:text-fg-2",
2163
+ className
2164
+ ),
2165
+ ...props,
2166
+ children: [
2167
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ds:mt-0.5 ds:shrink-0", children: icon ?? /* @__PURE__ */ jsx(InfoIcon, { className: "ds:size-4" }) }),
2168
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0", children: [
2169
+ title && /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:font-semibold", children: title }),
2170
+ /* @__PURE__ */ jsx("div", { className: cn(title && "ds:mt-0.5"), children })
2171
+ ] })
2172
+ ]
2173
+ }
2174
+ );
2175
+ }
2176
+ );
2177
+ ProposalNote.displayName = "ProposalNote";
2178
+ var STATUS_META = {
2179
+ signed: {
2180
+ label: "Signed",
2181
+ icon: CheckIcon,
2182
+ className: "ds:text-success-fg ds:bg-success-bg ds:border-success-line"
2183
+ },
2184
+ viewed: {
2185
+ label: "Viewed",
2186
+ icon: EyeIcon,
2187
+ className: "ds:text-[var(--av-accent-soft,var(--color-accent-2))] ds:bg-[var(--av-accent-tint,var(--color-accent-tint))] ds:border-[var(--av-accent-tint2,var(--color-accent-tint))]"
2188
+ },
2189
+ pending: { label: "Pending", icon: ClockIcon, className: "ds:text-fg-3 ds:bg-bg-2 ds:border-rule" }
2190
+ };
2191
+ var ProposalSignerList = forwardRef(
2192
+ function ProposalSignerList2({ signers, title = "Recipients", className, ...props }, ref) {
2193
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("ds:flex ds:flex-col", className), ...props, children: [
2194
+ title && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-3 ds:mb-2 ds:text-[11.5px] ds:font-semibold ds:tracking-wide", children: title }),
2195
+ /* @__PURE__ */ jsx("div", { className: "ds:border-rule ds:divide-rule ds:divide-y ds:overflow-hidden ds:rounded-[12px] ds:border", children: signers.map((s, i) => {
2196
+ const status = s.status ? STATUS_META[s.status] : null;
2197
+ const StatusIcon = status?.icon;
2198
+ const initials = s.name.split(" ").map((w) => w[0]).slice(0, 2).join("").toUpperCase();
2199
+ return /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-center ds:gap-3 ds:px-4 ds:py-3", children: [
2200
+ /* @__PURE__ */ jsx(
2201
+ "span",
2202
+ {
2203
+ "aria-hidden": "true",
2204
+ className: "ds:flex ds:size-9 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-full ds:bg-[var(--av-accent-tint,var(--color-accent-tint))] ds:text-[12.5px] ds:font-semibold ds:text-[var(--av-accent-soft,var(--color-accent-2))]",
2205
+ children: initials
2206
+ }
2207
+ ),
2208
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0 ds:flex-1", children: [
2209
+ /* @__PURE__ */ jsxs("div", { className: "ds:text-fg ds:truncate ds:text-sm ds:font-medium", children: [
2210
+ s.name,
2211
+ s.role && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-4 ds:ml-2 ds:text-xs ds:font-normal", children: s.role })
2212
+ ] }),
2213
+ s.email && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:truncate ds:text-xs", children: s.email })
2214
+ ] }),
2215
+ status && StatusIcon && /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:shrink-0 ds:flex-col ds:items-end ds:gap-1", children: [
2216
+ /* @__PURE__ */ jsxs(
2217
+ "span",
2218
+ {
2219
+ className: cn(
2220
+ "ds:inline-flex ds:items-center ds:gap-1 ds:rounded-full ds:border ds:px-2 ds:py-0.5 ds:text-[11px] ds:font-medium",
2221
+ status.className
2222
+ ),
2223
+ children: [
2224
+ /* @__PURE__ */ jsx(StatusIcon, { className: "ds:size-3", "aria-hidden": "true" }),
2225
+ status.label
2226
+ ]
2227
+ }
2228
+ ),
2229
+ s.at != null && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-4 ds:text-[11px]", children: s.at })
2230
+ ] })
2231
+ ] }, i);
2232
+ }) })
2233
+ ] });
2234
+ }
2235
+ );
2236
+ ProposalSignerList.displayName = "ProposalSignerList";
2237
+ function deriveInitials(name) {
2238
+ return name.trim().split(/\s+/).filter(Boolean).map((w) => w[0]).slice(0, 2).join("").toUpperCase();
2239
+ }
2240
+ var ProposalSignatureBlock = forwardRef(
2241
+ function ProposalSignatureBlock2({
2242
+ signed = false,
2243
+ name = "",
2244
+ initials,
2245
+ defaultName = "",
2246
+ onChange,
2247
+ placeholder = "Type your full name",
2248
+ signatureFont = "Georgia, serif",
2249
+ footer,
2250
+ hideModeTabs = false,
2251
+ className,
2252
+ ...props
2253
+ }, ref) {
2254
+ const [nameVal, setNameVal] = useState(defaultName);
2255
+ const [initialsVal, setInitialsVal] = useState("");
2256
+ const [initialsTouched, setInitialsTouched] = useState(false);
2257
+ const displayName = signed ? name : nameVal;
2258
+ const displayInitials = signed ? initials ?? deriveInitials(name) : initialsTouched ? initialsVal : deriveInitials(nameVal);
2259
+ const emitChange = (n, i) => onChange?.({ name: n, initials: i });
2260
+ const handleName = (v) => {
2261
+ setNameVal(v);
2262
+ emitChange(v, initialsTouched ? initialsVal : deriveInitials(v));
2263
+ };
2264
+ const handleInitials = (v) => {
2265
+ setInitialsTouched(true);
2266
+ setInitialsVal(v);
2267
+ emitChange(nameVal, v);
2268
+ };
2269
+ return /* @__PURE__ */ jsxs(
2270
+ "div",
2271
+ {
2272
+ ref,
2273
+ className: cn("ds:@container/signature ds:flex ds:flex-col", className),
2274
+ ...props,
2275
+ children: [
2276
+ !hideModeTabs && /* @__PURE__ */ jsxs("div", { className: "ds:border-rule ds:mb-4 ds:flex ds:gap-6 ds:border-b", children: [
2277
+ /* @__PURE__ */ jsx("span", { className: "ds:border-[var(--av-accent,var(--color-accent))] ds:text-fg ds:-mb-px ds:border-b-2 ds:pb-2.5 ds:text-sm ds:font-medium", children: "Type" }),
2278
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg-4 ds:pb-2.5 ds:text-sm ds:font-medium", children: "Draw" })
2279
+ ] }),
2280
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:flex-col ds:gap-4 ds:@2xl/signature:flex-row", children: [
2281
+ /* @__PURE__ */ jsx("div", { className: "ds:border-rule ds:bg-surface-2 ds:flex ds:h-[84px] ds:flex-none ds:items-center ds:overflow-hidden ds:rounded-[12px] ds:border ds:px-4 ds:@2xl/signature:h-[118px] ds:@2xl/signature:flex-1 ds:@2xl/signature:px-7", children: /* @__PURE__ */ jsx(
2282
+ "span",
2283
+ {
2284
+ className: cn("ds:text-3xl ds:leading-none ds:font-semibold ds:@2xl/signature:text-[46px]", displayName ? "ds:text-fg" : "ds:text-fg-4"),
2285
+ style: { fontFamily: signatureFont },
2286
+ children: displayName || placeholder
2287
+ }
2288
+ ) }),
2289
+ /* @__PURE__ */ jsx("div", { className: "ds:border-rule ds:bg-surface-2 ds:flex ds:h-[84px] ds:w-full ds:shrink-0 ds:items-center ds:justify-center ds:rounded-[12px] ds:border ds:@2xl/signature:h-[118px] ds:@2xl/signature:w-[168px]", children: /* @__PURE__ */ jsx(
2290
+ "span",
2291
+ {
2292
+ className: cn("ds:text-2xl ds:leading-none ds:@2xl/signature:text-[34px]", displayInitials ? "ds:text-fg-3" : "ds:text-fg-4"),
2293
+ style: { fontFamily: signatureFont },
2294
+ children: displayInitials || "\u2014"
2295
+ }
2296
+ ) })
2297
+ ] }),
2298
+ /* @__PURE__ */ jsxs(
2299
+ "div",
2300
+ {
2301
+ className: "ds:mt-5 ds:grid ds:grid-cols-1 ds:gap-3.5 ds:@2xl/signature:grid-cols-[1fr_120px]",
2302
+ children: [
2303
+ /* @__PURE__ */ jsxs("label", { className: "ds:flex ds:flex-col ds:gap-1.5", children: [
2304
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:text-xs ds:font-medium", children: "Your legal name" }),
2305
+ /* @__PURE__ */ jsx(
2306
+ "input",
2307
+ {
2308
+ value: displayName,
2309
+ readOnly: signed,
2310
+ onChange: (e) => handleName(e.target.value),
2311
+ placeholder: signed ? void 0 : placeholder,
2312
+ "aria-label": "Your legal name",
2313
+ className: "ds:border-rule-strong ds:rounded-input ds:text-fg-2 ds:bg-surface ds:h-10 ds:border ds:px-3 ds:text-sm ds:read-only:bg-[var(--color-bg-2)]"
2314
+ }
2315
+ )
2316
+ ] }),
2317
+ /* @__PURE__ */ jsxs("label", { className: "ds:flex ds:flex-col ds:gap-1.5", children: [
2318
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:text-xs ds:font-medium", children: "Initials" }),
2319
+ /* @__PURE__ */ jsx(
2320
+ "input",
2321
+ {
2322
+ value: displayInitials,
2323
+ readOnly: signed,
2324
+ onChange: (e) => handleInitials(e.target.value),
2325
+ placeholder: signed ? void 0 : "\u2014",
2326
+ "aria-label": "Initials",
2327
+ className: "ds:border-rule-strong ds:rounded-input ds:text-fg-2 ds:bg-surface ds:h-10 ds:border ds:px-3 ds:text-sm ds:read-only:bg-[var(--color-bg-2)]"
2328
+ }
2329
+ )
2330
+ ] })
2331
+ ]
2332
+ }
2333
+ ),
2334
+ footer && /* @__PURE__ */ jsx("div", { className: "ds:mt-6", children: footer })
2335
+ ]
2336
+ }
2337
+ );
2338
+ }
2339
+ );
2340
+ ProposalSignatureBlock.displayName = "ProposalSignatureBlock";
2341
+ var ProposalConsentGate = forwardRef(
2342
+ function ProposalConsentGate2({ children, checked = false, onCheckedChange, signed = false, signedNote, onSign, signLabel = "Sign & approve", disabled = false, className, ...props }, ref) {
2343
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("ds:flex ds:flex-col ds:gap-4", className), ...props, children: [
2344
+ !signed && /* @__PURE__ */ jsxs("label", { className: "ds:flex ds:cursor-pointer ds:items-start ds:gap-2.5 ds:text-[13.5px] ds:leading-relaxed", children: [
2345
+ /* @__PURE__ */ jsx(
2346
+ "input",
2347
+ {
2348
+ type: "checkbox",
2349
+ checked,
2350
+ onChange: (e) => onCheckedChange?.(e.target.checked),
2351
+ className: "ds:mt-0.5 ds:size-4 ds:shrink-0 ds:rounded ds:accent-[var(--av-accent,var(--color-accent))]"
2352
+ }
2353
+ ),
2354
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg-2", children })
2355
+ ] }),
2356
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-center ds:justify-between ds:gap-4", children: [
2357
+ signed ? /* @__PURE__ */ jsxs("span", { className: "ds:text-success-fg ds:flex ds:items-center ds:gap-2 ds:text-[13px] ds:font-medium", children: [
2358
+ /* @__PURE__ */ jsx(CheckIcon, { className: "ds:size-4 ds:shrink-0", "aria-hidden": "true" }),
2359
+ signedNote ?? "This agreement has been signed."
2360
+ ] }) : /* @__PURE__ */ jsxs("span", { className: "ds:text-fg-4 ds:flex ds:items-center ds:gap-1.5 ds:text-[12.5px]", children: [
2361
+ /* @__PURE__ */ jsx(LockIcon, { className: "ds:size-3.5", "aria-hidden": "true" }),
2362
+ " Secure e-signature"
2363
+ ] }),
2364
+ onSign && /* @__PURE__ */ jsxs(
2365
+ "button",
2366
+ {
2367
+ type: "button",
2368
+ onClick: onSign,
2369
+ disabled: signed || !checked || disabled,
2370
+ className: cn(
2371
+ "ds:inline-flex ds:h-[46px] ds:items-center ds:gap-2 ds:rounded-[12px] ds:px-5 ds:text-[14.5px] ds:font-semibold",
2372
+ "ds:transition-[filter] ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
2373
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
2374
+ "ds:bg-[var(--av-accent,var(--color-accent))] ds:text-[var(--av-accent-contrast,var(--color-fg-on-accent))] ds:hover:brightness-105",
2375
+ "ds:disabled:bg-bg-disabled ds:disabled:text-fg-disabled ds:disabled:cursor-not-allowed ds:disabled:brightness-100"
2376
+ ),
2377
+ children: [
2378
+ /* @__PURE__ */ jsx(PenSignIcon, { className: "ds:size-4", "aria-hidden": "true" }),
2379
+ signLabel
2380
+ ]
2381
+ }
2382
+ )
2383
+ ] })
2384
+ ] });
2385
+ }
2386
+ );
2387
+ ProposalConsentGate.displayName = "ProposalConsentGate";
2388
+ var ProposalPaymentCapture = forwardRef(
2389
+ function ProposalPaymentCapture2({ title = "Payment at signing", amount, caption, method = "card", capturedLast4, children, className, ...props }, ref) {
2390
+ return /* @__PURE__ */ jsxs(
2391
+ "div",
2392
+ {
2393
+ ref,
2394
+ className: cn("ds:border-rule ds:rounded-[14px] ds:border ds:p-5", className),
2395
+ ...props,
2396
+ children: [
2397
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:items-center ds:gap-3", children: [
2398
+ /* @__PURE__ */ jsx(
2399
+ "span",
2400
+ {
2401
+ "aria-hidden": "true",
2402
+ className: "ds:rounded-card ds:flex ds:size-10 ds:shrink-0 ds:items-center ds:justify-center ds:bg-[var(--av-accent-tint,var(--color-accent-tint))] ds:text-[var(--av-accent,var(--color-accent))]",
2403
+ children: /* @__PURE__ */ jsx(CreditCardIcon, { className: "ds:size-5" })
2404
+ }
2405
+ ),
2406
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex-1", children: [
2407
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:text-sm ds:font-semibold", children: title }),
2408
+ caption && /* @__PURE__ */ jsx("div", { className: "ds:text-fg-4 ds:text-xs", children: caption })
2409
+ ] }),
2410
+ amount != null && /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:text-lg ds:font-bold ds:tabular", children: amount })
2411
+ ] }),
2412
+ /* @__PURE__ */ jsx("div", { className: "ds:mt-4", children: children ?? (capturedLast4 ? /* @__PURE__ */ jsxs("div", { className: "ds:border-rule ds:flex ds:items-center ds:gap-2.5 ds:rounded-[10px] ds:border ds:px-3.5 ds:py-3", children: [
2413
+ /* @__PURE__ */ jsx(CreditCardIcon, { className: "ds:text-fg-4 ds:size-4", "aria-hidden": "true" }),
2414
+ /* @__PURE__ */ jsxs("span", { className: "ds:text-fg-2 ds:text-sm ds:font-medium ds:tabular", children: [
2415
+ method === "bank" ? "Bank account" : "Card",
2416
+ " \u2022\u2022\u2022\u2022 ",
2417
+ capturedLast4
2418
+ ] }),
2419
+ /* @__PURE__ */ jsx(CheckIcon, { className: "ds:text-success-fg ds:ml-auto ds:size-4", "aria-hidden": "true" })
2420
+ ] }) : /* @__PURE__ */ jsx("div", { className: "ds:border-rule ds:text-fg-4 ds:flex ds:h-11 ds:items-center ds:rounded-[10px] ds:border ds:border-dashed ds:px-3.5 ds:text-sm", children: method === "bank" ? "Bank account details" : "Card number" })) })
2421
+ ]
2422
+ }
2423
+ );
2424
+ }
2425
+ );
2426
+ ProposalPaymentCapture.displayName = "ProposalPaymentCapture";
2427
+ var Grid = forwardRef(function Grid2({
2428
+ columns,
2429
+ rows,
2430
+ value,
2431
+ onChange,
2432
+ ariaLabel,
2433
+ rowHeaderLabel,
2434
+ currencySymbol = "$",
2435
+ minWidth = 560,
2436
+ disabled = false,
2437
+ className,
2438
+ ...props
2439
+ }, ref) {
2440
+ const updateCell = (rowKey, colKey, nextValue) => {
2441
+ onChange({
2442
+ ...value,
2443
+ [rowKey]: { ...value[rowKey] ?? {}, [colKey]: nextValue }
2444
+ });
2445
+ };
2446
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("ds:overflow-x-auto", className), ...props, children: /* @__PURE__ */ jsxs(
2447
+ "div",
2448
+ {
2449
+ role: "group",
2450
+ "aria-label": ariaLabel,
2451
+ className: "ds:grid ds:gap-2",
2452
+ style: {
2453
+ minWidth: `${minWidth}px`,
2454
+ gridTemplateColumns: `minmax(120px,max-content) ${columns.map((column) => `minmax(0, ${column.width ?? 1}fr)`).join(" ")}`
2455
+ },
2456
+ children: [
2457
+ rowHeaderLabel ? /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:flex ds:items-end ds:px-1 ds:text-[12px] ds:font-semibold", children: rowHeaderLabel }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true" }),
2458
+ columns.map((column) => /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:flex ds:items-end ds:px-1 ds:text-[12px] ds:font-semibold", children: column.label }, column.key)),
2459
+ rows.map((row) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
2460
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:flex ds:items-center ds:text-[13px] ds:font-semibold", children: row.label }),
2461
+ columns.map((column) => /* @__PURE__ */ jsx(
2462
+ Input,
2463
+ {
2464
+ type: column.inputType === "date" ? "date" : "text",
2465
+ value: value[row.key]?.[column.key] ?? "",
2466
+ onChange: (event) => updateCell(row.key, column.key, event.target.value),
2467
+ placeholder: column.placeholder,
2468
+ "aria-label": [ariaLabel, row.label, column.label].filter(Boolean).join(" "),
2469
+ disabled,
2470
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]",
2471
+ inputMode: column.inputType === "number" || column.inputType === "currency" ? "decimal" : void 0,
2472
+ prefixIcon: column.inputType === "currency" ? /* @__PURE__ */ jsx("span", { className: "ds:text-xs ds:font-semibold", children: currencySymbol }) : void 0
2473
+ },
2474
+ column.key
2475
+ ))
2476
+ ] }, row.key))
2477
+ ]
2478
+ }
2479
+ ) });
2480
+ });
2481
+ Grid.displayName = "Grid";
2482
+ var QUESTION_TYPE_CONTRACT_VERSION = 1;
2483
+ var QUESTION_TYPES = [
2484
+ "short-text",
2485
+ "long-text",
2486
+ "email",
2487
+ "phone",
2488
+ "ssn-sin",
2489
+ "date",
2490
+ "number",
2491
+ "currency",
2492
+ "percentage",
2493
+ "single-choice",
2494
+ "multi-choice",
2495
+ "yes-no",
2496
+ "dropdown",
2497
+ "multi-select",
2498
+ "address",
2499
+ "file-upload",
2500
+ "table",
2501
+ "repeater",
2502
+ "signature",
2503
+ "section-header",
2504
+ "consent-checkbox",
2505
+ "name",
2506
+ "labeled-table",
2507
+ "number-stepper"
2508
+ ];
2509
+ var defaultOptions = [
2510
+ { value: "yes", label: "Yes" },
2511
+ { value: "no", label: "No" },
2512
+ { value: "not-sure", label: "Not sure" }
2513
+ ];
2514
+ var Questions = forwardRef(function Questions2({
2515
+ index,
2516
+ title,
2517
+ description,
2518
+ type = "short-text",
2519
+ required = false,
2520
+ chrome = "card",
2521
+ sectionLabel,
2522
+ hideHeader = false,
2523
+ options = defaultOptions,
2524
+ value = "",
2525
+ values = [],
2526
+ placeholder,
2527
+ help,
2528
+ addressValue = {},
2529
+ nameValue = {},
2530
+ showSuffix = true,
2531
+ tableColumns = [],
2532
+ tableRows = [],
2533
+ labeledColumns = [],
2534
+ labeledRows = [],
2535
+ labeledValue = {},
2536
+ files = [],
2537
+ accept,
2538
+ maxSize,
2539
+ multiple,
2540
+ currencySymbol = "$",
2541
+ min = 0,
2542
+ max,
2543
+ step = 1,
2544
+ countLabel,
2545
+ itemNoun,
2546
+ onValueChange,
2547
+ onValuesChange,
2548
+ onAddressChange,
2549
+ onNameChange,
2550
+ onLabeledChange,
2551
+ onTableRowsChange,
2552
+ onFilesSelected,
2553
+ onFileRemove,
2554
+ className,
2555
+ ...props
2556
+ }, ref) {
2557
+ const humanIndex = typeof index === "number" ? index + 1 : void 0;
2558
+ const isSectionHeader = type === "section-header";
2559
+ const isPlain = chrome === "plain" || isSectionHeader;
2560
+ const showHeader = isSectionHeader || !hideHeader;
2561
+ const toggleOption = (optionValue, checked) => {
2562
+ const nextValues = checked ? Array.from(/* @__PURE__ */ new Set([...values, optionValue])) : values.filter((item) => item !== optionValue);
2563
+ onValuesChange?.(nextValues);
2564
+ };
2565
+ const updateAddress = (key, nextValue) => {
2566
+ onAddressChange?.({ ...addressValue, [key]: nextValue });
2567
+ };
2568
+ const updateName = (key, nextValue) => {
2569
+ onNameChange?.({ ...nameValue, [key]: nextValue });
2570
+ };
2571
+ const updateRow = (rowIndex, key, nextValue) => {
2572
+ onTableRowsChange?.(
2573
+ tableRows.map((row, index2) => index2 === rowIndex ? { ...row, [key]: nextValue } : row)
2574
+ );
2575
+ };
2576
+ const emptyRow = () => tableColumns.reduce((row, column) => ({ ...row, [column.key]: "" }), {});
2577
+ const addRow = () => {
2578
+ onTableRowsChange?.([...tableRows, emptyRow()]);
2579
+ };
2580
+ const removeRow = (rowIndex) => {
2581
+ onTableRowsChange?.(tableRows.filter((_, index2) => index2 !== rowIndex));
2582
+ };
2583
+ const setRowCount = (nextCount) => {
2584
+ const clamped = Math.max(min, max != null ? Math.min(nextCount, max) : nextCount);
2585
+ if (clamped > tableRows.length) {
2586
+ const added = Array.from({ length: clamped - tableRows.length }, emptyRow);
2587
+ onTableRowsChange?.([...tableRows, ...added]);
2588
+ } else if (clamped < tableRows.length) {
2589
+ onTableRowsChange?.(tableRows.slice(0, clamped));
2590
+ }
2591
+ };
2592
+ return /* @__PURE__ */ jsxs(
2593
+ "section",
2594
+ {
2595
+ ref,
2596
+ className: cn(
2597
+ "ds:font-body",
2598
+ isPlain ? "ds:bg-transparent" : "ds:border-rule ds:bg-surface ds:shadow-card ds:rounded-[18px] ds:border ds:p-5",
2599
+ className
2600
+ ),
2601
+ ...props,
2602
+ children: [
2603
+ showHeader && /* @__PURE__ */ jsxs("div", { className: cn("ds:flex ds:items-start ds:gap-3", !isSectionHeader && "ds:mb-4"), children: [
2604
+ humanIndex && !isPlain && /* @__PURE__ */ jsx(
2605
+ "span",
2606
+ {
2607
+ "aria-hidden": "true",
2608
+ className: "ds:bg-brand-bg ds:text-brand ds:grid ds:size-7 ds:shrink-0 ds:place-items-center ds:rounded-full ds:text-xs ds:font-bold",
2609
+ children: humanIndex
2610
+ }
2611
+ ),
2612
+ /* @__PURE__ */ jsxs("div", { className: "ds:min-w-0 ds:flex-1", children: [
2613
+ (sectionLabel || isSectionHeader) && /* @__PURE__ */ jsx("p", { className: "ds:text-brand ds:mb-1 ds:text-[11px] ds:font-bold ds:tracking-[0.12em] ds:uppercase", children: sectionLabel }),
2614
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:flex-wrap ds:items-center ds:gap-2", children: [
2615
+ /* @__PURE__ */ jsx(
2616
+ "h3",
2617
+ {
2618
+ className: cn(
2619
+ "ds:text-fg",
2620
+ isSectionHeader ? "ds:text-[22px] ds:leading-7 ds:font-bold" : "ds:text-[14px] ds:leading-5 ds:font-bold"
2621
+ ),
2622
+ children: title
2623
+ }
2624
+ ),
2625
+ help && /* @__PURE__ */ jsx(HelpTip, { title: help.title ?? title, body: help.body }),
2626
+ required && /* @__PURE__ */ jsx("span", { className: "ds:bg-brand-bg ds:text-brand ds:rounded-full ds:px-2 ds:py-0.5 ds:text-[11px] ds:font-bold", children: "Required" })
2627
+ ] }),
2628
+ description && type !== "consent-checkbox" && /* @__PURE__ */ jsx("p", { className: "ds:text-fg-3 ds:mt-1 ds:text-[13px] ds:leading-5", children: description })
2629
+ ] })
2630
+ ] }),
2631
+ type === "section-header" && null,
2632
+ type === "short-text" && /* @__PURE__ */ jsx(
2633
+ Input,
2634
+ {
2635
+ value,
2636
+ onChange: (event) => onValueChange?.(event.target.value),
2637
+ placeholder: placeholder ?? "Type your answer",
2638
+ "aria-label": title,
2639
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2640
+ }
2641
+ ),
2642
+ type === "email" && /* @__PURE__ */ jsx(
2643
+ Input,
2644
+ {
2645
+ type: "email",
2646
+ value,
2647
+ onChange: (event) => onValueChange?.(event.target.value),
2648
+ placeholder: placeholder ?? "client@example.com",
2649
+ "aria-label": title,
2650
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2651
+ }
2652
+ ),
2653
+ type === "phone" && /* @__PURE__ */ jsx(
2654
+ Input,
2655
+ {
2656
+ type: "tel",
2657
+ value,
2658
+ onChange: (event) => onValueChange?.(event.target.value),
2659
+ placeholder: placeholder ?? "(555) 123-4567",
2660
+ "aria-label": title,
2661
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2662
+ }
2663
+ ),
2664
+ type === "ssn-sin" && /* @__PURE__ */ jsx(
2665
+ Input,
2666
+ {
2667
+ value,
2668
+ onChange: (event) => onValueChange?.(event.target.value),
2669
+ placeholder: placeholder ?? "Enter SSN or SIN",
2670
+ "aria-label": title,
2671
+ inputMode: "numeric",
2672
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2673
+ }
2674
+ ),
2675
+ type === "date" && /* @__PURE__ */ jsx(
2676
+ Input,
2677
+ {
2678
+ type: "date",
2679
+ value,
2680
+ onChange: (event) => onValueChange?.(event.target.value),
2681
+ "aria-label": title,
2682
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2683
+ }
2684
+ ),
2685
+ type === "number" && /* @__PURE__ */ jsx(
2686
+ Input,
2687
+ {
2688
+ type: "number",
2689
+ value,
2690
+ onChange: (event) => onValueChange?.(event.target.value),
2691
+ placeholder: placeholder ?? "0",
2692
+ "aria-label": title,
2693
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2694
+ }
2695
+ ),
2696
+ type === "number-stepper" && /* @__PURE__ */ jsx(
2697
+ NumberStepper,
2698
+ {
2699
+ value: Number(value) || 0,
2700
+ onValueChange: (next) => onValueChange?.(String(next)),
2701
+ min,
2702
+ max,
2703
+ step,
2704
+ ariaLabel: title
2705
+ }
2706
+ ),
2707
+ type === "currency" && /* @__PURE__ */ jsx(
2708
+ Input,
2709
+ {
2710
+ value,
2711
+ onChange: (event) => onValueChange?.(event.target.value),
2712
+ placeholder: placeholder ?? "0.00",
2713
+ "aria-label": title,
2714
+ inputMode: "decimal",
2715
+ prefixIcon: /* @__PURE__ */ jsx("span", { className: "ds:text-xs ds:font-semibold", children: currencySymbol }),
2716
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2717
+ }
2718
+ ),
2719
+ type === "percentage" && /* @__PURE__ */ jsx(
2720
+ Input,
2721
+ {
2722
+ value,
2723
+ onChange: (event) => onValueChange?.(event.target.value),
2724
+ placeholder: placeholder ?? "0",
2725
+ "aria-label": title,
2726
+ inputMode: "decimal",
2727
+ suffixIcon: /* @__PURE__ */ jsx("span", { className: "ds:text-xs ds:font-semibold", children: "%" }),
2728
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2729
+ }
2730
+ ),
2731
+ type === "long-text" && /* @__PURE__ */ jsx(
2732
+ Textarea,
2733
+ {
2734
+ value,
2735
+ onChange: (event) => onValueChange?.(event.target.value),
2736
+ placeholder: placeholder ?? "Write a detailed answer",
2737
+ "aria-label": title,
2738
+ autoResize: true,
2739
+ className: "ds:rounded-[12px] ds:text-[14px]"
2740
+ }
2741
+ ),
2742
+ (type === "single-choice" || type === "yes-no") && /* @__PURE__ */ jsx(
2743
+ "div",
2744
+ {
2745
+ className: cn(
2746
+ "ds:grid ds:gap-3",
2747
+ type === "yes-no" ? "ds:grid-cols-[repeat(auto-fit,minmax(78px,max-content))]" : ""
2748
+ ),
2749
+ role: "radiogroup",
2750
+ "aria-label": title,
2751
+ children: (type === "yes-no" ? [
2752
+ { value: "yes", label: "Yes" },
2753
+ { value: "no", label: "No" }
2754
+ ] : options).map((option) => /* @__PURE__ */ jsx(
2755
+ QuestionOptionButton,
2756
+ {
2757
+ option,
2758
+ selected: value === option.value,
2759
+ compact: type === "yes-no",
2760
+ role: "radio",
2761
+ "aria-checked": value === option.value,
2762
+ onClick: () => onValueChange?.(option.value)
2763
+ },
2764
+ option.value
2765
+ ))
2766
+ }
2767
+ ),
2768
+ type === "dropdown" && /* @__PURE__ */ jsx(
2769
+ Select,
2770
+ {
2771
+ options,
2772
+ value,
2773
+ onValueChange,
2774
+ placeholder: placeholder ?? "Select an option",
2775
+ "aria-label": title
2776
+ }
2777
+ ),
2778
+ (type === "multi-choice" || type === "multi-select") && /* @__PURE__ */ jsx("div", { className: "ds:grid ds:gap-3", role: "group", "aria-label": title, children: options.map((option) => /* @__PURE__ */ jsx(
2779
+ QuestionOptionButton,
2780
+ {
2781
+ option,
2782
+ selected: values.includes(option.value),
2783
+ role: "checkbox",
2784
+ "aria-checked": values.includes(option.value),
2785
+ onClick: () => toggleOption(option.value, !values.includes(option.value))
2786
+ },
2787
+ option.value
2788
+ )) }),
2789
+ type === "address" && /* @__PURE__ */ jsxs("div", { className: "ds:grid ds:gap-3 ds:sm:grid-cols-2", children: [
2790
+ /* @__PURE__ */ jsx(
2791
+ Input,
2792
+ {
2793
+ value: addressValue.line1 ?? "",
2794
+ onChange: (event) => updateAddress("line1", event.target.value),
2795
+ placeholder: "Street address",
2796
+ "aria-label": `${title} street address`,
2797
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px] ds:sm:col-span-2"
2798
+ }
2799
+ ),
2800
+ /* @__PURE__ */ jsx(
2801
+ Input,
2802
+ {
2803
+ value: addressValue.line2 ?? "",
2804
+ onChange: (event) => updateAddress("line2", event.target.value),
2805
+ placeholder: "Apt, suite, unit",
2806
+ "aria-label": `${title} address line 2`,
2807
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px] ds:sm:col-span-2"
2808
+ }
2809
+ ),
2810
+ /* @__PURE__ */ jsx(
2811
+ Input,
2812
+ {
2813
+ value: addressValue.city ?? "",
2814
+ onChange: (event) => updateAddress("city", event.target.value),
2815
+ placeholder: "City",
2816
+ "aria-label": `${title} city`,
2817
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2818
+ }
2819
+ ),
2820
+ /* @__PURE__ */ jsx(
2821
+ Input,
2822
+ {
2823
+ value: addressValue.region ?? "",
2824
+ onChange: (event) => updateAddress("region", event.target.value),
2825
+ placeholder: "State / Province",
2826
+ "aria-label": `${title} state or province`,
2827
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2828
+ }
2829
+ ),
2830
+ /* @__PURE__ */ jsx(
2831
+ Input,
2832
+ {
2833
+ value: addressValue.postalCode ?? "",
2834
+ onChange: (event) => updateAddress("postalCode", event.target.value),
2835
+ placeholder: "ZIP / Postal code",
2836
+ "aria-label": `${title} zip or postal code`,
2837
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2838
+ }
2839
+ ),
2840
+ /* @__PURE__ */ jsx(
2841
+ Input,
2842
+ {
2843
+ value: addressValue.country ?? "",
2844
+ onChange: (event) => updateAddress("country", event.target.value),
2845
+ placeholder: "Country",
2846
+ "aria-label": `${title} country`,
2847
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
2848
+ }
2849
+ )
2850
+ ] }),
2851
+ type === "name" && /* @__PURE__ */ jsxs("div", { className: "ds:grid ds:gap-3 ds:sm:grid-cols-6", children: [
2852
+ /* @__PURE__ */ jsx(
2853
+ Input,
2854
+ {
2855
+ value: nameValue.first ?? "",
2856
+ onChange: (event) => updateName("first", event.target.value),
2857
+ placeholder: "First name",
2858
+ "aria-label": `${title} first name`,
2859
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px] ds:sm:col-span-2"
2860
+ }
2861
+ ),
2862
+ /* @__PURE__ */ jsx(
2863
+ Input,
2864
+ {
2865
+ value: nameValue.middle ?? "",
2866
+ onChange: (event) => updateName("middle", event.target.value),
2867
+ placeholder: "Middle",
2868
+ "aria-label": `${title} middle name`,
2869
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px] ds:sm:col-span-1"
2870
+ }
2871
+ ),
2872
+ /* @__PURE__ */ jsx(
2873
+ Input,
2874
+ {
2875
+ value: nameValue.last ?? "",
2876
+ onChange: (event) => updateName("last", event.target.value),
2877
+ placeholder: "Last name",
2878
+ "aria-label": `${title} last name`,
2879
+ className: cn(
2880
+ "ds:h-11 ds:rounded-[12px] ds:text-[14px]",
2881
+ showSuffix ? "ds:sm:col-span-2" : "ds:sm:col-span-3"
2882
+ )
2883
+ }
2884
+ ),
2885
+ showSuffix && /* @__PURE__ */ jsx(
2886
+ Input,
2887
+ {
2888
+ value: nameValue.suffix ?? "",
2889
+ onChange: (event) => updateName("suffix", event.target.value),
2890
+ placeholder: "Suffix",
2891
+ "aria-label": `${title} suffix`,
2892
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px] ds:sm:col-span-1"
2893
+ }
2894
+ )
2895
+ ] }),
2896
+ type === "labeled-table" && /* @__PURE__ */ jsx(
2897
+ Grid,
2898
+ {
2899
+ ariaLabel: title,
2900
+ currencySymbol,
2901
+ columns: labeledColumns.map((column) => ({
2902
+ key: column.key,
2903
+ label: column.title,
2904
+ inputType: column.inputType,
2905
+ width: column.width
2906
+ })),
2907
+ rows: labeledRows.map((row) => ({ key: row.key, label: row.title })),
2908
+ value: labeledValue,
2909
+ onChange: (next) => onLabeledChange?.(next)
2910
+ }
2911
+ ),
2912
+ type === "file-upload" && /* @__PURE__ */ jsxs("div", { className: "ds:grid ds:gap-3", children: [
2913
+ /* @__PURE__ */ jsx(
2914
+ FileUpload,
2915
+ {
2916
+ accept,
2917
+ maxSize,
2918
+ multiple,
2919
+ onFilesSelected
2920
+ }
2921
+ ),
2922
+ files.length > 0 && /* @__PURE__ */ jsx("div", { className: "ds:grid ds:gap-2", children: files.map((file, fileIndex) => /* @__PURE__ */ jsx(
2923
+ FileChip,
2924
+ {
2925
+ name: file.name,
2926
+ meta: file.size ? formatBytes(file.size) : void 0,
2927
+ kind: file.kind ?? "doc",
2928
+ action: onFileRemove ? /* @__PURE__ */ jsx(
2929
+ Button,
2930
+ {
2931
+ type: "button",
2932
+ variant: "ghost",
2933
+ size: "icon-sm",
2934
+ onClick: () => onFileRemove(file, fileIndex),
2935
+ "aria-label": `Remove ${file.name}`,
2936
+ className: "ds:hover:text-danger-fg",
2937
+ children: /* @__PURE__ */ jsx(TrashIcon, { size: 14, "aria-hidden": "true" })
2938
+ }
2939
+ ) : void 0
2940
+ },
2941
+ `${file.name}-${file.size ?? "unknown"}`
2942
+ )) })
2943
+ ] }),
2944
+ (type === "table" || type === "repeater") && /* @__PURE__ */ jsxs("div", { className: "ds:grid ds:gap-3", children: [
2945
+ countLabel && /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-3", children: [
2946
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-[13px] ds:font-semibold", children: countLabel }),
2947
+ /* @__PURE__ */ jsx(
2948
+ NumberStepper,
2949
+ {
2950
+ value: tableRows.length,
2951
+ onValueChange: setRowCount,
2952
+ min,
2953
+ max,
2954
+ step,
2955
+ ariaLabel: countLabel
2956
+ }
2957
+ )
2958
+ ] }),
2959
+ tableRows.map((row, rowIndex) => /* @__PURE__ */ jsxs("div", { className: "ds:border-rule ds:bg-surface-2 ds:rounded-[16px] ds:border ds:p-4", children: [
2960
+ /* @__PURE__ */ jsxs("div", { className: "ds:mb-3 ds:flex ds:items-center ds:justify-between ds:gap-3", children: [
2961
+ /* @__PURE__ */ jsxs("span", { className: "ds:text-fg ds:text-[13px] ds:font-semibold", children: [
2962
+ type === "repeater" ? itemNoun ?? "Item" : "Row",
2963
+ " ",
2964
+ rowIndex + 1
2965
+ ] }),
2966
+ !countLabel && tableRows.length > 1 && /* @__PURE__ */ jsx(
2967
+ Button,
2968
+ {
2969
+ type: "button",
2970
+ variant: "ghost",
2971
+ size: "icon-sm",
2972
+ onClick: () => removeRow(rowIndex),
2973
+ "aria-label": `Remove row ${rowIndex + 1}`,
2974
+ children: /* @__PURE__ */ jsx(TrashIcon, { size: 14, "aria-hidden": "true" })
2975
+ }
2976
+ )
2977
+ ] }),
2978
+ /* @__PURE__ */ jsx("div", { className: "ds:grid ds:gap-3 ds:sm:grid-cols-2", children: tableColumns.map((column) => /* @__PURE__ */ jsx(
2979
+ Input,
2980
+ {
2981
+ type: column.inputType === "date" ? "date" : "text",
2982
+ value: row[column.key] ?? "",
2983
+ onChange: (event) => updateRow(rowIndex, column.key, event.target.value),
2984
+ placeholder: column.placeholder ?? column.label,
2985
+ "aria-label": `${title} ${column.label} row ${rowIndex + 1}`,
2986
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]",
2987
+ inputMode: column.inputType === "number" || column.inputType === "currency" ? "decimal" : void 0,
2988
+ prefixIcon: column.inputType === "currency" ? /* @__PURE__ */ jsx("span", { className: "ds:text-xs ds:font-semibold", children: currencySymbol }) : void 0
2989
+ },
2990
+ column.key
2991
+ )) })
2992
+ ] }, rowIndex)),
2993
+ !countLabel && /* @__PURE__ */ jsxs(
2994
+ Button,
2995
+ {
2996
+ type: "button",
2997
+ variant: "dashed",
2998
+ size: "sm",
2999
+ onClick: addRow,
3000
+ iconLeft: /* @__PURE__ */ jsx(PlusIcon, { size: 14 }),
3001
+ children: [
3002
+ "Add ",
3003
+ type === "repeater" ? "item" : "row"
3004
+ ]
3005
+ }
3006
+ )
3007
+ ] }),
3008
+ type === "signature" && /* @__PURE__ */ jsxs("div", { className: "ds:border-rule-strong ds:bg-surface-2 ds:rounded-[16px] ds:border ds:border-dashed ds:p-5", children: [
3009
+ /* @__PURE__ */ jsxs("div", { className: "ds:text-fg-2 ds:mb-3 ds:flex ds:items-center ds:gap-2", children: [
3010
+ /* @__PURE__ */ jsx(PenSignIcon, { size: 18, "aria-hidden": "true" }),
3011
+ /* @__PURE__ */ jsx("span", { className: "ds:text-[13px] ds:font-semibold", children: "Signature" })
3012
+ ] }),
3013
+ /* @__PURE__ */ jsx(
3014
+ Input,
3015
+ {
3016
+ value,
3017
+ onChange: (event) => onValueChange?.(event.target.value),
3018
+ placeholder: placeholder ?? "Type full legal name",
3019
+ "aria-label": title,
3020
+ className: "ds:h-11 ds:rounded-[12px] ds:text-[14px]"
3021
+ }
3022
+ )
3023
+ ] }),
3024
+ type === "consent-checkbox" && /* @__PURE__ */ jsx(
3025
+ Checkbox,
3026
+ {
3027
+ label: description ?? title,
3028
+ checked: value === "true",
3029
+ onCheckedChange: (checked) => onValueChange?.(checked === true ? "true" : "false")
3030
+ }
3031
+ )
3032
+ ]
3033
+ }
3034
+ );
3035
+ });
3036
+ Questions.displayName = "Questions";
3037
+ function QuestionOptionButton({
3038
+ option,
3039
+ selected,
3040
+ compact,
3041
+ className,
3042
+ ...props
3043
+ }) {
3044
+ return /* @__PURE__ */ jsxs(
3045
+ "button",
3046
+ {
3047
+ type: "button",
3048
+ disabled: option.disabled,
3049
+ className: cn(
3050
+ "ds:group ds:bg-surface ds:flex ds:w-full ds:items-center ds:gap-3 ds:border ds:text-left",
3051
+ "ds:transition-[border-color,background-color,color,box-shadow,transform] ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)]",
3052
+ "ds:motion-reduce:transition-none",
3053
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
3054
+ "ds:disabled:bg-bg-disabled ds:disabled:text-fg-disabled ds:disabled:cursor-not-allowed",
3055
+ compact ? "ds:h-10 ds:max-w-max ds:rounded-[10px] ds:px-3" : "ds:min-h-16 ds:rounded-[12px] ds:px-7 ds:py-4",
3056
+ selected ? compact ? "ds:border-brand ds:bg-brand-bg ds:text-brand ds:shadow-xs" : "ds:border-brand-line ds:bg-brand-bg ds:text-brand ds:hover:bg-brand-bg-hover ds:shadow-xs" : "ds:border-rule-strong ds:text-fg ds:hover:border-brand-line ds:hover:bg-brand-bg/40",
3057
+ className
3058
+ ),
3059
+ ...props,
3060
+ children: [
3061
+ /* @__PURE__ */ jsx(
3062
+ "span",
3063
+ {
3064
+ "aria-hidden": "true",
3065
+ className: cn(
3066
+ "ds:grid ds:shrink-0 ds:place-items-center ds:rounded-full ds:border ds:transition-colors ds:duration-[var(--duration-fast)] ds:motion-reduce:transition-none",
3067
+ compact ? "ds:size-5" : "ds:size-4",
3068
+ selected ? "ds:border-brand ds:bg-brand ds:text-fg-on-brand" : "ds:border-rule-strong ds:bg-surface ds:group-hover:border-brand-line ds:text-transparent"
3069
+ ),
3070
+ children: selected && /* @__PURE__ */ jsx(CheckCircleSolidIcon, { size: compact ? 18 : 14 })
3071
+ }
3072
+ ),
3073
+ /* @__PURE__ */ jsxs("span", { className: "ds:flex ds:min-w-0 ds:flex-1 ds:items-center ds:gap-1.5", children: [
3074
+ /* @__PURE__ */ jsx("span", { className: cn("ds:truncate ds:font-bold", compact ? "ds:text-[13px]" : "ds:text-[15px]"), children: option.label }),
3075
+ option.helpText && /* @__PURE__ */ jsx(HelpTip, { title: option.label, body: option.helpText })
3076
+ ] }),
3077
+ option.formLabel && !compact && /* @__PURE__ */ jsx(
3078
+ "span",
3079
+ {
3080
+ className: cn(
3081
+ "ds:ml-auto ds:shrink-0 ds:text-right ds:text-[13px] ds:font-semibold",
3082
+ selected ? "ds:text-brand" : "ds:text-fg-3"
3083
+ ),
3084
+ children: option.formLabel
3085
+ }
3086
+ )
3087
+ ]
3088
+ }
3089
+ );
3090
+ }
3091
+ function formatBytes(bytes) {
3092
+ if (bytes < 1024) return `${bytes} B`;
3093
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
3094
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
3095
+ }
3096
+ function HelpTip({ title, body }) {
3097
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
3098
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "ds:text-brand ds:inline-flex ds:shrink-0 ds:cursor-help", children: /* @__PURE__ */ jsx(HelpCircleIcon, { size: 14, "aria-hidden": "true" }) }) }),
3099
+ /* @__PURE__ */ jsxs(
3100
+ TooltipContent,
3101
+ {
3102
+ side: "top",
3103
+ align: "center",
3104
+ sideOffset: 12,
3105
+ className: cn(
3106
+ "ds:border-rule ds:bg-surface ds:shadow-pop ds:relative ds:max-w-[352px] ds:rounded-[7px] ds:p-5 ds:text-left",
3107
+ "ds:after:border-rule ds:after:bg-surface ds:after:absolute ds:after:top-full ds:after:left-1/2 ds:after:size-4 ds:after:-translate-x-1/2 ds:after:-translate-y-1/2 ds:after:rotate-45 ds:after:border-r ds:after:border-b ds:after:content-['']"
3108
+ ),
3109
+ children: [
3110
+ /* @__PURE__ */ jsx("div", { className: "ds:text-fg ds:text-[15px] ds:leading-5 ds:font-bold", children: title }),
3111
+ /* @__PURE__ */ jsx("p", { className: "ds:text-fg-2 ds:mt-3 ds:text-[14px] ds:leading-6", children: body })
3112
+ ]
3113
+ }
3114
+ )
3115
+ ] });
3116
+ }
3117
+ function NumberStepper({
3118
+ value,
3119
+ onValueChange,
3120
+ min = 0,
3121
+ max,
3122
+ step = 1,
3123
+ ariaLabel
3124
+ }) {
3125
+ const clamp = (next) => Math.max(min, max != null ? Math.min(next, max) : next);
3126
+ const current = clamp(Number.isFinite(value) ? value : min);
3127
+ const atMin = current <= min;
3128
+ const atMax = max != null && current >= max;
3129
+ return /* @__PURE__ */ jsxs(
3130
+ "div",
3131
+ {
3132
+ className: "ds:inline-flex ds:items-center ds:gap-2",
3133
+ role: "spinbutton",
3134
+ "aria-valuenow": current,
3135
+ "aria-valuemin": min,
3136
+ "aria-valuemax": max,
3137
+ "aria-label": ariaLabel,
3138
+ children: [
3139
+ /* @__PURE__ */ jsx(
3140
+ Button,
3141
+ {
3142
+ type: "button",
3143
+ variant: "secondary",
3144
+ size: "icon-sm",
3145
+ onClick: () => onValueChange(clamp(current - step)),
3146
+ disabled: atMin,
3147
+ "aria-label": "Decrease",
3148
+ children: /* @__PURE__ */ jsx(MinusIcon, { size: 14, "aria-hidden": "true" })
3149
+ }
3150
+ ),
3151
+ /* @__PURE__ */ jsx(
3152
+ Input,
3153
+ {
3154
+ value: String(current),
3155
+ onChange: (event) => {
3156
+ const parsed = Number(event.target.value.replace(/[^0-9-]/g, ""));
3157
+ onValueChange(clamp(Number.isFinite(parsed) ? parsed : min));
3158
+ },
3159
+ inputMode: "numeric",
3160
+ "aria-label": ariaLabel,
3161
+ className: "ds:h-11 ds:w-14 ds:rounded-[12px] ds:text-center ds:text-[14px] ds:tabular-nums"
3162
+ }
3163
+ ),
3164
+ /* @__PURE__ */ jsx(
3165
+ Button,
3166
+ {
3167
+ type: "button",
3168
+ variant: "secondary",
3169
+ size: "icon-sm",
3170
+ onClick: () => onValueChange(clamp(current + step)),
3171
+ disabled: atMax,
3172
+ "aria-label": "Increase",
3173
+ children: /* @__PURE__ */ jsx(PlusIcon, { size: 14, "aria-hidden": "true" })
3174
+ }
3175
+ )
3176
+ ]
3177
+ }
3178
+ );
3179
+ }
3180
+ var SidebarContext = React6.createContext(null);
3181
+ var NOOP_CONTEXT = {
3182
+ state: "expanded",
3183
+ setState: () => {
3184
+ },
3185
+ toggle: () => {
3186
+ },
3187
+ collapsible: false,
3188
+ peekLockCount: 0,
3189
+ acquirePeekLock: () => () => {
3190
+ }
3191
+ };
3192
+ function useSidebarState() {
3193
+ return React6.useContext(SidebarContext) ?? NOOP_CONTEXT;
3194
+ }
3195
+ var DEFAULT_SHORTCUT = "Mod+\\";
3196
+ var asState = (value) => value === "rail" || value === "expanded" ? value : null;
3197
+ function readStorage(key, storage) {
3198
+ if (!key || typeof document === "undefined") return null;
3199
+ try {
3200
+ if (storage === "cookie") {
3201
+ const match = document.cookie.match(
3202
+ new RegExp(`(?:^|;\\s*)${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)`)
3203
+ );
3204
+ return asState(match ? decodeURIComponent(match[1] ?? "") : null);
3205
+ }
3206
+ return asState(window.localStorage.getItem(key));
3207
+ } catch {
3208
+ return null;
3209
+ }
3210
+ }
3211
+ function writeStorage(key, storage, next) {
3212
+ if (typeof document === "undefined") return;
3213
+ try {
3214
+ if (storage === "cookie") {
3215
+ document.cookie = `${key}=${next}; path=/; max-age=31536000; samesite=lax`;
3216
+ return;
3217
+ }
3218
+ window.localStorage.setItem(key, next);
3219
+ } catch {
3220
+ }
3221
+ }
3222
+ function SidebarProvider({
3223
+ children,
3224
+ state: controlled,
3225
+ defaultState = "expanded",
3226
+ onStateChange,
3227
+ storageKey,
3228
+ storage = "localStorage",
3229
+ shortcut = DEFAULT_SHORTCUT
3230
+ }) {
3231
+ const [uncontrolled, setUncontrolled] = React6.useState(
3232
+ controlled ?? defaultState
3233
+ );
3234
+ React6.useEffect(() => {
3235
+ if (controlled !== void 0) return;
3236
+ const stored = readStorage(storageKey, storage);
3237
+ if (stored && stored !== uncontrolled) setUncontrolled(stored);
3238
+ }, []);
3239
+ const state = controlled ?? uncontrolled;
3240
+ const setState = React6.useCallback(
3241
+ (next) => {
3242
+ if (controlled === void 0) setUncontrolled(next);
3243
+ onStateChange?.(next);
3244
+ if (storageKey) writeStorage(storageKey, storage, next);
3245
+ },
3246
+ [controlled, onStateChange, storageKey, storage]
3247
+ );
3248
+ const toggle = React6.useCallback(() => {
3249
+ setState(state === "expanded" ? "rail" : "expanded");
3250
+ }, [state, setState]);
3251
+ const [peekLockCount, setPeekLockCount] = React6.useState(0);
3252
+ const acquirePeekLock = React6.useCallback(() => {
3253
+ setPeekLockCount((n) => n + 1);
3254
+ let released = false;
3255
+ return () => {
3256
+ if (released) return;
3257
+ released = true;
3258
+ setPeekLockCount((n) => Math.max(0, n - 1));
3259
+ };
3260
+ }, []);
3261
+ React6.useEffect(() => {
3262
+ if (!shortcut) return;
3263
+ const parts = shortcut.split("+");
3264
+ const key = parts.pop() ?? "";
3265
+ const wantMod = parts.includes("Mod");
3266
+ const wantShift = parts.includes("Shift");
3267
+ const wantAlt = parts.includes("Alt");
3268
+ function onKey(e) {
3269
+ const isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform);
3270
+ const mod = isMac ? e.metaKey : e.ctrlKey;
3271
+ if (e.key.toLowerCase() !== key.toLowerCase()) return;
3272
+ if (wantMod !== mod) return;
3273
+ if (wantShift !== e.shiftKey) return;
3274
+ if (wantAlt !== e.altKey) return;
3275
+ e.preventDefault();
3276
+ toggle();
3277
+ }
3278
+ window.addEventListener("keydown", onKey);
3279
+ return () => window.removeEventListener("keydown", onKey);
3280
+ }, [shortcut, toggle]);
3281
+ const value = React6.useMemo(
3282
+ () => ({ state, setState, toggle, collapsible: true, peekLockCount, acquirePeekLock }),
3283
+ [state, setState, toggle, peekLockCount, acquirePeekLock]
3284
+ );
3285
+ return /* @__PURE__ */ jsx(SidebarContext.Provider, { value, children });
3286
+ }
3287
+ SidebarProvider.displayName = "SidebarProvider";
3288
+ var PEEK_ENTER_DELAY_MS = 100;
3289
+ var PEEK_LEAVE_DELAY_MS = 200;
3290
+ var SidebarLabelsHiddenContext = React6.createContext(false);
3291
+ var SidebarPeekEnabledContext = React6.createContext(true);
3292
+ function useCollapsedAttribute() {
3293
+ return React6.useContext(SidebarLabelsHiddenContext) ? { "data-collapsed": "true" } : {};
3294
+ }
3295
+ var Sidebar = React6.forwardRef(function Sidebar2({
3296
+ className,
3297
+ collapsible = false,
3298
+ variant = "classic",
3299
+ peek: peekEnabled = true,
3300
+ onMouseEnter,
3301
+ onMouseLeave,
3302
+ style,
3303
+ children,
3304
+ ...props
3305
+ }, ref) {
3306
+ const isFloating = variant === "floating";
3307
+ const ctx = React6.useContext(SidebarContext);
3308
+ const state = collapsible && ctx ? ctx.state : "expanded";
3309
+ const peekLockCount = collapsible && ctx && peekEnabled ? ctx.peekLockCount : 0;
3310
+ const [peek, setPeek] = React6.useState(false);
3311
+ const enterTimer = React6.useRef(null);
3312
+ const leaveTimer = React6.useRef(null);
3313
+ const clearTimers = React6.useCallback(() => {
3314
+ if (enterTimer.current != null) {
3315
+ window.clearTimeout(enterTimer.current);
3316
+ enterTimer.current = null;
3317
+ }
3318
+ if (leaveTimer.current != null) {
3319
+ window.clearTimeout(leaveTimer.current);
3320
+ leaveTimer.current = null;
3321
+ }
3322
+ }, []);
3323
+ React6.useEffect(() => () => clearTimers(), [clearTimers]);
3324
+ React6.useEffect(() => {
3325
+ if (state === "expanded") {
3326
+ clearTimers();
3327
+ setPeek(false);
3328
+ }
3329
+ }, [state, clearTimers]);
3330
+ const handleEnter = (e) => {
3331
+ onMouseEnter?.(e);
3332
+ if (!peekEnabled) return;
3333
+ if (!collapsible || state !== "rail") return;
3334
+ if (leaveTimer.current != null) {
3335
+ window.clearTimeout(leaveTimer.current);
3336
+ leaveTimer.current = null;
3337
+ }
3338
+ if (peek) return;
3339
+ enterTimer.current = window.setTimeout(() => setPeek(true), PEEK_ENTER_DELAY_MS);
3340
+ };
3341
+ const handleLeave = (e) => {
3342
+ onMouseLeave?.(e);
3343
+ if (!peekEnabled) return;
3344
+ if (!collapsible) return;
3345
+ if (enterTimer.current != null) {
3346
+ window.clearTimeout(enterTimer.current);
3347
+ enterTimer.current = null;
3348
+ }
3349
+ if (!peek) return;
3350
+ leaveTimer.current = window.setTimeout(() => setPeek(false), PEEK_LEAVE_DELAY_MS);
3351
+ };
3352
+ const overlay = state === "rail" && (peek || peekLockCount > 0);
3353
+ const labelsHidden = state === "rail" && !peek && peekLockCount === 0;
3354
+ const effectiveWidth = labelsHidden ? "var(--ds-layout-shell-sidebar-rail-width, var(--shell-sidebar-w-rail))" : "var(--ds-layout-shell-sidebar-width, var(--shell-sidebar-w))";
3355
+ return (
3356
+ // Hover-peek is *enhancement only*: the canonical way to toggle the
3357
+ // sidebar is <SidebarTrigger> (button) or the Mod+\ shortcut, both
3358
+ // fully keyboard- and screen-reader-accessible. The mouse handlers
3359
+ // here exist to widen the column on pointer hover, which has no
3360
+ // keyboard analogue and intentionally so.
3361
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
3362
+ /* @__PURE__ */ jsx(
3363
+ "aside",
3364
+ {
3365
+ ref,
3366
+ "data-state": state,
3367
+ "data-peek": peek ? "true" : void 0,
3368
+ "data-overlay": overlay ? "true" : void 0,
3369
+ "data-labels": labelsHidden ? "hide" : "show",
3370
+ "data-collapsible": collapsible ? "true" : void 0,
3371
+ "data-variant": variant,
3372
+ ...slot(sidebarAnatomy, "root"),
3373
+ onMouseEnter: handleEnter,
3374
+ onMouseLeave: handleLeave,
3375
+ style: { width: effectiveWidth, ...style },
3376
+ className: cn(
3377
+ "ds:group/sidebar group/sidebar ds:scrollbar-thin ds:flex ds:shrink-0 ds:flex-col ds:overflow-y-auto ds:px-3 ds:pt-4 ds:pb-4",
3378
+ // Classic: full-height column flush to the left edge with a right
3379
+ // rule. The legacy look.
3380
+ !isFloating && "ds:h-dvh ds:border-rule ds:bg-bg-2 ds:border-r",
3381
+ // Floating: a detached, rounded card inset from the viewport with a
3382
+ // soft shadow — the modern SaaS pattern. The clear figure/ground gap
3383
+ // (Aesthetic-Usability) reads as its own surface above the canvas.
3384
+ isFloating && "ds:border-rule ds:bg-surface ds:shadow-card ds:m-2.5 ds:h-[calc(100dvh-1.25rem)] ds:rounded-2xl ds:border",
3385
+ // 220ms feels right for a ~192px width sweep — slower than the
3386
+ // 150ms `--duration-fast` (which reads as a snap on this size of
3387
+ // movement) but well short of `--duration-slow` (which feels
3388
+ // sluggish). `will-change` hints the compositor so the column
3389
+ // doesn't repaint every frame mid-transition.
3390
+ "ds:transition-[width,box-shadow] ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
3391
+ "ds:[will-change:width]",
3392
+ // Overlay (hover-peek OR programmatic peek-lock): float above the
3393
+ // canvas without reflowing layout. Driven by `data-overlay` so a
3394
+ // single rule handles both transient sources.
3395
+ "ds:data-[overlay=true]:fixed ds:data-[overlay=true]:top-0 ds:data-[overlay=true]:left-0",
3396
+ "ds:data-[overlay=true]:z-[var(--z-overlay)] ds:data-[overlay=true]:shadow-pop",
3397
+ // Padding is held constant across states so icons keep their
3398
+ // horizontal anchor when the column widens — peek expands the
3399
+ // labels rightward rather than shifting the icons leftward.
3400
+ className
3401
+ ),
3402
+ ...props,
3403
+ children: /* @__PURE__ */ jsx(SidebarPeekEnabledContext.Provider, { value: peekEnabled, children: /* @__PURE__ */ jsx(SidebarLabelsHiddenContext.Provider, { value: labelsHidden, children: collapsible && !peekEnabled ? /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children }) : children }) })
3404
+ }
3405
+ )
3406
+ );
3407
+ });
3408
+ Sidebar.displayName = "Sidebar";
3409
+ var SidebarTrigger = React6.forwardRef(
3410
+ function SidebarTrigger2({
3411
+ className,
3412
+ expandLabel,
3413
+ collapseLabel,
3414
+ onClick,
3415
+ ...props
3416
+ }, ref) {
3417
+ const messages = useDsMessages("sidebar");
3418
+ const ctx = React6.useContext(SidebarContext);
3419
+ if (!ctx) return null;
3420
+ const { state, toggle } = ctx;
3421
+ const label = state === "expanded" ? collapseLabel ?? messages.collapse : expandLabel ?? messages.expand;
3422
+ return /* @__PURE__ */ jsx(
3423
+ "button",
3424
+ {
3425
+ ref,
3426
+ type: "button",
3427
+ "aria-label": label,
3428
+ "aria-expanded": state === "expanded",
3429
+ onClick: (e) => {
3430
+ onClick?.(e);
3431
+ if (!e.defaultPrevented) toggle();
3432
+ },
3433
+ ...slot(sidebarAnatomy, "trigger"),
3434
+ className: cn(
3435
+ "ds:inline-flex ds:size-7 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-md",
3436
+ "ds:text-fg-3 ds:hover:bg-bg-3 ds:hover:text-fg",
3437
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
3438
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
3439
+ "ds:[&_svg]:size-4",
3440
+ className
3441
+ ),
3442
+ ...props,
3443
+ children: state === "expanded" ? /* @__PURE__ */ jsx(PanelLeftCloseIcon, {}) : /* @__PURE__ */ jsx(PanelLeftIcon, {})
3444
+ }
3445
+ );
3446
+ }
3447
+ );
3448
+ SidebarTrigger.displayName = "SidebarTrigger";
3449
+ function useSidebarPeekLock(active) {
3450
+ const ctx = React6.useContext(SidebarContext);
3451
+ React6.useEffect(() => {
3452
+ if (!active || !ctx) return;
3453
+ const release = ctx.acquirePeekLock();
3454
+ return release;
3455
+ }, [active, ctx]);
3456
+ }
3457
+ var SidebarPinButton = React6.forwardRef(
3458
+ function SidebarPinButton2({
3459
+ pinLabel,
3460
+ unpinLabel,
3461
+ className,
3462
+ onClick,
3463
+ ...props
3464
+ }, ref) {
3465
+ const messages = useDsMessages("sidebar");
3466
+ const ctx = React6.useContext(SidebarContext);
3467
+ if (!ctx || !ctx.collapsible) return null;
3468
+ const { state, setState } = ctx;
3469
+ const isPinned = state === "expanded";
3470
+ return /* @__PURE__ */ jsx(
3471
+ "button",
3472
+ {
3473
+ ref,
3474
+ type: "button",
3475
+ "aria-label": isPinned ? unpinLabel ?? messages.unpin : pinLabel ?? messages.pin,
3476
+ "aria-pressed": isPinned,
3477
+ onClick: (e) => {
3478
+ onClick?.(e);
3479
+ if (!e.defaultPrevented) setState(isPinned ? "rail" : "expanded");
3480
+ },
3481
+ ...slot(sidebarAnatomy, "pin"),
3482
+ ...stateAttributes({ selected: isPinned }),
3483
+ className: cn(
3484
+ "ds:inline-flex ds:size-7 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-md",
3485
+ "ds:text-fg-4 ds:hover:bg-bg-3 ds:hover:text-fg ds:aria-pressed:text-fg",
3486
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
3487
+ "ds:focus-visible:outline-none ds:focus-visible:[box-shadow:var(--shadow-focus-ring)]",
3488
+ // Hidden when labels are hidden (rail-no-peek-no-lock). Visible
3489
+ // in every overlay state so users can pin during hover or while
3490
+ // a dropdown holds the column open.
3491
+ "ds:group-data-[labels=hide]/sidebar:hidden",
3492
+ className
3493
+ ),
3494
+ ...props,
3495
+ children: /* @__PURE__ */ jsx(PinGlyph, { size: 14, filled: isPinned, className: "ds:rotate-45" })
3496
+ }
3497
+ );
3498
+ }
3499
+ );
3500
+ SidebarPinButton.displayName = "SidebarPinButton";
3501
+ function PinGlyph({
3502
+ size = 16,
3503
+ filled = false,
3504
+ className
3505
+ }) {
3506
+ return /* @__PURE__ */ jsxs(
3507
+ "svg",
3508
+ {
3509
+ xmlns: "http://www.w3.org/2000/svg",
3510
+ width: size,
3511
+ height: size,
3512
+ viewBox: "0 0 24 24",
3513
+ fill: "none",
3514
+ stroke: "currentColor",
3515
+ strokeWidth: 2,
3516
+ strokeLinecap: "round",
3517
+ strokeLinejoin: "round",
3518
+ "aria-hidden": "true",
3519
+ className,
3520
+ children: [
3521
+ /* @__PURE__ */ jsx("path", { d: "M12 17v5" }),
3522
+ /* @__PURE__ */ jsx(
3523
+ "path",
3524
+ {
3525
+ d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z",
3526
+ fill: filled ? "currentColor" : "none"
3527
+ }
3528
+ )
3529
+ ]
3530
+ }
3531
+ );
3532
+ }
3533
+ var SidebarBrand = React6.forwardRef(
3534
+ function SidebarBrand2({ className, ...props }, ref) {
3535
+ return /* @__PURE__ */ jsx(
3536
+ "div",
3537
+ {
3538
+ ref,
3539
+ ...slot(sidebarAnatomy, "brand"),
3540
+ className: cn(
3541
+ "ds:flex ds:min-w-0 ds:items-center ds:gap-2 ds:px-2.5 ds:pt-1 ds:pb-4",
3542
+ className
3543
+ ),
3544
+ ...props
3545
+ }
3546
+ );
3547
+ }
3548
+ );
3549
+ SidebarBrand.displayName = "SidebarBrand";
3550
+ var SidebarBrandText = React6.forwardRef(
3551
+ function SidebarBrandText2({ className, ...props }, ref) {
3552
+ const collapsed = useCollapsedAttribute();
3553
+ return /* @__PURE__ */ jsx(
3554
+ "span",
3555
+ {
3556
+ ref,
3557
+ "aria-hidden": "false",
3558
+ ...slot(sidebarAnatomy, "brand-text"),
3559
+ ...collapsed,
3560
+ className: cn(
3561
+ // line-clamp-1 (not `truncate`) so multi-word wordmarks clip at a
3562
+ // word boundary instead of mid-word when the rail is narrow.
3563
+ "ds:min-w-0 ds:line-clamp-1",
3564
+ // Smooth fade + width collapse on rail. Keeps the wordmark
3565
+ // legible up to the moment the column reaches rail width, then
3566
+ // fully drops out (visibility:hidden cuts hit-testing).
3567
+ "ds:transition-[opacity,max-width] ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
3568
+ "ds:max-w-[160px] ds:opacity-100",
3569
+ "ds:group-data-[labels=hide]/sidebar:max-w-0 ds:group-data-[labels=hide]/sidebar:opacity-0 ds:group-data-[labels=hide]/sidebar:invisible",
3570
+ className
3571
+ ),
3572
+ ...props
3573
+ }
3574
+ );
3575
+ }
3576
+ );
3577
+ SidebarBrandText.displayName = "SidebarBrandText";
3578
+ var SidebarGroupScopeContext = React6.createContext(null);
3579
+ var SidebarSection = React6.forwardRef(
3580
+ function SidebarSection2({ label, tone = "pro", headerActions, className, children, ...props }, ref) {
3581
+ const collapsed = useCollapsedAttribute();
3582
+ const ariaLabel = typeof label === "string" ? label : typeof label === "number" ? String(label) : void 0;
3583
+ const [exclusiveId, setExclusiveIdState] = React6.useState(null);
3584
+ const setExclusive = React6.useCallback(
3585
+ (id) => setExclusiveIdState(id),
3586
+ []
3587
+ );
3588
+ const scope = React6.useMemo(
3589
+ () => ({ exclusiveId, setExclusive }),
3590
+ [exclusiveId, setExclusive]
3591
+ );
3592
+ return /* @__PURE__ */ jsx(SidebarGroupScopeContext.Provider, { value: scope, children: /* @__PURE__ */ jsxs(
3593
+ "div",
3594
+ {
3595
+ ref,
3596
+ role: ariaLabel ? "group" : void 0,
3597
+ "aria-label": ariaLabel,
3598
+ ...slot(sidebarAnatomy, "section"),
3599
+ ...collapsed,
3600
+ className: cn(
3601
+ "ds:mb-4",
3602
+ // In rail, the visible section labels disappear and the only
3603
+ // grouping cue is a thin rule. No extra mb/pb — the border
3604
+ // itself separates groups, so inter-section spacing matches
3605
+ // intra-section spacing and the rail stays dense.
3606
+ "ds:group-data-[labels=hide]/sidebar:mb-0 ds:group-data-[labels=hide]/sidebar:border-b ds:group-data-[labels=hide]/sidebar:border-rule ds:group-data-[labels=hide]/sidebar:pb-0 ds:group-data-[labels=hide]/sidebar:last:border-b-0",
3607
+ className
3608
+ ),
3609
+ ...props,
3610
+ children: [
3611
+ (label != null || headerActions != null) && /* @__PURE__ */ jsxs(
3612
+ "div",
3613
+ {
3614
+ ...slot(sidebarAnatomy, "section-header"),
3615
+ ...collapsed,
3616
+ className: cn(
3617
+ "ds:mb-1 ds:flex ds:items-center ds:justify-between ds:px-2.5 ds:py-1",
3618
+ "ds:transition-opacity ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
3619
+ "ds:opacity-100",
3620
+ "ds:group-data-[labels=hide]/sidebar:invisible ds:group-data-[labels=hide]/sidebar:opacity-0"
3621
+ ),
3622
+ children: [
3623
+ label != null && /* @__PURE__ */ jsx(
3624
+ "span",
3625
+ {
3626
+ ...slot(sidebarAnatomy, "section-label"),
3627
+ className: cn(
3628
+ "ds:font-mono ds:text-[11px] ds:tracking-[0.14em] ds:uppercase",
3629
+ tone === "muted" ? "ds:text-fg-3" : "ds:text-brand"
3630
+ ),
3631
+ children: label
3632
+ }
3633
+ ),
3634
+ headerActions
3635
+ ]
3636
+ }
3637
+ ),
3638
+ children
3639
+ ]
3640
+ }
3641
+ ) });
3642
+ }
3643
+ );
3644
+ SidebarSection.displayName = "SidebarSection";
3645
+ function getTextContent(node) {
3646
+ if (node == null || typeof node === "boolean") return "";
3647
+ if (typeof node === "string" || typeof node === "number") return String(node);
3648
+ if (Array.isArray(node)) return node.map(getTextContent).filter(Boolean).join(" ");
3649
+ if (React6.isValidElement(node)) {
3650
+ return getTextContent(node.props.children);
3651
+ }
3652
+ return "";
3653
+ }
3654
+ var SidebarLink = React6.forwardRef(
3655
+ function SidebarLink2({ href, icon, active = false, asChild, className, children, "aria-label": ariaLabel, ...props }, ref) {
3656
+ const Comp = asChild ? Slot : "a";
3657
+ const accessibleLabel = ariaLabel ?? (asChild ? void 0 : getTextContent(children) || void 0);
3658
+ const labelsHidden = React6.useContext(SidebarLabelsHiddenContext);
3659
+ const peekEnabled = React6.useContext(SidebarPeekEnabledContext);
3660
+ const tooltipLabel = ariaLabel ?? (getTextContent(children) || void 0);
3661
+ const showTooltip = labelsHidden && !peekEnabled && Boolean(tooltipLabel);
3662
+ const link = /* @__PURE__ */ jsx(
3663
+ Comp,
3664
+ {
3665
+ ref,
3666
+ ...asChild ? {} : { href },
3667
+ "data-active": active ? "true" : void 0,
3668
+ "aria-current": active ? "page" : void 0,
3669
+ "aria-label": accessibleLabel,
3670
+ ...slot(sidebarAnatomy, "link"),
3671
+ className: cn(
3672
+ "ds:group/link ds:relative ds:mb-px ds:flex ds:items-center ds:gap-2.5 ds:rounded-md ds:px-2.5 ds:py-1.5",
3673
+ "ds:text-fg-2 ds:text-[13px] ds:font-normal ds:no-underline",
3674
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)]",
3675
+ "ds:motion-reduce:transition-none",
3676
+ "ds:hover:bg-bg-3 ds:hover:text-fg",
3677
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
3678
+ "ds:data-[active=true]:bg-brand-bg ds:data-[active=true]:text-brand ds:data-[active=true]:font-medium",
3679
+ // In rail, the icon itself carries the active state rather
3680
+ // than just the rule bar — color is more legible than a 2px
3681
+ // vertical mark at the column's left edge when labels are
3682
+ // hidden. The full-opacity icon override (`opacity-100`)
3683
+ // counters the default `[&_svg]:opacity-85` so the active
3684
+ // icon doesn't read as "still inactive but darker".
3685
+ "ds:group-data-[labels=hide]/sidebar:data-[active=true]:[&_svg]:text-brand ds:group-data-[labels=hide]/sidebar:data-[active=true]:[&_svg]:opacity-100",
3686
+ // Active rail: 2px wide, 16px tall, anchored to the link's
3687
+ // own left edge — no parent-padding dependency. Continues
3688
+ // working unchanged when the aside narrows to a rail.
3689
+ "ds:data-[active=true]:before:absolute ds:data-[active=true]:before:content-['']",
3690
+ "ds:data-[active=true]:before:top-1/2 ds:data-[active=true]:before:left-0",
3691
+ "ds:data-[active=true]:before:h-4 ds:data-[active=true]:before:w-[2px] ds:data-[active=true]:before:-translate-y-1/2",
3692
+ "ds:data-[active=true]:before:bg-brand ds:data-[active=true]:before:rounded-r-full",
3693
+ // Padding/gap stay constant so the icon stays under the cursor
3694
+ // when the column widens during peek. The label simply collapses
3695
+ // to width 0 via <SidebarLinkLabel>.
3696
+ "ds:[&_svg]:size-3.5 ds:[&_svg]:shrink-0 ds:[&_svg]:opacity-85",
3697
+ // Floating variant: softer corners + a taller hit area (Fitts's
3698
+ // law — a larger target is faster and lower-error to acquire), and
3699
+ // a full pill highlight for active instead of the left rail bar.
3700
+ "ds:group-data-[variant=floating]/sidebar:gap-3 ds:group-data-[variant=floating]/sidebar:rounded-lg ds:group-data-[variant=floating]/sidebar:py-2",
3701
+ "ds:group-data-[variant=floating]/sidebar:data-[active=true]:before:hidden",
3702
+ className
3703
+ ),
3704
+ ...props,
3705
+ children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
3706
+ icon,
3707
+ /* @__PURE__ */ jsx(
3708
+ "span",
3709
+ {
3710
+ ...slot(sidebarAnatomy, "link-label"),
3711
+ ...labelsHidden ? { "data-collapsed": "true" } : {},
3712
+ className: cn(
3713
+ // Flex row so a trailing <SidebarLinkBadge> (ml-auto) aligns
3714
+ // to the right edge with a gap from the label, instead of
3715
+ // butting against it. A line-clamp box swallows the badge's
3716
+ // auto margin, which is why "Billing$48k" rendered glued.
3717
+ // Single-line label clips via overflow; badge stays put.
3718
+ "ds:flex ds:min-w-0 ds:flex-1 ds:items-center ds:gap-1.5 ds:overflow-hidden ds:whitespace-nowrap",
3719
+ "ds:transition-[opacity,max-width] ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
3720
+ "ds:max-w-full ds:opacity-100",
3721
+ "ds:group-data-[labels=hide]/sidebar:max-w-0 ds:group-data-[labels=hide]/sidebar:opacity-0 ds:group-data-[labels=hide]/sidebar:invisible"
3722
+ ),
3723
+ children
3724
+ }
3725
+ )
3726
+ ] })
3727
+ }
3728
+ );
3729
+ if (!showTooltip) return link;
3730
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
3731
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: link }),
3732
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: tooltipLabel })
3733
+ ] });
3734
+ }
3735
+ );
3736
+ SidebarLink.displayName = "SidebarLink";
3737
+ var SidebarLinkLabel = React6.forwardRef(
3738
+ function SidebarLinkLabel2({ className, ...props }, ref) {
3739
+ const collapsed = useCollapsedAttribute();
3740
+ return /* @__PURE__ */ jsx(
3741
+ "span",
3742
+ {
3743
+ ref,
3744
+ ...slot(sidebarAnatomy, "link-label"),
3745
+ ...collapsed,
3746
+ className: cn(
3747
+ // line-clamp-1 (not `truncate`) so multi-word labels clip at a
3748
+ // word boundary; collapses cleanly with the rail-mode max-width
3749
+ // animation since both rules only constrain visible content.
3750
+ "ds:min-w-0 ds:flex-1 ds:line-clamp-1",
3751
+ // Fade + collapse instead of hard display:none so a single
3752
+ // 180ms opacity tween covers all labels in lockstep with the
3753
+ // 220ms aside-width transition — no snap on the last frame.
3754
+ "ds:transition-[opacity,max-width] ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
3755
+ "ds:max-w-full ds:opacity-100",
3756
+ "ds:group-data-[labels=hide]/sidebar:max-w-0 ds:group-data-[labels=hide]/sidebar:opacity-0 ds:group-data-[labels=hide]/sidebar:invisible",
3757
+ className
3758
+ ),
3759
+ ...props
3760
+ }
3761
+ );
3762
+ }
3763
+ );
3764
+ SidebarLinkLabel.displayName = "SidebarLinkLabel";
3765
+ var SidebarLinkAction = React6.forwardRef(
3766
+ function SidebarLinkAction2({ className, ...props }, ref) {
3767
+ const collapsed = useCollapsedAttribute();
3768
+ return /* @__PURE__ */ jsx(
3769
+ "span",
3770
+ {
3771
+ ref,
3772
+ ...slot(sidebarAnatomy, "link-action"),
3773
+ ...collapsed,
3774
+ className: cn(
3775
+ "ds:transition-opacity ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
3776
+ "ds:opacity-100",
3777
+ "ds:group-data-[labels=hide]/sidebar:invisible ds:group-data-[labels=hide]/sidebar:opacity-0",
3778
+ className
3779
+ ),
3780
+ ...props
3781
+ }
3782
+ );
3783
+ }
3784
+ );
3785
+ SidebarLinkAction.displayName = "SidebarLinkAction";
3786
+ var sidebarLinkBadgeVariants = cva(
3787
+ "ds:ml-auto ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center ds:font-mono ds:tabular-nums ds:group-data-[labels=hide]/sidebar:hidden",
3788
+ {
3789
+ variants: {
3790
+ tone: {
3791
+ default: "ds:text-[10.5px] ds:text-fg-4 ds:group-data-[active=true]/link:text-brand",
3792
+ danger: "ds:rounded-pill ds:bg-danger-bg ds:px-1.5 ds:py-0.5 ds:text-[10.5px] ds:text-danger-fg",
3793
+ warning: "ds:rounded-pill ds:bg-warning-bg ds:px-1.5 ds:py-0.5 ds:text-[10.5px] ds:text-warning-fg",
3794
+ neutral: "ds:rounded-pill ds:bg-bg-3 ds:px-1.5 ds:py-0.5 ds:text-[10.5px] ds:text-fg-2"
3795
+ }
3796
+ },
3797
+ defaultVariants: { tone: "default" }
3798
+ }
3799
+ );
3800
+ var SidebarLinkBadge = React6.forwardRef(
3801
+ function SidebarLinkBadge2({ tone, className, ...props }, ref) {
3802
+ return /* @__PURE__ */ jsx(
3803
+ "span",
3804
+ {
3805
+ ref,
3806
+ ...slot(sidebarAnatomy, "link-badge"),
3807
+ className: cn(sidebarLinkBadgeVariants({ tone }), className),
3808
+ ...props
3809
+ }
3810
+ );
3811
+ }
3812
+ );
3813
+ SidebarLinkBadge.displayName = "SidebarLinkBadge";
3814
+ var SidebarLinkGroup = React6.forwardRef(
3815
+ function SidebarLinkGroup2({
3816
+ id: idProp,
3817
+ icon,
3818
+ label,
3819
+ href,
3820
+ active = false,
3821
+ defaultOpen = false,
3822
+ open: controlled,
3823
+ onOpenChange,
3824
+ onActivate,
3825
+ classNames,
3826
+ className,
3827
+ children,
3828
+ ...props
3829
+ }, ref) {
3830
+ const messages = useDsMessages("sidebar");
3831
+ const collapsed = useCollapsedAttribute();
3832
+ const reactId = React6.useId();
3833
+ const id = idProp ?? reactId;
3834
+ const scope = React6.useContext(SidebarGroupScopeContext);
3835
+ const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
3836
+ const open = controlled ?? uncontrolledOpen;
3837
+ const setOpen = React6.useCallback(
3838
+ (next) => {
3839
+ if (controlled === void 0) setUncontrolledOpen(next);
3840
+ onOpenChange?.(next);
3841
+ },
3842
+ [controlled, onOpenChange]
3843
+ );
3844
+ React6.useEffect(() => {
3845
+ if (scope?.exclusiveId && scope.exclusiveId !== id && open) {
3846
+ setOpen(false);
3847
+ }
3848
+ }, [scope?.exclusiveId, id, open, setOpen]);
3849
+ const handleBodyClick = (e) => {
3850
+ onActivate?.(e);
3851
+ if (e.defaultPrevented) return;
3852
+ scope?.setExclusive(id);
3853
+ setOpen(true);
3854
+ };
3855
+ const handleChevronClick = (e) => {
3856
+ e.preventDefault();
3857
+ e.stopPropagation();
3858
+ setOpen(!open);
3859
+ };
3860
+ const contentId = `${id}-content`;
3861
+ const bodyClassName = cn(
3862
+ "ds:group/link ds:relative ds:flex ds:flex-1 ds:items-center ds:gap-2.5 ds:rounded-md ds:px-2.5 ds:py-1.5",
3863
+ "ds:text-fg-2 ds:text-[13px] ds:font-normal ds:no-underline",
3864
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)]",
3865
+ "ds:motion-reduce:transition-none",
3866
+ "ds:hover:bg-bg-3 ds:hover:text-fg",
3867
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
3868
+ "ds:data-[active=true]:bg-brand-bg ds:data-[active=true]:text-brand ds:data-[active=true]:font-medium",
3869
+ // In rail, color carries active state since the chevron is hidden.
3870
+ "ds:group-data-[labels=hide]/sidebar:data-[active=true]:[&_svg]:text-brand ds:group-data-[labels=hide]/sidebar:data-[active=true]:[&_svg]:opacity-100",
3871
+ // Active rail mark — anchored to body row's left edge.
3872
+ "ds:data-[active=true]:before:absolute ds:data-[active=true]:before:content-['']",
3873
+ "ds:data-[active=true]:before:top-1/2 ds:data-[active=true]:before:left-0",
3874
+ "ds:data-[active=true]:before:h-4 ds:data-[active=true]:before:w-[2px] ds:data-[active=true]:before:-translate-y-1/2",
3875
+ "ds:data-[active=true]:before:bg-brand ds:data-[active=true]:before:rounded-r-full",
3876
+ "ds:[&_svg]:size-3.5 ds:[&_svg]:shrink-0 ds:[&_svg]:opacity-85",
3877
+ // Floating variant — match SidebarLink: taller hit area, pill active.
3878
+ "ds:group-data-[variant=floating]/sidebar:gap-3 ds:group-data-[variant=floating]/sidebar:rounded-lg ds:group-data-[variant=floating]/sidebar:py-2",
3879
+ "ds:group-data-[variant=floating]/sidebar:data-[active=true]:before:hidden",
3880
+ classNames?.link
3881
+ );
3882
+ const labelSpan = /* @__PURE__ */ jsx(
3883
+ "span",
3884
+ {
3885
+ ...slot(sidebarAnatomy, "link-label"),
3886
+ ...collapsed,
3887
+ className: cn(
3888
+ // line-clamp-1 (not `truncate`) so multi-word labels clip at a
3889
+ // word boundary; collapses cleanly with the rail-mode max-width
3890
+ // animation since both rules only constrain visible content.
3891
+ "ds:min-w-0 ds:flex-1 ds:line-clamp-1",
3892
+ "ds:transition-[opacity,max-width] ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
3893
+ "ds:max-w-full ds:opacity-100",
3894
+ "ds:group-data-[labels=hide]/sidebar:max-w-0 ds:group-data-[labels=hide]/sidebar:opacity-0 ds:group-data-[labels=hide]/sidebar:invisible"
3895
+ ),
3896
+ children: label
3897
+ }
3898
+ );
3899
+ return /* @__PURE__ */ jsx(
3900
+ "div",
3901
+ {
3902
+ ref,
3903
+ ...slot(sidebarAnatomy, "group"),
3904
+ ...stateAttributes({ state: open ? "open" : "closed" }),
3905
+ className: cn("ds:mb-px", className),
3906
+ ...props,
3907
+ children: /* @__PURE__ */ jsxs(Collapsible, { open, onOpenChange: setOpen, children: [
3908
+ /* @__PURE__ */ jsxs("div", { className: cn("ds:flex ds:items-stretch", classNames?.row), children: [
3909
+ /* @__PURE__ */ jsxs(
3910
+ "a",
3911
+ {
3912
+ href,
3913
+ "data-active": active ? "true" : void 0,
3914
+ "aria-current": active ? "page" : void 0,
3915
+ "aria-label": getTextContent(label) || void 0,
3916
+ onClick: handleBodyClick,
3917
+ ...slot(sidebarAnatomy, "group-link"),
3918
+ className: bodyClassName,
3919
+ children: [
3920
+ icon,
3921
+ labelSpan
3922
+ ]
3923
+ }
3924
+ ),
3925
+ /* @__PURE__ */ jsx(
3926
+ "button",
3927
+ {
3928
+ type: "button",
3929
+ "aria-expanded": open,
3930
+ "aria-controls": contentId,
3931
+ "aria-label": open ? messages.collapseSection : messages.expandSection,
3932
+ onClick: handleChevronClick,
3933
+ ...slot(sidebarAnatomy, "group-trigger"),
3934
+ className: cn(
3935
+ "ds:ml-px ds:inline-flex ds:size-7 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-md",
3936
+ "ds:text-fg-4 ds:hover:bg-bg-3 ds:hover:text-fg-2",
3937
+ "ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
3938
+ "ds:focus-visible:[box-shadow:var(--shadow-focus-ring)] ds:focus-visible:outline-none",
3939
+ "ds:[&_svg]:size-3.5 ds:[&_svg]:shrink-0 ds:[&_svg]:transition-transform ds:[&_svg]:duration-[var(--duration-fast)] ds:[&_svg]:ease-[var(--ease-out-quart)] ds:motion-reduce:[&_svg]:transition-none",
3940
+ // Hide in rail — content tree is hidden too, so the
3941
+ // affordance has nothing to control.
3942
+ "ds:group-data-[labels=hide]/sidebar:hidden"
3943
+ ),
3944
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: open ? "" : "ds:-rotate-90" })
3945
+ }
3946
+ )
3947
+ ] }),
3948
+ /* @__PURE__ */ jsx(
3949
+ CollapsibleContent,
3950
+ {
3951
+ id: contentId,
3952
+ ...slot(sidebarAnatomy, "group-content"),
3953
+ className: cn(
3954
+ // Indent column + connecting rule. Children render as
3955
+ // standard <SidebarLink>s and keep their own active-rail
3956
+ // indicator, which lands flush at the indented column's
3957
+ // left edge.
3958
+ "ds:group-data-[labels=hide]/sidebar:hidden"
3959
+ ),
3960
+ children: /* @__PURE__ */ jsx("div", { className: "ds:border-rule ds:mt-px ds:ml-[18px] ds:border-l ds:pl-2", children })
3961
+ }
3962
+ )
3963
+ ] })
3964
+ }
3965
+ );
3966
+ }
3967
+ );
3968
+ SidebarLinkGroup.displayName = "SidebarLinkGroup";
3969
+ var SidebarFooter = React6.forwardRef(
3970
+ function SidebarFooter2({ className, ...props }, ref) {
3971
+ return /* @__PURE__ */ jsx(
3972
+ "div",
3973
+ {
3974
+ ref,
3975
+ ...slot(sidebarAnatomy, "footer"),
3976
+ className: cn(
3977
+ "ds:border-rule ds:mt-auto ds:flex ds:items-center ds:gap-2.5 ds:border-t ds:px-2 ds:pt-2.5 ds:pb-1",
3978
+ "ds:text-fg-3 ds:text-xs",
3979
+ className
3980
+ ),
3981
+ ...props
3982
+ }
3983
+ );
3984
+ }
3985
+ );
3986
+ SidebarFooter.displayName = "SidebarFooter";
3987
+ var SidebarUser = React6.forwardRef(function SidebarUser2({ name, subtitle, avatarSrc, className, ...props }, ref) {
3988
+ const collapsed = useCollapsedAttribute();
3989
+ return /* @__PURE__ */ jsxs(
3990
+ "div",
3991
+ {
3992
+ ref,
3993
+ ...slot(sidebarAnatomy, "user"),
3994
+ ...collapsed,
3995
+ className: cn("ds:flex ds:min-w-0 ds:items-center ds:gap-2.5", className),
3996
+ ...props,
3997
+ children: [
3998
+ /* @__PURE__ */ jsx(Avatar, { size: "sm", variant: "branded", name, src: avatarSrc ?? void 0 }),
3999
+ /* @__PURE__ */ jsxs(
4000
+ "div",
4001
+ {
4002
+ className: cn(
4003
+ "ds:min-w-0 ds:leading-tight",
4004
+ "ds:transition-[opacity,max-width] ds:duration-[var(--motion-duration-spatial)] ds:ease-[var(--motion-ease-move)] ds:motion-reduce:transition-none",
4005
+ "ds:max-w-full ds:opacity-100",
4006
+ "ds:group-data-[labels=hide]/sidebar:max-w-0 ds:group-data-[labels=hide]/sidebar:opacity-0 ds:group-data-[labels=hide]/sidebar:invisible"
4007
+ ),
4008
+ children: [
4009
+ /* @__PURE__ */ jsx(
4010
+ "div",
4011
+ {
4012
+ ...slot(sidebarAnatomy, "user-name"),
4013
+ className: "ds:text-fg ds:line-clamp-1 ds:text-[13px] ds:font-medium",
4014
+ children: name
4015
+ }
4016
+ ),
4017
+ subtitle != null && /* @__PURE__ */ jsx(
4018
+ "div",
4019
+ {
4020
+ ...slot(sidebarAnatomy, "user-subtitle"),
4021
+ className: "ds:text-fg-4 ds:line-clamp-1 ds:font-mono ds:text-[10.5px]",
4022
+ children: subtitle
4023
+ }
4024
+ )
4025
+ ]
4026
+ }
4027
+ )
4028
+ ]
4029
+ }
4030
+ );
4031
+ });
4032
+ SidebarUser.displayName = "SidebarUser";
4033
+ function SidebarDrawer({
4034
+ open,
4035
+ defaultOpen,
4036
+ onOpenChange,
4037
+ label,
4038
+ className,
4039
+ children
4040
+ }) {
4041
+ const messages = useDsMessages("sidebar");
4042
+ return /* @__PURE__ */ jsx(
4043
+ Sheet,
4044
+ {
4045
+ ...open !== void 0 && { open },
4046
+ ...defaultOpen !== void 0 && { defaultOpen },
4047
+ ...onOpenChange !== void 0 && { onOpenChange },
4048
+ children: /* @__PURE__ */ jsxs(
4049
+ SheetContent,
4050
+ {
4051
+ side: "left",
4052
+ "data-mode": "mobile",
4053
+ "data-labels": "show",
4054
+ style: { width: "var(--ds-layout-shell-sidebar-width, var(--shell-sidebar-w))" },
4055
+ className: cn(
4056
+ "ds:group/sidebar group/sidebar ds:scrollbar-thin ds:bg-bg-2 ds:flex ds:flex-col ds:overflow-y-auto ds:px-3 ds:pt-4 ds:pb-4",
4057
+ className
4058
+ ),
4059
+ children: [
4060
+ /* @__PURE__ */ jsx(SheetTitle, { className: "ds:sr-only", children: label ?? messages.navigation }),
4061
+ children
4062
+ ]
4063
+ }
4064
+ )
4065
+ }
4066
+ );
4067
+ }
4068
+ SidebarDrawer.displayName = "SidebarDrawer";
4069
+ var SidebarBrandSwitcher = React6.forwardRef(
4070
+ function SidebarBrandSwitcher2({
4071
+ brand,
4072
+ label,
4073
+ current,
4074
+ items,
4075
+ onLaunch,
4076
+ extras,
4077
+ isLaunching,
4078
+ currentSectionLabel = "Currently using",
4079
+ switchSectionLabel = "Switch to",
4080
+ menuLabel = "Suite",
4081
+ currentBadge = "Current",
4082
+ unavailableBadge = "Soon",
4083
+ triggerLabel = "Switch product",
4084
+ className,
4085
+ triggerClassName,
4086
+ contentClassName,
4087
+ rowClassName,
4088
+ trailing
4089
+ }, ref) {
4090
+ const [open, setOpen] = React6.useState(false);
4091
+ useSidebarPeekLock(open);
4092
+ const others = items.filter((p) => p.id !== current.id);
4093
+ return (
4094
+ // Geometry mirrors <SidebarBrand>: `px-2.5 pt-1 pb-4 gap-2`. This is
4095
+ // deliberate — the switcher replaces SidebarBrand, so the brand
4096
+ // glyph must land at the same column x-position that direct children
4097
+ // of <SidebarBrand> sit at, which in turn matches the 10px left
4098
+ // padding of <SidebarLink> icons below.
4099
+ /* @__PURE__ */ jsxs(
4100
+ "div",
4101
+ {
4102
+ ref,
4103
+ ...slot(sidebarBrandSwitcherAnatomy, "root"),
4104
+ className: cn("ds:flex ds:min-w-0 ds:items-center ds:gap-2 ds:px-2.5 ds:pt-1 ds:pb-4", className),
4105
+ children: [
4106
+ /* @__PURE__ */ jsxs(DropdownMenu, { open, onOpenChange: setOpen, children: [
4107
+ /* @__PURE__ */ jsxs(
4108
+ DropdownMenuTrigger,
4109
+ {
4110
+ "aria-label": triggerLabel,
4111
+ ...slot(sidebarBrandSwitcherAnatomy, "trigger"),
4112
+ className: cn(
4113
+ // Negative left margin pulls the trigger's hover-bg toward
4114
+ // the column edge while the inner padding holds the brand
4115
+ // glyph at the same x-position as direct <SidebarBrand>
4116
+ // children — same hover affordance, no glyph drift.
4117
+ "ds:group/brand-trigger ds:-ml-2 ds:flex ds:min-w-0 ds:flex-1 ds:items-center ds:gap-2 ds:rounded-md ds:py-1.5 ds:pr-1.5 ds:pl-2",
4118
+ "ds:text-fg ds:transition-colors ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
4119
+ "ds:hover:bg-bg-3 ds:data-[state=open]:bg-bg-3",
4120
+ "ds:focus-visible:outline-none ds:focus-visible:[box-shadow:var(--shadow-focus-ring)]",
4121
+ triggerClassName
4122
+ ),
4123
+ children: [
4124
+ brand,
4125
+ /* @__PURE__ */ jsx(SidebarBrandText, { className: "ds:font-display ds:text-fg ds:text-[17px] ds:font-semibold ds:tracking-tight", children: label }),
4126
+ /* @__PURE__ */ jsx(
4127
+ ChevronDownIcon,
4128
+ {
4129
+ ...slot(sidebarBrandSwitcherAnatomy, "icon"),
4130
+ className: cn(
4131
+ "ds:ml-auto ds:size-3.5 ds:shrink-0 ds:text-fg-4",
4132
+ "ds:transition-transform ds:duration-[var(--duration-fast)] ds:ease-[var(--ease-out-quart)] ds:motion-reduce:transition-none",
4133
+ "ds:group-data-[state=open]/brand-trigger:rotate-180",
4134
+ "ds:group-data-[labels=hide]/sidebar:hidden"
4135
+ )
4136
+ }
4137
+ )
4138
+ ]
4139
+ }
4140
+ ),
4141
+ /* @__PURE__ */ jsxs(
4142
+ DropdownMenuContent,
4143
+ {
4144
+ side: "right",
4145
+ align: "start",
4146
+ sideOffset: 12,
4147
+ className: cn("ds:w-72 ds:p-1", contentClassName),
4148
+ children: [
4149
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "ds:px-2 ds:pt-1 ds:pb-1.5", children: menuLabel }),
4150
+ /* @__PURE__ */ jsx(SidebarBrandSwitcherSectionLabel, { children: currentSectionLabel }),
4151
+ /* @__PURE__ */ jsx(
4152
+ SidebarBrandSwitcherCurrentRow,
4153
+ {
4154
+ item: current,
4155
+ badge: currentBadge,
4156
+ rowClassName
4157
+ }
4158
+ ),
4159
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, { className: "ds:my-1.5" }),
4160
+ /* @__PURE__ */ jsx(SidebarBrandSwitcherSectionLabel, { children: switchSectionLabel }),
4161
+ others.map((p) => /* @__PURE__ */ jsx(
4162
+ SidebarBrandSwitcherOtherRow,
4163
+ {
4164
+ item: p,
4165
+ onLaunch,
4166
+ unavailableBadge,
4167
+ rowClassName,
4168
+ isLaunching
4169
+ },
4170
+ p.id
4171
+ )),
4172
+ extras?.map((extra) => /* @__PURE__ */ jsx(
4173
+ SidebarBrandSwitcherExtraRow,
4174
+ {
4175
+ extra,
4176
+ rowClassName
4177
+ },
4178
+ extra.id
4179
+ ))
4180
+ ]
4181
+ }
4182
+ )
4183
+ ] }),
4184
+ trailing
4185
+ ]
4186
+ }
4187
+ )
4188
+ );
4189
+ }
4190
+ );
4191
+ SidebarBrandSwitcher.displayName = "SidebarBrandSwitcher";
4192
+ function SidebarBrandSwitcherSectionLabel({ children }) {
4193
+ return /* @__PURE__ */ jsx("div", { className: "ds:px-2 ds:pt-1 ds:pb-0.5 ds:text-[10px] ds:tracking-wider ds:uppercase ds:text-fg-4", children });
4194
+ }
4195
+ function SidebarBrandSwitcherTile({ item }) {
4196
+ if (item.glyph) return /* @__PURE__ */ jsx(Fragment, { children: item.glyph });
4197
+ const initial = (item.short ?? item.name).charAt(0).toUpperCase();
4198
+ return /* @__PURE__ */ jsx(
4199
+ "span",
4200
+ {
4201
+ "aria-hidden": true,
4202
+ className: cn(
4203
+ "ds:inline-flex ds:size-6 ds:shrink-0 ds:items-center ds:justify-center ds:rounded-md",
4204
+ "ds:text-[11px] ds:font-semibold ds:text-white",
4205
+ item.tone
4206
+ ),
4207
+ children: initial
4208
+ }
4209
+ );
4210
+ }
4211
+ function SidebarBrandSwitcherIdentity({ item }) {
4212
+ if (item.identity) {
4213
+ return /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-0.5", children: [
4214
+ item.identity,
4215
+ item.tagline && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:text-[11px] ds:leading-tight", children: item.tagline })
4216
+ ] });
4217
+ }
4218
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4219
+ /* @__PURE__ */ jsx(SidebarBrandSwitcherTile, { item }),
4220
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:min-w-0 ds:flex-1 ds:flex-col", children: [
4221
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-[13px] ds:font-medium", children: item.name }),
4222
+ item.tagline && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:text-[11px]", children: item.tagline })
4223
+ ] })
4224
+ ] });
4225
+ }
4226
+ function SidebarBrandSwitcherCurrentRow({
4227
+ item,
4228
+ badge,
4229
+ rowClassName
4230
+ }) {
4231
+ return /* @__PURE__ */ jsxs(
4232
+ "div",
4233
+ {
4234
+ className: cn(
4235
+ "ds:mx-0 ds:flex ds:cursor-default ds:items-center ds:gap-2.5 ds:rounded-md ds:bg-bg-2 ds:px-2 ds:py-1.5",
4236
+ rowClassName
4237
+ ),
4238
+ children: [
4239
+ /* @__PURE__ */ jsx(SidebarBrandSwitcherIdentity, { item }),
4240
+ badge && /* @__PURE__ */ jsx("span", { className: "ds:rounded-sm ds:px-1.5 ds:py-0.5 ds:text-[10px] ds:font-medium ds:tracking-wider ds:uppercase ds:text-pro-fg ds:ring-1 ds:ring-pro-fg/30", children: badge })
4241
+ ]
4242
+ }
4243
+ );
4244
+ }
4245
+ function SidebarBrandSwitcherOtherRow({
4246
+ item,
4247
+ onLaunch,
4248
+ unavailableBadge,
4249
+ rowClassName,
4250
+ isLaunching
4251
+ }) {
4252
+ const reachable = item.available !== false;
4253
+ const [launching, setLaunching] = React6.useState(false);
4254
+ const externalLaunching = isLaunching?.(item) ?? false;
4255
+ const busy = launching || externalLaunching;
4256
+ const handleSelect = async () => {
4257
+ if (!reachable || busy || !onLaunch) return;
4258
+ setLaunching(true);
4259
+ try {
4260
+ await onLaunch(item);
4261
+ } finally {
4262
+ setLaunching(false);
4263
+ }
4264
+ };
4265
+ return /* @__PURE__ */ jsxs(
4266
+ DropdownMenuItem,
4267
+ {
4268
+ disabled: !reachable,
4269
+ onSelect: (e) => {
4270
+ if (!reachable) {
4271
+ e.preventDefault();
4272
+ return;
4273
+ }
4274
+ void handleSelect();
4275
+ },
4276
+ "data-item": item.dataAttr ?? item.id,
4277
+ className: cn("ds:flex ds:items-center ds:gap-2.5 ds:rounded-md ds:px-2 ds:py-1.5", rowClassName),
4278
+ children: [
4279
+ /* @__PURE__ */ jsx(SidebarBrandSwitcherIdentity, { item }),
4280
+ !reachable && unavailableBadge && /* @__PURE__ */ jsx("span", { className: "ds:rounded-sm ds:bg-bg-3 ds:px-1.5 ds:py-0.5 ds:text-[10px] ds:font-medium ds:tracking-wider ds:uppercase ds:text-fg-4", children: unavailableBadge }),
4281
+ reachable && busy && /* @__PURE__ */ jsx("span", { className: "ds:rounded-sm ds:bg-bg-3 ds:px-1.5 ds:py-0.5 ds:text-[10px] ds:font-medium ds:tracking-wider ds:uppercase ds:text-fg-4", children: "Opening\u2026" })
4282
+ ]
4283
+ }
4284
+ );
4285
+ }
4286
+ function SidebarBrandSwitcherExtraRow({
4287
+ extra,
4288
+ rowClassName
4289
+ }) {
4290
+ return /* @__PURE__ */ jsx(
4291
+ DropdownMenuItem,
4292
+ {
4293
+ onSelect: () => extra.onSelect(),
4294
+ "data-item": extra.dataAttr ?? extra.id,
4295
+ className: cn("ds:flex ds:items-center ds:gap-2.5 ds:rounded-md ds:px-2 ds:py-1.5", rowClassName),
4296
+ children: extra.identity ? /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-0.5", children: [
4297
+ extra.identity,
4298
+ extra.tagline && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:text-[11px] ds:leading-tight", children: extra.tagline })
4299
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4300
+ extra.glyph,
4301
+ /* @__PURE__ */ jsxs("div", { className: "ds:flex ds:min-w-0 ds:flex-1 ds:flex-col", children: [
4302
+ /* @__PURE__ */ jsx("span", { className: "ds:text-fg ds:text-[13px] ds:font-medium", children: extra.name }),
4303
+ extra.tagline && /* @__PURE__ */ jsx("span", { className: "ds:text-fg-3 ds:text-[11px]", children: extra.tagline })
4304
+ ] })
4305
+ ] })
4306
+ }
4307
+ );
4308
+ }
4309
+ function brandScope(product) {
4310
+ return { "data-brand": product };
4311
+ }
4312
+ var BRAND_PRODUCTS = ["pro", "audit", "books", "tax"];
4313
+ var brandLabel = {
4314
+ pro: "Pro",
4315
+ audit: "Audit",
4316
+ books: "Books",
4317
+ tax: "Tax"
4318
+ };
4319
+ var BrandScopeContext = createContext("pro");
4320
+ function BrandScopeProvider({
4321
+ product,
4322
+ children
4323
+ }) {
4324
+ return /* @__PURE__ */ jsx(BrandScopeContext.Provider, { value: product, children });
4325
+ }
4326
+ function useBrandScope() {
4327
+ return useContext(BrandScopeContext);
4328
+ }
4329
+ var BrandScope = forwardRef(function BrandScope2({ product, children, ...props }, ref) {
4330
+ return /* @__PURE__ */ jsx(BrandScopeProvider, { product, children: /* @__PURE__ */ jsx("div", { ref, "data-brand": product, ...props, children }) });
4331
+ });
4332
+ BrandScope.displayName = "BrandScope";
4333
+
4334
+ export { AgreementPaneHeading, AgreementViewer, AssureAuditBrandIcon, AssureBooksBrandIcon, AssureProBrandIcon, AssureTaxBrandIcon, BRAND_PRODUCTS, BrandScope, BrandScopeProvider, Chip, ClientSelect, CmdkCompatContext, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComingSoon, DEFAULT_COMBOBOX_MESSAGES, Grid, Logo, PlainLink, ProposalAddOn, ProposalBillingTerms, ProposalConsentGate, ProposalCustomPage, ProposalNote, ProposalPackageCard, ProposalPaymentCapture, ProposalPricingSummary, ProposalServiceRow, ProposalSignatureBlock, ProposalSignerList, QUESTION_TYPES, QUESTION_TYPE_CONTRACT_VERSION, Questions, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarBrand, SidebarBrandSwitcher, SidebarBrandSwitcherTile, SidebarBrandText, SidebarDrawer, SidebarFooter, SidebarLink, SidebarLinkAction, SidebarLinkBadge, SidebarLinkGroup, SidebarLinkLabel, SidebarPinButton, SidebarProvider, SidebarSection, SidebarTrigger, SidebarUser, assetPath, brandLabel, brandScope, chipVariants, getAssetBasePath, resolveChipStyle, setAssetBasePath, sidebarLinkBadgeVariants, useBrandScope, useSidebarPeekLock, useSidebarState };
4335
+ //# sourceMappingURL=chunk-7U3ADR2Q.js.map
4336
+ //# sourceMappingURL=chunk-7U3ADR2Q.js.map