@lilydesignsystem/svelte-headless 0.3.0 → 0.5.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/components/CandlestickChart/CandlestickChart.svelte +63 -0
  3. package/dist/components/CandlestickChart/CandlestickChart.svelte.d.ts +13 -0
  4. package/dist/components/ChatComposer/ChatComposer.svelte +110 -0
  5. package/dist/components/ChatComposer/ChatComposer.svelte.d.ts +25 -0
  6. package/dist/components/ChoroplethChart/ChoroplethChart.svelte +63 -0
  7. package/dist/components/ChoroplethChart/ChoroplethChart.svelte.d.ts +13 -0
  8. package/dist/components/ComposedChart/ComposedChart.svelte +63 -0
  9. package/dist/components/ComposedChart/ComposedChart.svelte.d.ts +13 -0
  10. package/dist/components/ContentsLink/ContentsLink.svelte +36 -2
  11. package/dist/components/ContentsLink/ContentsLink.svelte.d.ts +3 -0
  12. package/dist/components/ContentsNav/ContentsNav.svelte +193 -1
  13. package/dist/components/ContentsNav/ContentsNav.svelte.d.ts +18 -1
  14. package/dist/components/DataTableTD/DataTableTD.svelte +5 -7
  15. package/dist/components/DataTableTD/DataTableTD.svelte.d.ts +1 -1
  16. package/dist/components/FiveFaceRatingPicker/FiveFaceRatingPicker.svelte +32 -2
  17. package/dist/components/FiveFaceRatingView/FiveFaceRatingView.svelte +3 -2
  18. package/dist/components/FiveStarRatingPicker/FiveStarRatingPicker.svelte +34 -2
  19. package/dist/components/FiveStarRatingPicker/FiveStarRatingPicker.svelte.d.ts +2 -0
  20. package/dist/components/FunnelChart/FunnelChart.svelte +63 -0
  21. package/dist/components/FunnelChart/FunnelChart.svelte.d.ts +13 -0
  22. package/dist/components/GanttTableTD/GanttTableTD.svelte +3 -4
  23. package/dist/components/KanbanTableTD/KanbanTableTD.svelte +3 -4
  24. package/dist/components/KanbanTableTD/KanbanTableTD.svelte.d.ts +1 -1
  25. package/dist/components/Mark/Mark.svelte +27 -0
  26. package/dist/components/Mark/Mark.svelte.d.ts +9 -0
  27. package/dist/components/NetPromoterScorePicker/NetPromoterScorePicker.svelte +29 -0
  28. package/dist/components/PieChart/PieChart.svelte +63 -0
  29. package/dist/components/PieChart/PieChart.svelte.d.ts +13 -0
  30. package/dist/components/PinInputDiv/PinInputDiv.svelte +42 -2
  31. package/dist/components/PinInputDiv/PinInputDiv.svelte.d.ts +5 -0
  32. package/dist/components/RingChart/RingChart.svelte +63 -0
  33. package/dist/components/RingChart/RingChart.svelte.d.ts +13 -0
  34. package/dist/components/StreamingText/StreamingText.svelte +48 -0
  35. package/dist/components/StreamingText/StreamingText.svelte.d.ts +13 -0
  36. package/dist/components/SunburstChart/SunburstChart.svelte +63 -0
  37. package/dist/components/SunburstChart/SunburstChart.svelte.d.ts +13 -0
  38. package/dist/components/Tag/Tag.svelte +20 -8
  39. package/dist/components/Tag/Tag.svelte.d.ts +6 -0
  40. package/dist/components/ToolCall/ToolCall.svelte +54 -0
  41. package/dist/components/ToolCall/ToolCall.svelte.d.ts +15 -0
  42. package/dist/components/ToolCallError/ToolCallError.svelte +27 -0
  43. package/dist/components/ToolCallError/ToolCallError.svelte.d.ts +9 -0
  44. package/dist/components/ToolCallInput/ToolCallInput.svelte +30 -0
  45. package/dist/components/ToolCallInput/ToolCallInput.svelte.d.ts +11 -0
  46. package/dist/components/ToolCallName/ToolCallName.svelte +27 -0
  47. package/dist/components/ToolCallName/ToolCallName.svelte.d.ts +9 -0
  48. package/dist/components/ToolCallOutput/ToolCallOutput.svelte +30 -0
  49. package/dist/components/ToolCallOutput/ToolCallOutput.svelte.d.ts +11 -0
  50. package/dist/components/ToolCallStatus/ToolCallStatus.svelte +29 -0
  51. package/dist/components/ToolCallStatus/ToolCallStatus.svelte.d.ts +11 -0
  52. package/dist/index.d.ts +16 -0
  53. package/dist/index.js +16 -0
  54. package/index.md +1 -1
  55. package/package.json +3 -2
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { untrack } from "svelte";
2
3
  // NetPromoterScorePicker component
3
4
  //
4
5
  // A headless Net Promoter Score (NPS) rating input that renders a fieldset
@@ -69,10 +70,38 @@
69
70
  name?: string;
70
71
  [key: string]: unknown;
71
72
  } = $props();
73
+
74
+ // Form reset: the radios use a one-way `checked`, which a reset clears
75
+ // without telling this component, so `value` would keep a rating the form no
76
+ // longer submits. Restore the initial value instead — one tick later, after
77
+ // the browser has reset the DOM, and not when the reset was cancelled.
78
+ let root: HTMLFieldSetElement | undefined = $state();
79
+ const initialValue = untrack(() => value);
80
+ $effect(() => {
81
+ const form = root?.form ?? root?.closest("form");
82
+ if (!form) return;
83
+ let timer: ReturnType<typeof setTimeout> | undefined;
84
+ const onReset = (event: Event) => {
85
+ clearTimeout(timer);
86
+ timer = setTimeout(() => {
87
+ if (event.defaultPrevented || !root) return;
88
+ value = initialValue;
89
+ for (const input of root.querySelectorAll<HTMLInputElement>('input[type="radio"]')) {
90
+ input.checked = input.value === String(initialValue);
91
+ }
92
+ }, 0);
93
+ };
94
+ form.addEventListener("reset", onReset);
95
+ return () => {
96
+ clearTimeout(timer);
97
+ form.removeEventListener("reset", onReset);
98
+ };
99
+ });
72
100
  </script>
73
101
 
74
102
  <!-- NetPromoterScorePicker: a fieldset radiogroup with 11 radio buttons (0-10) -->
75
103
  <fieldset
104
+ bind:this={root}
76
105
  class={`net-promoter-score-picker ${className}`}
77
106
  role="radiogroup"
78
107
  aria-label={label}
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ // PieChart component
3
+ //
4
+ // A headless chart container for a circular chart divided into slices that show each part of a whole. The consumer supplies the inline
5
+ // svg as `children`; the component draws nothing. The graphic is a
6
+ // role="img" wrapper named by `label`. The optional `dataTable` snippet
7
+ // renders the accessible table alternative as a SIBLING of that image
8
+ // wrapper, never inside it: a role="img" element makes its descendants
9
+ // presentational, so a table placed inside would be invisible to
10
+ // assistive technology.
11
+ //
12
+ // Props:
13
+ // class — string, optional. Consumer class appended after the base class.
14
+ // label — string, optional. Accessible name of the chart image.
15
+ // children — Snippet. The consumer-supplied inline svg.
16
+ // dataTable — Snippet, optional. The accessible table alternative.
17
+ // ...restProps — spread onto the root <figure>.
18
+ //
19
+ // Markup:
20
+ // <figure class="pie-chart">
21
+ // <div class="pie-chart-graphic" role="img" aria-label>…svg…</div>
22
+ // <div class="pie-chart-data-table">…table…</div> (only when provided)
23
+ // </figure>
24
+ //
25
+ // Keyboard: none on the graphic; the data table follows native table behaviour.
26
+ //
27
+ // Claude rules:
28
+ // - Headless: no CSS, no inline styles; no drawing.
29
+ // - No hardcoded user-facing strings.
30
+
31
+ import type { Snippet } from "svelte";
32
+
33
+ let {
34
+ class: className = "",
35
+ label = undefined,
36
+ children,
37
+ dataTable,
38
+ ...restProps
39
+ }: {
40
+ /** Accessible name for the chart. */
41
+ label?: string;
42
+ /** The consumer-supplied inline svg. */
43
+ children: Snippet;
44
+ /** Optional accessible data table alternative. */
45
+ dataTable?: Snippet;
46
+ [key: string]: unknown;
47
+ } = $props();
48
+ </script>
49
+
50
+ <!-- PieChart.svelte -->
51
+ <figure
52
+ class={`pie-chart ${className}`}
53
+ {...restProps}
54
+ >
55
+ <div class="pie-chart-graphic" role="img" aria-label={label}>
56
+ {@render children?.()}
57
+ </div>
58
+ {#if dataTable}
59
+ <div class="pie-chart-data-table">
60
+ {@render dataTable()}
61
+ </div>
62
+ {/if}
63
+ </figure>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ /** Accessible name for the chart. */
4
+ label?: string;
5
+ /** The consumer-supplied inline svg. */
6
+ children: Snippet;
7
+ /** Optional accessible data table alternative. */
8
+ dataTable?: Snippet;
9
+ [key: string]: unknown;
10
+ };
11
+ declare const PieChart: import("svelte").Component<$$ComponentProps, {}, "">;
12
+ type PieChart = ReturnType<typeof PieChart>;
13
+ export default PieChart;
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { untrack } from "svelte";
2
3
  // PinInputDiv component
3
4
  //
4
5
  // A headless PIN input that renders a group of single-character numeric inputs
@@ -12,6 +13,7 @@
12
13
  // className — string, optional. CSS class name.
13
14
  // label — string, required. Accessible label for the group of inputs via aria-label.
14
15
  // length — number, default 4. Number of digit inputs to render.
16
+ // digitLabel — (position, length) => string, optional. Each input's accessible name; defaults to `label`.
15
17
  // value — string, default "". Bindable combined string of all entered digits.
16
18
  // disabled — boolean, default false. Whether all inputs are disabled.
17
19
  // ...restProps — additional HTML attributes spread onto the group <div>.
@@ -60,6 +62,7 @@
60
62
  class: className = "",
61
63
  label,
62
64
  length = 4,
65
+ digitLabel,
63
66
  value = $bindable(""),
64
67
  disabled = false,
65
68
  ...restProps
@@ -68,6 +71,11 @@
68
71
  label: string;
69
72
  /** Number of digit inputs to render */
70
73
  length?: number;
74
+ /**
75
+ * Each digit input's accessible name, e.g. (n, of) => `Digit ${n} of ${of}`.
76
+ * Without it each input is named by `label`: no English default.
77
+ */
78
+ digitLabel?: (position: number, length: number) => string;
71
79
  /** Combined string of all entered digits, bindable */
72
80
  value?: string;
73
81
  /** Whether all inputs are disabled */
@@ -79,7 +87,12 @@
79
87
  // Internal state: array of individual digit characters.
80
88
  // Note: the length prop is captured at initialization time for the initial
81
89
  // array size. This is intentional -- the pin length is expected to be static.
82
- let digits: string[] = $state(Array.from({ length }, () => ""));
90
+ // Seeded from the initial `value`: starting empty meant the effect below
91
+ // overwrote a bound starting value with "" on mount.
92
+ const initialDigits = untrack(() =>
93
+ Array.from({ length }, (_, i) => (/^[0-9]$/.test(value[i] ?? "") ? value[i] : "")),
94
+ );
95
+ let digits: string[] = $state([...initialDigits]);
83
96
 
84
97
  // References to each input element for focus management
85
98
  let inputRefs: HTMLInputElement[] = $state([]);
@@ -93,6 +106,32 @@
93
106
  });
94
107
 
95
108
  // Handle input events on individual digit fields
109
+ // Form reset: the digit inputs use a one-way `value`, which a reset clears
110
+ // without telling this component, so `value` would keep digits the fields no
111
+ // longer show. Restore the initial digits instead — one tick later, after the
112
+ // browser has reset the DOM, and not when the reset was cancelled.
113
+ let root: HTMLDivElement | undefined = $state();
114
+ $effect(() => {
115
+ const form = root?.closest("form");
116
+ if (!form) return;
117
+ let timer: ReturnType<typeof setTimeout> | undefined;
118
+ const onReset = (event: Event) => {
119
+ clearTimeout(timer);
120
+ timer = setTimeout(() => {
121
+ if (event.defaultPrevented) return;
122
+ digits = [...initialDigits];
123
+ inputRefs.forEach((input, i) => {
124
+ if (input) input.value = initialDigits[i];
125
+ });
126
+ }, 0);
127
+ };
128
+ form.addEventListener("reset", onReset);
129
+ return () => {
130
+ clearTimeout(timer);
131
+ form.removeEventListener("reset", onReset);
132
+ };
133
+ });
134
+
96
135
  function handleInput(index: number, event: Event): void {
97
136
  const target = event.target as HTMLInputElement;
98
137
  const inputValue = target.value;
@@ -137,6 +176,7 @@
137
176
 
138
177
  <!-- PinInputDiv.svelte -->
139
178
  <div
179
+ bind:this={root}
140
180
  class={`pin-input-div ${className}`}
141
181
  role="group"
142
182
  aria-label={label}
@@ -148,7 +188,7 @@
148
188
  type="text"
149
189
  inputmode="numeric"
150
190
  maxlength="1"
151
- aria-label={`Digit ${index + 1} of ${length}`}
191
+ aria-label={digitLabel ? digitLabel(index + 1, length) : label}
152
192
  value={digits[index]}
153
193
  {disabled}
154
194
  oninput={(e) => handleInput(index, e)}
@@ -3,6 +3,11 @@ type $$ComponentProps = {
3
3
  label: string;
4
4
  /** Number of digit inputs to render */
5
5
  length?: number;
6
+ /**
7
+ * Each digit input's accessible name, e.g. (n, of) => `Digit ${n} of ${of}`.
8
+ * Without it each input is named by `label`: no English default.
9
+ */
10
+ digitLabel?: (position: number, length: number) => string;
6
11
  /** Combined string of all entered digits, bindable */
7
12
  value?: string;
8
13
  /** Whether all inputs are disabled */
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ // RingChart component
3
+ //
4
+ // A headless chart container for a pie chart with a hollow centre, often used to show progress or a share of a total. The consumer supplies the inline
5
+ // svg as `children`; the component draws nothing. The graphic is a
6
+ // role="img" wrapper named by `label`. The optional `dataTable` snippet
7
+ // renders the accessible table alternative as a SIBLING of that image
8
+ // wrapper, never inside it: a role="img" element makes its descendants
9
+ // presentational, so a table placed inside would be invisible to
10
+ // assistive technology.
11
+ //
12
+ // Props:
13
+ // class — string, optional. Consumer class appended after the base class.
14
+ // label — string, optional. Accessible name of the chart image.
15
+ // children — Snippet. The consumer-supplied inline svg.
16
+ // dataTable — Snippet, optional. The accessible table alternative.
17
+ // ...restProps — spread onto the root <figure>.
18
+ //
19
+ // Markup:
20
+ // <figure class="ring-chart">
21
+ // <div class="ring-chart-graphic" role="img" aria-label>…svg…</div>
22
+ // <div class="ring-chart-data-table">…table…</div> (only when provided)
23
+ // </figure>
24
+ //
25
+ // Keyboard: none on the graphic; the data table follows native table behaviour.
26
+ //
27
+ // Claude rules:
28
+ // - Headless: no CSS, no inline styles; no drawing.
29
+ // - No hardcoded user-facing strings.
30
+
31
+ import type { Snippet } from "svelte";
32
+
33
+ let {
34
+ class: className = "",
35
+ label = undefined,
36
+ children,
37
+ dataTable,
38
+ ...restProps
39
+ }: {
40
+ /** Accessible name for the chart. */
41
+ label?: string;
42
+ /** The consumer-supplied inline svg. */
43
+ children: Snippet;
44
+ /** Optional accessible data table alternative. */
45
+ dataTable?: Snippet;
46
+ [key: string]: unknown;
47
+ } = $props();
48
+ </script>
49
+
50
+ <!-- RingChart.svelte -->
51
+ <figure
52
+ class={`ring-chart ${className}`}
53
+ {...restProps}
54
+ >
55
+ <div class="ring-chart-graphic" role="img" aria-label={label}>
56
+ {@render children?.()}
57
+ </div>
58
+ {#if dataTable}
59
+ <div class="ring-chart-data-table">
60
+ {@render dataTable()}
61
+ </div>
62
+ {/if}
63
+ </figure>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ /** Accessible name for the chart. */
4
+ label?: string;
5
+ /** The consumer-supplied inline svg. */
6
+ children: Snippet;
7
+ /** Optional accessible data table alternative. */
8
+ dataTable?: Snippet;
9
+ [key: string]: unknown;
10
+ };
11
+ declare const RingChart: import("svelte").Component<$$ComponentProps, {}, "">;
12
+ type RingChart = ReturnType<typeof RingChart>;
13
+ export default RingChart;
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ // StreamingText component
3
+ //
4
+ // A polite live region for text that grows over time. While `streaming` is true the region is marked busy (`aria-busy="true"`, `data-streaming="true"`) so assistive technology waits instead of announcing every chunk; when it flips to false the finished text is announced once (`role="status"`, `aria-live="polite"`, `aria-atomic="true"`). The component never splits, times, reveals or animates the text: the consumer appends chunks to the children, and owns any caret or reduced-motion CSS.
5
+ //
6
+ // Props:
7
+ // class — string, optional. CSS class name.
8
+ // label — string, optional. Accessible name of the status region.
9
+ // streaming — boolean, default false. True while chunks are still arriving.
10
+ // children — Snippet. The text so far.
11
+ // ...restProps — additional HTML attributes spread onto the root <div>.
12
+ //
13
+ // Keyboard: none.
14
+ //
15
+ // Claude rules:
16
+ // - Headless: no CSS, no animation, no timing, no hardcoded strings
17
+ import type { Snippet } from "svelte";
18
+
19
+ let {
20
+ class: className = "",
21
+ label = undefined,
22
+ streaming = false,
23
+ children,
24
+ ...restProps
25
+ }: {
26
+ /** Accessible name of the region. */
27
+ label?: string;
28
+ /** Whether text is still arriving. */
29
+ streaming?: boolean;
30
+ /** The text so far. */
31
+ children?: Snippet;
32
+ [key: string]: unknown;
33
+ } = $props();
34
+ </script>
35
+
36
+ <!-- StreamingText.svelte -->
37
+ <div
38
+ class={`streaming-text ${className}`}
39
+ role="status"
40
+ aria-live="polite"
41
+ aria-atomic="true"
42
+ aria-label={label}
43
+ aria-busy={streaming ? "true" : undefined}
44
+ data-streaming={streaming ? "true" : undefined}
45
+ {...restProps}
46
+ >
47
+ {@render children?.()}
48
+ </div>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ /** Accessible name of the region. */
4
+ label?: string;
5
+ /** Whether text is still arriving. */
6
+ streaming?: boolean;
7
+ /** The text so far. */
8
+ children?: Snippet;
9
+ [key: string]: unknown;
10
+ };
11
+ declare const StreamingText: import("svelte").Component<$$ComponentProps, {}, "">;
12
+ type StreamingText = ReturnType<typeof StreamingText>;
13
+ export default StreamingText;
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ // SunburstChart component
3
+ //
4
+ // A headless chart container for a radial chart showing a hierarchy as concentric rings of arcs. The consumer supplies the inline
5
+ // svg as `children`; the component draws nothing. The graphic is a
6
+ // role="img" wrapper named by `label`. The optional `dataTable` snippet
7
+ // renders the accessible table alternative as a SIBLING of that image
8
+ // wrapper, never inside it: a role="img" element makes its descendants
9
+ // presentational, so a table placed inside would be invisible to
10
+ // assistive technology.
11
+ //
12
+ // Props:
13
+ // class — string, optional. Consumer class appended after the base class.
14
+ // label — string, optional. Accessible name of the chart image.
15
+ // children — Snippet. The consumer-supplied inline svg.
16
+ // dataTable — Snippet, optional. The accessible table alternative.
17
+ // ...restProps — spread onto the root <figure>.
18
+ //
19
+ // Markup:
20
+ // <figure class="sunburst-chart">
21
+ // <div class="sunburst-chart-graphic" role="img" aria-label>…svg…</div>
22
+ // <div class="sunburst-chart-data-table">…table…</div> (only when provided)
23
+ // </figure>
24
+ //
25
+ // Keyboard: none on the graphic; the data table follows native table behaviour.
26
+ //
27
+ // Claude rules:
28
+ // - Headless: no CSS, no inline styles; no drawing.
29
+ // - No hardcoded user-facing strings.
30
+
31
+ import type { Snippet } from "svelte";
32
+
33
+ let {
34
+ class: className = "",
35
+ label = undefined,
36
+ children,
37
+ dataTable,
38
+ ...restProps
39
+ }: {
40
+ /** Accessible name for the chart. */
41
+ label?: string;
42
+ /** The consumer-supplied inline svg. */
43
+ children: Snippet;
44
+ /** Optional accessible data table alternative. */
45
+ dataTable?: Snippet;
46
+ [key: string]: unknown;
47
+ } = $props();
48
+ </script>
49
+
50
+ <!-- SunburstChart.svelte -->
51
+ <figure
52
+ class={`sunburst-chart ${className}`}
53
+ {...restProps}
54
+ >
55
+ <div class="sunburst-chart-graphic" role="img" aria-label={label}>
56
+ {@render children?.()}
57
+ </div>
58
+ {#if dataTable}
59
+ <div class="sunburst-chart-data-table">
60
+ {@render dataTable()}
61
+ </div>
62
+ {/if}
63
+ </figure>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ /** Accessible name for the chart. */
4
+ label?: string;
5
+ /** The consumer-supplied inline svg. */
6
+ children: Snippet;
7
+ /** Optional accessible data table alternative. */
8
+ dataTable?: Snippet;
9
+ [key: string]: unknown;
10
+ };
11
+ declare const SunburstChart: import("svelte").Component<$$ComponentProps, {}, "">;
12
+ type SunburstChart = ReturnType<typeof SunburstChart>;
13
+ export default SunburstChart;
@@ -47,11 +47,18 @@
47
47
  let {
48
48
  class: className = "",
49
49
  label,
50
+ live = false,
50
51
  children,
51
52
  ...restProps
52
53
  }: {
53
54
  /** Accessible label for screen readers */
54
55
  label: string;
56
+ /**
57
+ * Announce changes: a `role="status"` live region, for a tag whose text
58
+ * changes in place (a job's status). Off by default — a page of static
59
+ * tags should not be a page of live regions.
60
+ */
61
+ live?: boolean;
55
62
  /** The tag content (text, icon, etc.) */
56
63
  children: Snippet;
57
64
  /** Additional HTML attributes */
@@ -60,11 +67,16 @@
60
67
  </script>
61
68
 
62
69
  <!-- Tag.svelte -->
63
- <span
64
- class={`tag ${className}`}
65
- role="status"
66
- aria-label={label}
67
- {...restProps}
68
- >
69
- {@render children?.()}
70
- </span>
70
+ {#if live}
71
+ <span class={`tag ${className}`} role="status" aria-label={label} {...restProps}>
72
+ {@render children?.()}
73
+ </span>
74
+ {:else}
75
+ <!-- Not a live region: aria-label is not allowed on a plain <span>, so the
76
+ label is screen-reader text appended after the content (the themes hide
77
+ .screen-reader-span). The content stays exposed: it may hold a focusable
78
+ control, such as a remove button. -->
79
+ <span class={`tag ${className}`} {...restProps}>
80
+ {@render children?.()}{#if label}<span class="screen-reader-span">{label}</span>{/if}
81
+ </span>
82
+ {/if}
@@ -2,6 +2,12 @@ import type { Snippet } from "svelte";
2
2
  type $$ComponentProps = {
3
3
  /** Accessible label for screen readers */
4
4
  label: string;
5
+ /**
6
+ * Announce changes: a `role="status"` live region, for a tag whose text
7
+ * changes in place (a job's status). Off by default — a page of static
8
+ * tags should not be a page of live regions.
9
+ */
10
+ live?: boolean;
5
11
  /** The tag content (text, icon, etc.) */
6
12
  children: Snippet;
7
13
  /** Additional HTML attributes */
@@ -0,0 +1,54 @@
1
+ <script lang="ts">
2
+ // ToolCall component
3
+ //
4
+ // A headless disclosure for one tool invocation, built on the native <details>. Closed by default. The `summary` content (typically ToolCallName and ToolCallStatus) goes inside <summary class="tool-call-summary">; the body (ToolCallInput, ToolCallOutput, ToolCallError) goes inside <div class="tool-call-content">. `status` (pending | running | done | error) sets data-status on the root, and aria-busy="true" only while running. The component never animates, times or opens itself: the consumer owns `open` (open it on error so ToolCallError is not hidden) and any spinner/animation CSS.
5
+ //
6
+ // Props:
7
+ // class — string, optional. CSS class name.
8
+ // status — string, optional. pending | running | done | error. No default.
9
+ // open — boolean, default false. Bindable.
10
+ // summary — Snippet. The summary content (name + status words).
11
+ // children — Snippet. The body.
12
+ // ...restProps — additional HTML attributes spread onto the root <details>.
13
+ //
14
+ // Keyboard: Enter / Space on the native <summary> toggles.
15
+ //
16
+ // Claude rules:
17
+ // - Headless: no CSS, no animation, no hardcoded strings
18
+ import type { Snippet } from "svelte";
19
+
20
+ let {
21
+ class: className = "",
22
+ status = undefined,
23
+ open = $bindable(false),
24
+ summary,
25
+ children,
26
+ ...restProps
27
+ }: {
28
+ /** pending | running | done | error. */
29
+ status?: string;
30
+ /** Whether open. Bindable. */
31
+ open?: boolean;
32
+ /** Summary content. */
33
+ summary?: Snippet;
34
+ /** Body content. */
35
+ children?: Snippet;
36
+ [key: string]: unknown;
37
+ } = $props();
38
+ </script>
39
+
40
+ <!-- ToolCall.svelte -->
41
+ <details
42
+ class={`tool-call ${className}`}
43
+ bind:open
44
+ data-status={status}
45
+ aria-busy={status === "running" ? "true" : undefined}
46
+ {...restProps}
47
+ >
48
+ <summary class="tool-call-summary">
49
+ {@render summary?.()}
50
+ </summary>
51
+ <div class="tool-call-content">
52
+ {@render children?.()}
53
+ </div>
54
+ </details>
@@ -0,0 +1,15 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ /** pending | running | done | error. */
4
+ status?: string;
5
+ /** Whether open. Bindable. */
6
+ open?: boolean;
7
+ /** Summary content. */
8
+ summary?: Snippet;
9
+ /** Body content. */
10
+ children?: Snippet;
11
+ [key: string]: unknown;
12
+ };
13
+ declare const ToolCall: import("svelte").Component<$$ComponentProps, {}, "open">;
14
+ type ToolCall = ReturnType<typeof ToolCall>;
15
+ export default ToolCall;
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ // ToolCallError component
3
+ //
4
+ // A headless inner part of ToolCall: the error shown when a tool call fails. Contract: `role="alert"` announces the error when it appears (open the tool call on error so it is not hidden inside a closed `<details>`).
5
+ // Draws nothing and carries no strings of its own; the consumer supplies the text.
6
+ import type { Snippet } from "svelte";
7
+
8
+ let {
9
+ class: className = "",
10
+ children,
11
+ ...restProps
12
+ }: {
13
+
14
+ /** The content. */
15
+ children?: Snippet;
16
+ [key: string]: unknown;
17
+ } = $props();
18
+ </script>
19
+
20
+ <!-- ToolCallError.svelte -->
21
+ <div
22
+ class={`tool-call-error ${className}`}
23
+ role="alert"
24
+ {...restProps}
25
+ >
26
+ {@render children?.()}
27
+ </div>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ /** The content. */
4
+ children?: Snippet;
5
+ [key: string]: unknown;
6
+ };
7
+ declare const ToolCallError: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type ToolCallError = ReturnType<typeof ToolCallError>;
9
+ export default ToolCallError;
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ // ToolCallInput component
3
+ //
4
+ // A headless inner part of ToolCall: the input or arguments passed to a tool in a tool call. Contract: `label` (optional) sets `role="group"` and `aria-label`; without it neither is rendered.
5
+ // Draws nothing and carries no strings of its own; the consumer supplies the text.
6
+ import type { Snippet } from "svelte";
7
+
8
+ let {
9
+ class: className = "",
10
+ label = undefined,
11
+ children,
12
+ ...restProps
13
+ }: {
14
+ /** Accessible name of the group. */
15
+ label?: string;
16
+ /** The content. */
17
+ children?: Snippet;
18
+ [key: string]: unknown;
19
+ } = $props();
20
+ </script>
21
+
22
+ <!-- ToolCallInput.svelte -->
23
+ <div
24
+ class={`tool-call-input ${className}`}
25
+ role={label ? "group" : undefined}
26
+ aria-label={label}
27
+ {...restProps}
28
+ >
29
+ {@render children?.()}
30
+ </div>
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ /** Accessible name of the group. */
4
+ label?: string;
5
+ /** The content. */
6
+ children?: Snippet;
7
+ [key: string]: unknown;
8
+ };
9
+ declare const ToolCallInput: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type ToolCallInput = ReturnType<typeof ToolCallInput>;
11
+ export default ToolCallInput;