@nocoo/basalt 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/DESIGN.md +157 -39
- package/ai/INTEGRATION.md +83 -8
- package/ai/USAGE.md +2 -2
- package/ai/registry.json +302 -79
- package/dist/charts/config.d.ts +1 -1
- package/dist/charts/config.js +1 -1
- package/dist/charts/config.js.map +1 -1
- package/dist/charts/heatmap-matrix.js +2 -2
- package/dist/charts/heatmap-matrix.js.map +1 -1
- package/dist/charts/sparkline.js +1 -1
- package/dist/charts/sparkline.js.map +1 -1
- package/dist/charts/stat-card.js +1 -1
- package/dist/charts/stat-card.js.map +1 -1
- package/dist/components/alert-dialog.js +4 -4
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/approval-card.js +5 -6
- package/dist/components/approval-card.js.map +1 -1
- package/dist/components/avatar.js +1 -1
- package/dist/components/avatar.js.map +1 -1
- package/dist/components/chat-bubble.js +1 -1
- package/dist/components/chat-bubble.js.map +1 -1
- package/dist/components/chat-header.js +1 -1
- package/dist/components/chat-header.js.map +1 -1
- package/dist/components/chat-inbox.js +1 -1
- package/dist/components/chat-inbox.js.map +1 -1
- package/dist/components/chat-markdown.js +1 -1
- package/dist/components/chat-markdown.js.map +1 -1
- package/dist/components/chat-message.js +1 -1
- package/dist/components/chat-message.js.map +1 -1
- package/dist/components/code.js +4 -3
- package/dist/components/code.js.map +1 -1
- package/dist/components/context-cards.js +5 -5
- package/dist/components/context-cards.js.map +1 -1
- package/dist/components/data-table.d.ts +7 -1
- package/dist/components/data-table.js +127 -132
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/dialog.js +3 -3
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/diff-table.js +20 -15
- package/dist/components/diff-table.js.map +1 -1
- package/dist/components/input-area.js +1 -1
- package/dist/components/input-area.js.map +1 -1
- package/dist/components/layer-card.d.ts +6 -4
- package/dist/components/layer-card.js +60 -71
- package/dist/components/layer-card.js.map +1 -1
- package/dist/components/loader.js +1 -1
- package/dist/components/loader.js.map +1 -1
- package/dist/components/page-header.d.ts +2 -2
- package/dist/components/page-header.js +7 -7
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/recommendation-card.js +2 -2
- package/dist/components/recommendation-card.js.map +1 -1
- package/dist/components/section-rule.js +1 -1
- package/dist/components/section-rule.js.map +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/select.js.map +1 -1
- package/dist/components/sheet.js +3 -3
- package/dist/components/sheet.js.map +1 -1
- package/dist/components/sidebar.js +19 -16
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/skeleton-line.js +1 -1
- package/dist/components/skeleton-line.js.map +1 -1
- package/dist/components/stat-strip.js +1 -1
- package/dist/components/stat-strip.js.map +1 -1
- package/dist/components/table.d.ts +41 -2
- package/dist/components/table.js +44 -15
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tag-badge.js +1 -1
- package/dist/components/tag-badge.js.map +1 -1
- package/dist/components/text.js +2 -2
- package/dist/components/text.js.map +1 -1
- package/dist/components/thinking.js +1 -1
- package/dist/components/thinking.js.map +1 -1
- package/dist/components/tool-chips.js +2 -2
- package/dist/components/tool-chips.js.map +1 -1
- package/dist/styles/standalone.css +145 -89
- package/dist/styles/tailwind.css +2 -0
- package/dist/styles/tokens.css +84 -39
- package/dist/utils/use-hover-highlight.js +38 -36
- package/dist/utils/use-hover-highlight.js.map +1 -1
- package/package.json +28 -28
|
@@ -5,7 +5,7 @@ import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
|
5
5
|
//#region src/components/chat-bubble.tsx
|
|
6
6
|
function i({ variant: i = "assistant", streaming: a = !1, className: o, children: s }) {
|
|
7
7
|
if (i === "system") return /* @__PURE__ */ n("p", {
|
|
8
|
-
className: e(t, "px-basalt-space-sm text-center text-basalt-
|
|
8
|
+
className: e(t, "px-basalt-space-sm text-center text-basalt-sm text-basalt-muted-foreground", o),
|
|
9
9
|
children: s
|
|
10
10
|
});
|
|
11
11
|
let c = i === "user";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-bubble.js","names":["ChatBubble","variant","cn","BASALT_UI_CLASS","className","user","children","streaming"],"sources":["../../src/components/chat-bubble.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport type ChatBubbleVariant = \"assistant\" | \"system\" | \"user\";\n\nexport interface ChatBubbleProps {\n\t/**\n\t * Alignment and fill.\n\t * @default \"assistant\"\n\t */\n\tvariant?: ChatBubbleVariant;\n\t/**\n\t * Show a streaming caret after the body.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\t/**\n\t * Optional class name applied to the message bubble.\n\t * Component only accepts variant, streaming, className, and children without native HTML rest forwarding or forwarded ref.\n\t */\n\tclassName?: string;\n\t/**\n\t * Message content.\n\t */\n\tchildren: ReactNode;\n}\n\nexport function ChatBubble({\n\tvariant = \"assistant\",\n\tstreaming = false,\n\tclassName,\n\tchildren,\n}: ChatBubbleProps) {\n\tif (variant === \"system\") {\n\t\treturn (\n\t\t\t<p\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\t\"px-basalt-space-sm text-center text-basalt-
|
|
1
|
+
{"version":3,"file":"chat-bubble.js","names":["ChatBubble","variant","cn","BASALT_UI_CLASS","className","user","children","streaming"],"sources":["../../src/components/chat-bubble.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport type ChatBubbleVariant = \"assistant\" | \"system\" | \"user\";\n\nexport interface ChatBubbleProps {\n\t/**\n\t * Alignment and fill.\n\t * @default \"assistant\"\n\t */\n\tvariant?: ChatBubbleVariant;\n\t/**\n\t * Show a streaming caret after the body.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\t/**\n\t * Optional class name applied to the message bubble.\n\t * Component only accepts variant, streaming, className, and children without native HTML rest forwarding or forwarded ref.\n\t */\n\tclassName?: string;\n\t/**\n\t * Message content.\n\t */\n\tchildren: ReactNode;\n}\n\nexport function ChatBubble({\n\tvariant = \"assistant\",\n\tstreaming = false,\n\tclassName,\n\tchildren,\n}: ChatBubbleProps) {\n\tif (variant === \"system\") {\n\t\treturn (\n\t\t\t<p\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\t\"px-basalt-space-sm text-center text-basalt-sm text-basalt-muted-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</p>\n\t\t);\n\t}\n\tconst user = variant === \"user\";\n\treturn (\n\t\t<div className={cn(BASALT_UI_CLASS, \"flex w-full\", user ? \"justify-end\" : \"justify-start\")}>\n\t\t\t<div\n\t\t\t\tdata-basalt-surface={user ? undefined : \"\"}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"max-w-[92%] px-basalt-panel-x py-basalt-panel-y text-basalt-base leading-[var(--basalt-line-body)] shadow-sm\",\n\t\t\t\t\tuser\n\t\t\t\t\t\t? \"rounded-basalt-lg rounded-br-basalt-md bg-basalt-primary text-basalt-primary-foreground\"\n\t\t\t\t\t\t: \"rounded-basalt-lg rounded-bl-basalt-md text-basalt-foreground ring-1 ring-basalt-border/50\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t{streaming ? (\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName=\"mt-basalt-space-sm inline-block h-basalt-3 w-basalt-1_5 animate-pulse rounded-basalt-sm bg-basalt-primary/70 align-middle motion-reduce:animate-none\"\n\t\t\t\t\t\taria-hidden\n\t\t\t\t\t/>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;AA4BA,SAAgBA,EAAW,EAC1B,aAAU,aACV,eAAY,IACZ,cACA,eACmB;CACnB,IAAIC,MAAY,UACf,OACC,kBAAC,KAAD;EACC,WAAWC,EACVC,GACA,8EACAC,CACD;EAEC;CACC,CAAA;CAGL,IAAMC,IAAOJ,MAAY;CACzB,OACC,kBAAC,OAAD;EAAK,WAAWC,EAAGC,GAAiB,eAAeE,IAAO,gBAAgB,eAAe;EACxF,UAAA,kBAAC,OAAD;GACC,uBAAqBA,IAAO,KAAA,IAAY;GACxC,WAAWH,EACV,gHACAG,IACG,4FACA,8FACHD,CACD;GARD,UAAA,CAUEE,GACAC,IACA,kBAAC,QAAD;IACC,WAAU;IACV,eAAA;GACA,CAAA,IACE,IACA;;CACD,CAAA;AAEP"}
|
|
@@ -18,7 +18,7 @@ function i({ title: i, subtitle: a, leading: o, children: s, className: c, ...l
|
|
|
18
18
|
className: "truncate text-basalt-base font-semibold tracking-tight",
|
|
19
19
|
children: i
|
|
20
20
|
}), a ? /* @__PURE__ */ n("p", {
|
|
21
|
-
className: "truncate text-basalt-
|
|
21
|
+
className: "truncate text-basalt-sm text-basalt-muted-foreground",
|
|
22
22
|
children: a
|
|
23
23
|
}) : null]
|
|
24
24
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-header.js","names":["ChatHeader","props","cn","BASALT_UI_CLASS","className","leading","title","subtitle","children"],"sources":["../../src/components/chat-header.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface ChatHeaderProps\n\textends Omit<HTMLAttributes<HTMLElement>, \"title\" | \"children\" | \"className\"> {\n\t/**\n\t * Conversation title.\n\t */\n\ttitle: ReactNode;\n\t/**\n\t * Secondary line under the title.\n\t */\n\tsubtitle?: ReactNode;\n\t/**\n\t * Leading mark, usually an icon.\n\t */\n\tleading?: ReactNode;\n\t/**\n\t * Trailing actions.\n\t */\n\tchildren?: ReactNode;\n\t/**\n\t * Optional class name applied to the header element.\n\t * Component inherits native header HTMLAttributes on the root element but does not forward ref.\n\t */\n\tclassName?: string;\n}\n\nexport function ChatHeader({\n\ttitle,\n\tsubtitle,\n\tleading,\n\tchildren,\n\tclassName,\n\t...props\n}: ChatHeaderProps) {\n\treturn (\n\t\t<header\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"flex items-center justify-between gap-basalt-content-gap border-b border-basalt-border/50 px-basalt-panel-x py-basalt-panel-y leading-[var(--basalt-line-body)]\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<div className=\"flex min-w-0 items-center gap-basalt-content-gap\">\n\t\t\t\t{leading ? (\n\t\t\t\t\t<span className=\"flex h-basalt-8 w-basalt-8 items-center justify-center\">{leading}</span>\n\t\t\t\t) : null}\n\t\t\t\t<div className=\"min-w-0\">\n\t\t\t\t\t<p className=\"truncate text-basalt-base font-semibold tracking-tight\">{title}</p>\n\t\t\t\t\t{subtitle ? (\n\t\t\t\t\t\t<p className=\"truncate text-basalt-
|
|
1
|
+
{"version":3,"file":"chat-header.js","names":["ChatHeader","props","cn","BASALT_UI_CLASS","className","leading","title","subtitle","children"],"sources":["../../src/components/chat-header.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface ChatHeaderProps\n\textends Omit<HTMLAttributes<HTMLElement>, \"title\" | \"children\" | \"className\"> {\n\t/**\n\t * Conversation title.\n\t */\n\ttitle: ReactNode;\n\t/**\n\t * Secondary line under the title.\n\t */\n\tsubtitle?: ReactNode;\n\t/**\n\t * Leading mark, usually an icon.\n\t */\n\tleading?: ReactNode;\n\t/**\n\t * Trailing actions.\n\t */\n\tchildren?: ReactNode;\n\t/**\n\t * Optional class name applied to the header element.\n\t * Component inherits native header HTMLAttributes on the root element but does not forward ref.\n\t */\n\tclassName?: string;\n}\n\nexport function ChatHeader({\n\ttitle,\n\tsubtitle,\n\tleading,\n\tchildren,\n\tclassName,\n\t...props\n}: ChatHeaderProps) {\n\treturn (\n\t\t<header\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"flex items-center justify-between gap-basalt-content-gap border-b border-basalt-border/50 px-basalt-panel-x py-basalt-panel-y leading-[var(--basalt-line-body)]\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<div className=\"flex min-w-0 items-center gap-basalt-content-gap\">\n\t\t\t\t{leading ? (\n\t\t\t\t\t<span className=\"flex h-basalt-8 w-basalt-8 items-center justify-center\">{leading}</span>\n\t\t\t\t) : null}\n\t\t\t\t<div className=\"min-w-0\">\n\t\t\t\t\t<p className=\"truncate text-basalt-base font-semibold tracking-tight\">{title}</p>\n\t\t\t\t\t{subtitle ? (\n\t\t\t\t\t\t<p className=\"truncate text-basalt-sm text-basalt-muted-foreground\">{subtitle}</p>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{children ? <div className=\"flex items-center gap-basalt-space-sm\">{children}</div> : null}\n\t\t</header>\n\t);\n}\n"],"mappings":";;;;;AA6BA,SAAgBA,EAAW,EAC1B,UACA,aACA,YACA,aACA,cACA,GAAGC,KACgB;CACnB,OACC,kBAAC,UAAD;EACC,WAAWC,EACVC,GACA,mKACAC,CACD;EACA,GAAIH;EANL,UAAA,CAQC,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACEI,IACA,kBAAC,QAAD;IAAM,WAAU;IAA0D,UAAAA;GAAc,CAAA,IACrF,MACJ,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACC,kBAAC,KAAD;KAAG,WAAU;KAA0D,UAAAC;IAAS,CAAA,GAC/EC,IACA,kBAAC,KAAD;KAAG,WAAU;KAAwD,UAAAA;IAAY,CAAA,IAC9E,IACA;GACD,CAAA,CAAA;EACJ,CAAA,GAAAC,IAAW,kBAAC,OAAD;GAAK,WAAU;GAAyC;EAAc,CAAA,IAAI,IAC/E;;AAEV"}
|
|
@@ -30,7 +30,7 @@ function o({ items: o, activeId: s, onSelect: c, className: l, ...u }) {
|
|
|
30
30
|
className: "truncate text-basalt-base font-medium text-basalt-foreground",
|
|
31
31
|
children: t.title
|
|
32
32
|
}), t.time ? /* @__PURE__ */ i("span", {
|
|
33
|
-
className: "shrink-0 text-basalt-
|
|
33
|
+
className: "shrink-0 text-basalt-sm text-basalt-muted-foreground",
|
|
34
34
|
children: t.time
|
|
35
35
|
}) : null]
|
|
36
36
|
}), t.preview ? /* @__PURE__ */ i("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-inbox.js","names":["ChatInbox","props","highlightRef","useHoverHighlight","cn","NAV_LIST_CLASS","className","items","active","item","activeId","onSelect","NAV_ITEM_CLASS"],"sources":["../../src/components/chat-inbox.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { NAV_ITEM_CLASS, NAV_LIST_CLASS } from \"../utils/navigation\";\nimport { useHoverHighlight } from \"../utils/use-hover-highlight\";\n\nexport interface ChatInboxItem {\n\t/** Stable id for selection. */\n\tid: string;\n\t/** Thread title. */\n\ttitle: string;\n\t/** Last-message preview. */\n\tpreview?: string;\n\t/** Timestamp label. */\n\ttime?: string;\n\t/** Optional leading mark. */\n\tleading?: ReactNode;\n}\n\nexport interface ChatInboxProps\n\textends Omit<HTMLAttributes<HTMLElement>, \"onSelect\" | \"className\"> {\n\t/**\n\t * Threads to list ({ id: string, title: string, preview?: string, time?: string, leading?: ReactNode }[]).\n\t */\n\titems: readonly ChatInboxItem[];\n\t/**\n\t * Selected thread id.\n\t */\n\tactiveId?: string;\n\t/**\n\t * Called when a thread is chosen.\n\t */\n\tonSelect: (id: string) => void;\n\t/**\n\t * Optional class name applied to the navigation element.\n\t * Component inherits native nav HTMLAttributes on the root element but does not forward ref.\n\t */\n\tclassName?: string;\n}\n\nexport function ChatInbox({ items, activeId, onSelect, className, ...props }: ChatInboxProps) {\n\tconst highlightRef = useHoverHighlight();\n\treturn (\n\t\t<nav\n\t\t\tref={highlightRef}\n\t\t\tclassName={cn(\n\t\t\t\tNAV_LIST_CLASS,\n\t\t\t\t\"min-h-0 flex-col overflow-y-auto overscroll-y-contain\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{items.map((item) => {\n\t\t\t\tconst active = item.id === activeId;\n\t\t\t\treturn (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-current={active ? \"true\" : undefined}\n\t\t\t\t\t\tdata-basalt-hover-item=\"\"\n\t\t\t\t\t\tdata-hover-selected={active}\n\t\t\t\t\t\tonClick={() => onSelect(item.id)}\n\t\t\t\t\t\tclassName={cn(NAV_ITEM_CLASS, \"w-full justify-start\")}\n\t\t\t\t\t>\n\t\t\t\t\t\t{item.leading ? (\n\t\t\t\t\t\t\t<span className=\"flex h-basalt-8 w-basalt-8 shrink-0 items-center justify-center\">\n\t\t\t\t\t\t\t\t{item.leading}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t<span className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t\t<span className=\"flex items-baseline justify-between gap-basalt-row-gap\">\n\t\t\t\t\t\t\t\t<span className=\"truncate text-basalt-base font-medium text-basalt-foreground\">\n\t\t\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{item.time ? (\n\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 text-basalt-
|
|
1
|
+
{"version":3,"file":"chat-inbox.js","names":["ChatInbox","props","highlightRef","useHoverHighlight","cn","NAV_LIST_CLASS","className","items","active","item","activeId","onSelect","NAV_ITEM_CLASS"],"sources":["../../src/components/chat-inbox.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { NAV_ITEM_CLASS, NAV_LIST_CLASS } from \"../utils/navigation\";\nimport { useHoverHighlight } from \"../utils/use-hover-highlight\";\n\nexport interface ChatInboxItem {\n\t/** Stable id for selection. */\n\tid: string;\n\t/** Thread title. */\n\ttitle: string;\n\t/** Last-message preview. */\n\tpreview?: string;\n\t/** Timestamp label. */\n\ttime?: string;\n\t/** Optional leading mark. */\n\tleading?: ReactNode;\n}\n\nexport interface ChatInboxProps\n\textends Omit<HTMLAttributes<HTMLElement>, \"onSelect\" | \"className\"> {\n\t/**\n\t * Threads to list ({ id: string, title: string, preview?: string, time?: string, leading?: ReactNode }[]).\n\t */\n\titems: readonly ChatInboxItem[];\n\t/**\n\t * Selected thread id.\n\t */\n\tactiveId?: string;\n\t/**\n\t * Called when a thread is chosen.\n\t */\n\tonSelect: (id: string) => void;\n\t/**\n\t * Optional class name applied to the navigation element.\n\t * Component inherits native nav HTMLAttributes on the root element but does not forward ref.\n\t */\n\tclassName?: string;\n}\n\nexport function ChatInbox({ items, activeId, onSelect, className, ...props }: ChatInboxProps) {\n\tconst highlightRef = useHoverHighlight();\n\treturn (\n\t\t<nav\n\t\t\tref={highlightRef}\n\t\t\tclassName={cn(\n\t\t\t\tNAV_LIST_CLASS,\n\t\t\t\t\"min-h-0 flex-col overflow-y-auto overscroll-y-contain\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{items.map((item) => {\n\t\t\t\tconst active = item.id === activeId;\n\t\t\t\treturn (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-current={active ? \"true\" : undefined}\n\t\t\t\t\t\tdata-basalt-hover-item=\"\"\n\t\t\t\t\t\tdata-hover-selected={active}\n\t\t\t\t\t\tonClick={() => onSelect(item.id)}\n\t\t\t\t\t\tclassName={cn(NAV_ITEM_CLASS, \"w-full justify-start\")}\n\t\t\t\t\t>\n\t\t\t\t\t\t{item.leading ? (\n\t\t\t\t\t\t\t<span className=\"flex h-basalt-8 w-basalt-8 shrink-0 items-center justify-center\">\n\t\t\t\t\t\t\t\t{item.leading}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t<span className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t\t<span className=\"flex items-baseline justify-between gap-basalt-row-gap\">\n\t\t\t\t\t\t\t\t<span className=\"truncate text-basalt-base font-medium text-basalt-foreground\">\n\t\t\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{item.time ? (\n\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t{item.time}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{item.preview ? (\n\t\t\t\t\t\t\t\t<span className=\"mt-basalt-space-xs block truncate text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{item.preview}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</button>\n\t\t\t\t);\n\t\t\t})}\n\t\t</nav>\n\t);\n}\n"],"mappings":";;;;;;AAuCA,SAAgBA,EAAU,EAAE,UAAO,aAAU,aAAU,cAAW,GAAGC,KAAyB;CAC7F,IAAMC,IAAeC,EAAkB;CACvC,OACC,kBAAC,OAAD;EACC,KAAKD;EACL,WAAWE,EACVC,GACA,yDACAC,CACD;EACA,GAAIL;EAEH,UAAAM,EAAM,KAAK,MAAS;GACpB,IAAMC,IAASC,EAAK,OAAOC;GAC3B,OACC,kBAAC,UAAD;IAEC,MAAK;IACL,gBAAcF,IAAS,SAAS,KAAA;IAChC,0BAAuB;IACvB,uBAAqBA;IACrB,eAAeG,EAASF,EAAK,EAAE;IAC/B,WAAWL,EAAGQ,GAAgB,sBAAsB;IAPrD,UAAA,CASEH,EAAK,UACL,kBAAC,QAAD;KAAM,WAAU;KACd,UAAAA,EAAK;IACD,CAAA,IACH,MACJ,kBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,CACC,kBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACC,kBAAC,QAAD;OAAM,WAAU;OACd,UAAAA,EAAK;MACD,CAAA,GACLA,EAAK,OACL,kBAAC,QAAD;OAAM,WAAU;OACd,UAAAA,EAAK;MACD,CAAA,IACH,IACC;KACL,CAAA,GAAAA,EAAK,UACL,kBAAC,QAAD;MAAM,WAAU;MACd,UAAAA,EAAK;KACD,CAAA,IACH,IACC;IACC,CAAA,CAAA;GA9BF,GAAAA,EAAK,EA8BH;EAEV,CAAC;CACG,CAAA;AAEP"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-markdown.js","names":["nodes","tokens","token","raw","node","Heading","streaming","decodeHTML","word","i","CodeHighlighted","List","cn","item","index","href","contextSourceHref","text","cell","row","j","Fragment","ChatMarkdown","rendered","useMemo","marked","content","className"],"sources":["../../src/components/chat-markdown.tsx"],"sourcesContent":["import { decodeHTML } from \"entities\";\nimport { type MarkedToken, marked, type Token } from \"marked\";\nimport { Fragment, type ReactNode, useMemo } from \"react\";\nimport { contextSourceHref } from \"../models/context-cards\";\nimport { cn } from \"../utils/cn\";\nimport { CodeHighlighted } from \"./code\";\n\nexport interface ChatMarkdownProps {\n\t/** Untrusted Markdown. Raw HTML is rendered as text, never injected. */\n\tcontent: string;\n\t/** Animate newly appended prose words; disable for static output. */\n\tstreaming?: boolean;\n\tclassName?: string;\n}\n\nfunction nodes(tokens: readonly Token[], streaming = false): ReactNode {\n\treturn tokens.map((raw, index) => {\n\t\tconst token = raw as MarkedToken;\n\t\tlet node: ReactNode;\n\t\tswitch (token.type) {\n\t\t\tcase \"space\":\n\t\t\tcase \"def\":\n\t\t\t\treturn null;\n\t\t\tcase \"heading\": {\n\t\t\t\tconst Heading = `h${Math.min(6, token.depth + 1)}` as \"h2\";\n\t\t\t\tnode = (\n\t\t\t\t\t<Heading className=\"font-semibold text-basalt-
|
|
1
|
+
{"version":3,"file":"chat-markdown.js","names":["nodes","tokens","token","raw","node","Heading","streaming","decodeHTML","word","i","CodeHighlighted","List","cn","item","index","href","contextSourceHref","text","cell","row","j","Fragment","ChatMarkdown","rendered","useMemo","marked","content","className"],"sources":["../../src/components/chat-markdown.tsx"],"sourcesContent":["import { decodeHTML } from \"entities\";\nimport { type MarkedToken, marked, type Token } from \"marked\";\nimport { Fragment, type ReactNode, useMemo } from \"react\";\nimport { contextSourceHref } from \"../models/context-cards\";\nimport { cn } from \"../utils/cn\";\nimport { CodeHighlighted } from \"./code\";\n\nexport interface ChatMarkdownProps {\n\t/** Untrusted Markdown. Raw HTML is rendered as text, never injected. */\n\tcontent: string;\n\t/** Animate newly appended prose words; disable for static output. */\n\tstreaming?: boolean;\n\tclassName?: string;\n}\n\nfunction nodes(tokens: readonly Token[], streaming = false): ReactNode {\n\treturn tokens.map((raw, index) => {\n\t\tconst token = raw as MarkedToken;\n\t\tlet node: ReactNode;\n\t\tswitch (token.type) {\n\t\t\tcase \"space\":\n\t\t\tcase \"def\":\n\t\t\t\treturn null;\n\t\t\tcase \"heading\": {\n\t\t\t\tconst Heading = `h${Math.min(6, token.depth + 1)}` as \"h2\";\n\t\t\t\tnode = (\n\t\t\t\t\t<Heading className=\"font-semibold text-basalt-xl\">\n\t\t\t\t\t\t{nodes(token.tokens, streaming)}\n\t\t\t\t\t</Heading>\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"paragraph\":\n\t\t\t\tnode = <p>{nodes(token.tokens, streaming)}</p>;\n\t\t\t\tbreak;\n\t\t\tcase \"text\":\n\t\t\t\tnode = token.tokens\n\t\t\t\t\t? nodes(token.tokens, streaming)\n\t\t\t\t\t: streaming\n\t\t\t\t\t\t? decodeHTML(token.text)\n\t\t\t\t\t\t\t\t.split(/(\\s+)/)\n\t\t\t\t\t\t\t\t.map((word, i) =>\n\t\t\t\t\t\t\t\t\t/\\S/.test(word) ? (\n\t\t\t\t\t\t\t\t\t\t<span key={i} className=\"basalt-chat-word\">\n\t\t\t\t\t\t\t\t\t\t\t{word}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\tword\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: decodeHTML(token.text);\n\t\t\t\tbreak;\n\t\t\tcase \"strong\":\n\t\t\t\tnode = <strong>{nodes(token.tokens, streaming)}</strong>;\n\t\t\t\tbreak;\n\t\t\tcase \"em\":\n\t\t\t\tnode = <em>{nodes(token.tokens, streaming)}</em>;\n\t\t\t\tbreak;\n\t\t\tcase \"del\":\n\t\t\t\tnode = <del>{nodes(token.tokens, streaming)}</del>;\n\t\t\t\tbreak;\n\t\t\tcase \"codespan\":\n\t\t\t\tnode = (\n\t\t\t\t\t<code className=\"rounded-basalt-sm bg-basalt-accent px-basalt-space-sm py-basalt-space-xs font-mono text-basalt-sm\">\n\t\t\t\t\t\t{token.text}\n\t\t\t\t\t</code>\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"code\":\n\t\t\t\tnode = <CodeHighlighted code={token.text} title={token.lang || \"text\"} lineNumbers />;\n\t\t\t\tbreak;\n\t\t\tcase \"blockquote\":\n\t\t\t\tnode = (\n\t\t\t\t\t<blockquote className=\"border-l-2 border-basalt-border pl-basalt-space-lg text-basalt-muted-foreground\">\n\t\t\t\t\t\t{nodes(token.tokens, streaming)}\n\t\t\t\t\t</blockquote>\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"list\": {\n\t\t\t\tconst List = token.ordered ? \"ol\" : \"ul\";\n\t\t\t\tnode = (\n\t\t\t\t\t<List\n\t\t\t\t\t\tstart={token.ordered ? Number(token.start) || 1 : undefined}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"space-y-basalt-space-sm pl-basalt-space-lg\",\n\t\t\t\t\t\t\ttoken.ordered ? \"list-decimal\" : \"list-disc\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{token.items.map((item, i) => (\n\t\t\t\t\t\t\t<li key={`${index}-${i}`}>\n\t\t\t\t\t\t\t\t{item.task && (\n\t\t\t\t\t\t\t\t\t<span aria-label={item.checked ? \"Complete\" : \"Incomplete\"} role=\"img\">\n\t\t\t\t\t\t\t\t\t\t{item.checked ? \"☑ \" : \"☐ \"}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{nodes(item.tokens, streaming)}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</List>\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"link\":\n\t\t\tcase \"image\": {\n\t\t\t\tconst href = contextSourceHref(decodeHTML(token.href));\n\t\t\t\tconst text =\n\t\t\t\t\ttoken.type === \"link\" ? nodes(token.tokens, streaming) : decodeHTML(token.text);\n\t\t\t\tnode = href ? (\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={href}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\tclassName=\"text-basalt-primary underline underline-offset-4\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{text}\n\t\t\t\t\t</a>\n\t\t\t\t) : (\n\t\t\t\t\ttext\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"table\":\n\t\t\t\tnode = (\n\t\t\t\t\t<div className=\"max-w-full overflow-x-auto\">\n\t\t\t\t\t\t<table className=\"w-full border-collapse text-left text-basalt-sm\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t{token.header.map((cell, i) => (\n\t\t\t\t\t\t\t\t\t\t<th\n\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"whitespace-nowrap border-b border-basalt-border px-basalt-space-lg py-basalt-space-md\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{nodes(cell.tokens, streaming)}\n\t\t\t\t\t\t\t\t\t\t</th>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t{token.rows.map((row, i) => (\n\t\t\t\t\t\t\t\t\t<tr key={i}>\n\t\t\t\t\t\t\t\t\t\t{row.map((cell, j) => (\n\t\t\t\t\t\t\t\t\t\t\t<td\n\t\t\t\t\t\t\t\t\t\t\t\tkey={j}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"border-b border-basalt-border px-basalt-space-lg py-basalt-space-md\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{nodes(cell.tokens, streaming)}\n\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"br\":\n\t\t\t\tnode = <br />;\n\t\t\t\tbreak;\n\t\t\tcase \"hr\":\n\t\t\t\tnode = <hr className=\"border-basalt-border\" />;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tnode = \"text\" in token ? String(token.text) : token.raw;\n\t\t}\n\t\treturn <Fragment key={index}>{node}</Fragment>;\n\t});\n}\n\nexport function ChatMarkdown({ content, streaming = false, className }: ChatMarkdownProps) {\n\tconst rendered = useMemo(\n\t\t() => nodes(marked.lexer(content, { gfm: true }), streaming),\n\t\t[content, streaming],\n\t);\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"basalt-ui min-w-0 space-y-basalt-space-lg break-words text-basalt-base leading-[var(--basalt-line-relaxed)] [&_p]:whitespace-pre-wrap\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{rendered}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -123,7 +123,7 @@ function v({ variant: v, content: y, streaming: b, trace: x, children: S, author
|
|
|
123
123
|
children: e.name
|
|
124
124
|
}),
|
|
125
125
|
e.type && /* @__PURE__ */ g("span", {
|
|
126
|
-
className: "shrink-0 font-mono text-basalt-
|
|
126
|
+
className: "shrink-0 font-mono text-basalt-sm",
|
|
127
127
|
children: e.type
|
|
128
128
|
}),
|
|
129
129
|
e.href && /* @__PURE__ */ g(l, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-message.js","names":["_Fragment","ChatMessage","vm","useChatMessage","content","sources","author","variant","cn","className","trace","ChatMarkdown","streaming","children","Collapsible","Button","text","Check","Copy","onEdit","Pencil","onRegenerate","RotateCcw","onFeedback","Fragment","feedback","ThumbsUp","ThumbsDown","CollapsibleTrigger","sourcesLabel","FileText","CollapsibleContent","Source","source","ExternalLink"],"sources":["../../src/components/chat-message.tsx"],"sourcesContent":["import {\n\tCheck,\n\tCopy,\n\tExternalLink,\n\tFileText,\n\tPencil,\n\tRotateCcw,\n\tThumbsDown,\n\tThumbsUp,\n} from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useChatMessage } from \"../viewmodels/use-chat-message\";\nimport { Button } from \"./button\";\nimport { ChatMarkdown } from \"./chat-markdown\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"./collapsible\";\n\nexport interface ChatMessageProps {\n\tvariant: \"user\" | \"assistant\";\n\tcontent: string;\n\tstreaming?: boolean;\n\t/** Thinking, tool calls and other trace content before the response. */\n\ttrace?: ReactNode;\n\t/** Approval or result content after the response; use sources for citations. */\n\tchildren?: ReactNode;\n\tauthor?: string;\n\tonEdit?: () => void;\n\tonRegenerate?: () => void;\n\tfeedback?: \"up\" | \"down\";\n\tonFeedback?: (value: \"up\" | \"down\") => void;\n\t/** Compact source disclosure beside message actions. No card wrapper is added. */\n\tsources?: readonly { id: string; name: string; type?: string; href?: string }[];\n\t/** Source disclosure label. @default \"Sources\" */\n\tsourcesLabel?: string;\n\tclassName?: string;\n}\n\nexport function ChatMessage({\n\tvariant,\n\tcontent,\n\tstreaming,\n\ttrace,\n\tchildren,\n\tauthor,\n\tonEdit,\n\tonRegenerate,\n\tfeedback,\n\tonFeedback,\n\tclassName,\n\tsources = [],\n\tsourcesLabel = \"Sources\",\n}: ChatMessageProps) {\n\tconst vm = useChatMessage(content, sources);\n\treturn (\n\t\t<article\n\t\t\taria-label={`${author || (variant === \"user\" ? \"You\" : \"Assistant\")} message`}\n\t\t\tclassName={cn(\"basalt-ui group min-w-0 space-y-basalt-content-gap\", className)}\n\t\t>\n\t\t\t<div className={cn(\"flex\", variant === \"user\" ? \"justify-end\" : \"justify-start\")}>\n\t\t\t\t<div\n\t\t\t\t\tdata-basalt-surface={variant === \"user\" ? \"\" : undefined}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"min-w-0 space-y-basalt-content-gap\",\n\t\t\t\t\t\tvariant === \"user\"\n\t\t\t\t\t\t\t? \"max-w-[90%] rounded-basalt-lg px-basalt-panel-x py-basalt-panel-y\"\n\t\t\t\t\t\t\t: \"w-full\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{trace}\n\t\t\t\t\t{content &&\n\t\t\t\t\t\t(variant === \"user\" ? (\n\t\t\t\t\t\t\t<p className=\"whitespace-pre-wrap break-words text-basalt-base leading-[var(--basalt-line-relaxed)]\">\n\t\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<ChatMarkdown content={content} streaming={streaming} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t{streaming && (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tclassName=\"inline-block size-basalt-2 rounded-basalt-full bg-basalt-primary animate-pulse motion-reduce:animate-none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{!streaming && content && (\n\t\t\t\t<Collapsible className=\"space-y-basalt-content-gap\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tdata-slot=\"chat-actions\"\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex flex-wrap items-center gap-basalt-space-xs text-basalt-muted-foreground\",\n\t\t\t\t\t\t\tvariant === \"user\"\n\t\t\t\t\t\t\t\t? \"justify-end -mr-[calc((var(--basalt-size-action)-var(--basalt-size-icon))/2)]\"\n\t\t\t\t\t\t\t\t: \"-ml-[calc((var(--basalt-size-action)-var(--basalt-size-icon))/2)]\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\taria-label={vm.copied ? \"Copied\" : \"Copy message\"}\n\t\t\t\t\t\t\tonClick={() => void vm.copy((text) => navigator.clipboard.writeText(text))}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{vm.copied ? <Check strokeWidth={1.5} /> : <Copy strokeWidth={1.5} />}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t{onEdit && (\n\t\t\t\t\t\t\t<Button size=\"icon\" variant=\"ghost\" aria-label=\"Edit message\" onClick={onEdit}>\n\t\t\t\t\t\t\t\t<Pencil strokeWidth={1.5} />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onRegenerate && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\taria-label=\"Regenerate response\"\n\t\t\t\t\t\t\t\tonClick={onRegenerate}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<RotateCcw strokeWidth={1.5} />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onFeedback && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\taria-label=\"Helpful\"\n\t\t\t\t\t\t\t\t\taria-pressed={feedback === \"up\"}\n\t\t\t\t\t\t\t\t\tonClick={() => onFeedback(\"up\")}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ThumbsUp strokeWidth={1.5} />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\taria-label=\"Not helpful\"\n\t\t\t\t\t\t\t\t\taria-pressed={feedback === \"down\"}\n\t\t\t\t\t\t\t\t\tonClick={() => onFeedback(\"down\")}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ThumbsDown strokeWidth={1.5} />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{vm.sources.length > 0 && (\n\t\t\t\t\t\t\t<CollapsibleTrigger\n\t\t\t\t\t\t\t\taria-label={`${sourcesLabel} ${vm.sources.length}`}\n\t\t\t\t\t\t\t\tclassName=\"ml-basalt-control-gap min-h-basalt-action gap-basalt-control-gap rounded-basalt-sm px-basalt-space-sm text-basalt-sm font-normal text-basalt-muted-foreground hover:bg-basalt-hover\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-basalt-control-gap\">\n\t\t\t\t\t\t\t\t\t<FileText aria-hidden=\"true\" className=\"size-basalt-icon\" strokeWidth={1.5} />\n\t\t\t\t\t\t\t\t\t<span>{sourcesLabel}</span>\n\t\t\t\t\t\t\t\t\t<span className=\"tabular-nums\">{vm.sources.length}</span>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</CollapsibleTrigger>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{vm.copyError && (\n\t\t\t\t\t\t\t<span role=\"alert\" className=\"text-basalt-sm text-basalt-danger\">\n\t\t\t\t\t\t\t\tCould not copy\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t{vm.sources.length > 0 && (\n\t\t\t\t\t\t<CollapsibleContent unstyled>\n\t\t\t\t\t\t\t<ul aria-label={sourcesLabel} className=\"space-y-basalt-space-xs\">\n\t\t\t\t\t\t\t\t{vm.sources.map((source) => {\n\t\t\t\t\t\t\t\t\tconst Source = source.href ? \"a\" : \"span\";\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<li key={source.id}>\n\t\t\t\t\t\t\t\t\t\t\t<Source\n\t\t\t\t\t\t\t\t\t\t\t\thref={source.href}\n\t\t\t\t\t\t\t\t\t\t\t\ttarget={source.href ? \"_blank\" : undefined}\n\t\t\t\t\t\t\t\t\t\t\t\trel={source.href ? \"noopener noreferrer\" : undefined}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex min-w-0 items-center gap-basalt-row-gap rounded-basalt-sm px-basalt-row-x py-basalt-control-y text-basalt-sm leading-[var(--basalt-line-body)] text-basalt-muted-foreground outline-hidden hover:bg-basalt-hover focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<FileText\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"min-w-0 flex-1 break-words\">{source.name}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{source.type && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 font-mono text-basalt-xs\">{source.type}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t{source.href && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ExternalLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon-sm shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</Source>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t</CollapsibleContent>\n\t\t\t\t\t)}\n\t\t\t\t</Collapsible>\n\t\t\t)}\n\t\t</article>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat-message.js","names":["_Fragment","ChatMessage","vm","useChatMessage","content","sources","author","variant","cn","className","trace","ChatMarkdown","streaming","children","Collapsible","Button","text","Check","Copy","onEdit","Pencil","onRegenerate","RotateCcw","onFeedback","Fragment","feedback","ThumbsUp","ThumbsDown","CollapsibleTrigger","sourcesLabel","FileText","CollapsibleContent","Source","source","ExternalLink"],"sources":["../../src/components/chat-message.tsx"],"sourcesContent":["import {\n\tCheck,\n\tCopy,\n\tExternalLink,\n\tFileText,\n\tPencil,\n\tRotateCcw,\n\tThumbsDown,\n\tThumbsUp,\n} from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useChatMessage } from \"../viewmodels/use-chat-message\";\nimport { Button } from \"./button\";\nimport { ChatMarkdown } from \"./chat-markdown\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"./collapsible\";\n\nexport interface ChatMessageProps {\n\tvariant: \"user\" | \"assistant\";\n\tcontent: string;\n\tstreaming?: boolean;\n\t/** Thinking, tool calls and other trace content before the response. */\n\ttrace?: ReactNode;\n\t/** Approval or result content after the response; use sources for citations. */\n\tchildren?: ReactNode;\n\tauthor?: string;\n\tonEdit?: () => void;\n\tonRegenerate?: () => void;\n\tfeedback?: \"up\" | \"down\";\n\tonFeedback?: (value: \"up\" | \"down\") => void;\n\t/** Compact source disclosure beside message actions. No card wrapper is added. */\n\tsources?: readonly { id: string; name: string; type?: string; href?: string }[];\n\t/** Source disclosure label. @default \"Sources\" */\n\tsourcesLabel?: string;\n\tclassName?: string;\n}\n\nexport function ChatMessage({\n\tvariant,\n\tcontent,\n\tstreaming,\n\ttrace,\n\tchildren,\n\tauthor,\n\tonEdit,\n\tonRegenerate,\n\tfeedback,\n\tonFeedback,\n\tclassName,\n\tsources = [],\n\tsourcesLabel = \"Sources\",\n}: ChatMessageProps) {\n\tconst vm = useChatMessage(content, sources);\n\treturn (\n\t\t<article\n\t\t\taria-label={`${author || (variant === \"user\" ? \"You\" : \"Assistant\")} message`}\n\t\t\tclassName={cn(\"basalt-ui group min-w-0 space-y-basalt-content-gap\", className)}\n\t\t>\n\t\t\t<div className={cn(\"flex\", variant === \"user\" ? \"justify-end\" : \"justify-start\")}>\n\t\t\t\t<div\n\t\t\t\t\tdata-basalt-surface={variant === \"user\" ? \"\" : undefined}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"min-w-0 space-y-basalt-content-gap\",\n\t\t\t\t\t\tvariant === \"user\"\n\t\t\t\t\t\t\t? \"max-w-[90%] rounded-basalt-lg px-basalt-panel-x py-basalt-panel-y\"\n\t\t\t\t\t\t\t: \"w-full\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{trace}\n\t\t\t\t\t{content &&\n\t\t\t\t\t\t(variant === \"user\" ? (\n\t\t\t\t\t\t\t<p className=\"whitespace-pre-wrap break-words text-basalt-base leading-[var(--basalt-line-relaxed)]\">\n\t\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<ChatMarkdown content={content} streaming={streaming} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t{streaming && (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tclassName=\"inline-block size-basalt-2 rounded-basalt-full bg-basalt-primary animate-pulse motion-reduce:animate-none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{!streaming && content && (\n\t\t\t\t<Collapsible className=\"space-y-basalt-content-gap\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tdata-slot=\"chat-actions\"\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex flex-wrap items-center gap-basalt-space-xs text-basalt-muted-foreground\",\n\t\t\t\t\t\t\tvariant === \"user\"\n\t\t\t\t\t\t\t\t? \"justify-end -mr-[calc((var(--basalt-size-action)-var(--basalt-size-icon))/2)]\"\n\t\t\t\t\t\t\t\t: \"-ml-[calc((var(--basalt-size-action)-var(--basalt-size-icon))/2)]\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\taria-label={vm.copied ? \"Copied\" : \"Copy message\"}\n\t\t\t\t\t\t\tonClick={() => void vm.copy((text) => navigator.clipboard.writeText(text))}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{vm.copied ? <Check strokeWidth={1.5} /> : <Copy strokeWidth={1.5} />}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t{onEdit && (\n\t\t\t\t\t\t\t<Button size=\"icon\" variant=\"ghost\" aria-label=\"Edit message\" onClick={onEdit}>\n\t\t\t\t\t\t\t\t<Pencil strokeWidth={1.5} />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onRegenerate && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\taria-label=\"Regenerate response\"\n\t\t\t\t\t\t\t\tonClick={onRegenerate}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<RotateCcw strokeWidth={1.5} />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onFeedback && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\taria-label=\"Helpful\"\n\t\t\t\t\t\t\t\t\taria-pressed={feedback === \"up\"}\n\t\t\t\t\t\t\t\t\tonClick={() => onFeedback(\"up\")}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ThumbsUp strokeWidth={1.5} />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\taria-label=\"Not helpful\"\n\t\t\t\t\t\t\t\t\taria-pressed={feedback === \"down\"}\n\t\t\t\t\t\t\t\t\tonClick={() => onFeedback(\"down\")}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ThumbsDown strokeWidth={1.5} />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{vm.sources.length > 0 && (\n\t\t\t\t\t\t\t<CollapsibleTrigger\n\t\t\t\t\t\t\t\taria-label={`${sourcesLabel} ${vm.sources.length}`}\n\t\t\t\t\t\t\t\tclassName=\"ml-basalt-control-gap min-h-basalt-action gap-basalt-control-gap rounded-basalt-sm px-basalt-space-sm text-basalt-sm font-normal text-basalt-muted-foreground hover:bg-basalt-hover\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-basalt-control-gap\">\n\t\t\t\t\t\t\t\t\t<FileText aria-hidden=\"true\" className=\"size-basalt-icon\" strokeWidth={1.5} />\n\t\t\t\t\t\t\t\t\t<span>{sourcesLabel}</span>\n\t\t\t\t\t\t\t\t\t<span className=\"tabular-nums\">{vm.sources.length}</span>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</CollapsibleTrigger>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{vm.copyError && (\n\t\t\t\t\t\t\t<span role=\"alert\" className=\"text-basalt-sm text-basalt-danger\">\n\t\t\t\t\t\t\t\tCould not copy\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t{vm.sources.length > 0 && (\n\t\t\t\t\t\t<CollapsibleContent unstyled>\n\t\t\t\t\t\t\t<ul aria-label={sourcesLabel} className=\"space-y-basalt-space-xs\">\n\t\t\t\t\t\t\t\t{vm.sources.map((source) => {\n\t\t\t\t\t\t\t\t\tconst Source = source.href ? \"a\" : \"span\";\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<li key={source.id}>\n\t\t\t\t\t\t\t\t\t\t\t<Source\n\t\t\t\t\t\t\t\t\t\t\t\thref={source.href}\n\t\t\t\t\t\t\t\t\t\t\t\ttarget={source.href ? \"_blank\" : undefined}\n\t\t\t\t\t\t\t\t\t\t\t\trel={source.href ? \"noopener noreferrer\" : undefined}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex min-w-0 items-center gap-basalt-row-gap rounded-basalt-sm px-basalt-row-x py-basalt-control-y text-basalt-sm leading-[var(--basalt-line-body)] text-basalt-muted-foreground outline-hidden hover:bg-basalt-hover focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<FileText\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"min-w-0 flex-1 break-words\">{source.name}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{source.type && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 font-mono text-basalt-sm\">{source.type}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t{source.href && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ExternalLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon-sm shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</Source>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t</CollapsibleContent>\n\t\t\t\t\t)}\n\t\t\t\t</Collapsible>\n\t\t\t)}\n\t\t</article>\n\t);\n}\n"],"mappings":"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"}
|
package/dist/components/code.js
CHANGED
|
@@ -43,12 +43,13 @@ function p({ children: u, title: d, icon: f = /* @__PURE__ */ c(s, { strokeWidth
|
|
|
43
43
|
}), /* @__PURE__ */ c("span", {
|
|
44
44
|
id: b,
|
|
45
45
|
title: x,
|
|
46
|
-
className: "min-w-0 break-words font-mono text-basalt-
|
|
46
|
+
className: "min-w-0 break-words font-mono text-basalt-base font-medium leading-[var(--basalt-line-body)] [overflow-wrap:anywhere]",
|
|
47
47
|
children: x
|
|
48
48
|
})]
|
|
49
49
|
}), p && /* @__PURE__ */ l(n, {
|
|
50
50
|
variant: "ghost",
|
|
51
|
-
|
|
51
|
+
size: "sm",
|
|
52
|
+
className: "-my-basalt-space-sm shrink-0 border-0 px-basalt-space-md font-normal text-basalt-muted-foreground [&_svg]:size-basalt-icon-sm",
|
|
52
53
|
"aria-label": C,
|
|
53
54
|
disabled: y.status === "pending",
|
|
54
55
|
onClick: () => void y.copy((e) => navigator.clipboard.writeText(e)),
|
|
@@ -74,7 +75,7 @@ function p({ children: u, title: d, icon: f = /* @__PURE__ */ c(s, { strokeWidth
|
|
|
74
75
|
className: "flex min-w-max",
|
|
75
76
|
children: [m && /* @__PURE__ */ c("span", {
|
|
76
77
|
"aria-hidden": "true",
|
|
77
|
-
className: "shrink-0 select-none border-r border-basalt-border text-right text-basalt-
|
|
78
|
+
className: "shrink-0 select-none border-r border-basalt-border text-right text-basalt-sm tabular-nums text-basalt-muted-foreground",
|
|
78
79
|
style: { width: `calc(${String(y.lines.length).length}ch + 2 * var(--basalt-space-row-x))` },
|
|
79
80
|
children: y.lines.map((e, t) => /* @__PURE__ */ c("span", {
|
|
80
81
|
"data-line-number": t + 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.js","names":["Code","props","cn","className","CodeBlock","CodePanel","CodeHighlighted","code","FileCode2","vm","useCodeBlock","highlighted","id","useId","heading","title","header","copyable","copyLabel","attached","controlSurfaceClass","icon","Button","text","Check","Copy","event","lineNumbers","index","line","token","tokenIndex"],"sources":["../../src/components/code.tsx"],"sourcesContent":["import { Check, Copy, FileCode2 } from \"lucide-react\";\nimport { type HTMLAttributes, type ReactNode, useId } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { controlSurfaceClass } from \"../utils/control-surface\";\nimport { useCodeBlock } from \"../viewmodels/use-code-block\";\nimport { Button } from \"./button\";\n\nexport type CodeProps = {\n\t/** Additional classes for the inline code. */\n\tclassName?: string;\n};\n\nexport function Code({ className, ...props }: CodeProps & HTMLAttributes<HTMLElement>) {\n\treturn (\n\t\t<code\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-basalt-sm bg-basalt-secondary px-basalt-space-md py-basalt-space-xs font-mono text-basalt-sm text-basalt-foreground\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport interface CodeBlockProps\n\textends Omit<HTMLAttributes<HTMLDivElement>, \"children\" | \"title\" | \"className\"> {\n\t/** Exact source text. Copy preserves whitespace and original line endings. */\n\tchildren: string;\n\t/** Filename or label shown in the header. Defaults to \"Code\" when copyable. */\n\ttitle?: string;\n\t/** Decorative header icon. Defaults to a file-code glyph; pass null to hide. */\n\ticon?: ReactNode;\n\t/** Show the copy control and its success/error feedback. @default true */\n\tcopyable?: boolean;\n\t/** Show a non-selectable, screen-reader-hidden line-number gutter. @default false */\n\tlineNumbers?: boolean;\n\t/** Join a card edge without an outer frame. Code retains its own header and content insets. @default false */\n\tattached?: boolean;\n\t/** Additional classes for the panel root, not the inner pre element. */\n\tclassName?: string;\n}\n\nexport function CodeBlock(props: CodeBlockProps) {\n\treturn <CodePanel {...props} />;\n}\n\nexport interface CodeHighlightedProps extends Omit<CodeBlockProps, \"children\"> {\n\t/** Source text to highlight with the built-in lightweight tokenizer. */\n\tcode: string;\n}\n\nexport function CodeHighlighted({ code, ...props }: CodeHighlightedProps) {\n\treturn (\n\t\t<CodePanel {...props} highlighted>\n\t\t\t{code}\n\t\t</CodePanel>\n\t);\n}\n\nfunction CodePanel({\n\tchildren: code,\n\ttitle,\n\ticon = <FileCode2 strokeWidth={1.5} />,\n\tcopyable = true,\n\tlineNumbers = false,\n\tattached = false,\n\tclassName,\n\thighlighted = false,\n\t...props\n}: CodeBlockProps & { highlighted?: boolean }) {\n\tconst vm = useCodeBlock(code, highlighted);\n\tconst id = useId();\n\tconst heading = title || \"Code\";\n\tconst header = Boolean(title) || copyable;\n\tconst copyLabel =\n\t\tvm.status === \"copied\" ? \"Copied\" : vm.status === \"error\" ? \"Copy failed\" : \"Copy code\";\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-code=\"\"\n\t\t\tdata-code-attached={attached || undefined}\n\t\t\tclassName={controlSurfaceClass(\n\t\t\t\tcn(\n\t\t\t\t\t\"flex min-h-0 min-w-0 max-w-full flex-col overflow-hidden text-basalt-foreground\",\n\t\t\t\t\tattached && \"rounded-none border-0 border-t\",\n\t\t\t\t\tclassName,\n\t\t\t\t),\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{header && (\n\t\t\t\t<div\n\t\t\t\t\tdata-slot=\"code-header\"\n\t\t\t\t\tclassName=\"flex shrink-0 flex-wrap items-center justify-between gap-basalt-space-lg border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y\"\n\t\t\t\t>\n\t\t\t\t\t<div className=\"flex min-w-0 flex-1 items-center gap-basalt-row-gap\">\n\t\t\t\t\t\t{icon && (\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tclassName=\"flex size-basalt-icon shrink-0 items-center justify-center text-basalt-muted-foreground [&_svg]:size-basalt-icon\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{icon}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tid={id}\n\t\t\t\t\t\t\ttitle={heading}\n\t\t\t\t\t\t\tclassName=\"min-w-0 break-words font-mono text-basalt-code leading-[var(--basalt-line-row)] [overflow-wrap:anywhere]\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{heading}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{copyable && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tclassName=\"shrink-0 border-0 px-basalt-space-md font-normal text-basalt-muted-foreground [&_svg]:size-basalt-icon-sm\"\n\t\t\t\t\t\t\taria-label={copyLabel}\n\t\t\t\t\t\t\tdisabled={vm.status === \"pending\"}\n\t\t\t\t\t\t\tonClick={() => void vm.copy((text) => navigator.clipboard.writeText(text))}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{vm.status === \"copied\" ? (\n\t\t\t\t\t\t\t\t<Check aria-hidden=\"true\" strokeWidth={1.5} />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<Copy aria-hidden=\"true\" strokeWidth={1.5} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<span>{copyLabel}</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<pre\n\t\t\t\trole=\"region\"\n\t\t\t\taria-labelledby={header ? id : undefined}\n\t\t\t\taria-label={header ? undefined : \"Code\"}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named code overflow region must support keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\tif (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n\t\t\t\t\tif (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.currentTarget.scrollLeft +=\n\t\t\t\t\t\t((event.key === \"ArrowRight\" ? 1 : -1) * event.currentTarget.clientWidth) / 4;\n\t\t\t\t}}\n\t\t\t\tclassName=\"min-h-0 min-w-0 overflow-auto overscroll-x-contain overscroll-y-auto py-basalt-panel-y font-mono text-basalt-sm leading-[var(--basalt-line-body)] outline-hidden focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t>\n\t\t\t\t<span className=\"flex min-w-max\">\n\t\t\t\t\t{lineNumbers && (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tclassName=\"shrink-0 select-none border-r border-basalt-border text-right text-basalt-xs tabular-nums text-basalt-muted-foreground\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: `calc(${String(vm.lines.length).length}ch + 2 * var(--basalt-space-row-x))`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{vm.lines.map((_, index) => (\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\t\tdata-line-number={index + 1}\n\t\t\t\t\t\t\t\t\tclassName=\"block h-[var(--basalt-line-body)] px-basalt-row-x before:content-[attr(data-line-number)]\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t<code\n\t\t\t\t\t\tclassName=\"block flex-1 whitespace-pre px-basalt-panel-x font-mono\"\n\t\t\t\t\t\tstyle={{ minHeight: `calc(${vm.lines.length} * var(--basalt-line-body))` }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{vm.lines.map((line, index) => (\n\t\t\t\t\t\t\t<span key={index} data-code-line=\"\">\n\t\t\t\t\t\t\t\t{line.map((token, tokenIndex) =>\n\t\t\t\t\t\t\t\t\ttoken.className ? (\n\t\t\t\t\t\t\t\t\t\t<span key={tokenIndex} className={token.className}>\n\t\t\t\t\t\t\t\t\t\t\t{token.text}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\ttoken.text\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{index < vm.lines.length - 1 ? \"\\n\" : \"\"}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</code>\n\t\t\t\t</span>\n\t\t\t</pre>\n\t\t\t{copyable && (\n\t\t\t\t<span role={vm.status === \"error\" ? \"alert\" : \"status\"} className=\"sr-only\">\n\t\t\t\t\t{vm.status === \"copied\"\n\t\t\t\t\t\t? \"Code copied\"\n\t\t\t\t\t\t: vm.status === \"error\"\n\t\t\t\t\t\t\t? \"Could not copy code. Try again.\"\n\t\t\t\t\t\t\t: \"\"}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"code.js","names":["Code","props","cn","className","CodeBlock","CodePanel","CodeHighlighted","code","FileCode2","vm","useCodeBlock","highlighted","id","useId","heading","title","header","copyable","copyLabel","attached","controlSurfaceClass","icon","Button","text","Check","Copy","event","lineNumbers","index","line","token","tokenIndex"],"sources":["../../src/components/code.tsx"],"sourcesContent":["import { Check, Copy, FileCode2 } from \"lucide-react\";\nimport { type HTMLAttributes, type ReactNode, useId } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { controlSurfaceClass } from \"../utils/control-surface\";\nimport { useCodeBlock } from \"../viewmodels/use-code-block\";\nimport { Button } from \"./button\";\n\nexport type CodeProps = {\n\t/** Additional classes for the inline code. */\n\tclassName?: string;\n};\n\nexport function Code({ className, ...props }: CodeProps & HTMLAttributes<HTMLElement>) {\n\treturn (\n\t\t<code\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-basalt-sm bg-basalt-secondary px-basalt-space-md py-basalt-space-xs font-mono text-basalt-sm text-basalt-foreground\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport interface CodeBlockProps\n\textends Omit<HTMLAttributes<HTMLDivElement>, \"children\" | \"title\" | \"className\"> {\n\t/** Exact source text. Copy preserves whitespace and original line endings. */\n\tchildren: string;\n\t/** Filename or label shown in the header. Defaults to \"Code\" when copyable. */\n\ttitle?: string;\n\t/** Decorative header icon. Defaults to a file-code glyph; pass null to hide. */\n\ticon?: ReactNode;\n\t/** Show the copy control and its success/error feedback. @default true */\n\tcopyable?: boolean;\n\t/** Show a non-selectable, screen-reader-hidden line-number gutter. @default false */\n\tlineNumbers?: boolean;\n\t/** Join a card edge without an outer frame. Code retains its own header and content insets. @default false */\n\tattached?: boolean;\n\t/** Additional classes for the panel root, not the inner pre element. */\n\tclassName?: string;\n}\n\nexport function CodeBlock(props: CodeBlockProps) {\n\treturn <CodePanel {...props} />;\n}\n\nexport interface CodeHighlightedProps extends Omit<CodeBlockProps, \"children\"> {\n\t/** Source text to highlight with the built-in lightweight tokenizer. */\n\tcode: string;\n}\n\nexport function CodeHighlighted({ code, ...props }: CodeHighlightedProps) {\n\treturn (\n\t\t<CodePanel {...props} highlighted>\n\t\t\t{code}\n\t\t</CodePanel>\n\t);\n}\n\nfunction CodePanel({\n\tchildren: code,\n\ttitle,\n\ticon = <FileCode2 strokeWidth={1.5} />,\n\tcopyable = true,\n\tlineNumbers = false,\n\tattached = false,\n\tclassName,\n\thighlighted = false,\n\t...props\n}: CodeBlockProps & { highlighted?: boolean }) {\n\tconst vm = useCodeBlock(code, highlighted);\n\tconst id = useId();\n\tconst heading = title || \"Code\";\n\tconst header = Boolean(title) || copyable;\n\tconst copyLabel =\n\t\tvm.status === \"copied\" ? \"Copied\" : vm.status === \"error\" ? \"Copy failed\" : \"Copy code\";\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-code=\"\"\n\t\t\tdata-code-attached={attached || undefined}\n\t\t\tclassName={controlSurfaceClass(\n\t\t\t\tcn(\n\t\t\t\t\t\"flex min-h-0 min-w-0 max-w-full flex-col overflow-hidden text-basalt-foreground\",\n\t\t\t\t\tattached && \"rounded-none border-0 border-t\",\n\t\t\t\t\tclassName,\n\t\t\t\t),\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{header && (\n\t\t\t\t<div\n\t\t\t\t\tdata-slot=\"code-header\"\n\t\t\t\t\tclassName=\"flex shrink-0 flex-wrap items-center justify-between gap-basalt-space-lg border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y\"\n\t\t\t\t>\n\t\t\t\t\t<div className=\"flex min-w-0 flex-1 items-center gap-basalt-row-gap\">\n\t\t\t\t\t\t{icon && (\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tclassName=\"flex size-basalt-icon shrink-0 items-center justify-center text-basalt-muted-foreground [&_svg]:size-basalt-icon\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{icon}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tid={id}\n\t\t\t\t\t\t\ttitle={heading}\n\t\t\t\t\t\t\tclassName=\"min-w-0 break-words font-mono text-basalt-base font-medium leading-[var(--basalt-line-body)] [overflow-wrap:anywhere]\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{heading}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{copyable && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tclassName=\"-my-basalt-space-sm shrink-0 border-0 px-basalt-space-md font-normal text-basalt-muted-foreground [&_svg]:size-basalt-icon-sm\"\n\t\t\t\t\t\t\taria-label={copyLabel}\n\t\t\t\t\t\t\tdisabled={vm.status === \"pending\"}\n\t\t\t\t\t\t\tonClick={() => void vm.copy((text) => navigator.clipboard.writeText(text))}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{vm.status === \"copied\" ? (\n\t\t\t\t\t\t\t\t<Check aria-hidden=\"true\" strokeWidth={1.5} />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<Copy aria-hidden=\"true\" strokeWidth={1.5} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<span>{copyLabel}</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<pre\n\t\t\t\trole=\"region\"\n\t\t\t\taria-labelledby={header ? id : undefined}\n\t\t\t\taria-label={header ? undefined : \"Code\"}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named code overflow region must support keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\tif (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n\t\t\t\t\tif (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.currentTarget.scrollLeft +=\n\t\t\t\t\t\t((event.key === \"ArrowRight\" ? 1 : -1) * event.currentTarget.clientWidth) / 4;\n\t\t\t\t}}\n\t\t\t\tclassName=\"min-h-0 min-w-0 overflow-auto overscroll-x-contain overscroll-y-auto py-basalt-panel-y font-mono text-basalt-sm leading-[var(--basalt-line-body)] outline-hidden focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t>\n\t\t\t\t<span className=\"flex min-w-max\">\n\t\t\t\t\t{lineNumbers && (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tclassName=\"shrink-0 select-none border-r border-basalt-border text-right text-basalt-sm tabular-nums text-basalt-muted-foreground\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: `calc(${String(vm.lines.length).length}ch + 2 * var(--basalt-space-row-x))`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{vm.lines.map((_, index) => (\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\t\tdata-line-number={index + 1}\n\t\t\t\t\t\t\t\t\tclassName=\"block h-[var(--basalt-line-body)] px-basalt-row-x before:content-[attr(data-line-number)]\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t<code\n\t\t\t\t\t\tclassName=\"block flex-1 whitespace-pre px-basalt-panel-x font-mono\"\n\t\t\t\t\t\tstyle={{ minHeight: `calc(${vm.lines.length} * var(--basalt-line-body))` }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{vm.lines.map((line, index) => (\n\t\t\t\t\t\t\t<span key={index} data-code-line=\"\">\n\t\t\t\t\t\t\t\t{line.map((token, tokenIndex) =>\n\t\t\t\t\t\t\t\t\ttoken.className ? (\n\t\t\t\t\t\t\t\t\t\t<span key={tokenIndex} className={token.className}>\n\t\t\t\t\t\t\t\t\t\t\t{token.text}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\ttoken.text\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{index < vm.lines.length - 1 ? \"\\n\" : \"\"}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</code>\n\t\t\t\t</span>\n\t\t\t</pre>\n\t\t\t{copyable && (\n\t\t\t\t<span role={vm.status === \"error\" ? \"alert\" : \"status\"} className=\"sr-only\">\n\t\t\t\t\t{vm.status === \"copied\"\n\t\t\t\t\t\t? \"Code copied\"\n\t\t\t\t\t\t: vm.status === \"error\"\n\t\t\t\t\t\t\t? \"Could not copy code. Try again.\"\n\t\t\t\t\t\t\t: \"\"}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ function f({ chunks: f, title: p = "All chunks", totalCount: m, loading: h = !1,
|
|
|
19
19
|
className: "flex items-center gap-basalt-content-gap",
|
|
20
20
|
children: [/* @__PURE__ */ u("h3", {
|
|
21
21
|
id: b,
|
|
22
|
-
className: "text-basalt-
|
|
22
|
+
className: "text-basalt-base font-medium",
|
|
23
23
|
children: p
|
|
24
24
|
}), /* @__PURE__ */ u(n, {
|
|
25
25
|
variant: "secondary",
|
|
@@ -70,7 +70,7 @@ function f({ chunks: f, title: p = "All chunks", totalCount: m, loading: h = !1,
|
|
|
70
70
|
/* @__PURE__ */ d("div", {
|
|
71
71
|
className: "flex flex-wrap items-center justify-between gap-basalt-control-gap border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y",
|
|
72
72
|
children: [/* @__PURE__ */ d("h4", {
|
|
73
|
-
className: "inline-flex min-w-0 items-center gap-basalt-row-gap text-basalt-
|
|
73
|
+
className: "inline-flex min-w-0 items-center gap-basalt-row-gap text-basalt-base leading-[var(--basalt-line-body)] font-medium",
|
|
74
74
|
children: [/* @__PURE__ */ u(l, {
|
|
75
75
|
"aria-hidden": "true",
|
|
76
76
|
className: "size-basalt-icon shrink-0",
|
|
@@ -85,7 +85,7 @@ function f({ chunks: f, title: p = "All chunks", totalCount: m, loading: h = !1,
|
|
|
85
85
|
})]
|
|
86
86
|
}),
|
|
87
87
|
/* @__PURE__ */ u("p", {
|
|
88
|
-
className: "whitespace-pre-wrap break-words px-basalt-panel-x py-basalt-panel-y text-basalt-
|
|
88
|
+
className: "whitespace-pre-wrap break-words px-basalt-panel-x py-basalt-panel-y text-basalt-base leading-[var(--basalt-line-body)] text-basalt-muted-foreground",
|
|
89
89
|
children: e.body
|
|
90
90
|
}),
|
|
91
91
|
/* @__PURE__ */ u("div", {
|
|
@@ -102,7 +102,7 @@ function f({ chunks: f, title: p = "All chunks", totalCount: m, loading: h = !1,
|
|
|
102
102
|
strokeWidth: 1.5
|
|
103
103
|
}),
|
|
104
104
|
/* @__PURE__ */ u("span", {
|
|
105
|
-
className: "shrink-0 font-mono text-basalt-
|
|
105
|
+
className: "shrink-0 font-mono text-basalt-sm text-basalt-muted-foreground",
|
|
106
106
|
children: e.source.type
|
|
107
107
|
}),
|
|
108
108
|
/* @__PURE__ */ u("span", {
|
|
@@ -125,7 +125,7 @@ function f({ chunks: f, title: p = "All chunks", totalCount: m, loading: h = !1,
|
|
|
125
125
|
strokeWidth: 1.5
|
|
126
126
|
}),
|
|
127
127
|
/* @__PURE__ */ u("span", {
|
|
128
|
-
className: "shrink-0 font-mono text-basalt-
|
|
128
|
+
className: "shrink-0 font-mono text-basalt-sm text-basalt-muted-foreground",
|
|
129
129
|
children: e.source.type
|
|
130
130
|
}),
|
|
131
131
|
/* @__PURE__ */ u("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-cards.js","names":["ContextCards","vm","useContextCardsViewModel","chunks","totalCount","id","useId","loading","cn","className","title","Badge","LayerCard","SkeletonLine","error","onRetry","Button","chunk","TextAlignStart","FileText","ExternalLink"],"sources":["../../src/components/context-cards.tsx"],"sourcesContent":["import { ExternalLink, FileText, TextAlignStart } from \"lucide-react\";\nimport { useId } from \"react\";\nimport type { ContextChunk } from \"../models/context-cards\";\nimport { cn } from \"../utils/cn\";\nimport { useContextCardsViewModel } from \"../viewmodels/use-context-cards\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { LayerCard } from \"./layer-card\";\nimport { SkeletonLine } from \"./skeleton-line\";\n\nexport type { ContextChunk } from \"../models/context-cards\";\n\nexport interface ContextCardsProps {\n\t/** Retrieved chunks with stable IDs and caller-owned source metadata. */\n\tchunks: readonly ContextChunk[];\n\t/** Heading for the chunk list. @default \"All chunks\" */\n\ttitle?: string;\n\t/** Total available chunks, when displaying a subset. Never smaller than the visible count. */\n\ttotalCount?: number;\n\tloading?: boolean;\n\terror?: string;\n\tonRetry?: () => void;\n\tclassName?: string;\n}\n\nexport function ContextCards({\n\tchunks,\n\ttitle = \"All chunks\",\n\ttotalCount,\n\tloading = false,\n\terror,\n\tonRetry,\n\tclassName,\n}: ContextCardsProps) {\n\tconst vm = useContextCardsViewModel(chunks, totalCount);\n\tconst id = useId();\n\treturn (\n\t\t<section\n\t\t\taria-labelledby={id}\n\t\t\taria-busy={loading || undefined}\n\t\t\tclassName={cn(\n\t\t\t\t\"basalt-ui min-w-0 space-y-basalt-content-gap leading-[var(--basalt-line-body)]\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<header className=\"flex items-center gap-basalt-content-gap\">\n\t\t\t\t<h3 id={id} className=\"text-basalt-
|
|
1
|
+
{"version":3,"file":"context-cards.js","names":["ContextCards","vm","useContextCardsViewModel","chunks","totalCount","id","useId","loading","cn","className","title","Badge","LayerCard","SkeletonLine","error","onRetry","Button","chunk","TextAlignStart","FileText","ExternalLink"],"sources":["../../src/components/context-cards.tsx"],"sourcesContent":["import { ExternalLink, FileText, TextAlignStart } from \"lucide-react\";\nimport { useId } from \"react\";\nimport type { ContextChunk } from \"../models/context-cards\";\nimport { cn } from \"../utils/cn\";\nimport { useContextCardsViewModel } from \"../viewmodels/use-context-cards\";\nimport { Badge } from \"./badge\";\nimport { Button } from \"./button\";\nimport { LayerCard } from \"./layer-card\";\nimport { SkeletonLine } from \"./skeleton-line\";\n\nexport type { ContextChunk } from \"../models/context-cards\";\n\nexport interface ContextCardsProps {\n\t/** Retrieved chunks with stable IDs and caller-owned source metadata. */\n\tchunks: readonly ContextChunk[];\n\t/** Heading for the chunk list. @default \"All chunks\" */\n\ttitle?: string;\n\t/** Total available chunks, when displaying a subset. Never smaller than the visible count. */\n\ttotalCount?: number;\n\tloading?: boolean;\n\terror?: string;\n\tonRetry?: () => void;\n\tclassName?: string;\n}\n\nexport function ContextCards({\n\tchunks,\n\ttitle = \"All chunks\",\n\ttotalCount,\n\tloading = false,\n\terror,\n\tonRetry,\n\tclassName,\n}: ContextCardsProps) {\n\tconst vm = useContextCardsViewModel(chunks, totalCount);\n\tconst id = useId();\n\treturn (\n\t\t<section\n\t\t\taria-labelledby={id}\n\t\t\taria-busy={loading || undefined}\n\t\t\tclassName={cn(\n\t\t\t\t\"basalt-ui min-w-0 space-y-basalt-content-gap leading-[var(--basalt-line-body)]\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<header className=\"flex items-center gap-basalt-content-gap\">\n\t\t\t\t<h3 id={id} className=\"text-basalt-base font-medium\">\n\t\t\t\t\t{title}\n\t\t\t\t</h3>\n\t\t\t\t<Badge variant=\"secondary\" className=\"tabular-nums leading-[var(--basalt-line-compact)]\">\n\t\t\t\t\t{vm.count}\n\t\t\t\t</Badge>\n\t\t\t</header>\n\t\t\t{loading ? (\n\t\t\t\t<LayerCard padding=\"sm\">\n\t\t\t\t\t<div role=\"status\" aria-label=\"Loading context\" className=\"space-y-basalt-space-lg\">\n\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t</div>\n\t\t\t\t</LayerCard>\n\t\t\t) : error ? (\n\t\t\t\t<LayerCard padding=\"sm\">\n\t\t\t\t\t<p role=\"alert\" className=\"text-basalt-base text-basalt-danger\">\n\t\t\t\t\t\t{error}\n\t\t\t\t\t</p>\n\t\t\t\t\t{onRetry && (\n\t\t\t\t\t\t<Button size=\"sm\" variant=\"outline\" className=\"mt-basalt-space-lg\" onClick={onRetry}>\n\t\t\t\t\t\t\tTry again\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</LayerCard>\n\t\t\t) : vm.chunks.length === 0 ? (\n\t\t\t\t<p\n\t\t\t\t\trole=\"status\"\n\t\t\t\t\tclassName=\"py-basalt-space-lg text-basalt-base text-basalt-muted-foreground\"\n\t\t\t\t>\n\t\t\t\t\tNo context retrieved\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul className=\"space-y-basalt-content-gap\">\n\t\t\t\t\t{vm.chunks.map((chunk) => (\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\tkey={chunk.id}\n\t\t\t\t\t\t\tclassName=\"basalt-agent-reveal\"\n\t\t\t\t\t\t\tstyle={{ animationDelay: `${chunk.delay}ms`, animationFillMode: \"both\" }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<LayerCard padding=\"none\" className=\"min-w-0 overflow-hidden\">\n\t\t\t\t\t\t\t\t<div className=\"flex flex-wrap items-center justify-between gap-basalt-control-gap border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t\t\t\t\t\t<h4 className=\"inline-flex min-w-0 items-center gap-basalt-row-gap text-basalt-base leading-[var(--basalt-line-body)] font-medium\">\n\t\t\t\t\t\t\t\t\t\t<TextAlignStart\n\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<span className=\"break-words\">{chunk.title}</span>\n\t\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 text-basalt-sm tabular-nums text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t{chunk.characters.toLocaleString(\"en-US\")} characters\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<p className=\"whitespace-pre-wrap break-words px-basalt-panel-x py-basalt-panel-y text-basalt-base leading-[var(--basalt-line-body)] text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{chunk.body}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<div className=\"flex min-w-0 px-basalt-panel-x pb-basalt-panel-y\">\n\t\t\t\t\t\t\t\t\t{chunk.href ? (\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\thref={chunk.href}\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"inline-flex max-w-full items-center gap-basalt-control-gap py-basalt-space-xs text-basalt-sm text-basalt-foreground outline-hidden hover:bg-basalt-hover focus-visible:ring-2 focus-visible:ring-basalt-ring\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<FileText\n\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 font-mono text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t{chunk.source.type}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"truncate\" title={chunk.source.name}>\n\t\t\t\t\t\t\t\t\t\t\t\t{chunk.source.name}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<ExternalLink\n\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<span className=\"inline-flex max-w-full items-center gap-basalt-control-gap py-basalt-space-xs text-basalt-sm\">\n\t\t\t\t\t\t\t\t\t\t\t<FileText\n\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 font-mono text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t{chunk.source.type}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"truncate\" title={chunk.source.name}>\n\t\t\t\t\t\t\t\t\t\t\t\t{chunk.source.name}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</LayerCard>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</section>\n\t);\n}\n"],"mappings":";;;;;;;;;;;AAyBA,SAAgBA,EAAa,EAC5B,WACA,WAAQ,cACR,eACA,aAAU,IACV,UACA,YACA,gBACqB;CACrB,IAAMC,IAAKC,EAAyBC,GAAQC,CAAU,GAChDC,IAAKC,EAAM;CACjB,OACC,kBAAC,WAAD;EACC,mBAAiBD;EACjB,aAAWE,KAAW,KAAA;EACtB,WAAWC,EACV,kFACAC,CACD;EAND,UAAA,CAQC,kBAAC,UAAD;GAAQ,WAAU;GAAlB,UAAA,CACC,kBAAC,MAAD;IAAQ;IAAI,WAAU;IACpB,UAAAC;GACE,CAAA,GACJ,kBAACC,GAAD;IAAO,SAAQ;IAAY,WAAU;IACnC,UAAAV,EAAG;GACE,CAAA,CACA;EACP,CAAA,GAAAM,IACA,kBAACK,GAAD;GAAW,SAAQ;GAClB,UAAA,kBAAC,OAAD;IAAK,MAAK;IAAS,cAAW;IAAkB,WAAU;IAA1D,UAAA;KACC,kBAACC,GAAD,CAAe,CAAA;KACf,kBAACA,GAAD,CAAe,CAAA;KACf,kBAACA,GAAD,CAAe,CAAA;IACX;;EACK,CAAA,IACRC,IACH,kBAACF,GAAD;GAAW,SAAQ;GAAnB,UAAA,CACC,kBAAC,KAAD;IAAG,MAAK;IAAQ,WAAU;IACxB,UAAAE;GACC,CAAA,GACFC,KACA,kBAACC,GAAD;IAAQ,MAAK;IAAK,SAAQ;IAAU,WAAU;IAAqB,SAASD;IAAS,UAAA;GAE7E,CAAA,CAEC;EACR,CAAA,IAAAd,EAAG,OAAO,WAAW,IACxB,kBAAC,KAAD;GACC,MAAK;GACL,WAAU;GACV,UAAA;EAEE,CAAA,IAEH,kBAAC,MAAD;GAAI,WAAU;GACZ,UAAAA,EAAG,OAAO,KAAK,MACf,kBAAC,MAAD;IAEC,WAAU;IACV,OAAO;KAAE,gBAAgB,GAAGgB,EAAM,MAAM;KAAK,mBAAmB;IAAO;IAEvE,UAAA,kBAACL,GAAD;KAAW,SAAQ;KAAO,WAAU;KAApC,UAAA;MACC,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACC,kBAAC,MAAD;QAAI,WAAU;QAAd,UAAA,CACC,kBAACM,GAAD;SACC,eAAY;SACZ,WAAU;SACV,aAAa;QACb,CAAA,GACD,kBAAC,QAAD;SAAM,WAAU;SAAe,UAAAD,EAAM;QAAY,CAAA,CAC9C;OACJ,CAAA,GAAA,kBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA,CACEA,EAAM,WAAW,eAAe,OAAO,GAAE,aACrC;OACF,CAAA,CAAA;;MACL,kBAAC,KAAD;OAAG,WAAU;OACX,UAAAA,EAAM;MACL,CAAA;MACH,kBAAC,OAAD;OAAK,WAAU;OACb,UAAAA,EAAM,OACN,kBAAC,KAAD;QACC,MAAMA,EAAM;QACZ,QAAO;QACP,KAAI;QACJ,WAAU;QAJX,UAAA;SAMC,kBAACE,GAAD;UACC,eAAY;UACZ,WAAU;UACV,aAAa;SACb,CAAA;SACD,kBAAC,QAAD;UAAM,WAAU;UACd,UAAAF,EAAM,OAAO;SACT,CAAA;SACN,kBAAC,QAAD;UAAM,WAAU;UAAW,OAAOA,EAAM,OAAO;UAC7C,UAAAA,EAAM,OAAO;SACT,CAAA;SACN,kBAACG,GAAD;UACC,eAAY;UACZ,WAAU;UACV,aAAa;SACb,CAAA;QACC;OAEH,CAAA,IAAA,kBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA;SACC,kBAACD,GAAD;UACC,eAAY;UACZ,WAAU;UACV,aAAa;SACb,CAAA;SACD,kBAAC,QAAD;UAAM,WAAU;UACd,UAAAF,EAAM,OAAO;SACT,CAAA;SACN,kBAAC,QAAD;UAAM,WAAU;UAAW,OAAOA,EAAM,OAAO;UAC7C,UAAAA,EAAM,OAAO;SACT,CAAA;QACD;;MAEH,CAAA;KACK;;GACR,GA/DEA,EAAM,EA+DR,CACJ;EACE,CAAA,CAEG;;AAEX"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
import { type TableTextAlign } from "./table.js";
|
|
3
|
+
export type DataTableEdge = "inset" | "attached";
|
|
2
4
|
export type DataTableColumn<T> = {
|
|
3
5
|
id: string;
|
|
4
6
|
header: string;
|
|
@@ -17,6 +19,8 @@ export type DataTableColumn<T> = {
|
|
|
17
19
|
headerClassName?: string;
|
|
18
20
|
/** Classes applied to each data cell. */
|
|
19
21
|
cellClassName?: string;
|
|
22
|
+
/** Logical header and cell alignment. Omitted cells inherit from the table. */
|
|
23
|
+
textAlign?: TableTextAlign;
|
|
20
24
|
};
|
|
21
25
|
export type DataTableSort = {
|
|
22
26
|
id: string;
|
|
@@ -116,5 +120,7 @@ export type DataTableProps<T = unknown> = {
|
|
|
116
120
|
"aria-label"?: string;
|
|
117
121
|
/** ID of additional table instructions or summary. */
|
|
118
122
|
"aria-describedby"?: string;
|
|
123
|
+
/** Direct-card rails on the first and last display columns. @default "inset" */
|
|
124
|
+
edge?: DataTableEdge;
|
|
119
125
|
};
|
|
120
|
-
export declare function DataTable<T>({ data, columns, filter, loading, empty, selected, defaultSelected, onSelectedChange, multiple, page, defaultPage, pageSize, onPageChange, getRowId, className, maxHeight, rowNumbers, sort: controlledSort, defaultSort, onSortChange, manualSorting, manualPagination, manualFiltering, total, error, onRetry, retryLabel, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, }: DataTableProps<T>): import("react").JSX.Element;
|
|
126
|
+
export declare function DataTable<T>({ data, columns, filter, loading, empty, selected, defaultSelected, onSelectedChange, multiple, page, defaultPage, pageSize, onPageChange, getRowId, className, maxHeight, rowNumbers, sort: controlledSort, defaultSort, onSortChange, manualSorting, manualPagination, manualFiltering, total, error, onRetry, retryLabel, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, edge, }: DataTableProps<T>): import("react").JSX.Element;
|