@2lab.ai/ui 0.1.1 → 0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call-card.js","sources":["../src/components/tool-call-card/logic.ts","../src/components/tool-call-card/strings.ts","../src/components/tool-call-card/styles.ts","../src/components/tool-call-card/tool-call-card.ts","../src/components/tool-call-card/tool-call-group.ts"],"sourcesContent":["import { esc } from '../../core/html';\n\n/**\n * `running` — the call is in flight. `success` / `error` — it returned. `interrupted` — the run ended (stopped turn,\n * crashed process) before this call returned a result: neither running nor failed.\n */\nexport type ToolCallStatus = 'running' | 'success' | 'error' | 'interrupted';\n\nexport type ToolIcon = 'wrench' | 'search' | 'file' | 'edit' | 'terminal' | 'globe' | 'agent' | 'list' | 'plug';\n\nexport interface ToolCallData {\n /** Tool name as the agent calls it, shown in mono — `Read`, `mcp__github__get_issue`. */\n name: string;\n /** One human line — `src/app.ts (lines 1-80)`. */\n summary?: string;\n /** Icon in the tile. Default `toolIcon(name)`. */\n icon?: ToolIcon;\n status: ToolCallStatus;\n /** Object → pretty JSON; a JSON string is parsed; other text is shown as is. */\n args?: unknown;\n result?: unknown;\n /** Shown when status is `error`. */\n error?: string;\n /** Epoch ms the call started — the live timer counts from here while running. */\n startedAt?: number;\n /** Final duration in ms. */\n duration?: number;\n /** Epoch ms clock time the call started, shown muted in the body as HH:MM:SS. */\n at?: number;\n /** Set → controlled; unset → the element keeps its own open state. */\n open?: boolean;\n /** Initial open state while uncontrolled (read on the first render only). */\n defaultOpen?: boolean;\n /** Default true: opens when the call turns to error, closes again on the next run unless toggled by hand. */\n openOnError?: boolean;\n /** Shows Retry next to the error → `ui-retry`. */\n canRetry?: boolean;\n /** Default 220 — taller blocks get a fade and Show all / Show less. */\n maxCodeHeight?: number;\n /** The host is fetching args/result: the body shows a quiet Loading… line. */\n loading?: boolean;\n /** The host's fetch failed: this message plus Try again → `ui-reload`. */\n detailError?: string;\n /** One muted line in the body (e.g. “Showing the first 256 KiB of 1.2 MB”). */\n note?: string;\n /** Default true; false → the header button is out of the tab order (the host runs a roving focus). */\n focusable?: boolean;\n /** Host key for the call, echoed as `detail.id` in every event (and used by the group to keep cards). */\n id?: string;\n}\n\nexport interface ToolCallGroupData {\n calls: ToolCallData[];\n /** Label once every call is done. Default “Used N tools”. */\n label?: string;\n /** Label while any call runs. Default “Using tools…”. */\n runningLabel?: string;\n /** Total ms. Default: the sum of the calls' durations, or the time measured while running. */\n duration?: number;\n /** Set → controlled; unset → the element keeps its own open state. */\n open?: boolean;\n /** Initial open state while uncontrolled (read on the first render only). */\n defaultOpen?: boolean;\n /** Default true; false → the group's and the cards' header buttons are out of the tab order. */\n focusable?: boolean;\n}\n\n/** 0.4s · 12.3s · 2m 05s · 1h 02m. Live timers always show tenths below a minute; a final value under 1s reads 350ms. */\nexport function formatToolMs(ms: number, live = false): string {\n const v = Math.max(0, Number(ms) || 0);\n if (!live && v < 1000) return `${Math.max(1, Math.round(v))}ms`;\n if (v < 60_000) return `${(Math.floor(v / 100) / 10).toFixed(1)}s`;\n const s = Math.floor(v / 1000);\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${String(s % 60).padStart(2, '0')}s`;\n return `${Math.floor(m / 60)}h ${String(m % 60).padStart(2, '0')}m`;\n}\n\n/** Clock time HH:MM:SS (24h) in the card's language; empty for a missing or invalid time. */\nexport function formatToolClock(at: number | undefined, lang: 'en' | 'ko' = 'en'): string {\n const v = Number(at);\n if (at === undefined || at === null || !Number.isFinite(v) || Number.isNaN(new Date(v).getTime())) return '';\n try {\n return new Date(v).toLocaleTimeString(lang === 'ko' ? 'ko-KR' : 'en-GB', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hourCycle: 'h23',\n });\n } catch {\n return '';\n }\n}\n\n/**\n * What a code block shows: objects pretty-printed, a string that holds JSON parsed and pretty-printed, any other\n * text as is. `json` says whether the text may be highlighted.\n */\nexport function toCodeText(value: unknown): { text: string; json: boolean } {\n if (typeof value === 'string') {\n const head = value.trimStart().charAt(0);\n if (head === '{' || head === '[') {\n try {\n return { text: JSON.stringify(JSON.parse(value), null, 2), json: true };\n } catch {\n /* not JSON: shown as written */\n }\n }\n return { text: value, json: false };\n }\n if (value === undefined) return { text: '', json: false };\n try {\n const s = JSON.stringify(value, null, 2);\n return s === undefined ? { text: String(value), json: false } : { text: s, json: true };\n } catch {\n return { text: String(value), json: false };\n }\n}\n\n// One pass over already-escaped JSON. Escaping adds no quote, backslash or digit, so strings, numbers and literals\n// are found exactly as in the raw text. Groups: 1 = a string, 2 = the colon that makes it a key.\nconst JSON_TOKEN = /(\"(?:\\\\.|[^\"\\\\])*\")(\\s*:)?|\\b(?:true|false|null)\\b|-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?/g;\n\n/** JSON text → escaped HTML with `tc-k` (key), `tc-s` (string), `tc-n` (number), `tc-l` (literal) spans. */\nexport function highlightJson(text: string): string {\n return esc(text).replace(JSON_TOKEN, (m: string, str?: string, colon?: string) => {\n if (str) return colon ? `<span class=\"tc-k\">${str}</span>${colon}` : `<span class=\"tc-s\">${str}</span>`;\n return `<span class=\"tc-${m.charCodeAt(0) >= 97 ? 'l' : 'n'}\">${m}</span>`;\n });\n}\n\nconst ICON_BY_NAME: Record<string, ToolIcon> = {\n Read: 'file',\n Write: 'file',\n Edit: 'edit',\n MultiEdit: 'edit',\n NotebookEdit: 'edit',\n Bash: 'terminal',\n BashOutput: 'terminal',\n Grep: 'search',\n Glob: 'search',\n WebSearch: 'search',\n WebFetch: 'globe',\n Agent: 'agent',\n Task: 'agent',\n TodoWrite: 'list',\n};\n\n/** The tile icon for a tool name: Read/Write → file, Edit → edit, Bash → terminal, Grep/Glob/WebSearch → search,\n * WebFetch → globe, Agent/Task → agent, TodoWrite → list, mcp__* → plug, anything else → wrench. */\nexport function toolIcon(name: string): ToolIcon {\n const n = String(name ?? '');\n if (Object.hasOwn(ICON_BY_NAME, n)) return ICON_BY_NAME[n];\n return n.startsWith('mcp__') ? 'plug' : 'wrench';\n}\n\n/** Line count of a block (for the cap estimate when the layout cannot be measured). */\nexport function lineCount(text: string): number {\n let n = 1;\n for (let i = text.indexOf('\\n'); i !== -1; i = text.indexOf('\\n', i + 1)) n++;\n return n;\n}\n\n/** What the group line says about its calls. `interrupted` counts as neither running nor failed. */\nexport function groupStats(calls: ToolCallData[]): { running: boolean; failed: number; sum: number | undefined } {\n let running = false;\n let failed = 0;\n let sum = 0;\n let all = calls.length > 0;\n for (const c of calls) {\n if (c.status === 'running') running = true;\n else if (c.status === 'error') failed++;\n const d = Number(c.duration);\n if (c.duration === undefined || c.duration === null || !Number.isFinite(d)) all = false;\n else sum += Math.max(0, d);\n }\n return { running, failed, sum: all ? sum : undefined };\n}\n\n// 16×16 stroke glyphs drawn for this library (currentColor).\nconst G = (d: string) => `<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">${d}</svg>`;\nexport const TOOL_ICONS: Record<ToolIcon, string> = {\n wrench: G(\n '<path d=\"M13.4 4.6 11.6 6.4 9.9 6.1 9.6 4.4l1.8-1.8a3.2 3.2 0 0 0-4.3 4L2.9 10.8a1.6 1.6 0 0 0 2.3 2.3L9.4 8.9a3.2 3.2 0 0 0 4-4.3Z\"/>',\n ),\n search: G('<circle cx=\"7\" cy=\"7\" r=\"4.25\"/><path d=\"m10.2 10.2 3.3 3.3\"/>'),\n file: G(\n '<path d=\"M9 1.9H4.6a1 1 0 0 0-1 1v10.2a1 1 0 0 0 1 1h6.8a1 1 0 0 0 1-1V5.3Z\"/><path d=\"M9 1.9v3.4h3.4M5.9 8.6h4.2M5.9 11h2.8\"/>',\n ),\n edit: G(\n '<path d=\"M10.3 2.9a1.5 1.5 0 0 1 2.1 0l.7.7a1.5 1.5 0 0 1 0 2.1L6.4 12.4l-3.3.8.8-3.3Z\"/><path d=\"m9.2 4 2.8 2.8\"/>',\n ),\n terminal: G('<rect x=\"1.9\" y=\"2.9\" width=\"12.2\" height=\"10.2\" rx=\"2\"/><path d=\"m4.6 6.3 2 1.8-2 1.8M8.4 10.1h3\"/>'),\n globe: G(\n '<circle cx=\"8\" cy=\"8\" r=\"6.1\"/><path d=\"M1.9 8h12.2M8 1.9c-1.7 1.7-2.5 3.7-2.5 6.1s.8 4.4 2.5 6.1c1.7-1.7 2.5-3.7 2.5-6.1S9.7 3.6 8 1.9Z\"/>',\n ),\n agent: G(\n '<rect x=\"2.9\" y=\"5.1\" width=\"10.2\" height=\"8\" rx=\"2.4\"/><path d=\"M8 2.4v2.7M6.1 8.6v1M9.9 8.6v1M1.4 9.1v1.4M14.6 9.1v1.4\"/>',\n ),\n list: G('<path d=\"m2.4 4.1.9.9 1.6-1.9M2.4 8.6l.9.9 1.6-1.9M2.6 12.6h1.9M7.2 4.2h6.4M7.2 8.2h6.4M7.2 12.6h6.4\"/>'),\n plug: G('<path d=\"M5.9 1.9v2.9M10.1 1.9v2.9M4.1 4.8h7.8v2.3a3.9 3.9 0 0 1-7.8 0ZM8 11v3.1\"/>'),\n};\n","/** UI copy. English by default, Korean with `lang=\"ko\"` (the soma-work 작업 로그 wording). */\nconst en = {\n running: 'Running',\n done: 'Finished',\n failed: 'Failed',\n noResult: 'No result',\n args: 'Arguments',\n result: 'Result',\n waiting: 'Waiting for result…',\n nothing: 'No arguments or result.',\n failedDefault: 'The tool call failed.',\n interrupted: 'The run ended before this call returned.',\n showAll: 'Show all',\n showLess: 'Show less',\n retry: 'Retry',\n reload: 'Try again',\n loading: 'Loading…',\n copy: (part: string) => `Copy ${part.toLowerCase()}`,\n copied: 'Copied',\n selected: 'Selected — press ⌘C / Ctrl+C to copy',\n startedAt: (clock: string) => `Started at ${clock}`,\n sayRunning: (name: string) => `${name} running`,\n sayDone: (name: string) => `${name} finished`,\n sayFailed: (name: string, error: string) => `${name} failed${error ? `: ${error}` : ''}`,\n sayInterrupted: (name: string) => `${name} ended without a result`,\n used: (n: number) => `Used ${n} ${n === 1 ? 'tool' : 'tools'}`,\n using: 'Using tools…',\n nFailed: (n: number) => `${n} failed`,\n groupSay: (label: string, failed: number) => `${label}${failed ? `, ${failed} failed` : ''}`,\n};\n\nexport type ToolCallStrings = typeof en;\n\nconst ko: ToolCallStrings = {\n running: '실행 중',\n done: '완료',\n failed: '실패',\n noResult: '결과 없음',\n args: '입력',\n result: '결과',\n waiting: '결과 기다리는 중…',\n nothing: '입력과 결과 없음',\n failedDefault: '툴 호출이 실패했어요',\n interrupted: '이 호출이 끝나기 전에 실행이 멈췄어요',\n showAll: '모두 보기',\n showLess: '접기',\n retry: '다시 시도',\n reload: '다시 시도',\n loading: '불러오는 중…',\n copy: (part: string) => `${part} 복사`,\n copied: '복사됨',\n selected: '선택했습니다 — ⌘C / Ctrl+C로 복사',\n startedAt: (clock: string) => `${clock} 시작`,\n sayRunning: (name: string) => `${name} 실행 중`,\n sayDone: (name: string) => `${name} 완료`,\n sayFailed: (name: string, error: string) => `${name} 실패${error ? `: ${error}` : ''}`,\n sayInterrupted: (name: string) => `${name} 결과 없이 끝남`,\n used: (n: number) => `툴 ${n}개 사용`,\n using: '툴 사용 중…',\n nFailed: (n: number) => `${n}개 실패`,\n groupSay: (label: string, failed: number) => `${label}${failed ? `, ${failed}개 실패` : ''}`,\n};\n\nexport const STRINGS = { en, ko };\n\nexport type ToolCallLang = keyof typeof STRINGS;\n\nexport function toolCallStrings(lang: string | null | undefined): ToolCallStrings {\n return lang === 'ko' ? STRINGS.ko : STRINGS.en;\n}\n","/**\n * Tool Call Card + Group. Sizes and timings follow the affectUI Tool Call Card pattern; every colour is a dashboard\n * token or a color-mix() of tokens, so light and dark both read.\n */\nexport const styles = `\n:host { --tc-ink: var(--text); --tc-text: var(--text-secondary); --tc-muted: var(--text-tertiary);\n --tc-bg: var(--surface); --tc-line: var(--border); --tc-tile: var(--surface-raised);\n --tc-hover: color-mix(in srgb, var(--text) 3.5%, var(--surface));\n --tc-code: color-mix(in srgb, var(--surface-raised) 60%, var(--surface));\n --tc-ring: var(--surface);\n --tc-red: var(--st-fail-text); --tc-red-bg: color-mix(in srgb, var(--st-fail) 7%, var(--surface));\n --tc-red-line: color-mix(in srgb, var(--st-fail) 24%, transparent);\n --tc-key: var(--text); --tc-str: color-mix(in srgb, var(--green) 62%, var(--accent)); --tc-num: var(--orange);\n --tc-lit: var(--purple); --tc-shine: var(--text);\n --tc-lift: 0 1px 2px color-mix(in srgb, var(--text) 6%, transparent);\n --tc-ease: var(--ease-out);\n min-width: 0; font-size: 13.5px; line-height: 1.4; letter-spacing: -0.006em; }\n[hidden] { display: none !important; }\nbutton { appearance: none; margin: 0; border: 0; background: none; text-align: left; letter-spacing: inherit; }\n\n/* Card */\n.tc { position: relative; border: 1px solid var(--tc-line); border-radius: 12px; background: var(--tc-bg); box-shadow: var(--tc-lift); }\n.tc-head { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; padding: 8px 10px 8px 9px;\n border-radius: 11px; color: var(--tc-text); transition: background-color 160ms ease; }\n.tc[data-open] > .tc-head { border-radius: 11px 11px 0 0; }\n.tc-icon { display: grid; place-items: center; flex: none; width: 26px; height: 26px; border-radius: 7px;\n background: var(--tc-tile); box-shadow: inset 0 0 0 1px var(--tc-line); color: var(--tc-ink); }\n.tc-icon > svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }\n.tc-main { display: flex; align-items: baseline; gap: 8px; flex: 1; min-width: 0; }\n.tc-name { flex: 0 1 auto; max-width: 55%; overflow: hidden; color: var(--tc-ink); font-family: var(--mono); font-size: 12.5px;\n font-weight: 500; letter-spacing: 0; text-overflow: ellipsis; white-space: nowrap; }\n.tc-summary { flex: 1 1 0; min-width: 0; overflow: hidden; color: var(--tc-text); text-overflow: ellipsis; white-space: nowrap; }\n.tc-status { display: inline-flex; align-items: center; gap: 6px; flex: none; color: var(--tc-muted); font-size: 12.5px;\n font-variant-numeric: tabular-nums; white-space: nowrap; }\n.tc-status.is-in { animation: tc-in 360ms var(--tc-ease) both; }\n.tc[data-status=\"error\"] .tc-status { color: var(--tc-red); }\n.tc-status > svg { width: 14px; height: 14px; flex: none; fill: none; stroke-linecap: round; stroke-linejoin: round; }\n.tc-spin { animation: tc-spin 800ms linear infinite; }\n.tc-spin circle { stroke: currentColor; stroke-width: 1.6; opacity: 0.25; }\n.tc-spin path { stroke: var(--st-run); stroke-width: 1.6; }\n.tc-ok { stroke: var(--st-done); stroke-width: 1.8; }\n.is-in .tc-ok path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: tc-draw 360ms var(--tc-ease) 80ms forwards; }\n.tc-err { stroke: var(--st-fail); stroke-width: 1.5; }\n.tc-stop { stroke: currentColor; stroke-width: 1.5; }\n.tc-chev { flex: none; width: 14px; height: 14px; fill: none; stroke: var(--tc-muted); stroke-width: 1.5; stroke-linecap: round;\n stroke-linejoin: round; transition: transform 360ms var(--tc-ease); }\n.tc[data-open] > .tc-head .tc-chev, .tcg[data-open] > .tcg-head .tc-chev { transform: rotate(180deg); }\n@media (hover: hover) {\n .tc-head:hover { background: var(--tc-hover); }\n .tc-head:hover .tc-chev { stroke: var(--tc-ink); }\n .tcg-head:hover { background: var(--tc-hover); color: var(--tc-ink); }\n .tc-copy:hover { background: var(--tc-hover); color: var(--tc-ink); }\n .tc-more:hover { color: var(--tc-ink); }\n .tc-btn:hover { background: var(--tc-hover); }\n}\n\n/* Body: 0fr → 1fr, so the height animates without measuring */\n.tc-body { display: grid; grid-template-rows: 0fr; opacity: 0;\n transition: grid-template-rows 380ms var(--tc-ease), opacity 240ms ease; }\n.tc-body[data-open] { grid-template-rows: 1fr; opacity: 1; }\n.tc-clip { min-height: 0; overflow: hidden; }\n.tc-sections { display: grid; gap: 12px; padding: 12px; border-top: 1px solid var(--tc-line); }\n.tc-top { display: flex; justify-content: flex-end; margin: -2px 0 -6px; }\n.tc-line { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }\n.tc-line > p { min-width: 0; }\n.tc-head-end { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }\n.tc-at { flex: none; color: var(--tc-muted); font-size: 11.5px; line-height: 16px; font-variant-numeric: tabular-nums; }\n.tc-section { display: grid; gap: 6px; min-width: 0; }\n.tc-section-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 24px; }\n.tc-label { color: var(--tc-muted); font-size: 12px; font-weight: 500; }\n.tc-pending, .tc-note { margin: 0; color: var(--tc-muted); font-size: 12.5px; }\n.tc-note { font-size: 12px; }\n\n.tc-copy { position: relative; display: grid; place-items: center; flex: none; width: 24px; height: 24px; padding: 0;\n border-radius: 6px; color: var(--tc-muted); transition: background-color 160ms ease, color 160ms ease; }\n.tc-copy svg { position: absolute; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.4;\n stroke-linecap: round; stroke-linejoin: round;\n transition: opacity 200ms ease, transform 320ms var(--tc-ease), filter 200ms ease; }\n.tc-copy-done { opacity: 0; transform: scale(0.6); filter: blur(2px); stroke-width: 1.7; }\n.tc-copy[data-copied] { color: var(--st-done); }\n.tc-copy[data-copied] .tc-copy-icon { opacity: 0; transform: scale(0.6); filter: blur(2px); }\n.tc-copy[data-copied] .tc-copy-done { opacity: 1; transform: none; filter: none; }\n\n/* Code wraps instead of scrolling sideways; a capped block fades out at the bottom */\n.tc-code { position: relative; margin: 0; padding: 10px 12px; overflow: hidden; border-radius: 8px; background: var(--tc-code);\n box-shadow: inset 0 0 0 1px var(--tc-line); color: var(--tc-text); font-family: var(--mono); font-size: 12px;\n line-height: 1.6; letter-spacing: 0; white-space: pre-wrap; overflow-wrap: anywhere; tab-size: 2;\n transition: max-height 420ms var(--tc-ease); }\n.tc-code[data-json] { color: var(--tc-muted); }\n.tc-code code { display: block; font: inherit; }\n.tc-code::after { content: \"\"; position: absolute; left: 1px; right: 1px; bottom: 1px; height: 56px; border-radius: 0 0 7px 7px;\n background: linear-gradient(to bottom, color-mix(in srgb, var(--tc-code) 0%, transparent), var(--tc-code));\n opacity: 0; transition: opacity 240ms ease; pointer-events: none; }\n.tc-code[data-capped]::after { opacity: 1; }\n.tc-k { color: var(--tc-key); }\n.tc-s { color: var(--tc-str); }\n.tc-n { color: var(--tc-num); }\n.tc-l { color: var(--tc-lit); }\n.tc-more { position: relative; justify-self: start; padding: 2px 4px; margin-left: -4px; border-radius: 5px; color: var(--tc-text);\n font-size: 12.5px; font-weight: 500; transition: color 160ms ease; }\n\n/* Error: the message and an optional Retry; a failed host fetch: the message and Try again */\n.tc-error { display: flex; align-items: flex-start; gap: 8px; padding: 9px 10px 9px 11px; border-radius: 8px;\n background: var(--tc-red-bg); box-shadow: inset 0 0 0 1px var(--tc-red-line); }\n.tc-error > svg { flex: none; width: 14px; height: 14px; margin-top: 2px; fill: none; stroke-linecap: round; }\n.tc-error-text { flex: 1; min-width: 0; margin: 0; color: var(--tc-red); font-size: 13px; line-height: 1.45;\n white-space: pre-wrap; overflow-wrap: anywhere; }\n.tc-reload-row { display: flex; align-items: center; gap: 8px; }\n.tc-reload-row > .tc-pending { flex: 1; min-width: 0; overflow-wrap: anywhere; }\n.tc-btn { position: relative; display: inline-flex; align-items: center; gap: 5px; flex: none; height: 26px; margin: -3px 0;\n padding: 0 10px 0 8px; border-radius: 7px; background: var(--tc-bg); box-shadow: inset 0 0 0 1px var(--tc-line), var(--tc-lift);\n color: var(--tc-ink); font-size: 12.5px; font-weight: 500; white-space: nowrap; transition: background-color 160ms ease; }\n.tc-btn svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round;\n stroke-linejoin: round; transition: transform 200ms var(--tc-ease); }\n.tc-btn:active svg { transform: rotate(-60deg); }\n\n/* Group: one quiet line with the tools' icons stacked, the cards below */\n.tcg { display: grid; }\n.tcg-head { display: flex; align-items: center; gap: 9px; justify-self: start; max-width: 100%; min-height: 36px;\n padding: 4px 10px 4px 5px; border-radius: 10px; color: var(--tc-text);\n transition: background-color 160ms ease, color 160ms ease; }\n.tcg-stack { display: flex; flex: none; }\n.tcg-stack .tc-icon { width: 24px; height: 24px; box-shadow: inset 0 0 0 1px var(--tc-line), 0 0 0 2px var(--tc-ring); }\n.tcg-stack .tc-icon.is-in { animation: tc-pop 420ms var(--tc-ease) both; }\n.tcg-stack .tc-icon + .tc-icon { margin-left: -5px; }\n.tcg-stack .tc-icon > svg { width: 13px; height: 13px; }\n.tcg-title { display: flex; align-items: baseline; gap: 5px; min-width: 0; white-space: nowrap; }\n.tcg-title.is-in { animation: tc-in 360ms var(--tc-ease) both; }\n.tcg-label { position: relative; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: inherit; font-weight: 500; }\n.tcg-failed { flex: none; color: var(--tc-red); }\n.tcg-time { flex: none; color: var(--tc-muted); font-variant-numeric: tabular-nums; }\n.tcg-list { display: grid; gap: 8px; padding-top: 8px; }\n\n/* A band of the text colour sweeping over “Using tools…” */\n.tc-shine::after { content: attr(data-text); content: attr(data-text) / \"\"; position: absolute; inset: 0; white-space: nowrap;\n color: transparent; background: linear-gradient(90deg, transparent 38%, var(--tc-shine) 50%, transparent 62%) 100% 0 / 300% 100% no-repeat;\n -webkit-background-clip: text; background-clip: text; animation: tc-sweep 1.8s linear infinite; pointer-events: none; }\n\n@keyframes tc-in { from { opacity: 0; transform: translateY(3px); filter: blur(2px); } to { opacity: 1; transform: none; filter: none; } }\n@keyframes tc-pop { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: none; } }\n@keyframes tc-spin { to { transform: rotate(360deg); } }\n@keyframes tc-draw { to { stroke-dashoffset: 0; } }\n@keyframes tc-sweep { from { background-position: 100% 0; } to { background-position: 0% 0; } }\n\n/* Touch: every control gets a 44px target without changing the layout */\n@media (pointer: coarse) {\n .tcg-head { min-height: 44px; }\n .tc-copy::before, .tc-more::before, .tc-btn::before { content: \"\"; position: absolute; inset: -10px; }\n .tc-more::before { inset: -12px -8px; }\n .tc-btn::before { inset: -9px -4px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .tc-shine::after { display: none; }\n .tc-spin { animation: none; }\n .is-in .tc-ok path { animation: none; stroke-dashoffset: 0; }\n}\n`;\n","import { define, UiElement } from '../../core/element';\nimport { esc, escAttr } from '../../core/html';\nimport {\n formatToolClock,\n formatToolMs,\n highlightJson,\n lineCount,\n TOOL_ICONS,\n type ToolCallData,\n type ToolCallStatus,\n type ToolIcon,\n toCodeText,\n toolIcon,\n} from './logic';\nimport { type ToolCallLang, type ToolCallStrings, toolCallStrings } from './strings';\nimport { styles } from './styles';\n\n/** Which code block an event is about. */\nexport type ToolCallPart = 'args' | 'result';\nexport interface ToolCallToggleDetail {\n open: boolean;\n /** `data.id` when set. */\n id?: string;\n}\nexport interface ToolCallCopyDetail {\n part: ToolCallPart;\n text: string;\n id?: string;\n}\nexport interface ToolCallActionDetail {\n id?: string;\n}\n\nconst COPIED_MS = 1400;\nconst TICK_MS = 100;\nconst DEFAULT_CAP = 220;\n/** Cap estimate when the block cannot be measured (no layout yet): 12px × 1.6 per line + 2 × 10px padding. */\nconst LINE_PX = 19.2;\nconst CODE_PAD = 20;\n\nexport const SPIN_SVG =\n '<svg class=\"tc-spin\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"8\" r=\"5.8\"/><path d=\"M8 2.2a5.8 5.8 0 0 1 5.8 5.8\"/></svg>';\nconst OK_SVG =\n '<svg class=\"tc-ok\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"m3.6 8.5 3 2.9 5.8-6.4\" pathLength=\"1\"/></svg>';\nconst ERR_SVG =\n '<svg class=\"tc-err\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"8\" r=\"6.1\"/><path d=\"M8 4.9v3.6M8 11v.1\"/></svg>';\nconst STOP_SVG =\n '<svg class=\"tc-stop\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"8\" r=\"6.1\"/><path d=\"M5.4 8h5.2\"/></svg>';\nexport const CHEV_SVG =\n '<svg class=\"tc-chev\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"m4.4 6.2 3.6 3.6 3.6-3.6\"/></svg>';\nconst COPY_SVG =\n '<svg class=\"tc-copy-icon\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><rect x=\"5.4\" y=\"5.4\" width=\"8.1\" height=\"8.1\" rx=\"1.9\"/><path d=\"M10.6 5.4V4.3a1.6 1.6 0 0 0-1.6-1.6H4.3a1.6 1.6 0 0 0-1.6 1.6V9a1.6 1.6 0 0 0 1.6 1.6h1.1\"/></svg>';\nconst DONE_SVG =\n '<svg class=\"tc-copy-done\" viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"m3.6 8.5 3 2.9 5.8-6.4\"/></svg>';\nconst RETRY_SVG =\n '<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M2.8 8a5.2 5.2 0 1 0 1.5-3.7\"/><path d=\"M2.6 2.4v2.9h2.9\"/></svg>';\n\nconst STATUSES: ReadonlySet<string> = new Set(['running', 'success', 'error', 'interrupted']);\n\n/** A status the card knows; anything else reads as `interrupted` (neutral, no timer). */\nexport function normStatus(s: unknown): ToolCallStatus {\n return STATUSES.has(s as string) ? (s as ToolCallStatus) : 'interrupted';\n}\n\n/** The tile glyph for a call: its `icon` when it names one, else `toolIcon(name)`. */\nexport function callIconSvg(d: Pick<ToolCallData, 'name' | 'icon'>): string {\n const key: ToolIcon = d.icon && Object.hasOwn(TOOL_ICONS, d.icon) ? d.icon : toolIcon(d.name);\n return TOOL_ICONS[key];\n}\n\nconst finite = (v: unknown): number | undefined => {\n if (v === undefined || v === null || v === '') return undefined;\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n};\n\ninterface Code {\n value: unknown;\n text: string;\n json: boolean;\n lines: number;\n /** The whole block as HTML — built the first time it is shown in full. */\n html?: string;\n /** The first `keep` lines as HTML, for a block that is capped anyway. */\n head?: { keep: number; html: string };\n}\n\n/** Index of the n-th line break (the end of line n), or the text length when there are fewer lines. */\n/** Characters a first-screen line may hold before the head stops (wide panels, wrapped text). */\nconst HEAD_CHARS_PER_LINE = 240;\n\nfunction cutAfterLines(text: string, n: number): number {\n let i = -1;\n for (let k = 0; k < n; k++) {\n i = text.indexOf('\\n', i + 1);\n if (i === -1) return text.length;\n }\n return i;\n}\n\n/**\n * `<ui-tool-call-card>` — one tool call of an agent: icon, name, summary and status (spinner with a live timer, a\n * drawn check with the duration, Failed, or No result) on one line; open it for the arguments and the result as\n * highlighted JSON with copy buttons, long blocks capped with Show all, errors with Retry.\n */\nexport class UiToolCallCard extends UiElement<ToolCallData> {\n static override styles = [styles];\n static get observedAttributes() {\n return ['lang'];\n }\n\n #open = false;\n #auto = false;\n #shownOpen = false;\n #rendered = false;\n #status: ToolCallStatus | undefined;\n #statusIn = false;\n #runStart = 0;\n #measured: number | undefined;\n #tick = 0;\n #full = new Set<ToolCallPart>();\n #copied = new Set<ToolCallPart>();\n #copyTimers = new Map<ToolCallPart, number>();\n #code = new Map<ToolCallPart, Code>();\n #ro: ResizeObserver | undefined;\n #saidStatus: ToolCallStatus | undefined;\n readonly #live: HTMLElement;\n\n constructor() {\n super();\n // Outside the re-rendered markup, so a render never re-creates (or re-reads) the live region.\n this.#live = document.createElement('span');\n this.#live.className = 'sr-only';\n this.#live.setAttribute('role', 'status');\n this.#live.setAttribute('aria-live', 'polite');\n this.root.append(this.#live);\n this.root.addEventListener('click', (e) => this.#click(e));\n }\n\n attributeChangedCallback(): void {\n this.requestRender();\n }\n\n override disconnectedCallback(): void {\n this.#stopTick();\n this.#ro?.disconnect();\n }\n\n /** Focus the header button (the card's one tab stop). */\n /** Retry, Try again, a Show all that went away, an auto-closed body: focus stays on the card's header. */\n protected override focusFallback(): HTMLElement | null {\n return this.$<HTMLButtonElement>('.tc-head');\n }\n\n override focus(options?: FocusOptions): void {\n if (!this.$('.tc-head') && this.data && this.isConnected) this.renderNow();\n const head = this.$<HTMLButtonElement>('.tc-head');\n if (head) head.focus(options);\n else super.focus(options);\n }\n\n /** Whether the body is open now (controlled `data.open`, else the element's own state). */\n get isOpen(): boolean {\n return this.data ? this.#isOpen(this.data) : false;\n }\n\n get #lang(): ToolCallLang {\n return this.getAttribute('lang') === 'ko' ? 'ko' : 'en';\n }\n\n get #t(): ToolCallStrings {\n return toolCallStrings(this.#lang);\n }\n\n #isOpen(d: ToolCallData): boolean {\n return d.open ?? this.#open;\n }\n\n #startOf(d: ToolCallData): number {\n return finite(d.startedAt) ?? this.#runStart;\n }\n\n #liveMs(d: ToolCallData): number {\n return Math.max(0, Date.now() - this.#startOf(d));\n }\n\n /** Status transitions: first-render defaults, measured time, open-on-error. */\n #sync(d: ToolCallData, st: ToolCallStatus): void {\n const prev = this.#status;\n this.#statusIn = false;\n if (prev === undefined) {\n this.#open = !!d.defaultOpen;\n if (st === 'running') this.#runStart = Date.now();\n } else if (st !== prev) {\n this.#statusIn = true;\n if (prev === 'running') {\n this.#measured = this.#liveMs(d);\n this.#stopTick();\n }\n if (st === 'running') {\n this.#runStart = Date.now();\n this.#measured = undefined;\n }\n if (d.open === undefined && d.openOnError !== false) {\n if (st === 'error' && !this.#open) {\n this.#open = true;\n this.#auto = true;\n } else if (prev === 'error' && this.#auto) {\n this.#open = false;\n this.#auto = false;\n }\n }\n }\n this.#status = st;\n }\n\n protected render(): string {\n const d = this.data;\n if (!d) return '';\n const st = normStatus(d.status);\n this.#sync(d, st);\n const t = this.#t;\n const open = this.#isOpen(d);\n if (!this.#rendered) {\n this.#rendered = true;\n this.#shownOpen = open;\n }\n // Markup carries the state on screen now; updated() moves it to `open` after a layout, so the change animates.\n const shown = this.#shownOpen;\n const summary = d.summary === undefined || d.summary === null ? '' : String(d.summary);\n const head = `<button type=\"button\" class=\"tc-head\" data-act=\"toggle\" data-key=\"head\" aria-expanded=\"${shown}\" aria-controls=\"tc-body\"${\n d.focusable === false ? ' tabindex=\"-1\"' : ''\n }><span class=\"tc-icon\" aria-hidden=\"true\">${callIconSvg(d)}</span><span class=\"tc-main\"><code class=\"tc-name\">${esc(\n d.name,\n )}</code>${summary ? `<span class=\"tc-summary\" title=\"${escAttr(summary)}\">${esc(summary)}</span>` : ''}</span>${this.#statusHtml(\n d,\n st,\n t,\n )}${CHEV_SVG}</button>`;\n // A closed card keeps no body markup: a 256 KiB result costs nothing until it is opened.\n const sections = open || shown ? `<div class=\"tc-sections\">${this.#bodyHtml(d, st, t)}</div>` : '';\n return `<div class=\"tc\" data-status=\"${st}\"${shown ? ' data-open' : ''}>${head}<div class=\"tc-body\" id=\"tc-body\"${\n shown ? ' data-open' : ' inert'\n }><div class=\"tc-clip\">${sections}</div></div></div>`;\n }\n\n #statusHtml(d: ToolCallData, st: ToolCallStatus, t: ToolCallStrings): string {\n const cls = `tc-status${this.#statusIn ? ' is-in' : ''}`;\n if (st === 'running')\n return `<span class=\"${cls}\">${SPIN_SVG}<span class=\"sr-only\">${esc(t.running)}, </span><span class=\"tc-time\">${esc(\n formatToolMs(this.#liveMs(d), true),\n )}</span></span>`;\n if (st === 'success') {\n const ms = finite(d.duration) ?? this.#measured;\n return `<span class=\"${cls}\">${OK_SVG}<span class=\"sr-only\">${esc(t.done)}${ms !== undefined ? ', ' : ''}</span>${\n ms !== undefined ? `<span class=\"tc-time\">${esc(formatToolMs(ms))}</span>` : ''\n }</span>`;\n }\n if (st === 'error') return `<span class=\"${cls}\">${ERR_SVG}<span class=\"tc-time\">${esc(t.failed)}</span></span>`;\n const dur = finite(d.duration);\n return `<span class=\"${cls}\">${STOP_SVG}<span class=\"tc-time\">${esc(t.noResult)}${\n dur !== undefined ? ` · ${esc(formatToolMs(dur))}` : ''\n }</span></span>`;\n }\n\n #bodyHtml(d: ToolCallData, st: ToolCallStatus, t: ToolCallStrings): string {\n const items: string[] = [];\n const at = formatToolClock(d.at, this.#lang);\n let clock = at\n ? `<time class=\"tc-at\" datetime=\"${escAttr(new Date(Number(d.at)).toISOString())}\" title=\"${escAttr(\n t.startedAt(at),\n )}\">${esc(at)}</time>`\n : '';\n // The start clock sits at the right end of the body's first line (a section head or a muted line); before an\n // error box or a reload row it gets a short line of its own.\n const take = (): string => {\n if (items.length) return '';\n const c = clock;\n clock = '';\n return c;\n };\n const line = (cls: string, text: string): string => {\n const c = take();\n const p = `<p class=\"${cls}\">${esc(text)}</p>`;\n return c ? `<div class=\"tc-line\">${p}${c}</div>` : p;\n };\n if (st === 'interrupted') items.push(line('tc-pending', t.interrupted));\n if (st === 'error') {\n const msg = d.error === undefined || d.error === null || d.error === '' ? t.failedDefault : String(d.error);\n items.push(\n `<div class=\"tc-error\">${ERR_SVG}<p class=\"tc-error-text\">${esc(msg)}</p>${\n d.canRetry\n ? `<button type=\"button\" class=\"tc-btn\" data-act=\"retry\" data-key=\"retry\">${RETRY_SVG}${esc(t.retry)}</button>`\n : ''\n }</div>`,\n );\n }\n const hasArgs = d.args !== undefined;\n const hasResult = d.result !== undefined;\n const cap = this.#cap(d);\n if (hasArgs) items.push(this.#section('args', t.args, d.args, cap, t, take()));\n else this.#code.delete('args');\n if (hasResult) items.push(this.#section('result', t.result, d.result, cap, t, take()));\n else {\n this.#code.delete('result');\n if (st === 'running' && !d.loading && !d.detailError)\n items.push(\n `<div class=\"tc-section\"><div class=\"tc-section-head\"><span class=\"tc-label\">${esc(\n t.result,\n )}</span>${take()}</div><p class=\"tc-pending\">${esc(t.waiting)}</p></div>`,\n );\n }\n if (d.loading) items.push(line('tc-pending tc-loading', t.loading));\n else if (d.detailError)\n items.push(\n `<div class=\"tc-reload-row\"><p class=\"tc-pending\">${esc(\n d.detailError,\n )}</p><button type=\"button\" class=\"tc-btn\" data-act=\"reload\" data-key=\"reload\">${RETRY_SVG}${esc(t.reload)}</button></div>`,\n );\n else if (st === 'success' && !hasArgs && !hasResult) items.push(line('tc-pending', t.nothing));\n if (d.note !== undefined && d.note !== null && d.note !== '') items.push(line('tc-note', String(d.note)));\n if (clock) items.unshift(`<div class=\"tc-top\">${clock}</div>`);\n return items.join('');\n }\n\n #section(part: ToolCallPart, label: string, value: unknown, cap: number, t: ToolCallStrings, clock: string): string {\n const c = this.#codeOf(part, value);\n const full = this.#full.has(part);\n const code = this.#codeHtml(c, full, cap);\n const copied = this.#copied.has(part);\n const copy = copied ? t.copied : t.copy(label);\n return `<div class=\"tc-section\" data-part=\"${part}\"><div class=\"tc-section-head\"><span class=\"tc-label\">${esc(\n label,\n )}</span><span class=\"tc-head-end\">${clock}<button type=\"button\" class=\"tc-copy\" data-act=\"copy\" data-part=\"${part}\" data-key=\"copy-${part}\" aria-label=\"${escAttr(\n copy,\n )}\" title=\"${escAttr(copy)}\"${copied ? ' data-copied' : ''}>${COPY_SVG}${DONE_SVG}</button></span></div><pre class=\"tc-code\" data-part=\"${part}\"${\n c.json ? ' data-json' : ''\n }><code${code.partial ? ' data-partial' : ''}>${code.html}</code></pre><button type=\"button\" class=\"tc-more\" data-act=\"more\" data-part=\"${part}\" data-key=\"more-${part}\" aria-expanded=\"${full}\" hidden>${esc(\n full ? t.showLess : t.showAll,\n )}</button></div>`;\n }\n\n /** Text + highlighted HTML per block, kept across renders while the value is the same. */\n #codeOf(part: ToolCallPart, value: unknown): Code {\n const hit = this.#code.get(part);\n if (hit && hit.value === value) return hit;\n const { text, json } = toCodeText(value);\n if (hit && hit.text === text) {\n hit.value = value;\n return hit;\n }\n // New content starts capped again.\n if (hit) this.#full.delete(part);\n const c: Code = { value, text, json, lines: lineCount(text) };\n this.#code.set(part, c);\n return c;\n }\n\n /**\n * A block far taller than the cap renders only its first lines (enough to fill the cap, so it is capped all the\n * same); Show all, a fallback selection, or a block that fits renders the whole. A 256 KiB result costs its first\n * screen until someone asks for the rest.\n */\n #codeHtml(c: Code, full: boolean, cap: number): { html: string; partial: boolean } {\n const keep = Math.ceil((cap + 24) / LINE_PX) + 20;\n // Lines wrap, so a block with few newlines can still be huge: cap the first screen by characters as well.\n const maxChars = keep * HEAD_CHARS_PER_LINE;\n if (!full && (c.lines > keep || c.text.length > maxChars)) {\n if (c.head?.keep !== keep) {\n const head = c.text.slice(0, Math.min(cutAfterLines(c.text, keep), maxChars));\n c.head = { keep, html: c.json ? highlightJson(head) : esc(head) };\n }\n return { html: c.head.html, partial: true };\n }\n c.html ??= c.json ? highlightJson(c.text) : esc(c.text);\n return { html: c.html, partial: false };\n }\n\n /** Puts the whole block into a partially rendered code element (in place). */\n #fillCode(part: ToolCallPart): void {\n const code = this.$(`pre.tc-code[data-part=\"${part}\"] > code[data-partial]`);\n const c = this.#code.get(part);\n if (!code || !c) return;\n code.innerHTML = this.#codeHtml(c, true, 0).html;\n code.removeAttribute('data-partial');\n }\n\n protected override updated(): void {\n const d = this.data;\n if (d) {\n const open = this.#isOpen(d);\n if (open !== this.#shownOpen) {\n this.$('.tc-body')?.getBoundingClientRect(); // commit the current state so the change transitions\n this.#shownOpen = open;\n this.#applyOpen(open);\n }\n }\n this.#measure();\n this.#observe();\n this.#syncTick();\n this.#announce();\n }\n\n #applyOpen(open: boolean): void {\n this.$('.tc')?.toggleAttribute('data-open', open);\n this.$('.tc-head')?.setAttribute('aria-expanded', String(open));\n const body = this.$('.tc-body');\n body?.toggleAttribute('data-open', open);\n body?.toggleAttribute('inert', !open);\n }\n\n #click(e: Event): void {\n const btn = (e.target as Element | null)?.closest?.('[data-act]');\n const d = this.data;\n if (!btn || !d) return;\n const act = btn.getAttribute('data-act');\n const part = btn.getAttribute('data-part') === 'result' ? 'result' : 'args';\n if (act === 'toggle') this.#toggle(d);\n else if (act === 'copy') this.#copy(part);\n else if (act === 'more') this.#more(part);\n else if (act === 'retry') this.emit<ToolCallActionDetail>('ui-retry', this.#withId({}));\n else if (act === 'reload') this.emit<ToolCallActionDetail>('ui-reload', this.#withId({}));\n }\n\n #withId<T extends object>(detail: T): T & { id?: string } {\n const id = this.data?.id;\n return id === undefined || id === null ? detail : { ...detail, id: String(id) };\n }\n\n #toggle(d: ToolCallData): void {\n const next = !this.#isOpen(d);\n if (!this.emit<ToolCallToggleDetail>('ui-toggle', this.#withId({ open: next }))) return;\n this.#auto = false;\n if (d.open !== undefined) return; // controlled: the host answers with data.open\n this.#open = next;\n this.renderNow();\n }\n\n /** Show all / Show less changes the block in place, so its height animates and a re-render keeps it. */\n #more(part: ToolCallPart): void {\n if (this.#full.has(part)) this.#full.delete(part);\n else {\n this.#full.add(part);\n this.#fillCode(part);\n }\n this.#measure();\n }\n\n #cap(d: ToolCallData): number {\n return Math.max(40, finite(d.maxCodeHeight) ?? DEFAULT_CAP);\n }\n\n /** Caps blocks taller than maxCodeHeight (+24px slack) with a fade; Show all opens to the natural height. */\n #measure(): void {\n const d = this.data;\n if (!d) return;\n const t = this.#t;\n const cap = this.#cap(d);\n for (const pre of this.$$<HTMLElement>('pre.tc-code')) {\n const part = pre.dataset.part === 'result' ? 'result' : 'args';\n const c = this.#code.get(part);\n let h = pre.scrollHeight;\n if (!h && c) h = c.lines * LINE_PX + CODE_PAD;\n const capped = h > cap + 24;\n const full = capped && this.#full.has(part);\n pre.toggleAttribute('data-capped', capped && !full);\n pre.style.maxHeight = capped ? `${full ? Math.ceil(h) : cap}px` : '';\n const more = pre.parentElement?.querySelector<HTMLElement>('.tc-more');\n if (!more) continue;\n more.hidden = !capped;\n more.setAttribute('aria-expanded', String(full));\n const label = full ? t.showLess : t.showAll;\n if (more.textContent !== label) more.textContent = label;\n }\n }\n\n /** Re-measure when a block's wrapped height changes (width change, panel shown after display:none). */\n #observe(): void {\n if (typeof ResizeObserver === 'undefined') return;\n this.#ro ??= new ResizeObserver(() => this.#measure());\n this.#ro.disconnect();\n for (const code of this.$$('pre.tc-code > code')) this.#ro.observe(code);\n }\n\n #copy(part: ToolCallPart): void {\n const c = this.#code.get(part);\n if (!c) return;\n if (!this.emit<ToolCallCopyDetail>('ui-copy', this.#withId({ part, text: c.text }))) return;\n const done = () => this.#flashCopied(part);\n const fallback = () => this.#select(part);\n try {\n const clip = typeof navigator !== 'undefined' ? navigator.clipboard : undefined;\n if (clip && typeof clip.writeText === 'function') clip.writeText(c.text).then(done, fallback);\n else fallback();\n } catch {\n fallback();\n }\n }\n\n /** The copy icon morphs into a check for 1.4 s — in place, and a re-render in between keeps it. */\n #flashCopied(part: ToolCallPart): void {\n this.#copied.add(part);\n this.#paintCopy(part);\n this.#speak(this.#t.copied);\n clearTimeout(this.#copyTimers.get(part));\n this.#copyTimers.set(\n part,\n window.setTimeout(() => {\n this.#copied.delete(part);\n this.#copyTimers.delete(part);\n this.#paintCopy(part);\n }, COPIED_MS),\n );\n }\n\n #paintCopy(part: ToolCallPart): void {\n const b = this.$(`.tc-copy[data-part=\"${part}\"]`);\n if (!b) return;\n const t = this.#t;\n const on = this.#copied.has(part);\n const label = on ? t.copied : t.copy(part === 'args' ? t.args : t.result);\n b.toggleAttribute('data-copied', on);\n b.setAttribute('aria-label', label);\n b.setAttribute('title', label);\n }\n\n /** Without clipboard access (plain http, a denied permission) the block's text is selected for ⌘C / Ctrl+C. */\n #select(part: ToolCallPart): void {\n this.#fillCode(part);\n const code = this.$(`pre.tc-code[data-part=\"${part}\"] > code`);\n try {\n const sel = typeof getSelection === 'function' ? getSelection() : null;\n if (code && sel) {\n const range = document.createRange();\n range.selectNodeContents(code);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n } catch {\n /* selection is best effort */\n }\n this.#speak(this.#t.selected);\n }\n\n #speak(text: string): void {\n if (this.#live.textContent !== text) this.#live.textContent = text;\n }\n\n /** Status changes are announced once; a card that first appears finished or failed stays quiet. */\n #announce(): void {\n const d = this.data;\n if (!d) return;\n const st = normStatus(d.status);\n if (st === this.#saidStatus) return;\n const first = this.#saidStatus === undefined;\n this.#saidStatus = st;\n if (first && st !== 'running') return;\n const t = this.#t;\n const name = String(d.name ?? '');\n this.#speak(\n st === 'running'\n ? t.sayRunning(name)\n : st === 'success'\n ? t.sayDone(name)\n : st === 'error'\n ? t.sayFailed(name, d.error ? String(d.error) : '')\n : t.sayInterrupted(name),\n );\n }\n\n /** The live timer ticks a text node in place every 100 ms — only while running and connected. */\n #syncTick(): void {\n const run = !!this.data && normStatus(this.data.status) === 'running' && this.isConnected;\n if (run && !this.#tick) this.#tick = window.setInterval(() => this.#paintTime(), TICK_MS);\n else if (!run) this.#stopTick();\n }\n\n #stopTick(): void {\n if (!this.#tick) return;\n clearInterval(this.#tick);\n this.#tick = 0;\n }\n\n #paintTime(): void {\n const d = this.data;\n if (!d || normStatus(d.status) !== 'running' || !this.isConnected) {\n this.#stopTick();\n return;\n }\n const node = this.$('.tc-status .tc-time')?.firstChild;\n const text = formatToolMs(this.#liveMs(d), true);\n if (node && node.nodeType === Node.TEXT_NODE && (node as Text).data !== text) (node as Text).data = text;\n }\n}\n\ndefine('ui-tool-call-card', UiToolCallCard);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ui-tool-call-card': UiToolCallCard;\n }\n}\n","import { define, UiElement } from '../../core/element';\nimport { esc, escAttr } from '../../core/html';\nimport { formatToolMs, groupStats, type ToolCallData, type ToolCallGroupData } from './logic';\nimport { type ToolCallStrings, toolCallStrings } from './strings';\nimport { styles } from './styles';\nimport { CHEV_SVG, callIconSvg, type ToolCallToggleDetail, type UiToolCallCard } from './tool-call-card';\n\nconst TICK_MS = 100;\nconst STACK = 3;\n\n/** Stable keys for a group's calls: `id:<id>` when the call has an id, else `i:<index>` (duplicates get a suffix). */\nexport function callKeys(calls: ToolCallData[]): string[] {\n const seen = new Set<string>();\n return calls.map((c, i) => {\n const id = c && c.id !== undefined && c.id !== null && c.id !== '' ? `id:${c.id}` : `i:${i}`;\n const key = seen.has(id) ? `${id}#${i}` : id;\n seen.add(key);\n return key;\n });\n}\n\nfunction sameCall(a: ToolCallData, b: ToolCallData): boolean {\n if (a === b) return true;\n const ka = Object.keys(a) as Array<keyof ToolCallData>;\n if (ka.length !== Object.keys(b).length) return false;\n for (const k of ka) if (!Object.is(a[k], b[k])) return false;\n return true;\n}\n\nconst finite = (v: unknown): number | undefined => {\n if (v === undefined || v === null || v === '') return undefined;\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n};\n\ninterface Entry {\n el: UiToolCallCard;\n data: ToolCallData | undefined;\n}\n\n/**\n * `<ui-tool-call-group>` — several tool calls folded into one quiet line: the last three tools' icons stacked,\n * “Used 3 tools · 1 failed · 2.4s” (or “Using tools…” with a light sweep while any call runs). Open it for one\n * `<ui-tool-call-card>` per call. The cards live in a list outside the re-rendered line and are reconciled by key,\n * so a group update never re-creates them (open state, timers and copy checks survive).\n */\nexport class UiToolCallGroup extends UiElement<ToolCallGroupData> {\n static override styles = [styles];\n static get observedAttributes() {\n return ['lang', 'theme'];\n }\n\n #open = false;\n #shownOpen = false;\n #rendered = false;\n #running: boolean | undefined;\n #titleIn = false;\n #acc = 0;\n #since: number | null = null;\n #lastEnd = 0;\n #tick = 0;\n #keys: string[] = [];\n #stack = new Set<string>();\n #cards = new Map<string, Entry>();\n #saidRunning: boolean | undefined;\n readonly #body: HTMLElement;\n readonly #list: HTMLElement;\n readonly #live: HTMLElement;\n\n constructor() {\n super();\n this.#body = document.createElement('div');\n this.#body.className = 'tc-body tcg-body';\n this.#body.id = 'tcg-body';\n this.#body.hidden = true;\n this.#body.setAttribute('inert', '');\n const clip = document.createElement('div');\n clip.className = 'tc-clip';\n this.#list = document.createElement('div');\n this.#list.className = 'tcg-list';\n this.#list.setAttribute('role', 'list');\n clip.append(this.#list);\n this.#body.append(clip);\n this.#live = document.createElement('span');\n this.#live.className = 'sr-only';\n this.#live.setAttribute('role', 'status');\n this.#live.setAttribute('aria-live', 'polite');\n this.root.append(this.#body, this.#live);\n this.root.addEventListener('click', (e) => {\n if ((e.target as Element | null)?.closest?.('.tcg-head')) this.#toggle();\n });\n }\n\n attributeChangedCallback(): void {\n this.requestRender();\n }\n\n override disconnectedCallback(): void {\n this.#stopTick();\n }\n\n /** Focus the group's header button. */\n override focus(options?: FocusOptions): void {\n if (!this.$('.tcg-head') && this.data && this.isConnected) this.renderNow();\n const head = this.$<HTMLButtonElement>('.tcg-head');\n if (head) head.focus(options);\n else super.focus(options);\n }\n\n /** Whether the list is open now (controlled `data.open`, else the element's own state). */\n get isOpen(): boolean {\n return this.data ? this.#isOpen(this.data) : false;\n }\n\n /** The card elements, in call order. */\n get cards(): UiToolCallCard[] {\n return Array.from(this.#cards.values(), (e) => e.el);\n }\n\n get #t(): ToolCallStrings {\n return toolCallStrings(this.getAttribute('lang'));\n }\n\n #isOpen(d: ToolCallGroupData): boolean {\n return d.open ?? this.#open;\n }\n\n /** Time with tools running, added up over running stretches (e.g. a pause before a retry). */\n #syncRun(running: boolean, calls: ToolCallData[]): void {\n const prev = this.#running;\n this.#titleIn = prev !== undefined && prev !== running;\n const now = Date.now();\n if (running && this.#since === null) {\n const starts = calls\n .filter((c) => c.status === 'running')\n .map((c) => finite(c.startedAt))\n .filter((v): v is number => v !== undefined);\n const first = starts.length ? Math.min(...starts) : now;\n this.#since = Math.min(now, Math.max(this.#lastEnd, first));\n } else if (!running && this.#since !== null) {\n this.#lastEnd = now;\n this.#acc += now - this.#since;\n this.#since = null;\n }\n if (prev !== running && !running) this.#stopTick();\n this.#running = running;\n }\n\n #liveMs(): number {\n return this.#acc + (this.#since === null ? 0 : Math.max(0, Date.now() - this.#since));\n }\n\n protected render(): string {\n const d = this.data;\n if (!d) return '';\n const calls = Array.isArray(d.calls) ? d.calls : [];\n const t = this.#t;\n const { running, failed, sum } = groupStats(calls);\n this.#syncRun(running, calls);\n if (!this.#rendered) this.#open = !!d.defaultOpen;\n const open = this.#isOpen(d);\n const first = !this.#rendered;\n if (first) {\n this.#rendered = true;\n this.#shownOpen = open;\n }\n const shown = this.#shownOpen;\n const keys = callKeys(calls);\n this.#keys = keys;\n\n // The last three tools; a tile that just joined the stack pops in, the others stay still.\n const from = Math.max(0, calls.length - STACK);\n const stackKeys = new Set<string>();\n let stack = '';\n for (let i = from; i < calls.length; i++) {\n stackKeys.add(keys[i]);\n const enter = !first && !this.#stack.has(keys[i]);\n stack += `<span class=\"tc-icon${enter ? ' is-in' : ''}\">${callIconSvg(calls[i] ?? { name: '' })}</span>`;\n }\n this.#stack = stackKeys;\n\n const title = running ? d.runningLabel || t.using : d.label || t.used(calls.length);\n const ms = running ? this.#liveMs() : (finite(d.duration) ?? sum ?? (this.#acc > 0 ? this.#acc : undefined));\n return `<div class=\"tcg\"${running ? ' data-running' : ''}${shown ? ' data-open' : ''}><button type=\"button\" class=\"tcg-head\" data-key=\"head\" aria-expanded=\"${shown}\" aria-controls=\"tcg-body\"${\n d.focusable === false ? ' tabindex=\"-1\"' : ''\n }><span class=\"tcg-stack\" aria-hidden=\"true\">${stack}</span><span class=\"tcg-title${this.#titleIn ? ' is-in' : ''}\"><span class=\"tcg-label${\n running ? ' tc-shine' : ''\n }\" data-text=\"${escAttr(title)}\">${esc(title)}</span>${\n !running && failed ? `<span class=\"tcg-failed\">· ${esc(t.nFailed(failed))}</span>` : ''\n }${ms !== undefined ? `<span class=\"tcg-time\">· ${esc(formatToolMs(ms, running))}</span>` : ''}</span>${CHEV_SVG}</button></div>`;\n }\n\n protected override updated(): void {\n const d = this.data;\n this.#body.hidden = !d;\n if (d) {\n this.#reconcile(d);\n const open = this.#isOpen(d);\n if (open !== this.#shownOpen) {\n this.$('.tcg')?.getBoundingClientRect(); // commit the current state so the change transitions\n this.#shownOpen = open;\n }\n this.#applyOpen(this.#shownOpen);\n }\n this.#syncTick();\n this.#announce();\n }\n\n /** One card per call, keyed by id (else index): create / remove only what changed, keep the rest in place. */\n #reconcile(d: ToolCallGroupData): void {\n const calls = Array.isArray(d.calls) ? d.calls : [];\n const keys = this.#keys.length === calls.length ? this.#keys : callKeys(calls);\n const lang = this.getAttribute('lang');\n const theme = this.getAttribute('theme');\n const next = new Map<string, Entry>();\n calls.forEach((call, i) => {\n if (!call) return;\n let entry = this.#cards.get(keys[i]);\n if (!entry) {\n const el = document.createElement('ui-tool-call-card');\n el.setAttribute('role', 'listitem');\n entry = { el, data: undefined };\n }\n syncAttr(entry.el, 'lang', lang);\n syncAttr(entry.el, 'theme', theme);\n const data = d.focusable === false && call.focusable === undefined ? { ...call, focusable: false } : call;\n if (!entry.data || !sameCall(entry.data, data)) {\n entry.data = data;\n entry.el.data = data;\n }\n next.set(keys[i], entry);\n });\n for (const [key, entry] of this.#cards) if (!next.has(key)) entry.el.remove();\n let at = this.#list.firstElementChild;\n for (const { el } of next.values()) {\n if (el === at) at = at.nextElementSibling;\n else this.#list.insertBefore(el, at);\n }\n this.#cards = next;\n }\n\n #applyOpen(open: boolean): void {\n this.$('.tcg')?.toggleAttribute('data-open', open);\n this.$('.tcg-head')?.setAttribute('aria-expanded', String(open));\n this.#body.toggleAttribute('data-open', open);\n this.#body.toggleAttribute('inert', !open);\n }\n\n #toggle(): void {\n const d = this.data;\n if (!d) return;\n const next = !this.#isOpen(d);\n if (!this.emit<ToolCallToggleDetail>('ui-toggle', { open: next })) return;\n if (d.open !== undefined) return; // controlled: the host answers with data.open\n this.#open = next;\n this.#shownOpen = next;\n this.#applyOpen(next);\n }\n\n /** Running ↔ done is announced once each way; a group that first appears done stays quiet. */\n #announce(): void {\n const d = this.data;\n if (!d) return;\n const running = !!this.#running;\n if (running === this.#saidRunning) return;\n const first = this.#saidRunning === undefined;\n this.#saidRunning = running;\n if (first && !running) return;\n const t = this.#t;\n const calls = Array.isArray(d.calls) ? d.calls : [];\n const text = running\n ? d.runningLabel || t.using\n : t.groupSay(d.label || t.used(calls.length), groupStats(calls).failed);\n if (this.#live.textContent !== text) this.#live.textContent = text;\n }\n\n #syncTick(): void {\n const run = !!this.data && !!this.#running && this.isConnected;\n if (run && !this.#tick) this.#tick = window.setInterval(() => this.#paintTime(), TICK_MS);\n else if (!run) this.#stopTick();\n }\n\n #stopTick(): void {\n if (!this.#tick) return;\n clearInterval(this.#tick);\n this.#tick = 0;\n }\n\n #paintTime(): void {\n if (!this.#running || !this.isConnected) {\n this.#stopTick();\n return;\n }\n const node = this.$('.tcg-time')?.firstChild;\n const text = `· ${formatToolMs(this.#liveMs(), true)}`;\n if (node && node.nodeType === Node.TEXT_NODE && (node as Text).data !== text) (node as Text).data = text;\n }\n}\n\nfunction syncAttr(el: Element, name: string, value: string | null): void {\n if (el.getAttribute(name) === value) return;\n if (value === null) el.removeAttribute(name);\n else el.setAttribute(name, value);\n}\n\ndefine('ui-tool-call-group', UiToolCallGroup);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ui-tool-call-group': UiToolCallGroup;\n }\n}\n"],"names":["TICK_MS","finite"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@2lab.ai/ui",
3
- "version": "0.1.1",
4
- "description": "Agent UI components for 2lab \u2014 Web Components, zero runtime dependencies. Agent Inbox, Agent Run, AI Answer, Context Window, Model Picker, Memory Panel, Agent Queue.",
3
+ "version": "0.2.0",
4
+ "description": "Agent UI components for 2lab \u2014 Web Components, zero runtime dependencies. Agent Inbox, Agent Run, AI Answer, Tool Call Card, Context Window, Model Picker, Memory Panel, Agent Queue.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "repository": {
@@ -53,6 +53,10 @@
53
53
  "types": "./dist/components/agent-queue/index.d.ts",
54
54
  "import": "./dist/agent-queue.js"
55
55
  },
56
+ "./tool-call-card": {
57
+ "types": "./dist/components/tool-call-card/index.d.ts",
58
+ "import": "./dist/tool-call-card.js"
59
+ },
56
60
  "./tokens.css": "./dist/tokens.css",
57
61
  "./package.json": "./package.json"
58
62
  },
@@ -1 +0,0 @@
1
- {"version":3,"file":"html-DZWnrdcg.js","sources":["../src/core/tokens.ts","../src/core/element.ts","../src/core/html.ts"],"sourcesContent":["import tokens from './tokens.json';\n\n/**\n * Design tokens. Inside every component's shadow root the dashboard names (`--text`, `--surface`, `--st-run` …)\n * are defined on `:host` and read the public `--ui-*` property first, so a page themes every component by\n * setting `--ui-text` etc. (or loading `@2lab.ai/ui/tokens.css`). Without any page tokens a component follows\n * `prefers-color-scheme`, and the `theme=\"light|dark\"` attribute pins it.\n */\nexport type TokenSet = Record<string, string>;\nexport const LIGHT: TokenSet = tokens.light;\nexport const DARK: TokenSet = tokens.dark;\nexport const SHARED: TokenSet = tokens.shared;\n\nfunction hostVars(set: TokenSet): string {\n return Object.entries(set)\n .map(([k, v]) => `--${k}: var(--ui-${k}, ${v});`)\n .join(' ');\n}\n\nfunction pageVars(set: TokenSet): string {\n return Object.entries(set)\n .map(([k, v]) => `--ui-${k}: ${v};`)\n .join(' ');\n}\n\n/** Shared stylesheet prepended to every component's shadow root. */\nexport const baseCss = `\n:host { ${hostVars(SHARED)} ${hostVars(LIGHT)}\n display: block; box-sizing: border-box; color: var(--text); font-family: var(--font);\n font-size: 14px; line-height: 1.45; -webkit-font-smoothing: antialiased; color-scheme: light; }\n:host([theme=\"dark\"]) { ${hostVars(DARK)} color-scheme: dark; }\n@media (prefers-color-scheme: dark) { :host(:not([theme=\"light\"])) { ${hostVars(DARK)} color-scheme: dark; } }\n:host([hidden]) { display: none; }\n*, *::before, *::after { box-sizing: border-box; }\nbutton, input, textarea, select { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\n:focus { outline: none; }\n:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }\n.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;\n clip: rect(0 0 0 0); white-space: nowrap; border: 0; }\n.mono { font-family: var(--mono); }\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important; scroll-behavior: auto !important; }\n}\n`;\n\n/** Optional page-level tokens (`@2lab.ai/ui/tokens.css`): `data-theme=\"dark|light\"` on any ancestor switches. */\nexport const tokensCss = `/* @2lab.ai/ui design tokens */\n:root, [data-theme=\"light\"] { ${pageVars(SHARED)} ${pageVars(LIGHT)} color-scheme: light; }\n[data-theme=\"dark\"] { ${pageVars(DARK)} color-scheme: dark; }\n@media (prefers-color-scheme: dark) { :root:not([data-theme=\"light\"]) { ${pageVars(DARK)} color-scheme: dark; } }\n`;\n","import { baseCss } from './tokens';\n\n/**\n * Base class for every @2lab.ai/ui component.\n *\n * - Open shadow root with `baseCss` + the subclass's `static styles`.\n * - Data in, events out: set `el.data = {...}` (or the component's own properties) → one batched render;\n * user intent leaves as a bubbling, composed `CustomEvent` (`ui-*`) that the host app handles.\n * - `render()` returns an HTML string; every dynamic value must go through `esc` / `escAttr` / `safeHref`.\n * - Focus survives a re-render when the focused element carries `data-key` (restored to the same key).\n * - Subclasses that tick (timers) should update text nodes in place instead of re-rendering.\n */\nexport abstract class UiElement<D = unknown> extends HTMLElement {\n static styles: string[] = [];\n\n protected readonly root: ShadowRoot;\n protected readonly content: HTMLElement;\n #data: D | undefined;\n #queued = false;\n #gen = 0;\n\n constructor() {\n super();\n this.root = this.attachShadow({ mode: 'open' });\n const ctor = this.constructor as typeof UiElement;\n const style = document.createElement('style');\n style.textContent = [baseCss, ...ctor.styles].join('\\n');\n this.content = document.createElement('div');\n this.content.setAttribute('part', 'root');\n this.content.className = 'ui-root';\n this.root.append(style, this.content);\n }\n\n get data(): D | undefined {\n return this.#data;\n }\n\n set data(value: D | undefined) {\n this.#data = value;\n this.requestRender();\n }\n\n connectedCallback(): void {\n this.requestRender();\n }\n\n disconnectedCallback(): void {}\n\n /** Batch renders into one microtask. */\n requestRender(): void {\n if (this.#queued) return;\n this.#queued = true;\n const gen = this.#gen;\n queueMicrotask(() => {\n if (!this.#queued || gen !== this.#gen) return;\n this.#queued = false;\n if (this.isConnected) this.update();\n });\n }\n\n /** Render synchronously (tests, or right before measuring). Cancels a queued render. */\n renderNow(): void {\n this.#queued = false;\n this.#gen++;\n this.update();\n }\n\n protected update(): void {\n const key = this.#focusedKey();\n this.content.innerHTML = this.render();\n if (key) {\n // Compare dataset values instead of building a selector: keys may hold any characters.\n const next = Array.from(this.content.querySelectorAll<HTMLElement>('[data-key]')).find(\n (el) => el.dataset.key === key,\n );\n next?.focus({ preventScroll: true });\n }\n this.updated();\n }\n\n #focusedKey(): string | undefined {\n try {\n const active = this.root.activeElement as HTMLElement | null;\n return active && this.content.contains(active) ? active.dataset?.key : undefined;\n } catch {\n return undefined;\n }\n }\n\n /** The component's markup. */\n protected abstract render(): string;\n\n /** Hook after each render (wire listeners on fresh nodes, start timers). */\n protected updated(): void {}\n\n /** Dispatch a bubbling, composed, cancelable event. Returns false when a listener called preventDefault(). */\n protected emit<T>(name: string, detail: T): boolean {\n return this.dispatchEvent(new CustomEvent<T>(name, { detail, bubbles: true, composed: true, cancelable: true }));\n }\n\n /** Query inside the shadow root. */\n protected $<E extends Element = HTMLElement>(selector: string): E | null {\n return this.root.querySelector<E>(selector);\n }\n\n protected $$<E extends Element = HTMLElement>(selector: string): E[] {\n return Array.from(this.root.querySelectorAll<E>(selector));\n }\n}\n\n/** Register a custom element once (safe to import twice). */\nexport function define(tag: string, ctor: CustomElementConstructor): void {\n if (typeof customElements !== 'undefined' && !customElements.get(tag)) customElements.define(tag, ctor);\n}\n\n/** True when the user asked for less motion. */\nexport function prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n","/** HTML-escape text for element content. Every model-, user- or tool-written string goes through this. */\nexport function esc(value: unknown): string {\n return String(value ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/** Escape for a double-quoted attribute value. */\nexport function escAttr(value: unknown): string {\n return esc(value).replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n}\n\nconst SAFE_SCHEMES = /^(https?:|mailto:)/i;\n\n/** A link target that cannot run script: http(s)/mailto only, otherwise `#`. */\nexport function safeHref(url: unknown): string {\n const s = String(url ?? '').trim();\n return SAFE_SCHEMES.test(s) ? escAttr(s) : '#';\n}\n\n/** Join class names, skipping falsy entries. */\nexport function cls(...names: Array<string | false | null | undefined>): string {\n return names.filter(Boolean).join(' ');\n}\n\n/** `key=\"value\"` pairs for truthy values, escaped. `true` renders a bare boolean attribute. */\nexport function attrs(map: Record<string, string | number | boolean | null | undefined>): string {\n let out = '';\n for (const [k, v] of Object.entries(map)) {\n if (v === false || v === null || v === undefined) continue;\n out += v === true ? ` ${k}` : ` ${k}=\"${escAttr(v)}\"`;\n }\n return out;\n}\n"],"names":[],"mappings":"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"}