@joewinke/jatui 0.38.5 → 0.39.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 (67) hide show
  1. package/CLAUDE.md +32 -1
  2. package/THIRD_PARTY_NOTICES.md +51 -0
  3. package/dist/components/BulkActionBar.svelte +32 -2
  4. package/dist/components/BulkActionBar.svelte.d.ts +5 -1
  5. package/dist/components/FloatingActionBar.svelte +102 -34
  6. package/dist/components/FloatingActionBar.svelte.d.ts +9 -0
  7. package/dist/components/MediaExplorer.svelte +249 -0
  8. package/dist/components/MediaExplorer.svelte.d.ts +37 -0
  9. package/dist/components/NotificationCenter.svelte +481 -0
  10. package/dist/components/NotificationCenter.svelte.d.ts +29 -0
  11. package/dist/components/SearchDropdown.svelte +54 -8
  12. package/dist/components/SearchDropdown.svelte.d.ts +12 -0
  13. package/dist/components/VideoPlayer.svelte +269 -3
  14. package/dist/components/agent/AgentLog.svelte +217 -0
  15. package/dist/components/agent/AgentLog.svelte.d.ts +72 -0
  16. package/dist/components/agent/AgentLogRow.svelte +281 -0
  17. package/dist/components/agent/AgentLogRow.svelte.d.ts +21 -0
  18. package/dist/components/agent/AgentTaskList.svelte +607 -0
  19. package/dist/components/agent/AgentTaskList.svelte.d.ts +40 -0
  20. package/dist/components/agent/AgentThinking.svelte +280 -0
  21. package/dist/components/agent/AgentThinking.svelte.d.ts +22 -0
  22. package/dist/components/agent/ComposerGlow.svelte +265 -0
  23. package/dist/components/agent/ComposerGlow.svelte.d.ts +18 -0
  24. package/dist/components/agent/ContextMeter.svelte +277 -0
  25. package/dist/components/agent/ContextMeter.svelte.d.ts +21 -0
  26. package/dist/components/agent/Questionnaire.svelte +767 -0
  27. package/dist/components/agent/Questionnaire.svelte.d.ts +29 -0
  28. package/dist/components/agent/ShimmerText.svelte +100 -0
  29. package/dist/components/agent/ShimmerText.svelte.d.ts +19 -0
  30. package/dist/components/agent/StreamedText.svelte +135 -0
  31. package/dist/components/agent/StreamedText.svelte.d.ts +13 -0
  32. package/dist/components/agent/agentLog.d.ts +22 -0
  33. package/dist/components/agent/agentLog.js +26 -0
  34. package/dist/components/agent/agentTaskList.d.ts +90 -0
  35. package/dist/components/agent/agentTaskList.js +93 -0
  36. package/dist/components/agent/agentThinking.d.ts +46 -0
  37. package/dist/components/agent/agentThinking.js +78 -0
  38. package/dist/components/agent/contextMeter.d.ts +97 -0
  39. package/dist/components/agent/contextMeter.js +156 -0
  40. package/dist/components/agent/questionnaire.d.ts +104 -0
  41. package/dist/components/agent/questionnaire.js +225 -0
  42. package/dist/components/agent/revealCore.d.ts +74 -0
  43. package/dist/components/agent/revealCore.js +160 -0
  44. package/dist/components/agent/revealTicker.d.ts +34 -0
  45. package/dist/components/agent/revealTicker.js +73 -0
  46. package/dist/components/agent/streamedText.d.ts +28 -0
  47. package/dist/components/agent/streamedText.js +59 -0
  48. package/dist/components/messaging/MessageInput.svelte +34 -4
  49. package/dist/components/messaging/MessageInput.svelte.d.ts +7 -0
  50. package/dist/components/messaging/MessageItem.svelte +2 -2
  51. package/dist/components/notificationCenter.d.ts +65 -0
  52. package/dist/components/notificationCenter.js +110 -0
  53. package/dist/components/progress/Steps.svelte +269 -5
  54. package/dist/components/progress/Steps.svelte.d.ts +16 -1
  55. package/dist/components/progress/stepsSummary.d.ts +14 -0
  56. package/dist/components/progress/stepsSummary.js +32 -0
  57. package/dist/index.d.ts +34 -0
  58. package/dist/index.js +29 -0
  59. package/dist/selection/clickSelection.d.ts +89 -0
  60. package/dist/selection/clickSelection.js +152 -0
  61. package/dist/selection/createClickSelection.d.ts +79 -0
  62. package/dist/selection/createClickSelection.js +134 -0
  63. package/dist/video/keys.d.ts +5 -5
  64. package/dist/video/keys.js +9 -5
  65. package/dist/video/transcriptSearch.d.ts +80 -0
  66. package/dist/video/transcriptSearch.js +153 -0
  67. package/package.json +3 -2
@@ -0,0 +1,607 @@
1
+ <!--
2
+ AgentTaskList — an agent's plan as it runs: tasks, each with the steps the
3
+ agent took, streaming in on the AgentLog machinery (grow-in rows, a tree
4
+ guide under each task).
5
+
6
+ - Each task header and each step is one reveal unit. Leave `revealed`
7
+ unset and the units are paced by a timer (`startDelay`, `stepInterval`,
8
+ `delayFor`); set it and real events drive the count instead (pass
9
+ `Infinity` to show everything at once, e.g. a finished run's history).
10
+ - A running task's title shimmers; a task reported done or failed still
11
+ reads as running until its steps have appeared.
12
+ - Steps can carry resource `chips` (files, tables, links) and `sources`
13
+ (pages read) — the latter branch into a "Sources" row of overlapping site
14
+ marks, `maxSources` visible and the rest as "+N". Marks show the host's
15
+ `favicon` URL, else a letter tile; nothing is bundled.
16
+ - `collapseOnComplete`: `true` folds each finished task once the log moves
17
+ past it, `'all'` folds them together when the list completes. Failed
18
+ tasks stay open. The header is a button that folds / reopens a task.
19
+ - `onComplete` fires once when every unit is visible and no task is
20
+ pending or running.
21
+
22
+ Our own (clean-room) component; the row motion it builds on is AgentLog.
23
+ -->
24
+ <script lang="ts">
25
+ import { untrack } from 'svelte';
26
+ import AgentLog from './AgentLog.svelte';
27
+ import ShimmerText from './ShimmerText.svelte';
28
+ import { createRevealTicker } from './revealTicker';
29
+ import { revealDelay, DEFAULT_STEP_INTERVAL, DEFAULT_START_DELAY } from './revealCore';
30
+ import { motionSlide } from '../../motion/transitions';
31
+ import { tooltip } from '../../actions/tooltip';
32
+ import {
33
+ countUnits,
34
+ displayStatus,
35
+ foldedByPolicy,
36
+ isListComplete,
37
+ isTaskOpen,
38
+ layoutTaskReveal,
39
+ sourceInitial,
40
+ sourceLabel,
41
+ sourceStack,
42
+ stepKey,
43
+ DEFAULT_MAX_SOURCES,
44
+ type AgentTask,
45
+ type AgentTaskSource,
46
+ type AgentTaskStatus,
47
+ type AgentTaskStep,
48
+ type CollapsePolicy
49
+ } from './agentTaskList';
50
+
51
+ interface Props {
52
+ tasks: AgentTask[];
53
+ /**
54
+ * Units (task headers + steps) to show. Unset = timer-driven. A number =
55
+ * event-driven, no timer. `Infinity` shows everything.
56
+ */
57
+ revealed?: number;
58
+ /** ms between units (timer mode). Default 850. */
59
+ stepInterval?: number;
60
+ /** ms before the first unit (timer mode). Default 320. */
61
+ startDelay?: number;
62
+ /** Dwell before unit `index` (timer mode); overrides the two above. */
63
+ delayFor?: (index: number) => number;
64
+ /** Fold finished tasks: `true` one by one, `'all'` together at the end. */
65
+ collapseOnComplete?: CollapsePolicy;
66
+ /**
67
+ * Working line at the tail. Default: shown until the list completes. A
68
+ * string sets its label; false hides it.
69
+ */
70
+ working?: string | boolean;
71
+ /** Marks shown per Sources row before "+N". Default 6. */
72
+ maxSources?: number;
73
+ /** Heading of a step's sources row. */
74
+ sourcesLabel?: string;
75
+ /** Screen-reader status words. */
76
+ statusLabels?: Partial<Record<AgentTaskStatus, string>>;
77
+ /** Summary shown on a folded task. Default "3 steps". */
78
+ foldedSummary?: (task: AgentTask) => string;
79
+ /** Fired once when the list completes. */
80
+ onComplete?: () => void;
81
+ /** Fired when the user folds / reopens a task. */
82
+ onToggle?: (taskId: string, open: boolean) => void;
83
+ /** Accessible name for the log region. */
84
+ ariaLabel?: string;
85
+ class?: string;
86
+ }
87
+
88
+ let {
89
+ tasks,
90
+ revealed,
91
+ stepInterval,
92
+ startDelay,
93
+ delayFor,
94
+ collapseOnComplete = false,
95
+ working = true,
96
+ maxSources = DEFAULT_MAX_SOURCES,
97
+ sourcesLabel = 'Sources',
98
+ statusLabels,
99
+ foldedSummary,
100
+ onComplete,
101
+ onToggle,
102
+ ariaLabel = 'Agent tasks',
103
+ class: className = ''
104
+ }: Props = $props();
105
+
106
+ const STATUS_TEXT: Record<AgentTaskStatus, string> = {
107
+ pending: 'Pending',
108
+ running: 'In progress',
109
+ done: 'Done',
110
+ error: 'Failed'
111
+ };
112
+
113
+ const total = $derived(countUnits(tasks));
114
+ const ticker = createRevealTicker({
115
+ total: () => total,
116
+ revealed: () => revealed,
117
+ stepInterval: () => stepInterval ?? DEFAULT_STEP_INTERVAL,
118
+ startDelay: () => startDelay ?? DEFAULT_START_DELAY,
119
+ // Read through, so a changed delayFor prop takes effect on the next unit.
120
+ delayFor: (i) => (delayFor ? delayFor(i) : revealDelay(i, { startDelay, stepInterval }))
121
+ });
122
+
123
+ const layout = $derived(layoutTaskReveal(tasks, ticker.revealed));
124
+ const complete = $derived(isListComplete(tasks, ticker.revealed));
125
+ const visibleTasks = $derived(tasks.filter((_, i) => layout[i]?.visible));
126
+
127
+ /** The user's fold/open choice per task id; wins over the policy. */
128
+ let overrides = $state<Record<string, boolean>>({});
129
+
130
+ function revealOf(task: AgentTask) {
131
+ return layout[tasks.indexOf(task)];
132
+ }
133
+ function openOf(task: AgentTask): boolean {
134
+ const r = revealOf(task);
135
+ if (!r) return true;
136
+ return isTaskOpen(foldedByPolicy(task, r, collapseOnComplete, complete), overrides[task.id]);
137
+ }
138
+ function toggle(task: AgentTask) {
139
+ const next = !openOf(task);
140
+ overrides[task.id] = next;
141
+ onToggle?.(task.id, next);
142
+ }
143
+
144
+ const workingLabel = $derived(
145
+ working === false || complete ? null : typeof working === 'string' ? working : 'Working'
146
+ );
147
+
148
+ let fired = false;
149
+ $effect(() => {
150
+ if (!complete) {
151
+ fired = false;
152
+ return;
153
+ }
154
+ if (fired) return;
155
+ fired = true;
156
+ untrack(() => onComplete?.());
157
+ });
158
+
159
+ const uid = $props.id();
160
+
161
+ /** Favicons that failed to load fall back to a letter tile. */
162
+ let broken = $state<Record<string, true>>({});
163
+ const markKey = (s: AgentTaskSource, i: number) => s.href ?? s.favicon ?? `${s.title}#${i}`;
164
+
165
+ function summary(task: AgentTask): string {
166
+ if (foldedSummary) return foldedSummary(task);
167
+ const n = task.steps.length;
168
+ return `${n} step${n === 1 ? '' : 's'}`;
169
+ }
170
+ </script>
171
+
172
+ {#snippet glyph(status: AgentTaskStatus)}
173
+ <span class="atl-glyph atl-glyph--{status}" aria-hidden="true">
174
+ {#if status === 'running'}
175
+ <span class="loading loading-spinner atl-spinner"></span>
176
+ {:else if status === 'done'}
177
+ <svg viewBox="0 0 16 16" fill="none">
178
+ <circle cx="8" cy="8" r="7" fill="currentColor" opacity="0.16" />
179
+ <path
180
+ d="M5 8.2 7 10.2 11 6"
181
+ stroke="currentColor"
182
+ stroke-width="1.5"
183
+ stroke-linecap="round"
184
+ stroke-linejoin="round"
185
+ />
186
+ </svg>
187
+ {:else if status === 'error'}
188
+ <svg viewBox="0 0 16 16" fill="none">
189
+ <circle cx="8" cy="8" r="7" fill="currentColor" opacity="0.16" />
190
+ <path d="M5.75 5.75 10.25 10.25M10.25 5.75 5.75 10.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
191
+ </svg>
192
+ {:else}
193
+ <svg viewBox="0 0 16 16" fill="none">
194
+ <circle cx="8" cy="8" r="6.25" stroke="currentColor" stroke-width="1.25" stroke-dasharray="2.2 2.2" />
195
+ </svg>
196
+ {/if}
197
+ </span>
198
+ {/snippet}
199
+
200
+ {#snippet mark(source: AgentTaskSource, i: number)}
201
+ {@const k = markKey(source, i)}
202
+ {@const text = sourceLabel(source)}
203
+ {#snippet face()}
204
+ {#if source.favicon && !broken[k]}
205
+ <img
206
+ src={source.favicon}
207
+ alt=""
208
+ width="16"
209
+ height="16"
210
+ loading="lazy"
211
+ decoding="async"
212
+ referrerpolicy="no-referrer"
213
+ onerror={() => (broken[k] = true)}
214
+ />
215
+ {:else}
216
+ <span class="atl-letter">{sourceInitial(source)}</span>
217
+ {/if}
218
+ {/snippet}
219
+ <li class="atl-mark-item">
220
+ {#if source.href}
221
+ <a
222
+ class="atl-mark"
223
+ href={source.href}
224
+ target="_blank"
225
+ rel="noopener noreferrer"
226
+ aria-label={text}
227
+ use:tooltip={{ text, delayMs: 150 }}
228
+ >
229
+ {@render face()}
230
+ </a>
231
+ {:else}
232
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
233
+ <span class="atl-mark" role="img" tabindex="0" aria-label={text} use:tooltip={{ text, delayMs: 150 }}>
234
+ {@render face()}
235
+ </span>
236
+ {/if}
237
+ </li>
238
+ {/snippet}
239
+
240
+ {#snippet sourcesRow(sources: AgentTaskSource[])}
241
+ {@const stack = sourceStack(sources, maxSources)}
242
+ <div class="atl-sources">
243
+ <span class="atl-sources-label">{sourcesLabel}</span>
244
+ <ul class="atl-marks" aria-label="{sourcesLabel} ({sources.length})">
245
+ {#each stack.visible as s, i (markKey(s, i))}
246
+ {@render mark(s, i)}
247
+ {/each}
248
+ {#if stack.overflow.length > 0}
249
+ {@const rest = stack.overflow.map(sourceLabel).join(', ')}
250
+ <li class="atl-mark-item">
251
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
252
+ <span
253
+ class="atl-mark atl-more"
254
+ role="img"
255
+ tabindex="0"
256
+ aria-label="{stack.overflow.length} more: {rest}"
257
+ use:tooltip={{ text: rest, delayMs: 150 }}
258
+ >+{stack.overflow.length}</span>
259
+ </li>
260
+ {/if}
261
+ </ul>
262
+ </div>
263
+ {/snippet}
264
+
265
+ {#snippet stepRow(step: AgentTaskStep)}
266
+ <div class="atl-step">
267
+ <p class="atl-step-line">
268
+ <span class="atl-step-label">{step.label}</span>
269
+ {#if step.meta}<span class="atl-meta">{step.meta}</span>{/if}
270
+ </p>
271
+ {#if step.chips?.length}
272
+ <ul class="atl-chips">
273
+ {#each step.chips as chip, ci (ci)}
274
+ <li class="atl-chip-item">
275
+ <svelte:element
276
+ this={chip.href ? 'a' : 'span'}
277
+ class="atl-chip"
278
+ href={chip.href}
279
+ title={chip.label}
280
+ >
281
+ {#if chip.icon}
282
+ {#if typeof chip.icon === 'string'}
283
+ <span class="atl-chip-icon" aria-hidden="true">{chip.icon}</span>
284
+ {:else}
285
+ {@const Icon = chip.icon}
286
+ <Icon size={12} class="atl-chip-icon" />
287
+ {/if}
288
+ {/if}
289
+ <span class="atl-chip-text">{chip.label}</span>
290
+ </svelte:element>
291
+ </li>
292
+ {/each}
293
+ </ul>
294
+ {/if}
295
+ </div>
296
+ {#if step.sources?.length}
297
+ <div class="atl-nest">
298
+ <AgentLog items={[step.sources]} live={false} bridge={4}>
299
+ {#snippet row(sources)}{@render sourcesRow(sources)}{/snippet}
300
+ </AgentLog>
301
+ </div>
302
+ {/if}
303
+ {/snippet}
304
+
305
+ {#snippet taskRow(task: AgentTask)}
306
+ {@const r = revealOf(task)}
307
+ {@const status = displayStatus(task, r)}
308
+ {@const open = openOf(task)}
309
+ {@const steps = task.steps.slice(0, r.stepsVisible)}
310
+ {@const stepsId = `${uid}-${task.id}-steps`}
311
+ <div class="atl-task" data-status={status}>
312
+ <button
313
+ type="button"
314
+ class="atl-head"
315
+ aria-expanded={steps.length > 0 ? open : undefined}
316
+ aria-controls={steps.length > 0 ? stepsId : undefined}
317
+ onclick={() => toggle(task)}
318
+ >
319
+ {@render glyph(status)}
320
+ <span class="atl-title">
321
+ <ShimmerText
322
+ text={task.label}
323
+ active={status === 'running'}
324
+ tone={status === 'pending' ? 'subtle' : 'strong'}
325
+ />
326
+ </span>
327
+ <span class="sr-only">— {statusLabels?.[status] ?? STATUS_TEXT[status]}</span>
328
+ {#if steps.length > 0 && !open}
329
+ <span class="atl-summary">{summary(task)}</span>
330
+ {/if}
331
+ {#if steps.length > 0}
332
+ <svg class="atl-chevron" class:is-open={open} viewBox="0 0 16 16" fill="none" aria-hidden="true">
333
+ <path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
334
+ </svg>
335
+ {/if}
336
+ </button>
337
+ <!-- Mounted while open even before the first step, so that step arrives
338
+ into a live log and grows in; a reopened task's steps rest. -->
339
+ {#if open}
340
+ <div class="atl-steps" class:has-steps={steps.length > 0} id={stepsId} transition:motionSlide>
341
+ <AgentLog items={steps} key={stepKey} live={false} bridge={6} appear={false}>
342
+ {#snippet row(step)}{@render stepRow(step)}{/snippet}
343
+ </AgentLog>
344
+ </div>
345
+ {/if}
346
+ </div>
347
+ {/snippet}
348
+
349
+ <AgentLog
350
+ class="agent-task-list {className}"
351
+ items={visibleTasks}
352
+ key={(t) => t.id}
353
+ guide={false}
354
+ working={workingLabel}
355
+ {ariaLabel}
356
+ busy={!complete}
357
+ >
358
+ {#snippet row(task)}{@render taskRow(task)}{/snippet}
359
+ </AgentLog>
360
+
361
+ <style>
362
+ /* ── task header ──────────────────────────────────────────────────── */
363
+ .atl-head {
364
+ display: flex;
365
+ align-items: flex-start;
366
+ gap: 0.5rem;
367
+ width: 100%;
368
+ min-width: 0;
369
+ padding: 0.25rem 0.25rem 0.25rem 0;
370
+ border: 0;
371
+ background: none;
372
+ color: inherit;
373
+ font: inherit;
374
+ font-size: 0.875rem;
375
+ line-height: 1.25rem;
376
+ text-align: start;
377
+ cursor: pointer;
378
+ border-radius: var(--jatui-radius-field, 0.25rem);
379
+ }
380
+ .atl-head:focus-visible {
381
+ outline: 2px solid var(--color-primary);
382
+ outline-offset: 2px;
383
+ }
384
+ .atl-head:hover .atl-chevron {
385
+ color: var(--color-base-content);
386
+ }
387
+
388
+ .atl-glyph {
389
+ display: inline-flex;
390
+ align-items: center;
391
+ justify-content: center;
392
+ flex-shrink: 0;
393
+ width: 1rem;
394
+ height: 1.25rem; /* one line: centres on the first line of a wrapped title */
395
+ }
396
+ .atl-glyph svg {
397
+ width: 1rem;
398
+ height: 1rem;
399
+ }
400
+ .atl-glyph--pending {
401
+ color: color-mix(in oklab, var(--color-base-content) 40%, transparent);
402
+ }
403
+ .atl-glyph--running {
404
+ color: var(--color-primary);
405
+ }
406
+ .atl-glyph--done {
407
+ color: var(--color-success);
408
+ }
409
+ .atl-glyph--error {
410
+ color: var(--color-error);
411
+ }
412
+ .atl-spinner {
413
+ width: 0.875rem;
414
+ }
415
+
416
+ .atl-title {
417
+ flex: 1 1 auto;
418
+ min-width: 0;
419
+ font-weight: 500;
420
+ overflow-wrap: anywhere;
421
+ }
422
+ .atl-summary {
423
+ flex-shrink: 0;
424
+ font-size: 0.75rem;
425
+ color: color-mix(in oklab, var(--color-base-content) 55%, transparent);
426
+ }
427
+ .atl-chevron {
428
+ flex-shrink: 0;
429
+ width: 1rem;
430
+ height: 1.25rem;
431
+ color: color-mix(in oklab, var(--color-base-content) 45%, transparent);
432
+ transition:
433
+ rotate var(--motion-fast, 150ms) var(--motion-glide, ease-out),
434
+ color var(--motion-instant, 80ms) var(--motion-glide, ease-out);
435
+ }
436
+ .atl-chevron.is-open {
437
+ rotate: 90deg;
438
+ }
439
+ .atl-chevron:dir(rtl) {
440
+ scale: -1 1;
441
+ }
442
+ /* scale applies before rotate: mirror, then turn the other way to point down */
443
+ .atl-chevron.is-open:dir(rtl) {
444
+ rotate: -90deg;
445
+ }
446
+
447
+ /* Steps hang under the header glyph: the trunk sits on the glyph's centre. */
448
+ .atl-steps {
449
+ margin-inline-start: 0.47rem;
450
+ }
451
+ .atl-steps.has-steps {
452
+ padding-bottom: 0.25rem;
453
+ }
454
+
455
+ /* ── steps ────────────────────────────────────────────────────────── */
456
+ .atl-step {
457
+ padding-block: 0.25rem;
458
+ min-width: 0;
459
+ }
460
+ .atl-step-line {
461
+ margin: 0;
462
+ font-size: 0.875rem;
463
+ line-height: 1.25rem;
464
+ color: color-mix(in oklab, var(--color-base-content) 80%, transparent);
465
+ overflow-wrap: anywhere;
466
+ }
467
+ .atl-meta {
468
+ margin-inline-start: 0.5rem;
469
+ font-size: 0.75rem;
470
+ color: color-mix(in oklab, var(--color-base-content) 50%, transparent);
471
+ font-variant-numeric: tabular-nums;
472
+ }
473
+
474
+ .atl-chips {
475
+ display: flex;
476
+ flex-wrap: wrap;
477
+ gap: 0.25rem;
478
+ margin: 0.25rem 0 0;
479
+ padding: 0;
480
+ list-style: none;
481
+ min-width: 0;
482
+ }
483
+ .atl-chip-item {
484
+ min-width: 0;
485
+ max-width: 100%;
486
+ }
487
+ .atl-chip {
488
+ display: inline-flex;
489
+ align-items: center;
490
+ gap: 0.25rem;
491
+ max-width: min(16rem, 100%);
492
+ padding: 0 0.375rem;
493
+ height: 1.25rem;
494
+ border: var(--jatui-border-w, 1px) solid color-mix(in oklab, var(--color-base-content) 12%, transparent);
495
+ border-radius: var(--jatui-radius-selector, 0.375rem);
496
+ background: color-mix(in oklab, var(--color-base-content) 4%, transparent);
497
+ font-size: 0.75rem;
498
+ line-height: 1rem;
499
+ color: color-mix(in oklab, var(--color-base-content) 75%, transparent);
500
+ text-decoration: none;
501
+ }
502
+ a.atl-chip:hover {
503
+ color: var(--color-base-content);
504
+ border-color: color-mix(in oklab, var(--color-base-content) 25%, transparent);
505
+ }
506
+ a.atl-chip:focus-visible {
507
+ outline: 2px solid var(--color-primary);
508
+ outline-offset: 1px;
509
+ }
510
+ .atl-chip :global(.atl-chip-icon) {
511
+ flex-shrink: 0;
512
+ opacity: 0.75;
513
+ }
514
+ .atl-chip-text {
515
+ min-width: 0;
516
+ overflow: hidden;
517
+ text-overflow: ellipsis;
518
+ white-space: nowrap;
519
+ }
520
+
521
+ /* ── sources ──────────────────────────────────────────────────────── */
522
+ .atl-nest {
523
+ margin-inline-start: 0.25rem;
524
+ }
525
+ .atl-sources {
526
+ display: flex;
527
+ align-items: center;
528
+ flex-wrap: wrap;
529
+ gap: 0.5rem;
530
+ padding-block: 0.25rem;
531
+ min-height: 1.75rem;
532
+ }
533
+ .atl-sources-label {
534
+ font-size: 0.75rem;
535
+ line-height: 1.25rem;
536
+ color: color-mix(in oklab, var(--color-base-content) 55%, transparent);
537
+ }
538
+ .atl-marks {
539
+ display: flex;
540
+ align-items: center;
541
+ margin: 0;
542
+ padding: 0;
543
+ padding-inline-start: 0.25rem;
544
+ list-style: none;
545
+ }
546
+ .atl-mark-item {
547
+ margin-inline-start: -0.25rem;
548
+ position: relative;
549
+ }
550
+ .atl-mark {
551
+ display: inline-flex;
552
+ align-items: center;
553
+ justify-content: center;
554
+ width: 1.25rem;
555
+ height: 1.25rem;
556
+ overflow: hidden;
557
+ border-radius: 999px;
558
+ background: var(--color-base-100);
559
+ box-shadow: 0 0 0 2px var(--color-base-100);
560
+ color: color-mix(in oklab, var(--color-base-content) 70%, transparent);
561
+ text-decoration: none;
562
+ transition: translate var(--motion-fast, 150ms) var(--motion-glide, ease-out);
563
+ }
564
+ .atl-mark img {
565
+ width: 1rem;
566
+ height: 1rem;
567
+ object-fit: contain;
568
+ }
569
+ .atl-mark:hover,
570
+ .atl-mark:focus-visible {
571
+ translate: 0 -2px;
572
+ z-index: 1;
573
+ }
574
+ .atl-mark:focus-visible {
575
+ outline: 2px solid var(--color-primary);
576
+ outline-offset: 1px;
577
+ }
578
+ .atl-letter,
579
+ .atl-more {
580
+ font-size: 0.625rem;
581
+ font-weight: 600;
582
+ line-height: 1;
583
+ }
584
+ .atl-letter {
585
+ display: inline-flex;
586
+ align-items: center;
587
+ justify-content: center;
588
+ width: 100%;
589
+ height: 100%;
590
+ background: color-mix(in oklab, var(--color-base-content) 10%, var(--color-base-100));
591
+ }
592
+ .atl-more {
593
+ background: color-mix(in oklab, var(--color-base-content) 14%, var(--color-base-100));
594
+ font-variant-numeric: tabular-nums;
595
+ }
596
+
597
+ @media (prefers-reduced-motion: reduce) {
598
+ .atl-mark,
599
+ .atl-chevron {
600
+ transition: none;
601
+ }
602
+ .atl-mark:hover,
603
+ .atl-mark:focus-visible {
604
+ translate: none;
605
+ }
606
+ }
607
+ </style>
@@ -0,0 +1,40 @@
1
+ import { type AgentTask, type AgentTaskStatus, type CollapsePolicy } from './agentTaskList';
2
+ interface Props {
3
+ tasks: AgentTask[];
4
+ /**
5
+ * Units (task headers + steps) to show. Unset = timer-driven. A number =
6
+ * event-driven, no timer. `Infinity` shows everything.
7
+ */
8
+ revealed?: number;
9
+ /** ms between units (timer mode). Default 850. */
10
+ stepInterval?: number;
11
+ /** ms before the first unit (timer mode). Default 320. */
12
+ startDelay?: number;
13
+ /** Dwell before unit `index` (timer mode); overrides the two above. */
14
+ delayFor?: (index: number) => number;
15
+ /** Fold finished tasks: `true` one by one, `'all'` together at the end. */
16
+ collapseOnComplete?: CollapsePolicy;
17
+ /**
18
+ * Working line at the tail. Default: shown until the list completes. A
19
+ * string sets its label; false hides it.
20
+ */
21
+ working?: string | boolean;
22
+ /** Marks shown per Sources row before "+N". Default 6. */
23
+ maxSources?: number;
24
+ /** Heading of a step's sources row. */
25
+ sourcesLabel?: string;
26
+ /** Screen-reader status words. */
27
+ statusLabels?: Partial<Record<AgentTaskStatus, string>>;
28
+ /** Summary shown on a folded task. Default "3 steps". */
29
+ foldedSummary?: (task: AgentTask) => string;
30
+ /** Fired once when the list completes. */
31
+ onComplete?: () => void;
32
+ /** Fired when the user folds / reopens a task. */
33
+ onToggle?: (taskId: string, open: boolean) => void;
34
+ /** Accessible name for the log region. */
35
+ ariaLabel?: string;
36
+ class?: string;
37
+ }
38
+ declare const AgentTaskList: import("svelte").Component<Props, {}, "">;
39
+ type AgentTaskList = ReturnType<typeof AgentTaskList>;
40
+ export default AgentTaskList;