UNPKG

raft-ui

Version:

React UI components for Raft.

1,407 lines (1,405 loc) 572 kB
import { cn } from "./cn.mjs"; import { $ as buttonVariants, A as SidebarItemIndicator, B as SidebarGroupLabel, C as PanelSection, D as SidebarItemContent, E as SidebarItemChannelIcon, F as SidebarItemSubtitle, G as ScrollArea, H as SidebarHeaderTitle, I as SidebarItemTitle, J as ScrollAreaScrollbar, K as ScrollAreaContent, L as Badge, M as SidebarItemMetaIcon, O as SidebarItemCount, P as SidebarItemStatus, Q as Button, R as SidebarBody, S as PanelScrollViewport, T as SidebarItemAside, U as SidebarLiveActivity, V as SidebarHeader, W as SidebarRoot, X as ScrollAreaViewport, Y as ScrollAreaThumb, Z as useMobileViewport, _ as Panel, a as PanelHeaderIcon, at as ThemeStateContext, b as PanelHeaderRoot, c as PanelSectionHeader, d as ConversationPanelBody, et as Spinner, f as ConversationPanelContent, g as conversationPanel, h as ConversationPanelTabs, i as PanelHeaderContent, it as ThemeContext, j as SidebarItemMeta, k as SidebarItemIcon, l as PanelStatus, m as ConversationPanelRoot, n as PanelActivity, nt as useTheme, o as PanelHeading, ot as tv, p as ConversationPanelFooter, q as ScrollAreaCorner, r as PanelHeader, rt as useThemeFamily, s as PanelMeta, t as PanelActions, tt as defaultNativeButton, u as PanelTitle, v as PanelBody, w as SidebarItem, x as PanelScrollContent, y as PanelFooter, z as SidebarContent } from "./panel-header-Dzc23jwl.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 { 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 { 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/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/components/alert-dialog/alert-dialog.tsx const alertDialog = tv({ 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({ 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({ extend: tv({ 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({ 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({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "card-footer", className: footer({ className }) }, props) }); } //#endregion //#region src/components/status/status.tsx const STATUS_STYLE = ` @keyframes raft-status-pulse-background { 0% { box-shadow: 0 0 0 1px color-mix(in oklch, var(--status-color) 42%, transparent); } 70%, 100% { box-shadow: 0 0 0 8px color-mix(in oklch, var(--status-color) 0%, transparent); } } /* Pulse + attention: animate a bottom-layer ring; leave attention outline untouched. */ [data-slot="status"][data-attention][data-pulse]:not([data-pulse="false"])::before { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: -1; animation: raft-status-pulse-background 1.4s ease-out infinite; } @media (prefers-reduced-motion: reduce) { [data-slot="status"][data-attention][data-pulse]:not([data-pulse="false"])::before { animation: none; } } `; const status = tv({ extend: tv({ slots: { root: ["relative inline-block shrink-0 rounded-full", "bg-(--status-color)"] }, variants: { theme: { brutal: { root: "border border-line-strong" }, elegant: {} }, variant: { default: { root: "[--status-color:var(--color-gray-400)]" }, primary: { root: "[--status-color:var(--color-primary-400)]" }, information: { root: "[--status-color:var(--color-info)]" }, muted: { root: "[--status-color:var(--color-secondary-400)]" }, accent: { root: "[--status-color:var(--color-accent-400)]" }, success: { root: "[--status-color:var(--color-success)]" }, warning: { root: "[--status-color:var(--color-warning)]" }, danger: { root: "[--status-color:var(--color-danger)]" } } }, defaultVariants: { variant: "default" } }), variants: { theme: { brutal: {}, elegant: {} }, size: { xs: { root: "size-1" }, sm: { root: "size-2" }, md: { root: "size-2.5" }, lg: { root: "size-[11px]" } }, pulse: { true: { root: "" }, false: { root: "" } }, attention: { true: { root: "" }, false: { root: "" } } }, defaultVariants: { size: "md", variant: "default", pulse: false, attention: false }, compoundVariants: [ { theme: "brutal", variant: "success", class: { root: "[--status-color:var(--color-brutal-lime)]" } }, { theme: "brutal", variant: "warning", class: { root: "[--status-color:var(--color-warning)]" } }, { theme: "brutal", pulse: true, class: { root: "animate-pulse" } }, { theme: "elegant", attention: true, class: { root: [ "isolate overflow-visible", "border border-[color-mix(in_oklch,var(--status-color)_58%,transparent)]", "shadow-[inset_0_0.5px_1px_color-mix(in_oklch,oklch(1_0_0)_55%,transparent)]" ] } }, { theme: "elegant", pulse: true, attention: false, class: { root: "animate-[raft-status-pulse-background_1.4s_ease-out_infinite] motion-reduce:animate-none" } } ] }); const statusStyle = /* @__PURE__ */ jsx("style", { href: "raft-ui-status", precedence: "default", children: STATUS_STYLE }); function StatusRoot({ size, variant, pulse, attention, className, render, ...props }) { const theme = useThemeFamily(); const resolvedPulse = pulse ?? false; const resolvedAttention = attention ?? false; const { root } = status({ theme, size, variant, pulse: resolvedPulse, attention: resolvedAttention }); return useRender({ defaultTagName: "span", render, props: mergeProps({ className: root({ className }), children: statusStyle }, props), state: { slot: "status", variant, pulse: resolvedPulse, attention: resolvedAttention, size } }); } const Status = StatusRoot; //#endregion //#region src/components/app-rail/app-rail.recipe.ts const appRail = tv({ slots: { root: ["flex size-full flex-col items-center select-none"], header: ["relative flex w-full shrink-0 items-center justify-center"], nav: ["flex w-full flex-1 flex-col items-center gap-1.5 py-2"], footer: ["flex w-full shrink-0 flex-col items-center justify-center gap-1.5"], item: [ "relative inline-flex shrink-0 items-center justify-center", "outline-none", "disabled:pointer-events-none disabled:opacity-45", "[&_svg]:size-4.5 [&_svg]:shrink-0" ], itemIcon: ["relative inline-flex items-center justify-center"], itemAttentionMask: ["pointer-events-none absolute inset-0", "[&_svg]:size-full [&_svg]:shrink-0"], itemLabel: ["sr-only"], itemBadge: ["absolute -right-1 -top-1 inline-flex min-w-4 items-center justify-center", "px-1 text-[10px] font-bold leading-4"], itemIndicator: ["pointer-events-none absolute -right-1 top-[-2px]"] }, variants: { theme: { brutal: { root: "w-16 border-r-2 border-black bg-primary text-foreground-strong md:[@media(max-height:600px)]:w-[50px]", header: "h-(--shell-header-height,62px) border-b-2 border-black [@media(max-height:600px)]:h-12", footer: "h-auto pb-2 [@media(max-height:600px)]:pb-1", item: [ "size-10 border-2 border-transparent text-foreground-strong", "transition-colors", "hover:border-black hover:bg-white", "data-[selected=true]:border-black data-[selected=true]:bg-white data-[selected=true]:shadow-raft-sm", "focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-black", "md:[@media(max-height:600px)]:size-9" ], itemBadge: "border-2 border-black bg-brutal-pink text-black", itemAttentionMask: "hidden" }, elegant: { root: "w-14 bg-layer-canvas-muted", header: "h-(--shell-header-height,56px) border-b-0", nav: ["px-2 pt-4 pb-2"], footer: ["h-auto gap-1.5 px-2 pb-2", "*:data-[slot=app-rail-item]:text-foreground-muted"], item: [ "size-auto min-w-9 p-3 rounded-md border border-transparent", "text-[13px] text-foreground-icon [&_svg]:size-4", "hover:bg-fill-strong/80 hover:text-foreground-strong", "active:bg-fill-strong/80 active:text-foreground-strong", "dark:hover:bg-ink-6 dark:active:bg-ink-6", "data-[selected=true]:border-transparent data-[selected=true]:bg-fill-strong", "dark:data-[selected=true]:bg-layer-card", "data-[selected=true]:text-foreground-muted data-[selected=true]:shadow-none", "dark:data-[selected=true]:text-foreground-strong dark:data-[selected=true]:shadow-raft-sm", "focus-visible:ring-[0.5px] focus-visible:ring-primary-500" ], itemBadge: [ "rounded-full border-0 bg-primary-400 text-primary-950", "px-1 font-mono text-[10px] font-[450] leading-none tabular-nums normal-case tracking-normal", "ring-2 ring-layer-canvas-muted" ], itemAttentionMask: [ "text-[oklch(73.4%_0.149_89.2)] drop-shadow-[0_0_1px_oklch(88.3%_0.162_91.9/0.82)]", "mask-[radial-gradient(circle_at_96%_12%,black_0%,black_24%,oklch(0_0_0/0.82)_38%,oklch(0_0_0/0.38)_58%,transparent_74%)]", "[-webkit-mask-image:radial-gradient(circle_at_96%_12%,black_0%,black_24%,oklch(0_0_0/0.82)_38%,oklch(0_0_0/0.38)_58%,transparent_74%)]" ], itemIndicator: "data-[variant=primary]:bg-[color-mix(in_srgb-linear,var(--color-primary-400)_86%,var(--ink))]" } } } }); //#endregion //#region src/components/app-rail/app-rail.tsx function AppRailRoot({ className, render, ...props }) { const { root } = appRail({ theme: useThemeFamily() }); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "app-rail-root", className: root({ className }) }, props) }); } function AppRailHeader({ className, render, ...props }) { const { header } = appRail({ theme: useThemeFamily() }); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "app-rail-header", className: header({ className }) }, props) }); } function AppRailNav({ className, render, ...props }) { const { nav } = appRail({ theme: useThemeFamily() }); return useRender({ defaultTagName: "nav", render, props: mergeProps({ "data-slot": "app-rail-nav", className: nav({ className }) }, props) }); } function AppRailItem({ nativeButton = true, selected, disabled, className, render, ...props }) { const { item } = appRail({ theme: useThemeFamily() }); const defaultProps = { type: nativeButton ? "button" : void 0, disabled: nativeButton ? disabled : void 0, "aria-pressed": nativeButton ? selected : void 0, "data-slot": "app-rail-item", "data-selected": selected ? "true" : void 0, "data-disabled": disabled ? "true" : void 0, className: item({ className }) }; return useRender({ render: render ?? /* @__PURE__ */ jsx(Button$1, {}), props: mergeProps(defaultProps, props) }); } function AppRailItemIcon({ className, render, ...props }) { const { itemIcon } = appRail(); return useRender({ defaultTagName: "span", render, props: mergeProps({ "data-slot": "app-rail-item-icon", className: itemIcon({ className }) }, props) }); } function AppRailItemAttention({ title, children }) { return /* @__PURE__ */ jsxs(Fragment$1, { children: [ /* @__PURE__ */ jsx(AppRailItemAttentionMask, { "aria-hidden": true, children }), /* @__PURE__ */ jsx(AppRailItemIndicator, { "aria-hidden": true }), title ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: title }) : null ] }); } function AppRailItemAttentionMask({ className, render, ...props }) { const { itemAttentionMask } = appRail({ theme: useThemeFamily() }); return useRender({ defaultTagName: "span", render, props: mergeProps({ "data-slot": "app-rail-item-attention-mask", className: itemAttentionMask({ className }) }, props) }); } function AppRailItemLabel({ className, render, ...props }) { const { itemLabel } = appRail({ theme: useThemeFamily() }); return useRender({ defaultTagName: "span", render, props: mergeProps({ "data-slot": "app-rail-item-label", className: itemLabel({ className }) }, props) }); } function AppRailItemBadge({ className, render, ...props }) { const { itemBadge } = appRail({ theme: useThemeFamily() }); return useRender({ defaultTagName: "span", render, props: mergeProps({ "data-slot": "app-rail-item-badge", className: itemBadge({ className }) }, props) }); } function AppRailItemIndicator({ className, size = "sm", variant, attention = true, ...props }) { const theme = useThemeFamily(); const { itemIndicator } = appRail({ theme }); return /* @__PURE__ */ jsx(Status, { "aria-hidden": true, attention, size, variant: variant ?? (theme === "elegant" ? "primary" : "accent"), "data-slot": "app-rail-item-indicator", className: itemIndicator({ className }), ...props }); } function AppRailFooter({ className, render, ...props }) { const { footer } = appRail({ theme: useThemeFamily() }); return useRender({ defaultTagName: "div", render, props: mergeProps({ "data-slot": "app-rail-footer", className: footer({ className }) }, props) }); } //#endregion //#region src/components/copyable-code/copyable-code.tsx const copyableCode = tv({ slots: { root: ["group/copyable-code flex w-full min-w-0 items-center gap-2"], code: ["min-w-0 flex-1 font-mono text-xs"], codeInner: ["block w-full min-w-0 max-w-full break-all"], action: [ "shrink-0", "**:data-[slot=button]:transition-[color,background-color,box-shadow]", "**:data-[slot=button]:duration-150 [&_[data-slot=button]]:ease-out" ], iconSwap: [ "relative inline-grid size-3", "**:data-[slot=copyable-code-icon]:col-start-1 **:data-[slot=copyable-code-icon]:row-start-1", "**:data-[slot=copyable-code-icon]:origin-center", "**:data-[slot=copyable-code-icon]:transition-[opacity,filter,scale]", "**:data-[slot=copyable-code-icon]:duration-170", "**:data-[slot=copyable-code-icon]:ease-[cubic-bezier(0.16,1,0.3,1)]", "**:data-[slot=copyable-code-icon]:will-change-[opacity,filter,scale]", "motion-reduce:**:data-[slot=copyable-code-icon]:transition-none", "data-[state=idle]:**:data-[icon=copy]:scale-100 data-[state=idle]:**:data-[icon=copy]:opacity-100 data-[state=idle]:[&_[data-icon=copy]]:blur-0", "data-[state=idle]:**:data-[icon=check]:scale-[0.72] data-[state=idle]:**:data-[icon=check]:opacity-0 data-[state=idle]:**:data-[icon=check]:blur-[1px]", "data-[state=copied]:**:data-[icon=check]:scale-100 data-[state=copied]:**:data-[icon=check]:opacity-100 data-[state=copied]:[&_[data-icon=check]]:blur-0", "data-[state=copied]:**:data-[icon=copy]:scale-[0.72] data-[state=copied]:**:data-[icon=copy]:opacity-0 data-[state=copied]:**:data-[icon=copy]:blur-[1px]" ] }, variants: { theme: { brutal: { code: ["border-2 border-line-strong bg-black text-[oklch(0.88_0.18_132)] shadow-raft-sm"], codeInner: "break-all" }, elegant: { code: [ "bg-layer-inset text-[oklch(0.45_0.04_74)]", "ring-[0.5px] ring-ink-20 dark:ring-ink-10", "dark:text-[oklch(0.82_0.06_90)]" ], codeInner: ["border-x border-dashed border-ink-10 dark:border-ink-16 bg-layer-panel px-1", "dark:bg-[oklch(0.15_0.004_106.42)]"], action: [ "**:data-[slot=button]:text-foreground-muted", "**:data-[slot=button]:shadow-none", "**:data-[slot=button]:hover:bg-transparent **:data-[slot=button]:hover:text-foreground **:data-[slot=button]:hover:before:bg-transparent" ] } }, size: { sm: { code: "px-3 py-1.5 leading-5" }, md: { code: "px-3 py-2 leading-5" } } }, defaultVariants: { size: "md" }, compoundVariants: [{ theme: "elegant", size: "sm", class: { code: "px-2 py-0", codeInner: "py-1.5 leading-5" } }, { theme: "elegant", size: "md", class: { code: "px-2 py-0", codeInner: "py-2 leading-5" } }] }); const CopyableCodeContext = createContext(null); function useCopyableCode(part) { const context = useContext(CopyableCodeContext); if (!context) throw new Error(`${part} must be used inside CopyableCodeRoot.`); return context; } function CopyableCodeRoot({ copied, onCopy, size = "md", className, ...props }) { const theme = useThemeFamily(); const { root } = copyableCode({ theme, size }); const { copied: clipboardCopied, copy } = useClipboard({ timeout: 1400 }); const effectiveCopied = copied ?? clipboardCopied; const copyValue = useCallback(async (value) => { await copy(value); await onCopy?.(value); }, [copy, onCopy]); const context = useMemo(() => ({ copied: effectiveCopied, copyValue, size }), [ copyValue, effectiveCopied, size ]); return /* @__PURE__ */ jsx(CopyableCodeContext.Provider, { value: context, children: /* @__PURE__ */ jsx("div", { "data-slot": "copyable-code-root", "data-size": size, "data-state": effectiveCopied ? "copied" : "idle", className: root({ className }), ...props }) }); } function CopyableCode({ children, className, truncate, ...props }) { const { size } = useCopyableCode("CopyableCode"); const theme = useThemeFamily(); const { code, codeInner } = copyableCode({ theme, size }); const scrollClassName = "overflow-x-auto overflow-y-hidden break-normal whitespace-nowrap text-clip [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"; return /* @__PURE__ */ jsx("code", { "data-slot": "copyable-code", "data-truncate": truncate ? "true" : void 0, className: code({ className }), ...props, children: /* @__PURE__ */ jsx("span", { "data-slot": "copyable-code-inner", className: codeInner({ className: [truncate && scrollClassName] }), children }) }); } function CopyableCodeAction({ children, buttonClassName, className, onClick, size, variant, ...props }) { const { copied, copyValue } = useCopyableCode("CopyableCodeAction"); const theme = useThemeFamily(); const { action } = copyableCode({ theme }); const accessibleLabel = copied ? "Copied code" : "Copy code"; const buttonSize = size ?? (theme === "elegant" ? "icon-xs" : "icon-sm"); const buttonVariant = variant ?? (theme === "elegant" ? "ghost" : "outline"); const handleClick = async (event) => { const value = event.currentTarget.closest("[data-slot=\"copyable-code-root\"]")?.querySelector("[data-slot=\"copyable-code\"]")?.textContent ?? ""; await copyValue(value); onClick?.(event); }; return /* @__PURE__ */ jsx("span", { "data-slot": "copyable-code-action", className: action({ className }), children: /* @__PURE__ */ jsx(Button, { type: "button", variant: buttonV