@arbidocs/blocks 0.4.9 → 0.4.10

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 (73) hide show
  1. package/README.md +9 -0
  2. package/dist/StreamedArtifactEditor-5BMNWSS4.cjs +106 -0
  3. package/dist/StreamedArtifactEditor-5BMNWSS4.cjs.map +1 -0
  4. package/dist/StreamedArtifactEditor-6ETUHNQN.js +104 -0
  5. package/dist/StreamedArtifactEditor-6ETUHNQN.js.map +1 -0
  6. package/dist/agents/index.cjs +163 -163
  7. package/dist/agents/index.js +6 -6
  8. package/dist/artifacts/ArtifactEditor.d.ts +24 -1
  9. package/dist/artifacts/ArtifactToolbar.d.ts +3 -1
  10. package/dist/artifacts/StreamedArtifactFrame.d.ts +36 -0
  11. package/dist/artifacts/editor/index.cjs +11 -82
  12. package/dist/artifacts/editor/index.cjs.map +1 -1
  13. package/dist/artifacts/editor/index.js +2 -83
  14. package/dist/artifacts/editor/index.js.map +1 -1
  15. package/dist/artifacts/index.cjs +92 -800
  16. package/dist/artifacts/index.cjs.map +1 -1
  17. package/dist/artifacts/index.d.ts +2 -1
  18. package/dist/artifacts/index.js +3 -784
  19. package/dist/artifacts/index.js.map +1 -1
  20. package/dist/chat/index.cjs +65 -65
  21. package/dist/chat/index.js +3 -3
  22. package/dist/{chunk-JLOYWXRB.js → chunk-557EU3G4.js} +3 -3
  23. package/dist/{chunk-JLOYWXRB.js.map → chunk-557EU3G4.js.map} +1 -1
  24. package/dist/{chunk-5LUI4G5R.js → chunk-BV7FEMSI.js} +3 -3
  25. package/dist/{chunk-5LUI4G5R.js.map → chunk-BV7FEMSI.js.map} +1 -1
  26. package/dist/{chunk-CVFBSUXL.js → chunk-D5BZVKIF.js} +6 -6
  27. package/dist/{chunk-CVFBSUXL.js.map → chunk-D5BZVKIF.js.map} +1 -1
  28. package/dist/{chunk-YVIOCITQ.cjs → chunk-DCEI37AX.cjs} +3 -3
  29. package/dist/{chunk-YVIOCITQ.cjs.map → chunk-DCEI37AX.cjs.map} +1 -1
  30. package/dist/chunk-DTLOXXPN.js +831 -0
  31. package/dist/chunk-DTLOXXPN.js.map +1 -0
  32. package/dist/chunk-HSFGOA6V.js +86 -0
  33. package/dist/chunk-HSFGOA6V.js.map +1 -0
  34. package/dist/{chunk-IMA6I73C.js → chunk-ILOYJE63.js} +3 -3
  35. package/dist/{chunk-IMA6I73C.js.map → chunk-ILOYJE63.js.map} +1 -1
  36. package/dist/chunk-LOJVUGBJ.js +67 -0
  37. package/dist/chunk-LOJVUGBJ.js.map +1 -0
  38. package/dist/chunk-PVK3GAMH.cjs +852 -0
  39. package/dist/chunk-PVK3GAMH.cjs.map +1 -0
  40. package/dist/chunk-QVBZESYQ.cjs +70 -0
  41. package/dist/chunk-QVBZESYQ.cjs.map +1 -0
  42. package/dist/{chunk-67HGXV4I.cjs → chunk-RMIACB7N.cjs} +6 -6
  43. package/dist/{chunk-67HGXV4I.cjs.map → chunk-RMIACB7N.cjs.map} +1 -1
  44. package/dist/chunk-RUNQFXPH.cjs +89 -0
  45. package/dist/chunk-RUNQFXPH.cjs.map +1 -0
  46. package/dist/{chunk-TO4FAMQP.cjs → chunk-XKSFJYOD.cjs} +3 -3
  47. package/dist/{chunk-TO4FAMQP.cjs.map → chunk-XKSFJYOD.cjs.map} +1 -1
  48. package/dist/{chunk-22T6KHGB.cjs → chunk-YWSWRTGH.cjs} +4 -4
  49. package/dist/{chunk-22T6KHGB.cjs.map → chunk-YWSWRTGH.cjs.map} +1 -1
  50. package/dist/connect/index.cjs +97 -23
  51. package/dist/connect/index.cjs.map +1 -1
  52. package/dist/connect/index.d.ts +1 -0
  53. package/dist/connect/index.js +79 -6
  54. package/dist/connect/index.js.map +1 -1
  55. package/dist/connection/StreamedArtifact.d.ts +43 -0
  56. package/dist/connection/StreamedArtifactEditor.d.ts +31 -0
  57. package/dist/facts/index.cjs +1 -1
  58. package/dist/facts/index.js +1 -1
  59. package/dist/files/index.cjs +5 -5
  60. package/dist/files/index.js +7 -7
  61. package/dist/index.cjs +550 -550
  62. package/dist/index.js +17 -17
  63. package/dist/settings/index.cjs +32 -32
  64. package/dist/settings/index.js +3 -3
  65. package/dist/shell/index.cjs +33 -33
  66. package/dist/shell/index.js +3 -3
  67. package/dist/site/index.cjs +14 -14
  68. package/dist/site/index.js +2 -2
  69. package/dist/studio/index.cjs +3 -3
  70. package/dist/studio/index.js +3 -3
  71. package/dist/workspaces/index.cjs +2 -2
  72. package/dist/workspaces/index.js +2 -2
  73. package/package.json +3 -3
@@ -0,0 +1,852 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var chunkMHVNT4J3_cjs = require('./chunk-MHVNT4J3.cjs');
5
+ var lucideReact = require('lucide-react');
6
+ var ui = require('@arbidocs/react/ui');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+ var react = require('react');
9
+
10
+ var DEFAULT_ARTIFACT_COMPARE_BAR_LABELS = {
11
+ compareVs: "Compare vs.",
12
+ trackChanges: "Track changes",
13
+ trackChangesBack: "Back to editing (your comparison stays active)",
14
+ trackChangesView: "View tracked changes against Compare vs.",
15
+ flipComparison: "Flip comparison direction",
16
+ stopComparing: "Stop comparing"
17
+ };
18
+ var barButton = "inline-flex shrink-0 items-center gap-1 rounded-md px-1.5 py-0.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11 pointer-coarse:min-w-11 pointer-coarse:px-2.5";
19
+ function ArtifactCompareBar({
20
+ compareTarget,
21
+ versionLabel,
22
+ mode,
23
+ showTrackChanges,
24
+ onToggleTrackChanges,
25
+ onFlip,
26
+ onStop,
27
+ labels,
28
+ testIds
29
+ }) {
30
+ const l = { ...DEFAULT_ARTIFACT_COMPARE_BAR_LABELS, ...labels };
31
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
32
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-sm text-muted-foreground", children: l.compareVs }),
33
+ compareTarget,
34
+ versionLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-xs text-muted-foreground", children: versionLabel }),
35
+ mode === "track-changes" ? /* @__PURE__ */ jsxRuntime.jsxs(
36
+ "button",
37
+ {
38
+ type: "button",
39
+ onClick: onToggleTrackChanges,
40
+ "aria-pressed": showTrackChanges,
41
+ className: ui.cn(
42
+ barButton,
43
+ showTrackChanges ? "bg-accent text-accent-foreground hover:bg-accent/70" : "text-muted-foreground hover:bg-muted hover:text-foreground"
44
+ ),
45
+ title: showTrackChanges ? l.trackChangesBack : l.trackChangesView,
46
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.trackChanges, { testId: "track-changes-toggle" }),
47
+ children: [
48
+ showTrackChanges ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "size-3.5", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { className: "size-3.5", "aria-hidden": true }),
49
+ l.trackChanges
50
+ ]
51
+ }
52
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
53
+ "button",
54
+ {
55
+ type: "button",
56
+ onClick: onFlip,
57
+ className: ui.cn(
58
+ barButton,
59
+ "p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
60
+ ),
61
+ title: l.flipComparison,
62
+ "aria-label": l.flipComparison,
63
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftRight, { className: "size-3.5", "aria-hidden": true })
64
+ }
65
+ ),
66
+ /* @__PURE__ */ jsxRuntime.jsxs(
67
+ "button",
68
+ {
69
+ type: "button",
70
+ onClick: onStop,
71
+ className: ui.cn(
72
+ barButton,
73
+ "ml-auto text-muted-foreground hover:bg-muted hover:text-foreground"
74
+ ),
75
+ title: l.stopComparing,
76
+ children: [
77
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3", "aria-hidden": true }),
78
+ l.stopComparing
79
+ ]
80
+ }
81
+ )
82
+ ] });
83
+ }
84
+ function ArtifactEditorBody({
85
+ content,
86
+ isEditing,
87
+ comparing,
88
+ showTrackChanges,
89
+ editor,
90
+ redline,
91
+ renderMarkdown,
92
+ onSave,
93
+ canSave = true,
94
+ className,
95
+ testIds
96
+ }) {
97
+ const onKeyDown = react.useCallback(
98
+ (e) => {
99
+ if (!isEditing || !onSave) return;
100
+ if ((e.metaKey || e.ctrlKey) && !e.altKey && e.key.toLowerCase() === "s") {
101
+ e.preventDefault();
102
+ if (canSave) onSave();
103
+ }
104
+ },
105
+ [isEditing, onSave, canSave]
106
+ );
107
+ const tracking = isEditing && comparing && showTrackChanges;
108
+ return (
109
+ // The key handler only listens to bubbling keystrokes of the editor inside; the editor itself
110
+ // is the focusable element.
111
+ /* @__PURE__ */ jsxRuntime.jsx(
112
+ "div",
113
+ {
114
+ "data-slot": "artifact-body",
115
+ className: ui.cn("h-full min-h-0 overflow-auto", className),
116
+ onKeyDown,
117
+ children: !isEditing ? /* @__PURE__ */ jsxRuntime.jsx(
118
+ "div",
119
+ {
120
+ className: "p-6",
121
+ "data-slot": "artifact-rendered",
122
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.rendered, { testId: "document-rendered-markdown" }),
123
+ children: renderMarkdown(content)
124
+ }
125
+ ) : tracking ? /* @__PURE__ */ jsxRuntime.jsx(
126
+ "div",
127
+ {
128
+ className: "h-full",
129
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.trackChanges, { testId: "track-changes-panel" }),
130
+ children: redline
131
+ }
132
+ ) : editor
133
+ }
134
+ )
135
+ );
136
+ }
137
+ var DEFAULT_ARTIFACT_TOOLBAR_LABELS = {
138
+ group: "Document actions",
139
+ edit: "Edit",
140
+ cancel: "Cancel",
141
+ cancelTitle: "Cancel editing",
142
+ compare: "Compare with previous",
143
+ compareTitle: "Compare against the previous version",
144
+ saveDocument: "Save document",
145
+ saveAsVersion: "Save as a new version",
146
+ noChanges: "No changes to save",
147
+ saving: "Saving\u2026",
148
+ save: "Save",
149
+ saveVersion: "Save version",
150
+ unsaved: "Unsaved changes"
151
+ };
152
+ function ArtifactToolbar({
153
+ isEditing,
154
+ isDraft = false,
155
+ compact = false,
156
+ hasChanges,
157
+ isSaving,
158
+ canCompare,
159
+ editDisabled = false,
160
+ onStartEdit,
161
+ onCancel,
162
+ onCompare,
163
+ onSave,
164
+ className,
165
+ labels,
166
+ testIds
167
+ }) {
168
+ const l = { ...DEFAULT_ARTIFACT_TOOLBAR_LABELS, ...labels };
169
+ const group = (children) => /* @__PURE__ */ jsxRuntime.jsx(
170
+ "div",
171
+ {
172
+ role: "group",
173
+ "aria-label": l.group,
174
+ "data-slot": "artifact-toolbar",
175
+ className: ui.cn("flex items-center gap-2", compact && "gap-1", className),
176
+ children
177
+ }
178
+ );
179
+ if (!isEditing) {
180
+ return group(
181
+ /* @__PURE__ */ jsxRuntime.jsxs(
182
+ ui.Button,
183
+ {
184
+ onClick: onStartEdit,
185
+ disabled: editDisabled,
186
+ variant: "outline",
187
+ size: compact ? "icon" : "sm",
188
+ title: l.edit,
189
+ "aria-label": l.edit,
190
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.edit, { testId: "edit-document-button" }),
191
+ className: "pointer-coarse:min-h-11 pointer-coarse:min-w-11",
192
+ children: [
193
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "size-4", "aria-hidden": true }),
194
+ !compact && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", children: l.edit })
195
+ ]
196
+ }
197
+ )
198
+ );
199
+ }
200
+ return group(
201
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
202
+ !isDraft && /* @__PURE__ */ jsxRuntime.jsxs(
203
+ ui.Button,
204
+ {
205
+ onClick: onCancel,
206
+ variant: "outline",
207
+ size: "sm",
208
+ title: l.cancelTitle,
209
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.cancel, { testId: "cancel-edit-button" }),
210
+ className: "pointer-coarse:min-h-11",
211
+ children: [
212
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-4", "aria-hidden": true }),
213
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", children: l.cancel })
214
+ ]
215
+ }
216
+ ),
217
+ canCompare && /* @__PURE__ */ jsxRuntime.jsxs(
218
+ ui.Button,
219
+ {
220
+ onClick: onCompare,
221
+ variant: "outline",
222
+ size: compact ? "icon" : "sm",
223
+ title: l.compareTitle,
224
+ "aria-label": l.compare,
225
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.compare, { testId: "compare-button" }),
226
+ className: "pointer-coarse:min-h-11 pointer-coarse:min-w-11",
227
+ children: [
228
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitCompare, { className: "size-4", "aria-hidden": true }),
229
+ !compact && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", children: l.compare })
230
+ ]
231
+ }
232
+ ),
233
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
234
+ /* @__PURE__ */ jsxRuntime.jsxs(
235
+ ui.Button,
236
+ {
237
+ onClick: onSave,
238
+ variant: hasChanges ? "default" : "outline",
239
+ size: "sm",
240
+ title: hasChanges ? isDraft ? l.saveDocument : l.saveAsVersion : l.noChanges,
241
+ disabled: !hasChanges || isSaving,
242
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.save, { testId: "save-document-button" }),
243
+ className: "pointer-coarse:min-h-11",
244
+ children: [
245
+ isSaving ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-4", "aria-hidden": true }),
246
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", children: isSaving ? l.saving : isDraft ? l.save : l.saveVersion })
247
+ ]
248
+ }
249
+ ),
250
+ hasChanges && !isSaving && /* @__PURE__ */ jsxRuntime.jsx(
251
+ "span",
252
+ {
253
+ className: "absolute -right-1 -top-1 size-2.5 rounded-full bg-primary ring-2 ring-background",
254
+ "aria-hidden": true,
255
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.unsavedDot, { testId: "unsaved-changes-dot" })
256
+ }
257
+ )
258
+ ] }),
259
+ /* @__PURE__ */ jsxRuntime.jsx("span", { role: "status", className: "sr-only", children: hasChanges && !isSaving ? l.unsaved : "" })
260
+ ] })
261
+ );
262
+ }
263
+ var DEFAULT_ARTIFACT_VERSION_BAR_LABELS = {
264
+ group: "Versions",
265
+ position: (index, total) => `Version ${index} of ${total}`,
266
+ only: "Version 1",
267
+ latest: "Latest",
268
+ select: "Open a version",
269
+ option: (index, date, isCurrent) => `Version ${index} \xB7 ${date}${isCurrent ? " (open)" : ""}`,
270
+ compare: "Compare with previous",
271
+ compareTitle: "Compare this version against the one it was saved from"
272
+ };
273
+ function ArtifactVersionBar({
274
+ versions,
275
+ currentId,
276
+ formatDate,
277
+ onOpen,
278
+ onCompare,
279
+ className,
280
+ labels,
281
+ testIds
282
+ }) {
283
+ const l = { ...DEFAULT_ARTIFACT_VERSION_BAR_LABELS, ...labels };
284
+ const index = versions.findIndex((v) => v.id === currentId);
285
+ const isLatest = index === versions.length - 1;
286
+ return /* @__PURE__ */ jsxRuntime.jsxs(
287
+ "div",
288
+ {
289
+ role: "group",
290
+ "aria-label": l.group,
291
+ "data-slot": "artifact-version-bar",
292
+ className: ui.cn("flex min-w-0 flex-wrap items-center gap-2 text-sm", className),
293
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.root, { testId: "artifact-version-bar" }),
294
+ children: [
295
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
296
+ /* @__PURE__ */ jsxRuntime.jsx(
297
+ "span",
298
+ {
299
+ className: "shrink-0 font-medium text-foreground",
300
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.position, { testId: "artifact-version-position" }),
301
+ children: versions.length > 1 && index >= 0 ? l.position(index + 1, versions.length) : l.only
302
+ }
303
+ ),
304
+ versions.length > 1 && index >= 0 && isLatest && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded-full bg-accent px-2 py-0.5 text-xs font-medium text-accent-foreground", children: l.latest }),
305
+ versions.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
306
+ "select",
307
+ {
308
+ "aria-label": l.select,
309
+ value: currentId,
310
+ onChange: (e) => onOpen(e.target.value),
311
+ className: "min-w-0 max-w-full rounded-md border border-input bg-background px-2 py-1 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11 pointer-coarse:text-base",
312
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.select, { testId: "artifact-version-select" }),
313
+ children: versions.map((v, i) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: v.id, children: l.option(i + 1, formatDate(v.createdAt), v.id === currentId) }, v.id))
314
+ }
315
+ ),
316
+ onCompare && /* @__PURE__ */ jsxRuntime.jsxs(
317
+ ui.Button,
318
+ {
319
+ variant: "ghost",
320
+ size: "sm",
321
+ onClick: onCompare,
322
+ title: l.compareTitle,
323
+ className: "pointer-coarse:min-h-11",
324
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.compare, { testId: "artifact-version-compare" }),
325
+ children: [
326
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitCompare, { className: "size-4", "aria-hidden": true }),
327
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", children: l.compare })
328
+ ]
329
+ }
330
+ )
331
+ ]
332
+ }
333
+ );
334
+ }
335
+ var DEFAULT_ARTIFACT_EDITOR_STATUS_LABELS = {
336
+ preparing: "Preparing editor\u2026",
337
+ error: "The document couldn't be prepared for editing.",
338
+ retry: "Try again"
339
+ };
340
+ var defaultFormatDate = (iso) => {
341
+ const date = new Date(iso);
342
+ return Number.isNaN(date.getTime()) ? iso : date.toLocaleString();
343
+ };
344
+ function ArtifactEditor({
345
+ content,
346
+ isEditing,
347
+ hasChanges,
348
+ isSaving,
349
+ isDraft = false,
350
+ compact = false,
351
+ canCompare,
352
+ comparing,
353
+ compareId,
354
+ showTrackChanges,
355
+ status = "ready",
356
+ onRetry,
357
+ versions = [],
358
+ currentVersionId = "",
359
+ onStartEdit,
360
+ onCancel,
361
+ onSave,
362
+ onCompare,
363
+ onStopCompare,
364
+ onToggleTrackChanges,
365
+ onOpenVersion,
366
+ formatDate = defaultFormatDate,
367
+ editor,
368
+ redline,
369
+ renderMarkdown,
370
+ actions,
371
+ className,
372
+ labels,
373
+ testIds
374
+ }) {
375
+ const compared = versions.findIndex((v) => v.id === compareId);
376
+ const unavailable = status !== "ready";
377
+ const statusLabels = { ...DEFAULT_ARTIFACT_EDITOR_STATUS_LABELS, ...labels?.status };
378
+ return /* @__PURE__ */ jsxRuntime.jsxs(
379
+ "div",
380
+ {
381
+ "data-slot": "artifact-editor",
382
+ className: ui.cn("flex h-full max-h-dvh min-h-0 flex-col bg-background", className),
383
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.root, { testId: "artifact-editor" }),
384
+ children: [
385
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2", children: [
386
+ versions.length > 0 && onOpenVersion ? /* @__PURE__ */ jsxRuntime.jsx(
387
+ ArtifactVersionBar,
388
+ {
389
+ versions,
390
+ currentId: currentVersionId,
391
+ formatDate,
392
+ onOpen: onOpenVersion,
393
+ onCompare: canCompare && !isEditing && !unavailable ? onCompare : void 0,
394
+ labels: labels?.versions,
395
+ testIds: testIds?.versions
396
+ }
397
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
398
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
399
+ /* @__PURE__ */ jsxRuntime.jsx(
400
+ ArtifactToolbar,
401
+ {
402
+ isEditing,
403
+ isDraft,
404
+ compact,
405
+ hasChanges,
406
+ isSaving,
407
+ canCompare: canCompare && !unavailable && (isEditing || !(versions.length > 0 && onOpenVersion)),
408
+ editDisabled: unavailable,
409
+ onStartEdit,
410
+ onCancel,
411
+ onCompare,
412
+ onSave,
413
+ labels: labels?.toolbar
414
+ }
415
+ ),
416
+ actions
417
+ ] })
418
+ ] }),
419
+ comparing && /* @__PURE__ */ jsxRuntime.jsx(
420
+ "div",
421
+ {
422
+ className: "flex flex-wrap items-center gap-1.5 border-b border-border px-3 py-1.5",
423
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.compareRow, { testId: "artifact-compare-row" }),
424
+ children: /* @__PURE__ */ jsxRuntime.jsx(
425
+ ArtifactCompareBar,
426
+ {
427
+ compareTarget: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-sm font-medium text-foreground", children: compared >= 0 ? versions[compared].name : "" }),
428
+ versionLabel: compared >= 0 && versions.length > 1 ? `v${compared + 1}` : null,
429
+ mode: "track-changes",
430
+ showTrackChanges,
431
+ onToggleTrackChanges,
432
+ onFlip: onStopCompare,
433
+ onStop: onStopCompare,
434
+ labels: labels?.compare
435
+ }
436
+ )
437
+ }
438
+ ),
439
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: unavailable ? status === "error" ? /* @__PURE__ */ jsxRuntime.jsxs(
440
+ "div",
441
+ {
442
+ role: "alert",
443
+ className: "flex h-full flex-col items-center justify-center gap-3 p-6 text-center text-sm",
444
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.error, { testId: "artifact-editor-error" }),
445
+ children: [
446
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground", children: statusLabels.error }),
447
+ onRetry && /* @__PURE__ */ jsxRuntime.jsx(
448
+ ui.Button,
449
+ {
450
+ variant: "outline",
451
+ size: "sm",
452
+ onClick: onRetry,
453
+ className: "pointer-coarse:min-h-11",
454
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.retry, { testId: "artifact-editor-retry" }),
455
+ children: statusLabels.retry
456
+ }
457
+ )
458
+ ]
459
+ }
460
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
461
+ "p",
462
+ {
463
+ role: "status",
464
+ className: "flex h-full items-center justify-center gap-2 p-6 text-sm text-muted-foreground",
465
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.preparing, { testId: "artifact-editor-preparing" }),
466
+ children: [
467
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin", "aria-hidden": true }),
468
+ statusLabels.preparing
469
+ ]
470
+ }
471
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
472
+ ArtifactEditorBody,
473
+ {
474
+ content,
475
+ isEditing,
476
+ comparing,
477
+ showTrackChanges,
478
+ editor,
479
+ redline,
480
+ renderMarkdown,
481
+ onSave,
482
+ canSave: hasChanges && !isSaving,
483
+ testIds: testIds?.body
484
+ }
485
+ ) })
486
+ ]
487
+ }
488
+ );
489
+ }
490
+ var DEFAULT_REDLINE_LABELS = {
491
+ flipComparison: "Flip comparison",
492
+ noDocument: "No document selected for comparison.",
493
+ noChangesYet: "No changes yet \u2014 start editing to see redlined differences here.",
494
+ identical: "Documents are identical.",
495
+ unavailable: "Document text not available for comparison.",
496
+ revertMove: "Undo this move (revert both ends)",
497
+ revertReplace: "Undo this edit",
498
+ revertAdd: "Undo this insertion",
499
+ revertRemove: "Undo this deletion",
500
+ tracked: "Tracked changes",
501
+ computing: "Comparing\u2026"
502
+ };
503
+ function RedlineFrame({ header, children }) {
504
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", "data-slot": "redline-frame", children: [
505
+ header,
506
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-auto text-sm leading-relaxed", children })
507
+ ] });
508
+ }
509
+ function RedlineHeader({ base, compare, onFlip, labels }) {
510
+ const l = { ...DEFAULT_REDLINE_LABELS, ...labels };
511
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b border-border bg-muted px-3 py-2", children: [
512
+ base,
513
+ /* @__PURE__ */ jsxRuntime.jsx(
514
+ ui.Button,
515
+ {
516
+ variant: "ghost",
517
+ size: "icon",
518
+ className: "size-6 shrink-0 pointer-coarse:size-11",
519
+ onClick: onFlip,
520
+ title: l.flipComparison,
521
+ "aria-label": l.flipComparison,
522
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftRight, { className: "size-3.5" })
523
+ }
524
+ ),
525
+ compare
526
+ ] });
527
+ }
528
+ function RedlineStatus({
529
+ kind,
530
+ reviewMode,
531
+ labels
532
+ }) {
533
+ const l = { ...DEFAULT_REDLINE_LABELS, ...labels };
534
+ const text = kind === "idle" ? l.noDocument : kind === "identical" ? reviewMode ? l.noChangesYet : l.identical : l.unavailable;
535
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-sm text-muted-foreground", children: text });
536
+ }
537
+ function RedlineComputing({ children }) {
538
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children });
539
+ }
540
+ function RedlineDocument({ children, bodyRef, gutter }) {
541
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
542
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: bodyRef, className: "mx-auto max-w-3xl px-6 py-4 pr-14", children }),
543
+ gutter
544
+ ] });
545
+ }
546
+ var MARK_TONE = {
547
+ del: {
548
+ base: "font-semibold text-red-600 line-through decoration-2 dark:text-red-400",
549
+ move: "font-semibold text-emerald-600 line-through decoration-2 dark:text-emerald-400"
550
+ },
551
+ ins: {
552
+ base: "font-semibold text-blue-600 underline decoration-2 dark:text-blue-400",
553
+ move: "font-semibold text-emerald-600 underline decoration-2 dark:text-emerald-400"
554
+ }
555
+ };
556
+ function RedlineMark({
557
+ as: Tag,
558
+ isMove,
559
+ children,
560
+ ...props
561
+ }) {
562
+ const cls = MARK_TONE[Tag][isMove ? "move" : "base"];
563
+ return /* @__PURE__ */ jsxRuntime.jsx(Tag, { className: cls, ...props, children });
564
+ }
565
+ var REVERT_TONE = {
566
+ move: "border-emerald-600 text-emerald-700 hover:bg-emerald-50 dark:border-emerald-400 dark:text-emerald-300 dark:hover:bg-emerald-950/40",
567
+ add: "border-blue-600 text-blue-700 hover:bg-blue-50 dark:border-blue-400 dark:text-blue-300 dark:hover:bg-blue-950/40",
568
+ replace: "border-blue-600 text-blue-700 hover:bg-blue-50 dark:border-blue-400 dark:text-blue-300 dark:hover:bg-blue-950/40",
569
+ remove: "border-red-600 text-red-700 hover:bg-red-50 dark:border-red-400 dark:text-red-300 dark:hover:bg-red-950/40"
570
+ };
571
+ function RedlineRevertGutter({
572
+ markers,
573
+ onRevert,
574
+ labels,
575
+ testId
576
+ }) {
577
+ if (markers.length === 0) return null;
578
+ const l = { ...DEFAULT_REDLINE_LABELS, ...labels };
579
+ const revertTitle = {
580
+ move: l.revertMove,
581
+ replace: l.revertReplace,
582
+ add: l.revertAdd,
583
+ remove: l.revertRemove
584
+ };
585
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute right-2 top-0 w-9", "data-slot": "redline-gutter", children: markers.map((m) => /* @__PURE__ */ jsxRuntime.jsx(
586
+ "button",
587
+ {
588
+ type: "button",
589
+ onClick: () => onRevert(m.cid),
590
+ title: revertTitle[m.kind],
591
+ "aria-label": revertTitle[m.kind],
592
+ style: { top: m.top - 2 },
593
+ className: ui.cn(
594
+ "pointer-events-auto absolute right-0 inline-flex h-6 w-7 items-center justify-center rounded-md border bg-background transition-colors pointer-coarse:h-11 pointer-coarse:w-11",
595
+ REVERT_TONE[m.kind]
596
+ ),
597
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testId?.(m.cid), { testId: `redline-revert-${m.cid}` }),
598
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { className: "size-3.5" })
599
+ },
600
+ m.cid
601
+ )) });
602
+ }
603
+ function kindFromCid(cid) {
604
+ switch (cid?.[0]) {
605
+ case "p":
606
+ return "replace";
607
+ case "r":
608
+ return "remove";
609
+ case "a":
610
+ return "add";
611
+ case "m":
612
+ return "move";
613
+ default:
614
+ return null;
615
+ }
616
+ }
617
+ var MARKER_MIN_GAP = 26;
618
+ function ArtifactRedlineView({
619
+ state,
620
+ renderMarkdown,
621
+ onRevert,
622
+ header,
623
+ labels,
624
+ testIds
625
+ }) {
626
+ const l = { ...DEFAULT_REDLINE_LABELS, ...labels };
627
+ const reviewMode = typeof onRevert === "function";
628
+ const bodyRef = react.useRef(null);
629
+ const [markers, setMarkers] = react.useState([]);
630
+ const regionKinds = react.useMemo(
631
+ () => state.kind === "ready" ? new Map(state.regions.map((r) => [r.id, r.kind])) : null,
632
+ [state]
633
+ );
634
+ const components = react.useMemo(() => {
635
+ const isMove = (cid) => (regionKinds?.get(cid ?? "") ?? kindFromCid(cid)) === "move";
636
+ return {
637
+ del: ({ children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(RedlineMark, { as: "del", isMove: isMove(props["data-cid"]), ...props, children }),
638
+ ins: ({ children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(RedlineMark, { as: "ins", isMove: isMove(props["data-cid"]), ...props, children })
639
+ };
640
+ }, [regionKinds]);
641
+ react.useLayoutEffect(() => {
642
+ const host = bodyRef.current;
643
+ if (!reviewMode || state.kind !== "ready" || !host) {
644
+ setMarkers([]);
645
+ return;
646
+ }
647
+ const hostTop = host.getBoundingClientRect().top;
648
+ const seen = /* @__PURE__ */ new Map();
649
+ host.querySelectorAll("[data-cid]").forEach((el) => {
650
+ const cid = el.dataset.cid;
651
+ if (!cid || seen.has(cid)) return;
652
+ seen.set(cid, {
653
+ top: el.getBoundingClientRect().top - hostTop,
654
+ kind: regionKinds?.get(cid) ?? kindFromCid(cid) ?? "replace"
655
+ });
656
+ });
657
+ const sorted = Array.from(seen, ([cid, v]) => ({ cid, ...v })).sort((a, b) => a.top - b.top);
658
+ const spaced = [];
659
+ for (const m of sorted) {
660
+ const prev = spaced[spaced.length - 1];
661
+ spaced.push({
662
+ ...m,
663
+ top: prev && m.top - prev.top < MARKER_MIN_GAP ? prev.top + MARKER_MIN_GAP : m.top
664
+ });
665
+ }
666
+ setMarkers(spaced);
667
+ }, [reviewMode, state, regionKinds]);
668
+ return /* @__PURE__ */ jsxRuntime.jsx(
669
+ "section",
670
+ {
671
+ "aria-label": l.tracked,
672
+ className: "h-full",
673
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.root, { testId: "artifact-redline" }),
674
+ children: /* @__PURE__ */ jsxRuntime.jsx(RedlineFrame, { header, children: state.kind === "idle" || state.kind === "identical" || state.kind === "unavailable" ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", className: "h-full", children: /* @__PURE__ */ jsxRuntime.jsx(RedlineStatus, { kind: state.kind, reviewMode, labels }) }) : state.kind === "computing" ? /* @__PURE__ */ jsxRuntime.jsxs(RedlineComputing, { children: [
675
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-5 animate-spin text-muted-foreground", "aria-hidden": true }),
676
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", role: "status", children: l.computing })
677
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
678
+ RedlineDocument,
679
+ {
680
+ bodyRef,
681
+ gutter: reviewMode ? /* @__PURE__ */ jsxRuntime.jsx(
682
+ RedlineRevertGutter,
683
+ {
684
+ markers,
685
+ onRevert,
686
+ labels,
687
+ testId: testIds?.revert
688
+ }
689
+ ) : null,
690
+ children: renderMarkdown(state.markdown, components)
691
+ }
692
+ ) })
693
+ }
694
+ );
695
+ }
696
+ var DEFAULT_VERSION_TIMELINE_LABELS = {
697
+ emptyLive: "No earlier versions yet. When you ask the assistant for a change, the previous version is kept here.",
698
+ emptyDocument: "No earlier versions yet. Editing this draft and saving creates a new version here.",
699
+ untitled: "Untitled",
700
+ latest: "Latest",
701
+ viewing: "Viewing",
702
+ current: "Current",
703
+ version: (n) => `Version ${n}`,
704
+ branchedFrom: (n) => `branched from Version ${n}`,
705
+ open: "Open",
706
+ compare: "Compare"
707
+ };
708
+ function VersionTimeline({
709
+ versions,
710
+ currentId,
711
+ live = false,
712
+ formatDate,
713
+ onOpen,
714
+ onCompare,
715
+ className,
716
+ labels,
717
+ testIds
718
+ }) {
719
+ const l = { ...DEFAULT_VERSION_TIMELINE_LABELS, ...labels };
720
+ if (versions.length <= 1) {
721
+ return /* @__PURE__ */ jsxRuntime.jsx(
722
+ "div",
723
+ {
724
+ className: ui.cn("p-6 text-sm text-muted-foreground", className),
725
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.empty, { testId: "version-timeline-empty" }),
726
+ children: live ? l.emptyLive : l.emptyDocument
727
+ }
728
+ );
729
+ }
730
+ const numberById = /* @__PURE__ */ new Map();
731
+ versions.forEach((v, i) => numberById.set(v.id, i + 1));
732
+ const canCompare = !live && !!onCompare;
733
+ return /* @__PURE__ */ jsxRuntime.jsx(
734
+ "div",
735
+ {
736
+ className: ui.cn("h-full overflow-auto p-4", className),
737
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.root, { testId: "version-timeline" }),
738
+ children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "mx-auto max-w-2xl space-y-1", children: versions.map((v, i) => {
739
+ const isCurrent = v.id === currentId;
740
+ const isLatest = i === versions.length - 1;
741
+ const parentNumber = v.parentId ? numberById.get(v.parentId) : void 0;
742
+ const branchedFrom = parentNumber !== void 0 && parentNumber !== i ? parentNumber : null;
743
+ const badge = !isCurrent ? null : live ? isLatest ? l.latest : l.viewing : l.current;
744
+ const name = live ? (v.name || l.untitled).replace(/\.[A-Za-z0-9]+$/, "") : v.name || l.untitled;
745
+ return /* @__PURE__ */ jsxRuntime.jsxs(
746
+ "li",
747
+ {
748
+ className: ui.cn(
749
+ "flex items-center gap-3 rounded-md px-3 py-2.5",
750
+ isCurrent && "bg-accent"
751
+ ),
752
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.row?.(v.id), { testId: `version-row-${v.id}` }),
753
+ children: [
754
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
755
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
756
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
757
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-foreground", children: l.version(i + 1) }),
758
+ badge && /* @__PURE__ */ jsxRuntime.jsx(
759
+ "span",
760
+ {
761
+ className: "rounded-full bg-background px-2 py-0.5 text-xs font-medium text-accent-foreground",
762
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.currentBadge, {
763
+ testId: "version-current-badge"
764
+ }),
765
+ children: badge
766
+ }
767
+ )
768
+ ] }),
769
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "truncate text-sm text-muted-foreground", children: [
770
+ name,
771
+ " \xB7 ",
772
+ formatDate(v.createdAt),
773
+ branchedFrom !== null && /* @__PURE__ */ jsxRuntime.jsxs(
774
+ "span",
775
+ {
776
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.branch?.(v.id), {
777
+ testId: `version-branch-${v.id}`
778
+ }),
779
+ children: [
780
+ " ",
781
+ "\xB7 ",
782
+ l.branchedFrom(branchedFrom)
783
+ ]
784
+ }
785
+ )
786
+ ] })
787
+ ] }),
788
+ !isCurrent && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
789
+ /* @__PURE__ */ jsxRuntime.jsxs(
790
+ "button",
791
+ {
792
+ type: "button",
793
+ onClick: () => onOpen(v.id),
794
+ className: "inline-flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
795
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.open?.(v.id), {
796
+ testId: `open-version-${v.id}`
797
+ }),
798
+ children: [
799
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "size-3.5" }),
800
+ " ",
801
+ l.open
802
+ ]
803
+ }
804
+ ),
805
+ canCompare && /* @__PURE__ */ jsxRuntime.jsxs(
806
+ "button",
807
+ {
808
+ type: "button",
809
+ onClick: () => onCompare(v.id),
810
+ className: "inline-flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-sm font-medium text-primary transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
811
+ "data-testid": chunkMHVNT4J3_cjs.testIdOr(testIds?.compare?.(v.id), {
812
+ testId: `compare-version-${v.id}`
813
+ }),
814
+ children: [
815
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitCompare, { className: "size-3.5" }),
816
+ " ",
817
+ l.compare
818
+ ]
819
+ }
820
+ )
821
+ ] })
822
+ ]
823
+ },
824
+ v.id
825
+ );
826
+ }) })
827
+ }
828
+ );
829
+ }
830
+
831
+ exports.ArtifactCompareBar = ArtifactCompareBar;
832
+ exports.ArtifactEditor = ArtifactEditor;
833
+ exports.ArtifactEditorBody = ArtifactEditorBody;
834
+ exports.ArtifactRedlineView = ArtifactRedlineView;
835
+ exports.ArtifactToolbar = ArtifactToolbar;
836
+ exports.ArtifactVersionBar = ArtifactVersionBar;
837
+ exports.DEFAULT_ARTIFACT_COMPARE_BAR_LABELS = DEFAULT_ARTIFACT_COMPARE_BAR_LABELS;
838
+ exports.DEFAULT_ARTIFACT_EDITOR_STATUS_LABELS = DEFAULT_ARTIFACT_EDITOR_STATUS_LABELS;
839
+ exports.DEFAULT_ARTIFACT_TOOLBAR_LABELS = DEFAULT_ARTIFACT_TOOLBAR_LABELS;
840
+ exports.DEFAULT_ARTIFACT_VERSION_BAR_LABELS = DEFAULT_ARTIFACT_VERSION_BAR_LABELS;
841
+ exports.DEFAULT_REDLINE_LABELS = DEFAULT_REDLINE_LABELS;
842
+ exports.DEFAULT_VERSION_TIMELINE_LABELS = DEFAULT_VERSION_TIMELINE_LABELS;
843
+ exports.RedlineComputing = RedlineComputing;
844
+ exports.RedlineDocument = RedlineDocument;
845
+ exports.RedlineFrame = RedlineFrame;
846
+ exports.RedlineHeader = RedlineHeader;
847
+ exports.RedlineMark = RedlineMark;
848
+ exports.RedlineRevertGutter = RedlineRevertGutter;
849
+ exports.RedlineStatus = RedlineStatus;
850
+ exports.VersionTimeline = VersionTimeline;
851
+ //# sourceMappingURL=chunk-PVK3GAMH.cjs.map
852
+ //# sourceMappingURL=chunk-PVK3GAMH.cjs.map