@hex-core/components 1.7.0 → 1.8.1
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/dist/_tsup-dts-rollup.d.ts +1566 -5
- package/dist/arc.d.ts +4 -0
- package/dist/arc.js +147 -0
- package/dist/arc.js.map +1 -0
- package/dist/audio-player.d.ts +2 -0
- package/dist/audio-player.js +119 -0
- package/dist/audio-player.js.map +1 -0
- package/dist/audio-waveform.d.ts +2 -0
- package/dist/audio-waveform.js +72 -0
- package/dist/audio-waveform.js.map +1 -0
- package/dist/canvas.d.ts +2 -0
- package/dist/canvas.js +73 -0
- package/dist/canvas.js.map +1 -0
- package/dist/chord.d.ts +4 -0
- package/dist/chord.js +230 -0
- package/dist/chord.js.map +1 -0
- package/dist/cloze.d.ts +3 -0
- package/dist/cloze.js +98 -0
- package/dist/cloze.js.map +1 -0
- package/dist/color-picker.js.map +1 -1
- package/dist/compare-table.d.ts +4 -0
- package/dist/compare-table.js +109 -0
- package/dist/compare-table.js.map +1 -0
- package/dist/data-table.js.map +1 -1
- package/dist/deck.d.ts +3 -0
- package/dist/deck.js +231 -0
- package/dist/deck.js.map +1 -0
- package/dist/dendrogram.d.ts +3 -0
- package/dist/dendrogram.js +162 -0
- package/dist/dendrogram.js.map +1 -0
- package/dist/diagram.d.ts +2 -0
- package/dist/diagram.js +70 -0
- package/dist/diagram.js.map +1 -0
- package/dist/flashcard.d.ts +2 -0
- package/dist/flashcard.js +107 -0
- package/dist/flashcard.js.map +1 -0
- package/dist/flowchart.d.ts +4 -0
- package/dist/flowchart.js +275 -0
- package/dist/flowchart.js.map +1 -0
- package/dist/funnel.d.ts +3 -0
- package/dist/funnel.js +157 -0
- package/dist/funnel.js.map +1 -0
- package/dist/gantt.d.ts +3 -0
- package/dist/gantt.js +279 -0
- package/dist/gantt.js.map +1 -0
- package/dist/image-occlusion.d.ts +3 -0
- package/dist/image-occlusion.js +106 -0
- package/dist/image-occlusion.js.map +1 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +3946 -2
- package/dist/index.js.map +1 -1
- package/dist/matrix.d.ts +3 -0
- package/dist/matrix.js +155 -0
- package/dist/matrix.js.map +1 -0
- package/dist/mind-map.d.ts +3 -0
- package/dist/mind-map.js +167 -0
- package/dist/mind-map.js.map +1 -0
- package/dist/org-chart.d.ts +3 -0
- package/dist/org-chart.js +215 -0
- package/dist/org-chart.js.map +1 -0
- package/dist/pyramid.d.ts +3 -0
- package/dist/pyramid.js +150 -0
- package/dist/pyramid.js.map +1 -0
- package/dist/quiz.d.ts +3 -0
- package/dist/quiz.js +128 -0
- package/dist/quiz.js.map +1 -0
- package/dist/sankey.d.ts +4 -0
- package/dist/sankey.js +190 -0
- package/dist/sankey.js.map +1 -0
- package/dist/schemas.d.ts +23 -0
- package/dist/schemas.js +2210 -3
- package/dist/schemas.js.map +1 -1
- package/dist/sequence.d.ts +4 -0
- package/dist/sequence.js +229 -0
- package/dist/sequence.js.map +1 -0
- package/dist/sonner.js.map +1 -1
- package/dist/spaced-repetition.d.ts +3 -0
- package/dist/spaced-repetition.js +73 -0
- package/dist/spaced-repetition.js.map +1 -0
- package/dist/sunburst.d.ts +3 -0
- package/dist/sunburst.js +205 -0
- package/dist/sunburst.js.map +1 -0
- package/dist/terminal.d.ts +2 -0
- package/dist/terminal.js +153 -0
- package/dist/terminal.js.map +1 -0
- package/dist/textarea.js.map +1 -1
- package/dist/time-axis.d.ts +3 -0
- package/dist/time-axis.js +233 -0
- package/dist/time-axis.js.map +1 -0
- package/dist/tool-call.js +6 -1
- package/dist/tool-call.js.map +1 -1
- package/dist/tree-map.d.ts +3 -0
- package/dist/tree-map.js +171 -0
- package/dist/tree-map.js.map +1 -0
- package/dist/venn.d.ts +3 -0
- package/dist/venn.js +196 -0
- package/dist/venn.js.map +1 -0
- package/package.json +49 -5
package/dist/terminal.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
// src/lib/color.ts
|
|
8
|
+
function parseHslTriplet(triplet) {
|
|
9
|
+
const parts = triplet.trim().split(/\s+/);
|
|
10
|
+
return {
|
|
11
|
+
h: Number.parseFloat(parts[0]) || 0,
|
|
12
|
+
s: Number.parseFloat(parts[1]) || 0,
|
|
13
|
+
l: Number.parseFloat(parts[2]) || 0
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function hslToRgb(h, s, l) {
|
|
17
|
+
const sN = s / 100;
|
|
18
|
+
const lN = l / 100;
|
|
19
|
+
const k = (n) => (n + h / 30) % 12;
|
|
20
|
+
const a = sN * Math.min(lN, 1 - lN);
|
|
21
|
+
const f = (n) => lN - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));
|
|
22
|
+
return {
|
|
23
|
+
r: Math.round(255 * f(0)),
|
|
24
|
+
g: Math.round(255 * f(8)),
|
|
25
|
+
b: Math.round(255 * f(4))
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function hslTripletToHex(triplet) {
|
|
29
|
+
const { h, s, l } = parseHslTriplet(triplet);
|
|
30
|
+
const { r, g, b } = hslToRgb(h, s, l);
|
|
31
|
+
const toHex = (n) => n.toString(16).padStart(2, "0");
|
|
32
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
33
|
+
}
|
|
34
|
+
function cn(...inputs) {
|
|
35
|
+
return twMerge(clsx(inputs));
|
|
36
|
+
}
|
|
37
|
+
var DARK_FALLBACK = {
|
|
38
|
+
background: "#0a0a0a",
|
|
39
|
+
foreground: "#e5e5e5",
|
|
40
|
+
selectionBackground: "#404040"
|
|
41
|
+
};
|
|
42
|
+
var LIGHT_FALLBACK = {
|
|
43
|
+
background: "#fafafa",
|
|
44
|
+
foreground: "#171717",
|
|
45
|
+
selectionBackground: "#d4d4d4"
|
|
46
|
+
};
|
|
47
|
+
function readCssVarAsHex(name) {
|
|
48
|
+
if (typeof document === "undefined") return null;
|
|
49
|
+
const triplet = getComputedStyle(document.documentElement).getPropertyValue(`--${name}`).trim();
|
|
50
|
+
if (!triplet) return null;
|
|
51
|
+
return hslTripletToHex(triplet);
|
|
52
|
+
}
|
|
53
|
+
function Terminal({
|
|
54
|
+
output,
|
|
55
|
+
onInput,
|
|
56
|
+
cols = 80,
|
|
57
|
+
rows = 24,
|
|
58
|
+
theme = "dark",
|
|
59
|
+
cursorBlink = true,
|
|
60
|
+
disableInput = false,
|
|
61
|
+
className,
|
|
62
|
+
...rest
|
|
63
|
+
}) {
|
|
64
|
+
const containerRef = React.useRef(null);
|
|
65
|
+
const termRef = React.useRef(null);
|
|
66
|
+
const writtenRef = React.useRef("");
|
|
67
|
+
const onInputRef = React.useRef(onInput);
|
|
68
|
+
onInputRef.current = onInput;
|
|
69
|
+
const outputRef = React.useRef(output);
|
|
70
|
+
outputRef.current = output;
|
|
71
|
+
React.useEffect(() => {
|
|
72
|
+
if (!containerRef.current) return;
|
|
73
|
+
let disposed = false;
|
|
74
|
+
let inputDispose = null;
|
|
75
|
+
void (async () => {
|
|
76
|
+
const xtermModule = await import('@xterm/xterm');
|
|
77
|
+
if (disposed || !containerRef.current) return;
|
|
78
|
+
const fallback = theme === "dark" ? DARK_FALLBACK : LIGHT_FALLBACK;
|
|
79
|
+
const bgHex = readCssVarAsHex("background") ?? fallback.background;
|
|
80
|
+
const fgHex = readCssVarAsHex("foreground") ?? fallback.foreground;
|
|
81
|
+
const term = new xtermModule.Terminal({
|
|
82
|
+
cols,
|
|
83
|
+
rows,
|
|
84
|
+
cursorBlink,
|
|
85
|
+
disableStdin: disableInput,
|
|
86
|
+
theme: {
|
|
87
|
+
background: bgHex,
|
|
88
|
+
foreground: fgHex,
|
|
89
|
+
cursor: fgHex,
|
|
90
|
+
selectionBackground: fallback.selectionBackground
|
|
91
|
+
},
|
|
92
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
93
|
+
fontSize: 13
|
|
94
|
+
});
|
|
95
|
+
term.open(containerRef.current);
|
|
96
|
+
termRef.current = term;
|
|
97
|
+
const latest = normalizeOutput(outputRef.current);
|
|
98
|
+
if (latest) {
|
|
99
|
+
term.write(latest);
|
|
100
|
+
writtenRef.current = latest;
|
|
101
|
+
}
|
|
102
|
+
inputDispose = term.onData((data) => {
|
|
103
|
+
onInputRef.current?.(data);
|
|
104
|
+
});
|
|
105
|
+
})();
|
|
106
|
+
return () => {
|
|
107
|
+
disposed = true;
|
|
108
|
+
inputDispose?.dispose();
|
|
109
|
+
termRef.current?.dispose();
|
|
110
|
+
termRef.current = null;
|
|
111
|
+
writtenRef.current = "";
|
|
112
|
+
};
|
|
113
|
+
}, []);
|
|
114
|
+
React.useEffect(() => {
|
|
115
|
+
const term = termRef.current;
|
|
116
|
+
if (!term) return;
|
|
117
|
+
const next = normalizeOutput(output);
|
|
118
|
+
if (next === writtenRef.current) return;
|
|
119
|
+
if (next.startsWith(writtenRef.current)) {
|
|
120
|
+
const delta = next.slice(writtenRef.current.length);
|
|
121
|
+
if (delta) term.write(delta);
|
|
122
|
+
} else {
|
|
123
|
+
term.reset();
|
|
124
|
+
if (next) term.write(next);
|
|
125
|
+
}
|
|
126
|
+
writtenRef.current = next;
|
|
127
|
+
}, [output]);
|
|
128
|
+
const fallbackTriplet = theme === "dark" ? "0 0% 4%" : "0 0% 98%";
|
|
129
|
+
const themeBg = `hsl(var(--background, ${fallbackTriplet}))`;
|
|
130
|
+
return /* @__PURE__ */ jsx(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
...rest,
|
|
134
|
+
ref: containerRef,
|
|
135
|
+
"data-hex-terminal": true,
|
|
136
|
+
"data-theme": theme,
|
|
137
|
+
style: { backgroundColor: themeBg, ...rest.style ?? {} },
|
|
138
|
+
className: cn(
|
|
139
|
+
"overflow-hidden rounded-md border p-2",
|
|
140
|
+
"font-mono text-sm leading-tight",
|
|
141
|
+
className
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
function normalizeOutput(value) {
|
|
147
|
+
if (value == null) return "";
|
|
148
|
+
return Array.isArray(value) ? value.join("") : value;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { Terminal };
|
|
152
|
+
//# sourceMappingURL=terminal.js.map
|
|
153
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/color.ts","../src/lib/utils.ts","../src/ai/terminal/terminal.tsx"],"names":[],"mappings":"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","file":"terminal.js","sourcesContent":["/**\n * Color conversion utilities for the HSL-triplet token format used across\n * `@hex-core/tokens` themes (`H S% L%`, e.g. `\"240 5.9% 10%\"` — no `hsl()`\n * wrapper, no commas).\n *\n * The triplet is the round-trip-safe serialization for Hex Core: tokens flow\n * triplet → CSS `hsl(var(--token))` → rendered color, and the ColorPicker\n * component edits triplets directly. Hex/RGB conversions are display\n * adapters, not the source of truth.\n */\n\n/** Parsed HSL components. `h` is degrees (0–360); `s` and `l` are percentages (0–100). */\nexport interface HslTriplet {\n\th: number;\n\ts: number;\n\tl: number;\n}\n\n/** Parsed RGB components. Each channel is 0–255. */\nexport interface RgbColor {\n\tr: number;\n\tg: number;\n\tb: number;\n}\n\n/**\n * Parse an HSL triplet string into numeric components.\n *\n * Note: malformed input silently coerces to `{0,0,0}` (pure black) rather than\n * returning an error signal. Callers that need to distinguish \"user typed\n * black\" from \"user typed garbage\" should validate the input format first.\n * `hexToHslTriplet` returns `null` for malformed hex; this asymmetry is\n * intentional — triplets feed CSS variables where any non-color value would\n * already break rendering.\n *\n * @param triplet - String in the form `\"<H> <S>% <L>%\"` (e.g. `\"240 5.9% 10%\"`).\n * @returns Numeric components, or `{0,0,0}` if the input is malformed.\n */\nexport function parseHslTriplet(triplet: string): HslTriplet {\n\tconst parts = triplet.trim().split(/\\s+/);\n\treturn {\n\t\th: Number.parseFloat(parts[0]) || 0,\n\t\ts: Number.parseFloat(parts[1]) || 0,\n\t\tl: Number.parseFloat(parts[2]) || 0,\n\t};\n}\n\n/**\n * Format HSL components into an HSL triplet string (the canonical token format).\n * @param hsl - Numeric components.\n * @returns Triplet in the form `\"<H> <S>% <L>%\"`.\n */\nexport function formatHslTriplet({ h, s, l }: HslTriplet): string {\n\t// Tolerant integer check: rgbToHsl can produce values like 5.0000000001 due\n\t// to float arithmetic; format those as \"5\" rather than \"5.0\".\n\tconst round = (n: number) =>\n\t\tMath.abs(n - Math.round(n)) < 1e-6 ? `${Math.round(n)}` : n.toFixed(1);\n\treturn `${Math.round(h)} ${round(s)}% ${round(l)}%`;\n}\n\n/**\n * Convert HSL components to RGB.\n * @param h - Hue (0–360).\n * @param s - Saturation (0–100).\n * @param l - Lightness (0–100).\n * @returns RGB channels (0–255, rounded).\n */\nexport function hslToRgb(h: number, s: number, l: number): RgbColor {\n\tconst sN = s / 100;\n\tconst lN = l / 100;\n\tconst k = (n: number) => (n + h / 30) % 12;\n\tconst a = sN * Math.min(lN, 1 - lN);\n\tconst f = (n: number) => lN - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));\n\treturn {\n\t\tr: Math.round(255 * f(0)),\n\t\tg: Math.round(255 * f(8)),\n\t\tb: Math.round(255 * f(4)),\n\t};\n}\n\n/**\n * Convert RGB components to HSL.\n * @param r - Red (0–255).\n * @param g - Green (0–255).\n * @param b - Blue (0–255).\n * @returns HSL components (h: 0–360, s: 0–100, l: 0–100).\n */\nexport function rgbToHsl(r: number, g: number, b: number): HslTriplet {\n\tconst rN = r / 255;\n\tconst gN = g / 255;\n\tconst bN = b / 255;\n\tconst max = Math.max(rN, gN, bN);\n\tconst min = Math.min(rN, gN, bN);\n\tlet h = 0;\n\tlet s = 0;\n\tconst l = (max + min) / 2;\n\tif (max !== min) {\n\t\tconst d = max - min;\n\t\ts = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n\t\tif (max === rN) h = (gN - bN) / d + (gN < bN ? 6 : 0);\n\t\telse if (max === gN) h = (bN - rN) / d + 2;\n\t\telse h = (rN - gN) / d + 4;\n\t\th /= 6;\n\t}\n\treturn { h: h * 360, s: s * 100, l: l * 100 };\n}\n\n/**\n * Convert an HSL triplet to a 6-digit hex string.\n * @param triplet - HSL triplet (e.g. `\"240 5.9% 10%\"`).\n * @returns Lowercase hex string with leading `#` (e.g. `\"#181a1f\"`).\n */\nexport function hslTripletToHex(triplet: string): string {\n\tconst { h, s, l } = parseHslTriplet(triplet);\n\tconst { r, g, b } = hslToRgb(h, s, l);\n\tconst toHex = (n: number) => n.toString(16).padStart(2, \"0\");\n\treturn `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n}\n\n/**\n * Convert a hex string to an HSL triplet.\n * Accepts 3-digit (`#abc`) or 6-digit (`#aabbcc`) hex with optional `#`.\n * @param hex - Hex color string.\n * @returns HSL triplet, or `null` if the input is malformed.\n */\nexport function hexToHslTriplet(hex: string): string | null {\n\tconst clean = hex.trim().replace(/^#/, \"\");\n\tlet normalized: string;\n\tif (/^[0-9a-fA-F]{3}$/.test(clean)) {\n\t\tnormalized = clean\n\t\t\t.split(\"\")\n\t\t\t.map((c) => c + c)\n\t\t\t.join(\"\");\n\t} else if (/^[0-9a-fA-F]{6}$/.test(clean)) {\n\t\tnormalized = clean;\n\t} else {\n\t\treturn null;\n\t}\n\tconst r = Number.parseInt(normalized.slice(0, 2), 16);\n\tconst g = Number.parseInt(normalized.slice(2, 4), 16);\n\tconst b = Number.parseInt(normalized.slice(4, 6), 16);\n\treturn formatHslTriplet(rgbToHsl(r, g, b));\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { hslTripletToHex } from \"../../lib/color.js\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Headless terminal display backed by xterm.js. Renders an xterm grid\n * inside a div the consumer styles. No PTY, no shell — the consumer\n * owns the data-flow:\n *\n * - Pass `output` (string or string[]) to write to the display. Each\n * change is diffed against the prior render and only the new tail\n * is `term.write()`-ed, so feeding a streaming buffer doesn't redraw.\n * - Pass `onInput` to receive bytes the user typed. Wire it to a\n * WebSocket / IPC / fetch stream — terminal doesn't care.\n *\n * Heavy peer: requires `@xterm/xterm` (~150 KB gzip). The hex-core CLI's\n * `add` flow prompts before installing.\n *\n * @example\n * <Terminal\n * output={[\"$ ls\\r\\n\", \"package.json src/\\r\\n\", \"$ \"]}\n * onInput={(data) => ws.send(data)}\n * rows={24}\n * cols={80}\n * />\n */\nexport interface TerminalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\" | \"onInput\"> {\n\t/**\n\t * Bytes to display. String is written verbatim; string[] is joined.\n\t * On change, only the suffix beyond the prior render is emitted, so\n\t * appending to a streaming buffer is O(delta).\n\t */\n\toutput?: string | string[];\n\t/** Receive bytes the user typed (incl. control sequences). */\n\tonInput?: (data: string) => void;\n\t/** Initial cols. xterm allows runtime resize via fit-addon (not bundled). Default 80. */\n\tcols?: number;\n\t/** Initial rows. Default 24. */\n\trows?: number;\n\t/** Theme tokens — defaults to neutral light/dark via CSS vars. */\n\ttheme?: \"dark\" | \"light\";\n\t/** Enable cursor blink. Default true. */\n\tcursorBlink?: boolean;\n\t/** Whether the user can type into the terminal. Default true. */\n\tdisableInput?: boolean;\n}\n\n// Fallback xterm themes used when the consumer hasn't loaded `@hex-core/tokens`\n// or hasn't defined the standard `--background` / `--foreground` CSS vars\n// (e.g. consumer mounted Terminal in isolation). Match the `Terminal`\n// wrapper's inline `themeBg` defaults below — both must agree or there's\n// a visible seam between the xterm canvas and the wrapper.\nconst DARK_FALLBACK = {\n\tbackground: \"#0a0a0a\",\n\tforeground: \"#e5e5e5\",\n\tcursor: \"#e5e5e5\",\n\tselectionBackground: \"#404040\",\n};\nconst LIGHT_FALLBACK = {\n\tbackground: \"#fafafa\",\n\tforeground: \"#171717\",\n\tcursor: \"#171717\",\n\tselectionBackground: \"#d4d4d4\",\n};\n\n/**\n * Read a CSS HSL-triplet variable from `:root` (or the nearest theme\n * scope) and convert it to a 6-digit hex string suitable for xterm's\n * `theme: { background: \"#...\" }` option, which accepts hex/rgb but NOT\n * CSS variables. Returns `null` if the variable is unset, so the caller\n * can fall back to a hand-tuned theme without rendering pure-black.\n *\n * @param name - CSS variable name without the leading `--` (e.g. `\"background\"`).\n * @returns A `#xxxxxx` hex color string, or `null` if the var isn't defined.\n */\nfunction readCssVarAsHex(name: string): string | null {\n\tif (typeof document === \"undefined\") return null;\n\tconst triplet = getComputedStyle(document.documentElement)\n\t\t.getPropertyValue(`--${name}`)\n\t\t.trim();\n\tif (!triplet) return null;\n\treturn hslTripletToHex(triplet);\n}\n\n/**\n * Renders an xterm.js terminal display.\n * @param props - Terminal output + input handler + display options\n * @returns A div containing the xterm grid\n */\nfunction Terminal({\n\toutput,\n\tonInput,\n\tcols = 80,\n\trows = 24,\n\ttheme = \"dark\",\n\tcursorBlink = true,\n\tdisableInput = false,\n\tclassName,\n\t...rest\n}: TerminalProps) {\n\tconst containerRef = React.useRef<HTMLDivElement | null>(null);\n\tconst termRef = React.useRef<import(\"@xterm/xterm\").Terminal | null>(null);\n\tconst writtenRef = React.useRef<string>(\"\");\n\tconst onInputRef = React.useRef(onInput);\n\tonInputRef.current = onInput;\n\t// Latest-output mirror so the dynamic-import callback can read the value\n\t// at the moment the engine actually mounts (not the value at first render\n\t// — those can differ when the parent's `output` prop is set lazily).\n\tconst outputRef = React.useRef(output);\n\toutputRef.current = output;\n\n\t// Initialize xterm once on mount. Dynamic import keeps the engine out\n\t// of consumers' bundles unless they actually mount the component.\n\tReact.useEffect(() => {\n\t\tif (!containerRef.current) return;\n\n\t\tlet disposed = false;\n\t\tlet inputDispose: { dispose: () => void } | null = null;\n\n\t\tvoid (async () => {\n\t\t\tconst xtermModule = await import(\"@xterm/xterm\");\n\t\t\tif (disposed || !containerRef.current) return;\n\n\t\t\t// xterm needs hex colors (it can't accept CSS vars), so read\n\t\t\t// the consumer's `--background` / `--foreground` triplets at\n\t\t\t// mount time and convert. A consumer who themes those tokens\n\t\t\t// gets a terminal that follows the page; a consumer mounting\n\t\t\t// Terminal in isolation falls back to the hand-tuned defaults.\n\t\t\tconst fallback = theme === \"dark\" ? DARK_FALLBACK : LIGHT_FALLBACK;\n\t\t\tconst bgHex = readCssVarAsHex(\"background\") ?? fallback.background;\n\t\t\tconst fgHex = readCssVarAsHex(\"foreground\") ?? fallback.foreground;\n\n\t\t\tconst term = new xtermModule.Terminal({\n\t\t\t\tcols,\n\t\t\t\trows,\n\t\t\t\tcursorBlink,\n\t\t\t\tdisableStdin: disableInput,\n\t\t\t\ttheme: {\n\t\t\t\t\tbackground: bgHex,\n\t\t\t\t\tforeground: fgHex,\n\t\t\t\t\tcursor: fgHex,\n\t\t\t\t\tselectionBackground: fallback.selectionBackground,\n\t\t\t\t},\n\t\t\t\tfontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n\t\t\t\tfontSize: 13,\n\t\t\t});\n\t\t\tterm.open(containerRef.current);\n\t\t\ttermRef.current = term;\n\n\t\t\t// Read the LATEST output via the ref — between mount and\n\t\t\t// import-resolve, the parent may have updated the prop. Without\n\t\t\t// this, fast prop changes get clobbered.\n\t\t\tconst latest = normalizeOutput(outputRef.current);\n\t\t\tif (latest) {\n\t\t\t\tterm.write(latest);\n\t\t\t\twrittenRef.current = latest;\n\t\t\t}\n\n\t\t\tinputDispose = term.onData((data) => {\n\t\t\t\tonInputRef.current?.(data);\n\t\t\t});\n\t\t})();\n\n\t\treturn () => {\n\t\t\tdisposed = true;\n\t\t\tinputDispose?.dispose();\n\t\t\ttermRef.current?.dispose();\n\t\t\ttermRef.current = null;\n\t\t\twrittenRef.current = \"\";\n\t\t};\n\t\t// cols/rows/theme/cursorBlink/disableInput are mount-time options.\n\t\t// Changing them mid-session would force a full re-init that'd lose\n\t\t// scrollback — out of scope for v1.\n\t}, []);\n\n\t// Diff `output` against what's already on screen and write only the new tail.\n\tReact.useEffect(() => {\n\t\tconst term = termRef.current;\n\t\tif (!term) return;\n\t\tconst next = normalizeOutput(output);\n\t\tif (next === writtenRef.current) return;\n\t\tif (next.startsWith(writtenRef.current)) {\n\t\t\tconst delta = next.slice(writtenRef.current.length);\n\t\t\tif (delta) term.write(delta);\n\t\t} else {\n\t\t\t// Non-suffix change (e.g. consumer cleared the buffer or replaced it\n\t\t\t// with unrelated content) — reset the screen and write fresh.\n\t\t\tterm.reset();\n\t\t\tif (next) term.write(next);\n\t\t}\n\t\twrittenRef.current = next;\n\t}, [output]);\n\n\t// Inline background matches the xterm theme bg. xterm renders its grid\n\t// into a canvas (or DOM rows without their own background-color), so\n\t// a11y tools walk up the DOM looking for a background and would\n\t// otherwise hit the docs-page bg, producing a contrast false positive\n\t// against the xterm fg. The CSS var fallback is an HSL triplet — `hsl()`\n\t// rejects hex literals as a fallback, so the triplet is what makes this\n\t// work when a consumer mounts Terminal without loading `@hex-core/tokens`.\n\tconst fallbackTriplet = theme === \"dark\" ? \"0 0% 4%\" : \"0 0% 98%\";\n\tconst themeBg = `hsl(var(--background, ${fallbackTriplet}))`;\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tref={containerRef}\n\t\t\tdata-hex-terminal\n\t\t\tdata-theme={theme}\n\t\t\tstyle={{ backgroundColor: themeBg, ...(rest.style ?? {}) }}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-hidden rounded-md border p-2\",\n\t\t\t\t\"font-mono text-sm leading-tight\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t/>\n\t);\n}\n\nfunction normalizeOutput(value: string | string[] | undefined): string {\n\tif (value == null) return \"\";\n\treturn Array.isArray(value) ? value.join(\"\") : value;\n}\n\nexport { Terminal };\n"]}
|
package/dist/textarea.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/utils.ts","../src/primitives/textarea/textarea.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACDA,IAAM,QAAA,GAAiB,KAAA,CAAA,UAAA;AAAA,EACtB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AACjC,IAAA,uBACC,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACV,sIAAA;AAAA,UACA,iEAAA;AAAA,UACA,qDAAA;AAAA,UACA,mCAAA;AAAA,UACA,qGAAA;AAAA,UACA,sDAAA;AAAA,UACA,sCAAA;AAAA,UACA,iDAAA;AAAA,UACA;AAAA,SACD;AAAA,QACA,GAAA;AAAA,QACC,GAAG;AAAA;AAAA,KACL;AAAA,EAEF;AACD;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"textarea.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * A styled multi-line text input with smooth focus transitions and shadow effects.\n * Extends the native HTML textarea element with Hex
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts","../src/primitives/textarea/textarea.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACDA,IAAM,QAAA,GAAiB,KAAA,CAAA,UAAA;AAAA,EACtB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AACjC,IAAA,uBACC,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACV,sIAAA;AAAA,UACA,iEAAA;AAAA,UACA,qDAAA;AAAA,UACA,mCAAA;AAAA,UACA,qGAAA;AAAA,UACA,sDAAA;AAAA,UACA,sCAAA;AAAA,UACA,iDAAA;AAAA,UACA;AAAA,SACD;AAAA,QACA,GAAA;AAAA,QACC,GAAG;AAAA;AAAA,KACL;AAAA,EAEF;AACD;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"textarea.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * A styled multi-line text input with smooth focus transitions and shadow effects.\n * Extends the native HTML textarea element with Hex Core styling.\n */\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<textarea\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex min-h-[80px] w-full rounded-md border border-input bg-background px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\t\t\"placeholder:text-muted-foreground\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\"focus-visible:shadow-md focus-visible:border-ring/50\",\n\t\t\t\t\t\"hover:border-ring/30 hover:shadow-md\",\n\t\t\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea };\n"]}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return twMerge(clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
function TimeAxis({
|
|
11
|
+
events,
|
|
12
|
+
start,
|
|
13
|
+
end,
|
|
14
|
+
width = 720,
|
|
15
|
+
height = 200,
|
|
16
|
+
tickCount = 6,
|
|
17
|
+
onEventClick,
|
|
18
|
+
className,
|
|
19
|
+
...rest
|
|
20
|
+
}) {
|
|
21
|
+
const laidOut = React.useMemo(
|
|
22
|
+
() => layout(events, start, end, width, height, tickCount),
|
|
23
|
+
[events, start, end, width, height, tickCount]
|
|
24
|
+
);
|
|
25
|
+
const desc = events.length === 0 ? "Empty time axis" : `Time axis with ${events.length} event${events.length === 1 ? "" : "s"}, range ${laidOut.startLabel} to ${laidOut.endLabel}`;
|
|
26
|
+
return /* @__PURE__ */ jsxs(
|
|
27
|
+
"svg",
|
|
28
|
+
{
|
|
29
|
+
...rest,
|
|
30
|
+
"data-hex-time-axis": true,
|
|
31
|
+
role: "img",
|
|
32
|
+
width,
|
|
33
|
+
height,
|
|
34
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
35
|
+
className: cn("block", className),
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ jsx("title", { children: "Time axis" }),
|
|
38
|
+
/* @__PURE__ */ jsx("desc", { children: desc }),
|
|
39
|
+
/* @__PURE__ */ jsxs("g", { "data-hex-time-axis-axis": true, children: [
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
"line",
|
|
42
|
+
{
|
|
43
|
+
x1: laidOut.axisLeft,
|
|
44
|
+
x2: laidOut.axisRight,
|
|
45
|
+
y1: laidOut.axisY,
|
|
46
|
+
y2: laidOut.axisY,
|
|
47
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
48
|
+
strokeWidth: 1
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
laidOut.ticks.map((tick, i) => /* @__PURE__ */ jsxs("g", { "data-hex-time-axis-tick": true, children: [
|
|
52
|
+
/* @__PURE__ */ jsx(
|
|
53
|
+
"line",
|
|
54
|
+
{
|
|
55
|
+
x1: tick.x,
|
|
56
|
+
x2: tick.x,
|
|
57
|
+
y1: laidOut.axisY - 4,
|
|
58
|
+
y2: laidOut.axisY + 4,
|
|
59
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
60
|
+
strokeWidth: 1
|
|
61
|
+
}
|
|
62
|
+
),
|
|
63
|
+
/* @__PURE__ */ jsx(
|
|
64
|
+
"text",
|
|
65
|
+
{
|
|
66
|
+
x: tick.x,
|
|
67
|
+
y: laidOut.axisY + 18,
|
|
68
|
+
textAnchor: "middle",
|
|
69
|
+
fontSize: 10,
|
|
70
|
+
fill: "hsl(var(--muted-foreground))",
|
|
71
|
+
children: tick.label
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
] }, `tick-${i}`))
|
|
75
|
+
] }),
|
|
76
|
+
/* @__PURE__ */ jsx("g", { "data-hex-time-axis-events": true, children: laidOut.events.map((e) => {
|
|
77
|
+
const interactive = Boolean(onEventClick);
|
|
78
|
+
const handleActivate = () => onEventClick?.(e.event);
|
|
79
|
+
return /* @__PURE__ */ jsxs(
|
|
80
|
+
"g",
|
|
81
|
+
{
|
|
82
|
+
"data-hex-time-axis-event": true,
|
|
83
|
+
"data-row": e.rowIndex,
|
|
84
|
+
role: interactive ? "button" : void 0,
|
|
85
|
+
tabIndex: interactive ? 0 : void 0,
|
|
86
|
+
"aria-label": interactive ? `${e.event.label} on ${formatDate(toDate(e.event.date))}` : void 0,
|
|
87
|
+
style: interactive ? { cursor: "pointer" } : void 0,
|
|
88
|
+
onClick: interactive ? handleActivate : void 0,
|
|
89
|
+
onKeyDown: interactive ? (k) => activateOnKey(k, handleActivate) : void 0,
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ jsx(
|
|
92
|
+
"line",
|
|
93
|
+
{
|
|
94
|
+
x1: e.x,
|
|
95
|
+
x2: e.x,
|
|
96
|
+
y1: e.y,
|
|
97
|
+
y2: laidOut.axisY,
|
|
98
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
99
|
+
strokeOpacity: 0.65,
|
|
100
|
+
strokeWidth: 1
|
|
101
|
+
}
|
|
102
|
+
),
|
|
103
|
+
/* @__PURE__ */ jsx(
|
|
104
|
+
"circle",
|
|
105
|
+
{
|
|
106
|
+
cx: e.x,
|
|
107
|
+
cy: e.y,
|
|
108
|
+
r: 5,
|
|
109
|
+
fill: "hsl(var(--primary))",
|
|
110
|
+
stroke: "hsl(var(--background))",
|
|
111
|
+
strokeWidth: 2
|
|
112
|
+
}
|
|
113
|
+
),
|
|
114
|
+
/* @__PURE__ */ jsx(
|
|
115
|
+
"text",
|
|
116
|
+
{
|
|
117
|
+
x: e.x + 8,
|
|
118
|
+
y: e.y + 4,
|
|
119
|
+
fontSize: 11,
|
|
120
|
+
fill: "hsl(var(--foreground))",
|
|
121
|
+
style: { paintOrder: "stroke", pointerEvents: "none" },
|
|
122
|
+
stroke: "hsl(var(--background))",
|
|
123
|
+
strokeWidth: 3,
|
|
124
|
+
strokeLinejoin: "round",
|
|
125
|
+
children: e.event.label
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
e.event.id
|
|
131
|
+
);
|
|
132
|
+
}) })
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
function layout(events, start, end, width, height, tickCount) {
|
|
138
|
+
const margin = 32;
|
|
139
|
+
const axisLeft = margin;
|
|
140
|
+
const axisRight = width - margin;
|
|
141
|
+
const axisY = height - 40;
|
|
142
|
+
const usableWidth = axisRight - axisLeft;
|
|
143
|
+
const validEvents = events.filter((e) => Number.isFinite(toDate(e.date).getTime()));
|
|
144
|
+
if (validEvents.length === 0) {
|
|
145
|
+
return {
|
|
146
|
+
events: [],
|
|
147
|
+
ticks: [],
|
|
148
|
+
axisY,
|
|
149
|
+
axisLeft,
|
|
150
|
+
axisRight,
|
|
151
|
+
startLabel: "\u2014",
|
|
152
|
+
endLabel: "\u2014"
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const dates = validEvents.map((e) => toDate(e.date).getTime());
|
|
156
|
+
const explicitMin = start != null ? toDate(start).getTime() : NaN;
|
|
157
|
+
const explicitMax = end != null ? toDate(end).getTime() : NaN;
|
|
158
|
+
const minTs = Number.isFinite(explicitMin) ? explicitMin : Math.min(...dates);
|
|
159
|
+
const maxTs = Number.isFinite(explicitMax) ? explicitMax : Math.max(...dates);
|
|
160
|
+
const span = Math.max(1, maxTs - minTs);
|
|
161
|
+
const tToX = (t) => axisLeft + (t - minTs) / span * usableWidth;
|
|
162
|
+
const MIN_GAP_PX = 48;
|
|
163
|
+
const ROW_HEIGHT_PX = 22;
|
|
164
|
+
const maxRows = Math.max(1, Math.floor((axisY - 10 - 24) / ROW_HEIGHT_PX) + 1);
|
|
165
|
+
const rowsLastX = [];
|
|
166
|
+
const positioned = validEvents.map((event) => ({ event, t: toDate(event.date).getTime() })).sort((a, b) => a.t - b.t || a.event.id.localeCompare(b.event.id)).map(({ event, t }) => {
|
|
167
|
+
const x = tToX(t);
|
|
168
|
+
let rowIndex = rowsLastX.findIndex((lastX) => x - lastX >= MIN_GAP_PX);
|
|
169
|
+
if (rowIndex === -1) {
|
|
170
|
+
if (rowsLastX.length < maxRows) {
|
|
171
|
+
rowIndex = rowsLastX.length;
|
|
172
|
+
rowsLastX.push(x);
|
|
173
|
+
} else {
|
|
174
|
+
rowIndex = maxRows - 1;
|
|
175
|
+
rowsLastX[rowIndex] = x;
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
rowsLastX[rowIndex] = x;
|
|
179
|
+
}
|
|
180
|
+
return { event, x, y: 24 + rowIndex * ROW_HEIGHT_PX, rowIndex };
|
|
181
|
+
});
|
|
182
|
+
const rawTicks = [];
|
|
183
|
+
for (let i = 0; i < tickCount; i++) {
|
|
184
|
+
const t = minTs + i / Math.max(1, tickCount - 1) * span;
|
|
185
|
+
rawTicks.push({ x: tToX(t), label: formatTick(new Date(t), span) });
|
|
186
|
+
}
|
|
187
|
+
const ticks = rawTicks.map((t, i) => ({
|
|
188
|
+
x: t.x,
|
|
189
|
+
label: i > 0 && rawTicks[i - 1]?.label === t.label ? "" : t.label
|
|
190
|
+
}));
|
|
191
|
+
return {
|
|
192
|
+
events: positioned,
|
|
193
|
+
ticks,
|
|
194
|
+
axisY,
|
|
195
|
+
axisLeft,
|
|
196
|
+
axisRight,
|
|
197
|
+
startLabel: formatDate(new Date(minTs)),
|
|
198
|
+
endLabel: formatDate(new Date(maxTs))
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function toDate(v) {
|
|
202
|
+
if (v instanceof Date) return v;
|
|
203
|
+
if (typeof v === "number") return new Date(v);
|
|
204
|
+
return new Date(v);
|
|
205
|
+
}
|
|
206
|
+
function formatDate(d) {
|
|
207
|
+
if (Number.isNaN(d.getTime())) return "\u2014";
|
|
208
|
+
return d.toISOString().slice(0, 10);
|
|
209
|
+
}
|
|
210
|
+
function formatTick(d, spanMs) {
|
|
211
|
+
if (Number.isNaN(d.getTime())) return "\u2014";
|
|
212
|
+
const ONE_DAY = 24 * 60 * 60 * 1e3;
|
|
213
|
+
if (spanMs <= 7 * ONE_DAY) {
|
|
214
|
+
return d.toISOString().slice(0, 10);
|
|
215
|
+
}
|
|
216
|
+
if (spanMs <= 90 * ONE_DAY) {
|
|
217
|
+
return d.toISOString().slice(5, 10);
|
|
218
|
+
}
|
|
219
|
+
if (spanMs <= 730 * ONE_DAY) {
|
|
220
|
+
return d.toISOString().slice(0, 7);
|
|
221
|
+
}
|
|
222
|
+
return String(d.getUTCFullYear());
|
|
223
|
+
}
|
|
224
|
+
function activateOnKey(e, fn) {
|
|
225
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
226
|
+
e.preventDefault();
|
|
227
|
+
fn();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export { TimeAxis };
|
|
232
|
+
//# sourceMappingURL=time-axis.js.map
|
|
233
|
+
//# sourceMappingURL=time-axis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/time-axis/time-axis.tsx"],"names":[],"mappings":"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","file":"time-axis.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Events plotted along a horizontal time axis. Pure SVG; no heavy peer\n * dependency. Distinct from the existing `<Timeline>` component in\n * `components/timeline` — that one is an event-list with vertical\n * status markers; this one is a CHART with a real time axis where\n * spacing reflects elapsed time.\n *\n * Use TimeAxis when the *gap between events* is the message (release\n * cadence, incident frequency, sparse-then-dense patterns). Use\n * Timeline when the order of events is the message but the absolute\n * dates are secondary.\n *\n * @example\n * <TimeAxis\n * events={[\n * { id: \"v1\", label: \"v1.0\", date: \"2025-01-15\" },\n * { id: \"v2\", label: \"v2.0\", date: \"2025-04-20\" },\n * { id: \"v3\", label: \"v3.0\", date: \"2025-09-10\" },\n * ]}\n * />\n */\nexport type TimeAxisEvent = {\n\tid: string;\n\tlabel: string;\n\t/** Accepts Date, ISO string, or epoch ms. */\n\tdate: Date | string | number;\n\t/** Optional category — events with the same `category` share a row band. */\n\tcategory?: string;\n};\n\n// `start` and `end` collide with SVG's `<animate start=...>` / `<set end=...>`\n// animation attributes (their value type is string|number, not Date). Omit\n// both from the inherited SVG attributes so consumers can pass Date values\n// freely without a type collision.\nexport interface TimeAxisProps\n\textends Omit<React.SVGAttributes<SVGSVGElement>, \"children\" | \"start\" | \"end\"> {\n\t/** Events to plot. Order doesn't matter — positions come from `date`. */\n\tevents: TimeAxisEvent[];\n\t/** Optional explicit axis start. Auto-derived from `events` if omitted. */\n\tstart?: Date | string | number;\n\t/** Optional explicit axis end. Auto-derived from `events` if omitted. */\n\tend?: Date | string | number;\n\t/** Pixel width of the rendered SVG. Default 720. */\n\twidth?: number;\n\t/** Pixel height of the rendered SVG. Default 200. */\n\theight?: number;\n\t/** Number of axis ticks to show. Default 6. */\n\ttickCount?: number;\n\t/** Fired when an event is clicked. */\n\tonEventClick?: (event: TimeAxisEvent) => void;\n}\n\ninterface LaidOutEvent {\n\tevent: TimeAxisEvent;\n\tx: number;\n\ty: number;\n\trowIndex: number;\n}\n\ninterface AxisTick {\n\tx: number;\n\tlabel: string;\n}\n\nfunction TimeAxis({\n\tevents,\n\tstart,\n\tend,\n\twidth = 720,\n\theight = 200,\n\ttickCount = 6,\n\tonEventClick,\n\tclassName,\n\t...rest\n}: TimeAxisProps) {\n\tconst laidOut = React.useMemo(\n\t\t() => layout(events, start, end, width, height, tickCount),\n\t\t[events, start, end, width, height, tickCount],\n\t);\n\n\tconst desc =\n\t\tevents.length === 0\n\t\t\t? \"Empty time axis\"\n\t\t\t: `Time axis with ${events.length} event${events.length === 1 ? \"\" : \"s\"}, range ${laidOut.startLabel} to ${laidOut.endLabel}`;\n\n\treturn (\n\t\t<svg\n\t\t\t{...rest}\n\t\t\tdata-hex-time-axis\n\t\t\trole=\"img\"\n\t\t\twidth={width}\n\t\t\theight={height}\n\t\t\tviewBox={`0 0 ${width} ${height}`}\n\t\t\tclassName={cn(\"block\", className)}\n\t\t>\n\t\t\t<title>Time axis</title>\n\t\t\t<desc>{desc}</desc>\n\t\t\t{/* Baseline + ticks */}\n\t\t\t<g data-hex-time-axis-axis>\n\t\t\t\t<line\n\t\t\t\t\tx1={laidOut.axisLeft}\n\t\t\t\t\tx2={laidOut.axisRight}\n\t\t\t\t\ty1={laidOut.axisY}\n\t\t\t\t\ty2={laidOut.axisY}\n\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t/>\n\t\t\t\t{laidOut.ticks.map((tick, i) => (\n\t\t\t\t\t<g key={`tick-${i}`} data-hex-time-axis-tick>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1={tick.x}\n\t\t\t\t\t\t\tx2={tick.x}\n\t\t\t\t\t\t\ty1={laidOut.axisY - 4}\n\t\t\t\t\t\t\ty2={laidOut.axisY + 4}\n\t\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx={tick.x}\n\t\t\t\t\t\t\ty={laidOut.axisY + 18}\n\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\tfontSize={10}\n\t\t\t\t\t\t\tfill=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{tick.label}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t</g>\n\t\t\t\t))}\n\t\t\t</g>\n\t\t\t<g data-hex-time-axis-events>\n\t\t\t\t{laidOut.events.map((e) => {\n\t\t\t\t\tconst interactive = Boolean(onEventClick);\n\t\t\t\t\tconst handleActivate = () => onEventClick?.(e.event);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={e.event.id}\n\t\t\t\t\t\t\tdata-hex-time-axis-event\n\t\t\t\t\t\t\tdata-row={e.rowIndex}\n\t\t\t\t\t\t\trole={interactive ? \"button\" : undefined}\n\t\t\t\t\t\t\ttabIndex={interactive ? 0 : undefined}\n\t\t\t\t\t\t\taria-label={interactive ? `${e.event.label} on ${formatDate(toDate(e.event.date))}` : undefined}\n\t\t\t\t\t\t\tstyle={interactive ? { cursor: \"pointer\" } : undefined}\n\t\t\t\t\t\t\tonClick={interactive ? handleActivate : undefined}\n\t\t\t\t\t\t\tonKeyDown={interactive ? (k) => activateOnKey(k, handleActivate) : undefined}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* Connector from event marker to baseline */}\n\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\tx1={e.x}\n\t\t\t\t\t\t\t\tx2={e.x}\n\t\t\t\t\t\t\t\ty1={e.y}\n\t\t\t\t\t\t\t\ty2={laidOut.axisY}\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t\t\tstrokeOpacity={0.65}\n\t\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\tcx={e.x}\n\t\t\t\t\t\t\t\tcy={e.y}\n\t\t\t\t\t\t\t\tr={5}\n\t\t\t\t\t\t\t\tfill=\"hsl(var(--primary))\"\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\tx={e.x + 8}\n\t\t\t\t\t\t\t\ty={e.y + 4}\n\t\t\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\t\t\tfill=\"hsl(var(--foreground))\"\n\t\t\t\t\t\t\t\tstyle={{ paintOrder: \"stroke\", pointerEvents: \"none\" }}\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\t\tstrokeWidth={3}\n\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{e.event.label}\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t</g>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</g>\n\t\t</svg>\n\t);\n}\n\nfunction layout(\n\tevents: TimeAxisEvent[],\n\tstart: Date | string | number | undefined,\n\tend: Date | string | number | undefined,\n\twidth: number,\n\theight: number,\n\ttickCount: number,\n): {\n\tevents: LaidOutEvent[];\n\tticks: AxisTick[];\n\taxisY: number;\n\taxisLeft: number;\n\taxisRight: number;\n\tstartLabel: string;\n\tendLabel: string;\n} {\n\tconst margin = 32;\n\tconst axisLeft = margin;\n\tconst axisRight = width - margin;\n\tconst axisY = height - 40;\n\tconst usableWidth = axisRight - axisLeft;\n\n\t// Drop events whose date doesn't parse — `new Date(\"garbage\")` returns\n\t// NaN, which would propagate through `Math.min/max` and produce NaN\n\t// x-coordinates that crash some SVG renderers and noise up dev\n\t// consoles. Skip silently; downstream components can still inspect\n\t// the unrendered ids if they want to surface validation errors.\n\tconst validEvents = events.filter((e) => Number.isFinite(toDate(e.date).getTime()));\n\n\tif (validEvents.length === 0) {\n\t\treturn {\n\t\t\tevents: [],\n\t\t\tticks: [],\n\t\t\taxisY,\n\t\t\taxisLeft,\n\t\t\taxisRight,\n\t\t\tstartLabel: \"—\",\n\t\t\tendLabel: \"—\",\n\t\t};\n\t}\n\n\tconst dates = validEvents.map((e) => toDate(e.date).getTime());\n\tconst explicitMin = start != null ? toDate(start).getTime() : NaN;\n\tconst explicitMax = end != null ? toDate(end).getTime() : NaN;\n\tconst minTs = Number.isFinite(explicitMin) ? explicitMin : Math.min(...dates);\n\tconst maxTs = Number.isFinite(explicitMax) ? explicitMax : Math.max(...dates);\n\tconst span = Math.max(1, maxTs - minTs);\n\n\tconst tToX = (t: number) => axisLeft + ((t - minTs) / span) * usableWidth;\n\n\t// Distribute events across stacked rows so labels don't overlap when\n\t// events cluster. A new event takes the topmost row whose previously-\n\t// placed event is at least MIN_GAP px to the left.\n\t//\n\t// Tiebreaker on id: Array.prototype.sort isn't stable across all\n\t// engines for events with identical timestamps. Sorting by id second\n\t// produces deterministic rows on every engine, so visual diffing\n\t// across builds stays meaningful.\n\tconst MIN_GAP_PX = 48;\n\tconst ROW_HEIGHT_PX = 22;\n\t// Cap rows so events never spill below the baseline. The first row\n\t// sits at y=24; remaining rows go in 22-px steps; clamp at axisY-10.\n\tconst maxRows = Math.max(1, Math.floor((axisY - 10 - 24) / ROW_HEIGHT_PX) + 1);\n\tconst rowsLastX: number[] = [];\n\tconst positioned = validEvents\n\t\t.map((event) => ({ event, t: toDate(event.date).getTime() }))\n\t\t.sort((a, b) => (a.t - b.t) || a.event.id.localeCompare(b.event.id))\n\t\t.map(({ event, t }) => {\n\t\t\tconst x = tToX(t);\n\t\t\tlet rowIndex = rowsLastX.findIndex((lastX) => x - lastX >= MIN_GAP_PX);\n\t\t\tif (rowIndex === -1) {\n\t\t\t\tif (rowsLastX.length < maxRows) {\n\t\t\t\t\trowIndex = rowsLastX.length;\n\t\t\t\t\trowsLastX.push(x);\n\t\t\t\t} else {\n\t\t\t\t\t// Degraded fallback — recycle the last row instead of\n\t\t\t\t\t// pushing the event below the baseline.\n\t\t\t\t\trowIndex = maxRows - 1;\n\t\t\t\t\trowsLastX[rowIndex] = x;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trowsLastX[rowIndex] = x;\n\t\t\t}\n\t\t\treturn { event, x, y: 24 + rowIndex * ROW_HEIGHT_PX, rowIndex };\n\t\t});\n\n\t// Generate ticks then dedupe consecutive identical labels — at year-scale\n\t// or month-scale spans the formatter often emits the same string twice\n\t// (e.g. five ticks all in 2025 render as \"2025\" / \"2025\" / ...). Blanking\n\t// the duplicate keeps the gridline tick but drops the noisy repeat.\n\tconst rawTicks: AxisTick[] = [];\n\tfor (let i = 0; i < tickCount; i++) {\n\t\tconst t = minTs + (i / Math.max(1, tickCount - 1)) * span;\n\t\trawTicks.push({ x: tToX(t), label: formatTick(new Date(t), span) });\n\t}\n\tconst ticks: AxisTick[] = rawTicks.map((t, i) => ({\n\t\tx: t.x,\n\t\tlabel: i > 0 && rawTicks[i - 1]?.label === t.label ? \"\" : t.label,\n\t}));\n\n\treturn {\n\t\tevents: positioned,\n\t\tticks,\n\t\taxisY,\n\t\taxisLeft,\n\t\taxisRight,\n\t\tstartLabel: formatDate(new Date(minTs)),\n\t\tendLabel: formatDate(new Date(maxTs)),\n\t};\n}\n\nfunction toDate(v: Date | string | number): Date {\n\tif (v instanceof Date) return v;\n\tif (typeof v === \"number\") return new Date(v);\n\treturn new Date(v);\n}\n\nfunction formatDate(d: Date): string {\n\tif (Number.isNaN(d.getTime())) return \"—\";\n\treturn d.toISOString().slice(0, 10);\n}\n\nfunction formatTick(d: Date, spanMs: number): string {\n\tif (Number.isNaN(d.getTime())) return \"—\";\n\tconst ONE_DAY = 24 * 60 * 60 * 1000;\n\tif (spanMs <= 7 * ONE_DAY) {\n\t\t// short range — show day\n\t\treturn d.toISOString().slice(0, 10);\n\t}\n\tif (spanMs <= 90 * ONE_DAY) {\n\t\t// up to ~3 months — show month-day so adjacent ticks stay distinct\n\t\treturn d.toISOString().slice(5, 10);\n\t}\n\tif (spanMs <= 730 * ONE_DAY) {\n\t\t// up to ~2 years — show year-month\n\t\treturn d.toISOString().slice(0, 7);\n\t}\n\t// long range — year only\n\treturn String(d.getUTCFullYear());\n}\n\nfunction activateOnKey(e: React.KeyboardEvent, fn: () => void): void {\n\tif (e.key === \"Enter\" || e.key === \" \") {\n\t\te.preventDefault();\n\t\tfn();\n\t}\n}\n\nexport { TimeAxis };\n"]}
|
package/dist/tool-call.js
CHANGED
|
@@ -15,7 +15,12 @@ var STATE_LABEL = {
|
|
|
15
15
|
};
|
|
16
16
|
var STATE_CLASSES = {
|
|
17
17
|
pending: "bg-muted text-muted-foreground",
|
|
18
|
-
|
|
18
|
+
// Solid primary bg + primary-foreground text in dark mode — the
|
|
19
|
+
// previously tinted `bg-primary/15` made the badge fg/bg too close in
|
|
20
|
+
// hue at 10px to clear WCAG AA (was 4.41:1, fails the 4.5 floor).
|
|
21
|
+
// Light mode keeps the soft tint where contrast holds; dark mode uses
|
|
22
|
+
// the solid surface for guaranteed ≥7:1 contrast.
|
|
23
|
+
running: "bg-primary/15 text-primary dark:bg-primary dark:text-primary-foreground animate-pulse",
|
|
19
24
|
result: "bg-accent/30 text-accent-foreground",
|
|
20
25
|
error: "bg-destructive/15 text-destructive"
|
|
21
26
|
};
|
package/dist/tool-call.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/utils.ts","../src/ai/tool-call/tool-call.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACHA,IAAM,WAAA,GAA6C;AAAA,EAClD,OAAA,EAAS,SAAA;AAAA,EACT,OAAA,EAAS,SAAA;AAAA,EACT,MAAA,EAAQ,MAAA;AAAA,EACR,KAAA,EAAO;AACR,CAAA;AAEA,IAAM,aAAA,GAA+C;AAAA,EACpD,OAAA,EAAS,gCAAA;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts","../src/ai/tool-call/tool-call.tsx"],"names":[],"mappings":"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","file":"tool-call.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport type { ToolCallState } from \"../types.js\";\n\nconst STATE_LABEL: Record<ToolCallState, string> = {\n\tpending: \"Pending\",\n\trunning: \"Running\",\n\tresult: \"Done\",\n\terror: \"Error\",\n};\n\nconst STATE_CLASSES: Record<ToolCallState, string> = {\n\tpending: \"bg-muted text-muted-foreground\",\n\t// Solid primary bg + primary-foreground text in dark mode — the\n\t// previously tinted `bg-primary/15` made the badge fg/bg too close in\n\t// hue at 10px to clear WCAG AA (was 4.41:1, fails the 4.5 floor).\n\t// Light mode keeps the soft tint where contrast holds; dark mode uses\n\t// the solid surface for guaranteed ≥7:1 contrast.\n\trunning: \"bg-primary/15 text-primary dark:bg-primary dark:text-primary-foreground animate-pulse\",\n\tresult: \"bg-accent/30 text-accent-foreground\",\n\terror: \"bg-destructive/15 text-destructive\",\n};\n\n/**\n * Collapsible card displaying a tool / function invocation. Header shows the\n * tool name and lifecycle state badge; body reveals the JSON-stringified\n * arguments and result on expand.\n *\n * Display-only — the component does not run the tool. Wire it up in the\n * consumer (AI SDK `tool-*` parts → ToolCall props, LangChain\n * `AIMessage.tool_calls` → ToolCall props).\n *\n * @example\n * <ToolCall\n * name=\"searchDocs\"\n * state=\"result\"\n * args={{ query: \"auth\" }}\n * result={{ hits: 12 }}\n * />\n */\nexport interface ToolCallProps {\n\tname: string;\n\tstate: ToolCallState;\n\targs?: unknown;\n\tresult?: unknown;\n\tdefaultOpen?: boolean;\n\tclassName?: string;\n}\n\n/**\n * Renders a tool-invocation card with collapsible details.\n * @param props - tool name, state, optional args/result\n * @returns A Collapsible wrapping a header + JSON body\n */\nfunction ToolCall({\n\tname,\n\tstate,\n\targs,\n\tresult,\n\tdefaultOpen = false,\n\tclassName,\n}: ToolCallProps) {\n\treturn (\n\t\t<CollapsiblePrimitive.Root\n\t\t\tdefaultOpen={defaultOpen}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-hidden rounded-md border bg-card text-card-foreground\",\n\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\"data-[state=open]:shadow-sm\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<CollapsiblePrimitive.Trigger\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"group flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm\",\n\t\t\t\t\t\"hover:bg-muted/40\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<span className=\"flex min-w-0 items-center gap-2\">\n\t\t\t\t\t<ToolGlyph />\n\t\t\t\t\t<span className=\"truncate font-mono text-xs text-foreground\">{name}</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium\",\n\t\t\t\t\t\t\tSTATE_CLASSES[state],\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{STATE_LABEL[state]}\n\t\t\t\t\t</span>\n\t\t\t\t</span>\n\t\t\t\t<Chevron />\n\t\t\t</CollapsiblePrimitive.Trigger>\n\t\t\t<CollapsiblePrimitive.Content className=\"overflow-hidden border-t bg-muted/20 px-3 py-2 text-xs\">\n\t\t\t\t{args !== undefined ? <CodeSection label=\"Arguments\" value={args} /> : null}\n\t\t\t\t{result !== undefined ? <CodeSection label=\"Result\" value={result} /> : null}\n\t\t\t\t{args === undefined && result === undefined ? (\n\t\t\t\t\t<p className=\"text-muted-foreground\">No arguments or result yet.</p>\n\t\t\t\t) : null}\n\t\t\t</CollapsiblePrimitive.Content>\n\t\t</CollapsiblePrimitive.Root>\n\t);\n}\n\nfunction CodeSection({ label, value }: { label: string; value: unknown }) {\n\tconst text = typeof value === \"string\" ? value : safeStringify(value);\n\treturn (\n\t\t<div className=\"space-y-1 py-1\">\n\t\t\t<div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">{label}</div>\n\t\t\t<pre className=\"overflow-x-auto rounded bg-background/60 p-2 font-mono text-[11px] leading-snug\">\n\t\t\t\t{text}\n\t\t\t</pre>\n\t\t</div>\n\t);\n}\n\nfunction safeStringify(value: unknown): string {\n\ttry {\n\t\treturn JSON.stringify(value, null, 2);\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n\nfunction ToolGlyph() {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"14\"\n\t\t\theight=\"14\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"shrink-0 text-muted-foreground\"\n\t\t>\n\t\t\t<path d=\"M11.5 1.5l3 3-2.5 2.5-3-3 2.5-2.5z\" />\n\t\t\t<path d=\"M9 4l-7 7v3h3l7-7\" />\n\t\t</svg>\n\t);\n}\n\nfunction Chevron() {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"14\"\n\t\t\theight=\"14\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"shrink-0 text-muted-foreground transition-transform duration-200 group-data-[state=open]:rotate-180\"\n\t\t>\n\t\t\t<path d=\"M4 6l4 4 4-4\" />\n\t\t</svg>\n\t);\n}\n\nexport { ToolCall };\n"]}
|