@invana/boards 0.0.32

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/index.js ADDED
@@ -0,0 +1,1069 @@
1
+ import { cn, Button, PropertyList, PropertyRow, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Eyebrow, ButtonGroup, BoundChip, Badge, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, ToggleGroup, ToggleGroupItem, Terminal, TerminalLine, Item, ItemMedia, StatusDot, ItemContent, ItemTitle, ItemActions, Alert, AlertDescription, TabbedPanel, RecordHeader, Workbook, TraceList, TouchStrip, ArtifactTable, LayerSection, ParticipantRow, LensRow, ExchangeRecord, TraceGate, TraceLoop, TraceStep, MarkChip, AbsenceNote, PanelBox } from '@invana/ui';
2
+ import { CodeBlock } from '@invana/editor';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import * as React from 'react';
5
+ import { PaginatedTable, DataTable } from '@invana/tables';
6
+ import { BLOCKS, Block, useStreamedSpec, applyBlockPatch, BlockPatchError } from '@invana/blocks';
7
+ import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Label, Switch, ParamRow } from '@invana/forms';
8
+ import { X, Lock, ChevronDown, Check } from 'lucide-react';
9
+
10
+ // src/panels/data.tsx
11
+ function JsonPanel({ options }) {
12
+ const value = typeof options.value === "string" ? options.value : JSON.stringify(options.value, null, 2);
13
+ return /* @__PURE__ */ jsx(CodeBlock, { language: "json", value, maxHeight: options.maxHeight, className: "border-0" });
14
+ }
15
+ function CodePanel({ options }) {
16
+ return /* @__PURE__ */ jsx(
17
+ CodeBlock,
18
+ {
19
+ language: options.language ?? "plain",
20
+ value: options.value,
21
+ maxHeight: options.maxHeight,
22
+ showLineNumbers: options.showLineNumbers,
23
+ className: "border-0"
24
+ }
25
+ );
26
+ }
27
+ function ExchangePanel({ options }) {
28
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: options.blocks.map((block, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
29
+ /* @__PURE__ */ jsx(Eyebrow, { children: block.label }),
30
+ /* @__PURE__ */ jsx(CodeBlock, { language: block.language ?? "plain", value: block.value })
31
+ ] }, i)) });
32
+ }
33
+ var LEVELS = ["error", "warn", "info", "debug"];
34
+ var offset = (ms) => `${(ms / 1e3).toFixed(3)}s`;
35
+ var took = (ms) => ms == null ? "\u2014" : ms < 1e3 ? `${ms}ms` : `${(ms / 1e3).toFixed(1)}s`;
36
+ function KindBadge({ kind, level }) {
37
+ if (level === "error")
38
+ return /* @__PURE__ */ jsx(Badge, { variant: "destructive", size: "xs", children: kind });
39
+ if (level === "warn")
40
+ return /* @__PURE__ */ jsx(Badge, { variant: "soft", tone: "warning", size: "xs", children: kind });
41
+ return /* @__PURE__ */ jsx(Badge, { variant: "outline", tone: "muted", size: "xs", children: kind });
42
+ }
43
+ function StatusBadge({ status }) {
44
+ if (status === "succeeded")
45
+ return /* @__PURE__ */ jsx(Badge, { variant: "soft", tone: "success", size: "xs", children: status });
46
+ if (status === "failed")
47
+ return /* @__PURE__ */ jsx(Badge, { variant: "destructive", size: "xs", children: status });
48
+ return /* @__PURE__ */ jsx(Badge, { variant: "outline", tone: "muted", size: "xs", children: status.replace("_", " ") });
49
+ }
50
+ function EventsPanel(props) {
51
+ return props.options.layout === "tree" ? /* @__PURE__ */ jsx(EventTree, { ...props }) : /* @__PURE__ */ jsx(EventLog, { ...props });
52
+ }
53
+ function EventLog({ panel, options, onAction }) {
54
+ const { selectAction, hideTask } = options;
55
+ const columns = React.useMemo(
56
+ () => [
57
+ {
58
+ id: "at",
59
+ accessorKey: "atMs",
60
+ header: "t",
61
+ size: 84,
62
+ meta: { mono: true, align: "right" },
63
+ cell: ({ getValue }) => offset(getValue())
64
+ },
65
+ {
66
+ id: "kind",
67
+ accessorKey: "kind",
68
+ header: "Kind",
69
+ size: 132,
70
+ cell: ({ row }) => /* @__PURE__ */ jsx(KindBadge, { kind: row.original.kind, level: row.original.level })
71
+ },
72
+ ...hideTask ? [] : [
73
+ {
74
+ id: "task",
75
+ accessorKey: "task",
76
+ header: "Task",
77
+ size: 150,
78
+ meta: { mono: true },
79
+ cell: ({ getValue }) => getValue() ?? "\u2014"
80
+ }
81
+ ],
82
+ {
83
+ id: "took",
84
+ accessorKey: "tookMs",
85
+ header: "Took",
86
+ size: 72,
87
+ meta: { mono: true, align: "right" },
88
+ cell: ({ getValue }) => took(getValue())
89
+ },
90
+ { id: "message", accessorKey: "message", header: "Detail", size: 360, enableSorting: false }
91
+ ],
92
+ [hideTask]
93
+ );
94
+ const levels = React.useMemo(() => LEVELS.filter((l) => options.events.some((e) => e.level === l)), [options.events]);
95
+ const filters = React.useMemo(
96
+ () => [
97
+ { id: "kind", label: "kind" },
98
+ ...hideTask ? [] : [{ id: "task", label: "task" }],
99
+ { id: "level", label: "level", options: levels, match: (e, picked) => picked.includes(e.level) }
100
+ ],
101
+ [hideTask, levels]
102
+ );
103
+ return /* @__PURE__ */ jsx(
104
+ PaginatedTable,
105
+ {
106
+ columns,
107
+ data: options.events,
108
+ density: "compact",
109
+ seamless: true,
110
+ filters,
111
+ searchColumns: hideTask ? ["message"] : ["task", "message"],
112
+ searchPlaceholder: hideTask ? "Search detail\u2026" : "Search task or detail\u2026",
113
+ noun: "events",
114
+ pageSize: options.pageSize ?? 25,
115
+ pageSizeOptions: [25, 50, 100],
116
+ onRowClick: selectAction ? (e) => e.task && onAction(selectAction, { panelId: panel.id, value: e.task }) : void 0
117
+ }
118
+ );
119
+ }
120
+ function treeOf(options) {
121
+ const tasks = options.tasks ?? [];
122
+ const row = (t) => ({
123
+ id: t.key,
124
+ name: t.key,
125
+ atMs: t.startMs,
126
+ tookMs: t.durationMs,
127
+ summary: t.summary ?? "",
128
+ status: t.status,
129
+ task: t.key,
130
+ children: [
131
+ ...options.events.filter((e) => e.task === t.key).sort((a, b) => a.atMs - b.atMs).map((e) => ({
132
+ id: e.id,
133
+ name: e.kind,
134
+ atMs: e.atMs,
135
+ tookMs: e.tookMs,
136
+ summary: e.message,
137
+ event: e,
138
+ task: t.key
139
+ })),
140
+ ...tasks.filter((c) => c.parent === t.key).map(row)
141
+ ]
142
+ });
143
+ return tasks.filter((t) => !t.parent).map(row);
144
+ }
145
+ function troublePaths(options) {
146
+ const parent = new Map((options.tasks ?? []).map((t) => [t.key, t.parent]));
147
+ const open = {};
148
+ for (const e of options.events.filter((ev) => ev.level === "error" || ev.level === "warn")) {
149
+ open[e.id] = true;
150
+ for (let k = e.task; k; k = parent.get(k)) open[k] = true;
151
+ }
152
+ return open;
153
+ }
154
+ var resolve = (next, old) => typeof next === "function" ? next(old) : next;
155
+ var TREE_COLUMNS = [
156
+ {
157
+ id: "name",
158
+ accessorKey: "name",
159
+ header: "Task / event",
160
+ size: 260,
161
+ cell: ({ row }) => row.original.event ? /* @__PURE__ */ jsx(KindBadge, { kind: row.original.event.kind, level: row.original.event.level }) : /* @__PURE__ */ jsx("span", { className: "font-mono", children: row.original.name })
162
+ },
163
+ {
164
+ id: "status",
165
+ header: "Status",
166
+ size: 100,
167
+ cell: ({ row }) => row.original.status ? /* @__PURE__ */ jsx(StatusBadge, { status: row.original.status }) : "\u2014"
168
+ },
169
+ {
170
+ id: "at",
171
+ accessorKey: "atMs",
172
+ header: "t",
173
+ size: 84,
174
+ meta: { mono: true, align: "right" },
175
+ cell: ({ getValue }) => {
176
+ const v = getValue();
177
+ return v == null ? "\u2014" : offset(v);
178
+ }
179
+ },
180
+ {
181
+ id: "took",
182
+ accessorKey: "tookMs",
183
+ header: "Took",
184
+ size: 72,
185
+ meta: { mono: true, align: "right" },
186
+ cell: ({ getValue }) => took(getValue())
187
+ },
188
+ { id: "summary", accessorKey: "summary", header: "Detail", size: 360, enableSorting: false }
189
+ ];
190
+ function EventTree({ panel, options, onAction }) {
191
+ const tree = React.useMemo(() => treeOf(options), [options]);
192
+ const roots = React.useMemo(() => Object.fromEntries(tree.map((r) => [r.id, true])), [tree]);
193
+ const [expanded, setExpanded] = React.useState(roots);
194
+ const { selectAction } = options;
195
+ return /* @__PURE__ */ jsx(
196
+ DataTable,
197
+ {
198
+ columns: TREE_COLUMNS,
199
+ data: tree,
200
+ density: "compact",
201
+ seamless: true,
202
+ getSubRows: (r) => r.children,
203
+ getRowId: (r) => r.id,
204
+ expanded,
205
+ onExpandedChange: (next) => setExpanded(resolve(next, expanded)),
206
+ canExpand: (r) => r.event?.fields != null,
207
+ enableSorting: false,
208
+ enableColumnVisibility: false,
209
+ onRowClick: selectAction ? (r) => r.task && onAction(selectAction, { panelId: panel.id, value: r.task }) : void 0,
210
+ toolbar: /* @__PURE__ */ jsxs(ButtonGroup, { children: [
211
+ /* @__PURE__ */ jsx(Button, { size: "xs", variant: "outline", onClick: () => setExpanded(troublePaths(options)), children: "Open failures" }),
212
+ /* @__PURE__ */ jsx(Button, { size: "xs", variant: "outline", onClick: () => setExpanded(true), children: "Expand all" }),
213
+ /* @__PURE__ */ jsx(Button, { size: "xs", variant: "outline", onClick: () => setExpanded({}), children: "Collapse all" })
214
+ ] }),
215
+ renderExpanded: (r) => r.event?.fields ? /* @__PURE__ */ jsx(PropertyList, { labelWidth: 80, children: Object.entries(r.event.fields).map(([label, value]) => /* @__PURE__ */ jsx(PropertyRow, { label, mono: true, children: value }, label)) }) : null
216
+ }
217
+ );
218
+ }
219
+ function BlockPanel({ panel, options, onAction }) {
220
+ return /* @__PURE__ */ jsx(
221
+ Block,
222
+ {
223
+ spec: { kind: panel.kind, ...options },
224
+ id: panel.id,
225
+ state: panel.state,
226
+ value: panel.value,
227
+ onAction: (action, value) => (
228
+ // An action the spec declares arrives by its own id, as every panel's does.
229
+ action === "action" ? onAction(String(value), { panelId: panel.id }) : onAction(action, { panelId: panel.id, value })
230
+ )
231
+ }
232
+ );
233
+ }
234
+ var BLOCK_PANELS = Object.fromEntries(BLOCKS.map((b) => [b.id, BlockPanel]));
235
+ function SpecChip({ chip }) {
236
+ if (chip.bound)
237
+ return /* @__PURE__ */ jsx(BoundChip, { bound: chip.bound, swatch: chip.swatch });
238
+ return /* @__PURE__ */ jsx(
239
+ Badge,
240
+ {
241
+ variant: chip.variant ?? "outline",
242
+ tone: chip.tone === "running" || chip.tone === "error" ? void 0 : chip.tone,
243
+ size: "sm",
244
+ children: chip.label
245
+ }
246
+ );
247
+ }
248
+ function SpecChips({ chips }) {
249
+ if (!chips?.length) return null;
250
+ return /* @__PURE__ */ jsx(Fragment, { children: chips.map((chip, i) => /* @__PURE__ */ jsx(SpecChip, { chip }, i)) });
251
+ }
252
+ function SpecAction({
253
+ action,
254
+ onAction,
255
+ icons,
256
+ ctx
257
+ }) {
258
+ const switchId = React.useId();
259
+ const optionLabel = (option) => action.optionLabels?.[option] ?? option;
260
+ if (action.options?.length && action.menu) {
261
+ const Trigger = action.icon ? icons[action.icon] : void 0;
262
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
263
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
264
+ Button,
265
+ {
266
+ variant: action.variant ?? "outline",
267
+ size: Trigger ? "icon-sm" : "sm",
268
+ disabled: action.disabled,
269
+ "aria-label": action.label ?? action.id,
270
+ children: Trigger ? /* @__PURE__ */ jsx(Trigger, {}) : action.label
271
+ }
272
+ ) }),
273
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", children: action.options.map((option) => /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: () => onAction(action.id, { ...ctx, option }), children: optionLabel(option) }, option)) })
274
+ ] });
275
+ }
276
+ if (action.options?.length && action.picker) {
277
+ return /* @__PURE__ */ jsxs(
278
+ Select,
279
+ {
280
+ value: action.value,
281
+ disabled: action.disabled,
282
+ onValueChange: (option) => onAction(action.id, { ...ctx, option }),
283
+ children: [
284
+ /* @__PURE__ */ jsx(SelectTrigger, { triggerSize: "sm", className: "w-auto gap-2", "aria-label": action.label ?? action.id, children: /* @__PURE__ */ jsx(SelectValue, {}) }),
285
+ /* @__PURE__ */ jsx(SelectContent, { children: action.options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option, children: optionLabel(option) }, option)) })
286
+ ]
287
+ }
288
+ );
289
+ }
290
+ if (action.options?.length) {
291
+ return /* @__PURE__ */ jsx(
292
+ ToggleGroup,
293
+ {
294
+ type: "single",
295
+ size: "sm",
296
+ value: action.value,
297
+ disabled: action.disabled,
298
+ onValueChange: (option) => option && onAction(action.id, { ...ctx, option }),
299
+ children: action.options.map((option) => /* @__PURE__ */ jsx(ToggleGroupItem, { value: option, children: optionLabel(option) }, option))
300
+ }
301
+ );
302
+ }
303
+ const Icon = action.icon ? icons[action.icon] : void 0;
304
+ const iconOnly = !action.label && Icon;
305
+ if (action.pressed != null) {
306
+ return /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
307
+ /* @__PURE__ */ jsx(Label, { htmlFor: switchId, className: "font-normal", children: action.label ?? action.id }),
308
+ /* @__PURE__ */ jsx(
309
+ Switch,
310
+ {
311
+ id: switchId,
312
+ checked: action.pressed,
313
+ disabled: action.disabled,
314
+ onCheckedChange: (pressed) => onAction(action.id, { ...ctx, pressed })
315
+ }
316
+ )
317
+ ] });
318
+ }
319
+ return /* @__PURE__ */ jsxs(
320
+ Button,
321
+ {
322
+ variant: action.variant ?? "outline",
323
+ size: iconOnly ? "icon-sm" : "sm",
324
+ disabled: action.disabled,
325
+ "aria-label": iconOnly ? action.id : void 0,
326
+ onClick: () => onAction(action.id, ctx),
327
+ children: [
328
+ Icon ? /* @__PURE__ */ jsx(Icon, {}) : null,
329
+ action.label
330
+ ]
331
+ }
332
+ );
333
+ }
334
+ function SpecActions({
335
+ actions,
336
+ onAction,
337
+ icons,
338
+ ctx
339
+ }) {
340
+ if (!actions?.length) return null;
341
+ return /* @__PURE__ */ jsx(Fragment, { children: actions.map((action) => /* @__PURE__ */ jsx(
342
+ SpecAction,
343
+ {
344
+ action,
345
+ onAction,
346
+ icons,
347
+ ctx
348
+ },
349
+ action.id
350
+ )) });
351
+ }
352
+ function LogPanel({ options }) {
353
+ const columns = options.columnTemplate ?? "48px 44px 132px minmax(0,1fr)";
354
+ return /* @__PURE__ */ jsx(Terminal, { columnTemplate: columns, children: options.lines.map((line, i) => /* @__PURE__ */ jsx(
355
+ TerminalLine,
356
+ {
357
+ level: line.level,
358
+ columns: [
359
+ line.time ?? "",
360
+ line.level ? line.level.toUpperCase() : "",
361
+ line.source ?? "",
362
+ line.message
363
+ ]
364
+ },
365
+ i
366
+ )) });
367
+ }
368
+ function ListPanel({ panel, options, onAction, icons }) {
369
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: options.items.map((item, i) => {
370
+ const Icon = item.icon ? icons[item.icon] : void 0;
371
+ const clickable = Boolean(item.action);
372
+ return /* @__PURE__ */ jsxs(
373
+ Item,
374
+ {
375
+ size: "xs",
376
+ className: cn(
377
+ "flex-nowrap gap-2 border-b border-border/55 last:border-b-0",
378
+ clickable && "cursor-pointer"
379
+ ),
380
+ onClick: clickable ? () => onAction(item.action, { panelId: panel.id, itemId: item.id }) : void 0,
381
+ children: [
382
+ item.tone || Icon ? /* @__PURE__ */ jsxs(ItemMedia, { children: [
383
+ item.tone ? /* @__PURE__ */ jsx(StatusDot, { tone: item.tone, size: "md" }) : null,
384
+ Icon ? /* @__PURE__ */ jsx(Icon, { className: "size-3.5 text-muted-foreground" }) : null
385
+ ] }) : null,
386
+ /* @__PURE__ */ jsx(ItemContent, { className: "min-w-0", children: /* @__PURE__ */ jsx(ItemTitle, { className: cn("w-auto min-w-0", item.mono && "font-mono"), children: /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: item.title }) }) }),
387
+ item.meta || item.chip ? /* @__PURE__ */ jsxs(ItemActions, { className: "min-w-0 shrink justify-end", children: [
388
+ item.meta ? /* @__PURE__ */ jsx("span", { className: "max-w-[16ch] truncate font-mono text-sm text-muted-foreground", children: item.meta }) : null,
389
+ item.chip ? /* @__PURE__ */ jsx("span", { className: "shrink-0", children: /* @__PURE__ */ jsx(SpecChip, { chip: item.chip }) }) : null
390
+ ] }) : null
391
+ ]
392
+ },
393
+ item.id ?? i
394
+ );
395
+ }) });
396
+ }
397
+ function ParamsPanel({ panel, options, onAction }) {
398
+ const emit = options.changeAction;
399
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: options.params.map((param) => /* @__PURE__ */ jsx(
400
+ ParamRow,
401
+ {
402
+ name: param.name,
403
+ type: param.type,
404
+ source: param.source,
405
+ value: param.value,
406
+ note: param.note,
407
+ invalid: param.invalid,
408
+ disabled: param.disabled,
409
+ onSourceChange: emit ? (source) => onAction(emit, {
410
+ panelId: panel.id,
411
+ param: { name: param.name, source, value: param.value }
412
+ }) : void 0,
413
+ onValueChange: emit ? (value) => onAction(emit, {
414
+ panelId: panel.id,
415
+ param: { name: param.name, source: param.source, value }
416
+ }) : void 0
417
+ },
418
+ param.name
419
+ )) });
420
+ }
421
+ var TEXT_TONE = {
422
+ default: "text-foreground",
423
+ muted: "text-muted-foreground",
424
+ success: "text-success",
425
+ warning: "text-warning",
426
+ error: "text-destructive",
427
+ info: "text-info"
428
+ };
429
+ function TextPanel({ panel, options, onAction, icons }) {
430
+ const body = /* @__PURE__ */ jsx("p", { className: cn("text-sm", TEXT_TONE[options.tone ?? "muted"]), children: options.text });
431
+ const content = options.callout ? /* @__PURE__ */ jsx(Alert, { variant: options.tone === "error" ? "destructive" : "default", children: /* @__PURE__ */ jsx(AlertDescription, { children: body }) }) : body;
432
+ if (!options.actions?.length) return content;
433
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
434
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: content }),
435
+ /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1.5", children: /* @__PURE__ */ jsx(
436
+ SpecActions,
437
+ {
438
+ actions: options.actions,
439
+ onAction,
440
+ icons,
441
+ ctx: { panelId: panel.id }
442
+ }
443
+ ) })
444
+ ] });
445
+ }
446
+
447
+ // src/registry.ts
448
+ var BUILT_IN_PANELS = {
449
+ json: JsonPanel,
450
+ code: CodePanel,
451
+ exchange: ExchangePanel,
452
+ log: LogPanel,
453
+ events: EventsPanel,
454
+ list: ListPanel,
455
+ params: ParamsPanel,
456
+ text: TextPanel
457
+ };
458
+ function resolveRegistry(extra) {
459
+ return { ...BLOCK_PANELS, ...BUILT_IN_PANELS, ...extra };
460
+ }
461
+ var RecordDescription = React.forwardRef(
462
+ ({ description, details, moreLabel = "More", lessLabel = "Less", className, ...props }, ref) => {
463
+ const [expanded, setExpanded] = React.useState(false);
464
+ const [clipped, setClipped] = React.useState(false);
465
+ const lineRef = React.useRef(null);
466
+ React.useLayoutEffect(() => {
467
+ const el = lineRef.current;
468
+ if (!el || expanded) return;
469
+ const measure = () => setClipped(el.scrollWidth - el.clientWidth > 1);
470
+ measure();
471
+ const observer = new ResizeObserver(measure);
472
+ observer.observe(el);
473
+ return () => observer.disconnect();
474
+ }, [expanded, description]);
475
+ const hasMore = clipped || expanded || (details?.length ?? 0) > 0;
476
+ return /* @__PURE__ */ jsxs(
477
+ "div",
478
+ {
479
+ ref,
480
+ className: cn("flex flex-col gap-1 border-b border-border bg-card px-3 pb-2", className),
481
+ ...props,
482
+ children: [
483
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-baseline gap-2", children: [
484
+ /* @__PURE__ */ jsx(
485
+ "p",
486
+ {
487
+ ref: lineRef,
488
+ className: cn(
489
+ "min-w-0 flex-1 text-sm text-muted-foreground",
490
+ expanded ? "whitespace-pre-line" : "truncate"
491
+ ),
492
+ children: description
493
+ }
494
+ ),
495
+ hasMore ? /* @__PURE__ */ jsx(
496
+ Button,
497
+ {
498
+ type: "button",
499
+ variant: "link",
500
+ size: "sm",
501
+ className: "h-auto shrink-0 p-0",
502
+ "aria-expanded": expanded,
503
+ onClick: () => setExpanded((open) => !open),
504
+ children: expanded ? lessLabel : moreLabel
505
+ }
506
+ ) : null
507
+ ] }),
508
+ expanded && details?.length ? /* @__PURE__ */ jsx(PropertyList, { labelWidth: 110, children: details.map((d, i) => /* @__PURE__ */ jsx(PropertyRow, { label: d.label, mono: d.mono, children: d.value }, i)) }) : null
509
+ ]
510
+ }
511
+ );
512
+ }
513
+ );
514
+ RecordDescription.displayName = "RecordDescription";
515
+ var OP_SIGN = { add: "+", remove: "\u2212", change: "~" };
516
+ var OP_CLASS = {
517
+ add: "text-success",
518
+ remove: "text-destructive",
519
+ change: "text-warning"
520
+ };
521
+ var StagedBar = React.forwardRef(
522
+ ({ items, onDiscard, onDiscardAll, hint, discardAllLabel = "Discard all", className, ...props }, ref) => /* @__PURE__ */ jsxs(
523
+ "div",
524
+ {
525
+ ref,
526
+ role: "region",
527
+ "aria-label": "Staged changes",
528
+ className: cn(
529
+ "flex min-h-control-md shrink-0 flex-wrap items-center gap-2 border-b border-border bg-primary/5 px-3 py-1",
530
+ className
531
+ ),
532
+ ...props,
533
+ children: [
534
+ /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-sm font-semibold", children: [
535
+ items.length,
536
+ " staged"
537
+ ] }),
538
+ items.map((item) => /* @__PURE__ */ jsxs(
539
+ "span",
540
+ {
541
+ className: "inline-flex max-w-full items-center gap-1.5 border border-border bg-card px-1.5 py-0.5 text-xs",
542
+ children: [
543
+ /* @__PURE__ */ jsx("span", { className: cn("font-mono", OP_CLASS[item.op] ?? "text-muted-foreground"), children: OP_SIGN[item.op] ?? item.op }),
544
+ /* @__PURE__ */ jsx("span", { className: "truncate font-mono", children: item.name }),
545
+ item.note != null ? /* @__PURE__ */ jsx("span", { className: "truncate text-muted-foreground", children: item.note }) : null,
546
+ onDiscard ? /* @__PURE__ */ jsx(
547
+ "button",
548
+ {
549
+ type: "button",
550
+ "aria-label": "Discard this change",
551
+ className: "text-muted-foreground hover:text-foreground focus-visible:outline-none",
552
+ onClick: () => onDiscard(item.id),
553
+ children: /* @__PURE__ */ jsx(X, { className: "size-3" })
554
+ }
555
+ ) : null
556
+ ]
557
+ },
558
+ item.id
559
+ )),
560
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
561
+ onDiscardAll ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: onDiscardAll, children: discardAllLabel }) : null,
562
+ hint != null ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-sm text-muted-foreground", children: hint }) : null
563
+ ]
564
+ }
565
+ )
566
+ );
567
+ StagedBar.displayName = "StagedBar";
568
+ var BoardPatchError = class extends Error {
569
+ };
570
+ function onRows(rows, id, fn, hit) {
571
+ return rows.map((row) => {
572
+ if (!row.panels.some((p) => p.id === id)) return row;
573
+ hit.found = true;
574
+ return { ...row, panels: row.panels.map((p) => p.id === id ? fn(p) : p) };
575
+ });
576
+ }
577
+ function patchPanel(panel, patch) {
578
+ if (patch.op === "update-panel") {
579
+ const { id, kind, options } = panel;
580
+ return { ...applyBlockPatch(panel, { op: "set", fields: patch.fields }), id, kind, options };
581
+ }
582
+ try {
583
+ return { ...panel, options: applyBlockPatch(panel.options ?? {}, patch.patch) };
584
+ } catch (error) {
585
+ if (error instanceof BlockPatchError) throw new BoardPatchError(`"patch-panel" on "${patch.panel}": ${error.message}`);
586
+ throw error;
587
+ }
588
+ }
589
+ function applyBoardPatch(spec, patch) {
590
+ const loose = spec;
591
+ const hit = { found: false };
592
+ const fn = (panel) => patchPanel(panel, patch);
593
+ const next = {
594
+ ...loose,
595
+ rows: onRows(loose.rows, patch.panel, fn, hit),
596
+ ...loose.tabs ? { tabs: loose.tabs.map((tab) => ({ ...tab, rows: onRows(tab.rows, patch.panel, fn, hit) })) } : {}
597
+ };
598
+ if (!hit.found) throw new BoardPatchError(`"${patch.op}": no panel "${patch.panel}" on the board.`);
599
+ return next;
600
+ }
601
+ function applyBoardPatches(spec, patches) {
602
+ return patches.reduce(applyBoardPatch, spec);
603
+ }
604
+ function isDropped(panel) {
605
+ return panel.absent?.reason === "unrecorded";
606
+ }
607
+ function UnknownPanel({ kind }) {
608
+ return /* @__PURE__ */ jsxs("div", { className: "border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
609
+ "No renderer for panel kind ",
610
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: kind }),
611
+ ". Register one, or remove it from the spec."
612
+ ] });
613
+ }
614
+ function Panel({
615
+ panel,
616
+ registry,
617
+ onAction,
618
+ icons,
619
+ gap
620
+ }) {
621
+ const Renderer = registry[panel.kind];
622
+ const body = panel.absent ? /* @__PURE__ */ jsx(AbsenceNote, { reason: panel.absent.reason, label: panel.absent.label, children: panel.absent.note }) : panel.render ?? (Renderer ? /* @__PURE__ */ jsx(
623
+ Renderer,
624
+ {
625
+ panel,
626
+ options: panel.options ?? {},
627
+ onAction,
628
+ icons,
629
+ gap
630
+ }
631
+ ) : /* @__PURE__ */ jsx(UnknownPanel, { kind: panel.kind }));
632
+ const style = panel.width ? { width: panel.width, flexShrink: 0 } : { flexGrow: panel.grow ?? 1, flexBasis: 0, minWidth: 0 };
633
+ return /* @__PURE__ */ jsx(
634
+ PanelBox,
635
+ {
636
+ title: panel.title,
637
+ aside: panel.actions?.length ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
638
+ panel.asideChip ? /* @__PURE__ */ jsx(SpecChip, { chip: panel.asideChip }) : panel.aside,
639
+ /* @__PURE__ */ jsx(
640
+ SpecActions,
641
+ {
642
+ actions: panel.actions,
643
+ onAction,
644
+ icons,
645
+ ctx: { panelId: panel.id }
646
+ }
647
+ )
648
+ ] }) : panel.asideChip ? /* @__PURE__ */ jsx(SpecChip, { chip: panel.asideChip }) : panel.aside,
649
+ flush: panel.flush || panel.absent != null,
650
+ style,
651
+ children: body
652
+ }
653
+ );
654
+ }
655
+ function Row({
656
+ row,
657
+ gap,
658
+ registry,
659
+ onAction,
660
+ icons
661
+ }) {
662
+ return /* @__PURE__ */ jsx(
663
+ "div",
664
+ {
665
+ className: cn("flex min-w-0 items-stretch", row.fill && row.height == null && "min-h-0 flex-1"),
666
+ style: { gap: row.gap ?? gap, height: row.height },
667
+ children: row.panels.filter((panel) => !isDropped(panel)).map((panel, i) => /* @__PURE__ */ jsx(
668
+ Panel,
669
+ {
670
+ panel,
671
+ registry,
672
+ onAction,
673
+ icons,
674
+ gap
675
+ },
676
+ panel.id ?? i
677
+ ))
678
+ }
679
+ );
680
+ }
681
+ function Board({
682
+ spec: given,
683
+ onAction,
684
+ registry: extraRegistry,
685
+ icons = {},
686
+ stream,
687
+ onStreamEnd,
688
+ onStreamError,
689
+ className,
690
+ ...props
691
+ }) {
692
+ const { live: spec } = useStreamedSpec(given, stream, applyBoardPatches, {
693
+ onEnd: onStreamEnd,
694
+ onError: onStreamError
695
+ });
696
+ const registry = React.useMemo(() => resolveRegistry(extraRegistry), [extraRegistry]);
697
+ const gap = spec.gap ?? 12;
698
+ const emit = React.useCallback(
699
+ (id, ctx) => onAction?.(id, ctx),
700
+ [onAction]
701
+ );
702
+ const tabs = spec.tabs?.length ? spec.tabs : null;
703
+ const inspector = spec.inspector;
704
+ const [ownTab, setOwnTab] = React.useState(spec.tab ?? tabs?.[0]?.id);
705
+ const activeTab = spec.tabAction ? spec.tab ?? tabs?.[0]?.id : ownTab;
706
+ const body = (rows, flush) => /* @__PURE__ */ jsx(
707
+ "div",
708
+ {
709
+ className: cn("flex min-h-0 flex-1 flex-col overflow-y-auto", !flush && "p-3"),
710
+ style: { gap },
711
+ children: rows.filter((row) => row.panels.some((panel) => !isDropped(panel))).map((row, i) => /* @__PURE__ */ jsx(
712
+ Row,
713
+ {
714
+ row,
715
+ gap,
716
+ registry,
717
+ onAction: emit,
718
+ icons
719
+ },
720
+ row.id ?? i
721
+ ))
722
+ }
723
+ );
724
+ const main = tabs ? /* @__PURE__ */ jsx(
725
+ TabbedPanel,
726
+ {
727
+ className: "min-h-0 flex-1 border-0 bg-transparent shadow-none",
728
+ bodyClassName: "flex min-h-0 flex-col",
729
+ activeTab,
730
+ onTabChange: (value) => spec.tabAction ? emit(spec.tabAction, { option: value }) : setOwnTab(value),
731
+ headerContent: spec.tabActions?.length ? /* @__PURE__ */ jsx(SpecActions, { actions: spec.tabActions, onAction: emit, icons }) : void 0,
732
+ tabs: tabs.map((tab) => ({
733
+ value: tab.id,
734
+ label: tab.label,
735
+ icon: tab.locked ? Lock : void 0,
736
+ disabled: tab.locked,
737
+ content: body(tab.rows, tab.flush)
738
+ }))
739
+ }
740
+ ) : body(spec.rows);
741
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-0 flex-col bg-background", className), ...props, children: [
742
+ spec.header ? /* @__PURE__ */ jsx(SpecHeader, { header: spec.header, onAction: emit, icons }) : null,
743
+ spec.header?.description != null || spec.header?.details?.length ? /* @__PURE__ */ jsx(RecordDescription, { description: spec.header.description, details: spec.header.details }) : null,
744
+ spec.staged ? /* @__PURE__ */ jsx(SpecStaged, { staged: spec.staged, onAction: emit }) : null,
745
+ inspector ? /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1", children: [
746
+ /* @__PURE__ */ jsx("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: main }),
747
+ /* @__PURE__ */ jsx(
748
+ Board,
749
+ {
750
+ className: "border-l border-border",
751
+ style: { width: inspector.width ?? 440, flexShrink: 0 },
752
+ spec: {
753
+ ...inspector.spec,
754
+ inspector: void 0,
755
+ header: inspector.spec.header && { size: "md", ...inspector.spec.header }
756
+ },
757
+ onAction: emit,
758
+ registry: extraRegistry,
759
+ icons
760
+ }
761
+ )
762
+ ] }) : main
763
+ ] });
764
+ }
765
+ function SpecStaged({
766
+ staged,
767
+ onAction
768
+ }) {
769
+ const { discardAction, discardAllAction } = staged;
770
+ return /* @__PURE__ */ jsx(
771
+ StagedBar,
772
+ {
773
+ items: staged.items,
774
+ hint: staged.hint,
775
+ onDiscard: discardAction ? (id) => onAction(discardAction, { itemId: id }) : void 0,
776
+ onDiscardAll: discardAllAction ? () => onAction(discardAllAction) : void 0
777
+ }
778
+ );
779
+ }
780
+ function SpecHeader({
781
+ header,
782
+ onAction,
783
+ icons
784
+ }) {
785
+ const last = header.crumbs.length - 1;
786
+ const crumbs = header.crumbs.map((crumb, i) => {
787
+ const action = header.crumbActions?.[i];
788
+ if (i === last && header.crumbMenu) {
789
+ const menu = header.crumbMenu;
790
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
791
+ /* @__PURE__ */ jsxs(DropdownMenuTrigger, { className: "inline-flex items-center gap-1 hover:text-primary focus-visible:outline-none", children: [
792
+ crumb,
793
+ /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 text-muted-foreground" })
794
+ ] }),
795
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", className: "max-h-96 min-w-64 overflow-y-auto", children: [
796
+ menu.placeholder ? /* @__PURE__ */ jsx("div", { className: "px-2 py-1 text-sm text-muted-foreground", children: menu.placeholder }) : null,
797
+ menu.items.map((item) => /* @__PURE__ */ jsxs(
798
+ DropdownMenuItem,
799
+ {
800
+ onSelect: () => onAction(menu.action, { itemId: item.id }),
801
+ className: cn(item.id === menu.selected && "bg-accent"),
802
+ children: [
803
+ item.tone ? /* @__PURE__ */ jsx(StatusDot, { tone: item.tone }) : null,
804
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate font-mono", children: item.label }),
805
+ item.aside ? /* @__PURE__ */ jsx("span", { className: "font-mono text-sm text-muted-foreground tabular-nums", children: item.aside }) : null,
806
+ item.id === menu.selected ? /* @__PURE__ */ jsx(Check, { className: "size-3.5 text-primary" }) : /* @__PURE__ */ jsx("span", { className: "size-3.5" })
807
+ ]
808
+ },
809
+ item.id
810
+ ))
811
+ ] })
812
+ ] }, i);
813
+ }
814
+ return action ? /* @__PURE__ */ jsx(
815
+ "button",
816
+ {
817
+ type: "button",
818
+ className: "hover:text-primary hover:underline focus-visible:outline-none",
819
+ onClick: () => onAction(action),
820
+ children: crumb
821
+ },
822
+ i
823
+ ) : crumb;
824
+ });
825
+ return /* @__PURE__ */ jsx(
826
+ RecordHeader,
827
+ {
828
+ size: header.size,
829
+ tone: header.tone,
830
+ crumbs,
831
+ chips: /* @__PURE__ */ jsx(SpecChips, { chips: header.chips }),
832
+ actions: /* @__PURE__ */ jsx(SpecActions, { actions: header.actions, onAction, icons })
833
+ }
834
+ );
835
+ }
836
+ function BoardPages({
837
+ spec,
838
+ onAction,
839
+ registry,
840
+ icons = {},
841
+ className
842
+ }) {
843
+ const first = spec.pages[0]?.id ?? "";
844
+ const [ownActive, setOwnActive] = React.useState(spec.active ?? first);
845
+ const active = spec.selectAction ? spec.active ?? first : ownActive;
846
+ const emit = React.useCallback(
847
+ (id, ctx) => onAction?.(id, ctx),
848
+ [onAction]
849
+ );
850
+ const pages = React.useMemo(
851
+ () => spec.pages.map((page) => ({
852
+ id: page.id,
853
+ title: page.title,
854
+ icon: page.icon ? icons[page.icon] : void 0,
855
+ disabled: page.disabled,
856
+ closable: page.closable,
857
+ content: /* @__PURE__ */ jsx(
858
+ Board,
859
+ {
860
+ spec: page.board,
861
+ registry,
862
+ icons,
863
+ className: "h-full",
864
+ onAction: (id, ctx) => emit(id, { ...ctx, pageId: page.id })
865
+ }
866
+ )
867
+ })),
868
+ [spec.pages, icons, registry, emit]
869
+ );
870
+ return /* @__PURE__ */ jsx(
871
+ Workbook,
872
+ {
873
+ pages,
874
+ activeId: active,
875
+ tabPosition: spec.tabPosition,
876
+ pagerPosition: spec.pagerPosition,
877
+ onSelect: (id) => {
878
+ setOwnActive(id);
879
+ if (spec.selectAction) emit(spec.selectAction, { pageId: id });
880
+ },
881
+ onAdd: spec.addAction ? () => emit(spec.addAction) : void 0,
882
+ addLabel: spec.addLabel,
883
+ onClose: spec.closeAction ? (id) => emit(spec.closeAction, { pageId: id }) : void 0,
884
+ className
885
+ }
886
+ );
887
+ }
888
+ var TONE = {
889
+ muted: "text-muted-foreground",
890
+ info: "text-info",
891
+ success: "text-success",
892
+ warning: "text-warning",
893
+ destructive: "text-destructive"
894
+ };
895
+ var AttemptClock = React.forwardRef(
896
+ ({ rows, summary, className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col", className), ...props, children: [
897
+ /* @__PURE__ */ jsxs(Table, { density: "compact", children: [
898
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
899
+ /* @__PURE__ */ jsx(TableHead, { className: "w-[7rem]", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "what" }) }),
900
+ /* @__PURE__ */ jsx(TableHead, { className: "w-[6rem]", children: "started" }),
901
+ /* @__PURE__ */ jsx(TableHead, { className: "w-[5.5rem]", children: "took" }),
902
+ /* @__PURE__ */ jsx(TableHead, { children: "what happened" })
903
+ ] }) }),
904
+ /* @__PURE__ */ jsx(TableBody, { children: rows.map((row, index) => {
905
+ const tone = row.tone ? TONE[row.tone] : void 0;
906
+ return /* @__PURE__ */ jsxs(TableRow, { children: [
907
+ /* @__PURE__ */ jsx(TableCell, { className: cn(tone, row.struck && "line-through"), children: row.label }),
908
+ /* @__PURE__ */ jsx(TableCell, { className: "font-mono tabular-nums text-muted-foreground", children: row.started }),
909
+ /* @__PURE__ */ jsx(TableCell, { className: cn("font-mono tabular-nums", tone), children: row.took }),
910
+ /* @__PURE__ */ jsx(
911
+ TableCell,
912
+ {
913
+ className: cn(row.struck && ["line-through", tone]),
914
+ children: row.what
915
+ }
916
+ )
917
+ ] }, index);
918
+ }) })
919
+ ] }),
920
+ summary != null ? /* @__PURE__ */ jsx("div", { className: "border-border border-t px-2.5 py-1.5 text-sm text-muted-foreground", children: summary }) : null
921
+ ] })
922
+ );
923
+ AttemptClock.displayName = "AttemptClock";
924
+ function TracePanel({
925
+ panel,
926
+ options,
927
+ onAction
928
+ }) {
929
+ const step = (entry, key) => /* @__PURE__ */ jsx(
930
+ TraceStep,
931
+ {
932
+ seq: entry.seq,
933
+ name: entry.name,
934
+ description: entry.description,
935
+ layer: entry.layer,
936
+ role: entry.role,
937
+ duration: entry.duration,
938
+ note: entry.note,
939
+ mark: entry.mark ? /* @__PURE__ */ jsx(MarkChip, { tone: entry.markTone, children: entry.mark }) : void 0,
940
+ palette: options.palette,
941
+ depth: entry.depth,
942
+ dim: entry.dim,
943
+ struck: entry.struck,
944
+ selected: entry.id != null && entry.id === options.selectedId,
945
+ onSelect: options.selectAction && entry.id ? () => onAction(options.selectAction, {
946
+ panelId: panel.id,
947
+ stepId: entry.id
948
+ }) : void 0
949
+ },
950
+ key
951
+ );
952
+ const draw = (entry, key) => {
953
+ if (entry.kind === "gate")
954
+ return /* @__PURE__ */ jsx(
955
+ TraceGate,
956
+ {
957
+ label: entry.label,
958
+ note: entry.note,
959
+ tone: entry.tone,
960
+ edge: entry.edge
961
+ },
962
+ key
963
+ );
964
+ if (entry.kind === "loop")
965
+ return /* @__PURE__ */ jsx(
966
+ TraceLoop,
967
+ {
968
+ label: entry.label,
969
+ summary: entry.summary,
970
+ tone: entry.tone,
971
+ children: entry.rounds.map((round, i) => draw(round, `${key}-${i}`))
972
+ },
973
+ key
974
+ );
975
+ return step(entry, key);
976
+ };
977
+ return /* @__PURE__ */ jsx(TraceList, { children: options.entries.map((entry, i) => draw(entry, `${i}`)) });
978
+ }
979
+ function TouchedPanel({ options }) {
980
+ return /* @__PURE__ */ jsx(TouchStrip, { items: options.items, palette: options.palette });
981
+ }
982
+ function AttemptsPanel({ options }) {
983
+ return /* @__PURE__ */ jsx(AttemptClock, { rows: options.rows, summary: options.summary });
984
+ }
985
+ var RUN_PANELS = {
986
+ trace: TracePanel,
987
+ touched: TouchedPanel,
988
+ attempts: AttemptsPanel,
989
+ artifacts: ArtifactsPanel,
990
+ lens: LensPanel,
991
+ clarification: ClarificationPanel
992
+ };
993
+ function ArtifactsPanel({
994
+ panel,
995
+ options,
996
+ onAction
997
+ }) {
998
+ return /* @__PURE__ */ jsx(
999
+ ArtifactTable,
1000
+ {
1001
+ files: options.files,
1002
+ onOpen: options.openAction ? (file) => onAction(options.openAction, {
1003
+ panelId: panel.id,
1004
+ itemId: String(file.digest ?? file.name)
1005
+ }) : void 0,
1006
+ onDownload: options.downloadAction ? (file) => onAction(options.downloadAction, {
1007
+ panelId: panel.id,
1008
+ itemId: String(file.digest ?? file.name)
1009
+ }) : void 0
1010
+ }
1011
+ );
1012
+ }
1013
+ function LensPanel({ panel, options, onAction }) {
1014
+ const pick = options.selectAction ? (lens) => onAction(options.selectAction, { panelId: panel.id, lens }) : void 0;
1015
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: options.sections.map((section) => /* @__PURE__ */ jsxs(
1016
+ LayerSection,
1017
+ {
1018
+ layer: section.layer,
1019
+ summary: section.summary,
1020
+ palette: options.palette,
1021
+ count: section.count ?? section.participants?.length,
1022
+ dim: section.dim,
1023
+ children: [
1024
+ (section.participants ?? []).map((participant) => /* @__PURE__ */ jsx(
1025
+ ParticipantRow,
1026
+ {
1027
+ address: participant.address,
1028
+ verdict: participant.verdict,
1029
+ note: participant.note
1030
+ },
1031
+ participant.address
1032
+ )),
1033
+ (section.rows ?? []).map((row) => /* @__PURE__ */ jsx(
1034
+ LensRow,
1035
+ {
1036
+ name: row.name,
1037
+ narrows: row.narrows,
1038
+ usage: row.usage,
1039
+ palette: options.palette,
1040
+ selected: options.selected === row.name,
1041
+ onSelect: pick
1042
+ },
1043
+ row.name
1044
+ ))
1045
+ ]
1046
+ },
1047
+ section.layer
1048
+ )) });
1049
+ }
1050
+ function ClarificationPanel({
1051
+ options
1052
+ }) {
1053
+ return /* @__PURE__ */ jsx(
1054
+ ExchangeRecord,
1055
+ {
1056
+ asker: options.asker,
1057
+ question: options.question,
1058
+ why: options.why,
1059
+ options: options.options,
1060
+ answerer: options.answerer,
1061
+ answer: options.answer,
1062
+ answerNote: options.answerNote
1063
+ }
1064
+ );
1065
+ }
1066
+
1067
+ export { ArtifactsPanel, AttemptClock, AttemptsPanel, BLOCK_PANELS, BUILT_IN_PANELS, BlockPanel, Board, BoardPages, BoardPatchError, ClarificationPanel, CodePanel, EventsPanel, ExchangePanel, JsonPanel, LensPanel, ListPanel, LogPanel, ParamsPanel, RUN_PANELS, RecordDescription, SpecAction, SpecActions, SpecChip, SpecChips, StagedBar, TextPanel, TouchedPanel, TracePanel, applyBoardPatch, applyBoardPatches, resolveRegistry };
1068
+ //# sourceMappingURL=index.js.map
1069
+ //# sourceMappingURL=index.js.map