@burtson-labs/ui 0.12.3 → 0.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import { Button } from "./button.js";
3
3
  import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "./dropdown-menu.js";
4
+ import "./input.js";
4
5
  import * as React from "react";
5
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
7
  import AlertCircle from "@burtson-labs/icons/react/alert-circle";
@@ -130,7 +131,7 @@ function ChatHistory({ items, activeId, onSelect, onNewChat, onRename, onDelete,
130
131
  value: query,
131
132
  onChange: (e) => setQuery(e.target.value),
132
133
  placeholder: "Search chats",
133
- className: "h-8 w-full rounded-md border border-input bg-surface pr-2 pl-8 text-base outline-none placeholder:text-muted-foreground focus-visible:border-brand focus-visible:ring-[3px] focus-visible:ring-ring/15 sm:text-sm"
134
+ className: cn("h-8 w-full rounded-md border border-input bg-surface pr-2 pl-8 text-base placeholder:text-muted-foreground sm:text-sm", "outline-hidden! focus-visible:border-ring focus-visible:inset-ring-1 focus-visible:inset-ring-ring aria-invalid:focus-visible:inset-ring-destructive")
134
135
  })
135
136
  ]
136
137
  })]
@@ -272,7 +273,7 @@ function RenameRow({ title, onDone }) {
272
273
  onDone(title);
273
274
  }
274
275
  },
275
- className: "h-8 w-full rounded-md border border-brand bg-surface px-2 text-base ring-[3px] ring-ring/15 outline-none sm:text-sm"
276
+ className: "h-8 w-full rounded-md border border-ring bg-surface px-2 text-base inset-ring-1 inset-ring-ring outline-hidden! sm:text-sm"
276
277
  })
277
278
  });
278
279
  }
@@ -1 +1 @@
1
- {"version":3,"file":"chat-history.js","names":["_Fragment"],"sources":["../../src/components/chat-history.tsx"],"sourcesContent":["import AlertCircle from '@burtson-labs/icons/react/alert-circle';\nimport Edit from '@burtson-labs/icons/react/edit';\nimport MessageSquarePlus from '@burtson-labs/icons/react/message-square-plus';\nimport MoreHorizontal from '@burtson-labs/icons/react/more-horizontal';\nimport Pin from '@burtson-labs/icons/react/pin';\nimport PinOff from '@burtson-labs/icons/react/pin-off';\nimport Search from '@burtson-labs/icons/react/search';\nimport Trash from '@burtson-labs/icons/react/trash';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Button } from './button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from './dropdown-menu';\n\nexport interface ChatHistoryItem {\n id: string;\n title: string;\n /** When the conversation last changed; decides its group. */\n updatedAt: Date | string | number;\n pinned?: boolean;\n /** A line of the latest message, searched along with the title. */\n preview?: string;\n}\n\nexport type ChatHistoryGroupKey = 'pinned' | 'today' | 'yesterday' | 'week' | 'older';\n\nexport interface ChatHistoryGroup {\n key: ChatHistoryGroupKey;\n label: string;\n items: ChatHistoryItem[];\n}\n\nconst LABELS: Record<ChatHistoryGroupKey, string> = {\n pinned: 'Pinned',\n today: 'Today',\n yesterday: 'Yesterday',\n week: 'Previous 7 days',\n older: 'Older',\n};\n\nconst time = (d: ChatHistoryItem['updatedAt']) => new Date(d).getTime();\nconst startOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();\n\n/**\n * Pinned first, then Today, Yesterday, Previous 7 days and Older by the\n * local calendar, newest first in each. Empty groups are left out.\n */\nexport function groupConversations(\n items: ChatHistoryItem[],\n now: Date = new Date(),\n): ChatHistoryGroup[] {\n const today = startOfDay(now);\n const day = 24 * 60 * 60 * 1000;\n const buckets: Record<ChatHistoryGroupKey, ChatHistoryItem[]> = {\n pinned: [],\n today: [],\n yesterday: [],\n week: [],\n older: [],\n };\n for (const item of [...items].sort((a, b) => time(b.updatedAt) - time(a.updatedAt))) {\n if (item.pinned) {\n buckets.pinned.push(item);\n continue;\n }\n const t = startOfDay(new Date(item.updatedAt));\n const key: ChatHistoryGroupKey =\n t >= today\n ? 'today'\n : t >= today - day\n ? 'yesterday'\n : t >= today - 7 * day\n ? 'week'\n : 'older';\n buckets[key].push(item);\n }\n return (Object.keys(buckets) as ChatHistoryGroupKey[])\n .filter((k) => buckets[k].length > 0)\n .map((k) => ({ key: k, label: LABELS[k], items: buckets[k] }));\n}\n\n/** Case-insensitive match on every word, across title and preview. */\nexport function matchesConversation(item: ChatHistoryItem, query: string): boolean {\n const hay = `${item.title} ${item.preview ?? ''}`.toLowerCase();\n return query\n .toLowerCase()\n .split(/\\s+/)\n .filter(Boolean)\n .every((w) => hay.includes(w));\n}\n\nexport interface ChatHistoryProps extends Omit<React.ComponentProps<'div'>, 'onSelect'> {\n items: ChatHistoryItem[];\n activeId?: string;\n onSelect: (id: string) => void;\n /** Shows a \"New chat\" button at the top. */\n onNewChat?: () => void;\n /** Adds Rename to the row menu; the title is edited in place. */\n onRename?: (id: string, title: string) => void;\n /** Adds Delete to the row menu. Confirm or offer undo in your app. */\n onDelete?: (id: string) => void;\n /** Adds Pin / Unpin to the row menu. */\n onPinChange?: (id: string, pinned: boolean) => void;\n /** Controlled search text; leave out to let the list keep its own. */\n query?: string;\n onQueryChange?: (query: string) => void;\n /** Hides the search box, e.g. when the app searches on the server. */\n searchable?: boolean;\n loading?: boolean;\n /** Why the list could not load. Shown with Retry when `onRetry` is set. */\n error?: React.ReactNode;\n onRetry?: () => void;\n /** Shown when there are no conversations at all. */\n empty?: React.ReactNode;\n /** The clock grouping uses; pass it in tests. */\n now?: Date;\n /**\n * Virtualisation hook for long histories: receives a group's items and the\n * row renderer, returns what to render (e.g. a windowed list). Default\n * renders every row.\n */\n renderItems?: (\n items: ChatHistoryItem[],\n renderItem: (item: ChatHistoryItem) => React.ReactNode,\n ) => React.ReactNode;\n label?: string;\n}\n\n/**\n * The conversation list beside a chat: a New chat action, search, and the\n * history grouped by day with pinned chats on top. Up and Down move between\n * rows, Home and End jump, Enter opens; each row has a menu for rename, pin\n * and delete. The app owns the data; this only reports what the person did.\n */\nfunction ChatHistory({\n items,\n activeId,\n onSelect,\n onNewChat,\n onRename,\n onDelete,\n onPinChange,\n query: controlledQuery,\n onQueryChange,\n searchable = true,\n loading = false,\n error,\n onRetry,\n empty,\n now,\n renderItems,\n label = 'Chat history',\n className,\n ...props\n}: ChatHistoryProps) {\n const [ownQuery, setOwnQuery] = React.useState('');\n const query = controlledQuery ?? ownQuery;\n const setQuery = (q: string) => {\n if (controlledQuery === undefined) setOwnQuery(q);\n onQueryChange?.(q);\n };\n const [renaming, setRenaming] = React.useState<string | null>(null);\n const list = React.useRef<HTMLDivElement>(null);\n const searchId = React.useId();\n\n const visible = query.trim() ? items.filter((i) => matchesConversation(i, query)) : items;\n const groups = groupConversations(visible, now);\n\n const onRowKeyDown = (e: React.KeyboardEvent) => {\n const rows = Array.from(\n list.current?.querySelectorAll<HTMLElement>('[data-slot=\"chat-history-row\"]') ?? [],\n );\n const i = rows.indexOf(document.activeElement as HTMLElement);\n let next = -1;\n if (e.key === 'ArrowDown') next = Math.min(rows.length - 1, i + 1);\n else if (e.key === 'ArrowUp') next = Math.max(0, i - 1);\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = rows.length - 1;\n const row = next >= 0 ? rows[next] : undefined;\n if (row) {\n e.preventDefault();\n row.focus();\n }\n };\n\n const renderItem = (item: ChatHistoryItem) => (\n <HistoryRow\n key={item.id}\n item={item}\n active={item.id === activeId}\n renaming={renaming === item.id}\n onSelect={() => onSelect(item.id)}\n onStartRename={onRename ? () => setRenaming(item.id) : undefined}\n onRename={(title) => {\n setRenaming(null);\n if (onRename && title.trim() && title.trim() !== item.title)\n onRename(item.id, title.trim());\n }}\n onDelete={onDelete ? () => onDelete(item.id) : undefined}\n onPinChange={onPinChange ? (p) => onPinChange(item.id, p) : undefined}\n onKeyDown={onRowKeyDown}\n />\n );\n\n return (\n <div\n data-slot=\"chat-history\"\n aria-label={label}\n role=\"navigation\"\n className={cn('flex h-full min-h-0 flex-col', className)}\n {...props}\n >\n {(onNewChat || searchable) && (\n <div className=\"grid gap-2 p-2\">\n {onNewChat && (\n <Button variant=\"outline\" className=\"justify-start\" onClick={onNewChat}>\n <MessageSquarePlus /> New chat\n </Button>\n )}\n {searchable && (\n <label htmlFor={searchId} className=\"relative block\">\n <span className=\"sr-only\">Search chats</span>\n <Search\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <input\n id={searchId}\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search chats\"\n className=\"h-8 w-full rounded-md border border-input bg-surface pr-2 pl-8 text-base outline-none placeholder:text-muted-foreground focus-visible:border-brand focus-visible:ring-[3px] focus-visible:ring-ring/15 sm:text-sm\"\n />\n </label>\n )}\n </div>\n )}\n <div ref={list} className=\"min-h-0 flex-1 overflow-y-auto px-2 pb-2\">\n {loading ? (\n <div role=\"status\" aria-label=\"Loading chats\" className=\"grid gap-1.5 pt-1\">\n {[72, 56, 64, 48, 60].map((w, i) => (\n <div key={i} className=\"h-8 rounded-md bg-muted/70 motion-safe:animate-pulse\">\n <span className=\"sr-only\">Loading</span>\n <span\n aria-hidden\n className=\"ml-2 inline-block h-2.5 translate-y-3 rounded bg-muted-foreground/15\"\n style={{ width: `${w}%` }}\n />\n </div>\n ))}\n </div>\n ) : error ? (\n <div role=\"alert\" className=\"grid justify-items-start gap-2 p-2 text-sm\">\n <span className=\"inline-flex items-center gap-1.5 font-medium text-destructive [&_svg]:size-4\">\n <AlertCircle aria-hidden /> Chats could not load\n </span>\n <span className=\"text-muted-foreground\">{error}</span>\n {onRetry && (\n <Button size=\"sm\" variant=\"outline\" onClick={onRetry}>\n Try again\n </Button>\n )}\n </div>\n ) : items.length === 0 ? (\n <div className=\"p-3 text-sm text-muted-foreground\">\n {empty ?? 'No chats yet. Start one and it will appear here.'}\n </div>\n ) : groups.length === 0 ? (\n <p role=\"status\" className=\"p-3 text-sm text-muted-foreground\">\n No chats match &ldquo;{query}&rdquo;.\n </p>\n ) : (\n groups.map((g) => (\n <section key={g.key} aria-label={g.label} className=\"mt-2 first:mt-0\">\n <h3 className=\"px-2 pt-2 pb-1 text-[11px] font-semibold tracking-wide text-muted-foreground uppercase\">\n {g.label}\n </h3>\n <ul className=\"grid grid-cols-[minmax(0,1fr)] gap-0.5\">\n {renderItems ? renderItems(g.items, renderItem) : g.items.map(renderItem)}\n </ul>\n </section>\n ))\n )}\n </div>\n </div>\n );\n}\n\nfunction HistoryRow({\n item,\n active,\n renaming,\n onSelect,\n onStartRename,\n onRename,\n onDelete,\n onPinChange,\n onKeyDown,\n}: {\n item: ChatHistoryItem;\n active: boolean;\n renaming: boolean;\n onSelect: () => void;\n onStartRename?: () => void;\n onRename: (title: string) => void;\n onDelete?: () => void;\n onPinChange?: (pinned: boolean) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n}) {\n const hasMenu = Boolean(onStartRename || onDelete || onPinChange);\n if (renaming) return <RenameRow title={item.title} onDone={onRename} />;\n return (\n <li className=\"group/row relative min-w-0\">\n <button\n type=\"button\"\n data-slot=\"chat-history-row\"\n aria-current={active ? 'page' : undefined}\n onClick={onSelect}\n onKeyDown={onKeyDown}\n className={cn(\n 'flex h-8 w-full items-center gap-2 rounded-md px-2 text-left text-sm outline-none transition-colors hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20 pointer-coarse:h-11',\n hasMenu && 'pr-9',\n active && 'bg-accent font-medium text-accent-foreground hover:bg-accent',\n )}\n >\n <span className=\"min-w-0 flex-1 truncate\">{item.title || 'Untitled chat'}</span>\n </button>\n {hasMenu && (\n <DropdownMenu>\n <DropdownMenuTrigger\n aria-label={`Actions for ${item.title || 'chat'}`}\n className={cn(\n 'absolute top-1/2 right-1 grid size-7 -translate-y-1/2 place-items-center rounded-sm text-muted-foreground opacity-0 outline-none transition-opacity hover:bg-background hover:text-foreground focus-visible:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/20 group-hover/row:opacity-100 data-[state=open]:opacity-100 pointer-coarse:size-9 pointer-coarse:opacity-100 [&_svg]:size-4',\n active && 'opacity-100',\n )}\n >\n <MoreHorizontal aria-hidden />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-40\">\n {onStartRename && (\n <DropdownMenuItem onSelect={onStartRename}>\n <Edit aria-hidden /> Rename\n </DropdownMenuItem>\n )}\n {onPinChange && (\n <DropdownMenuItem onSelect={() => onPinChange(!item.pinned)}>\n {item.pinned ? <PinOff aria-hidden /> : <Pin aria-hidden />}\n {item.pinned ? 'Unpin' : 'Pin'}\n </DropdownMenuItem>\n )}\n {onDelete && (\n <>\n {(onStartRename || onPinChange) && <DropdownMenuSeparator />}\n <DropdownMenuItem variant=\"destructive\" onSelect={onDelete}>\n <Trash aria-hidden /> Delete\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </li>\n );\n}\n\n/** Rename in place: Enter or leaving the field saves, Escape keeps the old title. */\nfunction RenameRow({ title, onDone }: { title: string; onDone: (title: string) => void }) {\n const [draft, setDraft] = React.useState(title);\n const input = React.useRef<HTMLInputElement>(null);\n React.useEffect(() => {\n input.current?.select();\n }, []);\n return (\n <li className=\"px-1 py-0.5\">\n <input\n ref={input}\n aria-label=\"Chat title\"\n value={draft}\n // eslint-disable-next-line jsx-a11y/no-autofocus -- rename was just asked for\n autoFocus\n onChange={(e) => setDraft(e.target.value)}\n onBlur={() => onDone(draft)}\n onKeyDown={(e) => {\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return;\n if (e.key === 'Enter') {\n e.preventDefault();\n onDone(draft);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onDone(title);\n }\n }}\n className=\"h-8 w-full rounded-md border border-brand bg-surface px-2 text-base ring-[3px] ring-ring/15 outline-none sm:text-sm\"\n />\n </li>\n );\n}\n\nexport { ChatHistory };\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat-history.js","names":["_Fragment"],"sources":["../../src/components/chat-history.tsx"],"sourcesContent":["import AlertCircle from '@burtson-labs/icons/react/alert-circle';\nimport Edit from '@burtson-labs/icons/react/edit';\nimport MessageSquarePlus from '@burtson-labs/icons/react/message-square-plus';\nimport MoreHorizontal from '@burtson-labs/icons/react/more-horizontal';\nimport Pin from '@burtson-labs/icons/react/pin';\nimport PinOff from '@burtson-labs/icons/react/pin-off';\nimport Search from '@burtson-labs/icons/react/search';\nimport Trash from '@burtson-labs/icons/react/trash';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Button } from './button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from './dropdown-menu';\nimport { fieldFocusClasses } from './input';\n\nexport interface ChatHistoryItem {\n id: string;\n title: string;\n /** When the conversation last changed; decides its group. */\n updatedAt: Date | string | number;\n pinned?: boolean;\n /** A line of the latest message, searched along with the title. */\n preview?: string;\n}\n\nexport type ChatHistoryGroupKey = 'pinned' | 'today' | 'yesterday' | 'week' | 'older';\n\nexport interface ChatHistoryGroup {\n key: ChatHistoryGroupKey;\n label: string;\n items: ChatHistoryItem[];\n}\n\nconst LABELS: Record<ChatHistoryGroupKey, string> = {\n pinned: 'Pinned',\n today: 'Today',\n yesterday: 'Yesterday',\n week: 'Previous 7 days',\n older: 'Older',\n};\n\nconst time = (d: ChatHistoryItem['updatedAt']) => new Date(d).getTime();\nconst startOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();\n\n/**\n * Pinned first, then Today, Yesterday, Previous 7 days and Older by the\n * local calendar, newest first in each. Empty groups are left out.\n */\nexport function groupConversations(\n items: ChatHistoryItem[],\n now: Date = new Date(),\n): ChatHistoryGroup[] {\n const today = startOfDay(now);\n const day = 24 * 60 * 60 * 1000;\n const buckets: Record<ChatHistoryGroupKey, ChatHistoryItem[]> = {\n pinned: [],\n today: [],\n yesterday: [],\n week: [],\n older: [],\n };\n for (const item of [...items].sort((a, b) => time(b.updatedAt) - time(a.updatedAt))) {\n if (item.pinned) {\n buckets.pinned.push(item);\n continue;\n }\n const t = startOfDay(new Date(item.updatedAt));\n const key: ChatHistoryGroupKey =\n t >= today\n ? 'today'\n : t >= today - day\n ? 'yesterday'\n : t >= today - 7 * day\n ? 'week'\n : 'older';\n buckets[key].push(item);\n }\n return (Object.keys(buckets) as ChatHistoryGroupKey[])\n .filter((k) => buckets[k].length > 0)\n .map((k) => ({ key: k, label: LABELS[k], items: buckets[k] }));\n}\n\n/** Case-insensitive match on every word, across title and preview. */\nexport function matchesConversation(item: ChatHistoryItem, query: string): boolean {\n const hay = `${item.title} ${item.preview ?? ''}`.toLowerCase();\n return query\n .toLowerCase()\n .split(/\\s+/)\n .filter(Boolean)\n .every((w) => hay.includes(w));\n}\n\nexport interface ChatHistoryProps extends Omit<React.ComponentProps<'div'>, 'onSelect'> {\n items: ChatHistoryItem[];\n activeId?: string;\n onSelect: (id: string) => void;\n /** Shows a \"New chat\" button at the top. */\n onNewChat?: () => void;\n /** Adds Rename to the row menu; the title is edited in place. */\n onRename?: (id: string, title: string) => void;\n /** Adds Delete to the row menu. Confirm or offer undo in your app. */\n onDelete?: (id: string) => void;\n /** Adds Pin / Unpin to the row menu. */\n onPinChange?: (id: string, pinned: boolean) => void;\n /** Controlled search text; leave out to let the list keep its own. */\n query?: string;\n onQueryChange?: (query: string) => void;\n /** Hides the search box, e.g. when the app searches on the server. */\n searchable?: boolean;\n loading?: boolean;\n /** Why the list could not load. Shown with Retry when `onRetry` is set. */\n error?: React.ReactNode;\n onRetry?: () => void;\n /** Shown when there are no conversations at all. */\n empty?: React.ReactNode;\n /** The clock grouping uses; pass it in tests. */\n now?: Date;\n /**\n * Virtualisation hook for long histories: receives a group's items and the\n * row renderer, returns what to render (e.g. a windowed list). Default\n * renders every row.\n */\n renderItems?: (\n items: ChatHistoryItem[],\n renderItem: (item: ChatHistoryItem) => React.ReactNode,\n ) => React.ReactNode;\n label?: string;\n}\n\n/**\n * The conversation list beside a chat: a New chat action, search, and the\n * history grouped by day with pinned chats on top. Up and Down move between\n * rows, Home and End jump, Enter opens; each row has a menu for rename, pin\n * and delete. The app owns the data; this only reports what the person did.\n */\nfunction ChatHistory({\n items,\n activeId,\n onSelect,\n onNewChat,\n onRename,\n onDelete,\n onPinChange,\n query: controlledQuery,\n onQueryChange,\n searchable = true,\n loading = false,\n error,\n onRetry,\n empty,\n now,\n renderItems,\n label = 'Chat history',\n className,\n ...props\n}: ChatHistoryProps) {\n const [ownQuery, setOwnQuery] = React.useState('');\n const query = controlledQuery ?? ownQuery;\n const setQuery = (q: string) => {\n if (controlledQuery === undefined) setOwnQuery(q);\n onQueryChange?.(q);\n };\n const [renaming, setRenaming] = React.useState<string | null>(null);\n const list = React.useRef<HTMLDivElement>(null);\n const searchId = React.useId();\n\n const visible = query.trim() ? items.filter((i) => matchesConversation(i, query)) : items;\n const groups = groupConversations(visible, now);\n\n const onRowKeyDown = (e: React.KeyboardEvent) => {\n const rows = Array.from(\n list.current?.querySelectorAll<HTMLElement>('[data-slot=\"chat-history-row\"]') ?? [],\n );\n const i = rows.indexOf(document.activeElement as HTMLElement);\n let next = -1;\n if (e.key === 'ArrowDown') next = Math.min(rows.length - 1, i + 1);\n else if (e.key === 'ArrowUp') next = Math.max(0, i - 1);\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = rows.length - 1;\n const row = next >= 0 ? rows[next] : undefined;\n if (row) {\n e.preventDefault();\n row.focus();\n }\n };\n\n const renderItem = (item: ChatHistoryItem) => (\n <HistoryRow\n key={item.id}\n item={item}\n active={item.id === activeId}\n renaming={renaming === item.id}\n onSelect={() => onSelect(item.id)}\n onStartRename={onRename ? () => setRenaming(item.id) : undefined}\n onRename={(title) => {\n setRenaming(null);\n if (onRename && title.trim() && title.trim() !== item.title)\n onRename(item.id, title.trim());\n }}\n onDelete={onDelete ? () => onDelete(item.id) : undefined}\n onPinChange={onPinChange ? (p) => onPinChange(item.id, p) : undefined}\n onKeyDown={onRowKeyDown}\n />\n );\n\n return (\n <div\n data-slot=\"chat-history\"\n aria-label={label}\n role=\"navigation\"\n className={cn('flex h-full min-h-0 flex-col', className)}\n {...props}\n >\n {(onNewChat || searchable) && (\n <div className=\"grid gap-2 p-2\">\n {onNewChat && (\n <Button variant=\"outline\" className=\"justify-start\" onClick={onNewChat}>\n <MessageSquarePlus /> New chat\n </Button>\n )}\n {searchable && (\n <label htmlFor={searchId} className=\"relative block\">\n <span className=\"sr-only\">Search chats</span>\n <Search\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <input\n id={searchId}\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search chats\"\n className={cn(\n 'h-8 w-full rounded-md border border-input bg-surface pr-2 pl-8 text-base placeholder:text-muted-foreground sm:text-sm',\n fieldFocusClasses,\n )}\n />\n </label>\n )}\n </div>\n )}\n <div ref={list} className=\"min-h-0 flex-1 overflow-y-auto px-2 pb-2\">\n {loading ? (\n <div role=\"status\" aria-label=\"Loading chats\" className=\"grid gap-1.5 pt-1\">\n {[72, 56, 64, 48, 60].map((w, i) => (\n <div key={i} className=\"h-8 rounded-md bg-muted/70 motion-safe:animate-pulse\">\n <span className=\"sr-only\">Loading</span>\n <span\n aria-hidden\n className=\"ml-2 inline-block h-2.5 translate-y-3 rounded bg-muted-foreground/15\"\n style={{ width: `${w}%` }}\n />\n </div>\n ))}\n </div>\n ) : error ? (\n <div role=\"alert\" className=\"grid justify-items-start gap-2 p-2 text-sm\">\n <span className=\"inline-flex items-center gap-1.5 font-medium text-destructive [&_svg]:size-4\">\n <AlertCircle aria-hidden /> Chats could not load\n </span>\n <span className=\"text-muted-foreground\">{error}</span>\n {onRetry && (\n <Button size=\"sm\" variant=\"outline\" onClick={onRetry}>\n Try again\n </Button>\n )}\n </div>\n ) : items.length === 0 ? (\n <div className=\"p-3 text-sm text-muted-foreground\">\n {empty ?? 'No chats yet. Start one and it will appear here.'}\n </div>\n ) : groups.length === 0 ? (\n <p role=\"status\" className=\"p-3 text-sm text-muted-foreground\">\n No chats match &ldquo;{query}&rdquo;.\n </p>\n ) : (\n groups.map((g) => (\n <section key={g.key} aria-label={g.label} className=\"mt-2 first:mt-0\">\n <h3 className=\"px-2 pt-2 pb-1 text-[11px] font-semibold tracking-wide text-muted-foreground uppercase\">\n {g.label}\n </h3>\n <ul className=\"grid grid-cols-[minmax(0,1fr)] gap-0.5\">\n {renderItems ? renderItems(g.items, renderItem) : g.items.map(renderItem)}\n </ul>\n </section>\n ))\n )}\n </div>\n </div>\n );\n}\n\nfunction HistoryRow({\n item,\n active,\n renaming,\n onSelect,\n onStartRename,\n onRename,\n onDelete,\n onPinChange,\n onKeyDown,\n}: {\n item: ChatHistoryItem;\n active: boolean;\n renaming: boolean;\n onSelect: () => void;\n onStartRename?: () => void;\n onRename: (title: string) => void;\n onDelete?: () => void;\n onPinChange?: (pinned: boolean) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n}) {\n const hasMenu = Boolean(onStartRename || onDelete || onPinChange);\n if (renaming) return <RenameRow title={item.title} onDone={onRename} />;\n return (\n <li className=\"group/row relative min-w-0\">\n <button\n type=\"button\"\n data-slot=\"chat-history-row\"\n aria-current={active ? 'page' : undefined}\n onClick={onSelect}\n onKeyDown={onKeyDown}\n className={cn(\n 'flex h-8 w-full items-center gap-2 rounded-md px-2 text-left text-sm outline-none transition-colors hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20 pointer-coarse:h-11',\n hasMenu && 'pr-9',\n active && 'bg-accent font-medium text-accent-foreground hover:bg-accent',\n )}\n >\n <span className=\"min-w-0 flex-1 truncate\">{item.title || 'Untitled chat'}</span>\n </button>\n {hasMenu && (\n <DropdownMenu>\n <DropdownMenuTrigger\n aria-label={`Actions for ${item.title || 'chat'}`}\n className={cn(\n 'absolute top-1/2 right-1 grid size-7 -translate-y-1/2 place-items-center rounded-sm text-muted-foreground opacity-0 outline-none transition-opacity hover:bg-background hover:text-foreground focus-visible:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/20 group-hover/row:opacity-100 data-[state=open]:opacity-100 pointer-coarse:size-9 pointer-coarse:opacity-100 [&_svg]:size-4',\n active && 'opacity-100',\n )}\n >\n <MoreHorizontal aria-hidden />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-40\">\n {onStartRename && (\n <DropdownMenuItem onSelect={onStartRename}>\n <Edit aria-hidden /> Rename\n </DropdownMenuItem>\n )}\n {onPinChange && (\n <DropdownMenuItem onSelect={() => onPinChange(!item.pinned)}>\n {item.pinned ? <PinOff aria-hidden /> : <Pin aria-hidden />}\n {item.pinned ? 'Unpin' : 'Pin'}\n </DropdownMenuItem>\n )}\n {onDelete && (\n <>\n {(onStartRename || onPinChange) && <DropdownMenuSeparator />}\n <DropdownMenuItem variant=\"destructive\" onSelect={onDelete}>\n <Trash aria-hidden /> Delete\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </li>\n );\n}\n\n/** Rename in place: Enter or leaving the field saves, Escape keeps the old title. */\nfunction RenameRow({ title, onDone }: { title: string; onDone: (title: string) => void }) {\n const [draft, setDraft] = React.useState(title);\n const input = React.useRef<HTMLInputElement>(null);\n React.useEffect(() => {\n input.current?.select();\n }, []);\n return (\n <li className=\"px-1 py-0.5\">\n <input\n ref={input}\n aria-label=\"Chat title\"\n value={draft}\n // eslint-disable-next-line jsx-a11y/no-autofocus -- rename was just asked for\n autoFocus\n onChange={(e) => setDraft(e.target.value)}\n onBlur={() => onDone(draft)}\n onKeyDown={(e) => {\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return;\n if (e.key === 'Enter') {\n e.preventDefault();\n onDone(draft);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onDone(title);\n }\n }}\n className=\"h-8 w-full rounded-md border border-ring bg-surface px-2 text-base inset-ring-1 inset-ring-ring outline-hidden! sm:text-sm\"\n />\n </li>\n );\n}\n\nexport { ChatHistory };\n"],"mappings":";;;;;;;;;;;;;;;AAwCA,IAAM,SAA8C;CAClD,QAAQ;CACR,OAAO;CACP,WAAW;CACX,MAAM;CACN,OAAO;AACT;AAEA,IAAM,QAAQ,MAAoC,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ;AACtE,IAAM,cAAc,MAAY,IAAI,KAAK,EAAE,YAAY,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ;;;;;AAM7F,SAAgB,mBACd,OACA,sBAAY,IAAI,KAAK,GACD;CACpB,MAAM,QAAQ,WAAW,GAAG;CAC5B,MAAM,MAAM;CACZ,MAAM,UAA0D;EAC9D,QAAQ,CAAC;EACT,OAAO,CAAC;EACR,WAAW,CAAC;EACZ,MAAM,CAAC;EACP,OAAO,CAAC;CACV;CACA,KAAK,MAAM,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,KAAK,EAAE,SAAS,IAAI,KAAK,EAAE,SAAS,CAAC,GAAG;EACnF,IAAI,KAAK,QAAQ;GACf,QAAQ,OAAO,KAAK,IAAI;GACxB;EACF;EACA,MAAM,IAAI,WAAW,IAAI,KAAK,KAAK,SAAS,CAAC;EAS7C,QAPE,KAAK,QACD,UACA,KAAK,QAAQ,MACX,cACA,KAAK,QAAQ,IAAI,MACf,SACA,QACE,CAAC,KAAK,IAAI;CACxB;CACA,OAAQ,OAAO,KAAK,OAAO,CAAC,CACzB,QAAQ,MAAM,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAC,CACpC,KAAK,OAAO;EAAE,KAAK;EAAG,OAAO,OAAO;EAAI,OAAO,QAAQ;CAAG,EAAE;AACjE;;AAGA,SAAgB,oBAAoB,MAAuB,OAAwB;CACjF,MAAM,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,WAAW,KAAK,YAAY;CAC9D,OAAO,MACJ,YAAY,CAAC,CACb,MAAM,KAAK,CAAC,CACZ,OAAO,OAAO,CAAC,CACf,OAAO,MAAM,IAAI,SAAS,CAAC,CAAC;AACjC;;;;;;;AA6CA,SAAS,YAAY,EACnB,OACA,UACA,UACA,WACA,UACA,UACA,aACA,OAAO,iBACP,eACA,aAAa,MACb,UAAU,OACV,OACA,SACA,OACA,KACA,aACA,QAAQ,gBACR,WACA,GAAG,SACgB;CACnB,MAAM,CAAC,UAAU,eAAe,MAAM,SAAS,EAAE;CACjD,MAAM,QAAQ,mBAAmB;CACjC,MAAM,YAAY,MAAc;EAC9B,IAAI,oBAAoB,KAAA,GAAW,YAAY,CAAC;EAChD,gBAAgB,CAAC;CACnB;CACA,MAAM,CAAC,UAAU,eAAe,MAAM,SAAwB,IAAI;CAClE,MAAM,OAAO,MAAM,OAAuB,IAAI;CAC9C,MAAM,WAAW,MAAM,MAAM;CAG7B,MAAM,SAAS,mBADC,MAAM,KAAK,IAAI,MAAM,QAAQ,MAAM,oBAAoB,GAAG,KAAK,CAAC,IAAI,OACzC,GAAG;CAE9C,MAAM,gBAAgB,MAA2B;EAC/C,MAAM,OAAO,MAAM,KACjB,KAAK,SAAS,iBAA8B,kCAAgC,KAAK,CAAC,CACpF;EACA,MAAM,IAAI,KAAK,QAAQ,SAAS,aAA4B;EAC5D,IAAI,OAAO;EACX,IAAI,EAAE,QAAQ,aAAa,OAAO,KAAK,IAAI,KAAK,SAAS,GAAG,IAAI,CAAC;OAC5D,IAAI,EAAE,QAAQ,WAAW,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;OACjD,IAAI,EAAE,QAAQ,QAAQ,OAAO;OAC7B,IAAI,EAAE,QAAQ,OAAO,OAAO,KAAK,SAAS;EAC/C,MAAM,MAAM,QAAQ,IAAI,KAAK,QAAQ,KAAA;EACrC,IAAI,KAAK;GACP,EAAE,eAAe;GACjB,IAAI,MAAM;EACZ;CACF;CAEA,MAAM,cAAc,SAClB,oBAAC,YAAD;EAEQ;EACN,QAAQ,KAAK,OAAO;EACpB,UAAU,aAAa,KAAK;EAC5B,gBAAgB,SAAS,KAAK,EAAE;EAChC,eAAe,iBAAiB,YAAY,KAAK,EAAE,IAAI,KAAA;EACvD,WAAW,UAAU;GACnB,YAAY,IAAI;GAChB,IAAI,YAAY,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,OACpD,SAAS,KAAK,IAAI,MAAM,KAAK,CAAC;EAClC;EACA,UAAU,iBAAiB,SAAS,KAAK,EAAE,IAAI,KAAA;EAC/C,aAAa,eAAe,MAAM,YAAY,KAAK,IAAI,CAAC,IAAI,KAAA;EAC5D,WAAW;CACZ,GAdM,KAAK,EAcX;CAGH,OACE,qBAAC,OAAD;EACE,aAAU;EACV,cAAY;EACZ,MAAK;EACL,WAAW,GAAG,gCAAgC,SAAS;EACvD,GAAI;EALN,UAAA,EAOI,aAAa,eACb,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,aACC,qBAAC,QAAD;IAAQ,SAAQ;IAAU,WAAU;IAAgB,SAAS;IAA7D,UAAA,CACE,oBAAC,mBAAD,CAAoB,CAAA,GAAC,WACf;GAET,CAAA,GAAA,cACC,qBAAC,SAAD;IAAO,SAAS;IAAU,WAAU;IAApC,UAAA;KACE,oBAAC,QAAD;MAAM,WAAU;MAAU,UAAA;KAAkB,CAAA;KAC5C,oBAAC,QAAD;MACE,eAAA;MACA,WAAU;KACX,CAAA;KACD,oBAAC,SAAD;MACE,IAAI;MACJ,MAAK;MACL,OAAO;MACP,WAAW,MAAM,SAAS,EAAE,OAAO,KAAK;MACxC,aAAY;MACZ,WAAW,GACT,yHAAA,sJAEF;KACD,CAAA;IACI;GAEN,CAAA,CAAA;EAEP,CAAA,GAAA,oBAAC,OAAD;GAAK,KAAK;GAAM,WAAU;GACvB,UAAA,UACC,oBAAC,OAAD;IAAK,MAAK;IAAS,cAAW;IAAgB,WAAU;IACrD,UAAA;KAAC;KAAI;KAAI;KAAI;KAAI;IAAE,CAAC,CAAC,KAAK,GAAG,MAC5B,qBAAC,OAAD;KAAa,WAAU;KAAvB,UAAA,CACE,oBAAC,QAAD;MAAM,WAAU;MAAU,UAAA;KAAa,CAAA,GACvC,oBAAC,QAAD;MACE,eAAA;MACA,WAAU;MACV,OAAO,EAAE,OAAO,GAAG,EAAE,GAAG;KACzB,CAAA,CACE;IAPK,GAAA,CAOL,CACN;GACE,CAAA,IACH,QACF,qBAAC,OAAD;IAAK,MAAK;IAAQ,WAAU;IAA5B,UAAA;KACE,qBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACE,oBAAC,aAAD,EAAa,eAAA,KAAa,CAAA,GAAC,uBACvB;;KACN,oBAAC,QAAD;MAAM,WAAU;MAAyB,UAAA;KAAY,CAAA;KACpD,WACC,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAU,SAAS;MAAS,UAAA;KAE9C,CAAA;IAEP;GACH,CAAA,IAAA,MAAM,WAAW,IACnB,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,SAAS;GACP,CAAA,IACH,OAAO,WAAW,IACpB,qBAAC,KAAD;IAAG,MAAK;IAAS,WAAU;IAA3B,UAAA;KAA+D;KACtC;KAAM;IAC5B;GAEH,CAAA,IAAA,OAAO,KAAK,MACV,qBAAC,WAAD;IAAqB,cAAY,EAAE;IAAO,WAAU;IAApD,UAAA,CACE,oBAAC,MAAD;KAAI,WAAU;KACX,UAAA,EAAE;IACD,CAAA,GACJ,oBAAC,MAAD;KAAI,WAAU;KACX,UAAA,cAAc,YAAY,EAAE,OAAO,UAAU,IAAI,EAAE,MAAM,IAAI,UAAU;IACtE,CAAA,CACG;GAPK,GAAA,EAAE,GAOP,CACV;EAEA,CAAA,CACF;;AAET;AAEA,SAAS,WAAW,EAClB,MACA,QACA,UACA,UACA,eACA,UACA,UACA,aACA,aAWC;CACD,MAAM,UAAU,QAAQ,iBAAiB,YAAY,WAAW;CAChE,IAAI,UAAU,OAAO,oBAAC,WAAD;EAAW,OAAO,KAAK;EAAO,QAAQ;CAAW,CAAA;CACtE,OACE,qBAAC,MAAD;EAAI,WAAU;EAAd,UAAA,CACE,oBAAC,UAAD;GACE,MAAK;GACL,aAAU;GACV,gBAAc,SAAS,SAAS,KAAA;GAChC,SAAS;GACE;GACX,WAAW,GACT,8LACA,WAAW,QACX,UAAU,8DACZ;GAEA,UAAA,oBAAC,QAAD;IAAM,WAAU;IAA2B,UAAA,KAAK,SAAS;GAAsB,CAAA;EACzE,CAAA,GACP,WACC,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,qBAAD;GACE,cAAY,eAAe,KAAK,SAAS;GACzC,WAAW,GACT,yYACA,UAAU,aACZ;GAEA,UAAA,oBAAC,gBAAD,EAAgB,eAAA,KAAa,CAAA;EACV,CAAA,GACrB,qBAAC,qBAAD;GAAqB,OAAM;GAAM,WAAU;GAA3C,UAAA;IACG,iBACC,qBAAC,kBAAD;KAAkB,UAAU;KAA5B,UAAA,CACE,oBAAC,MAAD,EAAM,eAAA,KAAa,CAAA,GAAC,SACJ;;IAEnB,eACC,qBAAC,kBAAD;KAAkB,gBAAgB,YAAY,CAAC,KAAK,MAAM;KAA1D,UAAA,CACG,KAAK,SAAS,oBAAC,QAAD,EAAQ,eAAA,KAAa,CAAA,IAAI,oBAAC,KAAD,EAAK,eAAA,KAAa,CAAA,GACzD,KAAK,SAAS,UAAU,KACT;;IAEnB,YACC,qBAAAA,UAAA,EAAA,UAAA,EACI,iBAAiB,gBAAgB,oBAAC,uBAAD,CAAwB,CAAA,GAC3D,qBAAC,kBAAD;KAAkB,SAAQ;KAAc,UAAU;KAAlD,UAAA,CACE,oBAAC,OAAD,EAAO,eAAA,KAAa,CAAA,GAAC,SACL;IAClB,CAAA,CAAA,EAAA,CAAA;GAEe;EACT,CAAA,CAAA,EAAA,CAAA,CAEd;;AAER;;AAGA,SAAS,UAAU,EAAE,OAAO,UAA8D;CACxF,MAAM,CAAC,OAAO,YAAY,MAAM,SAAS,KAAK;CAC9C,MAAM,QAAQ,MAAM,OAAyB,IAAI;CACjD,MAAM,gBAAgB;EACpB,MAAM,SAAS,OAAO;CACxB,GAAG,CAAC,CAAC;CACL,OACE,oBAAC,MAAD;EAAI,WAAU;EACZ,UAAA,oBAAC,SAAD;GACE,KAAK;GACL,cAAW;GACX,OAAO;GAEP,WAAA;GACA,WAAW,MAAM,SAAS,EAAE,OAAO,KAAK;GACxC,cAAc,OAAO,KAAK;GAC1B,YAAY,MAAM;IAChB,IAAI,EAAE,YAAY,eAAe,EAAE,YAAY,YAAY,KAAK;IAChE,IAAI,EAAE,QAAQ,SAAS;KACrB,EAAE,eAAe;KACjB,OAAO,KAAK;IACd,OAAO,IAAI,EAAE,QAAQ,UAAU;KAC7B,EAAE,eAAe;KACjB,OAAO,KAAK;IACd;GACF;GACA,WAAU;EACX,CAAA;CACC,CAAA;AAER"}
@@ -1,8 +1,8 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import { Spinner } from "./spinner.js";
3
3
  import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
4
- import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "./command.js";
5
4
  import { fieldClasses } from "./input.js";
5
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "./command.js";
6
6
  import * as React from "react";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import Check from "@burtson-labs/icons/react/check";
@@ -8,7 +8,7 @@ import { Command } from "cmdk";
8
8
  function Command$1({ className, ...props }) {
9
9
  return /* @__PURE__ */ jsx(Command, {
10
10
  "data-slot": "command",
11
- className: cn("flex h-full w-full flex-col overflow-hidden rounded-lg bg-surface-raised text-popover-foreground", className),
11
+ className: cn("flex h-full w-full flex-col overflow-hidden rounded-lg bg-surface-raised text-popover-foreground has-[[cmdk-input]:focus-visible]:border-ring", className),
12
12
  ...props
13
13
  });
14
14
  }
@@ -38,7 +38,7 @@ function CommandInput({ className, ...props }) {
38
38
  "aria-hidden": true
39
39
  }), /* @__PURE__ */ jsx(Command.Input, {
40
40
  "data-slot": "command-input",
41
- className: cn("flex h-10 w-full bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", className),
41
+ className: cn("flex h-10 w-full rounded-none border-0 bg-transparent py-3 text-sm shadow-none outline-hidden! placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", className),
42
42
  ...props
43
43
  })]
44
44
  });
@@ -60,7 +60,7 @@ function CommandEmpty(props) {
60
60
  function CommandGroup({ className, ...props }) {
61
61
  return /* @__PURE__ */ jsx(Command.Group, {
62
62
  "data-slot": "command-group",
63
- className: cn("overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", className),
63
+ className: cn("overflow-hidden py-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", className),
64
64
  ...props
65
65
  });
66
66
  }
@@ -74,7 +74,7 @@ function CommandSeparator({ className, ...props }) {
74
74
  function CommandItem({ className, ...props }) {
75
75
  return /* @__PURE__ */ jsx(Command.Item, {
76
76
  "data-slot": "command-item",
77
- className: cn("relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-muted data-[selected=true]:text-foreground data-[selected=true]:shadow-[inset_2px_0_0_var(--color-brand)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground", className),
77
+ className: cn("relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden! select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-secondary data-[selected=true]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground", className),
78
78
  ...props
79
79
  });
80
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","names":["Command","CommandPrimitive"],"sources":["../../src/components/command.tsx"],"sourcesContent":["import Search from '@burtson-labs/icons/react/search';\nimport { Command as CommandPrimitive } from 'cmdk';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './dialog';\n\nfunction Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n 'flex h-full w-full flex-col overflow-hidden rounded-lg bg-surface-raised text-popover-foreground',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** A command palette in a dialog, the usual ⌘K surface. */\nfunction CommandDialog({\n title = 'Command palette',\n description = 'Search for a page or an action',\n children,\n className,\n ...props\n}: React.ComponentProps<typeof Dialog> & {\n title?: string;\n description?: string;\n className?: string;\n}) {\n return (\n <Dialog {...props}>\n <DialogContent\n className={cn(\n 'top-[20%] translate-y-0 gap-0 overflow-hidden p-0 sm:max-w-xl sm:p-0',\n className,\n )}\n showCloseButton={false}\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <Command className=\"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-2\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction CommandInput({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n return (\n <div data-slot=\"command-input-wrapper\" className=\"flex h-11 items-center gap-2 border-b px-3\">\n <Search className=\"size-4 shrink-0 opacity-50\" aria-hidden />\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n 'flex h-10 w-full bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n />\n </div>\n );\n}\n\nfunction CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn('max-h-80 scroll-py-1 overflow-x-hidden overflow-y-auto p-1', className)}\n {...props}\n />\n );\n}\n\nfunction CommandEmpty(props: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n data-slot=\"command-empty\"\n className=\"py-6 text-center text-sm text-muted-foreground\"\n {...props}\n />\n );\n}\n\nfunction CommandGroup({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\n 'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CommandSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn('-mx-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-muted data-[selected=true]:text-foreground data-[selected=true]:shadow-[inset_2px_0_0_var(--color-brand)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CommandShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\n 'ml-auto rounded-xs border border-border bg-surface-muted px-1.5 font-mono text-[11px] leading-5 text-muted-foreground',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Command,\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n};\n"],"mappings":";;;;;;;AAQA,SAASA,UAAQ,EAAE,WAAW,GAAG,SAAwD;CACvF,OACE,oBAACC,SAAD;EACE,aAAU;EACV,WAAW,GACT,oGACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;;AAGA,SAAS,cAAc,EACrB,QAAQ,mBACR,cAAc,kCACd,UACA,WACA,GAAG,SAKF;CACD,OACE,oBAAC,QAAD;EAAQ,GAAI;EACV,UAAA,qBAAC,eAAD;GACE,WAAW,GACT,wEACA,SACF;GACA,iBAAiB;GALnB,UAAA,CAOE,qBAAC,cAAD;IAAc,WAAU;IAAxB,UAAA,CACE,oBAAC,aAAD,EAAA,UAAc,MAAmB,CAAA,GACjC,oBAAC,mBAAD,EAAA,UAAoB,YAA+B,CAAA,CACvC;GACd,CAAA,GAAA,oBAACD,WAAD;IAAS,WAAU;IAChB;GACM,CAAA,CACI;;CACT,CAAA;AAEZ;AAEA,SAAS,aAAa,EACpB,WACA,GAAG,SACmD;CACtD,OACE,qBAAC,OAAD;EAAK,aAAU;EAAwB,WAAU;EAAjD,UAAA,CACE,oBAAC,QAAD;GAAQ,WAAU;GAA6B,eAAA;EAAa,CAAA,GAC5D,oBAACC,QAAiB,OAAlB;GACE,aAAU;GACV,WAAW,GACT,iJACA,SACF;GACA,GAAI;EACL,CAAA,CACE;;AAET;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACA,QAAiB,MAAlB;EACE,aAAU;EACV,WAAW,GAAG,8DAA8D,SAAS;EACrF,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,OAA4D;CAChF,OACE,oBAACA,QAAiB,OAAlB;EACE,aAAU;EACV,WAAU;EACV,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,EACpB,WACA,GAAG,SACmD;CACtD,OACE,oBAACA,QAAiB,OAAlB;EACE,aAAU;EACV,WAAW,GACT,0NACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,iBAAiB,EACxB,WACA,GAAG,SACuD;CAC1D,OACE,oBAACA,QAAiB,WAAlB;EACE,aAAU;EACV,WAAW,GAAG,wBAAwB,SAAS;EAC/C,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACA,QAAiB,MAAlB;EACE,aAAU;EACV,WAAW,GACT,mcACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAAuC;CAC9E,OACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GACT,yHACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"command.js","names":["Command","CommandPrimitive"],"sources":["../../src/components/command.tsx"],"sourcesContent":["import Search from '@burtson-labs/icons/react/search';\nimport { Command as CommandPrimitive } from 'cmdk';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './dialog';\n\nfunction Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n // Standalone with a border, the box is the field: its border takes the\n // ring colour while the search input has keyboard focus. In a popover or\n // dialog there is no border of its own, so the rule draws nothing.\n 'flex h-full w-full flex-col overflow-hidden rounded-lg bg-surface-raised text-popover-foreground has-[[cmdk-input]:focus-visible]:border-ring',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** A command palette in a dialog, the usual ⌘K surface. */\nfunction CommandDialog({\n title = 'Command palette',\n description = 'Search for a page or an action',\n children,\n className,\n ...props\n}: React.ComponentProps<typeof Dialog> & {\n title?: string;\n description?: string;\n className?: string;\n}) {\n return (\n <Dialog {...props}>\n <DialogContent\n className={cn(\n 'top-[20%] translate-y-0 gap-0 overflow-hidden p-0 sm:max-w-xl sm:p-0',\n className,\n )}\n showCloseButton={false}\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <Command className=\"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-2\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction CommandInput({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n return (\n // The row is the field (icon + input, ruled off from the list); the input\n // itself draws no border or outline, whatever the host page's CSS says.\n <div data-slot=\"command-input-wrapper\" className=\"flex h-11 items-center gap-2 border-b px-3\">\n <Search className=\"size-4 shrink-0 opacity-50\" aria-hidden />\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n 'flex h-10 w-full rounded-none border-0 bg-transparent py-3 text-sm shadow-none outline-hidden! placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n />\n </div>\n );\n}\n\nfunction CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn('max-h-80 scroll-py-1 overflow-x-hidden overflow-y-auto p-1', className)}\n {...props}\n />\n );\n}\n\nfunction CommandEmpty(props: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n data-slot=\"command-empty\"\n className=\"py-6 text-center text-sm text-muted-foreground\"\n {...props}\n />\n );\n}\n\nfunction CommandGroup({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\n 'overflow-hidden py-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CommandSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn('-mx-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden! select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-secondary data-[selected=true]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CommandShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\n 'ml-auto rounded-xs border border-border bg-surface-muted px-1.5 font-mono text-[11px] leading-5 text-muted-foreground',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Command,\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n};\n"],"mappings":";;;;;;;AAQA,SAASA,UAAQ,EAAE,WAAW,GAAG,SAAwD;CACvF,OACE,oBAACC,SAAD;EACE,aAAU;EACV,WAAW,GAIT,iJACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;;AAGA,SAAS,cAAc,EACrB,QAAQ,mBACR,cAAc,kCACd,UACA,WACA,GAAG,SAKF;CACD,OACE,oBAAC,QAAD;EAAQ,GAAI;EACV,UAAA,qBAAC,eAAD;GACE,WAAW,GACT,wEACA,SACF;GACA,iBAAiB;GALnB,UAAA,CAOE,qBAAC,cAAD;IAAc,WAAU;IAAxB,UAAA,CACE,oBAAC,aAAD,EAAA,UAAc,MAAmB,CAAA,GACjC,oBAAC,mBAAD,EAAA,UAAoB,YAA+B,CAAA,CACvC;GACd,CAAA,GAAA,oBAACD,WAAD;IAAS,WAAU;IAChB;GACM,CAAA,CACI;;CACT,CAAA;AAEZ;AAEA,SAAS,aAAa,EACpB,WACA,GAAG,SACmD;CACtD,OAGE,qBAAC,OAAD;EAAK,aAAU;EAAwB,WAAU;EAAjD,UAAA,CACE,oBAAC,QAAD;GAAQ,WAAU;GAA6B,eAAA;EAAa,CAAA,GAC5D,oBAACC,QAAiB,OAAlB;GACE,aAAU;GACV,WAAW,GACT,oLACA,SACF;GACA,GAAI;EACL,CAAA,CACE;;AAET;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACA,QAAiB,MAAlB;EACE,aAAU;EACV,WAAW,GAAG,8DAA8D,SAAS;EACrF,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,OAA4D;CAChF,OACE,oBAACA,QAAiB,OAAlB;EACE,aAAU;EACV,WAAU;EACV,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,EACpB,WACA,GAAG,SACmD;CACtD,OACE,oBAACA,QAAiB,OAAlB;EACE,aAAU;EACV,WAAW,GACT,2NACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,iBAAiB,EACxB,WACA,GAAG,SACuD;CAC1D,OACE,oBAACA,QAAiB,WAAlB;EACE,aAAU;EACV,WAAW,GAAG,wBAAwB,SAAS;EAC/C,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACA,QAAiB,MAAlB;EACE,aAAU;EACV,WAAW,GACT,yYACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAAuC;CAC9E,OACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GACT,yHACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
@@ -97,7 +97,7 @@ function Composer({ onSubmit, onSubmitError, submitErrorText = "Message could no
97
97
  setDragging(false);
98
98
  attach(e.dataTransfer?.files);
99
99
  },
100
- className: cn("relative grid gap-2 rounded-lg border border-input bg-surface p-2 shadow-xs transition-[border-color,box-shadow] focus-within:border-brand focus-within:ring-[3px] focus-within:ring-ring/15 dark:bg-surface-raised", "data-[dragging]:border-brand data-[dragging]:ring-[3px] data-[dragging]:ring-ring/20", disabled && "opacity-60", className),
100
+ className: cn("relative grid gap-2 rounded-lg border border-input bg-surface p-2 shadow-xs transition-[border-color,box-shadow] has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:inset-ring-1 has-[textarea:focus-visible]:inset-ring-ring dark:bg-surface-raised", "data-[dragging]:border-brand data-[dragging]:inset-ring-1 data-[dragging]:inset-ring-brand", disabled && "opacity-60", className),
101
101
  ...props,
102
102
  children: [
103
103
  dragging && /* @__PURE__ */ jsx("div", {
@@ -128,7 +128,7 @@ function Composer({ onSubmit, onSubmitError, submitErrorText = "Message could no
128
128
  send();
129
129
  }
130
130
  },
131
- className: "field-sizing-content max-h-48 min-h-9 w-full resize-none bg-transparent px-2 py-1.5 text-base sm:text-sm leading-6 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed"
131
+ className: "field-sizing-content max-h-48 min-h-9 w-full resize-none rounded-none border-0 bg-transparent px-2 py-1.5 text-base sm:text-sm leading-6 shadow-none outline-hidden! placeholder:text-muted-foreground disabled:cursor-not-allowed"
132
132
  }),
133
133
  failed && /* @__PURE__ */ jsx("p", {
134
134
  id: errorId,
@@ -1 +1 @@
1
- {"version":3,"file":"composer.js","names":["_Fragment"],"sources":["../../src/components/composer.tsx"],"sourcesContent":["import ArrowUp from '@burtson-labs/icons/react/arrow-up';\nimport Paperclip from '@burtson-labs/icons/react/paperclip';\nimport Square from '@burtson-labs/icons/react/square';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Button } from './button';\n\nexport interface ComposerProps extends Omit<React.ComponentProps<'form'>, 'onSubmit' | 'onChange'> {\n /**\n * Clears after success. Reject a returned promise to retain the draft. The\n * text can be empty when `attachmentCount` allows an attachment-only send.\n */\n onSubmit: (text: string) => void | Promise<void>;\n onSubmitError?: (error: unknown) => void;\n submitErrorText?: string;\n /** Controlled value; leave out to let the composer keep its own. */\n value?: string;\n onValueChange?: (value: string) => void;\n /** While a reply streams, the send button becomes Stop. */\n streaming?: boolean;\n onStop?: () => void;\n disabled?: boolean;\n placeholder?: string;\n /** Attachment chips or a file button, shown under the text. */\n attachments?: React.ReactNode;\n /** Attachments ready to send. Above zero, an empty message can be sent. */\n attachmentCount?: number;\n /**\n * Extra gate on sending, e.g. false while an attachment is still parsing.\n * Unlike `disabled`, the person can keep typing.\n */\n canSubmit?: boolean;\n /** Extra controls left of the send button (model picker, tools). */\n actions?: React.ReactNode;\n label?: string;\n /**\n * Files the person picked, dropped on the composer or pasted. Setting it\n * shows a paperclip button. The composer only hands the files over: the\n * app uploads them and renders their state in `attachments` (an\n * AttachmentTray), with `attachmentCount` and `canSubmit` for sending.\n */\n onAttach?: (files: File[]) => void;\n /** File input `accept`, e.g. \"image/*,.pdf\". Dropped and pasted files are filtered too. */\n accept?: string;\n /** Allow several files at once. Default true. */\n multiple?: boolean;\n /** Accessible name of the attach button. */\n attachLabel?: string;\n}\n\n/** Does `file` match an `accept` list (\"image/*,.pdf,text/plain\")? Empty accepts all. */\nexport function acceptsFile(file: Pick<File, 'name' | 'type'>, accept?: string): boolean {\n if (!accept?.trim()) return true;\n const name = file.name.toLowerCase();\n const type = (file.type || '').toLowerCase();\n return accept\n .split(',')\n .map((a) => a.trim().toLowerCase())\n .filter(Boolean)\n .some((rule) =>\n rule.startsWith('.')\n ? name.endsWith(rule)\n : rule.endsWith('/*')\n ? type.startsWith(rule.slice(0, -1))\n : type === rule,\n );\n}\n\n/**\n * The message box: grows with its text, Enter sends, Shift+Enter adds a\n * line, and it never sends mid-composition (IME input).\n */\nfunction Composer({\n onSubmit,\n onSubmitError,\n submitErrorText = 'Message could not be sent. Your draft is saved here. Try again.',\n value: controlled,\n onValueChange,\n streaming = false,\n onStop,\n disabled = false,\n placeholder = 'Ask anything…',\n attachments,\n attachmentCount = 0,\n canSubmit = true,\n actions,\n label = 'Message',\n onAttach,\n accept,\n multiple = true,\n attachLabel = 'Attach files',\n className,\n ...props\n}: ComposerProps) {\n const fileInput = React.useRef<HTMLInputElement>(null);\n const [dragging, setDragging] = React.useState(false);\n const dragDepth = React.useRef(0);\n const attach = (list: FileList | File[] | null | undefined) => {\n if (!onAttach || !list) return;\n let files = Array.from(list).filter((f) => acceptsFile(f, accept));\n if (!multiple) files = files.slice(0, 1);\n if (files.length) onAttach(files);\n };\n const hasFiles = (e: React.DragEvent) =>\n Array.from(e.dataTransfer?.types ?? []).includes('Files');\n const [own, setOwn] = React.useState('');\n const value = controlled ?? own;\n const [pending, setPending] = React.useState(false);\n const [failed, setFailed] = React.useState(false);\n const sending = React.useRef(false);\n const latest = React.useRef(value);\n const mounted = React.useRef(true);\n const errorId = React.useId();\n React.useEffect(() => {\n latest.current = value;\n }, [value]);\n React.useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const setValue = (v: string) => {\n if (controlled === undefined) setOwn(v);\n onValueChange?.(v);\n };\n const canSend =\n canSubmit &&\n !disabled &&\n !streaming &&\n !pending &&\n (value.trim().length > 0 || attachmentCount > 0);\n const send = async () => {\n if (!canSend || sending.current) return;\n const draft = value;\n sending.current = true;\n setFailed(false);\n setPending(true);\n try {\n await onSubmit(draft.trim());\n if (mounted.current && latest.current === draft) setValue('');\n } catch (error) {\n if (mounted.current) setFailed(true);\n onSubmitError?.(error);\n } finally {\n sending.current = false;\n if (mounted.current) setPending(false);\n }\n };\n\n return (\n <form\n data-slot=\"composer\"\n data-dragging={dragging || undefined}\n onSubmit={(e) => {\n e.preventDefault();\n void send();\n }}\n onDragEnter={(e) => {\n if (!onAttach || disabled || !hasFiles(e)) return;\n e.preventDefault();\n dragDepth.current += 1;\n setDragging(true);\n }}\n onDragOver={(e) => {\n if (!onAttach || disabled || !hasFiles(e)) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n }}\n onDragLeave={() => {\n if (!onAttach) return;\n dragDepth.current = Math.max(0, dragDepth.current - 1);\n if (dragDepth.current === 0) setDragging(false);\n }}\n onDrop={(e) => {\n if (!onAttach || disabled) return;\n e.preventDefault();\n dragDepth.current = 0;\n setDragging(false);\n attach(e.dataTransfer?.files);\n }}\n className={cn(\n 'relative grid gap-2 rounded-lg border border-input bg-surface p-2 shadow-xs transition-[border-color,box-shadow] focus-within:border-brand focus-within:ring-[3px] focus-within:ring-ring/15 dark:bg-surface-raised',\n 'data-[dragging]:border-brand data-[dragging]:ring-[3px] data-[dragging]:ring-ring/20',\n disabled && 'opacity-60',\n className,\n )}\n {...props}\n >\n {dragging && (\n <div\n aria-hidden\n className=\"pointer-events-none absolute inset-1 z-10 grid place-items-center rounded-md border border-dashed border-brand/50 bg-brand-soft/80 text-sm font-medium text-brand-soft-foreground\"\n >\n Drop files to attach\n </div>\n )}\n <textarea\n aria-label={label}\n rows={1}\n value={value}\n disabled={disabled || pending}\n aria-describedby={failed ? errorId : undefined}\n aria-invalid={failed || undefined}\n placeholder={placeholder}\n onChange={(e) => setValue(e.target.value)}\n onPaste={(e) => {\n if (!onAttach) return;\n const files = Array.from(e.clipboardData?.files ?? []);\n // Only take over the paste when it carries files; text pastes as text.\n if (files.length) {\n e.preventDefault();\n attach(files);\n }\n }}\n onKeyDown={(e) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n !e.nativeEvent.isComposing &&\n e.nativeEvent.keyCode !== 229\n ) {\n e.preventDefault();\n void send();\n }\n }}\n className=\"field-sizing-content max-h-48 min-h-9 w-full resize-none bg-transparent px-2 py-1.5 text-base sm:text-sm leading-6 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\"\n />\n {failed && (\n <p id={errorId} role=\"alert\" className=\"px-2 text-sm text-destructive\">\n {submitErrorText}\n </p>\n )}\n {attachments && <div className=\"flex flex-wrap gap-1.5 px-1\">{attachments}</div>}\n <div className=\"flex items-center gap-1\">\n {onAttach && (\n <>\n <input\n ref={fileInput}\n type=\"file\"\n hidden\n tabIndex={-1}\n accept={accept}\n multiple={multiple}\n data-slot=\"composer-file-input\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked again after a removal.\n e.target.value = '';\n }}\n />\n <Button\n type=\"button\"\n size=\"icon-sm\"\n variant=\"ghost\"\n aria-label={attachLabel}\n title={attachLabel}\n disabled={disabled}\n onClick={() => fileInput.current?.click()}\n className=\"pointer-coarse:size-11\"\n >\n <Paperclip />\n </Button>\n </>\n )}\n {actions}\n <div className=\"ml-auto\">\n {streaming ? (\n <Button\n type=\"button\"\n size=\"icon-sm\"\n variant=\"secondary\"\n aria-label=\"Stop\"\n className=\"pointer-coarse:size-11\"\n onClick={onStop}\n disabled={!onStop || disabled}\n >\n <Square className=\"fill-current\" />\n </Button>\n ) : (\n <Button\n type=\"submit\"\n size=\"icon-sm\"\n aria-label=\"Send\"\n className=\"pointer-coarse:size-11\"\n loading={pending}\n disabled={!canSend}\n >\n <ArrowUp />\n </Button>\n )}\n </div>\n </div>\n </form>\n );\n}\n\nexport interface SuggestionsProps extends Omit<React.ComponentProps<'div'>, 'onSelect'> {\n items: string[];\n onSelect: (item: string) => void;\n}\n\n/** Starter prompts as chips. */\nfunction Suggestions({ items, onSelect, className, ...props }: SuggestionsProps) {\n return (\n <div\n data-slot=\"suggestions\"\n role=\"group\"\n aria-label=\"Suggestions\"\n className={cn('flex flex-wrap gap-2', className)}\n {...props}\n >\n {items.map((item) => (\n <button\n key={item}\n type=\"button\"\n onClick={() => onSelect(item)}\n className=\"animate-in rounded-full border border-border-strong bg-surface px-3 py-1.5 text-[13px] text-foreground outline-none transition-colors hover:border-brand/40 hover:bg-brand-soft hover:text-brand-soft-foreground focus-visible:ring-[3px] focus-visible:ring-ring/20\"\n >\n {item}\n </button>\n ))}\n </div>\n );\n}\n\nexport { Composer, Suggestions };\n"],"mappings":"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"}
1
+ {"version":3,"file":"composer.js","names":["_Fragment"],"sources":["../../src/components/composer.tsx"],"sourcesContent":["import ArrowUp from '@burtson-labs/icons/react/arrow-up';\nimport Paperclip from '@burtson-labs/icons/react/paperclip';\nimport Square from '@burtson-labs/icons/react/square';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Button } from './button';\n\nexport interface ComposerProps extends Omit<React.ComponentProps<'form'>, 'onSubmit' | 'onChange'> {\n /**\n * Clears after success. Reject a returned promise to retain the draft. The\n * text can be empty when `attachmentCount` allows an attachment-only send.\n */\n onSubmit: (text: string) => void | Promise<void>;\n onSubmitError?: (error: unknown) => void;\n submitErrorText?: string;\n /** Controlled value; leave out to let the composer keep its own. */\n value?: string;\n onValueChange?: (value: string) => void;\n /** While a reply streams, the send button becomes Stop. */\n streaming?: boolean;\n onStop?: () => void;\n disabled?: boolean;\n placeholder?: string;\n /** Attachment chips or a file button, shown under the text. */\n attachments?: React.ReactNode;\n /** Attachments ready to send. Above zero, an empty message can be sent. */\n attachmentCount?: number;\n /**\n * Extra gate on sending, e.g. false while an attachment is still parsing.\n * Unlike `disabled`, the person can keep typing.\n */\n canSubmit?: boolean;\n /** Extra controls left of the send button (model picker, tools). */\n actions?: React.ReactNode;\n label?: string;\n /**\n * Files the person picked, dropped on the composer or pasted. Setting it\n * shows a paperclip button. The composer only hands the files over: the\n * app uploads them and renders their state in `attachments` (an\n * AttachmentTray), with `attachmentCount` and `canSubmit` for sending.\n */\n onAttach?: (files: File[]) => void;\n /** File input `accept`, e.g. \"image/*,.pdf\". Dropped and pasted files are filtered too. */\n accept?: string;\n /** Allow several files at once. Default true. */\n multiple?: boolean;\n /** Accessible name of the attach button. */\n attachLabel?: string;\n}\n\n/** Does `file` match an `accept` list (\"image/*,.pdf,text/plain\")? Empty accepts all. */\nexport function acceptsFile(file: Pick<File, 'name' | 'type'>, accept?: string): boolean {\n if (!accept?.trim()) return true;\n const name = file.name.toLowerCase();\n const type = (file.type || '').toLowerCase();\n return accept\n .split(',')\n .map((a) => a.trim().toLowerCase())\n .filter(Boolean)\n .some((rule) =>\n rule.startsWith('.')\n ? name.endsWith(rule)\n : rule.endsWith('/*')\n ? type.startsWith(rule.slice(0, -1))\n : type === rule,\n );\n}\n\n/**\n * The message box: grows with its text, Enter sends, Shift+Enter adds a\n * line, and it never sends mid-composition (IME input).\n */\nfunction Composer({\n onSubmit,\n onSubmitError,\n submitErrorText = 'Message could not be sent. Your draft is saved here. Try again.',\n value: controlled,\n onValueChange,\n streaming = false,\n onStop,\n disabled = false,\n placeholder = 'Ask anything…',\n attachments,\n attachmentCount = 0,\n canSubmit = true,\n actions,\n label = 'Message',\n onAttach,\n accept,\n multiple = true,\n attachLabel = 'Attach files',\n className,\n ...props\n}: ComposerProps) {\n const fileInput = React.useRef<HTMLInputElement>(null);\n const [dragging, setDragging] = React.useState(false);\n const dragDepth = React.useRef(0);\n const attach = (list: FileList | File[] | null | undefined) => {\n if (!onAttach || !list) return;\n let files = Array.from(list).filter((f) => acceptsFile(f, accept));\n if (!multiple) files = files.slice(0, 1);\n if (files.length) onAttach(files);\n };\n const hasFiles = (e: React.DragEvent) =>\n Array.from(e.dataTransfer?.types ?? []).includes('Files');\n const [own, setOwn] = React.useState('');\n const value = controlled ?? own;\n const [pending, setPending] = React.useState(false);\n const [failed, setFailed] = React.useState(false);\n const sending = React.useRef(false);\n const latest = React.useRef(value);\n const mounted = React.useRef(true);\n const errorId = React.useId();\n React.useEffect(() => {\n latest.current = value;\n }, [value]);\n React.useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const setValue = (v: string) => {\n if (controlled === undefined) setOwn(v);\n onValueChange?.(v);\n };\n const canSend =\n canSubmit &&\n !disabled &&\n !streaming &&\n !pending &&\n (value.trim().length > 0 || attachmentCount > 0);\n const send = async () => {\n if (!canSend || sending.current) return;\n const draft = value;\n sending.current = true;\n setFailed(false);\n setPending(true);\n try {\n await onSubmit(draft.trim());\n if (mounted.current && latest.current === draft) setValue('');\n } catch (error) {\n if (mounted.current) setFailed(true);\n onSubmitError?.(error);\n } finally {\n sending.current = false;\n if (mounted.current) setPending(false);\n }\n };\n\n return (\n <form\n data-slot=\"composer\"\n data-dragging={dragging || undefined}\n onSubmit={(e) => {\n e.preventDefault();\n void send();\n }}\n onDragEnter={(e) => {\n if (!onAttach || disabled || !hasFiles(e)) return;\n e.preventDefault();\n dragDepth.current += 1;\n setDragging(true);\n }}\n onDragOver={(e) => {\n if (!onAttach || disabled || !hasFiles(e)) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n }}\n onDragLeave={() => {\n if (!onAttach) return;\n dragDepth.current = Math.max(0, dragDepth.current - 1);\n if (dragDepth.current === 0) setDragging(false);\n }}\n onDrop={(e) => {\n if (!onAttach || disabled) return;\n e.preventDefault();\n dragDepth.current = 0;\n setDragging(false);\n attach(e.dataTransfer?.files);\n }}\n className={cn(\n // The box is the field: same focus as Input (ring border + 1px inset ring).\n 'relative grid gap-2 rounded-lg border border-input bg-surface p-2 shadow-xs transition-[border-color,box-shadow] has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:inset-ring-1 has-[textarea:focus-visible]:inset-ring-ring dark:bg-surface-raised',\n 'data-[dragging]:border-brand data-[dragging]:inset-ring-1 data-[dragging]:inset-ring-brand',\n disabled && 'opacity-60',\n className,\n )}\n {...props}\n >\n {dragging && (\n <div\n aria-hidden\n className=\"pointer-events-none absolute inset-1 z-10 grid place-items-center rounded-md border border-dashed border-brand/50 bg-brand-soft/80 text-sm font-medium text-brand-soft-foreground\"\n >\n Drop files to attach\n </div>\n )}\n <textarea\n aria-label={label}\n rows={1}\n value={value}\n disabled={disabled || pending}\n aria-describedby={failed ? errorId : undefined}\n aria-invalid={failed || undefined}\n placeholder={placeholder}\n onChange={(e) => setValue(e.target.value)}\n onPaste={(e) => {\n if (!onAttach) return;\n const files = Array.from(e.clipboardData?.files ?? []);\n // Only take over the paste when it carries files; text pastes as text.\n if (files.length) {\n e.preventDefault();\n attach(files);\n }\n }}\n onKeyDown={(e) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n !e.nativeEvent.isComposing &&\n e.nativeEvent.keyCode !== 229\n ) {\n e.preventDefault();\n void send();\n }\n }}\n className=\"field-sizing-content max-h-48 min-h-9 w-full resize-none rounded-none border-0 bg-transparent px-2 py-1.5 text-base sm:text-sm leading-6 shadow-none outline-hidden! placeholder:text-muted-foreground disabled:cursor-not-allowed\"\n />\n {failed && (\n <p id={errorId} role=\"alert\" className=\"px-2 text-sm text-destructive\">\n {submitErrorText}\n </p>\n )}\n {attachments && <div className=\"flex flex-wrap gap-1.5 px-1\">{attachments}</div>}\n <div className=\"flex items-center gap-1\">\n {onAttach && (\n <>\n <input\n ref={fileInput}\n type=\"file\"\n hidden\n tabIndex={-1}\n accept={accept}\n multiple={multiple}\n data-slot=\"composer-file-input\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked again after a removal.\n e.target.value = '';\n }}\n />\n <Button\n type=\"button\"\n size=\"icon-sm\"\n variant=\"ghost\"\n aria-label={attachLabel}\n title={attachLabel}\n disabled={disabled}\n onClick={() => fileInput.current?.click()}\n className=\"pointer-coarse:size-11\"\n >\n <Paperclip />\n </Button>\n </>\n )}\n {actions}\n <div className=\"ml-auto\">\n {streaming ? (\n <Button\n type=\"button\"\n size=\"icon-sm\"\n variant=\"secondary\"\n aria-label=\"Stop\"\n className=\"pointer-coarse:size-11\"\n onClick={onStop}\n disabled={!onStop || disabled}\n >\n <Square className=\"fill-current\" />\n </Button>\n ) : (\n <Button\n type=\"submit\"\n size=\"icon-sm\"\n aria-label=\"Send\"\n className=\"pointer-coarse:size-11\"\n loading={pending}\n disabled={!canSend}\n >\n <ArrowUp />\n </Button>\n )}\n </div>\n </div>\n </form>\n );\n}\n\nexport interface SuggestionsProps extends Omit<React.ComponentProps<'div'>, 'onSelect'> {\n items: string[];\n onSelect: (item: string) => void;\n}\n\n/** Starter prompts as chips. */\nfunction Suggestions({ items, onSelect, className, ...props }: SuggestionsProps) {\n return (\n <div\n data-slot=\"suggestions\"\n role=\"group\"\n aria-label=\"Suggestions\"\n className={cn('flex flex-wrap gap-2', className)}\n {...props}\n >\n {items.map((item) => (\n <button\n key={item}\n type=\"button\"\n onClick={() => onSelect(item)}\n className=\"animate-in rounded-full border border-border-strong bg-surface px-3 py-1.5 text-[13px] text-foreground outline-none transition-colors hover:border-brand/40 hover:bg-brand-soft hover:text-brand-soft-foreground focus-visible:ring-[3px] focus-visible:ring-ring/20\"\n >\n {item}\n </button>\n ))}\n </div>\n );\n}\n\nexport { Composer, Suggestions };\n"],"mappings":"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"}
@@ -110,7 +110,7 @@ function ContextMenuSubTrigger({ className, inset, children, ...props }) {
110
110
  return /* @__PURE__ */ jsxs(ContextMenu.SubTrigger, {
111
111
  "data-slot": "context-menu-sub-trigger",
112
112
  "data-inset": inset || void 0,
113
- className: cn(menuItemClasses, "data-[state=open]:bg-muted", className),
113
+ className: cn(menuItemClasses, "data-[state=open]:bg-secondary", className),
114
114
  ...props,
115
115
  children: [children, /* @__PURE__ */ jsx(ChevronRight, {
116
116
  className: "ml-auto size-4",
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu.js","names":["ContextMenu","ContextMenuPrimitive","itemClasses"],"sources":["../../src/components/context-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { ContextMenu as ContextMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep\n * your element); the menu opens at the pointer, and from the keyboard with the\n * context-menu key or Shift+F10 on the focused target. Same rows as\n * DropdownMenu, so a command can appear in both.\n */\nfunction ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\nfunction ContextMenuTrigger(props: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {\n return <ContextMenuPrimitive.Trigger data-slot=\"context-menu-trigger\" {...props} />;\n}\n\nfunction ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {\n return <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />;\n}\n\nfunction ContextMenuContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n data-slot=\"context-menu-content\"\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nfunction ContextMenuItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <ContextMenuPrimitive.Item\n data-slot=\"context-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n data-slot=\"context-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction ContextMenuRadioGroup(\n props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>,\n) {\n return <ContextMenuPrimitive.RadioGroup data-slot=\"context-menu-radio-group\" {...props} />;\n}\n\nfunction ContextMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {\n return (\n <ContextMenuPrimitive.RadioItem\n data-slot=\"context-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n );\n}\n\nfunction ContextMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.Label\n data-slot=\"context-menu-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {\n return (\n <ContextMenuPrimitive.Separator\n data-slot=\"context-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"context-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {\n return <ContextMenuPrimitive.Sub data-slot=\"context-menu-sub\" {...props} />;\n}\n\nfunction ContextMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.SubTrigger\n data-slot=\"context-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-muted', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </ContextMenuPrimitive.SubTrigger>\n );\n}\n\nfunction ContextMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.SubContent\n data-slot=\"context-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nexport {\n ContextMenu,\n ContextMenuCheckboxItem,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuItem,\n ContextMenuLabel,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuTrigger,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"context-menu.js","names":["ContextMenu","ContextMenuPrimitive","itemClasses"],"sources":["../../src/components/context-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { ContextMenu as ContextMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep\n * your element); the menu opens at the pointer, and from the keyboard with the\n * context-menu key or Shift+F10 on the focused target. Same rows as\n * DropdownMenu, so a command can appear in both.\n */\nfunction ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\nfunction ContextMenuTrigger(props: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {\n return <ContextMenuPrimitive.Trigger data-slot=\"context-menu-trigger\" {...props} />;\n}\n\nfunction ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {\n return <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />;\n}\n\nfunction ContextMenuContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n data-slot=\"context-menu-content\"\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nfunction ContextMenuItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <ContextMenuPrimitive.Item\n data-slot=\"context-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n data-slot=\"context-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction ContextMenuRadioGroup(\n props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>,\n) {\n return <ContextMenuPrimitive.RadioGroup data-slot=\"context-menu-radio-group\" {...props} />;\n}\n\nfunction ContextMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {\n return (\n <ContextMenuPrimitive.RadioItem\n data-slot=\"context-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n );\n}\n\nfunction ContextMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.Label\n data-slot=\"context-menu-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {\n return (\n <ContextMenuPrimitive.Separator\n data-slot=\"context-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"context-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {\n return <ContextMenuPrimitive.Sub data-slot=\"context-menu-sub\" {...props} />;\n}\n\nfunction ContextMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.SubTrigger\n data-slot=\"context-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-secondary', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </ContextMenuPrimitive.SubTrigger>\n );\n}\n\nfunction ContextMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.SubContent\n data-slot=\"context-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nexport {\n ContextMenu,\n ContextMenuCheckboxItem,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuItem,\n ContextMenuLabel,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuTrigger,\n};\n"],"mappings":";;;;;;;;;;;;;;AAeA,SAASA,cAAY,OAA+D;CAClF,OAAO,oBAACC,YAAqB,MAAtB;EAA2B,aAAU;EAAe,GAAI;CAAQ,CAAA;AACzE;AAEA,SAAS,mBAAmB,OAAkE;CAC5F,OAAO,oBAACA,YAAqB,SAAtB;EAA8B,aAAU;EAAuB,GAAI;CAAQ,CAAA;AACpF;AAEA,SAAS,iBAAiB,OAAgE;CACxF,OAAO,oBAACA,YAAqB,OAAtB;EAA4B,aAAU;EAAqB,GAAI;CAAQ,CAAA;AAChF;AAEA,SAAS,mBAAmB,EAC1B,WACA,GAAG,SACyD;CAC5D,OACE,oBAACA,YAAqB,QAAtB,EAAA,UACE,oBAACA,YAAqB,SAAtB;EACE,aAAU;EACV,WAAW,GACT,gBACA,mKACA,SACF;EACA,GAAI;CACL,CAAA,EAC0B,CAAA;AAEjC;AAEA,SAAS,gBAAgB,EACvB,WACA,OACA,UAAU,WACV,GAAG,SAIF;CACD,OACE,oBAACA,YAAqB,MAAtB;EACE,aAAU;EACV,cAAY,SAAS,KAAA;EACrB,gBAAc;EACd,WAAW,GACTC,iBACA,uJACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,wBAAwB,EAC/B,WACA,UACA,SACA,GAAG,SAC8D;CACjE,OACE,qBAACD,YAAqB,cAAtB;EACE,aAAU;EACV,WAAW,GAAGC,iBAAa,QAAQ,SAAS;EACnC;EACT,GAAI;EAJN,UAAA,CAME,oBAAC,QAAD;GAAM,WAAU;GACd,UAAA,oBAACD,YAAqB,eAAtB,EAAA,UACE,oBAAC,OAAD;IAAO,WAAU;IAAyB,eAAA;GAAa,CAAA,EACrB,CAAA;EAChC,CAAA,GACL,QACgC;;AAEvC;AAEA,SAAS,sBACP,OACA;CACA,OAAO,oBAACA,YAAqB,YAAtB;EAAiC,aAAU;EAA2B,GAAI;CAAQ,CAAA;AAC3F;AAEA,SAAS,qBAAqB,EAC5B,WACA,UACA,GAAG,SAC2D;CAC9D,OACE,qBAACA,YAAqB,WAAtB;EACE,aAAU;EACV,WAAW,GAAGC,iBAAa,QAAQ,SAAS;EAC5C,GAAI;EAHN,UAAA,CAKE,oBAAC,QAAD;GAAM,WAAU;GACd,UAAA,oBAACD,YAAqB,eAAtB,EAAA,UACE,oBAAC,QAAD,EAAM,WAAU,0CAA2C,CAAA,EACzB,CAAA;EAChC,CAAA,GACL,QAC6B;;AAEpC;AAEA,SAAS,iBAAiB,EACxB,WACA,OACA,GAAG,SAC6E;CAChF,OACE,oBAACA,YAAqB,OAAtB;EACE,aAAU;EACV,cAAY,SAAS,KAAA;EACrB,WAAW,GACT,gHACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,qBAAqB,EAC5B,WACA,GAAG,SAC2D;CAC9D,OACE,oBAACA,YAAqB,WAAtB;EACE,aAAU;EACV,WAAW,GAAG,6BAA6B,SAAS;EACpD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,oBAAoB,EAAE,WAAW,GAAG,SAAuC;CAClF,OACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GAAG,yDAAyD,SAAS;EAChF,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,eAAe,OAA8D;CACpF,OAAO,oBAACA,YAAqB,KAAtB;EAA0B,aAAU;EAAmB,GAAI;CAAQ,CAAA;AAC5E;AAEA,SAAS,sBAAsB,EAC7B,WACA,OACA,UACA,GAAG,SACkF;CACrF,OACE,qBAACA,YAAqB,YAAtB;EACE,aAAU;EACV,cAAY,SAAS,KAAA;EACrB,WAAW,GAAGC,iBAAa,kCAAkC,SAAS;EACtE,GAAI;EAJN,UAAA,CAMG,UACD,oBAAC,cAAD;GAAc,WAAU;GAAiB,eAAA;EAAa,CAAA,CACvB;;AAErC;AAEA,SAAS,sBAAsB,EAC7B,WACA,GAAG,SAC4D;CAC/D,OACE,oBAACD,YAAqB,QAAtB,EAAA,UACE,oBAACA,YAAqB,YAAtB;EACE,aAAU;EACV,WAAW,GACT,gBACA,2FACA,SACF;EACA,GAAI;CACL,CAAA,EAC0B,CAAA;AAEjC"}
@@ -1,7 +1,7 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import { Button } from "./button.js";
3
- import { Checkbox } from "./checkbox.js";
4
3
  import { Input } from "./input.js";
4
+ import { Checkbox } from "./checkbox.js";
5
5
  import { Pagination } from "./pagination.js";
6
6
  import { Skeleton } from "./skeleton.js";
7
7
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table.js";
@@ -105,7 +105,7 @@ function DropdownMenuSubTrigger({ className, inset, children, ...props }) {
105
105
  return /* @__PURE__ */ jsxs(DropdownMenu.SubTrigger, {
106
106
  "data-slot": "dropdown-menu-sub-trigger",
107
107
  "data-inset": inset || void 0,
108
- className: cn(menuItemClasses, "data-[state=open]:bg-muted", className),
108
+ className: cn(menuItemClasses, "data-[state=open]:bg-secondary", className),
109
109
  ...props,
110
110
  children: [children, /* @__PURE__ */ jsx(ChevronRight, {
111
111
  className: "ml-auto size-4",
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","DropdownMenuPrimitive","itemClasses"],"sources":["../../src/components/dropdown-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\nfunction DropdownMenu(props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuTrigger(props: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nfunction DropdownMenuGroup(props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,\n) {\n return <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub(props: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-muted', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","DropdownMenuPrimitive","itemClasses"],"sources":["../../src/components/dropdown-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\nfunction DropdownMenu(props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuTrigger(props: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nfunction DropdownMenuGroup(props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,\n) {\n return <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub(props: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-secondary', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n"],"mappings":"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"}
@@ -1,4 +1,18 @@
1
1
  import * as React from 'react';
2
- export declare const fieldClasses = "w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs outline-none transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:border-brand focus-visible:ring-[3px] focus-visible:ring-ring/15 disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive aria-invalid:ring-destructive/15 dark:bg-surface-raised";
2
+ /**
3
+ * Keyboard focus for anything that is a text field, or a box that contains
4
+ * one (Composer, a bordered Command): the border turns the ring colour and a
5
+ * 1px inset ring doubles it to 2px. It sits inside the border box, so it
6
+ * follows the radius exactly and no overflow can clip it. The outline is
7
+ * suppressed with !important: an app's unlayered `:focus-visible { outline }`
8
+ * would otherwise beat the utilities layer and draw a second, offset box.
9
+ * outline-hidden keeps a transparent outline, which forced-colors mode shows.
10
+ */
11
+ export declare const fieldFocusClasses = "outline-hidden! focus-visible:border-ring focus-visible:inset-ring-1 focus-visible:inset-ring-ring aria-invalid:focus-visible:inset-ring-destructive";
12
+ /**
13
+ * Fields and field-like triggers: 10px radius (radius-md). Popovers are 12px
14
+ * (radius-lg) and their rows 8px (radius-sm: 12px less the 4px inset).
15
+ */
16
+ export declare const fieldClasses = "w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong outline-hidden! focus-visible:border-ring focus-visible:inset-ring-1 focus-visible:inset-ring-ring aria-invalid:focus-visible:inset-ring-destructive disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive dark:bg-surface-raised";
3
17
  declare const Input: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
4
18
  export { Input };
@@ -2,7 +2,21 @@ import { cn } from "../lib/utils.js";
2
2
  import * as React from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/components/input.tsx
5
- var fieldClasses = "w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs outline-none transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:border-brand focus-visible:ring-[3px] focus-visible:ring-ring/15 disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive aria-invalid:ring-destructive/15 dark:bg-surface-raised";
5
+ /**
6
+ * Keyboard focus for anything that is a text field, or a box that contains
7
+ * one (Composer, a bordered Command): the border turns the ring colour and a
8
+ * 1px inset ring doubles it to 2px. It sits inside the border box, so it
9
+ * follows the radius exactly and no overflow can clip it. The outline is
10
+ * suppressed with !important: an app's unlayered `:focus-visible { outline }`
11
+ * would otherwise beat the utilities layer and draw a second, offset box.
12
+ * outline-hidden keeps a transparent outline, which forced-colors mode shows.
13
+ */
14
+ var fieldFocusClasses = "outline-hidden! focus-visible:border-ring focus-visible:inset-ring-1 focus-visible:inset-ring-ring aria-invalid:focus-visible:inset-ring-destructive";
15
+ /**
16
+ * Fields and field-like triggers: 10px radius (radius-md). Popovers are 12px
17
+ * (radius-lg) and their rows 8px (radius-sm: 12px less the 4px inset).
18
+ */
19
+ var fieldClasses = `w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong ${fieldFocusClasses} disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive dark:bg-surface-raised`;
6
20
  var Input = React.forwardRef(function Input({ className, type, ...props }, ref) {
7
21
  return /* @__PURE__ */ jsx("input", {
8
22
  ref,
@@ -13,6 +27,6 @@ var Input = React.forwardRef(function Input({ className, type, ...props }, ref)
13
27
  });
14
28
  });
15
29
  //#endregion
16
- export { Input, fieldClasses };
30
+ export { Input, fieldClasses, fieldFocusClasses };
17
31
 
18
32
  //# sourceMappingURL=input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","names":[],"sources":["../../src/components/input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport const fieldClasses =\n 'w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs outline-none transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:border-brand focus-visible:ring-[3px] focus-visible:ring-ring/15 disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive aria-invalid:ring-destructive/15 dark:bg-surface-raised';\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(function Input(\n { className, type, ...props }: React.ComponentProps<'input'>,\n ref,\n) {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n fieldClasses,\n 'h-9 py-1.5 file:mr-3 file:border-0 file:bg-transparent file:text-sm file:font-semibold file:text-foreground',\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Input };\n"],"mappings":";;;;AAIA,IAAa,eACX;AAEF,IAAM,QAAQ,MAAM,WAA4D,SAAS,MACvF,EAAE,WAAW,MAAM,GAAG,SACtB,KACA;CACA,OACE,oBAAC,SAAD;EACO;EACC;EACN,aAAU;EACV,WAAW,GACT,cACA,+GACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC"}
1
+ {"version":3,"file":"input.js","names":[],"sources":["../../src/components/input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\n/**\n * Keyboard focus for anything that is a text field, or a box that contains\n * one (Composer, a bordered Command): the border turns the ring colour and a\n * 1px inset ring doubles it to 2px. It sits inside the border box, so it\n * follows the radius exactly and no overflow can clip it. The outline is\n * suppressed with !important: an app's unlayered `:focus-visible { outline }`\n * would otherwise beat the utilities layer and draw a second, offset box.\n * outline-hidden keeps a transparent outline, which forced-colors mode shows.\n */\nexport const fieldFocusClasses =\n 'outline-hidden! focus-visible:border-ring focus-visible:inset-ring-1 focus-visible:inset-ring-ring aria-invalid:focus-visible:inset-ring-destructive';\n\n/**\n * Fields and field-like triggers: 10px radius (radius-md). Popovers are 12px\n * (radius-lg) and their rows 8px (radius-sm: 12px less the 4px inset).\n */\nexport const fieldClasses = `w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong ${fieldFocusClasses} disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive dark:bg-surface-raised`;\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(function Input(\n { className, type, ...props }: React.ComponentProps<'input'>,\n ref,\n) {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n fieldClasses,\n 'h-9 py-1.5 file:mr-3 file:border-0 file:bg-transparent file:text-sm file:font-semibold file:text-foreground',\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Input };\n"],"mappings":";;;;;;;;;;;;;AAaA,IAAa,oBACX;;;;;AAMF,IAAa,eAAe,sOAAsO,kBAAkB;AAEpR,IAAM,QAAQ,MAAM,WAA4D,SAAS,MACvF,EAAE,WAAW,MAAM,GAAG,SACtB,KACA;CACA,OACE,oBAAC,SAAD;EACO;EACC;EACN,aAAU;EACV,WAAW,GACT,cACA,+GACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC"}
@@ -119,7 +119,7 @@ function MenubarSubTrigger({ className, inset, children, ...props }) {
119
119
  return /* @__PURE__ */ jsxs(Menubar.SubTrigger, {
120
120
  "data-slot": "menubar-sub-trigger",
121
121
  "data-inset": inset || void 0,
122
- className: cn(menuItemClasses, "data-[state=open]:bg-muted", className),
122
+ className: cn(menuItemClasses, "data-[state=open]:bg-secondary", className),
123
123
  ...props,
124
124
  children: [children, /* @__PURE__ */ jsx(ChevronRight, {
125
125
  className: "ml-auto size-4",
@@ -1 +1 @@
1
- {"version":3,"file":"menubar.js","names":["Menubar","MenubarPrimitive","itemClasses"],"sources":["../../src/components/menubar.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { Menubar as MenubarPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * An application menu bar (File, Edit, View). Left/Right move between menus,\n * Down opens one, and an open menu follows the pointer across triggers. Rows\n * match DropdownMenu and ContextMenu.\n */\nfunction Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>) {\n return (\n <MenubarPrimitive.Root\n data-slot=\"menubar\"\n className={cn('flex h-8 items-center gap-0.5 rounded-md border bg-surface p-0.5', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarMenu(props: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\n return <MenubarPrimitive.Menu data-slot=\"menubar-menu\" {...props} />;\n}\n\nfunction MenubarTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {\n return (\n <MenubarPrimitive.Trigger\n data-slot=\"menubar-trigger\"\n className={cn(\n 'flex h-7 items-center rounded-sm px-2.5 text-[13px] font-medium outline-none select-none hover:bg-muted focus-visible:shadow-[inset_0_0_0_1px_var(--ring)] data-[state=open]:bg-muted',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarGroup(props: React.ComponentProps<typeof MenubarPrimitive.Group>) {\n return <MenubarPrimitive.Group data-slot=\"menubar-group\" {...props} />;\n}\n\nfunction MenubarContent({\n className,\n align = 'start',\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Content>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.Content\n data-slot=\"menubar-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-menubar-content-available-height) min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nfunction MenubarItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <MenubarPrimitive.Item\n data-slot=\"menubar-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {\n return (\n <MenubarPrimitive.CheckboxItem\n data-slot=\"menubar-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n );\n}\n\nfunction MenubarRadioGroup(props: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {\n return <MenubarPrimitive.RadioGroup data-slot=\"menubar-radio-group\" {...props} />;\n}\n\nfunction MenubarRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {\n return (\n <MenubarPrimitive.RadioItem\n data-slot=\"menubar-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n );\n}\n\nfunction MenubarLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Label> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.Label\n data-slot=\"menubar-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Separator>) {\n return (\n <MenubarPrimitive.Separator\n data-slot=\"menubar-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"menubar-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarSub(props: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\n}\n\nfunction MenubarSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.SubTrigger\n data-slot=\"menubar-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-muted', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </MenubarPrimitive.SubTrigger>\n );\n}\n\nfunction MenubarSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.SubContent\n data-slot=\"menubar-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"menubar.js","names":["Menubar","MenubarPrimitive","itemClasses"],"sources":["../../src/components/menubar.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { Menubar as MenubarPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * An application menu bar (File, Edit, View). Left/Right move between menus,\n * Down opens one, and an open menu follows the pointer across triggers. Rows\n * match DropdownMenu and ContextMenu.\n */\nfunction Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>) {\n return (\n <MenubarPrimitive.Root\n data-slot=\"menubar\"\n className={cn('flex h-8 items-center gap-0.5 rounded-md border bg-surface p-0.5', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarMenu(props: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\n return <MenubarPrimitive.Menu data-slot=\"menubar-menu\" {...props} />;\n}\n\nfunction MenubarTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {\n return (\n <MenubarPrimitive.Trigger\n data-slot=\"menubar-trigger\"\n className={cn(\n 'flex h-7 items-center rounded-sm px-2.5 text-[13px] font-medium outline-none select-none hover:bg-muted focus-visible:shadow-[inset_0_0_0_1px_var(--ring)] data-[state=open]:bg-muted',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarGroup(props: React.ComponentProps<typeof MenubarPrimitive.Group>) {\n return <MenubarPrimitive.Group data-slot=\"menubar-group\" {...props} />;\n}\n\nfunction MenubarContent({\n className,\n align = 'start',\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Content>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.Content\n data-slot=\"menubar-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-menubar-content-available-height) min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nfunction MenubarItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <MenubarPrimitive.Item\n data-slot=\"menubar-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {\n return (\n <MenubarPrimitive.CheckboxItem\n data-slot=\"menubar-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n );\n}\n\nfunction MenubarRadioGroup(props: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {\n return <MenubarPrimitive.RadioGroup data-slot=\"menubar-radio-group\" {...props} />;\n}\n\nfunction MenubarRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {\n return (\n <MenubarPrimitive.RadioItem\n data-slot=\"menubar-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n );\n}\n\nfunction MenubarLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Label> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.Label\n data-slot=\"menubar-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Separator>) {\n return (\n <MenubarPrimitive.Separator\n data-slot=\"menubar-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"menubar-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarSub(props: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\n}\n\nfunction MenubarSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.SubTrigger\n data-slot=\"menubar-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-secondary', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </MenubarPrimitive.SubTrigger>\n );\n}\n\nfunction MenubarSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.SubContent\n data-slot=\"menubar-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n};\n"],"mappings":"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"}
@@ -99,7 +99,7 @@ function MessageEditor({ defaultValue, onSubmit, onCancel, submitLabel = "Send",
99
99
  send();
100
100
  }
101
101
  },
102
- className: "field-sizing-content max-h-60 min-h-16 w-full resize-none rounded-lg border border-brand bg-surface px-3 py-2 text-base leading-6 ring-[3px] ring-ring/15 outline-none sm:text-sm"
102
+ className: "field-sizing-content max-h-60 min-h-16 w-full resize-none rounded-lg border border-ring bg-surface px-3 py-2 text-base leading-6 inset-ring-1 inset-ring-ring outline-hidden! sm:text-sm"
103
103
  }), /* @__PURE__ */ jsxs("div", {
104
104
  className: "flex justify-end gap-2",
105
105
  children: [/* @__PURE__ */ jsx(Button, {