@campfire-interactive/ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +66 -1
- package/dist/index.js +300 -152
- package/package.json +2 -3
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;
|
|
@@ -1221,4 +1286,4 @@ declare function formatNumber(value: number | null | undefined, decimals?: numbe
|
|
|
1221
1286
|
*/
|
|
1222
1287
|
declare function formatPercent(value: number | null | undefined, decimals?: number): string;
|
|
1223
1288
|
|
|
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 };
|
|
1289
|
+
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
|
|
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] =
|
|
758
|
-
const [search, setSearch] =
|
|
759
|
-
const [highlighted, setHighlighted] =
|
|
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 =
|
|
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__ */
|
|
818
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
842
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1001
|
+
children: /* @__PURE__ */ jsx12(X2, { "aria-hidden": "true" })
|
|
855
1002
|
}
|
|
856
1003
|
),
|
|
857
|
-
name && /* @__PURE__ */
|
|
1004
|
+
name && /* @__PURE__ */ jsx12("input", { type: "hidden", name, value: value ?? "" })
|
|
858
1005
|
]
|
|
859
1006
|
}
|
|
860
1007
|
) }),
|
|
861
|
-
/* @__PURE__ */
|
|
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__ */
|
|
874
|
-
/* @__PURE__ */
|
|
875
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
916
|
-
/* @__PURE__ */
|
|
917
|
-
/* @__PURE__ */
|
|
918
|
-
option.hint && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
959
|
-
return /* @__PURE__ */
|
|
960
|
-
/* @__PURE__ */
|
|
961
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
|
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] =
|
|
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 =
|
|
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__ */
|
|
1178
|
+
return /* @__PURE__ */ jsxs14(ToastContext.Provider, { value: api, children: [
|
|
1032
1179
|
children,
|
|
1033
|
-
/* @__PURE__ */
|
|
1180
|
+
/* @__PURE__ */ jsx14(ToastViewport, { items, onDismiss: dismiss, position })
|
|
1034
1181
|
] });
|
|
1035
1182
|
}
|
|
1036
1183
|
var TONE_ICON = {
|
|
1037
|
-
neutral: /* @__PURE__ */
|
|
1038
|
-
info: /* @__PURE__ */
|
|
1039
|
-
success: /* @__PURE__ */
|
|
1040
|
-
warning: /* @__PURE__ */
|
|
1041
|
-
error: /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1058
|
-
/* @__PURE__ */
|
|
1059
|
-
/* @__PURE__ */
|
|
1060
|
-
/* @__PURE__ */
|
|
1061
|
-
item.description && /* @__PURE__ */
|
|
1062
|
-
item.action && /* @__PURE__ */
|
|
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__ */
|
|
1222
|
+
/* @__PURE__ */ jsx14(
|
|
1076
1223
|
IconButton,
|
|
1077
1224
|
{
|
|
1078
1225
|
variant: "ghost",
|
|
1079
1226
|
size: "sm",
|
|
1080
|
-
icon: /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1114
|
-
actions ? /* @__PURE__ */
|
|
1115
|
-
actions && /* @__PURE__ */
|
|
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__ */
|
|
1266
|
+
return /* @__PURE__ */ jsx15(Tag, { className: cn("cfi-ui-card__title", className), ...rest });
|
|
1120
1267
|
}
|
|
1121
1268
|
function CardDescription({ className, ...rest }) {
|
|
1122
|
-
return /* @__PURE__ */
|
|
1269
|
+
return /* @__PURE__ */ jsx15("p", { className: cn("cfi-ui-card__description", className), ...rest });
|
|
1123
1270
|
}
|
|
1124
1271
|
function CardBody({ className, ...rest }) {
|
|
1125
|
-
return /* @__PURE__ */
|
|
1272
|
+
return /* @__PURE__ */ jsx15("div", { className: cn("cfi-ui-card__body", className), ...rest });
|
|
1126
1273
|
}
|
|
1127
1274
|
function CardFooter({ className, ...rest }) {
|
|
1128
|
-
return /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
@@ -1166,9 +1313,9 @@ import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
|
|
|
1166
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__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
|
|
1316
|
+
import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1170
1317
|
var Table = forwardRef13(function Table2({ density = "comfortable", stickyHeader = false, className, ...rest }, ref) {
|
|
1171
|
-
return /* @__PURE__ */
|
|
1318
|
+
return /* @__PURE__ */ jsx17(
|
|
1172
1319
|
"table",
|
|
1173
1320
|
{
|
|
1174
1321
|
ref,
|
|
@@ -1180,20 +1327,20 @@ var Table = forwardRef13(function Table2({ density = "comfortable", stickyHeader
|
|
|
1180
1327
|
);
|
|
1181
1328
|
});
|
|
1182
1329
|
function TableScroller({ className, ...rest }) {
|
|
1183
|
-
return /* @__PURE__ */
|
|
1330
|
+
return /* @__PURE__ */ jsx17("div", { className: cn("cfi-ui", "cfi-ui-table-scroller", className), ...rest });
|
|
1184
1331
|
}
|
|
1185
1332
|
function TableHeader({ className, ...rest }) {
|
|
1186
|
-
return /* @__PURE__ */
|
|
1333
|
+
return /* @__PURE__ */ jsx17("thead", { className: cn("cfi-ui-table__head", className), ...rest });
|
|
1187
1334
|
}
|
|
1188
1335
|
function TableBody({ className, ...rest }) {
|
|
1189
|
-
return /* @__PURE__ */
|
|
1336
|
+
return /* @__PURE__ */ jsx17("tbody", { className: cn("cfi-ui-table__body", className), ...rest });
|
|
1190
1337
|
}
|
|
1191
1338
|
function TableFooter({ className, ...rest }) {
|
|
1192
|
-
return /* @__PURE__ */
|
|
1339
|
+
return /* @__PURE__ */ jsx17("tfoot", { className: cn("cfi-ui-table__foot", className), ...rest });
|
|
1193
1340
|
}
|
|
1194
1341
|
var TableFoot = TableFooter;
|
|
1195
1342
|
function TableRow({ selected, interactive, className, ...rest }) {
|
|
1196
|
-
return /* @__PURE__ */
|
|
1343
|
+
return /* @__PURE__ */ jsx17(
|
|
1197
1344
|
"tr",
|
|
1198
1345
|
{
|
|
1199
1346
|
"data-selected": selected || void 0,
|
|
@@ -1216,7 +1363,7 @@ function TableHead({
|
|
|
1216
1363
|
...rest
|
|
1217
1364
|
}) {
|
|
1218
1365
|
const ariaSort = sortable ? sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none" : void 0;
|
|
1219
|
-
return /* @__PURE__ */
|
|
1366
|
+
return /* @__PURE__ */ jsx17(
|
|
1220
1367
|
"th",
|
|
1221
1368
|
{
|
|
1222
1369
|
scope: "col",
|
|
@@ -1225,15 +1372,15 @@ function TableHead({
|
|
|
1225
1372
|
style: { width, ...style },
|
|
1226
1373
|
className: cn("cfi-ui-table__th", className),
|
|
1227
1374
|
...rest,
|
|
1228
|
-
children: sortable ? /* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */
|
|
1230
|
-
/* @__PURE__ */
|
|
1375
|
+
children: sortable ? /* @__PURE__ */ jsxs17("button", { type: "button", className: "cfi-ui-table__sort", onClick: onSort, children: [
|
|
1376
|
+
/* @__PURE__ */ jsx17("span", { children }),
|
|
1377
|
+
/* @__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
1378
|
] }) : children
|
|
1232
1379
|
}
|
|
1233
1380
|
);
|
|
1234
1381
|
}
|
|
1235
1382
|
function TableCell({ numeric, truncate, className, ...rest }) {
|
|
1236
|
-
return /* @__PURE__ */
|
|
1383
|
+
return /* @__PURE__ */ jsx17(
|
|
1237
1384
|
"td",
|
|
1238
1385
|
{
|
|
1239
1386
|
"data-numeric": numeric || void 0,
|
|
@@ -1244,10 +1391,10 @@ function TableCell({ numeric, truncate, className, ...rest }) {
|
|
|
1244
1391
|
);
|
|
1245
1392
|
}
|
|
1246
1393
|
function TableEmpty({ colSpan, children }) {
|
|
1247
|
-
return /* @__PURE__ */
|
|
1394
|
+
return /* @__PURE__ */ jsx17("tr", { className: "cfi-ui-table__row", children: /* @__PURE__ */ jsx17("td", { colSpan, className: "cfi-ui-table__empty", children }) });
|
|
1248
1395
|
}
|
|
1249
1396
|
function TableCaption({ className, ...rest }) {
|
|
1250
|
-
return /* @__PURE__ */
|
|
1397
|
+
return /* @__PURE__ */ jsx17("caption", { className: cn("cfi-ui-table__caption", className), ...rest });
|
|
1251
1398
|
}
|
|
1252
1399
|
|
|
1253
1400
|
// src/Tabs.tsx
|
|
@@ -1258,12 +1405,12 @@ import * as RadixTabs from "@radix-ui/react-tabs";
|
|
|
1258
1405
|
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
1406
|
|
|
1260
1407
|
// src/Tabs.tsx
|
|
1261
|
-
import { jsx as
|
|
1408
|
+
import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1262
1409
|
var Tabs = RadixTabs.Root;
|
|
1263
1410
|
var TabsRoot = RadixTabs.Root;
|
|
1264
1411
|
var TabsList = forwardRef14(
|
|
1265
1412
|
function TabsList2({ variant = "pill", className, ...rest }, ref) {
|
|
1266
|
-
return /* @__PURE__ */
|
|
1413
|
+
return /* @__PURE__ */ jsx18(
|
|
1267
1414
|
RadixTabs.List,
|
|
1268
1415
|
{
|
|
1269
1416
|
ref,
|
|
@@ -1276,18 +1423,18 @@ var TabsList = forwardRef14(
|
|
|
1276
1423
|
);
|
|
1277
1424
|
var TabsTrigger = forwardRef14(
|
|
1278
1425
|
function TabsTrigger2({ icon, count, className, children, ...rest }, ref) {
|
|
1279
|
-
return /* @__PURE__ */
|
|
1280
|
-
icon && /* @__PURE__ */
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
count !== void 0 && /* @__PURE__ */
|
|
1426
|
+
return /* @__PURE__ */ jsxs18(RadixTabs.Trigger, { ref, className: cn("cfi-ui-tabs__trigger", className), ...rest, children: [
|
|
1427
|
+
icon && /* @__PURE__ */ jsx18("span", { className: "cfi-ui-tabs__icon", children: icon }),
|
|
1428
|
+
/* @__PURE__ */ jsx18("span", { children }),
|
|
1429
|
+
count !== void 0 && /* @__PURE__ */ jsx18(CountBadge, { count, size: "sm" })
|
|
1283
1430
|
] });
|
|
1284
1431
|
}
|
|
1285
1432
|
);
|
|
1286
1433
|
var TabsContent = forwardRef14(function TabsContent2({ className, ...rest }, ref) {
|
|
1287
|
-
return /* @__PURE__ */
|
|
1434
|
+
return /* @__PURE__ */ jsx18(RadixTabs.Content, { ref, className: cn("cfi-ui-tabs__content", className), ...rest });
|
|
1288
1435
|
});
|
|
1289
1436
|
function TabSet({ tabs, value, onValueChange, defaultValue, variant, className }) {
|
|
1290
|
-
return /* @__PURE__ */
|
|
1437
|
+
return /* @__PURE__ */ jsxs18(
|
|
1291
1438
|
Tabs,
|
|
1292
1439
|
{
|
|
1293
1440
|
value,
|
|
@@ -1295,7 +1442,7 @@ function TabSet({ tabs, value, onValueChange, defaultValue, variant, className }
|
|
|
1295
1442
|
defaultValue: defaultValue ?? tabs[0]?.value,
|
|
1296
1443
|
className: cn("cfi-ui", "cfi-ui-tabs", className),
|
|
1297
1444
|
children: [
|
|
1298
|
-
/* @__PURE__ */
|
|
1445
|
+
/* @__PURE__ */ jsx18(TabsList, { variant, children: tabs.map((tab) => /* @__PURE__ */ jsx18(
|
|
1299
1446
|
TabsTrigger,
|
|
1300
1447
|
{
|
|
1301
1448
|
value: tab.value,
|
|
@@ -1306,7 +1453,7 @@ function TabSet({ tabs, value, onValueChange, defaultValue, variant, className }
|
|
|
1306
1453
|
},
|
|
1307
1454
|
tab.value
|
|
1308
1455
|
)) }),
|
|
1309
|
-
tabs.map((tab) => /* @__PURE__ */
|
|
1456
|
+
tabs.map((tab) => /* @__PURE__ */ jsx18(TabsContent, { value: tab.value, children: tab.content }, tab.value))
|
|
1310
1457
|
]
|
|
1311
1458
|
}
|
|
1312
1459
|
);
|
|
@@ -1319,12 +1466,12 @@ import { forwardRef as forwardRef15 } from "react";
|
|
|
1319
1466
|
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
1467
|
|
|
1321
1468
|
// src/Display.tsx
|
|
1322
|
-
import { jsx as
|
|
1469
|
+
import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1323
1470
|
function Separator3({ orientation = "horizontal", label, className, ...rest }) {
|
|
1324
1471
|
if (label) {
|
|
1325
|
-
return /* @__PURE__ */
|
|
1472
|
+
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
1473
|
}
|
|
1327
|
-
return /* @__PURE__ */
|
|
1474
|
+
return /* @__PURE__ */ jsx19(
|
|
1328
1475
|
"div",
|
|
1329
1476
|
{
|
|
1330
1477
|
role: "separator",
|
|
@@ -1345,8 +1492,8 @@ function Progress({
|
|
|
1345
1492
|
...rest
|
|
1346
1493
|
}) {
|
|
1347
1494
|
const clamped = value == null ? null : Math.max(0, Math.min(100, value));
|
|
1348
|
-
return /* @__PURE__ */
|
|
1349
|
-
/* @__PURE__ */
|
|
1495
|
+
return /* @__PURE__ */ jsxs19("div", { className: cn("cfi-ui", "cfi-ui-progress-wrap", className), ...rest, children: [
|
|
1496
|
+
/* @__PURE__ */ jsx19(
|
|
1350
1497
|
"div",
|
|
1351
1498
|
{
|
|
1352
1499
|
role: "progressbar",
|
|
@@ -1358,7 +1505,7 @@ function Progress({
|
|
|
1358
1505
|
"data-size": size,
|
|
1359
1506
|
"data-indeterminate": clamped == null || void 0,
|
|
1360
1507
|
className: "cfi-ui-progress",
|
|
1361
|
-
children: /* @__PURE__ */
|
|
1508
|
+
children: /* @__PURE__ */ jsx19(
|
|
1362
1509
|
"div",
|
|
1363
1510
|
{
|
|
1364
1511
|
className: "cfi-ui-progress__fill",
|
|
@@ -1367,7 +1514,7 @@ function Progress({
|
|
|
1367
1514
|
)
|
|
1368
1515
|
}
|
|
1369
1516
|
),
|
|
1370
|
-
showValue && clamped != null && /* @__PURE__ */
|
|
1517
|
+
showValue && clamped != null && /* @__PURE__ */ jsxs19("span", { className: "cfi-ui-progress__value", children: [
|
|
1371
1518
|
Math.round(clamped),
|
|
1372
1519
|
"%"
|
|
1373
1520
|
] })
|
|
@@ -1375,7 +1522,7 @@ function Progress({
|
|
|
1375
1522
|
}
|
|
1376
1523
|
function Skeleton({ shape = "block", width, height, lines = 1, className, style, ...rest }) {
|
|
1377
1524
|
if (shape === "text" && lines > 1) {
|
|
1378
|
-
return /* @__PURE__ */
|
|
1525
|
+
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
1526
|
"div",
|
|
1380
1527
|
{
|
|
1381
1528
|
"data-shape": "text",
|
|
@@ -1385,7 +1532,7 @@ function Skeleton({ shape = "block", width, height, lines = 1, className, style,
|
|
|
1385
1532
|
i
|
|
1386
1533
|
)) });
|
|
1387
1534
|
}
|
|
1388
|
-
return /* @__PURE__ */
|
|
1535
|
+
return /* @__PURE__ */ jsx19(
|
|
1389
1536
|
"div",
|
|
1390
1537
|
{
|
|
1391
1538
|
"aria-hidden": "true",
|
|
@@ -1399,18 +1546,18 @@ function Skeleton({ shape = "block", width, height, lines = 1, className, style,
|
|
|
1399
1546
|
var Avatar = forwardRef15(function Avatar2({ name, src, size = "md", className, ...rest }, ref) {
|
|
1400
1547
|
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
1401
1548
|
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__ */
|
|
1403
|
-
src ? /* @__PURE__ */
|
|
1404
|
-
!src && /* @__PURE__ */
|
|
1549
|
+
return /* @__PURE__ */ jsxs19("span", { ref, "data-size": size, className: cn("cfi-ui", "cfi-ui-avatar", className), ...rest, children: [
|
|
1550
|
+
src ? /* @__PURE__ */ jsx19("img", { src, alt: name, className: "cfi-ui-avatar__image" }) : /* @__PURE__ */ jsx19("span", { "aria-hidden": "true", children: initials }),
|
|
1551
|
+
!src && /* @__PURE__ */ jsx19("span", { className: "cfi-ui-sr-only", children: name })
|
|
1405
1552
|
] });
|
|
1406
1553
|
});
|
|
1407
1554
|
function AvatarGroup({ max, className, children, ...rest }) {
|
|
1408
1555
|
const items = Array.isArray(children) ? children : [children];
|
|
1409
1556
|
const shown = max ? items.slice(0, max) : items;
|
|
1410
1557
|
const hidden = items.length - shown.length;
|
|
1411
|
-
return /* @__PURE__ */
|
|
1558
|
+
return /* @__PURE__ */ jsxs19("div", { className: cn("cfi-ui", "cfi-ui-avatar-group", className), ...rest, children: [
|
|
1412
1559
|
shown,
|
|
1413
|
-
hidden > 0 && /* @__PURE__ */
|
|
1560
|
+
hidden > 0 && /* @__PURE__ */ jsxs19("span", { className: "cfi-ui-avatar cfi-ui-avatar--overflow", children: [
|
|
1414
1561
|
"+",
|
|
1415
1562
|
hidden
|
|
1416
1563
|
] })
|
|
@@ -1423,7 +1570,7 @@ function ScrollArea({
|
|
|
1423
1570
|
style,
|
|
1424
1571
|
...rest
|
|
1425
1572
|
}) {
|
|
1426
|
-
return /* @__PURE__ */
|
|
1573
|
+
return /* @__PURE__ */ jsx19(
|
|
1427
1574
|
"div",
|
|
1428
1575
|
{
|
|
1429
1576
|
"data-orientation": orientation,
|
|
@@ -1444,20 +1591,20 @@ import { ChevronDown as ChevronDown3 } from "lucide-react";
|
|
|
1444
1591
|
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
1592
|
|
|
1446
1593
|
// src/Accordion.tsx
|
|
1447
|
-
import { jsx as
|
|
1594
|
+
import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1448
1595
|
var AccordionRoot = RadixAccordion.Root;
|
|
1449
1596
|
var AccordionItem = forwardRef16(function AccordionItem2({ className, ...rest }, ref) {
|
|
1450
|
-
return /* @__PURE__ */
|
|
1597
|
+
return /* @__PURE__ */ jsx20(RadixAccordion.Item, { ref, className: cn("cfi-ui-accordion__item", className), ...rest });
|
|
1451
1598
|
});
|
|
1452
1599
|
var AccordionTrigger = forwardRef16(function AccordionTrigger2({ meta, className, children, ...rest }, ref) {
|
|
1453
|
-
return /* @__PURE__ */
|
|
1454
|
-
/* @__PURE__ */
|
|
1455
|
-
/* @__PURE__ */
|
|
1456
|
-
meta && /* @__PURE__ */
|
|
1600
|
+
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: [
|
|
1601
|
+
/* @__PURE__ */ jsx20("span", { className: "cfi-ui-accordion__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx20(ChevronDown3, {}) }),
|
|
1602
|
+
/* @__PURE__ */ jsx20("span", { className: "cfi-ui-accordion__label", children }),
|
|
1603
|
+
meta && /* @__PURE__ */ jsx20("span", { className: "cfi-ui-accordion__meta", children: meta })
|
|
1457
1604
|
] }) });
|
|
1458
1605
|
});
|
|
1459
1606
|
var AccordionContent = forwardRef16(function AccordionContent2({ className, children, ...rest }, ref) {
|
|
1460
|
-
return /* @__PURE__ */
|
|
1607
|
+
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
1608
|
});
|
|
1462
1609
|
function Accordion({
|
|
1463
1610
|
sections,
|
|
@@ -1474,9 +1621,9 @@ function Accordion({
|
|
|
1474
1621
|
onValueChange,
|
|
1475
1622
|
className: cn("cfi-ui", "cfi-ui-accordion", className)
|
|
1476
1623
|
};
|
|
1477
|
-
return /* @__PURE__ */
|
|
1478
|
-
/* @__PURE__ */
|
|
1479
|
-
/* @__PURE__ */
|
|
1624
|
+
return /* @__PURE__ */ jsx20(AccordionRoot, { ...rootProps, children: sections.map((section) => /* @__PURE__ */ jsxs20(AccordionItem, { value: section.value, disabled: section.disabled, children: [
|
|
1625
|
+
/* @__PURE__ */ jsx20(AccordionTrigger, { meta: section.meta, children: section.label }),
|
|
1626
|
+
/* @__PURE__ */ jsx20(AccordionContent, { children: section.content })
|
|
1480
1627
|
] }, section.value)) });
|
|
1481
1628
|
}
|
|
1482
1629
|
function ToggleGroup({
|
|
@@ -1488,7 +1635,7 @@ function ToggleGroup({
|
|
|
1488
1635
|
className,
|
|
1489
1636
|
...aria
|
|
1490
1637
|
}) {
|
|
1491
|
-
return /* @__PURE__ */
|
|
1638
|
+
return /* @__PURE__ */ jsx20(
|
|
1492
1639
|
RadixToggleGroup.Root,
|
|
1493
1640
|
{
|
|
1494
1641
|
type: "single",
|
|
@@ -1500,7 +1647,7 @@ function ToggleGroup({
|
|
|
1500
1647
|
"data-size": size,
|
|
1501
1648
|
className: cn("cfi-ui", "cfi-ui-toggle-group", className),
|
|
1502
1649
|
...aria,
|
|
1503
|
-
children: options.map((option) => /* @__PURE__ */
|
|
1650
|
+
children: options.map((option) => /* @__PURE__ */ jsxs20(
|
|
1504
1651
|
RadixToggleGroup.Item,
|
|
1505
1652
|
{
|
|
1506
1653
|
value: option.value,
|
|
@@ -1509,7 +1656,7 @@ function ToggleGroup({
|
|
|
1509
1656
|
title: option.ariaLabel,
|
|
1510
1657
|
className: "cfi-ui-toggle-group__item",
|
|
1511
1658
|
children: [
|
|
1512
|
-
option.icon && /* @__PURE__ */
|
|
1659
|
+
option.icon && /* @__PURE__ */ jsx20("span", { className: "cfi-ui-toggle-group__icon", children: option.icon }),
|
|
1513
1660
|
option.label
|
|
1514
1661
|
]
|
|
1515
1662
|
},
|
|
@@ -1526,9 +1673,9 @@ import { AlertCircle, Loader2 } from "lucide-react";
|
|
|
1526
1673
|
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
1674
|
|
|
1528
1675
|
// src/PageState.tsx
|
|
1529
|
-
import { jsx as
|
|
1676
|
+
import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1530
1677
|
function LoadingState({ label = "Loading\u2026", size = "block", className }) {
|
|
1531
|
-
return /* @__PURE__ */
|
|
1678
|
+
return /* @__PURE__ */ jsxs21(
|
|
1532
1679
|
"div",
|
|
1533
1680
|
{
|
|
1534
1681
|
className: cn("cfi-ui", "cfi-ui-pagestate", className),
|
|
@@ -1536,8 +1683,8 @@ function LoadingState({ label = "Loading\u2026", size = "block", className }) {
|
|
|
1536
1683
|
role: "status",
|
|
1537
1684
|
"aria-live": "polite",
|
|
1538
1685
|
children: [
|
|
1539
|
-
/* @__PURE__ */
|
|
1540
|
-
/* @__PURE__ */
|
|
1686
|
+
/* @__PURE__ */ jsx21(Loader2, { className: "cfi-ui-pagestate__spinner", "aria-hidden": "true" }),
|
|
1687
|
+
/* @__PURE__ */ jsx21("span", { className: "cfi-ui-pagestate__muted", children: label })
|
|
1541
1688
|
]
|
|
1542
1689
|
}
|
|
1543
1690
|
);
|
|
@@ -1551,13 +1698,13 @@ function ErrorState({
|
|
|
1551
1698
|
className
|
|
1552
1699
|
}) {
|
|
1553
1700
|
const message = error instanceof Error ? error.message : error == null ? "" : String(error);
|
|
1554
|
-
return /* @__PURE__ */
|
|
1555
|
-
/* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1557
|
-
/* @__PURE__ */
|
|
1558
|
-
message && /* @__PURE__ */
|
|
1701
|
+
return /* @__PURE__ */ jsxs21("div", { className: cn("cfi-ui", "cfi-ui-pagestate", className), "data-size": size, role: "alert", children: [
|
|
1702
|
+
/* @__PURE__ */ jsx21(AlertCircle, { className: "cfi-ui-pagestate__icon", "data-tone": "error", "aria-hidden": "true" }),
|
|
1703
|
+
/* @__PURE__ */ jsxs21("div", { children: [
|
|
1704
|
+
/* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__title", children: title }),
|
|
1705
|
+
message && /* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__muted", children: message })
|
|
1559
1706
|
] }),
|
|
1560
|
-
onRetry && /* @__PURE__ */
|
|
1707
|
+
onRetry && /* @__PURE__ */ jsx21("button", { type: "button", className: "cfi-ui-pagestate__retry", onClick: onRetry, children: retryLabel })
|
|
1561
1708
|
] });
|
|
1562
1709
|
}
|
|
1563
1710
|
function EmptyState({
|
|
@@ -1568,17 +1715,17 @@ function EmptyState({
|
|
|
1568
1715
|
size = "block",
|
|
1569
1716
|
className
|
|
1570
1717
|
}) {
|
|
1571
|
-
return /* @__PURE__ */
|
|
1572
|
-
icon && /* @__PURE__ */
|
|
1573
|
-
/* @__PURE__ */
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
description && /* @__PURE__ */
|
|
1718
|
+
return /* @__PURE__ */ jsxs21("div", { className: cn("cfi-ui", "cfi-ui-pagestate", className), "data-size": size, children: [
|
|
1719
|
+
icon && /* @__PURE__ */ jsx21("span", { className: "cfi-ui-pagestate__icon", children: icon }),
|
|
1720
|
+
/* @__PURE__ */ jsxs21("div", { children: [
|
|
1721
|
+
/* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__title", children: title }),
|
|
1722
|
+
description && /* @__PURE__ */ jsx21("p", { className: "cfi-ui-pagestate__muted", children: description })
|
|
1576
1723
|
] }),
|
|
1577
|
-
action && /* @__PURE__ */
|
|
1724
|
+
action && /* @__PURE__ */ jsx21("div", { className: "cfi-ui-pagestate__action", children: action })
|
|
1578
1725
|
] });
|
|
1579
1726
|
}
|
|
1580
1727
|
function ComingSoon({ title, detail, className }) {
|
|
1581
|
-
return /* @__PURE__ */
|
|
1728
|
+
return /* @__PURE__ */ jsx21(
|
|
1582
1729
|
EmptyState,
|
|
1583
1730
|
{
|
|
1584
1731
|
title,
|
|
@@ -1589,9 +1736,9 @@ function ComingSoon({ title, detail, className }) {
|
|
|
1589
1736
|
}
|
|
1590
1737
|
|
|
1591
1738
|
// src/useSortState.ts
|
|
1592
|
-
import { useCallback as useCallback2, useMemo as
|
|
1739
|
+
import { useCallback as useCallback2, useMemo as useMemo4, useState as useState4 } from "react";
|
|
1593
1740
|
function useSortState(initialKey, initialDirection = "asc") {
|
|
1594
|
-
const [sort, setSort] =
|
|
1741
|
+
const [sort, setSort] = useState4({ key: initialKey, direction: initialDirection });
|
|
1595
1742
|
const toggle = useCallback2((key) => {
|
|
1596
1743
|
setSort(
|
|
1597
1744
|
(current) => current.key === key ? { key, direction: current.direction === "asc" ? "desc" : "asc" } : { key, direction: "asc" }
|
|
@@ -1621,23 +1768,23 @@ function useSortState(initialKey, initialDirection = "asc") {
|
|
|
1621
1768
|
},
|
|
1622
1769
|
[sort]
|
|
1623
1770
|
);
|
|
1624
|
-
return
|
|
1771
|
+
return useMemo4(
|
|
1625
1772
|
() => ({ sort, toggle, setSort, sortProps, sortBy }),
|
|
1626
1773
|
[sort, toggle, sortProps, sortBy]
|
|
1627
1774
|
);
|
|
1628
1775
|
}
|
|
1629
1776
|
|
|
1630
1777
|
// src/SearchInput.tsx
|
|
1631
|
-
import { forwardRef as forwardRef17, useEffect as useEffect3, useRef as useRef3, useState as
|
|
1778
|
+
import { forwardRef as forwardRef17, useEffect as useEffect3, useRef as useRef3, useState as useState5 } from "react";
|
|
1632
1779
|
import { Search as Search2, X as X4 } from "lucide-react";
|
|
1633
1780
|
|
|
1634
1781
|
// src/SearchInput.css
|
|
1635
1782
|
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
1783
|
|
|
1637
1784
|
// src/SearchInput.tsx
|
|
1638
|
-
import { jsx as
|
|
1785
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1639
1786
|
var SearchInput = forwardRef17(function SearchInput2({ value, onChange, delay = 250, placeholder = "Search\u2026", clearLabel = "Clear search", ...rest }, ref) {
|
|
1640
|
-
const [local, setLocal] =
|
|
1787
|
+
const [local, setLocal] = useState5(value);
|
|
1641
1788
|
const timer = useRef3(void 0);
|
|
1642
1789
|
const latest = useRef3(onChange);
|
|
1643
1790
|
latest.current = onChange;
|
|
@@ -1654,7 +1801,7 @@ var SearchInput = forwardRef17(function SearchInput2({ value, onChange, delay =
|
|
|
1654
1801
|
setLocal("");
|
|
1655
1802
|
latest.current("");
|
|
1656
1803
|
};
|
|
1657
|
-
return /* @__PURE__ */
|
|
1804
|
+
return /* @__PURE__ */ jsx22(
|
|
1658
1805
|
Input,
|
|
1659
1806
|
{
|
|
1660
1807
|
...rest,
|
|
@@ -1663,8 +1810,8 @@ var SearchInput = forwardRef17(function SearchInput2({ value, onChange, delay =
|
|
|
1663
1810
|
value: local,
|
|
1664
1811
|
placeholder,
|
|
1665
1812
|
onChange: (e) => push(e.target.value),
|
|
1666
|
-
prefix: /* @__PURE__ */
|
|
1667
|
-
suffix: local ? /* @__PURE__ */
|
|
1813
|
+
prefix: /* @__PURE__ */ jsx22(Search2, { "aria-hidden": "true" }),
|
|
1814
|
+
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
1815
|
}
|
|
1669
1816
|
);
|
|
1670
1817
|
});
|
|
@@ -1676,7 +1823,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
|
1676
1823
|
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
1824
|
|
|
1678
1825
|
// src/Pagination.tsx
|
|
1679
|
-
import { jsx as
|
|
1826
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1680
1827
|
function Pagination({
|
|
1681
1828
|
page,
|
|
1682
1829
|
pageSize,
|
|
@@ -1692,12 +1839,12 @@ function Pagination({
|
|
|
1692
1839
|
const from = (current - 1) * pageSize + 1;
|
|
1693
1840
|
const to = Math.min(current * pageSize, totalItems);
|
|
1694
1841
|
const range = labels?.range?.(from, to, totalItems) ?? `${from}\u2013${to} of ${totalItems.toLocaleString()}`;
|
|
1695
|
-
return /* @__PURE__ */
|
|
1842
|
+
return /* @__PURE__ */ jsxs22("nav", { className: cn("cfi-ui", "cfi-ui-pagination", className), "aria-label": "Pagination", children: [
|
|
1696
1843
|
showRange && // aria-live so a screen-reader user hears where they landed; paging
|
|
1697
1844
|
// otherwise moves focus nowhere and announces nothing.
|
|
1698
|
-
/* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1700
|
-
/* @__PURE__ */
|
|
1845
|
+
/* @__PURE__ */ jsx23("span", { className: "cfi-ui-pagination__range", "aria-live": "polite", children: range }),
|
|
1846
|
+
/* @__PURE__ */ jsxs22("div", { className: "cfi-ui-pagination__controls", children: [
|
|
1847
|
+
/* @__PURE__ */ jsx23(
|
|
1701
1848
|
"button",
|
|
1702
1849
|
{
|
|
1703
1850
|
type: "button",
|
|
@@ -1705,15 +1852,15 @@ function Pagination({
|
|
|
1705
1852
|
onClick: () => onPageChange(current - 1),
|
|
1706
1853
|
disabled: current <= 1,
|
|
1707
1854
|
"aria-label": labels?.previous ?? "Previous page",
|
|
1708
|
-
children: /* @__PURE__ */
|
|
1855
|
+
children: /* @__PURE__ */ jsx23(ChevronLeft, { "aria-hidden": "true" })
|
|
1709
1856
|
}
|
|
1710
1857
|
),
|
|
1711
|
-
/* @__PURE__ */
|
|
1858
|
+
/* @__PURE__ */ jsxs22("span", { className: "cfi-ui-pagination__page", children: [
|
|
1712
1859
|
current,
|
|
1713
1860
|
" / ",
|
|
1714
1861
|
pageCount
|
|
1715
1862
|
] }),
|
|
1716
|
-
/* @__PURE__ */
|
|
1863
|
+
/* @__PURE__ */ jsx23(
|
|
1717
1864
|
"button",
|
|
1718
1865
|
{
|
|
1719
1866
|
type: "button",
|
|
@@ -1721,7 +1868,7 @@ function Pagination({
|
|
|
1721
1868
|
onClick: () => onPageChange(current + 1),
|
|
1722
1869
|
disabled: current >= pageCount,
|
|
1723
1870
|
"aria-label": labels?.next ?? "Next page",
|
|
1724
|
-
children: /* @__PURE__ */
|
|
1871
|
+
children: /* @__PURE__ */ jsx23(ChevronRight, { "aria-hidden": "true" })
|
|
1725
1872
|
}
|
|
1726
1873
|
)
|
|
1727
1874
|
] })
|
|
@@ -1789,6 +1936,7 @@ export {
|
|
|
1789
1936
|
ComingSoon,
|
|
1790
1937
|
ConfirmDialog,
|
|
1791
1938
|
CountBadge,
|
|
1939
|
+
CreatableSelect,
|
|
1792
1940
|
Dialog,
|
|
1793
1941
|
DialogBody,
|
|
1794
1942
|
DialogClose,
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@campfire-interactive/ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
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",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Shared UI primitives for the Campfire Suite — Radix behavior, plain CSS styled entirely from the design tokens, no Tailwind required",
|
|
6
5
|
"type": "module",
|
|
7
6
|
"main": "dist/index.js",
|
|
8
7
|
"types": "dist/index.d.ts",
|