@arbidocs/blocks 0.4.9 → 0.4.11

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 (37) 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/artifacts/ArtifactEditor.d.ts +24 -1
  7. package/dist/artifacts/ArtifactToolbar.d.ts +3 -1
  8. package/dist/artifacts/StreamedArtifactFrame.d.ts +36 -0
  9. package/dist/artifacts/editor/index.cjs +11 -82
  10. package/dist/artifacts/editor/index.cjs.map +1 -1
  11. package/dist/artifacts/editor/index.js +2 -83
  12. package/dist/artifacts/editor/index.js.map +1 -1
  13. package/dist/artifacts/index.cjs +92 -800
  14. package/dist/artifacts/index.cjs.map +1 -1
  15. package/dist/artifacts/index.d.ts +2 -1
  16. package/dist/artifacts/index.js +3 -784
  17. package/dist/artifacts/index.js.map +1 -1
  18. package/dist/chunk-DTLOXXPN.js +831 -0
  19. package/dist/chunk-DTLOXXPN.js.map +1 -0
  20. package/dist/chunk-HSFGOA6V.js +86 -0
  21. package/dist/chunk-HSFGOA6V.js.map +1 -0
  22. package/dist/chunk-LOJVUGBJ.js +67 -0
  23. package/dist/chunk-LOJVUGBJ.js.map +1 -0
  24. package/dist/chunk-PVK3GAMH.cjs +852 -0
  25. package/dist/chunk-PVK3GAMH.cjs.map +1 -0
  26. package/dist/chunk-QVBZESYQ.cjs +70 -0
  27. package/dist/chunk-QVBZESYQ.cjs.map +1 -0
  28. package/dist/chunk-RUNQFXPH.cjs +89 -0
  29. package/dist/chunk-RUNQFXPH.cjs.map +1 -0
  30. package/dist/connect/index.cjs +74 -0
  31. package/dist/connect/index.cjs.map +1 -1
  32. package/dist/connect/index.d.ts +1 -0
  33. package/dist/connect/index.js +76 -3
  34. package/dist/connect/index.js.map +1 -1
  35. package/dist/connection/StreamedArtifact.d.ts +43 -0
  36. package/dist/connection/StreamedArtifactEditor.d.ts +31 -0
  37. package/package.json +3 -3
package/README.md CHANGED
@@ -148,6 +148,15 @@ Every part takes `labels` and `testIds`; Mod+S saves while editing; touch target
148
148
  editor needs `@mdxeditor/editor` (optional peer) and is heavy (mount it behind `lazy`) and needs the global `Prism` defined before it loads (`@lexical/code` reads it while it evaluates): in the module that lazily imports the editor, import first a side-effect module with `import Prism from 'prismjs'; globalThis.Prism = Prism`. A library cannot order that reliably across bundlers.
149
149
  See `examples/custom-ui/ArtifactPage.tsx` for a custom editing surface on in-memory data.
150
150
 
151
+ An agent's draft from stream to editor is one part: `StreamedArtifact` from
152
+ `@arbidocs/blocks/connect` shows the live canvas, then "Preparing editor..." while the finished
153
+ draft is stored and parsed, then the editor on the stored version (the presentational switch is
154
+ `StreamedArtifactFrame` in `/artifacts`; the phase comes from `useStreamedArtifact`).
155
+
156
+ ```tsx
157
+ <StreamedArtifact artifacts={task.artifacts} workspaceId={workspaceId} busy={task.status === 'running'} error={task.error} />
158
+ ```
159
+
151
160
  ## Editorial site parts
152
161
 
153
162
  `@arbidocs/blocks/site` (and the root) carry the layout parts for static marketing pages:
@@ -0,0 +1,106 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var chunkRUNQFXPH_cjs = require('./chunk-RUNQFXPH.cjs');
5
+ var chunkPVK3GAMH_cjs = require('./chunk-PVK3GAMH.cjs');
6
+ require('./chunk-QVBZESYQ.cjs');
7
+ require('./chunk-MHVNT4J3.cjs');
8
+ var react = require('react');
9
+ var lucideReact = require('lucide-react');
10
+ var ui = require('@arbidocs/react/ui');
11
+ var artifacts = require('@arbidocs/react/artifacts');
12
+ var jsxRuntime = require('react/jsx-runtime');
13
+
14
+ function StreamedArtifactEditor({
15
+ workspaceId,
16
+ docId,
17
+ title,
18
+ testId,
19
+ className,
20
+ editorProps,
21
+ onSaved,
22
+ onSaveError,
23
+ actions,
24
+ hideDefaultActions,
25
+ labels
26
+ }) {
27
+ const [openId, setOpenId] = react.useState(docId);
28
+ const s = artifacts.useArtifactSession({
29
+ workspaceId,
30
+ docId: openId,
31
+ title,
32
+ onSaved: ({ docId: next }) => {
33
+ if (next) setOpenId(next);
34
+ onSaved?.(next);
35
+ },
36
+ onSaveError
37
+ });
38
+ const copy = () => void navigator.clipboard.writeText(s.content);
39
+ const download = () => {
40
+ const url = URL.createObjectURL(new Blob([s.content], { type: "text/markdown" }));
41
+ const a = document.createElement("a");
42
+ a.href = url;
43
+ a.download = `${title.replace(/\.md$/i, "")}.md`;
44
+ a.click();
45
+ URL.revokeObjectURL(url);
46
+ };
47
+ return /* @__PURE__ */ jsxRuntime.jsx(
48
+ "div",
49
+ {
50
+ className: ui.cn(
51
+ "flex min-h-[560px] flex-col rounded-xl border border-border bg-card",
52
+ className
53
+ ),
54
+ "data-testid": testId,
55
+ children: /* @__PURE__ */ jsxRuntime.jsx(
56
+ chunkPVK3GAMH_cjs.ArtifactEditor,
57
+ {
58
+ ...s.view,
59
+ className: "min-h-[560px] flex-1",
60
+ labels,
61
+ onOpenVersion: setOpenId,
62
+ renderMarkdown: artifacts.renderArtifactMarkdown,
63
+ editor: /* @__PURE__ */ jsxRuntime.jsx(chunkRUNQFXPH_cjs.ArtifactMarkdownEditor, { ...editorProps, ...s.editorProps }),
64
+ redline: /* @__PURE__ */ jsxRuntime.jsx(chunkPVK3GAMH_cjs.ArtifactRedlineView, { ...s.redlineProps, renderMarkdown: artifacts.renderArtifactMarkdown }),
65
+ actions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
66
+ !hideDefaultActions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
67
+ /* @__PURE__ */ jsxRuntime.jsxs(
68
+ ui.Button,
69
+ {
70
+ variant: "ghost",
71
+ size: "sm",
72
+ onClick: copy,
73
+ "data-testid": `${testId}-copy`,
74
+ className: "pointer-coarse:min-h-11",
75
+ children: [
76
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "size-4", "aria-hidden": true }),
77
+ " Copy"
78
+ ]
79
+ }
80
+ ),
81
+ /* @__PURE__ */ jsxRuntime.jsxs(
82
+ ui.Button,
83
+ {
84
+ variant: "ghost",
85
+ size: "sm",
86
+ onClick: download,
87
+ "data-testid": `${testId}-download`,
88
+ className: "pointer-coarse:min-h-11",
89
+ children: [
90
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { className: "size-4", "aria-hidden": true }),
91
+ " Download"
92
+ ]
93
+ }
94
+ )
95
+ ] }),
96
+ actions?.({ content: s.content, title })
97
+ ] })
98
+ }
99
+ )
100
+ }
101
+ );
102
+ }
103
+
104
+ module.exports = StreamedArtifactEditor;
105
+ //# sourceMappingURL=StreamedArtifactEditor-5BMNWSS4.cjs.map
106
+ //# sourceMappingURL=StreamedArtifactEditor-5BMNWSS4.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/connection/StreamedArtifactEditor.tsx"],"names":["useState","useArtifactSession","jsx","cn","ArtifactEditor","renderArtifactMarkdown","ArtifactMarkdownEditor","ArtifactRedlineView","jsxs","Fragment","Button","Copy","Download"],"mappings":"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","file":"StreamedArtifactEditor-5BMNWSS4.cjs","sourcesContent":["import { useState, type ReactNode } from 'react'\nimport { Copy, Download } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { renderArtifactMarkdown, useArtifactSession } from '@arbidocs/react/artifacts'\nimport { ArtifactEditor, ArtifactRedlineView, type ArtifactEditorLabels } from '../artifacts'\nimport {\n ArtifactMarkdownEditor,\n type ArtifactMarkdownEditorProps,\n} from '../artifacts/editor/ArtifactMarkdownEditor'\n\nexport interface StreamedArtifactEditorProps {\n workspaceId: string | undefined\n /** The stored first version (the lineage's root as far as this panel goes). */\n docId: string\n /** File name for the versions saved from here. */\n title: string\n testId: string\n className?: string\n /** Extra props of the rich-text editor (`dictation`, labels). */\n editorProps?: Partial<Omit<ArtifactMarkdownEditorProps, 'markdown' | 'onChange' | 'onNormalized'>>\n /** Called after a version is saved. */\n onSaved?: (docId: string | undefined) => void\n onSaveError?: (error: unknown) => void\n /** Extra header actions next to the toolbar. */\n actions?: (ctx: { content: string; title: string }) => ReactNode\n /** Hide the default Copy and Download buttons. */\n hideDefaultActions?: boolean\n labels?: Partial<ArtifactEditorLabels>\n}\n\n/**\n * The editing stage of `StreamedArtifact`: `ArtifactEditor` bound to `useArtifactSession`. It is\n * a separate module because it pulls the rich-text editor (Lexical), which must stay behind a\n * `lazy()` boundary.\n */\nexport default function StreamedArtifactEditor({\n workspaceId,\n docId,\n title,\n testId,\n className,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n}: StreamedArtifactEditorProps) {\n const [openId, setOpenId] = useState(docId)\n const s = useArtifactSession({\n workspaceId,\n docId: openId,\n title,\n onSaved: ({ docId: next }) => {\n if (next) setOpenId(next)\n onSaved?.(next)\n },\n onSaveError,\n })\n\n const copy = () => void navigator.clipboard.writeText(s.content)\n const download = () => {\n const url = URL.createObjectURL(new Blob([s.content], { type: 'text/markdown' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${title.replace(/\\.md$/i, '')}.md`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-[560px] flex-col rounded-xl border border-border bg-card',\n className\n )}\n data-testid={testId}\n >\n <ArtifactEditor\n {...s.view}\n className=\"min-h-[560px] flex-1\"\n labels={labels}\n onOpenVersion={setOpenId}\n renderMarkdown={renderArtifactMarkdown}\n editor={<ArtifactMarkdownEditor {...editorProps} {...s.editorProps} />}\n redline={\n <ArtifactRedlineView {...s.redlineProps} renderMarkdown={renderArtifactMarkdown} />\n }\n actions={\n <>\n {!hideDefaultActions && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={copy}\n data-testid={`${testId}-copy`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Copy className=\"size-4\" aria-hidden /> Copy\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={download}\n data-testid={`${testId}-download`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Download className=\"size-4\" aria-hidden /> Download\n </Button>\n </>\n )}\n {actions?.({ content: s.content, title })}\n </>\n }\n />\n </div>\n )\n}\n"]}
@@ -0,0 +1,104 @@
1
+ "use client";
2
+ import { ArtifactMarkdownEditor } from './chunk-HSFGOA6V.js';
3
+ import { ArtifactEditor, ArtifactRedlineView } from './chunk-DTLOXXPN.js';
4
+ import './chunk-LOJVUGBJ.js';
5
+ import './chunk-7F6CBP3Z.js';
6
+ import { useState } from 'react';
7
+ import { Copy, Download } from 'lucide-react';
8
+ import { Button, cn } from '@arbidocs/react/ui';
9
+ import { useArtifactSession, renderArtifactMarkdown } from '@arbidocs/react/artifacts';
10
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
11
+
12
+ function StreamedArtifactEditor({
13
+ workspaceId,
14
+ docId,
15
+ title,
16
+ testId,
17
+ className,
18
+ editorProps,
19
+ onSaved,
20
+ onSaveError,
21
+ actions,
22
+ hideDefaultActions,
23
+ labels
24
+ }) {
25
+ const [openId, setOpenId] = useState(docId);
26
+ const s = useArtifactSession({
27
+ workspaceId,
28
+ docId: openId,
29
+ title,
30
+ onSaved: ({ docId: next }) => {
31
+ if (next) setOpenId(next);
32
+ onSaved?.(next);
33
+ },
34
+ onSaveError
35
+ });
36
+ const copy = () => void navigator.clipboard.writeText(s.content);
37
+ const download = () => {
38
+ const url = URL.createObjectURL(new Blob([s.content], { type: "text/markdown" }));
39
+ const a = document.createElement("a");
40
+ a.href = url;
41
+ a.download = `${title.replace(/\.md$/i, "")}.md`;
42
+ a.click();
43
+ URL.revokeObjectURL(url);
44
+ };
45
+ return /* @__PURE__ */ jsx(
46
+ "div",
47
+ {
48
+ className: cn(
49
+ "flex min-h-[560px] flex-col rounded-xl border border-border bg-card",
50
+ className
51
+ ),
52
+ "data-testid": testId,
53
+ children: /* @__PURE__ */ jsx(
54
+ ArtifactEditor,
55
+ {
56
+ ...s.view,
57
+ className: "min-h-[560px] flex-1",
58
+ labels,
59
+ onOpenVersion: setOpenId,
60
+ renderMarkdown: renderArtifactMarkdown,
61
+ editor: /* @__PURE__ */ jsx(ArtifactMarkdownEditor, { ...editorProps, ...s.editorProps }),
62
+ redline: /* @__PURE__ */ jsx(ArtifactRedlineView, { ...s.redlineProps, renderMarkdown: renderArtifactMarkdown }),
63
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [
64
+ !hideDefaultActions && /* @__PURE__ */ jsxs(Fragment, { children: [
65
+ /* @__PURE__ */ jsxs(
66
+ Button,
67
+ {
68
+ variant: "ghost",
69
+ size: "sm",
70
+ onClick: copy,
71
+ "data-testid": `${testId}-copy`,
72
+ className: "pointer-coarse:min-h-11",
73
+ children: [
74
+ /* @__PURE__ */ jsx(Copy, { className: "size-4", "aria-hidden": true }),
75
+ " Copy"
76
+ ]
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsxs(
80
+ Button,
81
+ {
82
+ variant: "ghost",
83
+ size: "sm",
84
+ onClick: download,
85
+ "data-testid": `${testId}-download`,
86
+ className: "pointer-coarse:min-h-11",
87
+ children: [
88
+ /* @__PURE__ */ jsx(Download, { className: "size-4", "aria-hidden": true }),
89
+ " Download"
90
+ ]
91
+ }
92
+ )
93
+ ] }),
94
+ actions?.({ content: s.content, title })
95
+ ] })
96
+ }
97
+ )
98
+ }
99
+ );
100
+ }
101
+
102
+ export { StreamedArtifactEditor as default };
103
+ //# sourceMappingURL=StreamedArtifactEditor-6ETUHNQN.js.map
104
+ //# sourceMappingURL=StreamedArtifactEditor-6ETUHNQN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/connection/StreamedArtifactEditor.tsx"],"names":[],"mappings":"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","file":"StreamedArtifactEditor-6ETUHNQN.js","sourcesContent":["import { useState, type ReactNode } from 'react'\nimport { Copy, Download } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { renderArtifactMarkdown, useArtifactSession } from '@arbidocs/react/artifacts'\nimport { ArtifactEditor, ArtifactRedlineView, type ArtifactEditorLabels } from '../artifacts'\nimport {\n ArtifactMarkdownEditor,\n type ArtifactMarkdownEditorProps,\n} from '../artifacts/editor/ArtifactMarkdownEditor'\n\nexport interface StreamedArtifactEditorProps {\n workspaceId: string | undefined\n /** The stored first version (the lineage's root as far as this panel goes). */\n docId: string\n /** File name for the versions saved from here. */\n title: string\n testId: string\n className?: string\n /** Extra props of the rich-text editor (`dictation`, labels). */\n editorProps?: Partial<Omit<ArtifactMarkdownEditorProps, 'markdown' | 'onChange' | 'onNormalized'>>\n /** Called after a version is saved. */\n onSaved?: (docId: string | undefined) => void\n onSaveError?: (error: unknown) => void\n /** Extra header actions next to the toolbar. */\n actions?: (ctx: { content: string; title: string }) => ReactNode\n /** Hide the default Copy and Download buttons. */\n hideDefaultActions?: boolean\n labels?: Partial<ArtifactEditorLabels>\n}\n\n/**\n * The editing stage of `StreamedArtifact`: `ArtifactEditor` bound to `useArtifactSession`. It is\n * a separate module because it pulls the rich-text editor (Lexical), which must stay behind a\n * `lazy()` boundary.\n */\nexport default function StreamedArtifactEditor({\n workspaceId,\n docId,\n title,\n testId,\n className,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n}: StreamedArtifactEditorProps) {\n const [openId, setOpenId] = useState(docId)\n const s = useArtifactSession({\n workspaceId,\n docId: openId,\n title,\n onSaved: ({ docId: next }) => {\n if (next) setOpenId(next)\n onSaved?.(next)\n },\n onSaveError,\n })\n\n const copy = () => void navigator.clipboard.writeText(s.content)\n const download = () => {\n const url = URL.createObjectURL(new Blob([s.content], { type: 'text/markdown' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${title.replace(/\\.md$/i, '')}.md`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-[560px] flex-col rounded-xl border border-border bg-card',\n className\n )}\n data-testid={testId}\n >\n <ArtifactEditor\n {...s.view}\n className=\"min-h-[560px] flex-1\"\n labels={labels}\n onOpenVersion={setOpenId}\n renderMarkdown={renderArtifactMarkdown}\n editor={<ArtifactMarkdownEditor {...editorProps} {...s.editorProps} />}\n redline={\n <ArtifactRedlineView {...s.redlineProps} renderMarkdown={renderArtifactMarkdown} />\n }\n actions={\n <>\n {!hideDefaultActions && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={copy}\n data-testid={`${testId}-copy`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Copy className=\"size-4\" aria-hidden /> Copy\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={download}\n data-testid={`${testId}-download`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Download className=\"size-4\" aria-hidden /> Download\n </Button>\n </>\n )}\n {actions?.({ content: s.content, title })}\n </>\n }\n />\n </div>\n )\n}\n"]}
@@ -5,13 +5,28 @@ import type { RenderMarkdown } from './ArtifactRedlineView';
5
5
  import { type ArtifactToolbarLabels } from './ArtifactToolbar';
6
6
  import { type ArtifactVersionBarLabels, type ArtifactVersionBarTestIds } from './ArtifactVersionBar';
7
7
  import type { VersionEntry } from './VersionTimeline';
8
+ /** Whether the artifact's text is available (`ArtifactTextStatus` of `@arbidocs/react/artifacts`). */
9
+ export type ArtifactEditorStatus = 'loading' | 'parsing' | 'ready' | 'error';
10
+ export interface ArtifactEditorStatusLabels {
11
+ /** Shown while the backend is still parsing a fresh upload. */
12
+ preparing: string;
13
+ error: string;
14
+ retry: string;
15
+ }
16
+ export declare const DEFAULT_ARTIFACT_EDITOR_STATUS_LABELS: ArtifactEditorStatusLabels;
8
17
  export interface ArtifactEditorLabels {
18
+ status: Partial<ArtifactEditorStatusLabels>;
9
19
  toolbar: Partial<ArtifactToolbarLabels>;
10
20
  versions: Partial<ArtifactVersionBarLabels>;
11
21
  compare: Partial<ArtifactCompareBarLabels>;
12
22
  }
13
23
  export interface ArtifactEditorTestIds {
14
24
  root: string;
25
+ /** The "Preparing editor" state. */
26
+ preparing: string;
27
+ /** The error state and its retry button. */
28
+ error: string;
29
+ retry: string;
15
30
  compareRow: string;
16
31
  body: Partial<ArtifactEditorBodyTestIds>;
17
32
  versions: Partial<ArtifactVersionBarTestIds>;
@@ -31,6 +46,14 @@ export interface ArtifactEditorProps {
31
46
  /** The version being compared against. */
32
47
  compareId?: string | null;
33
48
  showTrackChanges: boolean;
49
+ /**
50
+ * Whether the text is available. While `loading` or `parsing` the body is a "Preparing editor"
51
+ * state (the toolbar is disabled: an editor on an empty baseline would save a blank version);
52
+ * `error` shows `labels.status.error` with Retry (`onRetry`). Default `ready`.
53
+ */
54
+ status?: ArtifactEditorStatus;
55
+ /** Ask for the text again after an `error`. */
56
+ onRetry?: () => void;
34
57
  /** The lineage, oldest first. The version bar shows only for two or more. */
35
58
  versions?: VersionEntry[];
36
59
  currentVersionId?: string;
@@ -61,4 +84,4 @@ export interface ArtifactEditorProps {
61
84
  * changes). Everything is view-model driven: a host binds state with `useArtifactSession` from
62
85
  * `@arbidocs/react/artifacts` and passes the editor and redline as slots.
63
86
  */
64
- export declare function ArtifactEditor({ content, isEditing, hasChanges, isSaving, isDraft, compact, canCompare, comparing, compareId, showTrackChanges, versions, currentVersionId, onStartEdit, onCancel, onSave, onCompare, onStopCompare, onToggleTrackChanges, onOpenVersion, formatDate, editor, redline, renderMarkdown, actions, className, labels, testIds, }: ArtifactEditorProps): import("react").JSX.Element;
87
+ export declare function ArtifactEditor({ content, isEditing, hasChanges, isSaving, isDraft, compact, canCompare, comparing, compareId, showTrackChanges, status, onRetry, versions, currentVersionId, onStartEdit, onCancel, onSave, onCompare, onStopCompare, onToggleTrackChanges, onOpenVersion, formatDate, editor, redline, renderMarkdown, actions, className, labels, testIds, }: ArtifactEditorProps): import("react").JSX.Element;
@@ -36,6 +36,8 @@ export interface ArtifactToolbarProps {
36
36
  /** Offer "Compare against the previous version". */
37
37
  canCompare: boolean;
38
38
  onStartEdit: () => void;
39
+ /** Edit is not offered yet (the text is still being prepared). */
40
+ editDisabled?: boolean;
39
41
  /** Discard the buffer and leave edit mode. */
40
42
  onCancel: () => void;
41
43
  onCompare: () => void;
@@ -50,4 +52,4 @@ export interface ArtifactToolbarProps {
50
52
  * once there is something to save; a dot marks unsaved changes and a polite status announces them.
51
53
  * Touch targets are 44px on coarse pointers.
52
54
  */
53
- export declare function ArtifactToolbar({ isEditing, isDraft, compact, hasChanges, isSaving, canCompare, onStartEdit, onCancel, onCompare, onSave, className, labels, testIds, }: ArtifactToolbarProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
55
+ export declare function ArtifactToolbar({ isEditing, isDraft, compact, hasChanges, isSaving, canCompare, editDisabled, onStartEdit, onCancel, onCompare, onSave, className, labels, testIds, }: ArtifactToolbarProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -0,0 +1,36 @@
1
+ import type { ReactNode } from 'react';
2
+ /** `StreamedArtifactPhase` of `@arbidocs/react/artifacts`. */
3
+ export type StreamedArtifactFramePhase = 'streaming' | 'persisting' | 'parsing' | 'ready' | 'error';
4
+ export interface StreamedArtifactFrameLabels {
5
+ preparing: string;
6
+ error: string;
7
+ retry: string;
8
+ }
9
+ export declare const DEFAULT_STREAMED_ARTIFACT_FRAME_LABELS: StreamedArtifactFrameLabels;
10
+ export interface StreamedArtifactFrameTestIds {
11
+ /** The "Preparing editor" wrapper (`persisting` and `parsing`). */
12
+ preparing: string;
13
+ error: string;
14
+ retry: string;
15
+ }
16
+ export interface StreamedArtifactFrameProps {
17
+ phase: StreamedArtifactFramePhase;
18
+ /** The live canvas: shown while streaming, and kept in view under the status while preparing. */
19
+ canvas: ReactNode;
20
+ /** The editor, mounted only when `phase` is `ready`. */
21
+ children: ReactNode;
22
+ /** Why it failed (shown under the message). */
23
+ error?: string | null;
24
+ onRetry?: () => void;
25
+ className?: string;
26
+ labels?: Partial<StreamedArtifactFrameLabels>;
27
+ testIds?: Partial<StreamedArtifactFrameTestIds>;
28
+ }
29
+ /**
30
+ * The STREAM -> PERSIST -> EDIT switch of an agent-drafted artifact, presentational. The live
31
+ * `canvas` while the agent streams; "Preparing editor..." (a polite status above the canvas, so
32
+ * the draft stays readable) while the draft is stored and parsed; the editor (`children`) when it
33
+ * is ready; an alert with Retry when storing or parsing failed. The connected version is
34
+ * `StreamedArtifact` in `@arbidocs/blocks/connect`.
35
+ */
36
+ export declare function StreamedArtifactFrame({ phase, canvas, children, error, onRetry, className, labels, testIds, }: StreamedArtifactFrameProps): import("react").JSX.Element;
@@ -1,89 +1,18 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkMHVNT4J3_cjs = require('../../chunk-MHVNT4J3.cjs');
5
- var react = require('react');
6
- var editor = require('@mdxeditor/editor');
7
- var jsxRuntime = require('react/jsx-runtime');
4
+ var chunkRUNQFXPH_cjs = require('../../chunk-RUNQFXPH.cjs');
5
+ require('../../chunk-MHVNT4J3.cjs');
8
6
 
9
- function DictationSlot({
10
- render
11
- }) {
12
- const insertMarkdown = editor.usePublisher(editor.insertMarkdown$);
13
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render(insertMarkdown) });
14
- }
15
- var DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS = {
16
- editor: "Document editor",
17
- placeholder: "Start typing\u2026"
18
- };
19
- function ArtifactMarkdownEditor({
20
- markdown,
21
- onChange,
22
- onNormalized,
23
- dictation,
24
- labels,
25
- testId
26
- }) {
27
- const l = { ...DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS, ...labels };
28
- const ref = react.useRef(null);
29
- const pendingNormalizationRef = react.useRef(true);
30
- return /* @__PURE__ */ jsxRuntime.jsx(
31
- "div",
32
- {
33
- role: "group",
34
- "aria-label": l.editor,
35
- "data-testid": chunkMHVNT4J3_cjs.testIdOr(testId, { testId: "artifact-markdown-editor" }),
36
- className: "h-full pointer-coarse:[&_[role=toolbar]_button]:min-h-11 pointer-coarse:[&_[role=toolbar]_button]:min-w-11",
37
- children: /* @__PURE__ */ jsxRuntime.jsx(
38
- editor.MDXEditor,
39
- {
40
- ref,
41
- markdown,
42
- onChange: (next) => {
43
- if (pendingNormalizationRef.current) {
44
- pendingNormalizationRef.current = false;
45
- onNormalized?.(next);
46
- }
47
- onChange(next);
48
- },
49
- contentEditableClassName: "markdown-content max-w-none px-6 py-4 outline-none min-h-full",
50
- className: "h-full overflow-auto bg-background",
51
- placeholder: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: l.placeholder }),
52
- plugins: [
53
- editor.headingsPlugin(),
54
- editor.listsPlugin(),
55
- editor.quotePlugin(),
56
- editor.thematicBreakPlugin(),
57
- editor.linkPlugin(),
58
- editor.linkDialogPlugin(),
59
- editor.tablePlugin(),
60
- editor.markdownShortcutPlugin(),
61
- editor.toolbarPlugin({
62
- toolbarContents: () => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
63
- /* @__PURE__ */ jsxRuntime.jsx(editor.UndoRedo, {}),
64
- /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
65
- /* @__PURE__ */ jsxRuntime.jsx(editor.BoldItalicUnderlineToggles, {}),
66
- /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
67
- /* @__PURE__ */ jsxRuntime.jsx(editor.BlockTypeSelect, {}),
68
- /* @__PURE__ */ jsxRuntime.jsx(editor.ListsToggle, {}),
69
- /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
70
- /* @__PURE__ */ jsxRuntime.jsx(editor.CreateLink, {}),
71
- /* @__PURE__ */ jsxRuntime.jsx(editor.InsertTable, {}),
72
- /* @__PURE__ */ jsxRuntime.jsx(editor.InsertThematicBreak, {}),
73
- dictation && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
74
- /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
75
- /* @__PURE__ */ jsxRuntime.jsx(DictationSlot, { render: dictation })
76
- ] })
77
- ] })
78
- })
79
- ]
80
- }
81
- )
82
- }
83
- );
84
- }
85
7
 
86
- exports.ArtifactMarkdownEditor = ArtifactMarkdownEditor;
87
- exports.DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS = DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS;
8
+
9
+ Object.defineProperty(exports, "ArtifactMarkdownEditor", {
10
+ enumerable: true,
11
+ get: function () { return chunkRUNQFXPH_cjs.ArtifactMarkdownEditor; }
12
+ });
13
+ Object.defineProperty(exports, "DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS", {
14
+ enumerable: true,
15
+ get: function () { return chunkRUNQFXPH_cjs.DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS; }
16
+ });
88
17
  //# sourceMappingURL=index.cjs.map
89
18
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/artifacts/editor/ArtifactMarkdownEditor.tsx"],"names":["usePublisher","insertMarkdown$","jsx","Fragment","useRef","testIdOr","MDXEditor","headingsPlugin","listsPlugin","quotePlugin","thematicBreakPlugin","linkPlugin","linkDialogPlugin","tablePlugin","markdownShortcutPlugin","toolbarPlugin","jsxs","UndoRedo","Separator","BoldItalicUnderlineToggles","BlockTypeSelect","ListsToggle","CreateLink","InsertTable","InsertThematicBreak"],"mappings":"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","file":"index.cjs","sourcesContent":["import { useRef, type ReactNode } from 'react'\nimport {\n MDXEditor,\n type MDXEditorMethods,\n headingsPlugin,\n listsPlugin,\n quotePlugin,\n thematicBreakPlugin,\n linkPlugin,\n linkDialogPlugin,\n tablePlugin,\n markdownShortcutPlugin,\n toolbarPlugin,\n UndoRedo,\n BoldItalicUnderlineToggles,\n BlockTypeSelect,\n ListsToggle,\n CreateLink,\n InsertTable,\n InsertThematicBreak,\n Separator,\n insertMarkdown$,\n usePublisher,\n} from '@mdxeditor/editor'\nimport { testIdOr } from '../../chat/test-id'\n\n/** Renders the host's dictation control; `insert` puts text at the cursor. */\nfunction DictationSlot({\n render,\n}: {\n render: (insert: (markdown: string) => void) => ReactNode\n}): React.ReactElement {\n const insertMarkdown = usePublisher(insertMarkdown$)\n return <>{render(insertMarkdown)}</>\n}\n\nexport interface ArtifactMarkdownEditorLabels {\n /** The accessible name of the editor region. */\n editor: string\n placeholder: string\n}\n\nexport const DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS: ArtifactMarkdownEditorLabels = {\n editor: 'Document editor',\n placeholder: 'Start typing…',\n}\n\nexport interface ArtifactMarkdownEditorProps {\n /** Current markdown (controlled by the parent). */\n markdown: string\n /** Called with the new markdown whenever the document changes. */\n onChange: (markdown: string) => void\n /**\n * Fired exactly once per editor instance, with the markdown the editor produces on mount.\n * MDXEditor canonicalises the source as it parses (table padding, escapes, thematic-break\n * style), so the first `onChange` after mount is the round-tripped form of the input, not a\n * user edit. Use it to adopt the normalised form as the baseline so entering edit mode does\n * not look dirty. Remount via `key` to receive it for the next document.\n */\n onNormalized?: (normalized: string) => void\n /**\n * A dictation control for the toolbar (the host owns recording and transcription, for example\n * `@arbidocs/react`'s `InlineMicButton`). It gets a function that inserts text at the cursor.\n */\n dictation?: (insert: (markdown: string) => void) => ReactNode\n labels?: Partial<ArtifactMarkdownEditorLabels>\n testId?: string\n}\n\n/**\n * WYSIWYG editor for artifact documents: the user edits the rendered document directly and the\n * editor round-trips Markdown, so `onChange` always yields markdown a save can persist unchanged.\n *\n *\n * Heavy (Lexical via MDXEditor): mount it behind a lazy boundary. The host imports\n * `@mdxeditor/editor/style.css` once and, from the module that lazily imports this one, a module\n * that defines the global `Prism` FIRST (assign the prismjs core to `globalThis.Prism`):\n * `@lexical/code` reads it while it evaluates, and a library cannot order that in every bundler.\n */\nexport function ArtifactMarkdownEditor({\n markdown,\n onChange,\n onNormalized,\n dictation,\n labels,\n testId,\n}: ArtifactMarkdownEditorProps): React.ReactElement {\n const l = { ...DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS, ...labels }\n const ref = useRef<MDXEditorMethods>(null)\n // Latched until MDXEditor fires its first onChange after mount: that is the canonicalisation\n // round-trip, not a user edit.\n const pendingNormalizationRef = useRef(true)\n\n return (\n <div\n role=\"group\"\n aria-label={l.editor}\n data-testid={testIdOr(testId, { testId: 'artifact-markdown-editor' })}\n className=\"h-full pointer-coarse:[&_[role=toolbar]_button]:min-h-11 pointer-coarse:[&_[role=toolbar]_button]:min-w-11\"\n >\n <MDXEditor\n ref={ref}\n markdown={markdown}\n onChange={(next) => {\n if (pendingNormalizationRef.current) {\n pendingNormalizationRef.current = false\n onNormalized?.(next)\n }\n onChange(next)\n }}\n contentEditableClassName=\"markdown-content max-w-none px-6 py-4 outline-none min-h-full\"\n className=\"h-full overflow-auto bg-background\"\n placeholder={<span className=\"text-muted-foreground\">{l.placeholder}</span>}\n plugins={[\n headingsPlugin(),\n listsPlugin(),\n quotePlugin(),\n thematicBreakPlugin(),\n linkPlugin(),\n linkDialogPlugin(),\n tablePlugin(),\n markdownShortcutPlugin(),\n toolbarPlugin({\n toolbarContents: () => (\n <>\n <UndoRedo />\n <Separator />\n <BoldItalicUnderlineToggles />\n <Separator />\n <BlockTypeSelect />\n <ListsToggle />\n <Separator />\n <CreateLink />\n <InsertTable />\n <InsertThematicBreak />\n {dictation && (\n <>\n <Separator />\n <DictationSlot render={dictation} />\n </>\n )}\n </>\n ),\n }),\n ]}\n />\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -1,86 +1,5 @@
1
1
  "use client";
2
- import { testIdOr } from '../../chunk-7F6CBP3Z.js';
3
- import { useRef } from 'react';
4
- import { MDXEditor, headingsPlugin, listsPlugin, quotePlugin, thematicBreakPlugin, linkPlugin, linkDialogPlugin, tablePlugin, markdownShortcutPlugin, toolbarPlugin, UndoRedo, Separator, BoldItalicUnderlineToggles, BlockTypeSelect, ListsToggle, CreateLink, InsertTable, InsertThematicBreak, usePublisher, insertMarkdown$ } from '@mdxeditor/editor';
5
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
-
7
- function DictationSlot({
8
- render
9
- }) {
10
- const insertMarkdown = usePublisher(insertMarkdown$);
11
- return /* @__PURE__ */ jsx(Fragment, { children: render(insertMarkdown) });
12
- }
13
- var DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS = {
14
- editor: "Document editor",
15
- placeholder: "Start typing\u2026"
16
- };
17
- function ArtifactMarkdownEditor({
18
- markdown,
19
- onChange,
20
- onNormalized,
21
- dictation,
22
- labels,
23
- testId
24
- }) {
25
- const l = { ...DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS, ...labels };
26
- const ref = useRef(null);
27
- const pendingNormalizationRef = useRef(true);
28
- return /* @__PURE__ */ jsx(
29
- "div",
30
- {
31
- role: "group",
32
- "aria-label": l.editor,
33
- "data-testid": testIdOr(testId, { testId: "artifact-markdown-editor" }),
34
- className: "h-full pointer-coarse:[&_[role=toolbar]_button]:min-h-11 pointer-coarse:[&_[role=toolbar]_button]:min-w-11",
35
- children: /* @__PURE__ */ jsx(
36
- MDXEditor,
37
- {
38
- ref,
39
- markdown,
40
- onChange: (next) => {
41
- if (pendingNormalizationRef.current) {
42
- pendingNormalizationRef.current = false;
43
- onNormalized?.(next);
44
- }
45
- onChange(next);
46
- },
47
- contentEditableClassName: "markdown-content max-w-none px-6 py-4 outline-none min-h-full",
48
- className: "h-full overflow-auto bg-background",
49
- placeholder: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: l.placeholder }),
50
- plugins: [
51
- headingsPlugin(),
52
- listsPlugin(),
53
- quotePlugin(),
54
- thematicBreakPlugin(),
55
- linkPlugin(),
56
- linkDialogPlugin(),
57
- tablePlugin(),
58
- markdownShortcutPlugin(),
59
- toolbarPlugin({
60
- toolbarContents: () => /* @__PURE__ */ jsxs(Fragment, { children: [
61
- /* @__PURE__ */ jsx(UndoRedo, {}),
62
- /* @__PURE__ */ jsx(Separator, {}),
63
- /* @__PURE__ */ jsx(BoldItalicUnderlineToggles, {}),
64
- /* @__PURE__ */ jsx(Separator, {}),
65
- /* @__PURE__ */ jsx(BlockTypeSelect, {}),
66
- /* @__PURE__ */ jsx(ListsToggle, {}),
67
- /* @__PURE__ */ jsx(Separator, {}),
68
- /* @__PURE__ */ jsx(CreateLink, {}),
69
- /* @__PURE__ */ jsx(InsertTable, {}),
70
- /* @__PURE__ */ jsx(InsertThematicBreak, {}),
71
- dictation && /* @__PURE__ */ jsxs(Fragment, { children: [
72
- /* @__PURE__ */ jsx(Separator, {}),
73
- /* @__PURE__ */ jsx(DictationSlot, { render: dictation })
74
- ] })
75
- ] })
76
- })
77
- ]
78
- }
79
- )
80
- }
81
- );
82
- }
83
-
84
- export { ArtifactMarkdownEditor, DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS };
2
+ export { ArtifactMarkdownEditor, DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS } from '../../chunk-HSFGOA6V.js';
3
+ import '../../chunk-7F6CBP3Z.js';
85
4
  //# sourceMappingURL=index.js.map
86
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/artifacts/editor/ArtifactMarkdownEditor.tsx"],"names":[],"mappings":";;;;;AA2BA,SAAS,aAAA,CAAc;AAAA,EACrB;AACF,CAAA,EAEuB;AACrB,EAAA,MAAM,cAAA,GAAiB,aAAa,eAAe,CAAA;AACnD,EAAA,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAA,MAAA,CAAO,cAAc,CAAA,EAAE,CAAA;AACnC;AAQO,IAAM,uCAAA,GAAwE;AAAA,EACnF,MAAA,EAAQ,iBAAA;AAAA,EACR,WAAA,EAAa;AACf;AAkCO,SAAS,sBAAA,CAAuB;AAAA,EACrC,QAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAoD;AAClD,EAAA,MAAM,CAAA,GAAI,EAAE,GAAG,uCAAA,EAAyC,GAAG,MAAA,EAAO;AAClE,EAAA,MAAM,GAAA,GAAM,OAAyB,IAAI,CAAA;AAGzC,EAAA,MAAM,uBAAA,GAA0B,OAAO,IAAI,CAAA;AAE3C,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,OAAA;AAAA,MACL,cAAY,CAAA,CAAE,MAAA;AAAA,MACd,eAAa,QAAA,CAAS,MAAA,EAAQ,EAAE,MAAA,EAAQ,4BAA4B,CAAA;AAAA,MACpE,SAAA,EAAU,4GAAA;AAAA,MAEV,QAAA,kBAAA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,GAAA;AAAA,UACA,QAAA;AAAA,UACA,QAAA,EAAU,CAAC,IAAA,KAAS;AAClB,YAAA,IAAI,wBAAwB,OAAA,EAAS;AACnC,cAAA,uBAAA,CAAwB,OAAA,GAAU,KAAA;AAClC,cAAA,YAAA,GAAe,IAAI,CAAA;AAAA,YACrB;AACA,YAAA,QAAA,CAAS,IAAI,CAAA;AAAA,UACf,CAAA;AAAA,UACA,wBAAA,EAAyB,+DAAA;AAAA,UACzB,SAAA,EAAU,oCAAA;AAAA,UACV,6BAAa,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EAAyB,YAAE,WAAA,EAAY,CAAA;AAAA,UACpE,OAAA,EAAS;AAAA,YACP,cAAA,EAAe;AAAA,YACf,WAAA,EAAY;AAAA,YACZ,WAAA,EAAY;AAAA,YACZ,mBAAA,EAAoB;AAAA,YACpB,UAAA,EAAW;AAAA,YACX,gBAAA,EAAiB;AAAA,YACjB,WAAA,EAAY;AAAA,YACZ,sBAAA,EAAuB;AAAA,YACvB,aAAA,CAAc;AAAA,cACZ,eAAA,EAAiB,sBACf,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,QAAA,EAAA,EAAS,CAAA;AAAA,oCACT,SAAA,EAAA,EAAU,CAAA;AAAA,oCACV,0BAAA,EAAA,EAA2B,CAAA;AAAA,oCAC3B,SAAA,EAAA,EAAU,CAAA;AAAA,oCACV,eAAA,EAAA,EAAgB,CAAA;AAAA,oCAChB,WAAA,EAAA,EAAY,CAAA;AAAA,oCACZ,SAAA,EAAA,EAAU,CAAA;AAAA,oCACV,UAAA,EAAA,EAAW,CAAA;AAAA,oCACX,WAAA,EAAA,EAAY,CAAA;AAAA,oCACZ,mBAAA,EAAA,EAAoB,CAAA;AAAA,gBACpB,6BACC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,SAAA,EAAA,EAAU,CAAA;AAAA,kCACX,GAAA,CAAC,aAAA,EAAA,EAAc,MAAA,EAAQ,SAAA,EAAW;AAAA,iBAAA,EACpC;AAAA,eAAA,EAEJ;AAAA,aAEH;AAAA;AACH;AAAA;AACF;AAAA,GACF;AAEJ","file":"index.js","sourcesContent":["import { useRef, type ReactNode } from 'react'\nimport {\n MDXEditor,\n type MDXEditorMethods,\n headingsPlugin,\n listsPlugin,\n quotePlugin,\n thematicBreakPlugin,\n linkPlugin,\n linkDialogPlugin,\n tablePlugin,\n markdownShortcutPlugin,\n toolbarPlugin,\n UndoRedo,\n BoldItalicUnderlineToggles,\n BlockTypeSelect,\n ListsToggle,\n CreateLink,\n InsertTable,\n InsertThematicBreak,\n Separator,\n insertMarkdown$,\n usePublisher,\n} from '@mdxeditor/editor'\nimport { testIdOr } from '../../chat/test-id'\n\n/** Renders the host's dictation control; `insert` puts text at the cursor. */\nfunction DictationSlot({\n render,\n}: {\n render: (insert: (markdown: string) => void) => ReactNode\n}): React.ReactElement {\n const insertMarkdown = usePublisher(insertMarkdown$)\n return <>{render(insertMarkdown)}</>\n}\n\nexport interface ArtifactMarkdownEditorLabels {\n /** The accessible name of the editor region. */\n editor: string\n placeholder: string\n}\n\nexport const DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS: ArtifactMarkdownEditorLabels = {\n editor: 'Document editor',\n placeholder: 'Start typing…',\n}\n\nexport interface ArtifactMarkdownEditorProps {\n /** Current markdown (controlled by the parent). */\n markdown: string\n /** Called with the new markdown whenever the document changes. */\n onChange: (markdown: string) => void\n /**\n * Fired exactly once per editor instance, with the markdown the editor produces on mount.\n * MDXEditor canonicalises the source as it parses (table padding, escapes, thematic-break\n * style), so the first `onChange` after mount is the round-tripped form of the input, not a\n * user edit. Use it to adopt the normalised form as the baseline so entering edit mode does\n * not look dirty. Remount via `key` to receive it for the next document.\n */\n onNormalized?: (normalized: string) => void\n /**\n * A dictation control for the toolbar (the host owns recording and transcription, for example\n * `@arbidocs/react`'s `InlineMicButton`). It gets a function that inserts text at the cursor.\n */\n dictation?: (insert: (markdown: string) => void) => ReactNode\n labels?: Partial<ArtifactMarkdownEditorLabels>\n testId?: string\n}\n\n/**\n * WYSIWYG editor for artifact documents: the user edits the rendered document directly and the\n * editor round-trips Markdown, so `onChange` always yields markdown a save can persist unchanged.\n *\n *\n * Heavy (Lexical via MDXEditor): mount it behind a lazy boundary. The host imports\n * `@mdxeditor/editor/style.css` once and, from the module that lazily imports this one, a module\n * that defines the global `Prism` FIRST (assign the prismjs core to `globalThis.Prism`):\n * `@lexical/code` reads it while it evaluates, and a library cannot order that in every bundler.\n */\nexport function ArtifactMarkdownEditor({\n markdown,\n onChange,\n onNormalized,\n dictation,\n labels,\n testId,\n}: ArtifactMarkdownEditorProps): React.ReactElement {\n const l = { ...DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS, ...labels }\n const ref = useRef<MDXEditorMethods>(null)\n // Latched until MDXEditor fires its first onChange after mount: that is the canonicalisation\n // round-trip, not a user edit.\n const pendingNormalizationRef = useRef(true)\n\n return (\n <div\n role=\"group\"\n aria-label={l.editor}\n data-testid={testIdOr(testId, { testId: 'artifact-markdown-editor' })}\n className=\"h-full pointer-coarse:[&_[role=toolbar]_button]:min-h-11 pointer-coarse:[&_[role=toolbar]_button]:min-w-11\"\n >\n <MDXEditor\n ref={ref}\n markdown={markdown}\n onChange={(next) => {\n if (pendingNormalizationRef.current) {\n pendingNormalizationRef.current = false\n onNormalized?.(next)\n }\n onChange(next)\n }}\n contentEditableClassName=\"markdown-content max-w-none px-6 py-4 outline-none min-h-full\"\n className=\"h-full overflow-auto bg-background\"\n placeholder={<span className=\"text-muted-foreground\">{l.placeholder}</span>}\n plugins={[\n headingsPlugin(),\n listsPlugin(),\n quotePlugin(),\n thematicBreakPlugin(),\n linkPlugin(),\n linkDialogPlugin(),\n tablePlugin(),\n markdownShortcutPlugin(),\n toolbarPlugin({\n toolbarContents: () => (\n <>\n <UndoRedo />\n <Separator />\n <BoldItalicUnderlineToggles />\n <Separator />\n <BlockTypeSelect />\n <ListsToggle />\n <Separator />\n <CreateLink />\n <InsertTable />\n <InsertThematicBreak />\n {dictation && (\n <>\n <Separator />\n <DictationSlot render={dictation} />\n </>\n )}\n </>\n ),\n }),\n ]}\n />\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}