@nocoo/basalt 3.1.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 +108 -46
- package/ai/USAGE.md +1 -1
- package/ai/registry.json +115 -73
- 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/dialog.js +2 -2
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/diff-table.js +2 -2
- 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 +2 -2
- 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 +2 -0
- package/dist/components/table.js +10 -12
- 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 +119 -85
- package/dist/styles/tailwind.css +1 -0
- package/dist/styles/tokens.css +82 -39
- package/package.json +1 -1
|
@@ -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":";;;;;;;;;AAeA,SAASA,EAAM,GAA0B,IAAY,IAAkB;CACtE,OAAOC,EAAO,KAAK,GAAK,MAAU;EACjC,IAAMC,IAAQC,GACVC;EACJ,QAAQF,EAAM,MAAd;GACC,KAAK;GACL,KAAK,OACJ,OAAO;GACR,KAAK,WAAW;IACf,IAAMG,IAAU,IAAI,KAAK,IAAI,GAAGH,EAAM,QAAQ,CAAC;IAC/C,IACC,kBAACG,GAAD;KAAS,WAAU;KACjB,UAAAL,EAAME,EAAM,QAAQI,CAAS;IACtB,CAAA;IAEV;GACD;GACA,KAAK;IACJ,IAAO,kBAAC,KAAD,EAAA,UAAIN,EAAME,EAAM,QAAQI,CAAS,EAAK,CAAA;IAC7C;GACD,KAAK;IACJ,IAAOJ,EAAM,SACVF,EAAME,EAAM,QAAQI,CAAS,IAC7BA,IACCC,EAAWL,EAAM,IAAI,CAAC,CACrB,MAAM,OAAO,CAAC,CACd,KAAK,GAAM,MACX,KAAK,KAAKM,CAAI,IACb,kBAAC,QAAD;KAAc,WAAU;KACtB,UAAAA;IACI,GAFKC,CAEL,IAEND,CAEF,IACAD,EAAWL,EAAM,IAAI;IACzB;GACD,KAAK;IACJ,IAAO,kBAAC,UAAD,EAAA,UAASF,EAAME,EAAM,QAAQI,CAAS,EAAU,CAAA;IACvD;GACD,KAAK;IACJ,IAAO,kBAAC,MAAD,EAAA,UAAKN,EAAME,EAAM,QAAQI,CAAS,EAAM,CAAA;IAC/C;GACD,KAAK;IACJ,IAAO,kBAAC,OAAD,EAAA,UAAMN,EAAME,EAAM,QAAQI,CAAS,EAAO,CAAA;IACjD;GACD,KAAK;IACJ,IACC,kBAAC,QAAD;KAAM,WAAU;KACd,UAAAJ,EAAM;IACF,CAAA;IAEP;GACD,KAAK;IACJ,IAAO,kBAACQ,GAAD;KAAiB,MAAMR,EAAM;KAAM,OAAOA,EAAM,QAAQ;KAAQ,aAAA;IAAa,CAAA;IACpF;GACD,KAAK;IACJ,IACC,kBAAC,cAAD;KAAY,WAAU;KACpB,UAAAF,EAAME,EAAM,QAAQI,CAAS;IACnB,CAAA;IAEb;GACD,KAAK,QAAQ;IACZ,IAAMK,IAAOT,EAAM,UAAU,OAAO;IACpC,IACC,kBAACS,GAAD;KACC,OAAOT,EAAM,UAAU,OAAOA,EAAM,KAAK,KAAK,IAAI,KAAA;KAClD,WAAWU,EACV,8CACAV,EAAM,UAAU,iBAAiB,WAClC;KAEC,UAAAA,EAAM,MAAM,KAAK,GAAM,MACvB,kBAAC,MAAD,EAAA,UAAA,CACEW,EAAK,QACL,kBAAC,QAAD;MAAM,cAAYA,EAAK,UAAU,aAAa;MAAc,MAAK;MAC/D,UAAAA,EAAK,UAAU,OAAO;KAClB,CAAA,GAENb,EAAMa,EAAK,QAAQP,CAAS,CAC1B,EAAA,GAPK,GAAGQ,EAAM,GAAGL,GAOjB,CACJ;IACI,CAAA;IAEP;GACD;GACA,KAAK;GACL,KAAK,SAAS;IACb,IAAMM,IAAOC,EAAkBT,EAAWL,EAAM,IAAI,CAAC,GAC/Ce,IACLf,EAAM,SAAS,SAASF,EAAME,EAAM,QAAQI,CAAS,IAAIC,EAAWL,EAAM,IAAI;IAC/E,IAAOa,IACN,kBAAC,KAAD;KACO;KACN,QAAO;KACP,KAAI;KACJ,WAAU;KAET,UAAAE;IACC,CAAA,IAEHA;IAED;GACD;GACA,KAAK;IACJ,IACC,kBAAC,OAAD;KAAK,WAAU;KACd,UAAA,kBAAC,SAAD;MAAO,WAAU;MAAjB,UAAA,CACC,kBAAC,SAAD,EAAA,UACC,kBAAC,MAAD,EAAA,UACEf,EAAM,OAAO,KAAK,GAAM,MACxB,kBAAC,MAAD;OAEC,WAAU;OAET,UAAAF,EAAMkB,EAAK,QAAQZ,CAAS;MAC1B,GAJEG,CAIF,CACJ,EACE,CAAA,EACE,CAAA,GACP,kBAAC,SAAD,EAAA,UACEP,EAAM,KAAK,KAAK,GAAK,MACrB,kBAAC,MAAD,EAAA,UACEiB,EAAI,KAAK,GAAM,MACf,kBAAC,MAAD;OAEC,WAAU;OAET,UAAAnB,EAAMkB,EAAK,QAAQZ,CAAS;MAC1B,GAJEc,CAIF,CACJ,EACE,GATKX,CASL,CACJ,EACK,CAAA,CACD;;IACH,CAAA;IAEN;GACD,KAAK;IACJ,IAAO,kBAAC,MAAD,CAAK,CAAA;IACZ;GACD,KAAK;IACJ,IAAO,kBAAC,MAAD,EAAI,WAAU,uBAAwB,CAAA;IAC7C;GACD,SACC,IAAO,UAAUP,IAAQ,OAAOA,EAAM,IAAI,IAAIA,EAAM;EACtD;EACA,OAAO,kBAACmB,GAAD,EAAA,UAAuBjB,EAAe,GAAvBU,CAAuB;CAC9C,CAAC;AACF;AAEA,SAAgBQ,EAAa,EAAE,YAAS,eAAY,IAAO,gBAAgC;CAC1F,IAAMC,IAAWC,QACVxB,EAAMyB,EAAO,MAAMC,GAAS,EAAE,KAAK,GAAK,CAAC,GAAGpB,CAAS,GAC3D,CAACoB,GAASpB,CAAS,CACpB;CACA,OACC,kBAAC,OAAD;EACC,WAAWM,EACV,yIACAe,CACD;EAEC,UAAAJ;CACG,CAAA;AAEP"}
|
|
@@ -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":"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"}
|
|
@@ -46,13 +46,13 @@ var g = i.forwardRef(({ className: e, children: t, size: n = "base", disablePoin
|
|
|
46
46
|
g.displayName = s.Content.displayName;
|
|
47
47
|
var _ = i.forwardRef(({ className: t, ...n }, r) => /* @__PURE__ */ a(s.Title, {
|
|
48
48
|
ref: r,
|
|
49
|
-
className: e("min-w-0 text-basalt-
|
|
49
|
+
className: e("min-w-0 text-basalt-xl font-semibold leading-basalt-tight tracking-tight wrap-anywhere", t),
|
|
50
50
|
...n
|
|
51
51
|
}));
|
|
52
52
|
_.displayName = s.Title.displayName;
|
|
53
53
|
var v = i.forwardRef(({ className: t, ...n }, r) => /* @__PURE__ */ a(s.Description, {
|
|
54
54
|
ref: r,
|
|
55
|
-
className: e("text-basalt-
|
|
55
|
+
className: e("text-basalt-base leading-[var(--basalt-line-relaxed)] text-basalt-muted-foreground", t),
|
|
56
56
|
...n
|
|
57
57
|
}));
|
|
58
58
|
v.displayName = s.Description.displayName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","names":["React","DialogPrimitive","DIALOG_SIZES","dialogOverlayClass","cn","OVERLAY_LAYER","OVERLAY_MOTION","className","dialogPanelClass","BASALT_UI_CLASS","size","Dialog","DialogTrigger","DialogClose","DialogPortal","DialogOverlay","props","DialogContent","disablePointerDismissal","event","onPointerDownOutside","onInteractOutside","DialogTitle","DialogDescription","DialogHeader","DialogFooter"],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport const DIALOG_SIZES = {\n\tsm: \"sm:w-basalt-72\",\n\tbase: \"sm:w-basalt-96\",\n\tlg: \"sm:w-[32rem]\",\n\txl: \"sm:w-[48rem]\",\n} as const;\n\nexport type DialogSize = keyof typeof DIALOG_SIZES;\n\nexport function dialogOverlayClass(className?: string) {\n\treturn cn(\n\t\t\"fixed inset-0 bg-basalt-backdrop/40 backdrop-blur-md\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-overlay-in data-[state=closed]:animate-basalt-overlay-out\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n}\n\nexport function dialogPanelClass({\n\tsize = \"base\",\n\tclassName,\n}: {\n\tsize?: DialogSize;\n\tclassName?: string;\n} = {}) {\n\treturn cn(\n\t\tBASALT_UI_CLASS,\n\t\t\"fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-basalt-card sm:p-basalt-card-lg text-basalt-foreground shadow-lg ring-1 ring-basalt-border\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-dialog-in data-[state=closed]:animate-basalt-dialog-out\",\n\t\tOVERLAY_MOTION,\n\t\tDIALOG_SIZES[size],\n\t\tclassName,\n\t);\n}\n\ntype RadixDialogProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>;\ntype RadixDialogTriggerProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;\ntype RadixDialogPortalProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>;\ntype RadixDialogOverlayProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>;\ntype RadixDialogContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>;\ntype RadixDialogTitleProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>;\ntype RadixDialogDescriptionProps = React.ComponentPropsWithoutRef<\n\ttypeof DialogPrimitive.Description\n>;\ntype RadixDialogCloseProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;\n\nexport interface DialogProps\n\textends Omit<RadixDialogProps, \"open\" | \"defaultOpen\" | \"onOpenChange\" | \"modal\"> {\n\t/**\n\t * Controlled open state of the dialog.\n\t */\n\topen?: RadixDialogProps[\"open\"];\n\t/**\n\t * Uncontrolled default open state of the dialog on initial render.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDialogProps[\"defaultOpen\"];\n\t/**\n\t * Callback invoked when the open state changes.\n\t */\n\tonOpenChange?: RadixDialogProps[\"onOpenChange\"];\n\t/**\n\t * Whether the dialog renders modally, preventing outside interaction and hiding background content from screen readers.\n\t * @default true\n\t */\n\tmodal?: RadixDialogProps[\"modal\"];\n}\n\nexport const Dialog: React.FC<DialogProps> = DialogPrimitive.Root;\n\nexport interface DialogTriggerProps extends Omit<RadixDialogTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Trigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTriggerProps[\"asChild\"];\n}\n\nexport const DialogTrigger = DialogPrimitive.Trigger;\n\nexport interface DialogCloseProps extends Omit<RadixDialogCloseProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Close forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogCloseProps[\"asChild\"];\n}\n\nexport const DialogClose = DialogPrimitive.Close;\n\nexport interface DialogPortalProps\n\textends Omit<RadixDialogPortalProps, \"container\" | \"forceMount\"> {\n\t/**\n\t * Target container element where the dialog overlay and content portal should mount.\n\t */\n\tcontainer?: RadixDialogPortalProps[\"container\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogPortalProps[\"forceMount\"];\n}\n\nexport const DialogPortal = DialogPrimitive.Portal;\n\nexport interface DialogOverlayProps\n\textends Omit<RadixDialogOverlayProps, \"asChild\" | \"forceMount\"> {\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Overlay forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogOverlayProps[\"asChild\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogOverlayProps[\"forceMount\"];\n}\n\nexport const DialogOverlay = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Overlay>,\n\tDialogOverlayProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Overlay ref={ref} className={dialogOverlayClass(className)} {...props} />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nexport interface DialogContentProps\n\textends Omit<\n\t\tRadixDialogContentProps,\n\t\t| \"size\"\n\t\t| \"disablePointerDismissal\"\n\t\t| \"asChild\"\n\t\t| \"forceMount\"\n\t\t| \"trapFocus\"\n\t\t| \"onOpenAutoFocus\"\n\t\t| \"onCloseAutoFocus\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"onFocusOutside\"\n\t\t| \"onInteractOutside\"\n\t> {\n\t/**\n\t * Fixed desktop width preset. Dialog panel scrolls vertically when content overflows available viewport height.\n\t * @default \"base\"\n\t */\n\tsize?: DialogSize;\n\t/**\n\t * When true, pointer interactions outside the dialog panel are prevented from dismissing the dialog.\n\t * @default false\n\t */\n\tdisablePointerDismissal?: boolean;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Content forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogContentProps[\"asChild\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t * Note: Keeping modal content forceMounted may isolate background interactions until unmounted.\n\t */\n\tforceMount?: RadixDialogContentProps[\"forceMount\"];\n\t/**\n\t * Event handler called when auto-focusing the first element on open. Can be prevented with event.preventDefault().\n\t */\n\tonOpenAutoFocus?: RadixDialogContentProps[\"onOpenAutoFocus\"];\n\t/**\n\t * Event handler called when restoring focus on close. Can be prevented with event.preventDefault().\n\t */\n\tonCloseAutoFocus?: RadixDialogContentProps[\"onCloseAutoFocus\"];\n\t/**\n\t * Event handler called when the Escape key is pressed. Can be prevented with event.preventDefault().\n\t */\n\tonEscapeKeyDown?: RadixDialogContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Event handler called when a pointer event occurs outside the dialog bounds.\n\t */\n\tonPointerDownOutside?: RadixDialogContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Event handler called when focus moves outside the dialog bounds.\n\t */\n\tonFocusOutside?: RadixDialogContentProps[\"onFocusOutside\"];\n\t/**\n\t * Event handler called when any interaction (pointer or focus) occurs outside the dialog bounds.\n\t */\n\tonInteractOutside?: RadixDialogContentProps[\"onInteractOutside\"];\n}\n\nexport const DialogContent = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Content>,\n\tDialogContentProps\n>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tsize = \"base\",\n\t\t\tdisablePointerDismissal = false,\n\t\t\tonPointerDownOutside,\n\t\t\tonInteractOutside,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<DialogPortal forceMount={props.forceMount}>\n\t\t\t<DialogOverlay forceMount={props.forceMount} />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tdata-basalt-surface-root=\"\"\n\t\t\t\tclassName={dialogPanelClass({ size, className })}\n\t\t\t\tonPointerDownOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonPointerDownOutside?.(event);\n\t\t\t\t}}\n\t\t\t\tonInteractOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonInteractOutside?.(event);\n\t\t\t\t}}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t),\n);\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nexport interface DialogTitleProps extends Omit<RadixDialogTitleProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered heading element to the child element, merging props and behavior.\n\t * Title forwards ref to HTMLHeadingElement and inherits native h2 attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTitleProps[\"asChild\"];\n}\n\nexport const DialogTitle = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Title>,\n\tDialogTitleProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"min-w-0 text-basalt-3xl font-semibold tracking-tight wrap-anywhere\", className)}\n\t\t{...props}\n\t/>\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nexport interface DialogDescriptionProps extends Omit<RadixDialogDescriptionProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered paragraph element to the child element, merging props and behavior.\n\t * Description forwards ref to HTMLParagraphElement and inherits native p attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogDescriptionProps[\"asChild\"];\n}\n\nexport const DialogDescription = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Description>,\n\tDialogDescriptionProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-basalt-lg text-basalt-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogHeader = ({ className, ...props }: DialogHeaderProps) => (\n\t<div className={cn(\"flex flex-col space-y-basalt-space-md text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogFooter = ({ className, ...props }: DialogFooterProps) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"mt-basalt-layout flex flex-col-reverse gap-basalt-space-lg sm:flex-row sm:justify-end\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\nDialogFooter.displayName = \"DialogFooter\";\n"],"mappings":";;;;;;;;AAMA,IAAaE,IAAe;CAC3B,IAAI;CACJ,MAAM;CACN,IAAI;CACJ,IAAI;AACL;AAIA,SAAgBC,EAAmB,GAAoB;CACtD,OAAOC,EACN,wDACAC,GACA,8FACAC,GACAC,CACD;AACD;AAEA,SAAgBC,EAAiB,EAChC,UAAO,QACP,iBAIG,CAAC,GAAG;CACP,OAAOJ,EACNK,GACA,kQACAJ,GACA,4FACAC,GACAJ,EAAaQ,IACbH,CACD;AACD;AAmCA,IAAaI,IAAgCV,EAAgB,MAWhDW,IAAgBX,EAAgB,SAWhCY,IAAcZ,EAAgB,OAc9Ba,IAAeb,EAAgB,QAgB/Bc,IAAgBf,EAAM,YAGhC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,SAAjB;CAA8B;CAAK,WAAWE,EAAmBI,CAAS;CAAG,GAAIS;AAAQ,CAAA,CACzF;AACD,EAAc,cAAcf,EAAgB,QAAQ;AAkEpD,IAAagB,IAAgBjB,EAAM,YAKjC,EACC,cACA,aACA,UAAO,QACP,6BAA0B,IAC1B,yBACA,sBACA,GAAGgB,KAEJ,MAEA,kBAACF,GAAD;CAAc,YAAYE,EAAM;CAAhC,UAAA,CACC,kBAACD,GAAD,EAAe,YAAYC,EAAM,WAAa,CAAA,GAC9C,kBAACf,EAAgB,SAAjB;EACM;EACL,4BAAyB;EACzB,WAAWO,EAAiB;GAAE;GAAM;EAAU,CAAC;EAC/C,uBAAuB,MAAU;GAIhC,AAHIU,KACHC,EAAM,eAAe,GAEtBC,IAAuBD,CAAK;EAC7B;EACA,oBAAoB,MAAU;GAI7B,AAHID,KACHC,EAAM,eAAe,GAEtBE,IAAoBF,CAAK;EAC1B;EACA,GAAIH;EAEH;CACuB,CAAA,CACZ;AAEhB,CAAA,CAAA;AACA,EAAc,cAAcf,EAAgB,QAAQ;AAWpD,IAAaqB,IAActB,EAAM,YAG9B,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,OAAjB;CACM;CACL,WAAWG,EAAG,sEAAsEG,CAAS;CAC7F,GAAIS;AACJ,CAAA,CACD;AACD,EAAY,cAAcf,EAAgB,MAAM;AAWhD,IAAasB,IAAoBvB,EAAM,YAGpC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,aAAjB;CACM;CACL,WAAWG,EAAG,+CAA+CG,CAAS;CACtE,GAAIS;AACJ,CAAA,CACD;AACD,EAAkB,cAAcf,EAAgB,YAAY;AAI5D,IAAauB,KAAgB,EAAE,cAAW,GAAGR,QAC5C,kBAAC,OAAD;CAAK,WAAWZ,EAAG,mDAAmDG,CAAS;CAAG,GAAIS;AAAQ,CAAA;AAE/F,EAAa,cAAc;AAI3B,IAAaS,KAAgB,EAAE,cAAW,GAAGT,QAC5C,kBAAC,OAAD;CACC,WAAWZ,EACV,yFACAG,CACD;CACA,GAAIS;AACJ,CAAA;AAEF,EAAa,cAAc"}
|
|
1
|
+
{"version":3,"file":"dialog.js","names":["React","DialogPrimitive","DIALOG_SIZES","dialogOverlayClass","cn","OVERLAY_LAYER","OVERLAY_MOTION","className","dialogPanelClass","BASALT_UI_CLASS","size","Dialog","DialogTrigger","DialogClose","DialogPortal","DialogOverlay","props","DialogContent","disablePointerDismissal","event","onPointerDownOutside","onInteractOutside","DialogTitle","DialogDescription","DialogHeader","DialogFooter"],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport const DIALOG_SIZES = {\n\tsm: \"sm:w-basalt-72\",\n\tbase: \"sm:w-basalt-96\",\n\tlg: \"sm:w-[32rem]\",\n\txl: \"sm:w-[48rem]\",\n} as const;\n\nexport type DialogSize = keyof typeof DIALOG_SIZES;\n\nexport function dialogOverlayClass(className?: string) {\n\treturn cn(\n\t\t\"fixed inset-0 bg-basalt-backdrop/40 backdrop-blur-md\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-overlay-in data-[state=closed]:animate-basalt-overlay-out\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n}\n\nexport function dialogPanelClass({\n\tsize = \"base\",\n\tclassName,\n}: {\n\tsize?: DialogSize;\n\tclassName?: string;\n} = {}) {\n\treturn cn(\n\t\tBASALT_UI_CLASS,\n\t\t\"fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-basalt-card sm:p-basalt-card-lg text-basalt-foreground shadow-lg ring-1 ring-basalt-border\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-dialog-in data-[state=closed]:animate-basalt-dialog-out\",\n\t\tOVERLAY_MOTION,\n\t\tDIALOG_SIZES[size],\n\t\tclassName,\n\t);\n}\n\ntype RadixDialogProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>;\ntype RadixDialogTriggerProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;\ntype RadixDialogPortalProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>;\ntype RadixDialogOverlayProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>;\ntype RadixDialogContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>;\ntype RadixDialogTitleProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>;\ntype RadixDialogDescriptionProps = React.ComponentPropsWithoutRef<\n\ttypeof DialogPrimitive.Description\n>;\ntype RadixDialogCloseProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;\n\nexport interface DialogProps\n\textends Omit<RadixDialogProps, \"open\" | \"defaultOpen\" | \"onOpenChange\" | \"modal\"> {\n\t/**\n\t * Controlled open state of the dialog.\n\t */\n\topen?: RadixDialogProps[\"open\"];\n\t/**\n\t * Uncontrolled default open state of the dialog on initial render.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDialogProps[\"defaultOpen\"];\n\t/**\n\t * Callback invoked when the open state changes.\n\t */\n\tonOpenChange?: RadixDialogProps[\"onOpenChange\"];\n\t/**\n\t * Whether the dialog renders modally, preventing outside interaction and hiding background content from screen readers.\n\t * @default true\n\t */\n\tmodal?: RadixDialogProps[\"modal\"];\n}\n\nexport const Dialog: React.FC<DialogProps> = DialogPrimitive.Root;\n\nexport interface DialogTriggerProps extends Omit<RadixDialogTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Trigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTriggerProps[\"asChild\"];\n}\n\nexport const DialogTrigger = DialogPrimitive.Trigger;\n\nexport interface DialogCloseProps extends Omit<RadixDialogCloseProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Close forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogCloseProps[\"asChild\"];\n}\n\nexport const DialogClose = DialogPrimitive.Close;\n\nexport interface DialogPortalProps\n\textends Omit<RadixDialogPortalProps, \"container\" | \"forceMount\"> {\n\t/**\n\t * Target container element where the dialog overlay and content portal should mount.\n\t */\n\tcontainer?: RadixDialogPortalProps[\"container\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogPortalProps[\"forceMount\"];\n}\n\nexport const DialogPortal = DialogPrimitive.Portal;\n\nexport interface DialogOverlayProps\n\textends Omit<RadixDialogOverlayProps, \"asChild\" | \"forceMount\"> {\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Overlay forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogOverlayProps[\"asChild\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogOverlayProps[\"forceMount\"];\n}\n\nexport const DialogOverlay = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Overlay>,\n\tDialogOverlayProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Overlay ref={ref} className={dialogOverlayClass(className)} {...props} />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nexport interface DialogContentProps\n\textends Omit<\n\t\tRadixDialogContentProps,\n\t\t| \"size\"\n\t\t| \"disablePointerDismissal\"\n\t\t| \"asChild\"\n\t\t| \"forceMount\"\n\t\t| \"trapFocus\"\n\t\t| \"onOpenAutoFocus\"\n\t\t| \"onCloseAutoFocus\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"onFocusOutside\"\n\t\t| \"onInteractOutside\"\n\t> {\n\t/**\n\t * Fixed desktop width preset. Dialog panel scrolls vertically when content overflows available viewport height.\n\t * @default \"base\"\n\t */\n\tsize?: DialogSize;\n\t/**\n\t * When true, pointer interactions outside the dialog panel are prevented from dismissing the dialog.\n\t * @default false\n\t */\n\tdisablePointerDismissal?: boolean;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Content forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogContentProps[\"asChild\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t * Note: Keeping modal content forceMounted may isolate background interactions until unmounted.\n\t */\n\tforceMount?: RadixDialogContentProps[\"forceMount\"];\n\t/**\n\t * Event handler called when auto-focusing the first element on open. Can be prevented with event.preventDefault().\n\t */\n\tonOpenAutoFocus?: RadixDialogContentProps[\"onOpenAutoFocus\"];\n\t/**\n\t * Event handler called when restoring focus on close. Can be prevented with event.preventDefault().\n\t */\n\tonCloseAutoFocus?: RadixDialogContentProps[\"onCloseAutoFocus\"];\n\t/**\n\t * Event handler called when the Escape key is pressed. Can be prevented with event.preventDefault().\n\t */\n\tonEscapeKeyDown?: RadixDialogContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Event handler called when a pointer event occurs outside the dialog bounds.\n\t */\n\tonPointerDownOutside?: RadixDialogContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Event handler called when focus moves outside the dialog bounds.\n\t */\n\tonFocusOutside?: RadixDialogContentProps[\"onFocusOutside\"];\n\t/**\n\t * Event handler called when any interaction (pointer or focus) occurs outside the dialog bounds.\n\t */\n\tonInteractOutside?: RadixDialogContentProps[\"onInteractOutside\"];\n}\n\nexport const DialogContent = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Content>,\n\tDialogContentProps\n>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tsize = \"base\",\n\t\t\tdisablePointerDismissal = false,\n\t\t\tonPointerDownOutside,\n\t\t\tonInteractOutside,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<DialogPortal forceMount={props.forceMount}>\n\t\t\t<DialogOverlay forceMount={props.forceMount} />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tdata-basalt-surface-root=\"\"\n\t\t\t\tclassName={dialogPanelClass({ size, className })}\n\t\t\t\tonPointerDownOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonPointerDownOutside?.(event);\n\t\t\t\t}}\n\t\t\t\tonInteractOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonInteractOutside?.(event);\n\t\t\t\t}}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t),\n);\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nexport interface DialogTitleProps extends Omit<RadixDialogTitleProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered heading element to the child element, merging props and behavior.\n\t * Title forwards ref to HTMLHeadingElement and inherits native h2 attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTitleProps[\"asChild\"];\n}\n\nexport const DialogTitle = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Title>,\n\tDialogTitleProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"min-w-0 text-basalt-xl font-semibold leading-basalt-tight tracking-tight wrap-anywhere\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nexport interface DialogDescriptionProps extends Omit<RadixDialogDescriptionProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered paragraph element to the child element, merging props and behavior.\n\t * Description forwards ref to HTMLParagraphElement and inherits native p attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogDescriptionProps[\"asChild\"];\n}\n\nexport const DialogDescription = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Description>,\n\tDialogDescriptionProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"text-basalt-base leading-[var(--basalt-line-relaxed)] text-basalt-muted-foreground\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogHeader = ({ className, ...props }: DialogHeaderProps) => (\n\t<div className={cn(\"flex flex-col space-y-basalt-space-md text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogFooter = ({ className, ...props }: DialogFooterProps) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"mt-basalt-layout flex flex-col-reverse gap-basalt-space-lg sm:flex-row sm:justify-end\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\nDialogFooter.displayName = \"DialogFooter\";\n"],"mappings":";;;;;;;;AAMA,IAAaE,IAAe;CAC3B,IAAI;CACJ,MAAM;CACN,IAAI;CACJ,IAAI;AACL;AAIA,SAAgBC,EAAmB,GAAoB;CACtD,OAAOC,EACN,wDACAC,GACA,8FACAC,GACAC,CACD;AACD;AAEA,SAAgBC,EAAiB,EAChC,UAAO,QACP,iBAIG,CAAC,GAAG;CACP,OAAOJ,EACNK,GACA,kQACAJ,GACA,4FACAC,GACAJ,EAAaQ,IACbH,CACD;AACD;AAmCA,IAAaI,IAAgCV,EAAgB,MAWhDW,IAAgBX,EAAgB,SAWhCY,IAAcZ,EAAgB,OAc9Ba,IAAeb,EAAgB,QAgB/Bc,IAAgBf,EAAM,YAGhC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,SAAjB;CAA8B;CAAK,WAAWE,EAAmBI,CAAS;CAAG,GAAIS;AAAQ,CAAA,CACzF;AACD,EAAc,cAAcf,EAAgB,QAAQ;AAkEpD,IAAagB,IAAgBjB,EAAM,YAKjC,EACC,cACA,aACA,UAAO,QACP,6BAA0B,IAC1B,yBACA,sBACA,GAAGgB,KAEJ,MAEA,kBAACF,GAAD;CAAc,YAAYE,EAAM;CAAhC,UAAA,CACC,kBAACD,GAAD,EAAe,YAAYC,EAAM,WAAa,CAAA,GAC9C,kBAACf,EAAgB,SAAjB;EACM;EACL,4BAAyB;EACzB,WAAWO,EAAiB;GAAE;GAAM;EAAU,CAAC;EAC/C,uBAAuB,MAAU;GAIhC,AAHIU,KACHC,EAAM,eAAe,GAEtBC,IAAuBD,CAAK;EAC7B;EACA,oBAAoB,MAAU;GAI7B,AAHID,KACHC,EAAM,eAAe,GAEtBE,IAAoBF,CAAK;EAC1B;EACA,GAAIH;EAEH;CACuB,CAAA,CACZ;AAEhB,CAAA,CAAA;AACA,EAAc,cAAcf,EAAgB,QAAQ;AAWpD,IAAaqB,IAActB,EAAM,YAG9B,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,OAAjB;CACM;CACL,WAAWG,EACV,0FACAG,CACD;CACA,GAAIS;AACJ,CAAA,CACD;AACD,EAAY,cAAcf,EAAgB,MAAM;AAWhD,IAAasB,IAAoBvB,EAAM,YAGpC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,aAAjB;CACM;CACL,WAAWG,EACV,sFACAG,CACD;CACA,GAAIS;AACJ,CAAA,CACD;AACD,EAAkB,cAAcf,EAAgB,YAAY;AAI5D,IAAauB,KAAgB,EAAE,cAAW,GAAGR,QAC5C,kBAAC,OAAD;CAAK,WAAWZ,EAAG,mDAAmDG,CAAS;CAAG,GAAIS;AAAQ,CAAA;AAE/F,EAAa,cAAc;AAI3B,IAAaS,KAAgB,EAAE,cAAW,GAAGT,QAC5C,kBAAC,OAAD;CACC,WAAWZ,EACV,yFACAG,CACD;CACA,GAAIS;AACJ,CAAA;AAEF,EAAa,cAAc"}
|
|
@@ -20,7 +20,7 @@ function v({ title: v = "Proposed changes", columns: y, className: b, ...x }) {
|
|
|
20
20
|
className: "flex flex-wrap items-center justify-between gap-basalt-content-gap border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y",
|
|
21
21
|
children: [/* @__PURE__ */ g("h3", {
|
|
22
22
|
id: C,
|
|
23
|
-
className: "text-basalt-
|
|
23
|
+
className: "text-basalt-base font-medium",
|
|
24
24
|
children: v
|
|
25
25
|
}), /* @__PURE__ */ g("span", {
|
|
26
26
|
className: "text-basalt-sm text-basalt-muted-foreground",
|
|
@@ -68,7 +68,7 @@ function v({ title: v = "Proposed changes", columns: y, className: b, ...x }) {
|
|
|
68
68
|
/* @__PURE__ */ g(s, {
|
|
69
69
|
className: "whitespace-nowrap ps-basalt-table-edge text-basalt-sm",
|
|
70
70
|
children: /* @__PURE__ */ _("span", {
|
|
71
|
-
className: "inline-flex items-center gap-basalt-control-gap leading-[var(--basalt-line-body)]",
|
|
71
|
+
className: e("inline-flex items-center gap-basalt-control-gap leading-[var(--basalt-line-body)]", t.change === "add" && "text-basalt-success", t.change === "remove" && "text-basalt-destructive"),
|
|
72
72
|
children: [/* @__PURE__ */ g("span", {
|
|
73
73
|
"data-diff-marker": "",
|
|
74
74
|
"aria-hidden": "true",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-table.js","names":["_Fragment","Fragment$1","DiffTable","props","vm","useDiffTableViewModel","id","useId","LayerCard","cn","className","title","Table","TableHeader","TableRow","TableHead","columns","column","TableBody","included","row","event","TableCell","Plus","Minus","Checkbox","Check","Button"],"sources":["../../src/components/diff-table.tsx"],"sourcesContent":["import { Check, Minus, Plus } from \"lucide-react\";\nimport { useId } from \"react\";\nimport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\nimport { cn } from \"../utils/cn\";\nimport { useDiffTableViewModel } from \"../viewmodels/use-diff-table\";\nimport { Button } from \"./button\";\nimport { Checkbox } from \"./checkbox\";\nimport { LayerCard } from \"./layer-card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\n\nexport interface DiffTableProps {\n\t/** Stable columns and text/number cells. */\n\tcolumns: readonly DiffTableColumn[];\n\t/** Proposed rows; remount with a new key for a different proposal. */\n\trows: readonly DiffTableRow[];\n\t/** Heading and accessible table name. @default \"Proposed changes\" */\n\ttitle?: string;\n\t/** Explicitly apply only selected changes; rejection keeps the selection for retry. */\n\tonApply: (changes: readonly DiffTableRow[]) => void | Promise<void>;\n\tdisabled?: boolean;\n\tclassName?: string;\n}\n\nexport function DiffTable({\n\ttitle = \"Proposed changes\",\n\tcolumns,\n\tclassName,\n\t...props\n}: DiffTableProps) {\n\tconst vm = useDiffTableViewModel(props);\n\tconst id = useId();\n\treturn (\n\t\t<LayerCard\n\t\t\tpadding=\"none\"\n\t\t\taria-labelledby={id}\n\t\t\tclassName={cn(\"min-w-0 overflow-hidden leading-[var(--basalt-line-body)]\", className)}\n\t\t>\n\t\t\t<header className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t<h3 id={id} className=\"text-basalt-code font-medium\">\n\t\t\t\t\t{title}\n\t\t\t\t</h3>\n\t\t\t\t<span className=\"text-basalt-sm text-basalt-muted-foreground\">Select changes to apply</span>\n\t\t\t</header>\n\t\t\t<div\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={`${title} scroll area`}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named overflow region supports keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tclassName=\"overflow-x-auto outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t>\n\t\t\t\t<Table aria-label={title} aria-busy={vm.status === \"applying\" || undefined}>\n\t\t\t\t\t<TableHeader>\n\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t<TableHead scope=\"col\" className=\"ps-basalt-table-edge\">\n\t\t\t\t\t\t\t\tChange\n\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<TableHead key={column.id} scope=\"col\" style={{ minWidth: column.width }}>\n\t\t\t\t\t\t\t\t\t{column.label}\n\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t<TableHead scope=\"col\" className=\"pe-basalt-table-edge\">\n\t\t\t\t\t\t\t\t<span className=\"sr-only\">Include change</span>\n\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t</TableHeader>\n\t\t\t\t\t<TableBody>\n\t\t\t\t\t\t{props.rows.map((row) => {\n\t\t\t\t\t\t\tconst included = row.change !== \"unchanged\" && !vm.excluded.includes(row.id);\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\tdata-diff-change={row.change}\n\t\t\t\t\t\t\t\t\tdata-included={included}\n\t\t\t\t\t\t\t\t\taria-selected={row.change !== \"unchanged\" ? included : undefined}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"basalt-agent-reveal\",\n\t\t\t\t\t\t\t\t\t\trow.change !== \"unchanged\" && !vm.blocked && \"cursor-pointer\",\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\tif (event.target instanceof Element && event.target.closest(\"button, a, input\"))\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\tvm.toggle(row.id);\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\t<TableCell className=\"whitespace-nowrap ps-basalt-table-edge text-basalt-sm\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"inline-flex items-center gap-basalt-control-gap leading-[var(--basalt-line-body)]\">\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\tdata-diff-marker=\"\"\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=\"inline-flex size-basalt-icon-sm shrink-0 items-center justify-center\"\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{row.change === \"add\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Plus className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : row.change === \"remove\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Minus className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : null}\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{row.change === \"unchanged\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"Keep\"\n\t\t\t\t\t\t\t\t\t\t\t\t: row.change === \"add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"Add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: \"Remove\"}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\t\t\tkey={column.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"whitespace-nowrap\",\n\t\t\t\t\t\t\t\t\t\t\t\tincluded && row.change === \"remove\" && \"line-through\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ minWidth: column.width }}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{row.values[column.id] ?? \"—\"}\n\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t<TableCell className=\"pe-basalt-table-edge\">\n\t\t\t\t\t\t\t\t\t\t{row.change !== \"unchanged\" && (\n\t\t\t\t\t\t\t\t\t\t\t<Checkbox\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled={vm.blocked}\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={included}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={`Include ${row.change === \"add\" ? \"addition\" : \"removal\"} ${row.label}`}\n\t\t\t\t\t\t\t\t\t\t\t\tonCheckedChange={() => vm.toggle(row.id)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{props.rows.length === 0 && (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\tcolSpan={columns.length + 2}\n\t\t\t\t\t\t\t\t\tclassName=\"ps-basalt-table-edge pe-basalt-table-edge\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<p role=\"status\" className=\"text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\tNo proposed changes\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</TableBody>\n\t\t\t\t</Table>\n\t\t\t</div>\n\t\t\t{vm.error && (\n\t\t\t\t<p\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tclassName=\"px-basalt-panel-x py-basalt-panel-y text-basalt-sm text-basalt-danger\"\n\t\t\t\t>\n\t\t\t\t\t{vm.error}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<footer className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-t border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t{vm.status === \"applied\" ? (\n\t\t\t\t\t<p\n\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\tclassName=\"inline-flex items-center gap-basalt-space-md text-basalt-base\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Check aria-hidden=\"true\" className=\"size-basalt-icon\" />\n\t\t\t\t\t\t{vm.selected.length} changes applied\n\t\t\t\t\t</p>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"text-basalt-sm tabular-nums text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t{vm.removals} removals · {vm.additions} additions\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tloading={vm.status === \"applying\"}\n\t\t\t\t\t\t\tdisabled={vm.blocked || vm.selected.length === 0}\n\t\t\t\t\t\t\tonClick={() => void vm.apply()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tApply {vm.selected.length} changes\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</footer>\n\t\t</LayerCard>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"diff-table.js","names":["_Fragment","Fragment$1","DiffTable","props","vm","useDiffTableViewModel","id","useId","LayerCard","cn","className","title","Table","TableHeader","TableRow","TableHead","columns","column","TableBody","included","row","event","TableCell","Plus","Minus","Checkbox","Check","Button"],"sources":["../../src/components/diff-table.tsx"],"sourcesContent":["import { Check, Minus, Plus } from \"lucide-react\";\nimport { useId } from \"react\";\nimport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\nimport { cn } from \"../utils/cn\";\nimport { useDiffTableViewModel } from \"../viewmodels/use-diff-table\";\nimport { Button } from \"./button\";\nimport { Checkbox } from \"./checkbox\";\nimport { LayerCard } from \"./layer-card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\n\nexport interface DiffTableProps {\n\t/** Stable columns and text/number cells. */\n\tcolumns: readonly DiffTableColumn[];\n\t/** Proposed rows; remount with a new key for a different proposal. */\n\trows: readonly DiffTableRow[];\n\t/** Heading and accessible table name. @default \"Proposed changes\" */\n\ttitle?: string;\n\t/** Explicitly apply only selected changes; rejection keeps the selection for retry. */\n\tonApply: (changes: readonly DiffTableRow[]) => void | Promise<void>;\n\tdisabled?: boolean;\n\tclassName?: string;\n}\n\nexport function DiffTable({\n\ttitle = \"Proposed changes\",\n\tcolumns,\n\tclassName,\n\t...props\n}: DiffTableProps) {\n\tconst vm = useDiffTableViewModel(props);\n\tconst id = useId();\n\treturn (\n\t\t<LayerCard\n\t\t\tpadding=\"none\"\n\t\t\taria-labelledby={id}\n\t\t\tclassName={cn(\"min-w-0 overflow-hidden leading-[var(--basalt-line-body)]\", className)}\n\t\t>\n\t\t\t<header className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\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<span className=\"text-basalt-sm text-basalt-muted-foreground\">Select changes to apply</span>\n\t\t\t</header>\n\t\t\t<div\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={`${title} scroll area`}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named overflow region supports keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tclassName=\"overflow-x-auto outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t>\n\t\t\t\t<Table aria-label={title} aria-busy={vm.status === \"applying\" || undefined}>\n\t\t\t\t\t<TableHeader>\n\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t<TableHead scope=\"col\" className=\"ps-basalt-table-edge\">\n\t\t\t\t\t\t\t\tChange\n\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<TableHead key={column.id} scope=\"col\" style={{ minWidth: column.width }}>\n\t\t\t\t\t\t\t\t\t{column.label}\n\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t<TableHead scope=\"col\" className=\"pe-basalt-table-edge\">\n\t\t\t\t\t\t\t\t<span className=\"sr-only\">Include change</span>\n\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t</TableHeader>\n\t\t\t\t\t<TableBody>\n\t\t\t\t\t\t{props.rows.map((row) => {\n\t\t\t\t\t\t\tconst included = row.change !== \"unchanged\" && !vm.excluded.includes(row.id);\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\tdata-diff-change={row.change}\n\t\t\t\t\t\t\t\t\tdata-included={included}\n\t\t\t\t\t\t\t\t\taria-selected={row.change !== \"unchanged\" ? included : undefined}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"basalt-agent-reveal\",\n\t\t\t\t\t\t\t\t\t\trow.change !== \"unchanged\" && !vm.blocked && \"cursor-pointer\",\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\tif (event.target instanceof Element && event.target.closest(\"button, a, input\"))\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\tvm.toggle(row.id);\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\t<TableCell className=\"whitespace-nowrap ps-basalt-table-edge text-basalt-sm\">\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"inline-flex items-center gap-basalt-control-gap leading-[var(--basalt-line-body)]\",\n\t\t\t\t\t\t\t\t\t\t\t\trow.change === \"add\" && \"text-basalt-success\",\n\t\t\t\t\t\t\t\t\t\t\t\trow.change === \"remove\" && \"text-basalt-destructive\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\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\tdata-diff-marker=\"\"\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=\"inline-flex size-basalt-icon-sm shrink-0 items-center justify-center\"\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{row.change === \"add\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Plus className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : row.change === \"remove\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Minus className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : null}\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{row.change === \"unchanged\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"Keep\"\n\t\t\t\t\t\t\t\t\t\t\t\t: row.change === \"add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"Add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: \"Remove\"}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\t\t\tkey={column.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"whitespace-nowrap\",\n\t\t\t\t\t\t\t\t\t\t\t\tincluded && row.change === \"remove\" && \"line-through\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ minWidth: column.width }}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{row.values[column.id] ?? \"—\"}\n\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t<TableCell className=\"pe-basalt-table-edge\">\n\t\t\t\t\t\t\t\t\t\t{row.change !== \"unchanged\" && (\n\t\t\t\t\t\t\t\t\t\t\t<Checkbox\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled={vm.blocked}\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={included}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={`Include ${row.change === \"add\" ? \"addition\" : \"removal\"} ${row.label}`}\n\t\t\t\t\t\t\t\t\t\t\t\tonCheckedChange={() => vm.toggle(row.id)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{props.rows.length === 0 && (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\tcolSpan={columns.length + 2}\n\t\t\t\t\t\t\t\t\tclassName=\"ps-basalt-table-edge pe-basalt-table-edge\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<p role=\"status\" className=\"text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\tNo proposed changes\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</TableBody>\n\t\t\t\t</Table>\n\t\t\t</div>\n\t\t\t{vm.error && (\n\t\t\t\t<p\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tclassName=\"px-basalt-panel-x py-basalt-panel-y text-basalt-sm text-basalt-danger\"\n\t\t\t\t>\n\t\t\t\t\t{vm.error}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<footer className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-t border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t{vm.status === \"applied\" ? (\n\t\t\t\t\t<p\n\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\tclassName=\"inline-flex items-center gap-basalt-space-md text-basalt-base\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Check aria-hidden=\"true\" className=\"size-basalt-icon\" />\n\t\t\t\t\t\t{vm.selected.length} changes applied\n\t\t\t\t\t</p>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"text-basalt-sm tabular-nums text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t{vm.removals} removals · {vm.additions} additions\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tloading={vm.status === \"applying\"}\n\t\t\t\t\t\t\tdisabled={vm.blocked || vm.selected.length === 0}\n\t\t\t\t\t\t\tonClick={() => void vm.apply()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tApply {vm.selected.length} changes\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</footer>\n\t\t</LayerCard>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { jsx as i } from "react/jsx-runtime";
|
|
|
8
8
|
var a = {
|
|
9
9
|
sm: "min-h-basalt-textarea-sm px-basalt-space-lg py-basalt-space-md text-basalt-sm",
|
|
10
10
|
default: "min-h-basalt-textarea px-basalt-control-x py-basalt-space-lg text-basalt-base",
|
|
11
|
-
lg: "min-h-basalt-textarea-lg px-basalt-control-x-lg py-basalt-space-lg text-basalt-
|
|
11
|
+
lg: "min-h-basalt-textarea-lg px-basalt-control-x-lg py-basalt-space-lg text-basalt-base"
|
|
12
12
|
}, o = {
|
|
13
13
|
"data-1p-ignore": "true",
|
|
14
14
|
"data-bwignore": "true",
|