@ceebee/ui 0.4.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -1,16 +1,16 @@
1
1
  "use client";
2
- import { createContext, forwardRef, useContext, useMemo, useState, useRef, useEffect, useCallback, useId, Fragment, useReducer, Children } from 'react';
2
+ import { createContext, forwardRef, useContext, useMemo, useState, useRef, useEffect, useCallback, useId, isValidElement, cloneElement, Fragment, useReducer, Children } from 'react';
3
3
  import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
4
4
  import { motion } from 'motion/react';
5
5
  import { Select as Select$1 } from '@base-ui/react/select';
6
- import { ChevronLeft, ChevronRight, ChevronsUpDown, Check, Minus, X, CalendarDays, Clock, Upload, Plus, Search, PanelLeftOpen, PanelLeftClose, ArrowUp, ArrowDown, XCircle, AlertTriangle, CheckCircle2, Info } from 'lucide-react';
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
7
  import { Checkbox as Checkbox$1 } from '@base-ui/react/checkbox';
8
8
  import { Radio } from '@base-ui/react/radio';
9
9
  import { RadioGroup as RadioGroup$1 } from '@base-ui/react/radio-group';
10
10
  import { Switch as Switch$1 } from '@base-ui/react/switch';
11
- import { Combobox as Combobox$1 } from '@base-ui/react/combobox';
11
+ import { Combobox } from '@base-ui/react/combobox';
12
12
  import { Popover as Popover$1 } from '@base-ui/react/popover';
13
- import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
13
+ import { Dialog } from '@base-ui/react/dialog';
14
14
  import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
15
15
  import { Toast } from '@base-ui/react/toast';
16
16
  import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
@@ -204,7 +204,7 @@ function Field({ label, hint, error, required = false, labelHidden = false, clas
204
204
  error && error !== true ? /* @__PURE__ */ jsx("p", { className: "cb-field__error", id: errorId, role: "alert", children: error }) : null
205
205
  ] }) });
206
206
  }
207
- var TextInput = forwardRef(function TextInput2({ size = "md", invalid, className, ...rest }, ref) {
207
+ var Input = forwardRef(function Input2({ size = "md", invalid, className, ...rest }, ref) {
208
208
  const field = useFieldWiring();
209
209
  return /* @__PURE__ */ jsx(
210
210
  "input",
@@ -271,10 +271,18 @@ function Select({
271
271
  ]
272
272
  }
273
273
  ),
274
- /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(Select$1.Positioner, { sideOffset: 6, alignItemWithTrigger: false, 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: [
275
- /* @__PURE__ */ jsx("span", { className: "cb-select__check", children: /* @__PURE__ */ jsx(Select$1.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { size: 14 }) }) }),
276
- /* @__PURE__ */ jsx(Select$1.ItemText, { children: item.label })
277
- ] }, item.value)) }) }) })
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
+ ) })
278
286
  ]
279
287
  }
280
288
  );
@@ -326,6 +334,7 @@ function RadioGroup({
326
334
  name,
327
335
  label,
328
336
  direction = "column",
337
+ variant = "list",
329
338
  disabled,
330
339
  className
331
340
  }) {
@@ -341,7 +350,12 @@ function RadioGroup({
341
350
  disabled,
342
351
  "aria-label": label,
343
352
  "aria-describedby": field?.describedBy,
344
- className: cn("cb-radio-group", `cb-radio-group--${direction}`, className),
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
+ ),
345
359
  children: options.map((option) => {
346
360
  const id = `${groupId}-${option.value}`;
347
361
  const descriptionId = option.description ? `${id}-description` : void 0;
@@ -416,57 +430,146 @@ function Switch({
416
430
  ) : null
417
431
  ] });
418
432
  }
419
- function Combobox({
433
+ function AutoComplete({
420
434
  items,
435
+ loadItems,
436
+ loadDelay = 250,
421
437
  value,
422
438
  defaultValue,
423
439
  onValueChange,
424
440
  placeholder = "Search\u2026",
425
441
  emptyMessage = "Nothing matched",
442
+ loadingMessage = "Searching\u2026",
443
+ errorMessage = "Could not search",
426
444
  size = "md",
427
445
  disabled,
428
446
  invalid,
429
447
  name,
448
+ id,
430
449
  className
431
450
  }) {
432
451
  const field = useFieldWiring();
433
452
  const labels = useLabels();
434
- const optionFor = (candidate) => items.find((item) => item.value === candidate) ?? null;
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]);
435
512
  return /* @__PURE__ */ jsxs(
436
- Combobox$1.Root,
513
+ Combobox.Root,
437
514
  {
438
- items,
515
+ items: available,
516
+ filter: async ? null : void 0,
517
+ onInputValueChange: async ? (next) => setQuery(next) : void 0,
439
518
  value: value === void 0 ? void 0 : optionFor(value),
440
519
  defaultValue: defaultValue === void 0 ? void 0 : optionFor(defaultValue),
441
- onValueChange: (next) => onValueChange?.(next?.value ?? null),
520
+ onValueChange: (next) => {
521
+ const option = next;
522
+ setChosen(option);
523
+ onValueChange?.(option?.value ?? null);
524
+ },
525
+ modal: true,
526
+ open,
527
+ onOpenChange: setOpen,
442
528
  isItemEqualToValue: (a, b) => a?.value === b?.value,
443
529
  itemToStringLabel: (item) => typeof item === "string" ? item : item.label,
444
530
  disabled,
445
531
  name,
446
532
  children: [
447
- /* @__PURE__ */ jsxs("div", { className: cn("cb-combobox", `cb-combobox--${size}`, className), "data-disabled": disabled || void 0, children: [
448
- /* @__PURE__ */ jsx(
449
- Combobox$1.Input,
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,
450
559
  {
451
- className: "cb-combobox__input",
452
- placeholder,
453
- id: field?.controlId,
454
- "aria-describedby": field?.describedBy,
455
- "aria-invalid": invalid ?? field?.invalid ? true : void 0
456
- }
457
- ),
458
- /* @__PURE__ */ jsx(Combobox$1.Clear, { className: "cb-combobox__clear", "aria-label": labels.clear, children: /* @__PURE__ */ jsx(X, { size: 14 }) }),
459
- /* @__PURE__ */ jsx(Combobox$1.Trigger, { className: "cb-combobox__trigger", "aria-label": labels.open, children: /* @__PURE__ */ jsx(ChevronsUpDown, { size: 16 }) })
460
- ] }),
461
- /* @__PURE__ */ jsx(Combobox$1.Portal, { children: /* @__PURE__ */ jsx(Combobox$1.Positioner, { sideOffset: 6, children: /* @__PURE__ */ jsxs(Combobox$1.Popup, { className: "cb-combobox__popup", children: [
462
- /* @__PURE__ */ jsx(Combobox$1.Empty, { className: "cb-combobox__empty", children: emptyMessage }),
463
- /* @__PURE__ */ jsx(Combobox$1.List, { children: (item) => /* @__PURE__ */ jsxs(Combobox$1.Item, { value: item, className: "cb-combobox__item", children: [
464
- /* @__PURE__ */ jsx("span", { className: "cb-combobox__check", children: /* @__PURE__ */ jsx(Combobox$1.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { size: 14 }) }) }),
465
- /* @__PURE__ */ jsxs("span", { className: "cb-combobox__text", children: [
466
- /* @__PURE__ */ jsx("span", { className: "cb-combobox__label", children: item.label }),
467
- item.description ? /* @__PURE__ */ jsx("span", { className: "cb-combobox__description", children: item.description }) : null
468
- ] })
469
- ] }, item.value) })
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
+ ) })
470
573
  ] }) }) })
471
574
  ]
472
575
  }
@@ -526,7 +629,7 @@ function isOutOfRange(date, min, max) {
526
629
  return false;
527
630
  }
528
631
  var WEEKDAYS = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
529
- function DateInput({
632
+ function DatePicker({
530
633
  value,
531
634
  defaultValue = null,
532
635
  onValueChange,
@@ -601,57 +704,67 @@ function DateInput({
601
704
  ]
602
705
  }
603
706
  ),
604
- /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { anchor: fieldRef, side: "bottom", align: "start", sideOffset: 6, children: /* @__PURE__ */ jsxs(Popover$1.Popup, { className: "cb-calendar", children: [
605
- /* @__PURE__ */ jsxs("div", { className: "cb-calendar__head", children: [
606
- /* @__PURE__ */ jsx(
607
- "button",
608
- {
609
- type: "button",
610
- className: "cb-calendar__nav",
611
- "aria-label": labels.previousMonth,
612
- onClick: () => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1)),
613
- children: /* @__PURE__ */ jsx(ChevronLeft, { size: 16 })
614
- }
615
- ),
616
- /* @__PURE__ */ jsx("p", { className: "cb-calendar__month", "aria-live": "polite", children: cursor.toLocaleDateString(void 0, { month: "long", year: "numeric" }) }),
617
- /* @__PURE__ */ jsx(
618
- "button",
619
- {
620
- type: "button",
621
- className: "cb-calendar__nav",
622
- "aria-label": labels.nextMonth,
623
- onClick: () => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1)),
624
- children: /* @__PURE__ */ jsx(ChevronRight, { size: 16 })
625
- }
626
- )
627
- ] }),
628
- /* @__PURE__ */ jsxs("table", { className: "cb-calendar__grid", children: [
629
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: weekdays.map((day) => /* @__PURE__ */ jsx("th", { scope: "col", abbr: day, children: day }, day)) }) }),
630
- /* @__PURE__ */ jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsx("tr", { children: week.map((cell) => {
631
- const selected = isSameDay(cell.date, current);
632
- const outside = isOutOfRange(cell.date, min, max);
633
- return /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
634
- "button",
635
- {
636
- type: "button",
637
- className: "cb-calendar__day",
638
- "data-outside": !cell.inMonth || void 0,
639
- "data-selected": selected || void 0,
640
- "data-today": isSameDay(cell.date, /* @__PURE__ */ new Date()) || void 0,
641
- disabled: outside,
642
- "aria-pressed": selected,
643
- "aria-label": formatISO(cell.date),
644
- onClick: () => {
645
- commit(cell.date);
646
- setCursor(cell.date);
647
- setOpen(false);
648
- },
649
- children: cell.date.getDate()
650
- }
651
- ) }, cell.date.toISOString());
652
- }) }, weekIndex)) })
653
- ] })
654
- ] }) }) })
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
+ ) })
655
768
  ] });
656
769
  }
657
770
 
@@ -705,7 +818,7 @@ function isTimeOutOfRange(value, min, max) {
705
818
  if (max && minutes > timeToMinutes(max)) return true;
706
819
  return false;
707
820
  }
708
- function TimeInput({
821
+ function TimePicker({
709
822
  value,
710
823
  defaultValue = null,
711
824
  onValueChange,
@@ -772,27 +885,37 @@ function TimeInput({
772
885
  ]
773
886
  }
774
887
  ),
775
- /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { anchor: fieldRef, side: "bottom", align: "start", sideOffset: 6, children: /* @__PURE__ */ jsx(Popover$1.Popup, { className: "cb-times", children: /* @__PURE__ */ jsx("ul", { className: "cb-times__list", children: options.map((option) => {
776
- const selected = current ? timeToMinutes(current) === timeToMinutes(option) : false;
777
- return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
778
- "button",
779
- {
780
- type: "button",
781
- className: "cb-times__option",
782
- "data-selected": selected || void 0,
783
- "aria-pressed": selected,
784
- onClick: () => {
785
- commit(option);
786
- setOpen(false);
787
- },
788
- children: formatTime(option)
789
- }
790
- ) }, formatTime(option));
791
- }) }) }) }) })
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
+ ) })
792
915
  ] });
793
916
  }
794
917
 
795
- // src/form/file-drop.util.ts
918
+ // src/form/upload.util.ts
796
919
  function matchesAccept(file, accept) {
797
920
  if (!accept || accept.length === 0) return true;
798
921
  const name = file.name.toLowerCase();
@@ -830,7 +953,7 @@ function describeAccept(rules) {
830
953
  if (typeof rules.maxSize === "number") parts.push(`up to ${Math.round(rules.maxSize / (1024 * 1024))} MB`);
831
954
  return parts.length > 0 ? ` \u2014 ${parts.join(" ")}` : "";
832
955
  }
833
- function FileDrop({
956
+ function Upload({
834
957
  onFilesChange,
835
958
  files = [],
836
959
  onReject,
@@ -887,7 +1010,7 @@ function FileDrop({
887
1010
  }
888
1011
  }
889
1012
  ),
890
- /* @__PURE__ */ jsx("span", { className: "cb-filedrop__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Upload, { size: 20 }) }),
1013
+ /* @__PURE__ */ jsx("span", { className: "cb-filedrop__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Upload$1, { size: 20 }) }),
891
1014
  /* @__PURE__ */ jsx("span", { className: "cb-filedrop__button", children: multiple ? labels.chooseFiles : labels.chooseFile }),
892
1015
  /* @__PURE__ */ jsxs("p", { className: "cb-filedrop__hint", children: [
893
1016
  multiple ? labels.dropFilesHere : labels.dropFileHere,
@@ -950,7 +1073,7 @@ function canStep(value, direction, bounds) {
950
1073
  if (direction === 1) return typeof bounds.max !== "number" || value < bounds.max;
951
1074
  return typeof bounds.min !== "number" || value > bounds.min;
952
1075
  }
953
- function NumberInput({
1076
+ function InputNumber({
954
1077
  value,
955
1078
  defaultValue = null,
956
1079
  onValueChange,
@@ -1038,7 +1161,7 @@ function NumberInput({
1038
1161
  function formatValue(value) {
1039
1162
  return value === null ? "" : String(value);
1040
1163
  }
1041
- function Dialog({
1164
+ function Modal({
1042
1165
  open,
1043
1166
  defaultOpen,
1044
1167
  onOpenChange,
@@ -1051,26 +1174,51 @@ function Dialog({
1051
1174
  trigger,
1052
1175
  className
1053
1176
  }) {
1054
- return /* @__PURE__ */ jsxs(Dialog$1.Root, { open, defaultOpen, onOpenChange, children: [
1055
- trigger ? /* @__PURE__ */ jsx(Dialog$1.Trigger, { render: trigger }) : null,
1056
- /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [
1057
- /* @__PURE__ */ jsx(Dialog$1.Backdrop, { className: "cb-dialog__backdrop" }),
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" }),
1058
1181
  /* @__PURE__ */ jsxs(
1059
- Dialog$1.Popup,
1182
+ Dialog.Popup,
1060
1183
  {
1061
- className: cn("cb-dialog", `cb-dialog--${size}`, `cb-dialog--${placement}`, className),
1184
+ className: cn("cb-modal", `cb-modal--${size}`, `cb-modal--${placement}`, className),
1062
1185
  children: [
1063
- /* @__PURE__ */ jsx(Dialog$1.Title, { className: "cb-dialog__title", children: title }),
1064
- description ? /* @__PURE__ */ jsx(Dialog$1.Description, { className: "cb-dialog__description", children: description }) : null,
1065
- children ? /* @__PURE__ */ jsx("div", { className: "cb-dialog__body", children }) : null,
1066
- footer ? /* @__PURE__ */ jsx("div", { className: "cb-dialog__footer", children: footer }) : null
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
1067
1190
  ]
1068
1191
  }
1069
1192
  )
1070
1193
  ] })
1071
1194
  ] });
1072
1195
  }
1073
- var DialogClose = Dialog$1.Close;
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;
1074
1222
 
1075
1223
  // src/overlay/command.util.ts
1076
1224
  function rankCommand(command, query) {
@@ -1119,9 +1267,9 @@ function CommandPalette({
1119
1267
  onOpenChange(false);
1120
1268
  command.onRun();
1121
1269
  };
1122
- return /* @__PURE__ */ jsx(Dialog$1.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [
1123
- /* @__PURE__ */ jsx(Dialog$1.Backdrop, { className: "cb-dialog__backdrop" }),
1124
- /* @__PURE__ */ jsxs(Dialog$1.Popup, { className: cn("cb-palette", className), "aria-label": "Command palette", children: [
1270
+ return /* @__PURE__ */ jsx(Dialog.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
1271
+ /* @__PURE__ */ jsx(Dialog.Backdrop, { className: "cb-palette__backdrop" }),
1272
+ /* @__PURE__ */ jsxs(Dialog.Popup, { className: cn("cb-palette", className), "aria-label": "Command palette", children: [
1125
1273
  /* @__PURE__ */ jsxs("div", { className: "cb-palette__search", children: [
1126
1274
  /* @__PURE__ */ jsx(Search, { size: 16, className: "cb-palette__search-icon" }),
1127
1275
  /* @__PURE__ */ jsx(
@@ -1259,20 +1407,155 @@ function Popover({
1259
1407
  }) {
1260
1408
  return /* @__PURE__ */ jsxs(Popover$1.Root, { open, onOpenChange, children: [
1261
1409
  /* @__PURE__ */ jsx(Popover$1.Trigger, { render: trigger }),
1262
- /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { side, align, sideOffset, children: /* @__PURE__ */ jsxs(Popover$1.Popup, { className: cn("cb-popover", className), children: [
1263
- showArrow ? /* @__PURE__ */ jsx(Popover$1.Arrow, { className: "cb-popover__arrow", children: /* @__PURE__ */ jsx(ArrowShape, {}) }) : null,
1264
- children
1265
- ] }) }) })
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
+ ) })
1266
1423
  ] });
1267
1424
  }
1268
- function Tooltip({ children, label, side = "top", delay = 400 }) {
1425
+ function Tooltip({
1426
+ children,
1427
+ label,
1428
+ side = "top",
1429
+ align = "center",
1430
+ sideOffset = 6,
1431
+ showArrow = true,
1432
+ delay = 400
1433
+ }) {
1269
1434
  return /* @__PURE__ */ jsx(Tooltip$1.Provider, { delay, children: /* @__PURE__ */ jsxs(Tooltip$1.Root, { children: [
1270
1435
  /* @__PURE__ */ jsx(Tooltip$1.Trigger, { render: children }),
1271
- /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsx(Tooltip$1.Positioner, { side, sideOffset: 6, children: /* @__PURE__ */ jsx(Tooltip$1.Popup, { className: "cb-tooltip", children: label }) }) })
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
+ ) })
1272
1449
  ] }) });
1273
1450
  }
1274
1451
  function ArrowShape() {
1275
- return /* @__PURE__ */ jsx("span", { className: "cb-arrow", "aria-hidden": "true" });
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
+ );
1276
1559
  }
1277
1560
  var ICONS = {
1278
1561
  neutral: /* @__PURE__ */ jsx(Info, { size: 18 }),
@@ -1371,33 +1654,42 @@ function Tabs({ items, value, defaultValue, onValueChange, variant = "underline"
1371
1654
  }
1372
1655
  );
1373
1656
  }
1374
- function DropdownMenu({ trigger, items, sections, align = "end", side = "bottom", className }) {
1657
+ function Dropdown({ trigger, items, sections, align = "end", side = "bottom", className }) {
1375
1658
  const groups = sections ?? [{ items }];
1376
1659
  return /* @__PURE__ */ jsxs(Menu.Root, { children: [
1377
1660
  /* @__PURE__ */ jsx(Menu.Trigger, { render: trigger }),
1378
- /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { side, align, sideOffset: 6, children: /* @__PURE__ */ jsx(Menu.Popup, { className: cn("cb-menu", className), children: groups.map((section, sectionIndex) => /* @__PURE__ */ jsxs(Fragment, { children: [
1379
- sectionIndex > 0 ? /* @__PURE__ */ jsx(Menu.Separator, { className: "cb-menu__separator" }) : null,
1380
- /* @__PURE__ */ jsxs(Menu.Group, { className: "cb-menu__group", children: [
1381
- section.label ? /* @__PURE__ */ jsx(Menu.GroupLabel, { className: "cb-menu__group-label", children: section.label }) : null,
1382
- section.items.map(
1383
- (item, itemIndex) => item.separator ? /* @__PURE__ */ jsx(Menu.Separator, { className: "cb-menu__separator" }, `separator-${itemIndex}`) : /* @__PURE__ */ jsxs(
1384
- Menu.Item,
1385
- {
1386
- className: "cb-menu__item",
1387
- "data-tone": item.tone,
1388
- disabled: item.disabled,
1389
- onClick: item.onSelect,
1390
- children: [
1391
- /* @__PURE__ */ jsx("span", { className: "cb-menu__icon", children: item.checked ? /* @__PURE__ */ jsx(Check, { size: 14 }) : item.icon }),
1392
- /* @__PURE__ */ jsx("span", { className: "cb-menu__label", children: item.label }),
1393
- item.shortcut ? /* @__PURE__ */ jsx("kbd", { className: "cb-menu__shortcut", children: item.shortcut }) : null
1394
- ]
1395
- },
1396
- `${String(item.label)}-${itemIndex}`
1397
- )
1398
- )
1399
- ] })
1400
- ] }, `section-${sectionIndex}`)) }) }) })
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
+ ) })
1401
1693
  ] });
1402
1694
  }
1403
1695
  var hasActiveChild = (item) => Boolean(item.items?.some((child) => child.active));
@@ -1548,7 +1840,7 @@ function pageRange(page, pageSize, total, siblings = 1) {
1548
1840
  });
1549
1841
  return { items, totalPages, from, to };
1550
1842
  }
1551
- function DataTable({
1843
+ function Table({
1552
1844
  columns,
1553
1845
  rows,
1554
1846
  rowKey,
@@ -1616,7 +1908,7 @@ function DataTableSkeleton({ columns, rows = 5, className }) {
1616
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)) })
1617
1909
  ] }) });
1618
1910
  }
1619
- DataTable.Skeleton = DataTableSkeleton;
1911
+ Table.Skeleton = DataTableSkeleton;
1620
1912
  function Pagination({
1621
1913
  page,
1622
1914
  pageSize,
@@ -2108,4 +2400,4 @@ function Stagger({ children, step = 0.06, from = "below", onView = false, classN
2108
2400
  return /* @__PURE__ */ jsx("div", { className, children: Children.map(children, (child, index) => /* @__PURE__ */ jsx(Reveal, { from, delay: index * step, onView, children: child })) });
2109
2401
  }
2110
2402
 
2111
- export { Alert, Button, Carousel, Checkbox, Checklist, Coachmark, Combobox, CommandPalette, DEFAULT_LABELS, DataTable, DateInput, Dialog, DialogClose, DropdownMenu, Field, FileDrop, Image, LabelsProvider, MotionProvider, NumberInput, Pagination, Popover, RadioGroup, Reveal, Select, Sidebar, Stagger, Switch, Tabs, TextInput, Textarea, ThemeProvider, TimeInput, ToastProvider, Tooltip, TopBar, Tour, 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 };
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 };