UNPKG

raft-ui

Version:

React UI components for Raft.

1,541 lines (1,536 loc) 680 kB
import { cn } from "./cn.mjs"; import { Dialog as Dialog$1 } from "@base-ui/react/dialog"; import { AlertTriangle, Bell, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Copy, FileText, Image, Info, Minus, Upload, X } from "lucide-react"; import { tv } from "tailwind-variants/lite"; import { Children, Fragment, cloneElement, createContext, isValidElement, use, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react"; import { Button as Button$1 } from "@base-ui/react/button"; import { mergeProps } from "@base-ui/react/merge-props"; import { useRender } from "@base-ui/react/use-render"; import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime"; import { Drawer as Drawer$1 } from "@base-ui/react/drawer"; import { useClipboard } from "foxact/use-clipboard"; import { Checkbox as Checkbox$1 } from "@base-ui/react/checkbox"; import { ScrollArea as ScrollArea$1 } from "@base-ui/react/scroll-area"; import { Collapsible } from "@base-ui/react/collapsible"; import { Avatar as Avatar$1, ContextMenu as ContextMenu$1 } from "@base-ui/react"; import { Menu } from "@base-ui/react/menu"; import { useHotkey } from "@tanstack/react-hotkeys"; import { Tooltip as Tooltip$1 } from "@base-ui/react/tooltip"; import { Popover as Popover$1 } from "@base-ui/react/popover"; import { PreviewCard as PreviewCard$1 } from "@base-ui/react/preview-card"; import { Input as Input$1 } from "@base-ui/react/input"; import { Field as Field$1 } from "@base-ui/react/field"; import { Combobox as Combobox$1 } from "@base-ui/react/combobox"; import { Select as Select$1 } from "@base-ui/react/select"; import { Radio } from "@base-ui/react/radio"; import { RadioGroup as RadioGroup$1 } from "@base-ui/react/radio-group"; import { Switch as Switch$1 } from "@base-ui/react/switch"; import { Toggle } from "@base-ui/react/toggle"; import { ToggleGroup as ToggleGroup$1 } from "@base-ui/react/toggle-group"; import { Toolbar } from "@base-ui/react/toolbar"; import { Progress as Progress$1 } from "@base-ui/react/progress"; import { DndContext, DragOverlay, KeyboardSensor, PointerSensor, TouchSensor, closestCenter, pointerWithin, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core"; import { SortableContext, arrayMove, defaultAnimateLayoutChanges, horizontalListSortingStrategy, sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { Toast } from "@base-ui/react/toast"; import { Tabs as Tabs$1 } from "@base-ui/react/tabs"; import { Separator as Separator$1 } from "@base-ui/react/separator"; import { Group, Panel as Panel$1, Separator as Separator$2 } from "react-resizable-panels"; //#region src/lib/tv.ts const tv$1 = ((options) => { const recipe = tv(options); const wrappedRecipe = ((props) => { const result = recipe(props); if (result == null || typeof result === "string") return cn(result); return Object.fromEntries(Object.entries(result).map(([slotName, slot]) => [slotName, (slotProps) => cn(slot(slotProps))])); }); return Object.assign(wrappedRecipe, recipe); }); //#endregion //#region src/lib/theme/theme-context.ts const ThemeContext = createContext("brutal"); const ThemeStateContext = createContext({ theme: "brutal", setTheme: () => void 0, mode: "light", resolvedMode: "light" }); //#endregion //#region src/lib/theme/use-theme.ts /** Read the active style family for theme-aware component recipes. */ function useThemeFamily() { return use(ThemeContext); } /** Read and update the application-level RUI theme selection. */ function useTheme() { return use(ThemeStateContext); } //#endregion //#region src/lib/theme/theme-scope.ts function resolveThemeScopeProps({ className, "data-theme": _dataTheme, ...props }, { theme, resolvedMode }) { const modeClassName = theme === "elegant" ? resolvedMode : void 0; const resolvedClassName = typeof className === "function" && modeClassName ? (state) => cn(className(state), modeClassName) : typeof className === "string" && modeClassName ? cn(className, modeClassName) : className ?? modeClassName; return { ...props, "data-theme": theme, className: resolvedClassName }; } function useThemeScopeProps(props) { return resolveThemeScopeProps(props, useTheme()); } //#endregion //#region src/lib/default-native-button.ts function defaultNativeButton(render) { if (!render || typeof render !== "object" || !("type" in render)) return; const element = render; if (typeof element.type === "string") return element.type === "button"; } //#endregion //#region src/components/spinner/spinner.tsx const ELEGANT_SPINNER_STYLE = ` @keyframes raft-elegant-spinner-spin { to { transform: rotate(360deg); } } @keyframes raft-elegant-spinner-dash { 0% { stroke-dasharray: 1 150; stroke-dashoffset: 0; } 50% { stroke-dasharray: 90 150; stroke-dashoffset: -35; } 100% { stroke-dasharray: 90 150; stroke-dashoffset: -124; } } [data-slot="spinner"] [data-spinner-ring] { animation: raft-elegant-spinner-spin 1600ms linear infinite; transform-box: fill-box; transform-origin: center; will-change: transform; } [data-slot="spinner"] [data-spinner-arc] { animation: raft-elegant-spinner-dash 1400ms cubic-bezier(0.42, 0, 0.58, 1) infinite; stroke-dasharray: 1 150; stroke-dashoffset: 0; } @media (prefers-reduced-motion: reduce) { [data-slot="spinner"] [data-spinner-ring] { animation-duration: 2400ms; will-change: auto; } [data-slot="spinner"] [data-spinner-arc] { animation: none; stroke-dasharray: 72 150; stroke-dashoffset: -30; } } `; const spinner = tv$1({ slots: { root: ["relative inline-flex shrink-0 items-center justify-center", "leading-none text-current"], ring: "block size-full shrink-0" }, variants: { theme: { brutal: {}, elegant: {} }, size: { xs: {}, sm: {}, md: {}, lg: {} }, variant: { default: {}, inverse: {} } }, defaultVariants: { size: "sm" }, compoundVariants: [ { theme: "brutal", size: "xs", class: { root: "size-2.5" } }, { theme: "brutal", size: "sm", class: { root: "size-4" } }, { theme: "brutal", size: "md", class: { root: "size-5" } }, { theme: "brutal", size: "lg", class: { root: "size-8" } }, { theme: "brutal", variant: "default", class: { root: "text-black", ring: "animate-spin rounded-full border-2 border-current/20 border-t-current" } }, { theme: "brutal", variant: "inverse", class: { root: "text-white", ring: "animate-spin rounded-full border-2 border-current/40 border-t-current" } }, { theme: "elegant", size: "xs", class: { root: "size-3.5" } }, { theme: "elegant", size: "sm", class: { root: "size-3.5" } }, { theme: "elegant", size: "md", class: { root: "size-4.5" } }, { theme: "elegant", size: "lg", class: { root: "size-4.5" } } ] }); const spinnerStyle = /* @__PURE__ */ jsx("style", { href: "raft-ui-spinner", precedence: "default", children: ELEGANT_SPINNER_STYLE }); function Spinner({ size = "sm", variant = "default", className, render, ...props }) { const theme = useThemeFamily(); const { root, ring } = spinner({ theme, size, variant }); const children = theme === "elegant" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [spinnerStyle, /* @__PURE__ */ jsxs("svg", { "data-spinner-ring": "", "aria-hidden": "true", className: ring(), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [/* @__PURE__ */ jsx("circle", { className: "opacity-20", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2.5" }), /* @__PURE__ */ jsx("circle", { "data-spinner-arc": "", className: "opacity-80", cx: "12", cy: "12", r: "10", fill: "none", pathLength: "150", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "2.5" })] })] }) : /* @__PURE__ */ jsx("span", { "data-spinner-ring": "", "aria-hidden": "true", className: ring() }); return useRender({ defaultTagName: "span", render, props: mergeProps({ role: "status", "aria-label": "Loading", className: root({ className }), children }, props), state: { slot: "spinner", size } }); } //#endregion //#region src/components/button/button.tsx const buttonVariants = tv$1({ slots: { root: [ "relative inline-flex shrink-0 items-center justify-center", "font-heading whitespace-nowrap select-none", "rounded-none", "shadow-raft-sm transition-all duration-100", "outline-[1px] outline-offset-2 outline-transparent focus-visible:outline-transparent", "data-[loading=true]:cursor-wait", "disabled:pointer-events-none disabled:opacity-40 data-[loading=true]:opacity-100", "disabled:transform-none", "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4" ], content: "relative z-10 inline-flex items-center justify-center gap-[inherit] data-[loading=true]:invisible", loadingIndicator: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center" }, variants: { theme: { brutal: { root: ["border-2 font-bold"] }, elegant: { root: [ "overflow-clip border-0 font-sans font-medium antialiased", "focus-visible:ring-2 focus-visible:ring-[color-mix(in_oklch,var(--button-focus-ring,var(--primary-400))_80%,transparent)] focus-visible:ring-offset-1 focus-visible:ring-offset-layer-canvas-muted", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.05),0_0_0_1px_var(--line-muted)]", "before:pointer-events-none before:absolute before:inset-0 before:z-0 before:rounded-[inherit]", "active:scale-[0.985]" ] } }, variant: { primary: { root: ["border-line-strong bg-primary-400 text-primary-950", "hover:bg-primary-500"] }, default: { root: ["border-line-strong bg-layer-panel text-foreground", "hover:bg-layer-panel"] }, information: { root: ["border-line-strong bg-info text-foreground-inverse", "hover:bg-info"] }, muted: { root: ["border-line-strong bg-secondary-400 text-secondary-950", "hover:bg-secondary-400"] }, accent: { root: ["border-line-strong bg-accent-400 text-accent-950", "hover:bg-accent-500"] }, warning: { root: ["border-line-strong bg-warning text-warning-foreground", "hover:bg-warning"] }, outline: { root: [ "border-line-strong bg-transparent text-foreground", "hover:bg-fill-muted", "shadow-none" ] }, ghost: { root: ["border-transparent bg-transparent text-foreground-strong shadow-none", "hover:border-line-strong hover:bg-fill-muted"] }, link: { root: ["border-transparent bg-transparent text-foreground shadow-none underline-offset-4", "hover:underline"] }, "danger-secondary": { root: ["border-line-strong bg-danger-soft text-danger", "hover:bg-danger-soft"] }, danger: { root: ["border-line-strong bg-danger text-danger-foreground", "hover:border-danger-hover hover:bg-danger-hover"] }, "danger-outline": { root: [ "border-line-strong bg-transparent text-danger", "hover:bg-fill-muted", "shadow-none" ] } }, size: { xs: { root: [ "h-6 gap-1 px-2 py-0 text-[11px]", "has-data-[icon=inline-start]:pl-1.5 has-data-[icon=inline-end]:pr-1.5", "**:data-icon:size-[1em]", "[&_svg:not([class*='size-'])]:size-3" ] }, sm: { root: [ "h-7 gap-[5px] px-2.5 py-0 text-xs", "has-data-[icon=inline-start]:pl-2 has-data-[icon=inline-end]:pr-2", "**:data-icon:size-[1em]", "[&_svg:not([class*='size-'])]:size-3.5" ] }, md: { root: [ "h-8 gap-[5.5px] px-3 py-0 text-sm", "has-data-[icon=inline-start]:pl-2.5 has-data-[icon=inline-end]:pr-2.5", "**:data-icon:size-[1em]" ] }, lg: { root: [ "gap-1.5 px-3.5 py-0 text-base", "has-data-[icon=inline-start]:pl-3 has-data-[icon=inline-end]:pr-3", "**:data-icon:size-[1em]" ] }, "icon-xs": { root: ["size-6 p-0 text-[11px]", "[&_svg:not([class*='size-'])]:size-3"] }, "icon-sm": { root: ["size-7 p-0 text-xs", "[&_svg:not([class*='size-'])]:size-3.5"] }, "icon-md": { root: "size-8 p-0 text-sm" }, "icon-lg": { root: "p-0 text-sm" } } }, defaultVariants: { variant: "default", size: "md" }, compoundVariants: [ { theme: "elegant", size: "xs", class: { root: "rounded-sm" } }, { theme: "elegant", size: "icon-xs", class: { root: "rounded-sm" } }, { theme: "elegant", size: "sm", class: { root: "rounded-sm" } }, { theme: "elegant", size: "icon-sm", class: { root: "rounded-sm" } }, { theme: "elegant", size: "md", class: { root: "rounded-md" } }, { theme: "elegant", size: "icon-md", class: { root: "rounded-md" } }, { theme: "elegant", size: "lg", class: { root: "h-9 rounded-md" } }, { theme: "elegant", size: "icon-lg", class: { root: "size-9 rounded-md" } }, { theme: "elegant", variant: [ "default", "primary", "outline", "information", "muted", "accent", "warning", "danger", "danger-secondary", "danger-outline" ], class: { root: "dark:shadow-raft-xs" } }, { theme: "elegant", variant: ["default", "outline"], class: { root: "[--button-focus-ring:var(--foreground)]" } }, { theme: "elegant", variant: [ "ghost", "link", "muted" ], class: { root: "[--button-focus-ring:var(--line-hairline)]" } }, { theme: "elegant", variant: [ "danger-secondary", "danger", "danger-outline" ], class: { root: "[--button-focus-ring:var(--danger)]" } }, { theme: "brutal", variant: "primary", class: { root: "bg-brutal-yellow text-foreground-strong hover:bg-brutal-yellow" } }, { theme: "brutal", variant: "default", class: { root: "bg-layer-panel text-foreground-strong hover:bg-layer-panel" } }, { theme: "brutal", variant: "outline", class: { root: "bg-layer-panel text-foreground-strong shadow-raft-sm hover:bg-layer-panel" } }, { theme: "brutal", variant: "information", class: { root: "bg-brutal-cyan text-foreground-strong hover:bg-brutal-cyan" } }, { theme: "brutal", variant: "muted", class: { root: "bg-brutal-stone text-foreground-strong hover:bg-brutal-stone" } }, { theme: "brutal", variant: "accent", class: { root: "bg-brutal-pink text-foreground-strong hover:bg-brutal-pink" } }, { theme: "brutal", variant: "danger", class: { root: "bg-brutal-red text-foreground-strong hover:border-line-strong hover:bg-brutal-red" } }, { theme: "brutal", variant: "danger-secondary", class: { root: "text-[color-mix(in_oklab,var(--danger)_72%,transparent)] hover:border-line-strong" } }, { theme: "brutal", variant: "warning", class: { root: "bg-brutal-orange text-foreground-strong hover:bg-brutal-orange" } }, { theme: "brutal", size: "lg", class: { root: ["h-10 px-4 text-sm", "has-data-[icon=inline-start]:pl-3.5 has-data-[icon=inline-end]:pr-3.5"] } }, { theme: "brutal", size: "icon-lg", class: { root: "size-10" } }, { theme: "elegant", variant: "default", class: { root: [ "bg-foreground text-foreground-inverse", "dark:bg-ink", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.12),0_0_0_1px_var(--foreground)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/8%)_0%,oklab(0%_0_0/0%)_100%)]", "hover:bg-[oklch(0.31_0.006_106.42)] dark:hover:bg-foreground-strong" ] } }, { theme: "elegant", variant: "primary", class: { root: [ "bg-primary-400 text-primary-950", "[--button-focus-ring:var(--primary-400)]", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.15),0_0_0_1px_var(--primary-edge)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/11%)_0%,oklab(100%_0_0/0%)_0%,oklab(0%_0_0/0%)_100%)]", "hover:bg-primary-hover", "dark:hover:bg-primary-500" ] } }, { theme: "elegant", variant: "outline", class: { root: [ "bg-layer-panel text-foreground dark:text-foreground-muted", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.05),0_0_0_1px_var(--line-muted)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(0%_0_0/0%)_30%,oklab(0%_0_0/1%)_100%)]", "hover:bg-fill-muted", "dark:bg-fill-muted dark:hover:bg-fill-strong" ] } }, { theme: "elegant", variant: "ghost", class: { root: ["bg-transparent text-foreground-muted shadow-none", "hover:bg-ink-4"] } }, { theme: "elegant", variant: "danger-secondary", class: { root: [ "bg-danger-soft text-danger", "dark:bg-[oklch(0.37_0.06_27)] dark:text-[oklch(0.8_0.17_22)]", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.08),0_0_0_1px_var(--danger-muted)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/4%)_0%,oklab(0%_0_0/0%)_100%)]", "hover:bg-danger-muted", "dark:hover:bg-[oklch(0.4_0.07_27)]" ] } }, { theme: "elegant", variant: "danger", class: { root: [ "bg-danger text-danger-foreground", "dark:bg-[oklch(0.58_0.21_27)] dark:text-[oklch(0.985_0.004_106.42)]", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.12),0_0_0_1px_var(--danger)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/10%)_0%,oklab(0%_0_0/0%)_100%)]", "hover:bg-danger-hover", "dark:hover:bg-[oklch(0.61_0.21_27)]" ] } }, { theme: "elegant", variant: "danger-outline", class: { root: [ "bg-layer-panel text-danger", "dark:bg-fill-muted dark:text-[oklch(0.78_0.19_25)]", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.025),0_0_0_1px_var(--danger-muted)]", "hover:bg-danger-soft", "dark:hover:bg-fill-strong" ] } }, { theme: "elegant", variant: "accent", class: { root: [ "bg-accent-400 text-accent-950", "dark:text-foreground-inverse", "[--button-focus-ring:var(--accent-400)]", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.12),0_0_0_1px_var(--accent-400)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/8%)_0%,oklab(0%_0_0/0%)_100%)]", "hover:bg-accent-hover" ] } }, { theme: "elegant", variant: "warning", class: { root: [ "bg-warning text-[oklch(0.25_0.05_50)]", "dark:bg-[oklch(0.66_0.17_46)]", "[--button-focus-ring:var(--warning)]", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.14),0_0_0_1px_var(--warning)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/10%)_0%,oklab(0%_0_0/0%)_100%)]", "hover:bg-warning-hover", "dark:hover:bg-[oklch(0.69_0.17_46)]" ] } }, { theme: "elegant", variant: "link", class: { root: "bg-transparent text-foreground-muted shadow-none" } }, { theme: "elegant", variant: "information", class: { root: [ "bg-info text-foreground-inverse", "dark:bg-info-strong", "[--button-focus-ring:var(--info)]", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.12),0_0_0_1px_var(--info)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/8%)_0%,oklab(0%_0_0/0%)_100%)]", "hover:bg-info-hover", "dark:hover:bg-info" ] } }, { theme: "elegant", variant: "muted", class: { root: [ "bg-fill-muted text-foreground-muted dark:text-foreground-placeholder", "shadow-[inset_0_1px_0.5px_oklch(1_0_0/0.05),0_0_0_1px_var(--line-muted)]", "before:bg-[linear-gradient(in_oklab_180deg,oklab(100%_0_0/5%)_0%,oklab(0%_0_0/1%)_100%)]", "hover:bg-fill-strong", "dark:bg-layer-panel", "dark:hover:bg-fill-muted" ] } }, { theme: "brutal", variant: [ "primary", "default", "information", "muted", "accent", "warning", "outline", "danger-secondary", "danger" ], class: { root: [ "hover:-translate-y-px hover:shadow-raft-md", "active:translate-px", "active:shadow-raft-xs" ] } }, { theme: "brutal", variant: "danger-outline", class: { root: ["hover:-translate-y-px", "active:translate-px"] } } ] }); function Button({ variant, size, loading = false, loadingLabel = "Loading", disabled, className, children, render, nativeButton, ...props }) { const theme = useThemeFamily(); const { root, content, loadingIndicator } = buttonVariants({ theme, variant, size }); return /* @__PURE__ */ jsxs(Button$1, { ...props, render, nativeButton: nativeButton ?? defaultNativeButton(render), "data-slot": "button", className: root({ className }), "data-loading": loading ? "true" : void 0, disabled: disabled || loading, "aria-disabled": loading || void 0, children: [loading ? /* @__PURE__ */ jsx("span", { "data-slot": "button-loading-indicator", className: loadingIndicator(), children: /* @__PURE__ */ jsx(Spinner, { "aria-label": loadingLabel }) }) : null, /* @__PURE__ */ jsx("span", { "data-slot": "button-content", "data-loading": loading ? "true" : void 0, className: content(), children })] }); } //#endregion //#region src/components/alert-dialog/alert-dialog.tsx const alertDialog = tv$1({ slots: { overlay: [ "fixed inset-0 z-50", "transition-opacity duration-150 ease-out", "data-starting-style:opacity-0 data-ending-style:opacity-0" ], content: [ "fixed top-1/2 left-1/2 z-50 grid w-[calc(100%-2rem)] max-w-[408px] -translate-1/2 ", "origin-center transform-gpu outline-none transition-[opacity,transform] duration-150 ease-out", "data-starting-style:scale-[.98] data-starting-style:opacity-0", "data-ending-style:opacity-0" ], header: ["grid grid-cols-[minmax(0,1fr)_max-content] items-center gap-3 min-w-0"], body: ["min-w-0"], footer: ["flex items-center justify-end gap-3"], title: ["m-0 min-w-0 text-foreground"], description: ["m-0 text-foreground-muted"] }, variants: { theme: { brutal: { overlay: ["bg-layer-backdrop"], content: ["gap-4 border-2 border-line-strong bg-layer-panel px-6 py-4 shadow-raft-xl"], body: ["py-2 font-medium"], title: ["font-heading text-lg leading-none font-bold uppercase"], description: ["font-sans text-sm leading-5 text-foreground-strong/60"] }, elegant: { overlay: ["bg-layer-backdrop backdrop-blur-[2px]"], content: ["overflow-clip rounded-lg bg-layer-popover shadow-raft-xl"], header: ["border-b border-line-muted/75 bg-layer-inset px-5 py-3", "dark:border-transparent dark:bg-transparent"], body: ["px-6 py-5 dark:pt-2.5"], footer: ["border-t border-line-muted/75 bg-layer-inset px-5 py-3", "dark:border-transparent dark:bg-transparent"], title: ["font-sans text-sm leading-5 font-medium tracking-[-0.005em]"], description: ["font-sans text-sm leading-5 text-foreground-hint"] } } } }); function AlertDialog(props) { return /* @__PURE__ */ jsx(Dialog$1.Root, { "data-slot": "alert-dialog", ...props }); } function AlertDialogTrigger(props) { return /* @__PURE__ */ jsx(Dialog$1.Trigger, { "data-slot": "alert-dialog-trigger", ...props }); } function AlertDialogPortal(props) { return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "alert-dialog-portal", ...useThemeScopeProps(props) }); } function AlertDialogClose({ className, variant, size, children, ...props }) { const isBrutal = useThemeFamily() === "brutal"; return /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "alert-dialog-close", render: /* @__PURE__ */ jsx(Button, { variant: variant ?? (isBrutal ? "outline" : "ghost"), size: size ?? (isBrutal ? "icon-md" : "icon-sm"), "aria-label": "Close", className: isBrutal ? className : cn("p-0 text-foreground-placeholder hover:border-transparent hover:bg-transparent hover:text-foreground-strong", className) }), ...props, children: children ?? /* @__PURE__ */ jsx(X, { className: isBrutal ? "size-5" : "size-4" }) }); } function AlertDialogOverlay({ className, ...props }) { const theme = useThemeFamily(); const { overlay } = alertDialog({ theme }); return /* @__PURE__ */ jsx(Dialog$1.Backdrop, { "data-slot": "alert-dialog-overlay", className: overlay({ className }), ...props }); } function AlertDialogContent({ className, children, portalProps, overlay, ...props }) { const theme = useThemeFamily(); const { content } = alertDialog({ theme }); return /* @__PURE__ */ jsxs(AlertDialogPortal, { ...portalProps, children: [overlay === false ? null : /* @__PURE__ */ jsx(AlertDialogOverlay, { ...overlay }), /* @__PURE__ */ jsx(Dialog$1.Popup, { "data-slot": "alert-dialog-content", className: content({ className }), ...props, role: "alertdialog", children })] }); } function AlertDialogHeader({ className, ...props }) { const theme = useThemeFamily(); const { header } = alertDialog({ theme }); return /* @__PURE__ */ jsx("div", { "data-slot": "alert-dialog-header", className: header({ className }), ...props }); } function AlertDialogBody({ className, ...props }) { const theme = useThemeFamily(); const { body } = alertDialog({ theme }); return /* @__PURE__ */ jsx("div", { "data-slot": "alert-dialog-body", className: body({ className }), ...props }); } function AlertDialogFooter({ className, ...props }) { const theme = useThemeFamily(); const { footer } = alertDialog({ theme }); return /* @__PURE__ */ jsx("div", { "data-slot": "alert-dialog-footer", className: footer({ className }), ...props }); } function AlertDialogTitle({ className, ...props }) { const theme = useThemeFamily(); const { title } = alertDialog({ theme }); return /* @__PURE__ */ jsx(Dialog$1.Title, { "data-slot": "alert-dialog-title", className: title({ className }), ...props }); } function AlertDialogDescription({ className, ...props }) { const theme = useThemeFamily(); const { description } = alertDialog({ theme }); return /* @__PURE__ */ jsx(Dialog$1.Description, { "data-slot": "alert-dialog-description", className: description({ className }), ...props }); } function AlertDialogAction(props) { return /* @__PURE__ */ jsx(Button, { "data-slot": "alert-dialog-action", ...props }); } function AlertDialogCancel({ className, variant = "outline", size = "sm", ...props }) { return /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "alert-dialog-cancel", render: /* @__PURE__ */ jsx(Button, { className, variant, size }), ...props }); } //#endregion //#region src/components/dialog/dialog.tsx const dialog = tv$1({ slots: { overlay: [ "fixed inset-0 z-50", "transition-opacity duration-150 ease-out", "data-starting-style:opacity-0 data-ending-style:opacity-0" ], content: [ "fixed top-1/2 left-1/2 z-50 grid w-[calc(100%-2rem)] max-w-md -translate-1/2 ", "origin-center transform-gpu outline-none transition-[opacity,transform] duration-150 ease-out", "data-starting-style:scale-[.98] data-starting-style:opacity-0", "data-ending-style:opacity-0" ], header: ["grid grid-cols-[minmax(0,1fr)_max-content] items-center gap-3 min-w-0"], body: ["min-w-0"], footer: ["flex items-center justify-end gap-3"], title: ["m-0 min-w-0 text-foreground"], description: ["m-0 text-foreground-muted"] }, variants: { theme: { brutal: { overlay: ["bg-layer-backdrop"], content: ["gap-4 border-2 border-line-strong bg-layer-panel px-6 py-4 shadow-raft-xl"], body: ["py-2 font-medium"], title: ["font-heading text-lg leading-none font-bold uppercase"], description: ["font-sans text-sm leading-5 text-foreground-strong/60"] }, elegant: { overlay: ["bg-layer-backdrop backdrop-blur-[2px]"], content: ["overflow-clip rounded-lg bg-layer-popover shadow-raft-xl"], header: ["border-b border-line-muted/75 bg-layer-inset px-6 py-3", "dark:border-transparent dark:bg-transparent"], body: ["px-6 py-5 dark:pt-2.5"], footer: ["border-t border-line-muted/75 bg-layer-inset px-6 py-3", "dark:border-transparent dark:bg-transparent"], title: ["font-sans text-sm leading-5 font-medium tracking-[-0.005em]"], description: ["font-sans text-sm leading-5 text-foreground-hint"] } } } }); function Dialog(props) { return /* @__PURE__ */ jsx(Dialog$1.Root, { "data-slot": "dialog", ...props }); } function DialogTrigger(props) { return /* @__PURE__ */ jsx(Dialog$1.Trigger, { "data-slot": "dialog-trigger", ...props }); } function DialogPortal(props) { return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "dialog-portal", ...useThemeScopeProps(props) }); } function DialogOverlay({ className, ...props }) { const theme = useThemeFamily(); const { overlay } = dialog({ theme }); return /* @__PURE__ */ jsx(Dialog$1.Backdrop, { "data-slot": "dialog-overlay", className: overlay({ className }), ...props }); } function DialogContent({ className, children, portalProps, overlay, ...props }) { const theme = useThemeFamily(); const { content } = dialog({ theme }); return /* @__PURE__ */ jsxs(DialogPortal, { ...portalProps, children: [overlay === false ? null : /* @__PURE__ */ jsx(DialogOverlay, { ...overlay }), /* @__PURE__ */ jsx(Dialog$1.Popup, { "data-slot": "dialog-content", className: content({ className }), ...props, children })] }); } function DialogClose({ className, variant, size, children, render, ...props }) { const isBrutal = useThemeFamily() === "brutal"; if (render) return /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "dialog-close", render, ...props, children }); return /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "dialog-close", render: /* @__PURE__ */ jsx(Button, { variant: variant ?? (isBrutal ? "outline" : "ghost"), size: size ?? (isBrutal ? "icon-md" : "icon-sm"), "aria-label": "Close", className: isBrutal ? className : cn("p-0 text-foreground-placeholder hover:border-transparent hover:bg-transparent hover:text-foreground-strong", className) }), ...props, children: children ?? /* @__PURE__ */ jsx(X, { className: isBrutal ? "size-5" : "size-4" }) }); } function DialogHeader({ className, ...props }) { const theme = useThemeFamily(); const { header } = dialog({ theme }); return /* @__PURE__ */ jsx("div", { "data-slot": "dialog-header", className: header({ className }), ...props }); } function DialogBody({ className, ...props }) { const theme = useThemeFamily(); const { body } = dialog({ theme }); return /* @__PURE__ */ jsx("div", { "data-slot": "dialog-body", className: body({ className }), ...props }); } function DialogFooter({ className, ...props }) { const theme = useThemeFamily(); const { footer } = dialog({ theme }); return /* @__PURE__ */ jsx("div", { "data-slot": "dialog-footer", className: footer({ className }), ...props }); } function DialogTitle({ className, ...props }) { const theme = useThemeFamily(); const { title } = dialog({ theme }); return /* @__PURE__ */ jsx(Dialog$1.Title, { "data-slot": "dialog-title", className: title({ className }), ...props }); } function DialogDescription({ className, ...props }) { const theme = useThemeFamily(); const { description } = dialog({ theme }); return /* @__PURE__ */ jsx(Dialog$1.Description, { "data-slot": "dialog-description", className: description({ className }), ...props }); } const drawer = tv$1({ extend: tv$1({ slots: { overlay: [ "opacity-[max(var(--drawer-overlay-min-opacity,0),calc(1-var(--drawer-swipe-progress)))]", "transition-opacity duration-200 ease-slide", "data-starting-style:opacity-0 data-ending-style:pointer-events-none data-ending-style:opacity-0 data-ending-style:duration-150", "motion-reduce:transition-none" ], popup: [ "[--drawer-blur:2px] [--drawer-ease:var(--ease-slide)]", "[--closed-transform:translate3d(var(--drawer-exit-x,0px),var(--drawer-exit-y,0px),0)]", "[--drawer-stack-peek:16px] [--drawer-stack-step:0.05]", "[--drawer-stack-progress:clamp(0,var(--drawer-swipe-progress),1)]", "[--drawer-stack-offset:max(0px,calc((var(--nested-drawers)-var(--drawer-stack-progress))*var(--drawer-stack-peek)))]", "[--drawer-stack-scale-base:calc(max(0,1-(var(--nested-drawers)*var(--drawer-stack-step))))]", "[--drawer-stack-scale:clamp(0,calc(var(--drawer-stack-scale-base)+(var(--drawer-stack-step)*var(--drawer-stack-progress))),1)]", "[--drawer-stack-shrink:calc(1-var(--drawer-stack-scale))]", "[--drawer-stack-shrink-offset:calc(var(--drawer-stack-shrink)*var(--drawer-stack-size))]", "origin-(--drawer-transform-origin)", "transform-[translate3d(calc(var(--drawer-swipe-x,0px)+var(--drawer-stack-x,0px)),calc(var(--drawer-swipe-y,0px)+var(--drawer-stack-y,0px)),0)_scale(var(--drawer-stack-scale))]", "opacity-100 blur-0", "transition-[transform,height,opacity,filter] duration-240 ease-(--drawer-ease) will-change-transform", "data-ending-style:duration-[calc(var(--drawer-swipe-strength,1)*180ms)]", "data-starting-style:transform-(--closed-transform) data-starting-style:opacity-0 data-starting-style:blur-(--drawer-blur)", "data-ending-style:transform-(--closed-transform) data-ending-style:opacity-0 data-ending-style:blur-(--drawer-blur)", "data-swiping:duration-0 data-nested-drawer-swiping:duration-0 motion-reduce:transition-none" ], content: ["transition-opacity duration-150 ease-slide motion-reduce:transition-none", "group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100"], swipeHandle: ["transition-opacity duration-150 motion-reduce:transition-none", "group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100"] }, variants: { side: { down: { popup: [ "[--drawer-exit-y:calc(100%+var(--drawer-inset)+2px)]", "[--drawer-stack-y:calc(0px-var(--drawer-stack-offset)-var(--drawer-stack-shrink-offset))]", "[--drawer-transform-origin:50%_100%]" ] }, up: { popup: [ "[--drawer-exit-y:calc(-100%-var(--drawer-inset)-2px)]", "[--drawer-stack-y:calc(var(--drawer-stack-offset)+var(--drawer-stack-shrink-offset))]", "[--drawer-transform-origin:50%_0%]" ] }, left: { popup: [ "[--drawer-exit-x:calc(-100%-var(--drawer-inset)-2px)]", "[--drawer-stack-x:calc(var(--drawer-stack-offset)+var(--drawer-stack-shrink-offset))]", "[--drawer-transform-origin:0%_50%]" ] }, right: { popup: [ "[--drawer-exit-x:calc(100%+var(--drawer-inset)+2px)]", "[--drawer-stack-x:calc(0px-var(--drawer-stack-offset)-var(--drawer-stack-shrink-offset))]", "[--drawer-transform-origin:100%_50%]" ] } }, axis: { x: { popup: ["[--drawer-stack-size:100%]", "[--drawer-swipe-x:var(--drawer-swipe-movement-x)]"] }, y: { popup: ["[--drawer-stack-size:max(0px,var(--drawer-frontmost-height,var(--drawer-height)))]", "[--drawer-swipe-y:calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y))]"] } }, snapPoints: { true: { overlay: ["[--drawer-overlay-min-opacity:0.5]"] } } } }), slots: { overlay: [ "fixed inset-0 z-50 min-h-dvh select-none", "bg-layer-backdrop", "supports-[-webkit-touch-callout:none]:absolute" ], viewport: ["pointer-events-none fixed inset-0 z-50 select-none"], popup: [ "group/drawer-popup pointer-events-auto fixed z-50 flex h-(--drawer-content-height) flex-col outline-none", "text-foreground-strong", "[--drawer-inset:12px] [--drawer-content-height:var(--drawer-height,auto)]", "data-nested-drawer-open:overflow-hidden" ], content: ["flex min-h-0 flex-1 flex-col rounded-[inherit] select-text", "group-data-swiping/drawer-popup:select-none"], swipeHandle: ["relative z-10 shrink-0 cursor-grab select-none active:cursor-grabbing", "before:absolute before:rounded-full before:bg-ink-20 before:content-['']"], close: ["shrink-0"], closeIcon: [], header: ["flex flex-col items-center px-6 pt-8 pb-2 text-center"], body: ["flex flex-1 flex-col items-center px-6 pt-4 pb-6 text-center"], footer: ["mt-auto px-6 py-5"], actions: ["flex w-full flex-col items-stretch gap-2.5", "**:data-[slot=button]:w-full"], title: ["max-w-sm text-pretty text-center text-2xl leading-8 text-foreground"], description: ["max-w-sm text-pretty text-center text-sm leading-5 text-foreground-strong/60"] }, variants: { theme: { brutal: { title: ["font-bold"], swipeHandle: ["before:rounded-none before:bg-ink-40"], popup: ["border-2 border-line-strong bg-layer-panel shadow-raft-xl"], close: ["bg-layer-panel"], closeIcon: ["size-5"] }, elegant: { overlay: ["backdrop-blur-[2px]"], popup: ["overflow-clip rounded-lg bg-layer-popover shadow-raft-xl md:rounded-xl"], close: ["p-0 text-foreground-placeholder hover:bg-transparent hover:text-foreground-strong"], closeIcon: ["size-4"], header: ["bg-layer-panel px-8 pt-9 pb-2", "dark:bg-transparent"], body: ["bg-layer-panel px-8 pt-4 pb-7", "dark:bg-transparent"], footer: ["mt-0 px-8 py-5"], title: ["font-sans text-2xl leading-8 font-semibold"], description: ["font-sans text-sm leading-5 text-foreground-muted"] } }, side: { down: { popup: ["[--drawer-inset:max(12px,env(safe-area-inset-bottom,0px))]", "bottom-(--drawer-inset) min-h-64 max-h-[82vh]"], swipeHandle: ["before:top-3"] }, up: { popup: ["[--drawer-inset:max(12px,env(safe-area-inset-top,0px))]", "top-(--drawer-inset) max-h-[80vh]"], swipeHandle: ["order-last", "before:bottom-3"] }, left: { popup: ["left-(--drawer-inset)"], swipeHandle: ["order-last", "before:right-3"] }, right: { popup: ["right-(--drawer-inset)"], swipeHandle: ["before:left-3"] } }, axis: { x: { popup: ["inset-y-3", "flex-row w-3/4 max-w-sm"], swipeHandle: ["my-auto h-16 w-11", "before:top-1/2 before:h-12 before:w-1.5 before:-translate-y-1/2"], header: ["flex-row justify-between gap-3 pt-6 text-left"], body: ["items-stretch text-left"], footer: ["py-4"], title: ["min-w-0 max-w-none flex-1 text-left"], description: ["max-w-none text-left"] }, y: { popup: ["data-nested-drawer-open:h-(--drawer-frontmost-height)", "inset-x-3 mx-auto md:max-w-md"], swipeHandle: ["mx-auto h-11 w-16", "before:left-1/2 before:h-1.5 before:w-12 before:-translate-x-1/2"] } } }, compoundVariants: [ { theme: "brutal", side: "right", class: { popup: ["[--drawer-inset:20px]"] } }, { theme: "brutal", side: "down", class: { popup: ["[--drawer-inset:max(20px,env(safe-area-inset-bottom,0px))]"] } }, { theme: "elegant", axis: "x", class: { popup: ["md:max-w-md"] } }, { side: "down", snapPoints: true, class: { header: ["pt-2"] } }, { axis: "y", snapPoints: true, class: { popup: ["[--drawer-content-height:100dvh]"] } } ] }); //#endregion //#region src/components/drawer/drawer.tsx const DrawerConfigContext = createContext(null); function useDrawerConfig() { const context = useContext(DrawerConfigContext); if (!context) throw new Error("Drawer parts must be used within Drawer."); return context; } function Drawer({ modal = true, snapPoints, swipeDirection = "down", ...props }) { const hasSnapPoints = snapPoints != null && snapPoints.length > 0; const swipeAxis = swipeDirection === "down" || swipeDirection === "up" ? "y" : "x"; const contextValue = useMemo(() => ({ hasSnapPoints, modal, swipeAxis, swipeDirection }), [ hasSnapPoints, modal, swipeAxis, swipeDirection ]); return /* @__PURE__ */ jsx(DrawerConfigContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(Drawer$1.Root, { modal, snapPoints, swipeDirection, ...props }) }); } function DrawerTrigger(props) { return /* @__PURE__ */ jsx(Drawer$1.Trigger, { "data-slot": "drawer-trigger", ...props }); } function DrawerPortal(props) { return /* @__PURE__ */ jsx(Drawer$1.Portal, { "data-slot": "drawer-portal", ...useThemeScopeProps(props) }); } function DrawerOverlay({ className, ...props }) { const { hasSnapPoints } = useDrawerConfig(); const { overlay } = drawer({ theme: useThemeFamily(), snapPoints: hasSnapPoints }); return /* @__PURE__ */ jsx(Drawer$1.Backdrop, { "data-slot": "drawer-overlay", className: overlay({ className }), ...props }); } function DrawerSwipeHandle() { const { swipeAxis, swipeDirection } = useDrawerConfig(); const { swipeHandle } = drawer({ theme: useThemeFamily(), side: swipeDirection, axis: swipeAxis }); return /* @__PURE__ */ jsx("div", { "data-slot": "drawer-swipe-handle", "aria-hidden": "true", className: swipeHandle() }); } function DrawerContent({ className, children, portalProps, ...props }) { const { hasSnapPoints, modal, swipeAxis, swipeDirection } = useDrawerConfig(); const { content, popup, viewport } = drawer({ theme: useThemeFamily(), side: swipeDirection, axis: swipeAxis, snapPoints: hasSnapPoints }); return /* @__PURE__ */ jsxs(DrawerPortal, { ...portalProps, children: [modal === true ? /* @__PURE__ */ jsx(DrawerOverlay, {}) : null, /* @__PURE__ */ jsx(Drawer$1.Viewport, { "data-slot": "drawer-viewport", className: cn(viewport(), modal === true && "pointer-events-auto"), children: /* @__PURE__ */ jsxs(Drawer$1.Popup, { "data-slot": "drawer-popup", className: popup({ className }), ...props, children: [hasSnapPoints ? /* @__PURE__ */ jsx(DrawerSwipeHandle, {}) : null, /* @__PURE__ */ jsx(Drawer$1.Content, { "data-slot": "drawer-content", className: content(), children })] }) })] }); } function DrawerClose({ className, variant, size, children, render, ...props }) { const theme = useThemeFamily(); const isBrutal = theme === "brutal"; const { close, closeIcon } = drawer({ theme }); if (render) return /* @__PURE__ */ jsx(Drawer$1.Close, { "data-slot": "drawer-close", className, render, ...props, children }); return /* @__PURE__ */ jsx(Drawer$1.Close, { "data-slot": "drawer-close", render: /* @__PURE__ */ jsx(Button, { variant: variant ?? (isBrutal ? "outline" : "ghost"), size: size ?? (isBrutal ? "icon-md" : "icon-sm"), "aria-label": "Close" }), className: close({ className }), ...props, children: children ?? /* @__PURE__ */ jsx(X, { className: closeIcon() }) }); } function DrawerHeader({ className, render, ...props }) { const { hasSnapPoints, swipeAxis, swipeDirection } = useDrawerConfig(); const { header } = drawer({ theme: useThemeFamily(), side: swipeDirection, axis: swipeAxis, snapPoints: hasSnapPoints }); return useRender({ defaultTagName: "div", render, props: mergeProps({ className: header({ className }) }, props), state: { slot: "drawer-header" } }); } function DrawerFooter({ className, render, ...props }) { const { swipeAxis } = useDrawerConfig(); const { footer } = drawer({ theme: useThemeFamily(), axis: swipeAxis }); return useRender({ defaultTagName: "div", render, props: mergeProps({ className: footer({ className }) }, props), state: { slot: "drawer-footer" } }); } function DrawerBody({ className, render, ...props }) { const { swipeAxis } = useDrawerConfig(); const { body } = drawer({ theme: useThemeFamily(), axis: swipeAxis }); return useRender({ defaultTagName: "div", render, props: mergeProps({ className: body({ className }) }, props), state: { slot: "drawer-body" } }); } function DrawerActions({ className, render, children, ...props }) { const { actions } = drawer({ theme: useThemeFamily() }); return useRender({ defaultTagName: "div", render, props: mergeProps({ className: actions({ className }), children }, props), state: { slot: "drawer-actions" } }); } function DrawerTitle({ className, ...props }) { const { swipeAxis } = useDrawerConfig(); const { title } = drawer({ theme: useThemeFamily(), axis: swipeAxis }); return /* @__PURE__ */ jsx(Drawer$1.Title, { "data-slot": "drawer-title", className: title({ className }), ...props }); } function DrawerDescription({ className, ...props }) { const { swipeAxis } = useDrawerConfig(); const { description } = drawer({ theme: useThemeFamily(), axis: swipeAxis }); return /* @__PURE__ */ jsx(Drawer$1.Description, { "data-slot": "drawer-description", className: description({ className }), ...props }); } //#endregion //#region src/components/card/card.recipe.ts const card = tv$1({ slots: { root: ["flex min-w-0 flex-col overflow-hidden", "text-foreground"], header: [ "group/card-header grid min-w-0 auto-rows-min grid-cols-1 items-start gap-x-4 gap-y-1", "has-[>[data-slot=card-leading]]:grid-cols-[auto_minmax(0,1fr)]", "has-[>[data-slot=card-trailing]]:grid-cols-[minmax(0,1fr)_auto]", "has-[>[data-slot=card-leading]]:has-[>[data-slot=card-trailing]]:grid-cols-[auto_minmax(0,1fr)_auto]" ], title: ["col-start-1 row-start-1 min-w-0", "group-has-[>[data-slot=card-leading]]/card-header:col-start-2"], leading: [ "col-start-1 row-span-2 row-start-1", "flex shrink-0 items-center self-start", "[&>svg]:size-4 [&>svg]:shrink-0" ], description: ["col-start-1 row-start-2 min-w-0", "group-has-[>[data-slot=card-leading]]/card-header:col-start-2"], trailing: [ "col-start-2 row-start-1", "flex shrink-0 items-center self-center justify-self-end", "group-has-[>[data-slot=card-leading]]/card-header:col-start-3" ], content: ["min-w-0"], footer: ["flex min-w-0 flex-wrap items-center gap-2"] }, variants: { theme: { brutal: { leading: ["min-h-5"], title: ["font-heading text-lg leading-5 font-bold"], description: ["font-sans text-sm leading-5 text-foreground-strong/60"], footer: [ "flex-nowrap items-center", "font-sans text-xs leading-4 text-foreground-muted", "[&>svg]:size-3.5 [&>svg]:shrink-0", "[&>:not(svg)]:min-w-0" ] }, elegant: { leading: ["min-h-[22px]"], title: ["font-sans text-base leading-[22px] font-medium"], description: ["font-sans text-xs leading-4 tracking-[0.01em] text-pretty", "text-foreground-muted"], footer: [ "flex-nowrap items-center", "font-sans text-xs leading-4 text-foreground-hint", "[&>svg]:size-3.5 [&>svg]:shrink-0", "[&>:not(svg)]:min-w-0" ] } }, variant: { default: {}, inset: {} } }, defaultVariants: { variant: "default" }, compoundVariants: [ { theme: "brutal", variant: "default", class: { root: ["border-2 border-line-strong bg-layer-panel", "shadow-raft-md"], header: "border-b-2 border-line-strong p-4", content: "p-4", footer: "border-t-2 border-line-strong bg-layer-inset px-4 py-3" } }, { theme: "brutal", variant: "inset", class: { root: ["border-2 border-line-strong bg-layer-panel px-2", "shadow-raft-md"], header: "px-4 py-3", content: "-mx-2 border-y-2 border-line-strong bg-layer-panel px-6 py-4", footer: "px-4 py-3" } }, { theme: "elegant", variant: "default", class: { root: ["rounded-lg border-[0.5px] border-line-muted bg-layer-panel", "shadow-raft-xs dark:border-transparent"], header: "p-5 has-[+[data-slot=card-content]]:pb-0", content: "p-5", footer: ["border-t border-line-hairline bg-layer-inset px-5 py-3.5", "dark:border-transparent dark:bg-transparent"] } }, { theme: "elegant", variant: "inset", class: { root: ["rounded-lg border-[0.5px] border-line-muted bg-layer-card p-[2px]", "shadow-raft-xs dark:border-transparent"], header: "px-5 py-3.5", content: ["overflow-clip rounded-[5.5px] border-[0.5px] border-line-hairline bg-layer-panel p-5", "dark:border-transparent dark:shadow-[inset_0_1px_0_oklch(1_0_0/0.04),0_0_0_1px_oklch(0_0_0/0.35)]"], footer: "px-5 py-3" } } ] }); //#endregion //#region src/components/card/card.tsx const CardVariantContext = createContext("default"); function useCardRecipe() { return card({ theme: useThemeFamily(), variant: use(CardVariantContext) }); } function Card({ className, render, variant = "default", ...props }) { const { root } = card({ theme: useThemeFamily(), variant }); const element = useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card", "data-variant": variant, className: root({ className }) }, props) }); return /* @__PURE__ */ jsx(CardVariantContext, { value: variant, children: element }); } function CardHeader({ className, render, ...props }) { const { header } = useCardRecipe(); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card-header", className: header({ className }) }, props) }); } function CardTitle({ className, render, ...props }) { const { title } = useCardRecipe(); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card-title", className: title({ className }) }, props) }); } function CardLeading({ className, render, ...props }) { const { leading } = useCardRecipe(); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card-leading", className: leading({ className }) }, props) }); } function CardDescription({ className, render, ...props }) { const { description } = useCardRecipe(); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card-description", className: description({ className }) }, props) }); } function CardTrailing({ className, render, ...props }) { const { trailing } = useCardRecipe(); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card-trailing", className: trailing({ className }) }, props) }); } function CardContent({ className, render, ...props }) { const { content } = useCardRecipe(); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card-content", className: content({ className }) }, props) }); } function CardFooter({ className, render, ...props }) { const { footer } = useCardRecipe(); return useRender({