@campfire-interactive/ui 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +75 -1
  2. package/dist/index.js +303 -154
  3. package/package.json +55 -56
package/dist/index.d.ts CHANGED
@@ -494,6 +494,71 @@ interface SelectProps<T extends string = string> {
494
494
  */
495
495
  declare function Select<T extends string = string>({ options, value, onValueChange, defaultValue, placeholder, size, invalid, disabled, required, name, id, className, fullWidth, emptyLabel, onOpenChange, onBlur, ...aria }: SelectProps<T>): react.JSX.Element;
496
496
 
497
+ interface CreatableSelectProps<T extends string = string> extends SelectProps<T> {
498
+ /**
499
+ * Creates a new option from the typed label and returns it. The returned
500
+ * option is selected immediately, so the caller does not have to wait for
501
+ * its own list query to refetch before the field reads correctly.
502
+ *
503
+ * Reject to keep the dialog open with the message showing and the text
504
+ * intact — a name that collides server-side is the common case, and losing
505
+ * what they typed to learn that is the wrong trade.
506
+ *
507
+ * Omit it and this is a plain `Select`; the "+" does not render at all.
508
+ */
509
+ onCreate?: (label: string) => Promise<SelectOption<T>> | SelectOption<T>;
510
+ /**
511
+ * Whether this viewer may add to the list. False HIDES the "+" rather than
512
+ * disabling it: the lists behind these pickers are tenant configuration, and
513
+ * a disabled button advertises an action most people on a program will never
514
+ * be allowed to take.
515
+ */
516
+ canCreate?: boolean;
517
+ className?: string;
518
+ /** Accessible name and tooltip on the "+". */
519
+ addLabel?: string;
520
+ createTitle?: string;
521
+ createDescription?: React.ReactNode;
522
+ createFieldLabel?: string;
523
+ createPlaceholder?: string;
524
+ createSubmitLabel?: string;
525
+ createPendingLabel?: string;
526
+ createCancelLabel?: string;
527
+ /** Shown while the typed name already matches an option. */
528
+ duplicateHint?: string;
529
+ }
530
+ /**
531
+ * A select whose list can be extended without leaving the page.
532
+ *
533
+ * Every one of these lists is tenant configuration maintained on a Settings
534
+ * screen — work categories, health categories, process types, gate types,
535
+ * team roles. The cost of that is paid by the person filling in a form, who
536
+ * finds the value they need is not there yet and has to abandon what they are
537
+ * doing, navigate to Settings, add it, come back and start again. In practice
538
+ * they do not: they pick the closest wrong option, or the field gets widened
539
+ * to free text and the list stops meaning anything. pm's team-member role was
540
+ * free text for exactly that reason and grew "Tool Engineer", "tool eng" and
541
+ * "Tooling Eng" as three separate roles.
542
+ *
543
+ * So the "+" is not a convenience. It is what lets a constrained list stay
544
+ * constrained.
545
+ *
546
+ * Two behaviors are deliberate and easy to lose in a reimplementation:
547
+ *
548
+ * - A name that already exists selects the existing option instead of
549
+ * creating a second one. The duplicate is what the picker exists to
550
+ * prevent, and the person typing it wants that value either way.
551
+ * - The created option is held locally and merged into `options` until the
552
+ * caller's own list catches up. Without that, an optimistic close lands on
553
+ * an empty field for as long as the refetch takes, which reads as a failed
554
+ * save.
555
+ *
556
+ * Wraps `Select`, so the list is the short, known kind. Reach for `Combobox`
557
+ * when it needs searching; a creatable combobox can follow the first caller
558
+ * that actually needs one.
559
+ */
560
+ declare function CreatableSelect<T extends string = string>({ onCreate, canCreate, className, addLabel, createTitle, createDescription, createFieldLabel, createPlaceholder, createSubmitLabel, createPendingLabel, createCancelLabel, duplicateHint, options, onValueChange, disabled, ...select }: CreatableSelectProps<T>): react.JSX.Element;
561
+
497
562
  interface ComboboxOption<T extends string = string> {
498
563
  value: T;
499
564
  label: string;
@@ -736,6 +801,15 @@ interface TableProps extends React.TableHTMLAttributes<HTMLTableElement> {
736
801
  density?: 'comfortable' | 'compact';
737
802
  /** Keeps the header visible while the body scrolls. Requires a scrolling ancestor with a height. */
738
803
  stickyHeader?: boolean;
804
+ /**
805
+ * Pins the first column while the rest scrolls sideways.
806
+ *
807
+ * For any table wide enough to scroll in its `TableScroller` — which is most
808
+ * wide ones — because scrolling right otherwise takes the column that says
809
+ * which row you are looking at. Put the row's identity in the first column
810
+ * before turning this on; it pins position, not meaning.
811
+ */
812
+ stickyFirstColumn?: boolean;
739
813
  }
740
814
  /**
741
815
  * A data table.
@@ -1221,4 +1295,4 @@ declare function formatNumber(value: number | null | undefined, decimals?: numbe
1221
1295
  */
1222
1296
  declare function formatPercent(value: number | null | undefined, decimals?: number): string;
1223
1297
 
1224
- export { Accordion, AccordionContent, AccordionItem, type AccordionProps, AccordionRoot, type AccordionSection, AccordionTrigger, type AccordionTriggerProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Badge, type BadgeProps, type BadgeTone, Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, type ButtonSize, type ButtonVariant, Card, CardBody, CardDescription, CardFooter, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, Checkbox, type CheckboxProps, type ClassValue, Combobox, type ComboboxOption, type ComboboxProps, ComingSoon, type ComingSoonProps, ConfirmDialog, type ConfirmDialogProps, CountBadge, type CountBadgeProps, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogPortal, DialogRoot, type DialogSize, DialogTitle, DialogTrigger, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, Field, type FieldProps, Fieldset, type FieldsetProps, IconButton, type IconButtonProps, Input, type InputProps, type InputSize, Label, type LabelProps, LoadingState, type LoadingStateProps, Menu, type MenuAction, MenuCheckboxItem, MenuContent, MenuGroup, MenuItem, type MenuItemProps, MenuLabel, type MenuProps, MenuRadioGroup, MenuRadioItem, MenuRoot, MenuSeparator, MenuSub, MenuSubContent, MenuSubTrigger, MenuTrigger, Modal, type ModalProps, type MoneyOptions, Pagination, type PaginationProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverRoot, PopoverTrigger, Progress, type ProgressProps, ScrollArea, type ScrollAreaProps, SearchInput, type SearchInputProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, type SelectOption, type SelectProps, SelectRoot, SelectSeparator, SelectTrigger, type SelectTriggerProps, SelectValue, Separator, type SeparatorProps, Sheet, SheetBody, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger, SideModal, Skeleton, type SkeletonProps, Slider, type SliderProps, type SortDirection, type SortState, Switch, type SwitchProps, type TabDefinition, TabSet, type TabSetProps, Table, TableBody, TableCaption, TableCell, type TableCellProps, TableEmpty, TableFoot, TableFooter, TableHead, type TableHeadProps, TableHeader, type TableProps, TableRow, type TableRowProps, TableScroller, Tabs, TabsContent, TabsList, type TabsListProps, TabsRoot, TabsTrigger, type TabsTriggerProps, Textarea, type TextareaProps, type ToastOptions, ToastProvider, type ToastProviderProps, type ToastTone, ToggleGroup, type ToggleGroupProps, type ToggleOption, Tooltip, TooltipContent, type TooltipContentProps, type TooltipProps, TooltipProvider, TooltipRoot, TooltipTrigger, type UseSortStateResult, cn, formatDate, formatDateTime, formatMoney, formatNumber, formatPercent, useFieldControl, useSortState, useToast };
1298
+ export { Accordion, AccordionContent, AccordionItem, type AccordionProps, AccordionRoot, type AccordionSection, AccordionTrigger, type AccordionTriggerProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Badge, type BadgeProps, type BadgeTone, Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, type ButtonSize, type ButtonVariant, Card, CardBody, CardDescription, CardFooter, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, Checkbox, type CheckboxProps, type ClassValue, Combobox, type ComboboxOption, type ComboboxProps, ComingSoon, type ComingSoonProps, ConfirmDialog, type ConfirmDialogProps, CountBadge, type CountBadgeProps, CreatableSelect, type CreatableSelectProps, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogPortal, DialogRoot, type DialogSize, DialogTitle, DialogTrigger, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, Field, type FieldProps, Fieldset, type FieldsetProps, IconButton, type IconButtonProps, Input, type InputProps, type InputSize, Label, type LabelProps, LoadingState, type LoadingStateProps, Menu, type MenuAction, MenuCheckboxItem, MenuContent, MenuGroup, MenuItem, type MenuItemProps, MenuLabel, type MenuProps, MenuRadioGroup, MenuRadioItem, MenuRoot, MenuSeparator, MenuSub, MenuSubContent, MenuSubTrigger, MenuTrigger, Modal, type ModalProps, type MoneyOptions, Pagination, type PaginationProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverRoot, PopoverTrigger, Progress, type ProgressProps, ScrollArea, type ScrollAreaProps, SearchInput, type SearchInputProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, type SelectOption, type SelectProps, SelectRoot, SelectSeparator, SelectTrigger, type SelectTriggerProps, SelectValue, Separator, type SeparatorProps, Sheet, SheetBody, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger, SideModal, Skeleton, type SkeletonProps, Slider, type SliderProps, type SortDirection, type SortState, Switch, type SwitchProps, type TabDefinition, TabSet, type TabSetProps, Table, TableBody, TableCaption, TableCell, type TableCellProps, TableEmpty, TableFoot, TableFooter, TableHead, type TableHeadProps, TableHeader, type TableProps, TableRow, type TableRowProps, TableScroller, Tabs, TabsContent, TabsList, type TabsListProps, TabsRoot, TabsTrigger, type TabsTriggerProps, Textarea, type TextareaProps, type ToastOptions, ToastProvider, type ToastProviderProps, type ToastTone, ToggleGroup, type ToggleGroupProps, type ToggleOption, Tooltip, TooltipContent, type TooltipContentProps, type TooltipProps, TooltipProvider, TooltipRoot, TooltipTrigger, type UseSortStateResult, cn, formatDate, formatDateTime, formatMoney, formatNumber, formatPercent, useFieldControl, useSortState, useToast };
package/dist/index.js CHANGED
@@ -724,15 +724,162 @@ function Select({
724
724
  );
725
725
  }
726
726
 
727
+ // src/CreatableSelect.tsx
728
+ import { useMemo, useState } from "react";
729
+ import { Plus } from "lucide-react";
730
+
731
+ // src/CreatableSelect.css
732
+ styleInject("@layer components {\n :where(.cfi-creatable) {\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-sm);\n width: 100%;\n }\n :where(.cfi-creatable__select) {\n flex: 1 1 auto;\n min-width: 0;\n }\n :where(.cfi-creatable) > :where(button) {\n flex: 0 0 auto;\n }\n}\n");
733
+
734
+ // src/CreatableSelect.tsx
735
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
736
+ function normalize(value) {
737
+ return value.trim().toLowerCase();
738
+ }
739
+ function labelText(option) {
740
+ return typeof option.label === "string" ? option.label : null;
741
+ }
742
+ function CreatableSelect({
743
+ onCreate,
744
+ canCreate = true,
745
+ className,
746
+ addLabel = "Add to list",
747
+ createTitle = "Add to list",
748
+ createDescription,
749
+ createFieldLabel = "Name",
750
+ createPlaceholder,
751
+ createSubmitLabel = "Add",
752
+ createPendingLabel = "Adding...",
753
+ createCancelLabel = "Cancel",
754
+ duplicateHint = "Already in the list \u2014 this will select the existing one.",
755
+ options,
756
+ onValueChange,
757
+ disabled,
758
+ ...select
759
+ }) {
760
+ const [open, setOpen] = useState(false);
761
+ const [draft, setDraft] = useState("");
762
+ const [pending, setPending] = useState(false);
763
+ const [error, setError] = useState(null);
764
+ const [created, setCreated] = useState([]);
765
+ const merged = useMemo(() => {
766
+ const seen = new Set(options.map((o) => o.value));
767
+ return [...options, ...created.filter((o) => !seen.has(o.value))];
768
+ }, [options, created]);
769
+ const match = useMemo(() => {
770
+ const wanted = normalize(draft);
771
+ if (wanted === "") return null;
772
+ return merged.find((o) => {
773
+ const text = labelText(o);
774
+ return text !== null && normalize(text) === wanted;
775
+ }) ?? null;
776
+ }, [draft, merged]);
777
+ const showAdd = Boolean(onCreate) && canCreate && !disabled;
778
+ function close() {
779
+ setOpen(false);
780
+ setDraft("");
781
+ setError(null);
782
+ setPending(false);
783
+ }
784
+ async function submit() {
785
+ const name = draft.trim();
786
+ if (name === "" || pending || !onCreate) return;
787
+ if (match) {
788
+ onValueChange?.(match.value);
789
+ close();
790
+ return;
791
+ }
792
+ setPending(true);
793
+ setError(null);
794
+ try {
795
+ const option = await onCreate(name);
796
+ setCreated((prev) => [...prev, option]);
797
+ onValueChange?.(option.value);
798
+ close();
799
+ } catch (cause) {
800
+ setError(cause instanceof Error ? cause.message : String(cause));
801
+ setPending(false);
802
+ }
803
+ }
804
+ return /* @__PURE__ */ jsxs11("div", { className: cn("cfi-creatable", className), children: [
805
+ /* @__PURE__ */ jsx11("div", { className: "cfi-creatable__select", children: /* @__PURE__ */ jsx11(Select, { ...select, options: merged, onValueChange, disabled }) }),
806
+ showAdd && /* @__PURE__ */ jsx11(
807
+ IconButton,
808
+ {
809
+ type: "button",
810
+ variant: "secondary",
811
+ size: select.size ?? "md",
812
+ icon: /* @__PURE__ */ jsx11(Plus, { "aria-hidden": "true" }),
813
+ label: addLabel,
814
+ onClick: () => setOpen(true)
815
+ }
816
+ ),
817
+ /* @__PURE__ */ jsx11(
818
+ Modal,
819
+ {
820
+ open,
821
+ onOpenChange: (next) => next ? setOpen(true) : close(),
822
+ title: createTitle,
823
+ description: createDescription,
824
+ size: "sm",
825
+ footer: /* @__PURE__ */ jsxs11(ButtonGroup, { children: [
826
+ /* @__PURE__ */ jsx11(Button, { type: "button", variant: "secondary", onClick: close, disabled: pending, children: createCancelLabel }),
827
+ /* @__PURE__ */ jsx11(
828
+ Button,
829
+ {
830
+ type: "button",
831
+ loading: pending,
832
+ onClick: () => void submit(),
833
+ disabled: pending || draft.trim() === "",
834
+ children: pending ? createPendingLabel : createSubmitLabel
835
+ }
836
+ )
837
+ ] }),
838
+ children: /* @__PURE__ */ jsxs11(
839
+ "form",
840
+ {
841
+ onSubmit: (event) => {
842
+ event.preventDefault();
843
+ void submit();
844
+ },
845
+ children: [
846
+ /* @__PURE__ */ jsx11(
847
+ Field,
848
+ {
849
+ label: createFieldLabel,
850
+ required: true,
851
+ error,
852
+ hint: match ? duplicateHint : void 0,
853
+ children: /* @__PURE__ */ jsx11(
854
+ Input,
855
+ {
856
+ value: draft,
857
+ onChange: (event) => setDraft(event.target.value),
858
+ placeholder: createPlaceholder,
859
+ disabled: pending,
860
+ autoFocus: true
861
+ }
862
+ )
863
+ }
864
+ ),
865
+ /* @__PURE__ */ jsx11("button", { type: "submit", hidden: true, "aria-hidden": "true", tabIndex: -1 })
866
+ ]
867
+ }
868
+ )
869
+ }
870
+ )
871
+ ] });
872
+ }
873
+
727
874
  // src/Combobox.tsx
728
- import { useEffect, useId as useId2, useMemo, useRef, useState } from "react";
875
+ import { useEffect, useId as useId2, useMemo as useMemo2, useRef, useState as useState2 } from "react";
729
876
  import { Check as Check4, ChevronDown as ChevronDown2, Search, X as X2 } from "lucide-react";
730
877
 
731
878
  // src/Combobox.css
732
879
  styleInject("@layer components {\n .cfi-ui-combobox {\n position: relative;\n display: inline-flex;\n align-items: center;\n }\n .cfi-ui-combobox--full {\n display: flex;\n width: 100%;\n }\n :where(.cfi-ui-combobox__trigger) {\n display: inline-flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--cfi-ui-space-sm);\n width: 100%;\n height: var(--cfi-ui-control-height-md);\n padding-inline: 0.625rem;\n background: var(--cfi-ui-surface);\n color: var(--cfi-ui-content);\n border: 1px solid var(--cfi-ui-border-strong);\n border-radius: var(--cfi-ui-radius-md);\n font-family: inherit;\n font-size: var(--cfi-ui-text-sm);\n line-height: normal;\n cursor: pointer;\n transition: border-color var(--cfi-ui-transition-fast);\n }\n .cfi-ui-combobox__trigger:hover:not(:disabled) {\n border-color: var(--cfi-ui-content-subtle);\n }\n .cfi-ui-combobox__trigger:disabled {\n background: var(--cfi-ui-surface-disabled);\n color: var(--cfi-ui-content-disabled);\n cursor: not-allowed;\n }\n .cfi-ui-combobox__trigger[data-invalid] {\n border-color: var(--cfi-ui-error);\n }\n .cfi-ui-combobox__trigger[data-size=sm] {\n height: var(--cfi-ui-control-height-sm);\n padding-inline: 0.5rem;\n font-size: var(--cfi-ui-text-xs);\n }\n .cfi-ui-combobox__trigger[data-size=lg] {\n height: var(--cfi-ui-control-height-lg);\n padding-inline: 0.875rem;\n font-size: var(--cfi-ui-text-base);\n }\n .cfi-ui-combobox__trigger[data-placeholder] .cfi-ui-combobox__value {\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-combobox__value {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n }\n .cfi-ui-combobox__chevron {\n display: inline-flex;\n flex: none;\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-combobox__chevron > svg,\n .cfi-ui-combobox__clear > svg {\n width: 0.875rem;\n height: 0.875rem;\n display: block;\n }\n .cfi-ui-combobox__clear {\n position: absolute;\n right: 1.75rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: 0;\n border-radius: var(--cfi-ui-radius-sm);\n background: transparent;\n color: var(--cfi-ui-content-muted);\n cursor: pointer;\n }\n .cfi-ui-combobox__clear:hover {\n background: var(--cfi-ui-surface-active);\n color: var(--cfi-ui-content);\n }\n .cfi-ui-combobox__panel {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n max-height: min(22rem, var(--radix-popover-content-available-height, 22rem));\n }\n .cfi-ui-combobox__search {\n flex: none;\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-sm);\n padding: var(--cfi-ui-space-sm);\n border-bottom: 1px solid var(--cfi-ui-border);\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-combobox__search > svg {\n width: 0.875rem;\n height: 0.875rem;\n flex: none;\n }\n .cfi-ui-combobox__search input {\n flex: 1 1 auto;\n min-width: 0;\n border: 0;\n background: transparent;\n color: var(--cfi-ui-content);\n font-family: inherit;\n font-size: var(--cfi-ui-text-sm);\n outline: none;\n }\n .cfi-ui-combobox__search input::placeholder {\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-combobox__list {\n flex: 1 1 auto;\n min-height: 0;\n overflow-y: auto;\n padding: var(--cfi-ui-space-xs);\n }\n .cfi-ui-combobox__option {\n align-items: flex-start;\n }\n .cfi-ui-combobox__option > .cfi-ui-select-item__indicator {\n padding-top: 0.125rem;\n }\n .cfi-ui-combobox__option-text {\n display: grid;\n gap: var(--cfi-ui-space-3xs);\n min-width: 0;\n }\n .cfi-ui-combobox__option-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .cfi-ui-combobox__option-hint {\n font-size: var(--cfi-ui-text-xs);\n color: var(--cfi-ui-content-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n");
733
880
 
734
881
  // src/Combobox.tsx
735
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
882
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
736
883
  function Combobox({
737
884
  options,
738
885
  value,
@@ -754,13 +901,13 @@ function Combobox({
754
901
  fullWidth = true,
755
902
  ...aria
756
903
  }) {
757
- const [open, setOpen] = useState(false);
758
- const [search, setSearch] = useState("");
759
- const [highlighted, setHighlighted] = useState(0);
904
+ const [open, setOpen] = useState2(false);
905
+ const [search, setSearch] = useState2("");
906
+ const [highlighted, setHighlighted] = useState2(0);
760
907
  const listId = useId2();
761
908
  const searchRef = useRef(null);
762
909
  const listRef = useRef(null);
763
- const filtered = useMemo(() => {
910
+ const filtered = useMemo2(() => {
764
911
  if (onSearchChange) return options;
765
912
  const q = search.trim().toLowerCase();
766
913
  if (!q) return options;
@@ -814,14 +961,14 @@ function Combobox({
814
961
  setHighlighted(0);
815
962
  onSearchChange?.(next);
816
963
  }
817
- return /* @__PURE__ */ jsxs11(PopoverRoot, { open, onOpenChange: setOpen, children: [
818
- /* @__PURE__ */ jsx11(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs11(
964
+ return /* @__PURE__ */ jsxs12(PopoverRoot, { open, onOpenChange: setOpen, children: [
965
+ /* @__PURE__ */ jsx12(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs12(
819
966
  "div",
820
967
  {
821
968
  style,
822
969
  className: cn("cfi-ui", "cfi-ui-combobox", fullWidth && "cfi-ui-combobox--full", className),
823
970
  children: [
824
- /* @__PURE__ */ jsxs11(
971
+ /* @__PURE__ */ jsxs12(
825
972
  "button",
826
973
  {
827
974
  type: "button",
@@ -838,12 +985,12 @@ function Combobox({
838
985
  onClick: () => setOpen((o) => !o),
839
986
  ...aria,
840
987
  children: [
841
- /* @__PURE__ */ jsx11("span", { className: "cfi-ui-combobox__value", children: selected ? selected.label : placeholder }),
842
- /* @__PURE__ */ jsx11("span", { className: "cfi-ui-combobox__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx11(ChevronDown2, {}) })
988
+ /* @__PURE__ */ jsx12("span", { className: "cfi-ui-combobox__value", children: selected ? selected.label : placeholder }),
989
+ /* @__PURE__ */ jsx12("span", { className: "cfi-ui-combobox__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx12(ChevronDown2, {}) })
843
990
  ]
844
991
  }
845
992
  ),
846
- clearable && selected && !disabled && /* @__PURE__ */ jsx11(
993
+ clearable && selected && !disabled && /* @__PURE__ */ jsx12(
847
994
  "button",
848
995
  {
849
996
  type: "button",
@@ -851,14 +998,14 @@ function Combobox({
851
998
  "aria-label": `Clear ${selected.label}`,
852
999
  title: "Clear",
853
1000
  onClick: () => onValueChange(null),
854
- children: /* @__PURE__ */ jsx11(X2, { "aria-hidden": "true" })
1001
+ children: /* @__PURE__ */ jsx12(X2, { "aria-hidden": "true" })
855
1002
  }
856
1003
  ),
857
- name && /* @__PURE__ */ jsx11("input", { type: "hidden", name, value: value ?? "" })
1004
+ name && /* @__PURE__ */ jsx12("input", { type: "hidden", name, value: value ?? "" })
858
1005
  ]
859
1006
  }
860
1007
  ) }),
861
- /* @__PURE__ */ jsxs11(
1008
+ /* @__PURE__ */ jsxs12(
862
1009
  PopoverContent,
863
1010
  {
864
1011
  flush: true,
@@ -870,9 +1017,9 @@ function Combobox({
870
1017
  },
871
1018
  style: { width: "var(--radix-popover-trigger-width)" },
872
1019
  children: [
873
- /* @__PURE__ */ jsxs11("div", { className: "cfi-ui-combobox__search", children: [
874
- /* @__PURE__ */ jsx11(Search, { "aria-hidden": "true" }),
875
- /* @__PURE__ */ jsx11(
1020
+ /* @__PURE__ */ jsxs12("div", { className: "cfi-ui-combobox__search", children: [
1021
+ /* @__PURE__ */ jsx12(Search, { "aria-hidden": "true" }),
1022
+ /* @__PURE__ */ jsx12(
876
1023
  "input",
877
1024
  {
878
1025
  ref: searchRef,
@@ -888,7 +1035,7 @@ function Combobox({
888
1035
  }
889
1036
  )
890
1037
  ] }),
891
- /* @__PURE__ */ jsx11(
1038
+ /* @__PURE__ */ jsx12(
892
1039
  "div",
893
1040
  {
894
1041
  ref: listRef,
@@ -896,10 +1043,10 @@ function Combobox({
896
1043
  role: "listbox",
897
1044
  "aria-busy": loading || void 0,
898
1045
  className: "cfi-ui-combobox__list",
899
- children: loading ? /* @__PURE__ */ jsx11("p", { className: "cfi-ui-select-empty", children: loadingLabel }) : filtered.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "cfi-ui-select-empty", children: emptyLabel }) : filtered.map((option) => {
1046
+ children: loading ? /* @__PURE__ */ jsx12("p", { className: "cfi-ui-select-empty", children: loadingLabel }) : filtered.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "cfi-ui-select-empty", children: emptyLabel }) : filtered.map((option) => {
900
1047
  const index = selectable.indexOf(option);
901
1048
  const isHighlighted = index !== -1 && index === highlighted;
902
- return /* @__PURE__ */ jsxs11(
1049
+ return /* @__PURE__ */ jsxs12(
903
1050
  "div",
904
1051
  {
905
1052
  id: `${listId}-${option.value}`,
@@ -912,10 +1059,10 @@ function Combobox({
912
1059
  onClick: () => !option.disabled && commit(option),
913
1060
  onPointerMove: () => index !== -1 && setHighlighted(index),
914
1061
  children: [
915
- /* @__PURE__ */ jsx11("span", { className: "cfi-ui-select-item__indicator", children: option.value === value && /* @__PURE__ */ jsx11(Check4, { "aria-hidden": "true" }) }),
916
- /* @__PURE__ */ jsxs11("span", { className: "cfi-ui-combobox__option-text", children: [
917
- /* @__PURE__ */ jsx11("span", { className: "cfi-ui-combobox__option-label", children: option.label }),
918
- option.hint && /* @__PURE__ */ jsx11("span", { className: "cfi-ui-combobox__option-hint", children: option.hint })
1062
+ /* @__PURE__ */ jsx12("span", { className: "cfi-ui-select-item__indicator", children: option.value === value && /* @__PURE__ */ jsx12(Check4, { "aria-hidden": "true" }) }),
1063
+ /* @__PURE__ */ jsxs12("span", { className: "cfi-ui-combobox__option-text", children: [
1064
+ /* @__PURE__ */ jsx12("span", { className: "cfi-ui-combobox__option-label", children: option.label }),
1065
+ option.hint && /* @__PURE__ */ jsx12("span", { className: "cfi-ui-combobox__option-hint", children: option.hint })
919
1066
  ] })
920
1067
  ]
921
1068
  },
@@ -933,12 +1080,12 @@ function Combobox({
933
1080
  // src/Tooltip.tsx
934
1081
  import { forwardRef as forwardRef10 } from "react";
935
1082
  import * as RadixTooltip from "@radix-ui/react-tooltip";
936
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1083
+ import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
937
1084
  var TooltipProvider = RadixTooltip.Provider;
938
1085
  var TooltipRoot = RadixTooltip.Root;
939
1086
  var TooltipTrigger = RadixTooltip.Trigger;
940
1087
  var TooltipContent = forwardRef10(function TooltipContent2({ className, children, sideOffset = 5, ...rest }, ref) {
941
- return /* @__PURE__ */ jsx12(RadixTooltip.Portal, { children: /* @__PURE__ */ jsxs12(
1088
+ return /* @__PURE__ */ jsx13(RadixTooltip.Portal, { children: /* @__PURE__ */ jsxs13(
942
1089
  RadixTooltip.Content,
943
1090
  {
944
1091
  ref,
@@ -949,28 +1096,28 @@ var TooltipContent = forwardRef10(function TooltipContent2({ className, children
949
1096
  ...rest,
950
1097
  children: [
951
1098
  children,
952
- /* @__PURE__ */ jsx12(RadixTooltip.Arrow, { className: "cfi-ui-tooltip__arrow", width: 10, height: 4 })
1099
+ /* @__PURE__ */ jsx13(RadixTooltip.Arrow, { className: "cfi-ui-tooltip__arrow", width: 10, height: 4 })
953
1100
  ]
954
1101
  }
955
1102
  ) });
956
1103
  });
957
1104
  function Tooltip({ content, side = "top", align = "center", delay = 300, disabled, children }) {
958
- if (disabled || content == null || content === "") return /* @__PURE__ */ jsx12(Fragment3, { children });
959
- return /* @__PURE__ */ jsx12(RadixTooltip.Provider, { delayDuration: delay, children: /* @__PURE__ */ jsxs12(TooltipRoot, { children: [
960
- /* @__PURE__ */ jsx12(TooltipTrigger, { asChild: true, children }),
961
- /* @__PURE__ */ jsx12(TooltipContent, { side, align, children: content })
1105
+ if (disabled || content == null || content === "") return /* @__PURE__ */ jsx13(Fragment3, { children });
1106
+ return /* @__PURE__ */ jsx13(RadixTooltip.Provider, { delayDuration: delay, children: /* @__PURE__ */ jsxs13(TooltipRoot, { children: [
1107
+ /* @__PURE__ */ jsx13(TooltipTrigger, { asChild: true, children }),
1108
+ /* @__PURE__ */ jsx13(TooltipContent, { side, align, children: content })
962
1109
  ] }) });
963
1110
  }
964
1111
 
965
1112
  // src/Toast.tsx
966
- import { createContext as createContext2, useCallback, useContext as useContext2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
1113
+ import { createContext as createContext2, useCallback, useContext as useContext2, useEffect as useEffect2, useMemo as useMemo3, useRef as useRef2, useState as useState3 } from "react";
967
1114
  import { AlertTriangle, CheckCircle2, Info, X as X3, XCircle } from "lucide-react";
968
1115
 
969
1116
  // src/Toast.css
970
1117
  styleInject("@layer components {\n .cfi-ui-toast-viewport {\n position: fixed;\n z-index: var(--cfi-ui-z-toast);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-ui-space-sm);\n width: min(24rem, calc(100vw - 2 * var(--cfi-ui-space-md)));\n pointer-events: none;\n }\n .cfi-ui-toast-viewport[data-position=bottom-right] {\n right: var(--cfi-ui-space-md);\n bottom: var(--cfi-ui-space-md);\n }\n .cfi-ui-toast-viewport[data-position=top-right] {\n right: var(--cfi-ui-space-md);\n top: calc(var(--cfi-shell-header-height, 48px) + var(--cfi-ui-space-md));\n flex-direction: column-reverse;\n }\n .cfi-ui-toast-viewport[data-position=bottom-center] {\n left: 50%;\n bottom: var(--cfi-ui-space-md);\n transform: translateX(-50%);\n }\n .cfi-ui-toast-viewport[data-position=top-center] {\n left: 50%;\n top: calc(var(--cfi-shell-header-height, 48px) + var(--cfi-ui-space-md));\n transform: translateX(-50%);\n flex-direction: column-reverse;\n }\n .cfi-ui-toast {\n pointer-events: auto;\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: var(--cfi-ui-space-sm);\n align-items: start;\n padding: var(--cfi-ui-space-sm) var(--cfi-ui-space-sm) var(--cfi-ui-space-sm) var(--cfi-ui-space-md);\n background: var(--cfi-ui-surface-raised);\n color: var(--cfi-ui-content);\n border: 1px solid var(--cfi-ui-border);\n border-left: 3px solid var(--cfi-ui-border-strong);\n border-radius: var(--cfi-ui-radius-md);\n box-shadow: var(--cfi-ui-shadow-lg);\n font-family: var(--cfi-ui-font);\n animation: cfi-ui-zoom-in var(--cfi-ui-transition-base);\n }\n .cfi-ui-toast[data-tone=success] {\n border-left-color: var(--cfi-ui-success);\n }\n .cfi-ui-toast[data-tone=warning] {\n border-left-color: var(--cfi-ui-warning);\n }\n .cfi-ui-toast[data-tone=error] {\n border-left-color: var(--cfi-ui-error);\n }\n .cfi-ui-toast[data-tone=info] {\n border-left-color: var(--cfi-ui-info);\n }\n .cfi-ui-toast__icon {\n display: inline-flex;\n flex: none;\n padding-top: 0.0625rem;\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-toast[data-tone=success] .cfi-ui-toast__icon {\n color: var(--cfi-ui-success-text);\n }\n .cfi-ui-toast[data-tone=warning] .cfi-ui-toast__icon {\n color: var(--cfi-ui-warning-text);\n }\n .cfi-ui-toast[data-tone=error] .cfi-ui-toast__icon {\n color: var(--cfi-ui-error-text);\n }\n .cfi-ui-toast[data-tone=info] .cfi-ui-toast__icon {\n color: var(--cfi-ui-info-text);\n }\n .cfi-ui-toast__icon > svg {\n width: 1rem;\n height: 1rem;\n display: block;\n }\n .cfi-ui-toast__text {\n display: grid;\n gap: var(--cfi-ui-space-3xs);\n min-width: 0;\n }\n .cfi-ui-toast__title {\n margin: 0;\n font-size: var(--cfi-ui-text-sm);\n font-weight: var(--cfi-ui-weight-medium);\n line-height: var(--cfi-ui-leading-normal);\n }\n .cfi-ui-toast__description {\n margin: 0;\n font-size: var(--cfi-ui-text-xs);\n line-height: var(--cfi-ui-leading-normal);\n color: var(--cfi-ui-content-muted);\n overflow-wrap: anywhere;\n }\n .cfi-ui-toast__action {\n justify-self: start;\n margin-top: var(--cfi-ui-space-xs);\n padding: 0;\n border: 0;\n background: none;\n color: var(--cfi-ui-content-link);\n font-family: inherit;\n font-size: var(--cfi-ui-text-xs);\n font-weight: var(--cfi-ui-weight-medium);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n }\n .cfi-ui-toast__close {\n flex: none;\n color: var(--cfi-ui-content-muted);\n }\n}\n");
971
1118
 
972
1119
  // src/Toast.tsx
973
- import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1120
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
974
1121
  var ToastContext = createContext2(null);
975
1122
  function useToast() {
976
1123
  const api = useContext2(ToastContext);
@@ -983,7 +1130,7 @@ function ToastProvider({
983
1130
  max = 4,
984
1131
  position = "bottom-right"
985
1132
  }) {
986
- const [items, setItems] = useState2([]);
1133
+ const [items, setItems] = useState3([]);
987
1134
  const nextId = useRef2(1);
988
1135
  const timers = useRef2(/* @__PURE__ */ new Map());
989
1136
  const dismiss = useCallback((id) => {
@@ -1017,7 +1164,7 @@ function ToastProvider({
1017
1164
  pending.clear();
1018
1165
  };
1019
1166
  }, []);
1020
- const api = useMemo2(
1167
+ const api = useMemo3(
1021
1168
  () => ({
1022
1169
  toast,
1023
1170
  dismiss,
@@ -1028,24 +1175,24 @@ function ToastProvider({
1028
1175
  }),
1029
1176
  [toast, dismiss]
1030
1177
  );
1031
- return /* @__PURE__ */ jsxs13(ToastContext.Provider, { value: api, children: [
1178
+ return /* @__PURE__ */ jsxs14(ToastContext.Provider, { value: api, children: [
1032
1179
  children,
1033
- /* @__PURE__ */ jsx13(ToastViewport, { items, onDismiss: dismiss, position })
1180
+ /* @__PURE__ */ jsx14(ToastViewport, { items, onDismiss: dismiss, position })
1034
1181
  ] });
1035
1182
  }
1036
1183
  var TONE_ICON = {
1037
- neutral: /* @__PURE__ */ jsx13(Info, {}),
1038
- info: /* @__PURE__ */ jsx13(Info, {}),
1039
- success: /* @__PURE__ */ jsx13(CheckCircle2, {}),
1040
- warning: /* @__PURE__ */ jsx13(AlertTriangle, {}),
1041
- error: /* @__PURE__ */ jsx13(XCircle, {})
1184
+ neutral: /* @__PURE__ */ jsx14(Info, {}),
1185
+ info: /* @__PURE__ */ jsx14(Info, {}),
1186
+ success: /* @__PURE__ */ jsx14(CheckCircle2, {}),
1187
+ warning: /* @__PURE__ */ jsx14(AlertTriangle, {}),
1188
+ error: /* @__PURE__ */ jsx14(XCircle, {})
1042
1189
  };
1043
1190
  function ToastViewport({
1044
1191
  items,
1045
1192
  onDismiss,
1046
1193
  position
1047
1194
  }) {
1048
- return /* @__PURE__ */ jsx13(
1195
+ return /* @__PURE__ */ jsx14(
1049
1196
  "div",
1050
1197
  {
1051
1198
  role: "region",
@@ -1054,12 +1201,12 @@ function ToastViewport({
1054
1201
  "data-position": position,
1055
1202
  "data-cfi-ui-portal": "",
1056
1203
  className: cn("cfi-ui", "cfi-ui-toast-viewport"),
1057
- children: items.map((item) => /* @__PURE__ */ jsxs13("div", { "data-tone": item.tone, className: "cfi-ui-toast", children: [
1058
- /* @__PURE__ */ jsx13("span", { className: "cfi-ui-toast__icon", "aria-hidden": "true", children: TONE_ICON[item.tone ?? "neutral"] }),
1059
- /* @__PURE__ */ jsxs13("div", { className: "cfi-ui-toast__text", children: [
1060
- /* @__PURE__ */ jsx13("p", { className: "cfi-ui-toast__title", children: item.title }),
1061
- item.description && /* @__PURE__ */ jsx13("p", { className: "cfi-ui-toast__description", children: item.description }),
1062
- item.action && /* @__PURE__ */ jsx13(
1204
+ children: items.map((item) => /* @__PURE__ */ jsxs14("div", { "data-tone": item.tone, className: "cfi-ui-toast", children: [
1205
+ /* @__PURE__ */ jsx14("span", { className: "cfi-ui-toast__icon", "aria-hidden": "true", children: TONE_ICON[item.tone ?? "neutral"] }),
1206
+ /* @__PURE__ */ jsxs14("div", { className: "cfi-ui-toast__text", children: [
1207
+ /* @__PURE__ */ jsx14("p", { className: "cfi-ui-toast__title", children: item.title }),
1208
+ item.description && /* @__PURE__ */ jsx14("p", { className: "cfi-ui-toast__description", children: item.description }),
1209
+ item.action && /* @__PURE__ */ jsx14(
1063
1210
  "button",
1064
1211
  {
1065
1212
  type: "button",
@@ -1072,12 +1219,12 @@ function ToastViewport({
1072
1219
  }
1073
1220
  )
1074
1221
  ] }),
1075
- /* @__PURE__ */ jsx13(
1222
+ /* @__PURE__ */ jsx14(
1076
1223
  IconButton,
1077
1224
  {
1078
1225
  variant: "ghost",
1079
1226
  size: "sm",
1080
- icon: /* @__PURE__ */ jsx13(X3, {}),
1227
+ icon: /* @__PURE__ */ jsx14(X3, {}),
1081
1228
  label: "Dismiss",
1082
1229
  className: "cfi-ui-toast__close",
1083
1230
  onClick: () => onDismiss(item.id)
@@ -1095,9 +1242,9 @@ import { forwardRef as forwardRef11 } from "react";
1095
1242
  styleInject("@layer components {\n :where(.cfi-ui-card) {\n display: flex;\n flex-direction: column;\n min-width: 0;\n background: var(--cfi-ui-surface);\n color: var(--cfi-ui-content);\n border: 1px solid var(--cfi-ui-border);\n border-radius: var(--cfi-ui-radius-xl);\n box-shadow: var(--cfi-ui-shadow-xs);\n font-size: var(--cfi-ui-text-sm);\n }\n .cfi-ui-card[data-variant=outline] {\n box-shadow: none;\n }\n .cfi-ui-card[data-variant=plain] {\n border-color: transparent;\n box-shadow: none;\n background: transparent;\n }\n .cfi-ui-card[data-interactive] {\n cursor: pointer;\n transition: border-color var(--cfi-ui-transition-fast), box-shadow var(--cfi-ui-transition-fast);\n }\n .cfi-ui-card[data-interactive]:hover {\n border-color: var(--cfi-ui-border-strong);\n box-shadow: var(--cfi-ui-shadow-md);\n }\n :where(.cfi-ui-card__header) {\n flex: none;\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: var(--cfi-ui-space-md);\n padding: var(--cfi-ui-space-md);\n border-bottom: 1px solid var(--cfi-ui-border);\n }\n .cfi-ui-card__heading {\n display: grid;\n gap: var(--cfi-ui-space-3xs);\n min-width: 0;\n }\n .cfi-ui-card__actions {\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n flex: none;\n }\n :where(.cfi-ui-card__title) {\n margin: 0;\n font-size: var(--cfi-ui-text-sm);\n font-weight: var(--cfi-ui-weight-semibold);\n line-height: var(--cfi-ui-leading-snug);\n color: var(--cfi-ui-content);\n text-wrap: balance;\n }\n .cfi-ui-card__description {\n flex-basis: 100%;\n margin: 0;\n font-size: var(--cfi-ui-text-xs);\n line-height: var(--cfi-ui-leading-normal);\n color: var(--cfi-ui-content-muted);\n }\n :where(.cfi-ui-card__body) {\n flex: 1 1 auto;\n min-width: 0;\n padding: var(--cfi-ui-space-md);\n }\n .cfi-ui-card[data-flush] > .cfi-ui-card__body {\n padding: 0;\n }\n .cfi-ui-card[data-flush] > .cfi-ui-card__body:last-child {\n overflow: hidden;\n border-bottom-left-radius: var(--cfi-ui-radius-lg);\n border-bottom-right-radius: var(--cfi-ui-radius-lg);\n }\n :where(.cfi-ui-card__footer) {\n flex: none;\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-sm);\n padding: var(--cfi-ui-space-sm) var(--cfi-ui-space-md);\n border-top: 1px solid var(--cfi-ui-border);\n background: var(--cfi-ui-surface-sunken);\n border-bottom-left-radius: var(--cfi-ui-radius-lg);\n border-bottom-right-radius: var(--cfi-ui-radius-lg);\n font-size: var(--cfi-ui-text-xs);\n color: var(--cfi-ui-content-muted);\n }\n}\n");
1096
1243
 
1097
1244
  // src/Card.tsx
1098
- import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
1245
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
1099
1246
  var Card = forwardRef11(function Card2({ variant = "default", flush = false, interactive = false, className, ...rest }, ref) {
1100
- return /* @__PURE__ */ jsx14(
1247
+ return /* @__PURE__ */ jsx15(
1101
1248
  "div",
1102
1249
  {
1103
1250
  ref,
@@ -1110,22 +1257,22 @@ var Card = forwardRef11(function Card2({ variant = "default", flush = false, int
1110
1257
  );
1111
1258
  });
1112
1259
  function CardHeader({ actions, className, children, ...rest }) {
1113
- return /* @__PURE__ */ jsxs14("div", { className: cn("cfi-ui-card__header", className), ...rest, children: [
1114
- actions ? /* @__PURE__ */ jsx14("div", { className: "cfi-ui-card__heading", children }) : children,
1115
- actions && /* @__PURE__ */ jsx14("div", { className: "cfi-ui-card__actions", children: actions })
1260
+ return /* @__PURE__ */ jsxs15("div", { className: cn("cfi-ui-card__header", className), ...rest, children: [
1261
+ actions ? /* @__PURE__ */ jsx15("div", { className: "cfi-ui-card__heading", children }) : children,
1262
+ actions && /* @__PURE__ */ jsx15("div", { className: "cfi-ui-card__actions", children: actions })
1116
1263
  ] });
1117
1264
  }
1118
1265
  function CardTitle({ as: Tag = "h3", className, ...rest }) {
1119
- return /* @__PURE__ */ jsx14(Tag, { className: cn("cfi-ui-card__title", className), ...rest });
1266
+ return /* @__PURE__ */ jsx15(Tag, { className: cn("cfi-ui-card__title", className), ...rest });
1120
1267
  }
1121
1268
  function CardDescription({ className, ...rest }) {
1122
- return /* @__PURE__ */ jsx14("p", { className: cn("cfi-ui-card__description", className), ...rest });
1269
+ return /* @__PURE__ */ jsx15("p", { className: cn("cfi-ui-card__description", className), ...rest });
1123
1270
  }
1124
1271
  function CardBody({ className, ...rest }) {
1125
- return /* @__PURE__ */ jsx14("div", { className: cn("cfi-ui-card__body", className), ...rest });
1272
+ return /* @__PURE__ */ jsx15("div", { className: cn("cfi-ui-card__body", className), ...rest });
1126
1273
  }
1127
1274
  function CardFooter({ className, ...rest }) {
1128
- return /* @__PURE__ */ jsx14("div", { className: cn("cfi-ui-card__footer", className), ...rest });
1275
+ return /* @__PURE__ */ jsx15("div", { className: cn("cfi-ui-card__footer", className), ...rest });
1129
1276
  }
1130
1277
 
1131
1278
  // src/Badge.tsx
@@ -1135,9 +1282,9 @@ import { forwardRef as forwardRef12 } from "react";
1135
1282
  styleInject("@layer components {\n :where(.cfi-ui-badge) {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n padding: 0.125rem 0.5rem;\n border: 1px solid transparent;\n border-radius: var(--cfi-ui-radius-full);\n font-size: var(--cfi-ui-text-xs);\n font-weight: var(--cfi-ui-weight-medium);\n line-height: 1.4;\n white-space: nowrap;\n vertical-align: middle;\n }\n .cfi-ui-badge[data-size=sm] {\n padding: 0 0.375rem;\n font-size: 0.6875rem;\n }\n .cfi-ui-badge__dot {\n flex: none;\n width: 0.375rem;\n height: 0.375rem;\n border-radius: var(--cfi-ui-radius-full);\n background: currentColor;\n }\n .cfi-ui-badge__icon {\n display: inline-flex;\n flex: none;\n }\n .cfi-ui-badge__icon > svg {\n width: 0.75rem;\n height: 0.75rem;\n display: block;\n }\n .cfi-ui-badge--count {\n justify-content: center;\n min-width: 1.25rem;\n padding-inline: 0.375rem;\n font-variant-numeric: tabular-nums;\n }\n .cfi-ui-badge[data-variant=soft][data-tone=neutral] {\n background: var(--cfi-ui-neutral-soft);\n color: var(--cfi-ui-neutral-text);\n }\n .cfi-ui-badge[data-variant=soft][data-tone=success] {\n background: var(--cfi-ui-success-soft);\n color: var(--cfi-ui-success-text);\n }\n .cfi-ui-badge[data-variant=soft][data-tone=warning] {\n background: var(--cfi-ui-warning-soft);\n color: var(--cfi-ui-warning-text);\n }\n .cfi-ui-badge[data-variant=soft][data-tone=error] {\n background: var(--cfi-ui-error-soft);\n color: var(--cfi-ui-error-text);\n }\n .cfi-ui-badge[data-variant=soft][data-tone=info] {\n background: var(--cfi-ui-info-soft);\n color: var(--cfi-ui-info-text);\n }\n .cfi-ui-badge[data-variant=soft][data-tone=accent] {\n background: var(--cfi-ui-accent-soft);\n color: var(--cfi-ui-accent-hover);\n }\n .cfi-ui-badge[data-variant=solid] {\n color: var(--cfi-ui-content-inverse);\n }\n .cfi-ui-badge[data-variant=solid][data-tone=neutral] {\n background: var(--cfi-ui-content-muted);\n }\n .cfi-ui-badge[data-variant=solid][data-tone=success] {\n background: var(--cfi-ui-success-text);\n }\n .cfi-ui-badge[data-variant=solid][data-tone=warning] {\n background: var(--cfi-ui-warning-text);\n }\n .cfi-ui-badge[data-variant=solid][data-tone=error] {\n background: var(--cfi-ui-error-text);\n }\n .cfi-ui-badge[data-variant=solid][data-tone=info] {\n background: var(--cfi-ui-info-text);\n }\n .cfi-ui-badge[data-variant=solid][data-tone=accent] {\n background: var(--cfi-ui-accent);\n color: var(--cfi-ui-accent-fg);\n }\n .cfi-ui-badge[data-variant=outline] {\n background: transparent;\n }\n .cfi-ui-badge[data-variant=outline][data-tone=neutral] {\n border-color: var(--cfi-ui-neutral-border);\n color: var(--cfi-ui-neutral-text);\n }\n .cfi-ui-badge[data-variant=outline][data-tone=success] {\n border-color: var(--cfi-ui-success-border);\n color: var(--cfi-ui-success-text);\n }\n .cfi-ui-badge[data-variant=outline][data-tone=warning] {\n border-color: var(--cfi-ui-warning-border);\n color: var(--cfi-ui-warning-text);\n }\n .cfi-ui-badge[data-variant=outline][data-tone=error] {\n border-color: var(--cfi-ui-error-border);\n color: var(--cfi-ui-error-text);\n }\n .cfi-ui-badge[data-variant=outline][data-tone=info] {\n border-color: var(--cfi-ui-info-border);\n color: var(--cfi-ui-info-text);\n }\n .cfi-ui-badge[data-variant=outline][data-tone=accent] {\n border-color: var(--cfi-ui-accent);\n color: var(--cfi-ui-accent-hover);\n }\n}\n");
1136
1283
 
1137
1284
  // src/Badge.tsx
1138
- import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
1285
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
1139
1286
  var Badge = forwardRef12(function Badge2({ tone = "neutral", variant = "soft", size = "md", dot = false, icon, className, children, ...rest }, ref) {
1140
- return /* @__PURE__ */ jsxs15(
1287
+ return /* @__PURE__ */ jsxs16(
1141
1288
  "span",
1142
1289
  {
1143
1290
  ref,
@@ -1147,7 +1294,7 @@ var Badge = forwardRef12(function Badge2({ tone = "neutral", variant = "soft", s
1147
1294
  className: cn("cfi-ui", "cfi-ui-badge", className),
1148
1295
  ...rest,
1149
1296
  children: [
1150
- icon ? /* @__PURE__ */ jsx15("span", { className: "cfi-ui-badge__icon", children: icon }) : dot && /* @__PURE__ */ jsx15("span", { className: "cfi-ui-badge__dot", "aria-hidden": "true" }),
1297
+ icon ? /* @__PURE__ */ jsx16("span", { className: "cfi-ui-badge__icon", children: icon }) : dot && /* @__PURE__ */ jsx16("span", { className: "cfi-ui-badge__dot", "aria-hidden": "true" }),
1151
1298
  children
1152
1299
  ]
1153
1300
  }
@@ -1155,7 +1302,7 @@ var Badge = forwardRef12(function Badge2({ tone = "neutral", variant = "soft", s
1155
1302
  });
1156
1303
  var CountBadge = forwardRef12(function CountBadge2({ count, max = 99, hideZero = true, className, ...rest }, ref) {
1157
1304
  if (count === 0 && hideZero) return null;
1158
- return /* @__PURE__ */ jsx15(Badge, { ref, className: cn("cfi-ui-badge--count", className), ...rest, children: count > max ? `${max}+` : count });
1305
+ return /* @__PURE__ */ jsx16(Badge, { ref, className: cn("cfi-ui-badge--count", className), ...rest, children: count > max ? `${max}+` : count });
1159
1306
  });
1160
1307
 
1161
1308
  // src/Table.tsx
@@ -1163,37 +1310,38 @@ import { forwardRef as forwardRef13 } from "react";
1163
1310
  import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
1164
1311
 
1165
1312
  // src/Table.css
1166
- styleInject("@layer components {\n :where(.cfi-ui-table-scroller) {\n width: 100%;\n overflow-x: auto;\n position: relative;\n }\n :where(.cfi-ui-table) {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-sm);\n color: var(--cfi-ui-content);\n text-align: left;\n }\n :where(.cfi-ui-table__th) {\n height: 2.75rem;\n padding: 0.5rem 0.75rem;\n border-bottom: 1px solid var(--cfi-ui-border);\n background: transparent;\n font-size: var(--cfi-ui-text-sm);\n font-weight: var(--cfi-ui-weight-medium);\n color: var(--cfi-ui-content);\n white-space: nowrap;\n text-align: left;\n vertical-align: middle;\n }\n .cfi-ui-table[data-density=compact] .cfi-ui-table__th {\n background: var(--cfi-ui-surface-sunken);\n font-size: var(--cfi-ui-text-xs);\n font-weight: var(--cfi-ui-weight-semibold);\n color: var(--cfi-ui-content-muted);\n border-bottom-color: var(--cfi-ui-border-strong);\n }\n .cfi-ui-table[data-sticky] .cfi-ui-table__th {\n position: sticky;\n top: 0;\n z-index: var(--cfi-ui-z-raised, 10);\n }\n .cfi-ui-table__sort {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n margin: -0.125rem -0.25rem;\n padding: 0.125rem 0.25rem;\n border: 0;\n border-radius: var(--cfi-ui-radius-sm);\n background: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n .cfi-ui-table__sort:hover {\n color: var(--cfi-ui-content);\n background: var(--cfi-ui-surface-active);\n }\n .cfi-ui-table__sort-icon {\n display: inline-flex;\n flex: none;\n opacity: 0.55;\n }\n .cfi-ui-table__th[aria-sort=ascending] .cfi-ui-table__sort-icon,\n .cfi-ui-table__th[aria-sort=descending] .cfi-ui-table__sort-icon {\n opacity: 1;\n color: var(--cfi-ui-accent);\n }\n .cfi-ui-table__sort-icon > svg {\n width: 0.75rem;\n height: 0.75rem;\n display: block;\n }\n :where(.cfi-ui-table__td) {\n padding: 0.5rem 0.75rem;\n border-bottom: 1px solid var(--cfi-ui-border-subtle);\n vertical-align: middle;\n }\n .cfi-ui-table[data-density=compact] .cfi-ui-table__td,\n .cfi-ui-table[data-density=compact] .cfi-ui-table__th {\n padding: 0.3125rem 0.625rem;\n }\n .cfi-ui-table__row[data-interactive] {\n cursor: pointer;\n }\n .cfi-ui-table__row[data-interactive]:hover .cfi-ui-table__td {\n background: var(--cfi-ui-surface-hover);\n }\n .cfi-ui-table__row[data-selected] .cfi-ui-table__td {\n background: var(--cfi-ui-surface-selected);\n }\n .cfi-ui-table__body .cfi-ui-table__row:last-child .cfi-ui-table__td {\n border-bottom: 0;\n }\n .cfi-ui-table__th[data-numeric],\n .cfi-ui-table__td[data-numeric] {\n text-align: right;\n font-variant-numeric: tabular-nums;\n }\n .cfi-ui-table__td[data-truncate] {\n max-width: 18rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .cfi-ui-table__foot .cfi-ui-table__td {\n border-top: 1px solid var(--cfi-ui-border-strong);\n border-bottom: 0;\n background: var(--cfi-ui-surface-sunken);\n font-weight: var(--cfi-ui-weight-semibold);\n }\n .cfi-ui-table__empty {\n padding: var(--cfi-ui-space-xl) var(--cfi-ui-space-md);\n border-bottom: 0;\n color: var(--cfi-ui-content-muted);\n text-align: center;\n }\n .cfi-ui-table__caption {\n padding: var(--cfi-ui-space-sm) 0;\n caption-side: bottom;\n font-size: var(--cfi-ui-text-xs);\n color: var(--cfi-ui-content-muted);\n text-align: left;\n }\n}\n");
1313
+ styleInject("@layer components {\n :where(.cfi-ui-table-scroller) {\n width: 100%;\n overflow-x: auto;\n position: relative;\n }\n :where(.cfi-ui-table) {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-sm);\n color: var(--cfi-ui-content);\n text-align: left;\n }\n :where(.cfi-ui-table__th) {\n height: 2.75rem;\n padding: 0.5rem 0.75rem;\n border-bottom: 1px solid var(--cfi-ui-border);\n background: transparent;\n font-size: var(--cfi-ui-text-sm);\n font-weight: var(--cfi-ui-weight-medium);\n color: var(--cfi-ui-content);\n white-space: nowrap;\n text-align: left;\n vertical-align: middle;\n }\n .cfi-ui-table[data-density=compact] .cfi-ui-table__th {\n background: var(--cfi-ui-surface-sunken);\n font-size: var(--cfi-ui-text-xs);\n font-weight: var(--cfi-ui-weight-semibold);\n color: var(--cfi-ui-content-muted);\n border-bottom-color: var(--cfi-ui-border-strong);\n }\n .cfi-ui-table[data-sticky] .cfi-ui-table__th {\n position: sticky;\n top: 0;\n z-index: var(--cfi-ui-z-raised, 10);\n }\n .cfi-ui-table[data-sticky-col] .cfi-ui-table__th:first-child,\n .cfi-ui-table[data-sticky-col] .cfi-ui-table__td:first-child {\n position: sticky;\n left: 0;\n background: var(--cfi-ui-surface);\n box-shadow: 1px 0 0 0 var(--cfi-ui-border-subtle);\n }\n .cfi-ui-table[data-sticky-col] .cfi-ui-table__td:first-child {\n z-index: 1;\n }\n .cfi-ui-table[data-sticky-col] .cfi-ui-table__th:first-child {\n z-index: calc(var(--cfi-ui-z-raised, 10) + 1);\n }\n .cfi-ui-table[data-sticky-col] .cfi-ui-table__row[data-interactive]:hover .cfi-ui-table__td:first-child {\n background: var(--cfi-ui-surface-hover);\n }\n .cfi-ui-table[data-sticky-col] .cfi-ui-table__row[data-selected] .cfi-ui-table__td:first-child {\n background: var(--cfi-ui-surface-selected);\n }\n .cfi-ui-table__sort {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n margin: -0.125rem -0.25rem;\n padding: 0.125rem 0.25rem;\n border: 0;\n border-radius: var(--cfi-ui-radius-sm);\n background: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n .cfi-ui-table__sort:hover {\n color: var(--cfi-ui-content);\n background: var(--cfi-ui-surface-active);\n }\n .cfi-ui-table__sort-icon {\n display: inline-flex;\n flex: none;\n opacity: 0.55;\n }\n .cfi-ui-table__th[aria-sort=ascending] .cfi-ui-table__sort-icon,\n .cfi-ui-table__th[aria-sort=descending] .cfi-ui-table__sort-icon {\n opacity: 1;\n color: var(--cfi-ui-accent);\n }\n .cfi-ui-table__sort-icon > svg {\n width: 0.75rem;\n height: 0.75rem;\n display: block;\n }\n :where(.cfi-ui-table__td) {\n padding: 0.5rem 0.75rem;\n border-bottom: 1px solid var(--cfi-ui-border-subtle);\n vertical-align: middle;\n }\n .cfi-ui-table[data-density=compact] .cfi-ui-table__td,\n .cfi-ui-table[data-density=compact] .cfi-ui-table__th {\n padding: 0.3125rem 0.625rem;\n }\n .cfi-ui-table__row[data-interactive] {\n cursor: pointer;\n }\n .cfi-ui-table__row[data-interactive]:hover .cfi-ui-table__td {\n background: var(--cfi-ui-surface-hover);\n }\n .cfi-ui-table__row[data-selected] .cfi-ui-table__td {\n background: var(--cfi-ui-surface-selected);\n }\n .cfi-ui-table__body .cfi-ui-table__row:last-child .cfi-ui-table__td {\n border-bottom: 0;\n }\n .cfi-ui-table__th[data-numeric],\n .cfi-ui-table__td[data-numeric] {\n text-align: right;\n font-variant-numeric: tabular-nums;\n }\n .cfi-ui-table__td[data-truncate] {\n max-width: 18rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .cfi-ui-table__foot .cfi-ui-table__td {\n border-top: 1px solid var(--cfi-ui-border-strong);\n border-bottom: 0;\n background: var(--cfi-ui-surface-sunken);\n font-weight: var(--cfi-ui-weight-semibold);\n }\n .cfi-ui-table__empty {\n padding: var(--cfi-ui-space-xl) var(--cfi-ui-space-md);\n border-bottom: 0;\n color: var(--cfi-ui-content-muted);\n text-align: center;\n }\n .cfi-ui-table__caption {\n padding: var(--cfi-ui-space-sm) 0;\n caption-side: bottom;\n font-size: var(--cfi-ui-text-xs);\n color: var(--cfi-ui-content-muted);\n text-align: left;\n }\n}\n");
1167
1314
 
1168
1315
  // src/Table.tsx
1169
- import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
1170
- var Table = forwardRef13(function Table2({ density = "comfortable", stickyHeader = false, className, ...rest }, ref) {
1171
- return /* @__PURE__ */ jsx16(
1316
+ import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
1317
+ var Table = forwardRef13(function Table2({ density = "comfortable", stickyHeader = false, stickyFirstColumn = false, className, ...rest }, ref) {
1318
+ return /* @__PURE__ */ jsx17(
1172
1319
  "table",
1173
1320
  {
1174
1321
  ref,
1175
1322
  "data-density": density,
1176
1323
  "data-sticky": stickyHeader || void 0,
1324
+ "data-sticky-col": stickyFirstColumn || void 0,
1177
1325
  className: cn("cfi-ui", "cfi-ui-table", className),
1178
1326
  ...rest
1179
1327
  }
1180
1328
  );
1181
1329
  });
1182
1330
  function TableScroller({ className, ...rest }) {
1183
- return /* @__PURE__ */ jsx16("div", { className: cn("cfi-ui", "cfi-ui-table-scroller", className), ...rest });
1331
+ return /* @__PURE__ */ jsx17("div", { className: cn("cfi-ui", "cfi-ui-table-scroller", className), ...rest });
1184
1332
  }
1185
1333
  function TableHeader({ className, ...rest }) {
1186
- return /* @__PURE__ */ jsx16("thead", { className: cn("cfi-ui-table__head", className), ...rest });
1334
+ return /* @__PURE__ */ jsx17("thead", { className: cn("cfi-ui-table__head", className), ...rest });
1187
1335
  }
1188
1336
  function TableBody({ className, ...rest }) {
1189
- return /* @__PURE__ */ jsx16("tbody", { className: cn("cfi-ui-table__body", className), ...rest });
1337
+ return /* @__PURE__ */ jsx17("tbody", { className: cn("cfi-ui-table__body", className), ...rest });
1190
1338
  }
1191
1339
  function TableFooter({ className, ...rest }) {
1192
- return /* @__PURE__ */ jsx16("tfoot", { className: cn("cfi-ui-table__foot", className), ...rest });
1340
+ return /* @__PURE__ */ jsx17("tfoot", { className: cn("cfi-ui-table__foot", className), ...rest });
1193
1341
  }
1194
1342
  var TableFoot = TableFooter;
1195
1343
  function TableRow({ selected, interactive, className, ...rest }) {
1196
- return /* @__PURE__ */ jsx16(
1344
+ return /* @__PURE__ */ jsx17(
1197
1345
  "tr",
1198
1346
  {
1199
1347
  "data-selected": selected || void 0,
@@ -1216,7 +1364,7 @@ function TableHead({
1216
1364
  ...rest
1217
1365
  }) {
1218
1366
  const ariaSort = sortable ? sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none" : void 0;
1219
- return /* @__PURE__ */ jsx16(
1367
+ return /* @__PURE__ */ jsx17(
1220
1368
  "th",
1221
1369
  {
1222
1370
  scope: "col",
@@ -1225,15 +1373,15 @@ function TableHead({
1225
1373
  style: { width, ...style },
1226
1374
  className: cn("cfi-ui-table__th", className),
1227
1375
  ...rest,
1228
- children: sortable ? /* @__PURE__ */ jsxs16("button", { type: "button", className: "cfi-ui-table__sort", onClick: onSort, children: [
1229
- /* @__PURE__ */ jsx16("span", { children }),
1230
- /* @__PURE__ */ jsx16("span", { className: "cfi-ui-table__sort-icon", "aria-hidden": "true", children: sortDirection === "asc" ? /* @__PURE__ */ jsx16(ArrowUp, {}) : sortDirection === "desc" ? /* @__PURE__ */ jsx16(ArrowDown, {}) : /* @__PURE__ */ jsx16(ChevronsUpDown, {}) })
1376
+ children: sortable ? /* @__PURE__ */ jsxs17("button", { type: "button", className: "cfi-ui-table__sort", onClick: onSort, children: [
1377
+ /* @__PURE__ */ jsx17("span", { children }),
1378
+ /* @__PURE__ */ jsx17("span", { className: "cfi-ui-table__sort-icon", "aria-hidden": "true", children: sortDirection === "asc" ? /* @__PURE__ */ jsx17(ArrowUp, {}) : sortDirection === "desc" ? /* @__PURE__ */ jsx17(ArrowDown, {}) : /* @__PURE__ */ jsx17(ChevronsUpDown, {}) })
1231
1379
  ] }) : children
1232
1380
  }
1233
1381
  );
1234
1382
  }
1235
1383
  function TableCell({ numeric, truncate, className, ...rest }) {
1236
- return /* @__PURE__ */ jsx16(
1384
+ return /* @__PURE__ */ jsx17(
1237
1385
  "td",
1238
1386
  {
1239
1387
  "data-numeric": numeric || void 0,
@@ -1244,10 +1392,10 @@ function TableCell({ numeric, truncate, className, ...rest }) {
1244
1392
  );
1245
1393
  }
1246
1394
  function TableEmpty({ colSpan, children }) {
1247
- return /* @__PURE__ */ jsx16("tr", { className: "cfi-ui-table__row", children: /* @__PURE__ */ jsx16("td", { colSpan, className: "cfi-ui-table__empty", children }) });
1395
+ return /* @__PURE__ */ jsx17("tr", { className: "cfi-ui-table__row", children: /* @__PURE__ */ jsx17("td", { colSpan, className: "cfi-ui-table__empty", children }) });
1248
1396
  }
1249
1397
  function TableCaption({ className, ...rest }) {
1250
- return /* @__PURE__ */ jsx16("caption", { className: cn("cfi-ui-table__caption", className), ...rest });
1398
+ return /* @__PURE__ */ jsx17("caption", { className: cn("cfi-ui-table__caption", className), ...rest });
1251
1399
  }
1252
1400
 
1253
1401
  // src/Tabs.tsx
@@ -1258,12 +1406,12 @@ import * as RadixTabs from "@radix-ui/react-tabs";
1258
1406
  styleInject("@layer components {\n .cfi-ui-tabs {\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n :where(.cfi-ui-tabs__list) {\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n overflow-x: auto;\n scrollbar-width: none;\n }\n .cfi-ui-tabs__list::-webkit-scrollbar {\n display: none;\n }\n :where(.cfi-ui-tabs__trigger) {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n flex: none;\n border: 0;\n background: none;\n color: var(--cfi-ui-content-muted);\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-sm);\n font-weight: var(--cfi-ui-weight-medium);\n cursor: pointer;\n transition:\n color var(--cfi-ui-transition-fast),\n background-color var(--cfi-ui-transition-fast),\n border-color var(--cfi-ui-transition-fast);\n }\n .cfi-ui-tabs__trigger:disabled {\n color: var(--cfi-ui-content-disabled);\n cursor: not-allowed;\n }\n .cfi-ui-tabs__icon {\n display: inline-flex;\n flex: none;\n }\n .cfi-ui-tabs__icon > svg {\n width: 0.875rem;\n height: 0.875rem;\n display: block;\n }\n .cfi-ui-tabs__list[data-variant=underline] {\n gap: var(--cfi-ui-space-md);\n border-bottom: 1px solid var(--cfi-ui-border);\n }\n .cfi-ui-tabs__list[data-variant=underline] .cfi-ui-tabs__trigger {\n padding: 0.5rem 0.125rem;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n }\n .cfi-ui-tabs__list[data-variant=underline] .cfi-ui-tabs__trigger:hover:not(:disabled) {\n color: var(--cfi-ui-content);\n }\n .cfi-ui-tabs__list[data-variant=underline] .cfi-ui-tabs__trigger[data-state=active] {\n color: var(--cfi-ui-content);\n border-bottom-color: var(--cfi-ui-accent);\n }\n .cfi-ui-tabs__list[data-variant=pill] {\n gap: 0;\n padding: 0.1875rem;\n background: var(--cfi-ui-surface-muted);\n border: 0;\n border-radius: 14px;\n align-self: flex-start;\n }\n .cfi-ui-tabs__list[data-variant=pill] .cfi-ui-tabs__trigger {\n padding: 0.25rem 0.75rem;\n border-radius: 14px;\n color: var(--cfi-ui-content);\n }\n .cfi-ui-tabs__list[data-variant=pill] .cfi-ui-tabs__trigger:hover:not(:disabled) {\n color: var(--cfi-ui-content);\n }\n .cfi-ui-tabs__list[data-variant=pill] .cfi-ui-tabs__trigger[data-state=active] {\n background: var(--cfi-ui-surface);\n color: var(--cfi-ui-content);\n box-shadow: var(--cfi-ui-shadow-xs);\n }\n :where(.cfi-ui-tabs__content) {\n min-width: 0;\n padding-top: var(--cfi-ui-space-md);\n }\n .cfi-ui-tabs__content:focus-visible {\n outline: none;\n }\n}\n");
1259
1407
 
1260
1408
  // src/Tabs.tsx
1261
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
1409
+ import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
1262
1410
  var Tabs = RadixTabs.Root;
1263
1411
  var TabsRoot = RadixTabs.Root;
1264
1412
  var TabsList = forwardRef14(
1265
1413
  function TabsList2({ variant = "pill", className, ...rest }, ref) {
1266
- return /* @__PURE__ */ jsx17(
1414
+ return /* @__PURE__ */ jsx18(
1267
1415
  RadixTabs.List,
1268
1416
  {
1269
1417
  ref,
@@ -1276,18 +1424,18 @@ var TabsList = forwardRef14(
1276
1424
  );
1277
1425
  var TabsTrigger = forwardRef14(
1278
1426
  function TabsTrigger2({ icon, count, className, children, ...rest }, ref) {
1279
- return /* @__PURE__ */ jsxs17(RadixTabs.Trigger, { ref, className: cn("cfi-ui-tabs__trigger", className), ...rest, children: [
1280
- icon && /* @__PURE__ */ jsx17("span", { className: "cfi-ui-tabs__icon", children: icon }),
1281
- /* @__PURE__ */ jsx17("span", { children }),
1282
- count !== void 0 && /* @__PURE__ */ jsx17(CountBadge, { count, size: "sm" })
1427
+ return /* @__PURE__ */ jsxs18(RadixTabs.Trigger, { ref, className: cn("cfi-ui-tabs__trigger", className), ...rest, children: [
1428
+ icon && /* @__PURE__ */ jsx18("span", { className: "cfi-ui-tabs__icon", children: icon }),
1429
+ /* @__PURE__ */ jsx18("span", { children }),
1430
+ count !== void 0 && /* @__PURE__ */ jsx18(CountBadge, { count, size: "sm" })
1283
1431
  ] });
1284
1432
  }
1285
1433
  );
1286
1434
  var TabsContent = forwardRef14(function TabsContent2({ className, ...rest }, ref) {
1287
- return /* @__PURE__ */ jsx17(RadixTabs.Content, { ref, className: cn("cfi-ui-tabs__content", className), ...rest });
1435
+ return /* @__PURE__ */ jsx18(RadixTabs.Content, { ref, className: cn("cfi-ui-tabs__content", className), ...rest });
1288
1436
  });
1289
1437
  function TabSet({ tabs, value, onValueChange, defaultValue, variant, className }) {
1290
- return /* @__PURE__ */ jsxs17(
1438
+ return /* @__PURE__ */ jsxs18(
1291
1439
  Tabs,
1292
1440
  {
1293
1441
  value,
@@ -1295,7 +1443,7 @@ function TabSet({ tabs, value, onValueChange, defaultValue, variant, className }
1295
1443
  defaultValue: defaultValue ?? tabs[0]?.value,
1296
1444
  className: cn("cfi-ui", "cfi-ui-tabs", className),
1297
1445
  children: [
1298
- /* @__PURE__ */ jsx17(TabsList, { variant, children: tabs.map((tab) => /* @__PURE__ */ jsx17(
1446
+ /* @__PURE__ */ jsx18(TabsList, { variant, children: tabs.map((tab) => /* @__PURE__ */ jsx18(
1299
1447
  TabsTrigger,
1300
1448
  {
1301
1449
  value: tab.value,
@@ -1306,7 +1454,7 @@ function TabSet({ tabs, value, onValueChange, defaultValue, variant, className }
1306
1454
  },
1307
1455
  tab.value
1308
1456
  )) }),
1309
- tabs.map((tab) => /* @__PURE__ */ jsx17(TabsContent, { value: tab.value, children: tab.content }, tab.value))
1457
+ tabs.map((tab) => /* @__PURE__ */ jsx18(TabsContent, { value: tab.value, children: tab.content }, tab.value))
1310
1458
  ]
1311
1459
  }
1312
1460
  );
@@ -1319,12 +1467,12 @@ import { forwardRef as forwardRef15 } from "react";
1319
1467
  styleInject('@layer components {\n :where(.cfi-ui-separator) {\n flex: none;\n background: var(--cfi-ui-border);\n }\n .cfi-ui-separator[data-orientation=horizontal] {\n width: 100%;\n height: 1px;\n }\n .cfi-ui-separator[data-orientation=vertical] {\n width: 1px;\n align-self: stretch;\n min-height: 1rem;\n }\n .cfi-ui-separator-labeled {\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-sm);\n width: 100%;\n color: var(--cfi-ui-content-muted);\n font-size: var(--cfi-ui-text-xs);\n }\n .cfi-ui-separator-labeled::before,\n .cfi-ui-separator-labeled::after {\n content: "";\n flex: 1 1 auto;\n height: 1px;\n background: var(--cfi-ui-border);\n }\n .cfi-ui-separator-labeled__label {\n flex: none;\n white-space: nowrap;\n }\n .cfi-ui-progress-wrap {\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-sm);\n width: 100%;\n }\n .cfi-ui-progress {\n position: relative;\n flex: 1 1 auto;\n height: 0.5rem;\n overflow: hidden;\n border-radius: var(--cfi-ui-radius-full);\n background: var(--cfi-ui-surface-active);\n }\n .cfi-ui-progress[data-size=sm] {\n height: 0.25rem;\n }\n .cfi-ui-progress__fill {\n height: 100%;\n border-radius: var(--cfi-ui-radius-full);\n background: var(--cfi-ui-accent);\n transition: width var(--cfi-ui-transition-base);\n }\n .cfi-ui-progress[data-tone=success] .cfi-ui-progress__fill {\n background: var(--cfi-ui-success);\n }\n .cfi-ui-progress[data-tone=warning] .cfi-ui-progress__fill {\n background: var(--cfi-ui-warning);\n }\n .cfi-ui-progress[data-tone=error] .cfi-ui-progress__fill {\n background: var(--cfi-ui-error);\n }\n .cfi-ui-progress[data-indeterminate] .cfi-ui-progress__fill {\n width: 35%;\n animation: cfi-ui-progress-slide 1.2s ease-in-out infinite;\n transition: none;\n }\n @keyframes cfi-ui-progress-slide {\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(300%);\n }\n }\n .cfi-ui-progress__value {\n flex: none;\n min-width: 3ch;\n font-size: var(--cfi-ui-text-xs);\n font-variant-numeric: tabular-nums;\n color: var(--cfi-ui-content-muted);\n text-align: right;\n }\n :where(.cfi-ui-skeleton) {\n background: var(--cfi-ui-surface-active);\n border-radius: var(--cfi-ui-radius-sm);\n animation: cfi-ui-pulse 1.6s ease-in-out infinite;\n }\n .cfi-ui-skeleton[data-shape=text] {\n height: 0.875em;\n margin-block: 0.25em;\n border-radius: var(--cfi-ui-radius-sm);\n }\n .cfi-ui-skeleton[data-shape=circle] {\n border-radius: var(--cfi-ui-radius-full);\n aspect-ratio: 1;\n }\n .cfi-ui-skeleton-stack {\n display: grid;\n gap: 0;\n }\n :where(.cfi-ui-avatar) {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n overflow: hidden;\n width: 2rem;\n height: 2rem;\n border-radius: var(--cfi-ui-radius-full);\n background: var(--cfi-ui-surface-active);\n color: var(--cfi-ui-content-muted);\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-xs);\n font-weight: var(--cfi-ui-weight-semibold);\n letter-spacing: 0.02em;\n user-select: none;\n }\n .cfi-ui-avatar[data-size=xs] {\n width: 1.25rem;\n height: 1.25rem;\n font-size: 0.5625rem;\n }\n .cfi-ui-avatar[data-size=sm] {\n width: 1.5rem;\n height: 1.5rem;\n font-size: 0.625rem;\n }\n .cfi-ui-avatar[data-size=lg] {\n width: 2.5rem;\n height: 2.5rem;\n font-size: var(--cfi-ui-text-sm);\n }\n .cfi-ui-avatar__image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n }\n .cfi-ui-avatar-group {\n display: inline-flex;\n align-items: center;\n }\n .cfi-ui-avatar-group > .cfi-ui-avatar {\n box-shadow: 0 0 0 2px var(--cfi-ui-surface);\n }\n .cfi-ui-avatar-group > .cfi-ui-avatar + .cfi-ui-avatar {\n margin-left: -0.5rem;\n }\n .cfi-ui-avatar--overflow {\n background: var(--cfi-ui-surface-sunken);\n color: var(--cfi-ui-content-muted);\n font-variant-numeric: tabular-nums;\n }\n :where(.cfi-ui-scroll-area) {\n min-width: 0;\n scrollbar-width: thin;\n scrollbar-color: var(--cfi-ui-border-strong) transparent;\n overscroll-behavior: contain;\n }\n .cfi-ui-scroll-area[data-orientation=vertical] {\n overflow-y: auto;\n overflow-x: hidden;\n }\n .cfi-ui-scroll-area[data-orientation=horizontal] {\n overflow-x: auto;\n overflow-y: hidden;\n }\n .cfi-ui-scroll-area[data-orientation=both] {\n overflow: auto;\n }\n .cfi-ui-scroll-area::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n }\n .cfi-ui-scroll-area::-webkit-scrollbar-track {\n background: transparent;\n }\n .cfi-ui-scroll-area::-webkit-scrollbar-thumb {\n background: var(--cfi-ui-border-strong);\n border-radius: var(--cfi-ui-radius-full);\n border: 3px solid transparent;\n background-clip: content-box;\n }\n .cfi-ui-scroll-area::-webkit-scrollbar-thumb:hover {\n background: var(--cfi-ui-content-subtle);\n background-clip: content-box;\n }\n}\n');
1320
1468
 
1321
1469
  // src/Display.tsx
1322
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
1470
+ import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
1323
1471
  function Separator3({ orientation = "horizontal", label, className, ...rest }) {
1324
1472
  if (label) {
1325
- return /* @__PURE__ */ jsx18("div", { className: cn("cfi-ui", "cfi-ui-separator-labeled", className), ...rest, children: /* @__PURE__ */ jsx18("span", { className: "cfi-ui-separator-labeled__label", children: label }) });
1473
+ return /* @__PURE__ */ jsx19("div", { className: cn("cfi-ui", "cfi-ui-separator-labeled", className), ...rest, children: /* @__PURE__ */ jsx19("span", { className: "cfi-ui-separator-labeled__label", children: label }) });
1326
1474
  }
1327
- return /* @__PURE__ */ jsx18(
1475
+ return /* @__PURE__ */ jsx19(
1328
1476
  "div",
1329
1477
  {
1330
1478
  role: "separator",
@@ -1345,8 +1493,8 @@ function Progress({
1345
1493
  ...rest
1346
1494
  }) {
1347
1495
  const clamped = value == null ? null : Math.max(0, Math.min(100, value));
1348
- return /* @__PURE__ */ jsxs18("div", { className: cn("cfi-ui", "cfi-ui-progress-wrap", className), ...rest, children: [
1349
- /* @__PURE__ */ jsx18(
1496
+ return /* @__PURE__ */ jsxs19("div", { className: cn("cfi-ui", "cfi-ui-progress-wrap", className), ...rest, children: [
1497
+ /* @__PURE__ */ jsx19(
1350
1498
  "div",
1351
1499
  {
1352
1500
  role: "progressbar",
@@ -1358,7 +1506,7 @@ function Progress({
1358
1506
  "data-size": size,
1359
1507
  "data-indeterminate": clamped == null || void 0,
1360
1508
  className: "cfi-ui-progress",
1361
- children: /* @__PURE__ */ jsx18(
1509
+ children: /* @__PURE__ */ jsx19(
1362
1510
  "div",
1363
1511
  {
1364
1512
  className: "cfi-ui-progress__fill",
@@ -1367,7 +1515,7 @@ function Progress({
1367
1515
  )
1368
1516
  }
1369
1517
  ),
1370
- showValue && clamped != null && /* @__PURE__ */ jsxs18("span", { className: "cfi-ui-progress__value", children: [
1518
+ showValue && clamped != null && /* @__PURE__ */ jsxs19("span", { className: "cfi-ui-progress__value", children: [
1371
1519
  Math.round(clamped),
1372
1520
  "%"
1373
1521
  ] })
@@ -1375,7 +1523,7 @@ function Progress({
1375
1523
  }
1376
1524
  function Skeleton({ shape = "block", width, height, lines = 1, className, style, ...rest }) {
1377
1525
  if (shape === "text" && lines > 1) {
1378
- return /* @__PURE__ */ jsx18("div", { className: cn("cfi-ui", "cfi-ui-skeleton-stack", className), "aria-hidden": "true", ...rest, children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx18(
1526
+ return /* @__PURE__ */ jsx19("div", { className: cn("cfi-ui", "cfi-ui-skeleton-stack", className), "aria-hidden": "true", ...rest, children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx19(
1379
1527
  "div",
1380
1528
  {
1381
1529
  "data-shape": "text",
@@ -1385,7 +1533,7 @@ function Skeleton({ shape = "block", width, height, lines = 1, className, style,
1385
1533
  i
1386
1534
  )) });
1387
1535
  }
1388
- return /* @__PURE__ */ jsx18(
1536
+ return /* @__PURE__ */ jsx19(
1389
1537
  "div",
1390
1538
  {
1391
1539
  "aria-hidden": "true",
@@ -1399,18 +1547,18 @@ function Skeleton({ shape = "block", width, height, lines = 1, className, style,
1399
1547
  var Avatar = forwardRef15(function Avatar2({ name, src, size = "md", className, ...rest }, ref) {
1400
1548
  const parts = name.trim().split(/\s+/).filter(Boolean);
1401
1549
  const initials = parts.length === 0 ? "?" : parts.length === 1 ? parts[0].slice(0, 2).toUpperCase() : `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
1402
- return /* @__PURE__ */ jsxs18("span", { ref, "data-size": size, className: cn("cfi-ui", "cfi-ui-avatar", className), ...rest, children: [
1403
- src ? /* @__PURE__ */ jsx18("img", { src, alt: name, className: "cfi-ui-avatar__image" }) : /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", children: initials }),
1404
- !src && /* @__PURE__ */ jsx18("span", { className: "cfi-ui-sr-only", children: name })
1550
+ return /* @__PURE__ */ jsxs19("span", { ref, "data-size": size, className: cn("cfi-ui", "cfi-ui-avatar", className), ...rest, children: [
1551
+ src ? /* @__PURE__ */ jsx19("img", { src, alt: name, className: "cfi-ui-avatar__image" }) : /* @__PURE__ */ jsx19("span", { "aria-hidden": "true", children: initials }),
1552
+ !src && /* @__PURE__ */ jsx19("span", { className: "cfi-ui-sr-only", children: name })
1405
1553
  ] });
1406
1554
  });
1407
1555
  function AvatarGroup({ max, className, children, ...rest }) {
1408
1556
  const items = Array.isArray(children) ? children : [children];
1409
1557
  const shown = max ? items.slice(0, max) : items;
1410
1558
  const hidden = items.length - shown.length;
1411
- return /* @__PURE__ */ jsxs18("div", { className: cn("cfi-ui", "cfi-ui-avatar-group", className), ...rest, children: [
1559
+ return /* @__PURE__ */ jsxs19("div", { className: cn("cfi-ui", "cfi-ui-avatar-group", className), ...rest, children: [
1412
1560
  shown,
1413
- hidden > 0 && /* @__PURE__ */ jsxs18("span", { className: "cfi-ui-avatar cfi-ui-avatar--overflow", children: [
1561
+ hidden > 0 && /* @__PURE__ */ jsxs19("span", { className: "cfi-ui-avatar cfi-ui-avatar--overflow", children: [
1414
1562
  "+",
1415
1563
  hidden
1416
1564
  ] })
@@ -1423,7 +1571,7 @@ function ScrollArea({
1423
1571
  style,
1424
1572
  ...rest
1425
1573
  }) {
1426
- return /* @__PURE__ */ jsx18(
1574
+ return /* @__PURE__ */ jsx19(
1427
1575
  "div",
1428
1576
  {
1429
1577
  "data-orientation": orientation,
@@ -1444,20 +1592,20 @@ import { ChevronDown as ChevronDown3 } from "lucide-react";
1444
1592
  styleInject("@layer components {\n :where(.cfi-ui-accordion) {\n display: flex;\n flex-direction: column;\n min-width: 0;\n border: 1px solid var(--cfi-ui-border);\n border-radius: var(--cfi-ui-radius-lg);\n background: var(--cfi-ui-surface);\n overflow: hidden;\n }\n .cfi-ui-accordion__item + .cfi-ui-accordion__item {\n border-top: 1px solid var(--cfi-ui-border);\n }\n .cfi-ui-accordion__header {\n margin: 0;\n }\n .cfi-ui-accordion__trigger {\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-sm);\n width: 100%;\n padding: 0.625rem var(--cfi-ui-space-md);\n border: 0;\n background: none;\n color: var(--cfi-ui-content);\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-sm);\n font-weight: var(--cfi-ui-weight-medium);\n text-align: left;\n cursor: pointer;\n transition: background-color var(--cfi-ui-transition-fast);\n }\n .cfi-ui-accordion__trigger:hover:not(:disabled) {\n background: var(--cfi-ui-surface-hover);\n }\n .cfi-ui-accordion__trigger:disabled {\n color: var(--cfi-ui-content-disabled);\n cursor: not-allowed;\n }\n .cfi-ui-accordion__chevron {\n display: inline-flex;\n flex: none;\n color: var(--cfi-ui-content-muted);\n transition: transform var(--cfi-ui-transition-fast);\n }\n .cfi-ui-accordion__trigger[data-state=open] .cfi-ui-accordion__chevron {\n transform: rotate(180deg);\n }\n .cfi-ui-accordion__chevron > svg {\n width: 0.875rem;\n height: 0.875rem;\n display: block;\n }\n .cfi-ui-accordion__label {\n flex: 1 1 auto;\n min-width: 0;\n }\n .cfi-ui-accordion__meta {\n flex: none;\n font-size: var(--cfi-ui-text-xs);\n font-weight: var(--cfi-ui-weight-normal);\n font-variant-numeric: tabular-nums;\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-accordion__content {\n overflow: hidden;\n }\n .cfi-ui-accordion__content[data-state=open] {\n animation: cfi-ui-accordion-open var(--cfi-ui-transition-base);\n }\n .cfi-ui-accordion__content[data-state=closed] {\n animation: cfi-ui-accordion-close var(--cfi-ui-transition-base);\n }\n @keyframes cfi-ui-accordion-open {\n from {\n height: 0;\n }\n to {\n height: var(--radix-accordion-content-height);\n }\n }\n @keyframes cfi-ui-accordion-close {\n from {\n height: var(--radix-accordion-content-height);\n }\n to {\n height: 0;\n }\n }\n .cfi-ui-accordion__inner {\n padding: 0 var(--cfi-ui-space-md) var(--cfi-ui-space-md);\n }\n :where(.cfi-ui-toggle-group) {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-ui-space-3xs);\n padding: var(--cfi-ui-space-3xs);\n background: var(--cfi-ui-surface-sunken);\n border: 1px solid var(--cfi-ui-border);\n border-radius: var(--cfi-ui-radius-md);\n }\n :where(.cfi-ui-toggle-group__item) {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n height: 1.625rem;\n padding-inline: 0.5rem;\n border: 0;\n border-radius: var(--cfi-ui-radius-sm);\n background: transparent;\n color: var(--cfi-ui-content-muted);\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-xs);\n font-weight: var(--cfi-ui-weight-medium);\n white-space: nowrap;\n cursor: pointer;\n transition: background-color var(--cfi-ui-transition-fast), color var(--cfi-ui-transition-fast);\n }\n .cfi-ui-toggle-group[data-size=md] .cfi-ui-toggle-group__item {\n height: 1.875rem;\n padding-inline: 0.625rem;\n font-size: var(--cfi-ui-text-sm);\n }\n .cfi-ui-toggle-group__item:hover:not(:disabled) {\n color: var(--cfi-ui-content);\n }\n .cfi-ui-toggle-group__item[data-state=on] {\n background: var(--cfi-ui-surface);\n color: var(--cfi-ui-content);\n box-shadow: var(--cfi-ui-shadow-xs);\n }\n .cfi-ui-toggle-group__item:disabled {\n color: var(--cfi-ui-content-disabled);\n cursor: not-allowed;\n }\n .cfi-ui-toggle-group__icon {\n display: inline-flex;\n flex: none;\n }\n .cfi-ui-toggle-group__icon > svg {\n width: 0.875rem;\n height: 0.875rem;\n display: block;\n }\n}\n");
1445
1593
 
1446
1594
  // src/Accordion.tsx
1447
- import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
1595
+ import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
1448
1596
  var AccordionRoot = RadixAccordion.Root;
1449
1597
  var AccordionItem = forwardRef16(function AccordionItem2({ className, ...rest }, ref) {
1450
- return /* @__PURE__ */ jsx19(RadixAccordion.Item, { ref, className: cn("cfi-ui-accordion__item", className), ...rest });
1598
+ return /* @__PURE__ */ jsx20(RadixAccordion.Item, { ref, className: cn("cfi-ui-accordion__item", className), ...rest });
1451
1599
  });
1452
1600
  var AccordionTrigger = forwardRef16(function AccordionTrigger2({ meta, className, children, ...rest }, ref) {
1453
- return /* @__PURE__ */ jsx19(RadixAccordion.Header, { className: "cfi-ui-accordion__header", children: /* @__PURE__ */ jsxs19(RadixAccordion.Trigger, { ref, className: cn("cfi-ui-accordion__trigger", className), ...rest, children: [
1454
- /* @__PURE__ */ jsx19("span", { className: "cfi-ui-accordion__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx19(ChevronDown3, {}) }),
1455
- /* @__PURE__ */ jsx19("span", { className: "cfi-ui-accordion__label", children }),
1456
- meta && /* @__PURE__ */ jsx19("span", { className: "cfi-ui-accordion__meta", children: meta })
1601
+ return /* @__PURE__ */ jsx20(RadixAccordion.Header, { className: "cfi-ui-accordion__header", children: /* @__PURE__ */ jsxs20(RadixAccordion.Trigger, { ref, className: cn("cfi-ui-accordion__trigger", className), ...rest, children: [
1602
+ /* @__PURE__ */ jsx20("span", { className: "cfi-ui-accordion__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx20(ChevronDown3, {}) }),
1603
+ /* @__PURE__ */ jsx20("span", { className: "cfi-ui-accordion__label", children }),
1604
+ meta && /* @__PURE__ */ jsx20("span", { className: "cfi-ui-accordion__meta", children: meta })
1457
1605
  ] }) });
1458
1606
  });
1459
1607
  var AccordionContent = forwardRef16(function AccordionContent2({ className, children, ...rest }, ref) {
1460
- return /* @__PURE__ */ jsx19(RadixAccordion.Content, { ref, className: cn("cfi-ui-accordion__content", className), ...rest, children: /* @__PURE__ */ jsx19("div", { className: "cfi-ui-accordion__inner", children }) });
1608
+ return /* @__PURE__ */ jsx20(RadixAccordion.Content, { ref, className: cn("cfi-ui-accordion__content", className), ...rest, children: /* @__PURE__ */ jsx20("div", { className: "cfi-ui-accordion__inner", children }) });
1461
1609
  });
1462
1610
  function Accordion({
1463
1611
  sections,
@@ -1474,9 +1622,9 @@ function Accordion({
1474
1622
  onValueChange,
1475
1623
  className: cn("cfi-ui", "cfi-ui-accordion", className)
1476
1624
  };
1477
- return /* @__PURE__ */ jsx19(AccordionRoot, { ...rootProps, children: sections.map((section) => /* @__PURE__ */ jsxs19(AccordionItem, { value: section.value, disabled: section.disabled, children: [
1478
- /* @__PURE__ */ jsx19(AccordionTrigger, { meta: section.meta, children: section.label }),
1479
- /* @__PURE__ */ jsx19(AccordionContent, { children: section.content })
1625
+ return /* @__PURE__ */ jsx20(AccordionRoot, { ...rootProps, children: sections.map((section) => /* @__PURE__ */ jsxs20(AccordionItem, { value: section.value, disabled: section.disabled, children: [
1626
+ /* @__PURE__ */ jsx20(AccordionTrigger, { meta: section.meta, children: section.label }),
1627
+ /* @__PURE__ */ jsx20(AccordionContent, { children: section.content })
1480
1628
  ] }, section.value)) });
1481
1629
  }
1482
1630
  function ToggleGroup({
@@ -1488,7 +1636,7 @@ function ToggleGroup({
1488
1636
  className,
1489
1637
  ...aria
1490
1638
  }) {
1491
- return /* @__PURE__ */ jsx19(
1639
+ return /* @__PURE__ */ jsx20(
1492
1640
  RadixToggleGroup.Root,
1493
1641
  {
1494
1642
  type: "single",
@@ -1500,7 +1648,7 @@ function ToggleGroup({
1500
1648
  "data-size": size,
1501
1649
  className: cn("cfi-ui", "cfi-ui-toggle-group", className),
1502
1650
  ...aria,
1503
- children: options.map((option) => /* @__PURE__ */ jsxs19(
1651
+ children: options.map((option) => /* @__PURE__ */ jsxs20(
1504
1652
  RadixToggleGroup.Item,
1505
1653
  {
1506
1654
  value: option.value,
@@ -1509,7 +1657,7 @@ function ToggleGroup({
1509
1657
  title: option.ariaLabel,
1510
1658
  className: "cfi-ui-toggle-group__item",
1511
1659
  children: [
1512
- option.icon && /* @__PURE__ */ jsx19("span", { className: "cfi-ui-toggle-group__icon", children: option.icon }),
1660
+ option.icon && /* @__PURE__ */ jsx20("span", { className: "cfi-ui-toggle-group__icon", children: option.icon }),
1513
1661
  option.label
1514
1662
  ]
1515
1663
  },
@@ -1526,9 +1674,9 @@ import { AlertCircle, Loader2 } from "lucide-react";
1526
1674
  styleInject("@layer components {\n :where(.cfi-ui-pagestate) {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--cfi-ui-space-sm);\n padding-block: var(--cfi-ui-space-2xl, 4rem);\n text-align: center;\n color: var(--cfi-ui-content);\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-sm);\n }\n .cfi-ui-pagestate[data-size=inline] {\n padding-block: var(--cfi-ui-space-md);\n gap: var(--cfi-ui-space-xs);\n }\n .cfi-ui-pagestate:has(> .cfi-ui-pagestate__spinner) {\n flex-direction: row;\n }\n .cfi-ui-pagestate__spinner {\n width: 1rem;\n height: 1rem;\n flex: none;\n color: var(--cfi-ui-content-muted);\n animation: cfi-ui-pagestate-spin 1s linear infinite;\n }\n @media (prefers-reduced-motion: reduce) {\n .cfi-ui-pagestate__spinner {\n animation-duration: 2.4s;\n }\n }\n .cfi-ui-pagestate__icon {\n display: inline-flex;\n color: var(--cfi-ui-content-subtle);\n }\n .cfi-ui-pagestate__icon > svg {\n width: 1.5rem;\n height: 1.5rem;\n }\n .cfi-ui-pagestate__icon[data-tone=error] {\n width: 1.5rem;\n height: 1.5rem;\n color: var(--cfi-ui-error-strong);\n }\n .cfi-ui-pagestate__title {\n margin: 0;\n font-weight: var(--cfi-ui-weight-medium);\n color: var(--cfi-ui-content);\n }\n .cfi-ui-pagestate__muted {\n margin: 0;\n max-width: 34rem;\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-pagestate__title + .cfi-ui-pagestate__muted {\n margin-top: var(--cfi-ui-space-3xs);\n }\n .cfi-ui-pagestate__action {\n margin-top: var(--cfi-ui-space-xs);\n }\n .cfi-ui-pagestate__retry {\n height: var(--cfi-ui-control-height-sm);\n padding-inline: var(--cfi-ui-space-sm);\n background: var(--cfi-ui-surface);\n color: var(--cfi-ui-content);\n border: 1px solid var(--cfi-ui-border-strong);\n border-radius: var(--cfi-ui-radius-md);\n font-family: inherit;\n font-size: var(--cfi-ui-text-sm);\n line-height: normal;\n cursor: pointer;\n }\n .cfi-ui-pagestate__retry:hover {\n background: var(--cfi-ui-surface-hover);\n }\n .cfi-ui-pagestate__retry:focus-visible {\n outline: var(--cfi-ui-focus-width) solid var(--cfi-ui-focus-color);\n outline-offset: var(--cfi-ui-focus-offset);\n }\n}\n@keyframes cfi-ui-pagestate-spin {\n to {\n transform: rotate(360deg);\n }\n}\n");
1527
1675
 
1528
1676
  // src/PageState.tsx
1529
- import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
1677
+ import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
1530
1678
  function LoadingState({ label = "Loading\u2026", size = "block", className }) {
1531
- return /* @__PURE__ */ jsxs20(
1679
+ return /* @__PURE__ */ jsxs21(
1532
1680
  "div",
1533
1681
  {
1534
1682
  className: cn("cfi-ui", "cfi-ui-pagestate", className),
@@ -1536,8 +1684,8 @@ function LoadingState({ label = "Loading\u2026", size = "block", className }) {
1536
1684
  role: "status",
1537
1685
  "aria-live": "polite",
1538
1686
  children: [
1539
- /* @__PURE__ */ jsx20(Loader2, { className: "cfi-ui-pagestate__spinner", "aria-hidden": "true" }),
1540
- /* @__PURE__ */ jsx20("span", { className: "cfi-ui-pagestate__muted", children: label })
1687
+ /* @__PURE__ */ jsx21(Loader2, { className: "cfi-ui-pagestate__spinner", "aria-hidden": "true" }),
1688
+ /* @__PURE__ */ jsx21("span", { className: "cfi-ui-pagestate__muted", children: label })
1541
1689
  ]
1542
1690
  }
1543
1691
  );
@@ -1551,13 +1699,13 @@ function ErrorState({
1551
1699
  className
1552
1700
  }) {
1553
1701
  const message = error instanceof Error ? error.message : error == null ? "" : String(error);
1554
- return /* @__PURE__ */ jsxs20("div", { className: cn("cfi-ui", "cfi-ui-pagestate", className), "data-size": size, role: "alert", children: [
1555
- /* @__PURE__ */ jsx20(AlertCircle, { className: "cfi-ui-pagestate__icon", "data-tone": "error", "aria-hidden": "true" }),
1556
- /* @__PURE__ */ jsxs20("div", { children: [
1557
- /* @__PURE__ */ jsx20("p", { className: "cfi-ui-pagestate__title", children: title }),
1558
- message && /* @__PURE__ */ jsx20("p", { className: "cfi-ui-pagestate__muted", children: message })
1702
+ return /* @__PURE__ */ jsxs21("div", { className: cn("cfi-ui", "cfi-ui-pagestate", className), "data-size": size, role: "alert", children: [
1703
+ /* @__PURE__ */ jsx21(AlertCircle, { className: "cfi-ui-pagestate__icon", "data-tone": "error", "aria-hidden": "true" }),
1704
+ /* @__PURE__ */ jsxs21("div", { children: [
1705
+ /* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__title", children: title }),
1706
+ message && /* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__muted", children: message })
1559
1707
  ] }),
1560
- onRetry && /* @__PURE__ */ jsx20("button", { type: "button", className: "cfi-ui-pagestate__retry", onClick: onRetry, children: retryLabel })
1708
+ onRetry && /* @__PURE__ */ jsx21("button", { type: "button", className: "cfi-ui-pagestate__retry", onClick: onRetry, children: retryLabel })
1561
1709
  ] });
1562
1710
  }
1563
1711
  function EmptyState({
@@ -1568,17 +1716,17 @@ function EmptyState({
1568
1716
  size = "block",
1569
1717
  className
1570
1718
  }) {
1571
- return /* @__PURE__ */ jsxs20("div", { className: cn("cfi-ui", "cfi-ui-pagestate", className), "data-size": size, children: [
1572
- icon && /* @__PURE__ */ jsx20("span", { className: "cfi-ui-pagestate__icon", children: icon }),
1573
- /* @__PURE__ */ jsxs20("div", { children: [
1574
- /* @__PURE__ */ jsx20("p", { className: "cfi-ui-pagestate__title", children: title }),
1575
- description && /* @__PURE__ */ jsx20("p", { className: "cfi-ui-pagestate__muted", children: description })
1719
+ return /* @__PURE__ */ jsxs21("div", { className: cn("cfi-ui", "cfi-ui-pagestate", className), "data-size": size, children: [
1720
+ icon && /* @__PURE__ */ jsx21("span", { className: "cfi-ui-pagestate__icon", children: icon }),
1721
+ /* @__PURE__ */ jsxs21("div", { children: [
1722
+ /* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__title", children: title }),
1723
+ description && /* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__muted", children: description })
1576
1724
  ] }),
1577
- action && /* @__PURE__ */ jsx20("div", { className: "cfi-ui-pagestate__action", children: action })
1725
+ action && /* @__PURE__ */ jsx21("div", { className: "cfi-ui-pagestate__action", children: action })
1578
1726
  ] });
1579
1727
  }
1580
1728
  function ComingSoon({ title, detail, className }) {
1581
- return /* @__PURE__ */ jsx20(
1729
+ return /* @__PURE__ */ jsx21(
1582
1730
  EmptyState,
1583
1731
  {
1584
1732
  title,
@@ -1589,9 +1737,9 @@ function ComingSoon({ title, detail, className }) {
1589
1737
  }
1590
1738
 
1591
1739
  // src/useSortState.ts
1592
- import { useCallback as useCallback2, useMemo as useMemo3, useState as useState3 } from "react";
1740
+ import { useCallback as useCallback2, useMemo as useMemo4, useState as useState4 } from "react";
1593
1741
  function useSortState(initialKey, initialDirection = "asc") {
1594
- const [sort, setSort] = useState3({ key: initialKey, direction: initialDirection });
1742
+ const [sort, setSort] = useState4({ key: initialKey, direction: initialDirection });
1595
1743
  const toggle = useCallback2((key) => {
1596
1744
  setSort(
1597
1745
  (current) => current.key === key ? { key, direction: current.direction === "asc" ? "desc" : "asc" } : { key, direction: "asc" }
@@ -1621,23 +1769,23 @@ function useSortState(initialKey, initialDirection = "asc") {
1621
1769
  },
1622
1770
  [sort]
1623
1771
  );
1624
- return useMemo3(
1772
+ return useMemo4(
1625
1773
  () => ({ sort, toggle, setSort, sortProps, sortBy }),
1626
1774
  [sort, toggle, sortProps, sortBy]
1627
1775
  );
1628
1776
  }
1629
1777
 
1630
1778
  // src/SearchInput.tsx
1631
- import { forwardRef as forwardRef17, useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
1779
+ import { forwardRef as forwardRef17, useEffect as useEffect3, useRef as useRef3, useState as useState5 } from "react";
1632
1780
  import { Search as Search2, X as X4 } from "lucide-react";
1633
1781
 
1634
1782
  // src/SearchInput.css
1635
1783
  styleInject("@layer components {\n .cfi-ui-search__clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background: none;\n border: none;\n color: var(--cfi-ui-content-muted);\n cursor: pointer;\n border-radius: var(--cfi-ui-radius-sm);\n }\n .cfi-ui-search__clear > svg {\n width: 0.875rem;\n height: 0.875rem;\n }\n .cfi-ui-search__clear:hover {\n color: var(--cfi-ui-content);\n }\n .cfi-ui-search__clear:focus-visible {\n outline: var(--cfi-ui-focus-width) solid var(--cfi-ui-focus-color);\n outline-offset: 1px;\n }\n}\n");
1636
1784
 
1637
1785
  // src/SearchInput.tsx
1638
- import { jsx as jsx21 } from "react/jsx-runtime";
1786
+ import { jsx as jsx22 } from "react/jsx-runtime";
1639
1787
  var SearchInput = forwardRef17(function SearchInput2({ value, onChange, delay = 250, placeholder = "Search\u2026", clearLabel = "Clear search", ...rest }, ref) {
1640
- const [local, setLocal] = useState4(value);
1788
+ const [local, setLocal] = useState5(value);
1641
1789
  const timer = useRef3(void 0);
1642
1790
  const latest = useRef3(onChange);
1643
1791
  latest.current = onChange;
@@ -1654,7 +1802,7 @@ var SearchInput = forwardRef17(function SearchInput2({ value, onChange, delay =
1654
1802
  setLocal("");
1655
1803
  latest.current("");
1656
1804
  };
1657
- return /* @__PURE__ */ jsx21(
1805
+ return /* @__PURE__ */ jsx22(
1658
1806
  Input,
1659
1807
  {
1660
1808
  ...rest,
@@ -1663,8 +1811,8 @@ var SearchInput = forwardRef17(function SearchInput2({ value, onChange, delay =
1663
1811
  value: local,
1664
1812
  placeholder,
1665
1813
  onChange: (e) => push(e.target.value),
1666
- prefix: /* @__PURE__ */ jsx21(Search2, { "aria-hidden": "true" }),
1667
- suffix: local ? /* @__PURE__ */ jsx21("button", { type: "button", className: "cfi-ui-search__clear", onClick: clear, "aria-label": clearLabel, children: /* @__PURE__ */ jsx21(X4, { "aria-hidden": "true" }) }) : void 0
1814
+ prefix: /* @__PURE__ */ jsx22(Search2, { "aria-hidden": "true" }),
1815
+ suffix: local ? /* @__PURE__ */ jsx22("button", { type: "button", className: "cfi-ui-search__clear", onClick: clear, "aria-label": clearLabel, children: /* @__PURE__ */ jsx22(X4, { "aria-hidden": "true" }) }) : void 0
1668
1816
  }
1669
1817
  );
1670
1818
  });
@@ -1676,7 +1824,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
1676
1824
  styleInject("@layer components {\n :where(.cfi-ui-pagination) {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--cfi-ui-space-md);\n padding-block: var(--cfi-ui-space-sm);\n font-family: var(--cfi-ui-font);\n font-size: var(--cfi-ui-text-sm);\n color: var(--cfi-ui-content-muted);\n }\n .cfi-ui-pagination__controls {\n display: flex;\n align-items: center;\n gap: var(--cfi-ui-space-xs);\n margin-left: auto;\n }\n .cfi-ui-pagination__page {\n font-variant-numeric: tabular-nums;\n color: var(--cfi-ui-content);\n }\n .cfi-ui-pagination__range {\n font-variant-numeric: tabular-nums;\n }\n .cfi-ui-pagination__btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--cfi-ui-control-height-sm);\n height: var(--cfi-ui-control-height-sm);\n padding: 0;\n background: var(--cfi-ui-surface);\n color: var(--cfi-ui-content);\n border: 1px solid var(--cfi-ui-border-strong);\n border-radius: var(--cfi-ui-radius-md);\n cursor: pointer;\n }\n .cfi-ui-pagination__btn > svg {\n width: 1rem;\n height: 1rem;\n }\n .cfi-ui-pagination__btn:hover:not(:disabled) {\n background: var(--cfi-ui-surface-hover);\n }\n .cfi-ui-pagination__btn:disabled {\n color: var(--cfi-ui-content-disabled);\n cursor: default;\n }\n .cfi-ui-pagination__btn:focus-visible {\n outline: var(--cfi-ui-focus-width) solid var(--cfi-ui-focus-color);\n outline-offset: var(--cfi-ui-focus-offset);\n }\n}\n");
1677
1825
 
1678
1826
  // src/Pagination.tsx
1679
- import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
1827
+ import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
1680
1828
  function Pagination({
1681
1829
  page,
1682
1830
  pageSize,
@@ -1692,12 +1840,12 @@ function Pagination({
1692
1840
  const from = (current - 1) * pageSize + 1;
1693
1841
  const to = Math.min(current * pageSize, totalItems);
1694
1842
  const range = labels?.range?.(from, to, totalItems) ?? `${from}\u2013${to} of ${totalItems.toLocaleString()}`;
1695
- return /* @__PURE__ */ jsxs21("nav", { className: cn("cfi-ui", "cfi-ui-pagination", className), "aria-label": "Pagination", children: [
1843
+ return /* @__PURE__ */ jsxs22("nav", { className: cn("cfi-ui", "cfi-ui-pagination", className), "aria-label": "Pagination", children: [
1696
1844
  showRange && // aria-live so a screen-reader user hears where they landed; paging
1697
1845
  // otherwise moves focus nowhere and announces nothing.
1698
- /* @__PURE__ */ jsx22("span", { className: "cfi-ui-pagination__range", "aria-live": "polite", children: range }),
1699
- /* @__PURE__ */ jsxs21("div", { className: "cfi-ui-pagination__controls", children: [
1700
- /* @__PURE__ */ jsx22(
1846
+ /* @__PURE__ */ jsx23("span", { className: "cfi-ui-pagination__range", "aria-live": "polite", children: range }),
1847
+ /* @__PURE__ */ jsxs22("div", { className: "cfi-ui-pagination__controls", children: [
1848
+ /* @__PURE__ */ jsx23(
1701
1849
  "button",
1702
1850
  {
1703
1851
  type: "button",
@@ -1705,15 +1853,15 @@ function Pagination({
1705
1853
  onClick: () => onPageChange(current - 1),
1706
1854
  disabled: current <= 1,
1707
1855
  "aria-label": labels?.previous ?? "Previous page",
1708
- children: /* @__PURE__ */ jsx22(ChevronLeft, { "aria-hidden": "true" })
1856
+ children: /* @__PURE__ */ jsx23(ChevronLeft, { "aria-hidden": "true" })
1709
1857
  }
1710
1858
  ),
1711
- /* @__PURE__ */ jsxs21("span", { className: "cfi-ui-pagination__page", children: [
1859
+ /* @__PURE__ */ jsxs22("span", { className: "cfi-ui-pagination__page", children: [
1712
1860
  current,
1713
1861
  " / ",
1714
1862
  pageCount
1715
1863
  ] }),
1716
- /* @__PURE__ */ jsx22(
1864
+ /* @__PURE__ */ jsx23(
1717
1865
  "button",
1718
1866
  {
1719
1867
  type: "button",
@@ -1721,7 +1869,7 @@ function Pagination({
1721
1869
  onClick: () => onPageChange(current + 1),
1722
1870
  disabled: current >= pageCount,
1723
1871
  "aria-label": labels?.next ?? "Next page",
1724
- children: /* @__PURE__ */ jsx22(ChevronRight, { "aria-hidden": "true" })
1872
+ children: /* @__PURE__ */ jsx23(ChevronRight, { "aria-hidden": "true" })
1725
1873
  }
1726
1874
  )
1727
1875
  ] })
@@ -1789,6 +1937,7 @@ export {
1789
1937
  ComingSoon,
1790
1938
  ConfirmDialog,
1791
1939
  CountBadge,
1940
+ CreatableSelect,
1792
1941
  Dialog,
1793
1942
  DialogBody,
1794
1943
  DialogClose,
package/package.json CHANGED
@@ -1,56 +1,55 @@
1
- {
2
- "name": "@campfire-interactive/ui",
3
- "version": "0.1.0",
4
- "_notReady": "NOT READY FOR APP ADOPTIONsee docs/plans/2026-09-09-ui-package-and-showcase.md. private:true blocks npm publish until the components are vetted.",
5
- "description": "UNVETTED, DO NOT ADOPT YET — Shared UI primitives for the Campfire Suite — Radix behaviour, plain CSS styled entirely from the design tokens, no Tailwind required",
6
- "type": "module",
7
- "main": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
13
- }
14
- },
15
- "files": [
16
- "dist"
17
- ],
18
- "scripts": {
19
- "build": "tsup",
20
- "prepublishOnly": "npm run build",
21
- "dev": "tsup --watch",
22
- "test": "vitest run",
23
- "typecheck": "tsc --noEmit"
24
- },
25
- "peerDependencies": {
26
- "react": "^18.0.0 || ^19.0.0",
27
- "react-dom": "^18.0.0 || ^19.0.0"
28
- },
29
- "dependencies": {
30
- "@campfire-interactive/design-tokens": "*",
31
- "@radix-ui/react-accordion": "^1.2.12",
32
- "@radix-ui/react-checkbox": "^1.3.3",
33
- "@radix-ui/react-dialog": "^1.1.15",
34
- "@radix-ui/react-dropdown-menu": "^2.1.16",
35
- "@radix-ui/react-popover": "^1.1.15",
36
- "@radix-ui/react-select": "^2.2.6",
37
- "@radix-ui/react-slider": "^1.3.6",
38
- "@radix-ui/react-switch": "^1.2.6",
39
- "@radix-ui/react-tabs": "^1.1.13",
40
- "@radix-ui/react-toggle-group": "^1.1.11",
41
- "@radix-ui/react-tooltip": "^1.2.8",
42
- "lucide-react": "^0.487.0"
43
- },
44
- "devDependencies": {
45
- "@types/react": "^19.0.0",
46
- "@types/react-dom": "^19.0.0",
47
- "react": "^19.0.0",
48
- "react-dom": "^19.0.0",
49
- "tsup": "^8.0.0",
50
- "typescript": "^5.3.3"
51
- },
52
- "publishConfig": {
53
- "registry": "https://registry.npmjs.org",
54
- "access": "public"
55
- }
56
- }
1
+ {
2
+ "name": "@campfire-interactive/ui",
3
+ "version": "0.3.0",
4
+ "description": "Shared UI primitives for the Campfire Suite Radix behavior, plain CSS styled entirely from the design tokens, no Tailwind required",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "prepublishOnly": "npm run build",
20
+ "dev": "tsup --watch",
21
+ "test": "vitest run",
22
+ "typecheck": "tsc --noEmit"
23
+ },
24
+ "peerDependencies": {
25
+ "react": "^18.0.0 || ^19.0.0",
26
+ "react-dom": "^18.0.0 || ^19.0.0"
27
+ },
28
+ "dependencies": {
29
+ "@campfire-interactive/design-tokens": "*",
30
+ "@radix-ui/react-accordion": "^1.2.12",
31
+ "@radix-ui/react-checkbox": "^1.3.3",
32
+ "@radix-ui/react-dialog": "^1.1.15",
33
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
34
+ "@radix-ui/react-popover": "^1.1.15",
35
+ "@radix-ui/react-select": "^2.2.6",
36
+ "@radix-ui/react-slider": "^1.3.6",
37
+ "@radix-ui/react-switch": "^1.2.6",
38
+ "@radix-ui/react-tabs": "^1.1.13",
39
+ "@radix-ui/react-toggle-group": "^1.1.11",
40
+ "@radix-ui/react-tooltip": "^1.2.8",
41
+ "lucide-react": "^0.487.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/react": "^19.0.0",
45
+ "@types/react-dom": "^19.0.0",
46
+ "react": "^19.0.0",
47
+ "react-dom": "^19.0.0",
48
+ "tsup": "^8.0.0",
49
+ "typescript": "^5.3.3"
50
+ },
51
+ "publishConfig": {
52
+ "registry": "https://registry.npmjs.org",
53
+ "access": "public"
54
+ }
55
+ }