@ceebee/ui 0.5.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -1,22 +1,146 @@
1
1
  "use client";
2
- import { createContext, forwardRef, useContext, useMemo, useState, useRef, useEffect, useCallback, useId, isValidElement, cloneElement, Fragment, useReducer, Children } from 'react';
3
- import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
4
- import { motion } from 'motion/react';
5
- import { Select as Select$1 } from '@base-ui/react/select';
6
- import { ChevronLeft, ChevronRight, ChevronsUpDown, Check, Minus, X, CalendarDays, Clock, Upload as Upload$1, Plus, Search, Star, PanelLeftOpen, PanelLeftClose, ArrowUp, ArrowDown, XCircle, AlertTriangle, CheckCircle2, Info } from 'lucide-react';
7
- import { Checkbox as Checkbox$1 } from '@base-ui/react/checkbox';
8
- import { Radio } from '@base-ui/react/radio';
9
- import { RadioGroup as RadioGroup$1 } from '@base-ui/react/radio-group';
10
- import { Switch as Switch$1 } from '@base-ui/react/switch';
11
- import { Combobox } from '@base-ui/react/combobox';
12
- import { Popover as Popover$1 } from '@base-ui/react/popover';
2
+ import { theme, ConfigProvider, Progress } from 'antd';
3
+ export * from 'antd';
4
+ import { createContext, useState, useCallback, useEffect, useMemo, useContext, Children } from 'react';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ export { default as enUSLocale } from 'antd/locale/en_US';
7
+ export { default as enUSDatePickerLocale } from 'antd/es/date-picker/locale/en_US';
8
+ export { default as idIDLocale } from 'antd/locale/id_ID';
9
+ export { default as zhCNLocale } from 'antd/locale/zh_CN';
13
10
  import { Dialog } from '@base-ui/react/dialog';
14
- import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
11
+ import { Search, Check, ChevronRight, X, PanelLeftOpen, PanelLeftClose, Info, XCircle, AlertTriangle, CheckCircle2 } from 'lucide-react';
15
12
  import { Toast } from '@base-ui/react/toast';
16
- import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
17
- import { Menu } from '@base-ui/react/menu';
18
- import useEmblaCarousel from 'embla-carousel-react';
13
+ import { Popover } from '@base-ui/react/popover';
14
+ import { motion } from 'motion/react';
19
15
 
16
+ var SKIN_LINK_ID = "cb-skin";
17
+ function ThemeBridge({ children, mode, theme: theme$1 }) {
18
+ const [skinToken, setSkinToken] = useState({ token: {}, components: {} });
19
+ const refresh = useCallback(() => {
20
+ setSkinToken(readCeebeeThemeToken(document.documentElement));
21
+ }, []);
22
+ useEffect(() => {
23
+ refresh();
24
+ const rootObserver = new MutationObserver(refresh);
25
+ rootObserver.observe(document.documentElement, {
26
+ attributes: true,
27
+ attributeFilter: ["data-theme"]
28
+ });
29
+ const headObserver = new MutationObserver((records) => {
30
+ const skinChanged = records.some((record) => [...record.addedNodes, ...record.removedNodes].some((node) => node instanceof HTMLElement && node.id === SKIN_LINK_ID));
31
+ if (skinChanged) refresh();
32
+ });
33
+ headObserver.observe(document.head, { childList: true });
34
+ const onSkinLoad = (event) => {
35
+ if (event.target instanceof HTMLElement && event.target.id === SKIN_LINK_ID) refresh();
36
+ };
37
+ document.addEventListener("load", onSkinLoad, true);
38
+ return () => {
39
+ rootObserver.disconnect();
40
+ headObserver.disconnect();
41
+ document.removeEventListener("load", onSkinLoad, true);
42
+ };
43
+ }, [refresh]);
44
+ const mergedTheme = useMemo(() => ({
45
+ ...theme$1,
46
+ algorithm: theme$1?.algorithm ?? (mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm),
47
+ cssVar: theme$1?.cssVar ?? { prefix: "cb-ant" },
48
+ token: { ...skinToken.token, ...theme$1?.token },
49
+ components: mergeComponents(skinToken.components, theme$1?.components)
50
+ }), [mode, skinToken, theme$1]);
51
+ useEffect(() => {
52
+ ConfigProvider.config({
53
+ holderRender: (holder) => /* @__PURE__ */ jsx(ConfigProvider, { theme: mergedTheme, children: holder })
54
+ });
55
+ }, [mergedTheme]);
56
+ return /* @__PURE__ */ jsx(ConfigProvider, { theme: mergedTheme, children });
57
+ }
58
+ function mergeComponents(base, override) {
59
+ if (!override) return base;
60
+ const merged = { ...base };
61
+ for (const [name, tokens] of Object.entries(override)) {
62
+ merged[name] = { ...merged[name], ...tokens };
63
+ }
64
+ return merged;
65
+ }
66
+ function readCeebeeThemeToken(root) {
67
+ const probe = document.createElement("span");
68
+ probe.style.position = "fixed";
69
+ probe.style.pointerEvents = "none";
70
+ probe.style.visibility = "hidden";
71
+ root.append(probe);
72
+ const color = (name) => resolveCssColor(probe, name);
73
+ const length = (name) => resolveCssLength(probe, name);
74
+ const tokens = {
75
+ colorPrimary: color("--cb-tone-brand"),
76
+ colorInfo: color("--cb-tone-info"),
77
+ colorSuccess: color("--cb-tone-success"),
78
+ colorWarning: color("--cb-tone-warning"),
79
+ colorError: color("--cb-tone-danger"),
80
+ colorText: color("--cb-fg"),
81
+ colorTextSecondary: color("--cb-fg-muted"),
82
+ colorTextTertiary: color("--cb-fg-subtle"),
83
+ colorTextLightSolid: color("--cb-fg-on-brand"),
84
+ colorBgBase: color("--cb-bg"),
85
+ colorBgContainer: color("--cb-surface"),
86
+ colorBgElevated: color("--cb-surface-raised"),
87
+ colorBorder: color("--cb-border-strong"),
88
+ colorBorderSecondary: color("--cb-border"),
89
+ fontFamily: "var(--cb-font-sans)",
90
+ fontSize: length("--cb-text-sm"),
91
+ fontSizeSM: length("--cb-text-xs"),
92
+ fontSizeLG: length("--cb-text-md"),
93
+ borderRadius: length("--cb-radius-sm"),
94
+ borderRadiusLG: length("--cb-radius-md"),
95
+ controlHeight: length("--cb-control-height-md"),
96
+ controlHeightSM: length("--cb-control-height-sm"),
97
+ controlHeightLG: length("--cb-control-height-lg"),
98
+ lineWidth: length("--cb-border-width"),
99
+ boxShadow: "var(--cb-shadow-md)",
100
+ boxShadowSecondary: "var(--cb-shadow-sm)"
101
+ };
102
+ const components = {};
103
+ const trackBg = color("--cb-brand-300");
104
+ const trackHoverBg = color("--cb-brand-400");
105
+ if (trackBg && trackHoverBg) {
106
+ components.Slider = {
107
+ trackBg,
108
+ trackHoverBg,
109
+ handleColor: trackBg,
110
+ dotActiveBorderColor: trackBg
111
+ };
112
+ }
113
+ probe.remove();
114
+ return {
115
+ token: Object.fromEntries(
116
+ Object.entries(tokens).filter(([, value]) => value !== void 0)
117
+ ),
118
+ components
119
+ };
120
+ }
121
+ function resolveCssLength(probe, name) {
122
+ probe.style.width = `var(${name})`;
123
+ const value = Number.parseFloat(getComputedStyle(probe).width);
124
+ probe.style.removeProperty("width");
125
+ return Number.isFinite(value) ? value : void 0;
126
+ }
127
+ function resolveCssColor(probe, name) {
128
+ probe.style.color = `var(${name})`;
129
+ const value = getComputedStyle(probe).color;
130
+ probe.style.removeProperty("color");
131
+ if (!value) return void 0;
132
+ if (/^(?:#|rgb|hsl|hsv)/i.test(value)) return value;
133
+ const canvas = document.createElement("canvas");
134
+ canvas.width = 1;
135
+ canvas.height = 1;
136
+ const context = canvas.getContext("2d", { willReadFrequently: true });
137
+ if (!context) return void 0;
138
+ context.clearRect(0, 0, 1, 1);
139
+ context.fillStyle = value;
140
+ context.fillRect(0, 0, 1, 1);
141
+ const [red = 0, green = 0, blue = 0, alpha = 255] = context.getImageData(0, 0, 1, 1).data;
142
+ return `rgba(${red}, ${green}, ${blue}, ${alpha / 255})`;
143
+ }
20
144
  var DEFAULT_LABELS = {
21
145
  dismiss: "Dismiss",
22
146
  close: "Close",
@@ -42,11 +166,7 @@ var DEFAULT_LABELS = {
42
166
  decrease: "Decrease",
43
167
  expandNavigation: "Expand navigation",
44
168
  collapseNavigation: "Collapse navigation",
45
- back: "Back",
46
- next: "Next",
47
- done: "Done",
48
- skip: "Skip",
49
- progress: (current, total) => `${current} of ${total}`
169
+ next: "Next"
50
170
  };
51
171
  var LabelsContext = createContext(DEFAULT_LABELS);
52
172
  function LabelsProvider({ children, labels }) {
@@ -100,7 +220,8 @@ var STORAGE_KEY = "cb-theme";
100
220
  function ThemeProvider({
101
221
  children,
102
222
  defaultChoice = "system",
103
- persist = true
223
+ persist = true,
224
+ antdTheme: antdTheme2
104
225
  }) {
105
226
  const [choice, setChoiceState] = useState(defaultChoice);
106
227
  const [systemDark, setSystemDark] = useState(false);
@@ -129,7 +250,7 @@ function ThemeProvider({
129
250
  [persist]
130
251
  );
131
252
  const resolved = choice === "system" ? systemDark ? "dark" : "light" : choice;
132
- return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { choice, setChoice, resolved }, children });
253
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { choice, setChoice, resolved }, children: /* @__PURE__ */ jsx(ThemeBridge, { mode: resolved, theme: antdTheme2, children }) });
133
254
  }
134
255
  function useTheme() {
135
256
  const value = useContext(ThemeContext);
@@ -141,1084 +262,6 @@ function useTheme() {
141
262
  function cn(...parts) {
142
263
  return parts.filter(Boolean).join(" ");
143
264
  }
144
- var Button = forwardRef(function Button2({
145
- variant = "solid",
146
- tone = "brand",
147
- size = "md",
148
- loading = false,
149
- iconStart,
150
- iconEnd,
151
- motion: motionProp = true,
152
- className,
153
- children,
154
- disabled,
155
- ...rest
156
- }, ref) {
157
- const { enabled, spring } = useMotionSettings();
158
- const animate = enabled && motionProp;
159
- const iconOnly = children === void 0 || children === null || children === false || children === "";
160
- return /* @__PURE__ */ jsxs(
161
- motion.button,
162
- {
163
- ref,
164
- className: cn(
165
- "cb-button",
166
- `cb-button--${variant}`,
167
- `cb-button--${size}`,
168
- iconOnly && "cb-button--icon",
169
- className
170
- ),
171
- "data-tone": tone,
172
- "data-loading": loading || void 0,
173
- disabled: disabled ?? loading,
174
- "aria-busy": loading || void 0,
175
- whileTap: animate ? { scale: 0.97 } : void 0,
176
- whileHover: animate ? { y: -1 } : void 0,
177
- transition: spring("snappy"),
178
- ...rest,
179
- children: [
180
- loading ? /* @__PURE__ */ jsx("span", { className: "cb-button__spinner", "aria-hidden": "true" }) : iconStart,
181
- iconOnly ? null : /* @__PURE__ */ jsx("span", { className: "cb-button__label", children }),
182
- loading || iconOnly ? null : iconEnd
183
- ]
184
- }
185
- );
186
- });
187
- var FieldContext = createContext(null);
188
- function useFieldWiring() {
189
- return useContext(FieldContext);
190
- }
191
- function Field({ label, hint, error, required = false, labelHidden = false, className, children }) {
192
- const base = useId();
193
- const controlId = `${base}-control`;
194
- const hintId = hint ? `${base}-hint` : void 0;
195
- const errorId = error && error !== true ? `${base}-error` : void 0;
196
- const describedBy = [hintId, errorId].filter(Boolean).join(" ") || void 0;
197
- return /* @__PURE__ */ jsx(FieldContext.Provider, { value: { controlId, describedBy, invalid: Boolean(error), required }, children: /* @__PURE__ */ jsxs("div", { className: cn("cb-field", className), "data-invalid": error ? "" : void 0, children: [
198
- /* @__PURE__ */ jsxs("label", { className: cn("cb-field__label", labelHidden && "cb-visually-hidden"), htmlFor: controlId, children: [
199
- label,
200
- required ? /* @__PURE__ */ jsx("span", { className: "cb-field__required", "aria-hidden": "true", children: "*" }) : null
201
- ] }),
202
- children,
203
- hint ? /* @__PURE__ */ jsx("p", { className: "cb-field__hint", id: hintId, children: hint }) : null,
204
- error && error !== true ? /* @__PURE__ */ jsx("p", { className: "cb-field__error", id: errorId, role: "alert", children: error }) : null
205
- ] }) });
206
- }
207
- var Input = forwardRef(function Input2({ size = "md", invalid, className, ...rest }, ref) {
208
- const field = useFieldWiring();
209
- return /* @__PURE__ */ jsx(
210
- "input",
211
- {
212
- ref,
213
- className: cn("cb-input", `cb-input--${size}`, className),
214
- id: rest.id ?? field?.controlId,
215
- "aria-describedby": rest["aria-describedby"] ?? field?.describedBy,
216
- "aria-invalid": invalid ?? field?.invalid ? true : void 0,
217
- required: rest.required ?? field?.required,
218
- ...rest
219
- }
220
- );
221
- });
222
- var Textarea = forwardRef(function Textarea2({ invalid, className, ...rest }, ref) {
223
- const field = useFieldWiring();
224
- return /* @__PURE__ */ jsx(
225
- "textarea",
226
- {
227
- ref,
228
- className: cn("cb-input", "cb-input--textarea", className),
229
- id: rest.id ?? field?.controlId,
230
- "aria-describedby": rest["aria-describedby"] ?? field?.describedBy,
231
- "aria-invalid": invalid ?? field?.invalid ? true : void 0,
232
- required: rest.required ?? field?.required,
233
- ...rest
234
- }
235
- );
236
- });
237
- function Select({
238
- items,
239
- value,
240
- defaultValue,
241
- onValueChange,
242
- placeholder = "Select\u2026",
243
- size = "md",
244
- disabled,
245
- invalid,
246
- name,
247
- id,
248
- className
249
- }) {
250
- const field = useFieldWiring();
251
- return /* @__PURE__ */ jsxs(
252
- Select$1.Root,
253
- {
254
- items,
255
- value,
256
- defaultValue,
257
- onValueChange: (next) => onValueChange?.(next),
258
- disabled,
259
- name,
260
- children: [
261
- /* @__PURE__ */ jsxs(
262
- Select$1.Trigger,
263
- {
264
- id: id ?? field?.controlId,
265
- "aria-describedby": field?.describedBy,
266
- "aria-invalid": invalid ?? field?.invalid ? true : void 0,
267
- className: cn("cb-select", `cb-select--${size}`, className),
268
- children: [
269
- /* @__PURE__ */ jsx(Select$1.Value, { placeholder }),
270
- /* @__PURE__ */ jsx(Select$1.Icon, { className: "cb-select__icon", children: /* @__PURE__ */ jsx(ChevronsUpDown, { size: 16 }) })
271
- ]
272
- }
273
- ),
274
- /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(
275
- Select$1.Positioner,
276
- {
277
- sideOffset: 6,
278
- alignItemWithTrigger: false,
279
- className: "cb-select__positioner",
280
- children: /* @__PURE__ */ jsx(Select$1.Popup, { className: "cb-select__popup", children: items.map((item) => /* @__PURE__ */ jsxs(Select$1.Item, { value: item.value, disabled: item.disabled, className: "cb-select__item", children: [
281
- /* @__PURE__ */ jsx("span", { className: "cb-select__check", children: /* @__PURE__ */ jsx(Select$1.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { size: 14 }) }) }),
282
- /* @__PURE__ */ jsx(Select$1.ItemText, { children: item.label })
283
- ] }, item.value)) })
284
- }
285
- ) })
286
- ]
287
- }
288
- );
289
- }
290
- function Checkbox({
291
- label,
292
- checked,
293
- defaultChecked,
294
- indeterminate,
295
- onCheckedChange,
296
- disabled,
297
- name,
298
- value,
299
- description,
300
- className
301
- }) {
302
- const generated = useId();
303
- const field = useFieldWiring();
304
- const id = field?.controlId ?? generated;
305
- const descriptionId = description ? `${id}-description` : void 0;
306
- return /* @__PURE__ */ jsxs("div", { className: cn("cb-choice", className), children: [
307
- /* @__PURE__ */ jsx(
308
- Checkbox$1.Root,
309
- {
310
- id,
311
- checked,
312
- defaultChecked,
313
- indeterminate,
314
- onCheckedChange: (next) => onCheckedChange?.(next),
315
- disabled,
316
- name,
317
- value,
318
- "aria-describedby": [descriptionId, field?.describedBy].filter(Boolean).join(" ") || void 0,
319
- className: "cb-checkbox",
320
- children: /* @__PURE__ */ jsx(Checkbox$1.Indicator, { className: "cb-checkbox__indicator", children: indeterminate ? /* @__PURE__ */ jsx(Minus, { size: 12, strokeWidth: 3 }) : /* @__PURE__ */ jsx(Check, { size: 12, strokeWidth: 3 }) })
321
- }
322
- ),
323
- /* @__PURE__ */ jsxs("div", { className: "cb-choice__text", children: [
324
- /* @__PURE__ */ jsx("label", { htmlFor: id, className: "cb-choice__label", children: label }),
325
- description ? /* @__PURE__ */ jsx("p", { className: "cb-choice__description", id: descriptionId, children: description }) : null
326
- ] })
327
- ] });
328
- }
329
- function RadioGroup({
330
- options,
331
- value,
332
- defaultValue,
333
- onValueChange,
334
- name,
335
- label,
336
- direction = "column",
337
- variant = "list",
338
- disabled,
339
- className
340
- }) {
341
- const groupId = useId();
342
- const field = useFieldWiring();
343
- return /* @__PURE__ */ jsx(
344
- RadioGroup$1,
345
- {
346
- value,
347
- defaultValue,
348
- onValueChange: (next) => onValueChange?.(next),
349
- name,
350
- disabled,
351
- "aria-label": label,
352
- "aria-describedby": field?.describedBy,
353
- className: cn(
354
- "cb-radio-group",
355
- `cb-radio-group--${variant === "segmented" ? "row" : direction}`,
356
- variant === "segmented" && "cb-radio-group--segmented",
357
- className
358
- ),
359
- children: options.map((option) => {
360
- const id = `${groupId}-${option.value}`;
361
- const descriptionId = option.description ? `${id}-description` : void 0;
362
- return /* @__PURE__ */ jsxs("div", { className: "cb-choice", children: [
363
- /* @__PURE__ */ jsx(
364
- Radio.Root,
365
- {
366
- id,
367
- value: option.value,
368
- disabled: option.disabled,
369
- "aria-describedby": descriptionId,
370
- className: "cb-radio",
371
- children: /* @__PURE__ */ jsx(Radio.Indicator, { className: "cb-radio__indicator" })
372
- }
373
- ),
374
- /* @__PURE__ */ jsxs("div", { className: "cb-choice__text", children: [
375
- /* @__PURE__ */ jsx("label", { htmlFor: id, className: "cb-choice__label", children: option.label }),
376
- option.description ? /* @__PURE__ */ jsx("p", { className: "cb-choice__description", id: descriptionId, children: option.description }) : null
377
- ] })
378
- ] }, option.value);
379
- })
380
- }
381
- );
382
- }
383
- function Switch({
384
- label,
385
- checked,
386
- defaultChecked,
387
- onCheckedChange,
388
- disabled,
389
- name,
390
- description,
391
- justified = false,
392
- className
393
- }) {
394
- const generated = useId();
395
- const field = useFieldWiring();
396
- const id = field?.controlId ?? generated;
397
- const descriptionId = description ? `${id}-description` : void 0;
398
- return /* @__PURE__ */ jsxs("div", { className: cn("cb-choice", justified && "cb-choice--justified", className), children: [
399
- justified ? null : /* @__PURE__ */ jsx(
400
- Switch$1.Root,
401
- {
402
- id,
403
- checked,
404
- defaultChecked,
405
- onCheckedChange: (next) => onCheckedChange?.(next),
406
- disabled,
407
- name,
408
- "aria-describedby": [descriptionId, field?.describedBy].filter(Boolean).join(" ") || void 0,
409
- className: "cb-switch",
410
- children: /* @__PURE__ */ jsx(Switch$1.Thumb, { className: "cb-switch__thumb" })
411
- }
412
- ),
413
- /* @__PURE__ */ jsxs("div", { className: "cb-choice__text", children: [
414
- /* @__PURE__ */ jsx("label", { htmlFor: id, className: "cb-choice__label", children: label }),
415
- description ? /* @__PURE__ */ jsx("p", { className: "cb-choice__description", id: descriptionId, children: description }) : null
416
- ] }),
417
- justified ? /* @__PURE__ */ jsx(
418
- Switch$1.Root,
419
- {
420
- id,
421
- checked,
422
- defaultChecked,
423
- onCheckedChange: (next) => onCheckedChange?.(next),
424
- disabled,
425
- name,
426
- "aria-describedby": [descriptionId, field?.describedBy].filter(Boolean).join(" ") || void 0,
427
- className: "cb-switch",
428
- children: /* @__PURE__ */ jsx(Switch$1.Thumb, { className: "cb-switch__thumb" })
429
- }
430
- ) : null
431
- ] });
432
- }
433
- function AutoComplete({
434
- items,
435
- loadItems,
436
- loadDelay = 250,
437
- value,
438
- defaultValue,
439
- onValueChange,
440
- placeholder = "Search\u2026",
441
- emptyMessage = "Nothing matched",
442
- loadingMessage = "Searching\u2026",
443
- errorMessage = "Could not search",
444
- size = "md",
445
- disabled,
446
- invalid,
447
- name,
448
- id,
449
- className
450
- }) {
451
- const field = useFieldWiring();
452
- const labels = useLabels();
453
- const async = Boolean(loadItems);
454
- const shell = useRef(null);
455
- const [loaded, setLoaded] = useState([]);
456
- const [loading, setLoading] = useState(false);
457
- const [failed, setFailed] = useState(false);
458
- const [chosen, setChosen] = useState(null);
459
- const [open, setOpen] = useState(false);
460
- const available = async ? loaded : items ?? [];
461
- const optionFor = (candidate) => {
462
- if (candidate == null) return null;
463
- if (chosen?.value === candidate) return chosen;
464
- return available.find((item) => item.value === candidate) ?? null;
465
- };
466
- const asked = useRef(0);
467
- const inFlight = useRef(null);
468
- const search = useCallback((query2) => {
469
- if (!loadItems) return;
470
- const seq = asked.current + 1;
471
- asked.current = seq;
472
- inFlight.current?.abort();
473
- const controller = new AbortController();
474
- inFlight.current = controller;
475
- setLoading(true);
476
- setFailed(false);
477
- loadItems(query2, controller.signal).then(
478
- (next) => {
479
- if (seq !== asked.current) return;
480
- setLoaded(next);
481
- setLoading(false);
482
- },
483
- () => {
484
- if (seq !== asked.current || controller.signal.aborted) return;
485
- setLoaded([]);
486
- setFailed(true);
487
- setLoading(false);
488
- }
489
- );
490
- }, [loadItems]);
491
- const [query, setQuery] = useState("");
492
- useEffect(() => {
493
- if (!async) return void 0;
494
- const id2 = setTimeout(() => search(query), loadDelay);
495
- return () => clearTimeout(id2);
496
- }, [async, query, loadDelay, search]);
497
- useEffect(() => () => {
498
- asked.current += 1;
499
- inFlight.current?.abort();
500
- }, []);
501
- useEffect(() => {
502
- if (!open) return void 0;
503
- const onScroll = (event) => {
504
- const target = event.target;
505
- if (target === document || target === document.documentElement || target === document.body) {
506
- setOpen(false);
507
- }
508
- };
509
- window.addEventListener("scroll", onScroll, { capture: true, passive: true });
510
- return () => window.removeEventListener("scroll", onScroll, { capture: true });
511
- }, [open]);
512
- return /* @__PURE__ */ jsxs(
513
- Combobox.Root,
514
- {
515
- items: available,
516
- filter: async ? null : void 0,
517
- onInputValueChange: async ? (next) => setQuery(next) : void 0,
518
- value: value === void 0 ? void 0 : optionFor(value),
519
- defaultValue: defaultValue === void 0 ? void 0 : optionFor(defaultValue),
520
- onValueChange: (next) => {
521
- const option = next;
522
- setChosen(option);
523
- onValueChange?.(option?.value ?? null);
524
- },
525
- modal: true,
526
- open,
527
- onOpenChange: setOpen,
528
- isItemEqualToValue: (a, b) => a?.value === b?.value,
529
- itemToStringLabel: (item) => typeof item === "string" ? item : item.label,
530
- disabled,
531
- name,
532
- children: [
533
- /* @__PURE__ */ jsxs(
534
- "div",
535
- {
536
- ref: shell,
537
- className: cn("cb-autocomplete", `cb-autocomplete--${size}`, className),
538
- "data-disabled": disabled || void 0,
539
- children: [
540
- /* @__PURE__ */ jsx(
541
- Combobox.Input,
542
- {
543
- className: "cb-autocomplete__input",
544
- placeholder,
545
- id: id ?? field?.controlId,
546
- "aria-describedby": field?.describedBy,
547
- "aria-invalid": invalid ?? field?.invalid ? true : void 0
548
- }
549
- ),
550
- /* @__PURE__ */ jsx(Combobox.Clear, { className: "cb-autocomplete__clear", "aria-label": labels.clear, children: /* @__PURE__ */ jsx(X, { size: 14 }) }),
551
- /* @__PURE__ */ jsx(Combobox.Trigger, { className: "cb-autocomplete__trigger", "aria-label": labels.open, children: /* @__PURE__ */ jsx(ChevronsUpDown, { size: 16 }) })
552
- ]
553
- }
554
- ),
555
- /* @__PURE__ */ jsx(Combobox.Portal, { children: /* @__PURE__ */ jsx(Combobox.Positioner, { anchor: shell, sideOffset: 6, className: "cb-autocomplete__positioner", children: /* @__PURE__ */ jsxs(Combobox.Popup, { className: "cb-autocomplete__popup", children: [
556
- loading ? /* @__PURE__ */ jsx("p", { className: "cb-autocomplete__status", role: "status", children: loadingMessage }) : failed ? /* @__PURE__ */ jsx("p", { className: "cb-autocomplete__status", role: "alert", children: errorMessage }) : /* @__PURE__ */ jsx(Combobox.Empty, { className: "cb-autocomplete__empty", children: emptyMessage }),
557
- /* @__PURE__ */ jsx(Combobox.List, { children: (item) => /* @__PURE__ */ jsxs(
558
- Combobox.Item,
559
- {
560
- value: item,
561
- disabled: item.disabled,
562
- className: "cb-autocomplete__item",
563
- children: [
564
- /* @__PURE__ */ jsx("span", { className: "cb-autocomplete__check", children: /* @__PURE__ */ jsx(Combobox.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { size: 14 }) }) }),
565
- /* @__PURE__ */ jsxs("span", { className: "cb-autocomplete__text", children: [
566
- /* @__PURE__ */ jsx("span", { className: "cb-autocomplete__label", children: item.label }),
567
- item.description ? /* @__PURE__ */ jsx("span", { className: "cb-autocomplete__description", children: item.description }) : null
568
- ] })
569
- ]
570
- },
571
- item.value
572
- ) })
573
- ] }) }) })
574
- ]
575
- }
576
- );
577
- }
578
-
579
- // src/form/date.util.ts
580
- function isSameDay(a, b) {
581
- if (!a || !b) return false;
582
- return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
583
- }
584
- function startOfDay(date) {
585
- return new Date(date.getFullYear(), date.getMonth(), date.getDate());
586
- }
587
- function monthMatrix(year, month, weekStartsOn = 1) {
588
- const first = new Date(year, month, 1);
589
- const offset = (first.getDay() - weekStartsOn + 7) % 7;
590
- const start = new Date(year, month, 1 - offset);
591
- const weeks = [];
592
- for (let week = 0; week < 6; week += 1) {
593
- const cells = [];
594
- for (let day = 0; day < 7; day += 1) {
595
- const date = new Date(start.getFullYear(), start.getMonth(), start.getDate() + week * 7 + day);
596
- cells.push({ date, inMonth: date.getMonth() === month });
597
- }
598
- weeks.push(cells);
599
- }
600
- return weeks;
601
- }
602
- function parseDateInput(input) {
603
- const text2 = input.trim();
604
- if (!text2) return null;
605
- const iso = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(text2);
606
- if (iso) return build(Number(iso[1]), Number(iso[2]), Number(iso[3]));
607
- const dayFirst = /^(\d{1,2})[/.-](\d{1,2})[/.-](\d{2,4})$/.exec(text2);
608
- if (dayFirst) {
609
- const year = Number(dayFirst[3]);
610
- return build(year < 100 ? 2e3 + year : year, Number(dayFirst[2]), Number(dayFirst[1]));
611
- }
612
- return null;
613
- }
614
- function build(year, month, day) {
615
- if (month < 1 || month > 12 || day < 1 || day > 31) return null;
616
- const date = new Date(year, month - 1, day);
617
- if (date.getMonth() !== month - 1 || date.getDate() !== day) return null;
618
- return date;
619
- }
620
- function formatISO(date) {
621
- if (!date) return "";
622
- const month = String(date.getMonth() + 1).padStart(2, "0");
623
- const day = String(date.getDate()).padStart(2, "0");
624
- return `${date.getFullYear()}-${month}-${day}`;
625
- }
626
- function isOutOfRange(date, min, max) {
627
- if (min && startOfDay(date) < startOfDay(min)) return true;
628
- if (max && startOfDay(date) > startOfDay(max)) return true;
629
- return false;
630
- }
631
- var WEEKDAYS = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
632
- function DatePicker({
633
- value,
634
- defaultValue = null,
635
- onValueChange,
636
- min,
637
- max,
638
- format,
639
- weekStartsOn = 1,
640
- size = "md",
641
- disabled,
642
- invalid,
643
- placeholder = "dd/mm/yyyy",
644
- className
645
- }) {
646
- const field = useFieldWiring();
647
- const labels = useLabels();
648
- const controlled = value !== void 0;
649
- const [internal, setInternal] = useState(defaultValue);
650
- const current = controlled ? value ?? null : internal;
651
- const display = (date) => format ? format(date) : date.toLocaleDateString(void 0, { day: "2-digit", month: "short", year: "numeric" });
652
- const [text2, setText] = useState(() => current ? display(current) : "");
653
- const [open, setOpen] = useState(false);
654
- const [cursor, setCursor] = useState(() => current ?? /* @__PURE__ */ new Date());
655
- const fieldRef = useRef(null);
656
- const commit = (next) => {
657
- if (!controlled) setInternal(next);
658
- setText(next ? display(next) : "");
659
- onValueChange?.(next);
660
- };
661
- const weeks = monthMatrix(cursor.getFullYear(), cursor.getMonth(), weekStartsOn);
662
- const weekdays = weekStartsOn === 1 ? WEEKDAYS : [WEEKDAYS[6], ...WEEKDAYS.slice(0, 6)];
663
- return /* @__PURE__ */ jsxs(Popover$1.Root, { open, onOpenChange: setOpen, children: [
664
- /* @__PURE__ */ jsxs(
665
- "div",
666
- {
667
- ref: fieldRef,
668
- className: cn("cb-date", `cb-date--${size}`, className),
669
- "data-disabled": disabled || void 0,
670
- children: [
671
- /* @__PURE__ */ jsx(
672
- "input",
673
- {
674
- className: "cb-date__input",
675
- id: field?.controlId,
676
- value: controlled ? current ? display(current) : text2 : text2,
677
- placeholder,
678
- disabled,
679
- "aria-describedby": field?.describedBy,
680
- "aria-invalid": invalid ?? field?.invalid ? true : void 0,
681
- onClick: () => !disabled && setOpen(true),
682
- onChange: (event) => setText(event.target.value),
683
- onBlur: () => {
684
- const parsed = parseDateInput(text2);
685
- if (parsed && !isOutOfRange(parsed, min, max)) {
686
- commit(parsed);
687
- setCursor(parsed);
688
- } else {
689
- commit(null);
690
- }
691
- }
692
- }
693
- ),
694
- /* @__PURE__ */ jsx(
695
- Popover$1.Trigger,
696
- {
697
- className: "cb-date__trigger",
698
- "aria-label": labels.chooseDate,
699
- disabled,
700
- render: /* @__PURE__ */ jsx("button", { type: "button" }),
701
- children: /* @__PURE__ */ jsx(CalendarDays, { size: 16 })
702
- }
703
- )
704
- ]
705
- }
706
- ),
707
- /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
708
- Popover$1.Positioner,
709
- {
710
- anchor: fieldRef,
711
- side: "bottom",
712
- align: "start",
713
- sideOffset: 6,
714
- className: "cb-calendar__positioner",
715
- children: /* @__PURE__ */ jsxs(Popover$1.Popup, { className: "cb-calendar", children: [
716
- /* @__PURE__ */ jsxs("div", { className: "cb-calendar__head", children: [
717
- /* @__PURE__ */ jsx(
718
- "button",
719
- {
720
- type: "button",
721
- className: "cb-calendar__nav",
722
- "aria-label": labels.previousMonth,
723
- onClick: () => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1)),
724
- children: /* @__PURE__ */ jsx(ChevronLeft, { size: 16 })
725
- }
726
- ),
727
- /* @__PURE__ */ jsx("p", { className: "cb-calendar__month", "aria-live": "polite", children: cursor.toLocaleDateString(void 0, { month: "long", year: "numeric" }) }),
728
- /* @__PURE__ */ jsx(
729
- "button",
730
- {
731
- type: "button",
732
- className: "cb-calendar__nav",
733
- "aria-label": labels.nextMonth,
734
- onClick: () => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1)),
735
- children: /* @__PURE__ */ jsx(ChevronRight, { size: 16 })
736
- }
737
- )
738
- ] }),
739
- /* @__PURE__ */ jsxs("table", { className: "cb-calendar__grid", children: [
740
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: weekdays.map((day) => /* @__PURE__ */ jsx("th", { scope: "col", abbr: day, children: day }, day)) }) }),
741
- /* @__PURE__ */ jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsx("tr", { children: week.map((cell) => {
742
- const selected = isSameDay(cell.date, current);
743
- const outside = isOutOfRange(cell.date, min, max);
744
- return /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
745
- "button",
746
- {
747
- type: "button",
748
- className: "cb-calendar__day",
749
- "data-outside": !cell.inMonth || void 0,
750
- "data-selected": selected || void 0,
751
- "data-today": isSameDay(cell.date, /* @__PURE__ */ new Date()) || void 0,
752
- disabled: outside,
753
- "aria-pressed": selected,
754
- "aria-label": formatISO(cell.date),
755
- onClick: () => {
756
- commit(cell.date);
757
- setCursor(cell.date);
758
- setOpen(false);
759
- },
760
- children: cell.date.getDate()
761
- }
762
- ) }, cell.date.toISOString());
763
- }) }, weekIndex)) })
764
- ] })
765
- ] })
766
- }
767
- ) })
768
- ] });
769
- }
770
-
771
- // src/form/time.util.ts
772
- function parseTime(input) {
773
- const text2 = input.trim().toLowerCase().replace(/\s+/g, "");
774
- if (!text2) return null;
775
- const suffix = text2.endsWith("am") ? "am" : text2.endsWith("pm") ? "pm" : null;
776
- const body = suffix ? text2.slice(0, -2) : text2;
777
- let hours;
778
- let minutes = 0;
779
- const separated = /^(\d{1,2})[:.](\d{1,2})$/.exec(body);
780
- const compact = /^(\d{3,4})$/.exec(body);
781
- const hourOnly = /^(\d{1,2})$/.exec(body);
782
- if (separated) {
783
- hours = Number(separated[1]);
784
- minutes = Number(separated[2]);
785
- } else if (compact) {
786
- const digits = compact[1].padStart(4, "0");
787
- hours = Number(digits.slice(0, 2));
788
- minutes = Number(digits.slice(2));
789
- } else if (hourOnly) {
790
- hours = Number(hourOnly[1]);
791
- } else {
792
- return null;
793
- }
794
- if (suffix === "pm" && hours < 12) hours += 12;
795
- if (suffix === "am" && hours === 12) hours = 0;
796
- if (hours > 23 || minutes > 59) return null;
797
- return { hours, minutes };
798
- }
799
- function formatTime({ hours, minutes }) {
800
- return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
801
- }
802
- function timeToMinutes({ hours, minutes }) {
803
- return hours * 60 + minutes;
804
- }
805
- function timeOptions(step, min, max) {
806
- const safeStep = step > 0 ? step : 30;
807
- const from = min ? timeToMinutes(min) : 0;
808
- const to = max ? timeToMinutes(max) : 24 * 60 - 1;
809
- const options = [];
810
- for (let value = from; value <= to; value += safeStep) {
811
- options.push({ hours: Math.floor(value / 60) % 24, minutes: value % 60 });
812
- }
813
- return options;
814
- }
815
- function isTimeOutOfRange(value, min, max) {
816
- const minutes = timeToMinutes(value);
817
- if (min && minutes < timeToMinutes(min)) return true;
818
- if (max && minutes > timeToMinutes(max)) return true;
819
- return false;
820
- }
821
- function TimePicker({
822
- value,
823
- defaultValue = null,
824
- onValueChange,
825
- min,
826
- max,
827
- step = 30,
828
- size = "md",
829
- disabled,
830
- invalid,
831
- placeholder = "hh:mm",
832
- className
833
- }) {
834
- const field = useFieldWiring();
835
- const labels = useLabels();
836
- const controlled = value !== void 0;
837
- const [internal, setInternal] = useState(defaultValue);
838
- const current = controlled ? value ?? null : internal;
839
- const [text2, setText] = useState(() => current ? formatTime(current) : "");
840
- const [open, setOpen] = useState(false);
841
- const fieldRef = useRef(null);
842
- const commit = (next) => {
843
- if (!controlled) setInternal(next);
844
- setText(next ? formatTime(next) : "");
845
- onValueChange?.(next);
846
- };
847
- const options = timeOptions(step, min, max);
848
- return /* @__PURE__ */ jsxs(Popover$1.Root, { open, onOpenChange: setOpen, children: [
849
- /* @__PURE__ */ jsxs(
850
- "div",
851
- {
852
- ref: fieldRef,
853
- className: cn("cb-date", `cb-date--${size}`, className),
854
- "data-disabled": disabled || void 0,
855
- children: [
856
- /* @__PURE__ */ jsx(
857
- "input",
858
- {
859
- className: "cb-date__input",
860
- id: field?.controlId,
861
- value: controlled ? current ? formatTime(current) : text2 : text2,
862
- placeholder,
863
- disabled,
864
- inputMode: "numeric",
865
- "aria-describedby": field?.describedBy,
866
- "aria-invalid": invalid ?? field?.invalid ? true : void 0,
867
- onClick: () => !disabled && setOpen(true),
868
- onChange: (event) => setText(event.target.value),
869
- onBlur: () => {
870
- const parsed = parseTime(text2);
871
- commit(parsed && !isTimeOutOfRange(parsed, min, max) ? parsed : null);
872
- }
873
- }
874
- ),
875
- /* @__PURE__ */ jsx(
876
- Popover$1.Trigger,
877
- {
878
- className: "cb-date__trigger",
879
- "aria-label": labels.chooseTime,
880
- disabled,
881
- render: /* @__PURE__ */ jsx("button", { type: "button" }),
882
- children: /* @__PURE__ */ jsx(Clock, { size: 16 })
883
- }
884
- )
885
- ]
886
- }
887
- ),
888
- /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
889
- Popover$1.Positioner,
890
- {
891
- anchor: fieldRef,
892
- side: "bottom",
893
- align: "start",
894
- sideOffset: 6,
895
- className: "cb-times__positioner",
896
- children: /* @__PURE__ */ jsx(Popover$1.Popup, { className: "cb-times", children: /* @__PURE__ */ jsx("ul", { className: "cb-times__list", children: options.map((option) => {
897
- const selected = current ? timeToMinutes(current) === timeToMinutes(option) : false;
898
- return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
899
- "button",
900
- {
901
- type: "button",
902
- className: "cb-times__option",
903
- "data-selected": selected || void 0,
904
- "aria-pressed": selected,
905
- onClick: () => {
906
- commit(option);
907
- setOpen(false);
908
- },
909
- children: formatTime(option)
910
- }
911
- ) }, formatTime(option));
912
- }) }) })
913
- }
914
- ) })
915
- ] });
916
- }
917
-
918
- // src/form/upload.util.ts
919
- function matchesAccept(file, accept) {
920
- if (!accept || accept.length === 0) return true;
921
- const name = file.name.toLowerCase();
922
- return accept.some((pattern) => {
923
- const rule = pattern.trim().toLowerCase();
924
- if (rule.startsWith(".")) return name.endsWith(rule);
925
- if (rule.endsWith("/*")) return file.type.startsWith(rule.slice(0, -1));
926
- return file.type === rule;
927
- });
928
- }
929
- function partitionFiles(incoming, existing, rules) {
930
- const accepted = [];
931
- const rejected = [];
932
- const limit = rules.multiple === false ? 1 : rules.maxFiles;
933
- for (const file of incoming) {
934
- if (!matchesAccept(file, rules.accept)) {
935
- rejected.push({ file, reason: "type" });
936
- continue;
937
- }
938
- if (typeof rules.maxSize === "number" && file.size > rules.maxSize) {
939
- rejected.push({ file, reason: "size" });
940
- continue;
941
- }
942
- if (typeof limit === "number" && existing.length + accepted.length >= limit) {
943
- rejected.push({ file, reason: "count" });
944
- continue;
945
- }
946
- accepted.push(file);
947
- }
948
- return { accepted, rejected };
949
- }
950
- function describeAccept(rules) {
951
- const parts = [];
952
- if (rules.accept?.length) parts.push(rules.accept.join(", "));
953
- if (typeof rules.maxSize === "number") parts.push(`up to ${Math.round(rules.maxSize / (1024 * 1024))} MB`);
954
- return parts.length > 0 ? ` \u2014 ${parts.join(" ")}` : "";
955
- }
956
- function Upload({
957
- onFilesChange,
958
- files = [],
959
- onReject,
960
- accept,
961
- maxSize,
962
- maxFiles,
963
- multiple = true,
964
- disabled,
965
- children,
966
- className
967
- }) {
968
- const [over, setOver] = useState(false);
969
- const field = useFieldWiring();
970
- const labels = useLabels();
971
- const rules = { accept, maxSize, maxFiles, multiple };
972
- const take = (incoming) => {
973
- if (!incoming) return;
974
- const { accepted, rejected } = partitionFiles(Array.from(incoming), files, rules);
975
- if (accepted.length > 0) onFilesChange([...files, ...accepted]);
976
- if (rejected.length > 0) onReject?.(rejected);
977
- };
978
- const onDrop = (event) => {
979
- event.preventDefault();
980
- setOver(false);
981
- if (!disabled) take(event.dataTransfer.files);
982
- };
983
- return /* @__PURE__ */ jsxs("div", { className: cn("cb-filedrop", className), children: [
984
- /* @__PURE__ */ jsxs(
985
- "label",
986
- {
987
- className: "cb-filedrop__zone",
988
- "data-over": over || void 0,
989
- "data-disabled": disabled || void 0,
990
- onDragOver: (event) => {
991
- event.preventDefault();
992
- if (!disabled) setOver(true);
993
- },
994
- onDragLeave: () => setOver(false),
995
- onDrop,
996
- children: [
997
- /* @__PURE__ */ jsx(
998
- "input",
999
- {
1000
- type: "file",
1001
- className: "cb-visually-hidden",
1002
- id: field?.controlId,
1003
- accept: accept?.join(","),
1004
- multiple,
1005
- disabled,
1006
- "aria-describedby": field?.describedBy,
1007
- onChange: (event) => {
1008
- take(event.target.files);
1009
- event.target.value = "";
1010
- }
1011
- }
1012
- ),
1013
- /* @__PURE__ */ jsx("span", { className: "cb-filedrop__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Upload$1, { size: 20 }) }),
1014
- /* @__PURE__ */ jsx("span", { className: "cb-filedrop__button", children: multiple ? labels.chooseFiles : labels.chooseFile }),
1015
- /* @__PURE__ */ jsxs("p", { className: "cb-filedrop__hint", children: [
1016
- multiple ? labels.dropFilesHere : labels.dropFileHere,
1017
- describeAccept(rules)
1018
- ] }),
1019
- children
1020
- ]
1021
- }
1022
- ),
1023
- files.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "cb-filedrop__list", children: files.map((file, index) => /* @__PURE__ */ jsxs("li", { className: "cb-filedrop__file", children: [
1024
- /* @__PURE__ */ jsx("span", { className: "cb-filedrop__name", children: file.name }),
1025
- /* @__PURE__ */ jsx("span", { className: "cb-filedrop__size", children: formatSize(file.size) }),
1026
- /* @__PURE__ */ jsx(
1027
- "button",
1028
- {
1029
- type: "button",
1030
- className: "cb-filedrop__remove",
1031
- "aria-label": labels.removeFile(file.name),
1032
- onClick: () => onFilesChange(files.filter((_, i) => i !== index)),
1033
- children: /* @__PURE__ */ jsx(X, { size: 14 })
1034
- }
1035
- )
1036
- ] }, `${file.name}-${index}`)) }) : null
1037
- ] });
1038
- }
1039
- function formatSize(bytes) {
1040
- if (bytes < 1024) return `${bytes} B`;
1041
- if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
1042
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1043
- }
1044
-
1045
- // src/form/number.ts
1046
- function parseNumber(input) {
1047
- const trimmed = input.trim().replace(/\s/g, "").replace(",", ".");
1048
- if (trimmed === "" || trimmed === "-" || trimmed === ".") return null;
1049
- const parsed = Number(trimmed);
1050
- return Number.isFinite(parsed) ? parsed : null;
1051
- }
1052
- function clamp(value, { min, max }) {
1053
- let next = value;
1054
- if (typeof min === "number") next = Math.max(next, min);
1055
- if (typeof max === "number") next = Math.min(next, max);
1056
- return next;
1057
- }
1058
- function stepBy(value, direction, bounds) {
1059
- const step = bounds.step ?? 1;
1060
- const base = value ?? bounds.min ?? 0;
1061
- const next = base + direction * step;
1062
- const decimals = decimalPlaces(step);
1063
- const rounded = Number(next.toFixed(decimals));
1064
- return clamp(rounded, bounds);
1065
- }
1066
- function decimalPlaces(step) {
1067
- const text2 = String(step);
1068
- const dot = text2.indexOf(".");
1069
- return dot === -1 ? 0 : text2.length - dot - 1;
1070
- }
1071
- function canStep(value, direction, bounds) {
1072
- if (value === null) return true;
1073
- if (direction === 1) return typeof bounds.max !== "number" || value < bounds.max;
1074
- return typeof bounds.min !== "number" || value > bounds.min;
1075
- }
1076
- function InputNumber({
1077
- value,
1078
- defaultValue = null,
1079
- onValueChange,
1080
- min,
1081
- max,
1082
- step = 1,
1083
- size = "md",
1084
- disabled,
1085
- invalid,
1086
- name,
1087
- placeholder,
1088
- suffix,
1089
- className
1090
- }) {
1091
- const field = useFieldWiring();
1092
- const labels = useLabels();
1093
- const controlled = value !== void 0;
1094
- const [internal, setInternal] = useState(defaultValue);
1095
- const [text2, setText] = useState(() => formatValue(controlled ? value ?? null : defaultValue));
1096
- const current = controlled ? value ?? null : internal;
1097
- const bounds = { min, max, step };
1098
- const commit = (next) => {
1099
- if (!controlled) setInternal(next);
1100
- setText(formatValue(next));
1101
- onValueChange?.(next);
1102
- };
1103
- const onType = (event) => {
1104
- setText(event.target.value);
1105
- const parsed = parseNumber(event.target.value);
1106
- if (parsed === null) {
1107
- onValueChange?.(null);
1108
- if (!controlled) setInternal(null);
1109
- return;
1110
- }
1111
- if (!controlled) setInternal(parsed);
1112
- onValueChange?.(parsed);
1113
- };
1114
- return /* @__PURE__ */ jsxs("div", { className: cn("cb-number", `cb-number--${size}`, className), "data-disabled": disabled || void 0, children: [
1115
- /* @__PURE__ */ jsx(
1116
- "input",
1117
- {
1118
- className: "cb-number__input",
1119
- inputMode: "decimal",
1120
- id: field?.controlId,
1121
- name,
1122
- value: controlled ? formatValue(value ?? null) : text2,
1123
- placeholder,
1124
- disabled,
1125
- "aria-describedby": field?.describedBy,
1126
- "aria-invalid": invalid ?? field?.invalid ? true : void 0,
1127
- onChange: onType,
1128
- onBlur: () => {
1129
- const parsed = parseNumber(text2);
1130
- commit(parsed === null ? null : clamp(parsed, bounds));
1131
- }
1132
- }
1133
- ),
1134
- suffix ? /* @__PURE__ */ jsx("span", { className: "cb-number__suffix", "aria-hidden": "true", children: suffix }) : null,
1135
- /* @__PURE__ */ jsxs("span", { className: "cb-number__steppers", children: [
1136
- /* @__PURE__ */ jsx(
1137
- "button",
1138
- {
1139
- type: "button",
1140
- className: "cb-number__step",
1141
- "aria-label": labels.decrease,
1142
- disabled: disabled || !canStep(current, -1, bounds),
1143
- onClick: () => commit(stepBy(current, -1, bounds)),
1144
- children: /* @__PURE__ */ jsx(Minus, { size: 14 })
1145
- }
1146
- ),
1147
- /* @__PURE__ */ jsx(
1148
- "button",
1149
- {
1150
- type: "button",
1151
- className: "cb-number__step",
1152
- "aria-label": labels.increase,
1153
- disabled: disabled || !canStep(current, 1, bounds),
1154
- onClick: () => commit(stepBy(current, 1, bounds)),
1155
- children: /* @__PURE__ */ jsx(Plus, { size: 14 })
1156
- }
1157
- )
1158
- ] })
1159
- ] });
1160
- }
1161
- function formatValue(value) {
1162
- return value === null ? "" : String(value);
1163
- }
1164
- function Modal({
1165
- open,
1166
- defaultOpen,
1167
- onOpenChange,
1168
- title,
1169
- description,
1170
- children,
1171
- footer,
1172
- size = "md",
1173
- placement = "center",
1174
- trigger,
1175
- className
1176
- }) {
1177
- return /* @__PURE__ */ jsxs(Dialog.Root, { open, defaultOpen, onOpenChange, children: [
1178
- trigger ? /* @__PURE__ */ jsx(Dialog.Trigger, { render: trigger }) : null,
1179
- /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
1180
- /* @__PURE__ */ jsx(Dialog.Backdrop, { className: "cb-modal__backdrop" }),
1181
- /* @__PURE__ */ jsxs(
1182
- Dialog.Popup,
1183
- {
1184
- className: cn("cb-modal", `cb-modal--${size}`, `cb-modal--${placement}`, className),
1185
- children: [
1186
- /* @__PURE__ */ jsx(Dialog.Title, { className: "cb-modal__title", children: title }),
1187
- description ? /* @__PURE__ */ jsx(Dialog.Description, { className: "cb-modal__description", children: description }) : null,
1188
- children ? /* @__PURE__ */ jsx("div", { className: "cb-modal__body", children }) : null,
1189
- footer ? /* @__PURE__ */ jsx("div", { className: "cb-modal__footer", children: footer }) : null
1190
- ]
1191
- }
1192
- )
1193
- ] })
1194
- ] });
1195
- }
1196
- var DialogClose = Dialog.Close;
1197
- function Drawer({
1198
- open,
1199
- defaultOpen,
1200
- onOpenChange,
1201
- title,
1202
- description,
1203
- children,
1204
- footer,
1205
- trigger,
1206
- className
1207
- }) {
1208
- return /* @__PURE__ */ jsxs(Dialog.Root, { open, defaultOpen, onOpenChange, children: [
1209
- trigger ? /* @__PURE__ */ jsx(Dialog.Trigger, { render: trigger }) : null,
1210
- /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
1211
- /* @__PURE__ */ jsx(Dialog.Backdrop, { className: "cb-drawer__backdrop" }),
1212
- /* @__PURE__ */ jsxs(Dialog.Popup, { className: cn("cb-drawer", className), children: [
1213
- /* @__PURE__ */ jsx(Dialog.Title, { className: "cb-drawer__title", children: title }),
1214
- description ? /* @__PURE__ */ jsx(Dialog.Description, { className: "cb-drawer__description", children: description }) : null,
1215
- children ? /* @__PURE__ */ jsx("div", { className: "cb-drawer__body", children }) : null,
1216
- footer ? /* @__PURE__ */ jsx("div", { className: "cb-drawer__footer", children: footer }) : null
1217
- ] })
1218
- ] })
1219
- ] });
1220
- }
1221
- var DrawerClose = Dialog.Close;
1222
265
 
1223
266
  // src/overlay/command.util.ts
1224
267
  function rankCommand(command, query) {
@@ -1328,36 +371,6 @@ function CommandPalette({
1328
371
  ] })
1329
372
  ] }) });
1330
373
  }
1331
- function ProgressBar({ value, max = 100, tone = "brand", size = "md", label, showValue, className }) {
1332
- const indeterminate = value === void 0;
1333
- const clamped = indeterminate ? 0 : Math.min(Math.max(value, 0), max);
1334
- const percent = max > 0 ? Math.round(clamped / max * 100) : 0;
1335
- return /* @__PURE__ */ jsxs("div", { className: cn("cb-progress", className), "data-tone": tone, "data-size": size, children: [
1336
- /* @__PURE__ */ jsx(
1337
- "div",
1338
- {
1339
- className: "cb-progress__track",
1340
- role: "progressbar",
1341
- "aria-label": label,
1342
- "aria-valuemin": indeterminate ? void 0 : 0,
1343
- "aria-valuemax": indeterminate ? void 0 : max,
1344
- "aria-valuenow": indeterminate ? void 0 : clamped,
1345
- children: /* @__PURE__ */ jsx(
1346
- "div",
1347
- {
1348
- className: "cb-progress__fill",
1349
- "data-indeterminate": indeterminate || void 0,
1350
- style: indeterminate ? void 0 : { width: `${percent}%` }
1351
- }
1352
- )
1353
- }
1354
- ),
1355
- showValue && !indeterminate ? /* @__PURE__ */ jsxs("span", { className: "cb-progress__value", children: [
1356
- percent,
1357
- "%"
1358
- ] }) : null
1359
- ] });
1360
- }
1361
374
  function Checklist({ title = "Get started", tasks, completeSlot, className }) {
1362
375
  const done = tasks.filter((task) => task.done).length;
1363
376
  const complete = tasks.length > 0 && done === tasks.length;
@@ -1370,7 +383,15 @@ function Checklist({ title = "Get started", tasks, completeSlot, className }) {
1370
383
  tasks.length
1371
384
  ] })
1372
385
  ] }),
1373
- /* @__PURE__ */ jsx(ProgressBar, { value: done, max: Math.max(tasks.length, 1), size: "sm", label: `${done} of ${tasks.length} tasks done` }),
386
+ /* @__PURE__ */ jsx(
387
+ Progress,
388
+ {
389
+ percent: done / Math.max(tasks.length, 1) * 100,
390
+ size: "small",
391
+ showInfo: false,
392
+ "aria-label": `${done} of ${tasks.length} tasks done`
393
+ }
394
+ ),
1374
395
  complete && completeSlot ? /* @__PURE__ */ jsx("div", { className: "cb-checklist__complete", children: completeSlot }) : /* @__PURE__ */ jsx("ul", { className: "cb-checklist__list", children: tasks.map((task) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
1375
396
  "button",
1376
397
  {
@@ -1394,199 +415,6 @@ function Checklist({ title = "Get started", tasks, completeSlot, className }) {
1394
415
  ) }, task.id)) })
1395
416
  ] });
1396
417
  }
1397
- function Popover({
1398
- trigger,
1399
- children,
1400
- side = "bottom",
1401
- align = "center",
1402
- sideOffset = 8,
1403
- showArrow = true,
1404
- open,
1405
- onOpenChange,
1406
- className
1407
- }) {
1408
- return /* @__PURE__ */ jsxs(Popover$1.Root, { open, onOpenChange, children: [
1409
- /* @__PURE__ */ jsx(Popover$1.Trigger, { render: trigger }),
1410
- /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
1411
- Popover$1.Positioner,
1412
- {
1413
- side,
1414
- align,
1415
- sideOffset,
1416
- className: "cb-popover-positioner",
1417
- children: /* @__PURE__ */ jsxs(Popover$1.Popup, { className: cn("cb-popover", className), children: [
1418
- showArrow ? /* @__PURE__ */ jsx(Popover$1.Arrow, { className: "cb-popover__arrow", children: /* @__PURE__ */ jsx(ArrowShape, {}) }) : null,
1419
- children
1420
- ] })
1421
- }
1422
- ) })
1423
- ] });
1424
- }
1425
- function Tooltip({
1426
- children,
1427
- label,
1428
- side = "top",
1429
- align = "center",
1430
- sideOffset = 6,
1431
- showArrow = true,
1432
- delay = 400
1433
- }) {
1434
- return /* @__PURE__ */ jsx(Tooltip$1.Provider, { delay, children: /* @__PURE__ */ jsxs(Tooltip$1.Root, { children: [
1435
- /* @__PURE__ */ jsx(Tooltip$1.Trigger, { render: children }),
1436
- /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsx(
1437
- Tooltip$1.Positioner,
1438
- {
1439
- side,
1440
- align,
1441
- sideOffset,
1442
- className: "cb-tooltip-positioner",
1443
- children: /* @__PURE__ */ jsxs(Tooltip$1.Popup, { className: "cb-tooltip", children: [
1444
- showArrow ? /* @__PURE__ */ jsx(Tooltip$1.Arrow, { className: "cb-tooltip__arrow", children: /* @__PURE__ */ jsx(ArrowShape, {}) }) : null,
1445
- label
1446
- ] })
1447
- }
1448
- ) })
1449
- ] }) });
1450
- }
1451
- function ArrowShape() {
1452
- return /* @__PURE__ */ jsxs(
1453
- "svg",
1454
- {
1455
- className: "cb-arrow",
1456
- viewBox: "0 0 16 8",
1457
- preserveAspectRatio: "none",
1458
- "aria-hidden": "true",
1459
- focusable: "false",
1460
- children: [
1461
- /* @__PURE__ */ jsx("path", { className: "cb-arrow__fill", d: "M0 8 L8 0 L16 8 Z" }),
1462
- /* @__PURE__ */ jsx("path", { className: "cb-arrow__edge", d: "M0 8 L8 0 L16 8" })
1463
- ]
1464
- }
1465
- );
1466
- }
1467
- function Tag({
1468
- children,
1469
- tone = "neutral",
1470
- variant = "soft",
1471
- size = "md",
1472
- icon,
1473
- onClick,
1474
- pressed,
1475
- onClose,
1476
- render,
1477
- className
1478
- }) {
1479
- const labels = useLabels();
1480
- const classes = cn("cb-badge", "cb-tag", `cb-badge--${variant}`, `cb-badge--${size}`, className);
1481
- const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [
1482
- icon,
1483
- children
1484
- ] });
1485
- if (render && isValidElement(render)) {
1486
- return cloneElement(render, {
1487
- className: cn(classes, "cb-tag--pressable", render.props.className),
1488
- "data-tone": tone,
1489
- children: body
1490
- });
1491
- }
1492
- if (onClose) {
1493
- return /* @__PURE__ */ jsxs("span", { className: classes, "data-tone": tone, children: [
1494
- body,
1495
- /* @__PURE__ */ jsx("button", { type: "button", className: "cb-tag__close", "aria-label": labels.dismiss, onClick: onClose, children: /* @__PURE__ */ jsx(X, { size: 12 }) })
1496
- ] });
1497
- }
1498
- if (onClick) {
1499
- return /* @__PURE__ */ jsx(
1500
- "button",
1501
- {
1502
- type: "button",
1503
- className: cn(classes, "cb-tag--pressable"),
1504
- "data-tone": tone,
1505
- "aria-pressed": pressed,
1506
- onClick,
1507
- children: body
1508
- }
1509
- );
1510
- }
1511
- return /* @__PURE__ */ jsx("span", { className: classes, "data-tone": tone, children: body });
1512
- }
1513
- function Rate({
1514
- value,
1515
- onValueChange,
1516
- count = 5,
1517
- size = 20,
1518
- readOnly = false,
1519
- label,
1520
- className
1521
- }) {
1522
- const group = useId();
1523
- const field = useFieldWiring();
1524
- const scores = Array.from({ length: count }, (_, i) => i + 1);
1525
- if (readOnly) {
1526
- return /* @__PURE__ */ jsx(
1527
- "span",
1528
- {
1529
- className: cn("cb-rate", "cb-rate--static", className),
1530
- role: "img",
1531
- "aria-label": label ? `${label}: ${value}/${count}` : `${value}/${count}`,
1532
- children: scores.map((n) => /* @__PURE__ */ jsx(Star, { size, strokeWidth: 2.5, fill: value >= n ? "currentColor" : "none" }, n))
1533
- }
1534
- );
1535
- }
1536
- return /* @__PURE__ */ jsx(
1537
- "span",
1538
- {
1539
- className: cn("cb-rate", className),
1540
- role: "radiogroup",
1541
- "aria-label": label,
1542
- "aria-describedby": field?.describedBy,
1543
- children: scores.map((n) => /* @__PURE__ */ jsx(
1544
- "button",
1545
- {
1546
- id: `${group}-${n}`,
1547
- type: "button",
1548
- className: "cb-rate__star",
1549
- role: "radio",
1550
- "aria-checked": value === n,
1551
- "aria-label": `${n}/${count}`,
1552
- onClick: () => onValueChange?.(value === n ? 0 : n),
1553
- children: /* @__PURE__ */ jsx(Star, { size, strokeWidth: 2.5, fill: value >= n ? "currentColor" : "none" })
1554
- },
1555
- n
1556
- ))
1557
- }
1558
- );
1559
- }
1560
- var ICONS = {
1561
- neutral: /* @__PURE__ */ jsx(Info, { size: 18 }),
1562
- brand: /* @__PURE__ */ jsx(Info, { size: 18 }),
1563
- info: /* @__PURE__ */ jsx(Info, { size: 18 }),
1564
- success: /* @__PURE__ */ jsx(CheckCircle2, { size: 18 }),
1565
- warning: /* @__PURE__ */ jsx(AlertTriangle, { size: 18 }),
1566
- danger: /* @__PURE__ */ jsx(XCircle, { size: 18 })
1567
- };
1568
- function Alert({ title, children, tone = "info", icon, actions, onDismiss, className }) {
1569
- const labels = useLabels();
1570
- const assertive = tone === "danger" || tone === "warning";
1571
- return /* @__PURE__ */ jsxs(
1572
- "div",
1573
- {
1574
- className: cn("cb-alert", className),
1575
- "data-tone": tone,
1576
- role: assertive ? "alert" : "status",
1577
- "aria-live": assertive ? "assertive" : "polite",
1578
- children: [
1579
- icon === null ? null : /* @__PURE__ */ jsx("span", { className: "cb-alert__icon", children: icon ?? ICONS[tone] }),
1580
- /* @__PURE__ */ jsxs("div", { className: "cb-alert__body", children: [
1581
- title ? /* @__PURE__ */ jsx("p", { className: "cb-alert__title", children: title }) : null,
1582
- children ? /* @__PURE__ */ jsx("div", { className: "cb-alert__text", children }) : null,
1583
- actions ? /* @__PURE__ */ jsx("div", { className: "cb-alert__actions", children: actions }) : null
1584
- ] }),
1585
- onDismiss ? /* @__PURE__ */ jsx("button", { type: "button", className: "cb-alert__close", "aria-label": labels.dismiss, onClick: onDismiss, children: /* @__PURE__ */ jsx(X, { size: 16 }) }) : null
1586
- ]
1587
- }
1588
- );
1589
- }
1590
418
  function ToastProvider({
1591
419
  children,
1592
420
  timeout = 5e3,
@@ -1598,7 +426,7 @@ function ToastProvider({
1598
426
  /* @__PURE__ */ jsx(Toast.Portal, { children: /* @__PURE__ */ jsx(Toast.Viewport, { className: "cb-toast__viewport", "data-position": position, children: /* @__PURE__ */ jsx(ToastList, {}) }) })
1599
427
  ] });
1600
428
  }
1601
- var ICONS2 = {
429
+ var ICONS = {
1602
430
  success: /* @__PURE__ */ jsx(CheckCircle2, { size: 16 }),
1603
431
  warning: /* @__PURE__ */ jsx(AlertTriangle, { size: 16 }),
1604
432
  danger: /* @__PURE__ */ jsx(XCircle, { size: 16 }),
@@ -1609,7 +437,7 @@ function ToastList() {
1609
437
  const { toasts } = Toast.useToastManager();
1610
438
  const labels = useLabels();
1611
439
  return toasts.map((toast) => /* @__PURE__ */ jsxs(Toast.Root, { toast, className: cn("cb-toast"), "data-tone": toast.type ?? "neutral", children: [
1612
- /* @__PURE__ */ jsx("span", { className: "cb-toast__icon", children: ICONS2[toast.type ?? "info"] ?? ICONS2.info }),
440
+ /* @__PURE__ */ jsx("span", { className: "cb-toast__icon", children: ICONS[toast.type ?? "info"] ?? ICONS.info }),
1613
441
  /* @__PURE__ */ jsxs(Toast.Content, { className: "cb-toast__content", children: [
1614
442
  /* @__PURE__ */ jsx(Toast.Title, { className: "cb-toast__title" }),
1615
443
  /* @__PURE__ */ jsx(Toast.Description, { className: "cb-toast__description" })
@@ -1633,65 +461,6 @@ function useToast() {
1633
461
  promise: manager.promise
1634
462
  };
1635
463
  }
1636
- function Tabs({ items, value, defaultValue, onValueChange, variant = "underline", className }) {
1637
- return /* @__PURE__ */ jsxs(
1638
- Tabs$1.Root,
1639
- {
1640
- value,
1641
- defaultValue: defaultValue ?? items[0]?.value,
1642
- onValueChange: (next) => onValueChange?.(String(next)),
1643
- className: cn("cb-tabs", `cb-tabs--${variant}`, className),
1644
- children: [
1645
- /* @__PURE__ */ jsxs(Tabs$1.List, { className: "cb-tabs__list", children: [
1646
- items.map((item) => /* @__PURE__ */ jsxs(Tabs$1.Tab, { value: item.value, disabled: item.disabled, className: "cb-tabs__tab", children: [
1647
- item.label,
1648
- item.adornment ? /* @__PURE__ */ jsx("span", { className: "cb-tabs__adornment", children: item.adornment }) : null
1649
- ] }, item.value)),
1650
- /* @__PURE__ */ jsx(Tabs$1.Indicator, { className: "cb-tabs__indicator" })
1651
- ] }),
1652
- items.map((item) => /* @__PURE__ */ jsx(Tabs$1.Panel, { value: item.value, className: "cb-tabs__panel", children: item.content }, item.value))
1653
- ]
1654
- }
1655
- );
1656
- }
1657
- function Dropdown({ trigger, items, sections, align = "end", side = "bottom", className }) {
1658
- const groups = sections ?? [{ items }];
1659
- return /* @__PURE__ */ jsxs(Menu.Root, { children: [
1660
- /* @__PURE__ */ jsx(Menu.Trigger, { render: trigger }),
1661
- /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
1662
- Menu.Positioner,
1663
- {
1664
- side,
1665
- align,
1666
- sideOffset: 6,
1667
- className: "cb-menu-positioner",
1668
- children: /* @__PURE__ */ jsx(Menu.Popup, { className: cn("cb-menu", className), children: groups.map((section, sectionIndex) => /* @__PURE__ */ jsxs(Fragment, { children: [
1669
- sectionIndex > 0 ? /* @__PURE__ */ jsx(Menu.Separator, { className: "cb-menu__separator" }) : null,
1670
- /* @__PURE__ */ jsxs(Menu.Group, { className: "cb-menu__group", children: [
1671
- section.label ? /* @__PURE__ */ jsx(Menu.GroupLabel, { className: "cb-menu__group-label", children: section.label }) : null,
1672
- section.items.map(
1673
- (item, itemIndex) => item.separator ? /* @__PURE__ */ jsx(Menu.Separator, { className: "cb-menu__separator" }, `separator-${itemIndex}`) : /* @__PURE__ */ jsxs(
1674
- Menu.Item,
1675
- {
1676
- className: "cb-menu__item",
1677
- "data-tone": item.tone,
1678
- disabled: item.disabled,
1679
- onClick: item.onSelect,
1680
- children: [
1681
- /* @__PURE__ */ jsx("span", { className: "cb-menu__icon", children: item.checked ? /* @__PURE__ */ jsx(Check, { size: 14 }) : item.icon }),
1682
- /* @__PURE__ */ jsx("span", { className: "cb-menu__label", children: item.label }),
1683
- item.shortcut ? /* @__PURE__ */ jsx("kbd", { className: "cb-menu__shortcut", children: item.shortcut }) : null
1684
- ]
1685
- },
1686
- `${String(item.label)}-${itemIndex}`
1687
- )
1688
- )
1689
- ] })
1690
- ] }, `section-${sectionIndex}`)) })
1691
- }
1692
- ) })
1693
- ] });
1694
- }
1695
464
  var hasActiveChild = (item) => Boolean(item.items?.some((child) => child.active));
1696
465
  function Sidebar({ sections, header, footer, collapsed = false, onCollapsedChange, className }) {
1697
466
  const labels = useLabels();
@@ -1733,7 +502,7 @@ function SidebarEntry({ item, collapsed }) {
1733
502
  if (collapsed) {
1734
503
  return /* @__PURE__ */ jsx(Flyout, { label: item.label, items: children, children: /* @__PURE__ */ jsx(SidebarRow, { item: { ...item, active: item.active || hasActiveChild(item) }, collapsed: true }) });
1735
504
  }
1736
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
505
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1737
506
  /* @__PURE__ */ jsxs(
1738
507
  "button",
1739
508
  {
@@ -1754,7 +523,7 @@ function SidebarEntry({ item, collapsed }) {
1754
523
  ] });
1755
524
  }
1756
525
  function SidebarRow({ item, collapsed, nested }) {
1757
- const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
526
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1758
527
  item.icon ? /* @__PURE__ */ jsx("span", { className: "cb-sidebar__icon", children: item.icon }) : null,
1759
528
  /* @__PURE__ */ jsx("span", { className: "cb-sidebar__label", children: item.label }),
1760
529
  item.adornment && !collapsed ? /* @__PURE__ */ jsx("span", { className: "cb-sidebar__adornment", children: item.adornment }) : null
@@ -1767,9 +536,9 @@ function SidebarRow({ item, collapsed, nested }) {
1767
536
  return item.href ? /* @__PURE__ */ jsx("a", { href: item.href, ...props, children: content }) : /* @__PURE__ */ jsx("button", { type: "button", onClick: item.onClick, ...props, children: content });
1768
537
  }
1769
538
  function Flyout({ label, items, children }) {
1770
- return /* @__PURE__ */ jsxs(Popover$1.Root, { children: [
539
+ return /* @__PURE__ */ jsxs(Popover.Root, { children: [
1771
540
  /* @__PURE__ */ jsx(
1772
- Popover$1.Trigger,
541
+ Popover.Trigger,
1773
542
  {
1774
543
  openOnHover: true,
1775
544
  delay: 120,
@@ -1777,7 +546,7 @@ function Flyout({ label, items, children }) {
1777
546
  render: /* @__PURE__ */ jsx("span", { className: "cb-sidebar__flyout-trigger", children })
1778
547
  }
1779
548
  ),
1780
- /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { side: "right", align: "start", sideOffset: 8, className: "cb-sidebar__flyout-positioner", children: /* @__PURE__ */ jsxs(Popover$1.Popup, { className: "cb-sidebar__flyout", children: [
549
+ /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, { side: "right", align: "start", sideOffset: 8, className: "cb-sidebar__flyout-positioner", children: /* @__PURE__ */ jsxs(Popover.Popup, { className: "cb-sidebar__flyout", children: [
1781
550
  /* @__PURE__ */ jsx("p", { className: "cb-sidebar__flyout-title", children: label }),
1782
551
  items?.length ? /* @__PURE__ */ jsx("div", { className: "cb-sidebar__flyout-items", children: items.map((child, index) => /* @__PURE__ */ jsx(SidebarRow, { item: child, collapsed: false }, index)) }) : null
1783
552
  ] }) }) })
@@ -1793,578 +562,6 @@ function TopBar({ title, subtitle, center, actions, sticky = true, className })
1793
562
  actions ? /* @__PURE__ */ jsx("div", { className: "cb-topbar__actions", children: actions }) : null
1794
563
  ] });
1795
564
  }
1796
- function box({ width = "100%", height = "1rem", radius = "md", className }) {
1797
- const style = { "--cb-skeleton-w": width, "--cb-skeleton-h": height };
1798
- return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("cb-skeleton", `cb-radius--${radius}`, className), style });
1799
- }
1800
- function text({ lines = 3, lastLineWidth = "62%", className }) {
1801
- return /* @__PURE__ */ jsx("span", { className: cn("cb-skeleton-text", className), children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx(SkeletonBox, { height: "0.75rem", width: i === lines - 1 ? lastLineWidth : "100%" }, i)) });
1802
- }
1803
- function circle({ size = "2.5rem", className }) {
1804
- return /* @__PURE__ */ jsx(SkeletonBox, { width: size, height: size, radius: "full", className });
1805
- }
1806
- var SkeletonBox = box;
1807
- var Skeleton = Object.assign(box, {
1808
- Text: text,
1809
- Circle: circle,
1810
- Rect: box
1811
- });
1812
-
1813
- // src/data/table-sort.ts
1814
- function nextSort(current, column) {
1815
- if (!current || current.column !== column) return { column, direction: "asc" };
1816
- if (current.direction === "asc") return { column, direction: "desc" };
1817
- return null;
1818
- }
1819
- function ariaSortFor(current, column) {
1820
- if (!current || current.column !== column) return "none";
1821
- return current.direction === "asc" ? "ascending" : "descending";
1822
- }
1823
- function pageRange(page, pageSize, total, siblings = 1) {
1824
- const totalPages = Math.max(Math.ceil(total / Math.max(pageSize, 1)), 1);
1825
- const current = Math.min(Math.max(page, 1), totalPages);
1826
- const from = total === 0 ? 0 : (current - 1) * pageSize + 1;
1827
- const to = Math.min(current * pageSize, total);
1828
- const pages = /* @__PURE__ */ new Set([1, totalPages]);
1829
- for (let offset = -siblings; offset <= siblings; offset += 1) {
1830
- const candidate = current + offset;
1831
- if (candidate >= 1 && candidate <= totalPages) pages.add(candidate);
1832
- }
1833
- const sorted = [...pages].sort((a, b) => a - b);
1834
- const items = [];
1835
- sorted.forEach((value, index) => {
1836
- const previous = sorted[index - 1];
1837
- if (previous !== void 0 && value - previous === 2) items.push(previous + 1);
1838
- else if (previous !== void 0 && value - previous > 2) items.push(null);
1839
- items.push(value);
1840
- });
1841
- return { items, totalPages, from, to };
1842
- }
1843
- function Table({
1844
- columns,
1845
- rows,
1846
- rowKey,
1847
- label,
1848
- sort = null,
1849
- onSortChange,
1850
- onRowClick,
1851
- empty,
1852
- className
1853
- }) {
1854
- if (rows.length === 0 && empty) {
1855
- return /* @__PURE__ */ jsx("div", { className: cn("cb-table__empty", className), children: empty });
1856
- }
1857
- return /* @__PURE__ */ jsx("div", { className: cn("cb-table__scroll", className), children: /* @__PURE__ */ jsxs("table", { className: "cb-table", "aria-label": label, children: [
1858
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((column) => /* @__PURE__ */ jsx(
1859
- "th",
1860
- {
1861
- scope: "col",
1862
- style: column.width ? { width: column.width } : void 0,
1863
- "data-align": column.align,
1864
- "data-secondary": column.secondary || void 0,
1865
- "aria-sort": column.sortable ? ariaSortFor(sort, column.key) : void 0,
1866
- children: column.sortable && onSortChange ? /* @__PURE__ */ jsxs(
1867
- "button",
1868
- {
1869
- type: "button",
1870
- className: "cb-table__sort",
1871
- onClick: () => onSortChange(nextSort(sort, column.key)),
1872
- children: [
1873
- column.header,
1874
- /* @__PURE__ */ jsx(SortIcon, { state: sort, column: column.key })
1875
- ]
1876
- }
1877
- ) : column.header
1878
- },
1879
- column.key
1880
- )) }) }),
1881
- /* @__PURE__ */ jsx("tbody", { children: rows.map((row) => /* @__PURE__ */ jsx(
1882
- "tr",
1883
- {
1884
- "data-clickable": onRowClick ? "" : void 0,
1885
- onClick: onRowClick ? () => onRowClick(row) : void 0,
1886
- children: columns.map((column) => /* @__PURE__ */ jsx(
1887
- "td",
1888
- {
1889
- "data-align": column.align,
1890
- "data-secondary": column.secondary || void 0,
1891
- "data-truncate": column.truncate || void 0,
1892
- children: column.cell(row)
1893
- },
1894
- column.key
1895
- ))
1896
- },
1897
- rowKey(row)
1898
- )) })
1899
- ] }) });
1900
- }
1901
- function SortIcon({ state, column }) {
1902
- if (!state || state.column !== column) return /* @__PURE__ */ jsx(ChevronsUpDown, { size: 13, className: "cb-table__sort-idle" });
1903
- return state.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { size: 13 }) : /* @__PURE__ */ jsx(ArrowDown, { size: 13 });
1904
- }
1905
- function DataTableSkeleton({ columns, rows = 5, className }) {
1906
- return /* @__PURE__ */ jsx("div", { className: cn("cb-table__scroll", className), "aria-hidden": "true", children: /* @__PURE__ */ jsxs("table", { className: "cb-table", children: [
1907
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: Array.from({ length: columns }, (_, index) => /* @__PURE__ */ jsx("th", { children: /* @__PURE__ */ jsx(Skeleton, { width: "60%", height: "0.75rem" }) }, index)) }) }),
1908
- /* @__PURE__ */ jsx("tbody", { children: Array.from({ length: rows }, (_, rowIndex) => /* @__PURE__ */ jsx("tr", { children: Array.from({ length: columns }, (_2, cellIndex) => /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Skeleton, { width: cellIndex === 0 ? "70%" : "45%", height: "0.875rem" }) }, cellIndex)) }, rowIndex)) })
1909
- ] }) });
1910
- }
1911
- Table.Skeleton = DataTableSkeleton;
1912
- function Pagination({
1913
- page,
1914
- pageSize,
1915
- total,
1916
- onPageChange,
1917
- showSummary = true,
1918
- siblings = 1,
1919
- className
1920
- }) {
1921
- const labels = useLabels();
1922
- const { items, totalPages, from, to } = pageRange(page, pageSize, total, siblings);
1923
- const current = Math.min(Math.max(page, 1), totalPages);
1924
- return /* @__PURE__ */ jsxs("nav", { className: cn("cb-pagination", className), "aria-label": "Pagination", children: [
1925
- showSummary ? /* @__PURE__ */ jsx("p", { className: "cb-pagination__summary", children: labels.pageSummary(from, to, total) }) : null,
1926
- /* @__PURE__ */ jsxs("div", { className: "cb-pagination__controls", children: [
1927
- /* @__PURE__ */ jsx(
1928
- "button",
1929
- {
1930
- type: "button",
1931
- className: "cb-pagination__step",
1932
- "aria-label": labels.previousPage,
1933
- disabled: current <= 1,
1934
- onClick: () => onPageChange(current - 1),
1935
- children: /* @__PURE__ */ jsx(ChevronLeft, { size: 16 })
1936
- }
1937
- ),
1938
- items.map(
1939
- (item, index) => item === null ? /* @__PURE__ */ jsx("span", { className: "cb-pagination__gap", "aria-hidden": "true", children: "\u2026" }, `gap-${index}`) : /* @__PURE__ */ jsx(
1940
- "button",
1941
- {
1942
- type: "button",
1943
- className: "cb-pagination__page",
1944
- "data-active": item === current || void 0,
1945
- "aria-label": labels.page(item),
1946
- "aria-current": item === current ? "page" : void 0,
1947
- onClick: () => onPageChange(item),
1948
- children: item
1949
- },
1950
- item
1951
- )
1952
- ),
1953
- /* @__PURE__ */ jsx(
1954
- "button",
1955
- {
1956
- type: "button",
1957
- className: "cb-pagination__step",
1958
- "aria-label": labels.nextPage,
1959
- disabled: current >= totalPages,
1960
- onClick: () => onPageChange(current + 1),
1961
- children: /* @__PURE__ */ jsx(ChevronRight, { size: 16 })
1962
- }
1963
- )
1964
- ] })
1965
- ] });
1966
- }
1967
- function Image({
1968
- src,
1969
- alt,
1970
- aspectRatio,
1971
- blurDataUrl,
1972
- background,
1973
- fit = "cover",
1974
- radius = "md",
1975
- loading = "lazy",
1976
- className
1977
- }) {
1978
- const [loaded, setLoaded] = useState(false);
1979
- const style = {
1980
- ...aspectRatio ? { aspectRatio: String(aspectRatio) } : {},
1981
- ...background ? { background } : {},
1982
- ...blurDataUrl ? { backgroundImage: `url(${blurDataUrl})` } : {}
1983
- };
1984
- return /* @__PURE__ */ jsx(
1985
- "span",
1986
- {
1987
- className: cn("cb-image", `cb-radius--${radius}`, className),
1988
- "data-loaded": loaded || void 0,
1989
- "data-blurred": blurDataUrl ? "" : void 0,
1990
- style,
1991
- children: /* @__PURE__ */ jsx(
1992
- "img",
1993
- {
1994
- className: "cb-image__img",
1995
- src,
1996
- alt,
1997
- loading,
1998
- decoding: "async",
1999
- style: { objectFit: fit },
2000
- onLoad: () => setLoaded(true),
2001
- ref: (node) => {
2002
- if (node?.complete) setLoaded(true);
2003
- }
2004
- }
2005
- )
2006
- }
2007
- );
2008
- }
2009
-
2010
- // src/media/autoplay.ts
2011
- function shouldAutoplay(conditions) {
2012
- if (!conditions.requested) return false;
2013
- if (conditions.reducedMotion) return false;
2014
- if (conditions.documentHidden) return false;
2015
- if (conditions.pointerInside) return false;
2016
- if (conditions.focusInside) return false;
2017
- return true;
2018
- }
2019
- function CarouselRoot({
2020
- children,
2021
- label,
2022
- slideWidth = "18rem",
2023
- gap = 4,
2024
- loop = false,
2025
- align = "start",
2026
- autoplay,
2027
- showArrows = true,
2028
- showDots = true,
2029
- className
2030
- }) {
2031
- const { enabled: motionEnabled } = useMotionSettings();
2032
- const labels = useLabels();
2033
- const [emblaRef, embla] = useEmblaCarousel({ loop, align, containScroll: "trimSnaps" });
2034
- const [selected, setSelected] = useState(0);
2035
- const [snapCount, setSnapCount] = useState(0);
2036
- const [pointerInside, setPointerInside] = useState(false);
2037
- const [focusInside, setFocusInside] = useState(false);
2038
- const [documentHidden, setDocumentHidden] = useState(false);
2039
- const rootRef = useRef(null);
2040
- useEffect(() => {
2041
- if (!embla) return;
2042
- const sync = () => {
2043
- setSelected(embla.selectedScrollSnap());
2044
- setSnapCount(embla.scrollSnapList().length);
2045
- };
2046
- sync();
2047
- embla.on("select", sync).on("reInit", sync);
2048
- return () => {
2049
- embla.off("select", sync).off("reInit", sync);
2050
- };
2051
- }, [embla]);
2052
- useEffect(() => {
2053
- const onVisibility = () => setDocumentHidden(document.hidden);
2054
- onVisibility();
2055
- document.addEventListener("visibilitychange", onVisibility);
2056
- return () => document.removeEventListener("visibilitychange", onVisibility);
2057
- }, []);
2058
- const running = shouldAutoplay({
2059
- requested: Boolean(autoplay),
2060
- pointerInside,
2061
- focusInside,
2062
- documentHidden,
2063
- reducedMotion: !motionEnabled
2064
- });
2065
- useEffect(() => {
2066
- if (!embla || !running || !autoplay) return;
2067
- const timer = window.setInterval(() => {
2068
- if (embla.canScrollNext()) embla.scrollNext();
2069
- else embla.scrollTo(0);
2070
- }, autoplay);
2071
- return () => window.clearInterval(timer);
2072
- }, [embla, running, autoplay]);
2073
- const onKeyDown = useCallback(
2074
- (event) => {
2075
- if (!embla) return;
2076
- if (event.key === "ArrowRight") {
2077
- embla.scrollNext();
2078
- event.preventDefault();
2079
- }
2080
- if (event.key === "ArrowLeft") {
2081
- embla.scrollPrev();
2082
- event.preventDefault();
2083
- }
2084
- },
2085
- [embla]
2086
- );
2087
- const style = {
2088
- "--cb-carousel-slide": slideWidth,
2089
- "--cb-carousel-gap": `var(--cb-space-${gap})`
2090
- };
2091
- return /* @__PURE__ */ jsxs(
2092
- "div",
2093
- {
2094
- ref: rootRef,
2095
- className: cn("cb-carousel", className),
2096
- style,
2097
- role: "region",
2098
- "aria-roledescription": "carousel",
2099
- "aria-label": label,
2100
- tabIndex: 0,
2101
- onKeyDown,
2102
- onPointerEnter: () => setPointerInside(true),
2103
- onPointerLeave: () => setPointerInside(false),
2104
- onFocus: () => setFocusInside(true),
2105
- onBlur: (event) => {
2106
- if (!rootRef.current?.contains(event.relatedTarget)) setFocusInside(false);
2107
- },
2108
- children: [
2109
- /* @__PURE__ */ jsx("div", { className: "cb-carousel__viewport", ref: emblaRef, children: /* @__PURE__ */ jsx("div", { className: "cb-carousel__track", children }) }),
2110
- showArrows ? /* @__PURE__ */ jsxs("div", { className: "cb-carousel__arrows", children: [
2111
- /* @__PURE__ */ jsx(
2112
- "button",
2113
- {
2114
- type: "button",
2115
- className: "cb-carousel__arrow",
2116
- "aria-label": labels.previousSlide,
2117
- onClick: () => embla?.scrollPrev(),
2118
- disabled: !loop && selected === 0,
2119
- children: /* @__PURE__ */ jsx(ChevronLeft, { size: 18 })
2120
- }
2121
- ),
2122
- /* @__PURE__ */ jsx(
2123
- "button",
2124
- {
2125
- type: "button",
2126
- className: "cb-carousel__arrow",
2127
- "aria-label": labels.nextSlide,
2128
- onClick: () => embla?.scrollNext(),
2129
- disabled: !loop && snapCount > 0 && selected === snapCount - 1,
2130
- children: /* @__PURE__ */ jsx(ChevronRight, { size: 18 })
2131
- }
2132
- )
2133
- ] }) : null,
2134
- showDots && snapCount > 1 ? /* @__PURE__ */ jsx("div", { className: "cb-carousel__dots", children: Array.from({ length: snapCount }, (_, index) => /* @__PURE__ */ jsx(
2135
- "button",
2136
- {
2137
- type: "button",
2138
- className: "cb-carousel__dot",
2139
- "data-active": index === selected || void 0,
2140
- "aria-label": labels.goToSlide(index + 1),
2141
- "aria-current": index === selected || void 0,
2142
- onClick: () => embla?.scrollTo(index)
2143
- },
2144
- index
2145
- )) }) : null
2146
- ]
2147
- }
2148
- );
2149
- }
2150
- function CarouselSlide({ children, className }) {
2151
- return /* @__PURE__ */ jsx("div", { className: cn("cb-carousel__slide", className), role: "group", "aria-roledescription": "slide", children });
2152
- }
2153
- function CarouselSkeleton({
2154
- slides = 3,
2155
- slideWidth = "18rem",
2156
- slideHeight = "10rem",
2157
- gap = 4
2158
- }) {
2159
- const style = {
2160
- "--cb-carousel-slide": slideWidth,
2161
- "--cb-carousel-gap": `var(--cb-space-${gap})`
2162
- };
2163
- return /* @__PURE__ */ jsx("div", { className: "cb-carousel", style, "aria-hidden": "true", children: /* @__PURE__ */ jsx("div", { className: "cb-carousel__viewport", children: /* @__PURE__ */ jsx("div", { className: "cb-carousel__track", children: Array.from({ length: slides }, (_, index) => /* @__PURE__ */ jsx("div", { className: "cb-carousel__slide", children: /* @__PURE__ */ jsx(Skeleton, { height: slideHeight, radius: "lg" }) }, index)) }) }) });
2164
- }
2165
- var Carousel = Object.assign(CarouselRoot, {
2166
- Slide: CarouselSlide,
2167
- Skeleton: CarouselSkeleton
2168
- });
2169
- function Coachmark({
2170
- open,
2171
- anchor,
2172
- title,
2173
- children,
2174
- side = "bottom",
2175
- align = "center",
2176
- spotlight = true,
2177
- progress,
2178
- actions,
2179
- onDismiss,
2180
- className
2181
- }) {
2182
- const labels = useLabels();
2183
- const rect = useAnchorRect(anchor, open && spotlight !== false);
2184
- const padding = typeof spotlight === "number" ? spotlight : 8;
2185
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2186
- rect ? /* @__PURE__ */ jsx(
2187
- "div",
2188
- {
2189
- className: "cb-spotlight",
2190
- "aria-hidden": "true",
2191
- onClick: onDismiss,
2192
- style: {
2193
- "--cb-spotlight-x": `${rect.left - padding}px`,
2194
- "--cb-spotlight-y": `${rect.top - padding}px`,
2195
- "--cb-spotlight-w": `${rect.width + padding * 2}px`,
2196
- "--cb-spotlight-h": `${rect.height + padding * 2}px`
2197
- }
2198
- }
2199
- ) : null,
2200
- /* @__PURE__ */ jsx(Popover$1.Root, { open: open && Boolean(anchor), onOpenChange: (next) => !next && onDismiss?.(), children: /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
2201
- Popover$1.Positioner,
2202
- {
2203
- className: "cb-coachmark__positioner",
2204
- anchor,
2205
- side,
2206
- align,
2207
- sideOffset: 12,
2208
- children: /* @__PURE__ */ jsxs(Popover$1.Popup, { className: cn("cb-coachmark", className), children: [
2209
- /* @__PURE__ */ jsx(Popover$1.Arrow, { className: "cb-popover__arrow", children: /* @__PURE__ */ jsx(ArrowShape, {}) }),
2210
- /* @__PURE__ */ jsxs("div", { className: "cb-coachmark__head", children: [
2211
- /* @__PURE__ */ jsx("p", { className: "cb-coachmark__title", children: title }),
2212
- onDismiss ? /* @__PURE__ */ jsx(
2213
- "button",
2214
- {
2215
- type: "button",
2216
- className: "cb-coachmark__close",
2217
- "aria-label": labels.dismiss,
2218
- onClick: onDismiss,
2219
- children: /* @__PURE__ */ jsx(X, { size: 16 })
2220
- }
2221
- ) : null
2222
- ] }),
2223
- children ? /* @__PURE__ */ jsx("div", { className: "cb-coachmark__body", children }) : null,
2224
- progress || actions ? /* @__PURE__ */ jsxs("div", { className: "cb-coachmark__foot", children: [
2225
- progress ? /* @__PURE__ */ jsx("span", { className: "cb-coachmark__progress", children: labels.progress(progress.current, progress.total) }) : /* @__PURE__ */ jsx("span", {}),
2226
- actions ? /* @__PURE__ */ jsx("div", { className: "cb-coachmark__actions", children: actions }) : null
2227
- ] }) : null
2228
- ] })
2229
- }
2230
- ) }) })
2231
- ] });
2232
- }
2233
- function useAnchorRect(anchor, active) {
2234
- const [rect, setRect] = useState(null);
2235
- useEffect(() => {
2236
- if (!anchor || !active) {
2237
- setRect(null);
2238
- return;
2239
- }
2240
- const measure = () => setRect(anchor.getBoundingClientRect());
2241
- measure();
2242
- const observer = new ResizeObserver(measure);
2243
- observer.observe(anchor);
2244
- window.addEventListener("scroll", measure, true);
2245
- window.addEventListener("resize", measure);
2246
- return () => {
2247
- observer.disconnect();
2248
- window.removeEventListener("scroll", measure, true);
2249
- window.removeEventListener("resize", measure);
2250
- };
2251
- }, [anchor, active]);
2252
- return rect;
2253
- }
2254
-
2255
- // src/onboarding/tour-machine.ts
2256
- var initialTourState = { index: 0, status: "idle" };
2257
- function tourReducer(state, action, stepCount) {
2258
- const lastIndex = Math.max(stepCount - 1, 0);
2259
- switch (action.type) {
2260
- case "start":
2261
- return stepCount === 0 ? { index: 0, status: "finished" } : { index: 0, status: "running" };
2262
- case "next":
2263
- if (state.status !== "running") return state;
2264
- return state.index >= lastIndex ? { index: state.index, status: "finished" } : { index: state.index + 1, status: "running" };
2265
- case "prev":
2266
- if (state.status !== "running") return state;
2267
- return { index: Math.max(state.index - 1, 0), status: "running" };
2268
- case "goto":
2269
- if (state.status !== "running") return state;
2270
- return { index: Math.min(Math.max(action.index, 0), lastIndex), status: "running" };
2271
- case "skip":
2272
- return { index: state.index, status: "skipped" };
2273
- case "finish":
2274
- return { index: state.index, status: "finished" };
2275
- default:
2276
- return state;
2277
- }
2278
- }
2279
- function hasEnded(status) {
2280
- return status === "finished" || status === "skipped";
2281
- }
2282
- function resolveTarget(target, root) {
2283
- if (!target) return null;
2284
- if (typeof target === "string") return root.querySelector(target);
2285
- if (typeof target === "function") return target();
2286
- if (target instanceof Element) return target;
2287
- if ("current" in target) return target.current;
2288
- return null;
2289
- }
2290
- function Tour({ id, steps, open = false, onOpenChange, seenStore, onFinish, onSkip, labels }) {
2291
- const [state, rawDispatch] = useReducer(
2292
- (current, action) => tourReducer(current, action, steps.length),
2293
- initialTourState
2294
- );
2295
- const [anchor, setAnchor] = useState(null);
2296
- const { enabled: motionEnabled } = useMotionSettings();
2297
- const provided = useLabels();
2298
- const [allowed, setAllowed] = useState(seenStore ? null : true);
2299
- const marked = useRef(false);
2300
- const text2 = { back: provided.back, next: provided.next, done: provided.done, skip: provided.skip, ...labels };
2301
- useEffect(() => {
2302
- if (!seenStore) return;
2303
- let cancelled = false;
2304
- void Promise.resolve(seenStore.has(id)).then((seen) => {
2305
- if (!cancelled) setAllowed(!seen);
2306
- });
2307
- return () => {
2308
- cancelled = true;
2309
- };
2310
- }, [seenStore, id]);
2311
- useEffect(() => {
2312
- if (open && allowed && state.status === "idle") rawDispatch({ type: "start" });
2313
- }, [open, allowed, state.status]);
2314
- useEffect(() => {
2315
- if (state.status !== "running") {
2316
- setAnchor(null);
2317
- return;
2318
- }
2319
- const step2 = steps[state.index];
2320
- if (!step2) return;
2321
- let frame = 0;
2322
- let raf = 0;
2323
- const look = () => {
2324
- const found = resolveTarget(step2.target, document);
2325
- if (found) {
2326
- setAnchor(found);
2327
- found.scrollIntoView?.({ block: "center", behavior: motionEnabled ? "smooth" : "auto" });
2328
- return;
2329
- }
2330
- if (frame++ < 30) raf = requestAnimationFrame(look);
2331
- else setAnchor(null);
2332
- };
2333
- look();
2334
- return () => cancelAnimationFrame(raf);
2335
- }, [state.status, state.index, steps, motionEnabled]);
2336
- useEffect(() => {
2337
- if (!hasEnded(state.status) || marked.current) return;
2338
- marked.current = true;
2339
- void Promise.resolve(seenStore?.mark(id));
2340
- onOpenChange?.(false);
2341
- if (state.status === "finished") onFinish?.();
2342
- else onSkip?.();
2343
- }, [state.status, seenStore, id, onOpenChange, onFinish, onSkip]);
2344
- const skip = useCallback(() => rawDispatch({ type: "skip" }), []);
2345
- if (state.status !== "running" || !allowed) return null;
2346
- const step = steps[state.index];
2347
- if (!step) return null;
2348
- const isLast = state.index === steps.length - 1;
2349
- return /* @__PURE__ */ jsx(
2350
- Coachmark,
2351
- {
2352
- open: true,
2353
- anchor,
2354
- title: step.title,
2355
- side: step.side,
2356
- align: step.align,
2357
- spotlight: step.spotlight,
2358
- progress: { current: state.index + 1, total: steps.length },
2359
- onDismiss: skip,
2360
- actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [
2361
- state.index > 0 ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", tone: "neutral", onClick: () => rawDispatch({ type: "prev" }), children: text2.back }) : /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", tone: "neutral", onClick: skip, children: text2.skip }),
2362
- /* @__PURE__ */ jsx(Button, { size: "sm", onClick: () => rawDispatch({ type: "next" }), children: isLast ? text2.done : text2.next })
2363
- ] }),
2364
- children: step.content
2365
- }
2366
- );
2367
- }
2368
565
  var OFFSETS = {
2369
566
  below: (d) => ({ y: d }),
2370
567
  above: (d) => ({ y: -d }),
@@ -2400,4 +597,4 @@ function Stagger({ children, step = 0.06, from = "below", onView = false, classN
2400
597
  return /* @__PURE__ */ jsx("div", { className, children: Children.map(children, (child, index) => /* @__PURE__ */ jsx(Reveal, { from, delay: index * step, onView, children: child })) });
2401
598
  }
2402
599
 
2403
- export { Alert, AutoComplete, Button, Carousel, Checkbox, Checklist, Coachmark, CommandPalette, DEFAULT_LABELS, DatePicker, DialogClose, Drawer, DrawerClose, Dropdown, Field, Image, Input, InputNumber, LabelsProvider, Modal, MotionProvider, Pagination, Popover, RadioGroup, Rate, Reveal, Select, Sidebar, Stagger, Switch, Table, Tabs, Tag, Textarea, ThemeProvider, TimePicker, ToastProvider, Tooltip, TopBar, Tour, Upload, ariaSortFor, canStep, clamp, decimalPlaces, describeAccept, filterCommands, formatISO, formatTime, groupCommands, hasEnded, initialTourState, isOutOfRange, isSameDay, isTimeOutOfRange, matchesAccept, monthMatrix, nextSort, pageRange, parseDateInput, parseNumber, parseTime, partitionFiles, rankCommand, resolveTarget, shouldAutoplay, startOfDay, stepBy, timeOptions, timeToMinutes, tourReducer, useFieldWiring, useLabels, useMotionSettings, useTheme, useToast };
600
+ export { Checklist, CommandPalette, DEFAULT_LABELS, LabelsProvider, MotionProvider, Reveal, Sidebar, Stagger, ThemeBridge, ThemeProvider, ToastProvider, TopBar, filterCommands, groupCommands, rankCommand, useLabels, useMotionSettings, useTheme, useToast };