@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.
- package/README.md +63 -28
- package/codemods/README.md +76 -25
- package/codemods/lib/entry-map.mjs +315 -0
- package/codemods/lib/registry.mjs +28 -0
- package/codemods/lib/runner.mjs +8 -3
- package/codemods/run.mjs +27 -5
- package/codemods/transforms/cm-01-entry-imports.mjs +202 -0
- package/codemods/transforms/cm-15-dom-selectors.mjs +16 -9
- package/dist/brand-scope-BOHId6BY.d.ts +58 -0
- package/dist/brand-theme-ZYM867Jz.d.ts +59 -0
- package/dist/chunk-2MKLYYIY.js +3754 -0
- package/dist/chunk-2MKLYYIY.js.map +1 -0
- package/dist/chunk-6S2R2VWN.js +5527 -0
- package/dist/chunk-6S2R2VWN.js.map +1 -0
- package/dist/chunk-7U3ADR2Q.js +4336 -0
- package/dist/chunk-7U3ADR2Q.js.map +1 -0
- package/dist/chunk-CPOGSNXS.js +389 -0
- package/dist/chunk-CPOGSNXS.js.map +1 -0
- package/dist/chunk-EUHGZA6Q.js +313 -0
- package/dist/chunk-EUHGZA6Q.js.map +1 -0
- package/dist/chunk-KQBYTTAN.js +1829 -0
- package/dist/chunk-KQBYTTAN.js.map +1 -0
- package/dist/chunk-X76J4QSJ.js +164 -0
- package/dist/chunk-X76J4QSJ.js.map +1 -0
- package/dist/css/components.css +1 -1
- package/dist/css/legacy-aliases.css +2 -0
- package/dist/css/tailwind.css +2 -0
- package/dist/css/tokens.css +8 -6
- package/dist/data-table-view-ep8al7P9.d.ts +1132 -0
- package/dist/design-system-provider-CfD2g2lY.d.ts +142 -0
- package/dist/icons/index.d.ts +441 -3
- package/dist/icons/index.js +2 -1835
- package/dist/icons/index.js.map +1 -1
- package/dist/index.d.ts +404 -3847
- package/dist/index.js +8728 -24213
- package/dist/index.js.map +1 -1
- package/dist/legacy/index.d.ts +1464 -0
- package/dist/legacy/index.js +7 -0
- package/dist/legacy/index.js.map +1 -0
- package/dist/next/index.d.ts +2 -1
- package/dist/reference-BkDbrPIB.d.ts +310 -0
- package/dist/styles.css +2 -1
- package/dist/suite/index.d.ts +989 -0
- package/dist/suite/index.js +8 -0
- package/dist/suite/index.js.map +1 -0
- package/dist/{system-CyAVbHhM.d.ts → system-DfJIVBlJ.d.ts} +1 -310
- package/dist/testing/index.cjs +3 -2
- package/dist/testing/index.js +3 -2
- package/dist/tokens/index.d.ts +3 -61
- package/dist/tokens/index.js +3 -856
- package/dist/tokens/index.js.map +1 -1
- package/dist/{design-system-provider-B5MbvbRc.d.ts → types-Coqw8iaS.d.ts} +36 -142
- package/dist/vocab-DornLJbW.d.ts +76 -0
- package/docs/components.md +54 -52
- package/docs/components.registry.json +22 -8
- package/docs/for-ai-agents.md +12 -6
- package/package.json +17 -4
- package/public/brand/assure-audit-mark.svg +6 -0
- package/public/brand/assure-audit.svg +8 -0
- package/public/brand/assure-books-mark.svg +6 -0
- package/public/brand/assure-books.svg +8 -0
- package/public/brand/assure-pro-mark.svg +6 -0
- package/public/brand/assure-pro.svg +8 -0
- package/public/brand/assure-tax-mark.svg +6 -0
- package/public/brand/assure-tax.svg +8 -0
- package/public/brand/mycpe-teams-mark.svg +36 -0
- package/public/brand/mycpe-teams.svg +66 -0
- 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
|