@arbidocs/blocks 0.4.4 → 0.4.5
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/README.md +25 -0
- package/dist/agents/index.cjs +163 -163
- package/dist/agents/index.js +6 -6
- package/dist/artifacts/ArtifactCompareBar.d.ts +33 -0
- package/dist/artifacts/ArtifactEditor.d.ts +64 -0
- package/dist/artifacts/ArtifactEditorBody.d.ts +34 -0
- package/dist/artifacts/ArtifactRedlineView.d.ts +57 -0
- package/dist/artifacts/ArtifactToolbar.d.ts +53 -0
- package/dist/artifacts/ArtifactVersionBar.d.ts +42 -0
- package/dist/{files → artifacts}/RedlineParts.d.ts +4 -0
- package/dist/artifacts/editor/ArtifactMarkdownEditor.d.ts +39 -0
- package/dist/artifacts/editor/index.cjs +89 -0
- package/dist/artifacts/editor/index.cjs.map +1 -0
- package/dist/artifacts/editor/index.d.ts +1 -0
- package/dist/artifacts/editor/index.js +86 -0
- package/dist/artifacts/editor/index.js.map +1 -0
- package/dist/artifacts/index.cjs +807 -0
- package/dist/artifacts/index.cjs.map +1 -0
- package/dist/artifacts/index.d.ts +8 -0
- package/dist/artifacts/index.js +787 -0
- package/dist/artifacts/index.js.map +1 -0
- package/dist/chat/index.cjs +54 -54
- package/dist/chat/index.js +2 -2
- package/dist/{chunk-XKKGGUU2.cjs → chunk-3MIQASHO.cjs} +4 -4
- package/dist/{chunk-XKKGGUU2.cjs.map → chunk-3MIQASHO.cjs.map} +1 -1
- package/dist/{chunk-B673CCW5.js → chunk-3PJCET7H.js} +3 -3
- package/dist/{chunk-B673CCW5.js.map → chunk-3PJCET7H.js.map} +1 -1
- package/dist/{chunk-DGVKBOY5.cjs → chunk-3PZPRAAR.cjs} +14 -14
- package/dist/{chunk-DGVKBOY5.cjs.map → chunk-3PZPRAAR.cjs.map} +1 -1
- package/dist/{chunk-BBEMPS6C.js → chunk-5XTZFH65.js} +6 -6
- package/dist/{chunk-BBEMPS6C.js.map → chunk-5XTZFH65.js.map} +1 -1
- package/dist/{chunk-JPO3F4J7.js → chunk-6YHWXMPQ.js} +3 -3
- package/dist/{chunk-JPO3F4J7.js.map → chunk-6YHWXMPQ.js.map} +1 -1
- package/dist/{chunk-ZVPTFTGV.cjs → chunk-MVNCQDDE.cjs} +4 -4
- package/dist/{chunk-ZVPTFTGV.cjs.map → chunk-MVNCQDDE.cjs.map} +1 -1
- package/dist/{chunk-NJL4LIXX.js → chunk-NPKGUQU5.js} +4 -4
- package/dist/{chunk-NJL4LIXX.js.map → chunk-NPKGUQU5.js.map} +1 -1
- package/dist/{chunk-ATXPAD6S.cjs → chunk-YLOKCIQJ.cjs} +3 -3
- package/dist/{chunk-ATXPAD6S.cjs.map → chunk-YLOKCIQJ.cjs.map} +1 -1
- package/dist/connect/index.cjs +18 -18
- package/dist/connect/index.js +4 -4
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/ViewerChrome.d.ts +0 -45
- package/dist/files/ViewerParts.d.ts +0 -19
- package/dist/files/index.cjs +4 -436
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.d.ts +2 -4
- package/dist/files/index.js +8 -428
- package/dist/files/index.js.map +1 -1
- package/dist/home/index.cjs +19 -19
- package/dist/home/index.js +4 -4
- package/dist/index.cjs +415 -415
- package/dist/index.js +14 -14
- package/dist/settings/index.cjs +3 -3
- package/dist/settings/index.js +4 -4
- package/dist/shell/index.cjs +10 -10
- package/dist/shell/index.js +2 -2
- package/dist/site/index.cjs +5 -5
- package/dist/site/index.js +1 -1
- package/dist/studio/index.cjs +8 -8
- package/dist/studio/index.js +6 -6
- package/package.json +25 -4
- /package/dist/{files → artifacts}/VersionTimeline.d.ts +0 -0
package/dist/agents/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { ACTION_LABELS, AgentAvatarField, AgentBar, AgentBarIconButton, AgentBarMenu, AgentBarNotes, AgentBarProbeAnswer, AgentBarQueuedNote, AgentBarStatus, AgentCard, AgentCreateView, AgentCreatedView, AgentCreator, AgentEditView, AgentGallery, AgentMainView, AgentSelect, AgentTypeSelector, CapabilityGrid, CapabilityTile, ConfigField, ConfigForm, ConsentActions, ConsentBulletList, ConsentCard, ConsentFootnote, ConsentHeader, ConsentMessage, ConsentNotice, ConsentPage, ConsentPermissionList, ConsentSection, ConsentStrong, ConsentText, CopyableUrl, DEFAULT_AGENT_AVATAR_FIELD_LABELS, DEFAULT_AGENT_BAR_LABELS, DEFAULT_AGENT_CARD_LABELS, DEFAULT_AGENT_CREATOR_LABELS, DEFAULT_AGENT_GALLERY_LABELS, DEFAULT_AGENT_SELECT_LABELS, DEFAULT_AGENT_STEPS_LABELS, DEFAULT_AGENT_TYPE_SELECTOR_LABELS, DEFAULT_AUTHORIZE_AGENT_LABELS, DEFAULT_CONFIG_FIELD_LABELS, DEFAULT_CONFIG_FORM_LABELS, DEFAULT_CONSENT_ACTIONS_LABELS, DEFAULT_COPYABLE_URL_LABELS, DEFAULT_LIVE_RUNS_BANNER_LABELS, DEFAULT_RECURRENCE, DEFAULT_RECURRENCE_BUILDER_LABELS, DEFAULT_SCHEMA_FORM_LABELS, DEFAULT_SKILL_CARD_LABELS, DEFAULT_SKILL_EDIT_FORM_LABELS, DEFAULT_SKILL_GENERATE_FORM_LABELS, DEFAULT_SKILL_GLOBAL_BADGE_LABELS, DEFAULT_SKILL_ROW_LABELS, DEFAULT_SKILL_VIEW_TOGGLE_LABELS, DEFAULT_SUBAGENT_ROSTER_LABELS, DEFAULT_TASKS_CHROME_LABELS, DEFAULT_TASK_COLUMN_LABELS, DEFAULT_TASK_COMPOSER_LABELS, DEFAULT_TASK_PLAN_LABELS, DEFAULT_TASK_ROW_ACTIONS_LABELS, DEFAULT_TASK_RUNS_DIALOG_LABELS, DEFAULT_TUPLE_ARRAY_FIELD_LABELS, DEFAULT_UPLOAD_TASK_ITEM_LABELS, DEFAULT_UPLOAD_TASK_LIST_LABELS, DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, EMPTY_WORKFLOW_SCOPE, GoalCriteria, LiveRunsBanner, NewTaskEmptyAction, RecurrenceBuilder, SKILL_PROMPT_FALLBACK_PLACEHOLDER, SKILL_PROMPT_LABEL, STATUS_LABELS, SchemaForm, SkillActionButton, SkillCard, SkillDetail, SkillDetailSection, SkillEditForm, SkillFilterChips, SkillGenerateForm, SkillGlobalBadge, SkillRow, SkillTile, SkillTypeBadge, SkillViewToggle, StepDetail, StepNarration, StepOutcome, StepParams, StepRow, StepSummary, StepTrace, StepTraceSummary, SubAgentLane, SubStepGroup, SubagentRoster, TRIGGER_LABELS, TaskComposer, TaskPlan, TaskRowActions, TaskRunsDialog, TasksBulkBar, TasksToolbar, TupleArrayField, UploadTaskItem, UploadTaskList, WEEKDAYS, WorkflowConfigDialog, WorkflowLauncher, agentConfigSectionToValues, agentCreatorToConfigSection, authModeFor, buildLaunch, buildRRule, composePersona, composeWorkflowPrompt, createTaskColumns, defaultInputs, defaultTaskComposerValues, deriveAgentName, describeRRule, formatElapsed, goalProgress, humanizeSection, inferType, inputsFromContext, isAgenticWorkflow, isEmptyWorkflowScope, isOutOfBounds, isValidAgentName, isWorkflowScope, isoToLocalInput, localInputToIso, nextCriterionId, parseRRule, prettifyKey, promptFieldName, skillToWorkflow, statusBadgeVariant, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskComposerToCreateRequest, taskComposerToUpdateRequest, taskNeedsAccess, taskToComposerValues, validateInputs, workflowAccepts, workflowFromFrontmatter, workflowTaskFields, workflowsAccepting, workflowsForHost } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
2
|
+
export { ACTION_LABELS, AgentAvatarField, AgentBar, AgentBarIconButton, AgentBarMenu, AgentBarNotes, AgentBarProbeAnswer, AgentBarQueuedNote, AgentBarStatus, AgentCard, AgentCreateView, AgentCreatedView, AgentCreator, AgentEditView, AgentGallery, AgentMainView, AgentSelect, AgentTypeSelector, CapabilityGrid, CapabilityTile, ConfigField, ConfigForm, ConsentActions, ConsentBulletList, ConsentCard, ConsentFootnote, ConsentHeader, ConsentMessage, ConsentNotice, ConsentPage, ConsentPermissionList, ConsentSection, ConsentStrong, ConsentText, CopyableUrl, DEFAULT_AGENT_AVATAR_FIELD_LABELS, DEFAULT_AGENT_BAR_LABELS, DEFAULT_AGENT_CARD_LABELS, DEFAULT_AGENT_CREATOR_LABELS, DEFAULT_AGENT_GALLERY_LABELS, DEFAULT_AGENT_SELECT_LABELS, DEFAULT_AGENT_STEPS_LABELS, DEFAULT_AGENT_TYPE_SELECTOR_LABELS, DEFAULT_AUTHORIZE_AGENT_LABELS, DEFAULT_CONFIG_FIELD_LABELS, DEFAULT_CONFIG_FORM_LABELS, DEFAULT_CONSENT_ACTIONS_LABELS, DEFAULT_COPYABLE_URL_LABELS, DEFAULT_LIVE_RUNS_BANNER_LABELS, DEFAULT_RECURRENCE, DEFAULT_RECURRENCE_BUILDER_LABELS, DEFAULT_SCHEMA_FORM_LABELS, DEFAULT_SKILL_CARD_LABELS, DEFAULT_SKILL_EDIT_FORM_LABELS, DEFAULT_SKILL_GENERATE_FORM_LABELS, DEFAULT_SKILL_GLOBAL_BADGE_LABELS, DEFAULT_SKILL_ROW_LABELS, DEFAULT_SKILL_VIEW_TOGGLE_LABELS, DEFAULT_SUBAGENT_ROSTER_LABELS, DEFAULT_TASKS_CHROME_LABELS, DEFAULT_TASK_COLUMN_LABELS, DEFAULT_TASK_COMPOSER_LABELS, DEFAULT_TASK_PLAN_LABELS, DEFAULT_TASK_ROW_ACTIONS_LABELS, DEFAULT_TASK_RUNS_DIALOG_LABELS, DEFAULT_TUPLE_ARRAY_FIELD_LABELS, DEFAULT_UPLOAD_TASK_ITEM_LABELS, DEFAULT_UPLOAD_TASK_LIST_LABELS, DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, EMPTY_WORKFLOW_SCOPE, GoalCriteria, LiveRunsBanner, NewTaskEmptyAction, RecurrenceBuilder, SKILL_PROMPT_FALLBACK_PLACEHOLDER, SKILL_PROMPT_LABEL, STATUS_LABELS, SchemaForm, SkillActionButton, SkillCard, SkillDetail, SkillDetailSection, SkillEditForm, SkillFilterChips, SkillGenerateForm, SkillGlobalBadge, SkillRow, SkillTile, SkillTypeBadge, SkillViewToggle, StepDetail, StepNarration, StepOutcome, StepParams, StepRow, StepSummary, StepTrace, StepTraceSummary, SubAgentLane, SubStepGroup, SubagentRoster, TRIGGER_LABELS, TaskComposer, TaskPlan, TaskRowActions, TaskRunsDialog, TasksBulkBar, TasksToolbar, TupleArrayField, UploadTaskItem, UploadTaskList, WEEKDAYS, WorkflowConfigDialog, WorkflowLauncher, agentConfigSectionToValues, agentCreatorToConfigSection, authModeFor, buildLaunch, buildRRule, composePersona, composeWorkflowPrompt, createTaskColumns, defaultInputs, defaultTaskComposerValues, deriveAgentName, describeRRule, formatElapsed, goalProgress, humanizeSection, inferType, inputsFromContext, isAgenticWorkflow, isEmptyWorkflowScope, isOutOfBounds, isValidAgentName, isWorkflowScope, isoToLocalInput, localInputToIso, nextCriterionId, parseRRule, prettifyKey, promptFieldName, skillToWorkflow, statusBadgeVariant, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskComposerToCreateRequest, taskComposerToUpdateRequest, taskNeedsAccess, taskToComposerValues, validateInputs, workflowAccepts, workflowFromFrontmatter, workflowTaskFields, workflowsAccepting, workflowsForHost } from '../chunk-5XTZFH65.js';
|
|
3
|
+
import '../chunk-NUNKSZKU.js';
|
|
4
|
+
import '../chunk-NPKGUQU5.js';
|
|
4
5
|
import '../chunk-CQCC7LE7.js';
|
|
6
|
+
import '../chunk-UBNVIIBT.js';
|
|
7
|
+
import '../chunk-NPLYHR2E.js';
|
|
5
8
|
import '../chunk-P6GHJSLR.js';
|
|
6
9
|
import '../chunk-S7PSMMRG.js';
|
|
7
10
|
import '../chunk-TX2ZICS7.js';
|
|
8
|
-
import '../chunk-NUNKSZKU.js';
|
|
9
|
-
import '../chunk-UBNVIIBT.js';
|
|
10
|
-
import '../chunk-NPLYHR2E.js';
|
|
11
11
|
import '../chunk-76JDDMSP.js';
|
|
12
|
-
import '../chunk-OXF2IFXG.js';
|
|
13
12
|
import '../chunk-7F6CBP3Z.js';
|
|
13
|
+
import '../chunk-OXF2IFXG.js';
|
|
14
14
|
//# sourceMappingURL=index.js.map
|
|
15
15
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/** Every fixed string of the compare bar. Pass a partial `labels` to translate or reword. */
|
|
3
|
+
export interface ArtifactCompareBarLabels {
|
|
4
|
+
compareVs: string;
|
|
5
|
+
trackChanges: string;
|
|
6
|
+
trackChangesBack: string;
|
|
7
|
+
trackChangesView: string;
|
|
8
|
+
flipComparison: string;
|
|
9
|
+
stopComparing: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const DEFAULT_ARTIFACT_COMPARE_BAR_LABELS: ArtifactCompareBarLabels;
|
|
12
|
+
export interface ArtifactCompareBarTestIds {
|
|
13
|
+
trackChanges: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ArtifactCompareBarProps {
|
|
16
|
+
/** The compared-against version (the host renders its name or pill). */
|
|
17
|
+
compareTarget: ReactNode;
|
|
18
|
+
/** "v2": which version it is, when every version shares one file name. */
|
|
19
|
+
versionLabel?: string | null;
|
|
20
|
+
/** An editable artifact toggles Track changes; a read-only comparison gets a flip arrow. */
|
|
21
|
+
mode: 'track-changes' | 'flip';
|
|
22
|
+
showTrackChanges: boolean;
|
|
23
|
+
onToggleTrackChanges: () => void;
|
|
24
|
+
onFlip: () => void;
|
|
25
|
+
onStop: () => void;
|
|
26
|
+
labels?: Partial<ArtifactCompareBarLabels>;
|
|
27
|
+
testIds?: Partial<ArtifactCompareBarTestIds>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* "Compare vs. [version]" row contents: always an explicit text label (an icon-only pill was
|
|
31
|
+
* unclear), with Track changes or Flip, and Stop comparing.
|
|
32
|
+
*/
|
|
33
|
+
export declare function ArtifactCompareBar({ compareTarget, versionLabel, mode, showTrackChanges, onToggleTrackChanges, onFlip, onStop, labels, testIds, }: ArtifactCompareBarProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type ArtifactCompareBarLabels } from './ArtifactCompareBar';
|
|
3
|
+
import { type ArtifactEditorBodyTestIds } from './ArtifactEditorBody';
|
|
4
|
+
import type { RenderMarkdown } from './ArtifactRedlineView';
|
|
5
|
+
import { type ArtifactToolbarLabels } from './ArtifactToolbar';
|
|
6
|
+
import { type ArtifactVersionBarLabels, type ArtifactVersionBarTestIds } from './ArtifactVersionBar';
|
|
7
|
+
import type { VersionEntry } from './VersionTimeline';
|
|
8
|
+
export interface ArtifactEditorLabels {
|
|
9
|
+
toolbar: Partial<ArtifactToolbarLabels>;
|
|
10
|
+
versions: Partial<ArtifactVersionBarLabels>;
|
|
11
|
+
compare: Partial<ArtifactCompareBarLabels>;
|
|
12
|
+
}
|
|
13
|
+
export interface ArtifactEditorTestIds {
|
|
14
|
+
root: string;
|
|
15
|
+
compareRow: string;
|
|
16
|
+
body: Partial<ArtifactEditorBodyTestIds>;
|
|
17
|
+
versions: Partial<ArtifactVersionBarTestIds>;
|
|
18
|
+
}
|
|
19
|
+
export interface ArtifactEditorProps {
|
|
20
|
+
/** The saved markdown of the open version. */
|
|
21
|
+
content: string;
|
|
22
|
+
isEditing: boolean;
|
|
23
|
+
hasChanges: boolean;
|
|
24
|
+
isSaving: boolean;
|
|
25
|
+
isDraft?: boolean;
|
|
26
|
+
/** Narrow container: icon-only Edit and Compare. */
|
|
27
|
+
compact?: boolean;
|
|
28
|
+
canCompare: boolean;
|
|
29
|
+
/** A comparison is active. */
|
|
30
|
+
comparing: boolean;
|
|
31
|
+
/** The version being compared against. */
|
|
32
|
+
compareId?: string | null;
|
|
33
|
+
showTrackChanges: boolean;
|
|
34
|
+
/** The lineage, oldest first. The version bar shows only for two or more. */
|
|
35
|
+
versions?: VersionEntry[];
|
|
36
|
+
currentVersionId?: string;
|
|
37
|
+
onStartEdit: () => void;
|
|
38
|
+
onCancel: () => void;
|
|
39
|
+
/** Save the buffer as a new version. */
|
|
40
|
+
onSave: () => void;
|
|
41
|
+
onCompare: () => void;
|
|
42
|
+
onStopCompare: () => void;
|
|
43
|
+
onToggleTrackChanges: () => void;
|
|
44
|
+
/** Open another version from the version list. */
|
|
45
|
+
onOpenVersion?: (id: string) => void;
|
|
46
|
+
formatDate?: (iso: string) => string;
|
|
47
|
+
/** The editing surface (for example `ArtifactMarkdownEditor`). */
|
|
48
|
+
editor: ReactNode;
|
|
49
|
+
/** The track-changes panel (for example `ArtifactRedlineView`). */
|
|
50
|
+
redline: ReactNode;
|
|
51
|
+
renderMarkdown: RenderMarkdown;
|
|
52
|
+
/** Extra actions in the header (share, download...). */
|
|
53
|
+
actions?: ReactNode;
|
|
54
|
+
className?: string;
|
|
55
|
+
labels?: Partial<ArtifactEditorLabels>;
|
|
56
|
+
testIds?: Partial<ArtifactEditorTestIds>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The artifact surface: a header with the version bar and the toolbar (Edit, Cancel, Compare,
|
|
60
|
+
* Save as a new version), a compare row while comparing, and the body (read, edit or track
|
|
61
|
+
* changes). Everything is view-model driven: a host binds state with `useArtifactSession` from
|
|
62
|
+
* `@arbidocs/react/artifacts` and passes the editor and redline as slots.
|
|
63
|
+
*/
|
|
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;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { RenderMarkdown } from './ArtifactRedlineView';
|
|
3
|
+
export interface ArtifactEditorBodyTestIds {
|
|
4
|
+
/** The read-only rendered document. */
|
|
5
|
+
rendered: string;
|
|
6
|
+
/** The track-changes panel. */
|
|
7
|
+
trackChanges: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ArtifactEditorBodyProps {
|
|
10
|
+
/** The saved markdown, shown rendered while not editing. */
|
|
11
|
+
content: string;
|
|
12
|
+
isEditing: boolean;
|
|
13
|
+
/** A comparison is active. */
|
|
14
|
+
comparing: boolean;
|
|
15
|
+
/** Show the track-changes panel instead of the editor (needs `comparing`). */
|
|
16
|
+
showTrackChanges: boolean;
|
|
17
|
+
/** The editing surface (for example `ArtifactMarkdownEditor`). */
|
|
18
|
+
editor: ReactNode;
|
|
19
|
+
/** The track-changes panel (for example `ArtifactRedlineView`). */
|
|
20
|
+
redline: ReactNode;
|
|
21
|
+
renderMarkdown: RenderMarkdown;
|
|
22
|
+
/** Mod+S while editing; omit to leave the shortcut to the browser. */
|
|
23
|
+
onSave?: () => void;
|
|
24
|
+
/** Mod+S only saves when this is true (there are changes and no save is running). */
|
|
25
|
+
canSave?: boolean;
|
|
26
|
+
className?: string;
|
|
27
|
+
testIds?: Partial<ArtifactEditorBodyTestIds>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The body of an artifact: the rendered document when reading, the editor when editing, and the
|
|
31
|
+
* track-changes panel in its place while comparing. It is either typing or reviewing, never both
|
|
32
|
+
* stacked, as in Word's Show Markup. Mod+S saves from anywhere inside it.
|
|
33
|
+
*/
|
|
34
|
+
export declare function ArtifactEditorBody({ content, isEditing, comparing, showTrackChanges, editor, redline, renderMarkdown, onSave, canSave, className, testIds, }: ArtifactEditorBodyProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type RedlineLabels, type RedlineRegionKind } from './RedlineParts';
|
|
3
|
+
type DelProps = React.ComponentPropsWithoutRef<'del'> & {
|
|
4
|
+
'data-cid'?: string;
|
|
5
|
+
};
|
|
6
|
+
type InsProps = React.ComponentPropsWithoutRef<'ins'> & {
|
|
7
|
+
'data-cid'?: string;
|
|
8
|
+
};
|
|
9
|
+
/** The `<del>` / `<ins>` renderers a markdown renderer must use for the tracked changes. */
|
|
10
|
+
export interface RedlineMarkdownComponents {
|
|
11
|
+
del: React.FC<DelProps>;
|
|
12
|
+
ins: React.FC<InsProps>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Renders markdown to React. The redline markdown carries raw `<del>` / `<ins>` tags, so the
|
|
16
|
+
* renderer must allow inline HTML and honour `components`.
|
|
17
|
+
*/
|
|
18
|
+
export type RenderMarkdown = (markdown: string, components?: RedlineMarkdownComponents) => ReactNode;
|
|
19
|
+
/** What the view shows. Matches `RedlineState` of `@arbidocs/react/artifacts`. */
|
|
20
|
+
export type ArtifactRedlineState = {
|
|
21
|
+
kind: 'idle';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'computing';
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'ready';
|
|
26
|
+
markdown: string;
|
|
27
|
+
regions: {
|
|
28
|
+
id: string;
|
|
29
|
+
kind: RedlineRegionKind;
|
|
30
|
+
}[];
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'identical';
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'unavailable';
|
|
35
|
+
};
|
|
36
|
+
export interface ArtifactRedlineViewTestIds {
|
|
37
|
+
/** Replaces the whole `redline-revert-<cid>` id. */
|
|
38
|
+
revert: (cid: string) => string;
|
|
39
|
+
root: string;
|
|
40
|
+
}
|
|
41
|
+
export interface ArtifactRedlineViewProps {
|
|
42
|
+
state: ArtifactRedlineState;
|
|
43
|
+
renderMarkdown: RenderMarkdown;
|
|
44
|
+
/** Accept/reject mode: a margin button per change undoes that change. Omit for read-only. */
|
|
45
|
+
onRevert?: (regionId: string) => void;
|
|
46
|
+
/** A header row (for example `RedlineHeader`). */
|
|
47
|
+
header?: ReactNode;
|
|
48
|
+
labels?: Partial<RedlineLabels>;
|
|
49
|
+
testIds?: Partial<ArtifactRedlineViewTestIds>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Word-style track changes between two versions: deletions struck through in red, insertions
|
|
53
|
+
* underlined in blue, moves in green, status lines when there is nothing to diff, and (when
|
|
54
|
+
* `onRevert` is set) an undo button per change aligned in the margin.
|
|
55
|
+
*/
|
|
56
|
+
export declare function ArtifactRedlineView({ state, renderMarkdown, onRevert, header, labels, testIds, }: ArtifactRedlineViewProps): import("react").JSX.Element;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Every fixed string of the toolbar. Pass a partial `labels` to translate or reword. */
|
|
2
|
+
export interface ArtifactToolbarLabels {
|
|
3
|
+
/** The accessible name of the group of actions. */
|
|
4
|
+
group: string;
|
|
5
|
+
edit: string;
|
|
6
|
+
cancel: string;
|
|
7
|
+
cancelTitle: string;
|
|
8
|
+
compare: string;
|
|
9
|
+
compareTitle: string;
|
|
10
|
+
saveDocument: string;
|
|
11
|
+
saveAsVersion: string;
|
|
12
|
+
noChanges: string;
|
|
13
|
+
saving: string;
|
|
14
|
+
save: string;
|
|
15
|
+
saveVersion: string;
|
|
16
|
+
/** Announced (not shown) when there are unsaved changes. */
|
|
17
|
+
unsaved: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEFAULT_ARTIFACT_TOOLBAR_LABELS: ArtifactToolbarLabels;
|
|
20
|
+
export interface ArtifactToolbarTestIds {
|
|
21
|
+
edit: string;
|
|
22
|
+
cancel: string;
|
|
23
|
+
compare: string;
|
|
24
|
+
save: string;
|
|
25
|
+
unsavedDot: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ArtifactToolbarProps {
|
|
28
|
+
isEditing: boolean;
|
|
29
|
+
/** A new document that has no earlier version: "Save" instead of "Save version", no Cancel. */
|
|
30
|
+
isDraft?: boolean;
|
|
31
|
+
/** Narrow panel: icon-only Edit and Compare. Save keeps its label. */
|
|
32
|
+
compact?: boolean;
|
|
33
|
+
/** The buffer differs from the saved version. */
|
|
34
|
+
hasChanges: boolean;
|
|
35
|
+
isSaving: boolean;
|
|
36
|
+
/** Offer "Compare against the previous version". */
|
|
37
|
+
canCompare: boolean;
|
|
38
|
+
onStartEdit: () => void;
|
|
39
|
+
/** Discard the buffer and leave edit mode. */
|
|
40
|
+
onCancel: () => void;
|
|
41
|
+
onCompare: () => void;
|
|
42
|
+
/** Save the buffer as a NEW version. */
|
|
43
|
+
onSave: () => void;
|
|
44
|
+
className?: string;
|
|
45
|
+
labels?: Partial<ArtifactToolbarLabels>;
|
|
46
|
+
testIds?: Partial<ArtifactToolbarTestIds>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Edit, Cancel (discard), Compare and Save for an artifact. Save is the ONE filled button and only
|
|
50
|
+
* once there is something to save; a dot marks unsaved changes and a polite status announces them.
|
|
51
|
+
* Touch targets are 44px on coarse pointers.
|
|
52
|
+
*/
|
|
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>>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { VersionEntry } from './VersionTimeline';
|
|
2
|
+
/** Every fixed string of the version bar. Pass a partial `labels` to translate or reword. */
|
|
3
|
+
export interface ArtifactVersionBarLabels {
|
|
4
|
+
group: string;
|
|
5
|
+
/** "Version 2 of 3". */
|
|
6
|
+
position: (index: number, total: number) => string;
|
|
7
|
+
/** The only version: nothing to choose from yet. */
|
|
8
|
+
only: string;
|
|
9
|
+
latest: string;
|
|
10
|
+
select: string;
|
|
11
|
+
option: (index: number, date: string, isCurrent: boolean) => string;
|
|
12
|
+
compare: string;
|
|
13
|
+
compareTitle: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const DEFAULT_ARTIFACT_VERSION_BAR_LABELS: ArtifactVersionBarLabels;
|
|
16
|
+
export interface ArtifactVersionBarTestIds {
|
|
17
|
+
root: string;
|
|
18
|
+
position: string;
|
|
19
|
+
select: string;
|
|
20
|
+
compare: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ArtifactVersionBarProps {
|
|
23
|
+
/** The lineage, oldest first. */
|
|
24
|
+
versions: VersionEntry[];
|
|
25
|
+
/** The open version. */
|
|
26
|
+
currentId: string;
|
|
27
|
+
formatDate: (iso: string) => string;
|
|
28
|
+
/** Open another version (selected from the list). */
|
|
29
|
+
onOpen: (id: string) => void;
|
|
30
|
+
/** Compare the open version with the one before it. Omit to hide the button. */
|
|
31
|
+
onCompare?: () => void;
|
|
32
|
+
className?: string;
|
|
33
|
+
labels?: Partial<ArtifactVersionBarLabels>;
|
|
34
|
+
testIds?: Partial<ArtifactVersionBarTestIds>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Where you are in an artifact's versions: "Version 2 of 3", a list to open any version, and
|
|
38
|
+
* Compare with the previous one. Saving a new version is the toolbar's Save button; the editor
|
|
39
|
+
* lays the two out on one row. The list is a native select: it is keyboard and screen-reader
|
|
40
|
+
* complete and uses the phone's own picker.
|
|
41
|
+
*/
|
|
42
|
+
export declare function ArtifactVersionBar({ versions, currentId, formatDate, onOpen, onCompare, className, labels, testIds, }: ArtifactVersionBarProps): import("react").JSX.Element;
|
|
@@ -10,6 +10,10 @@ export interface RedlineLabels {
|
|
|
10
10
|
revertReplace: string;
|
|
11
11
|
revertAdd: string;
|
|
12
12
|
revertRemove: string;
|
|
13
|
+
/** The accessible name of the redline region. */
|
|
14
|
+
tracked: string;
|
|
15
|
+
/** Announced while the diff computes. */
|
|
16
|
+
computing: string;
|
|
13
17
|
}
|
|
14
18
|
export declare const DEFAULT_REDLINE_LABELS: RedlineLabels;
|
|
15
19
|
export type RedlineRegionKind = 'replace' | 'remove' | 'add' | 'move';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export interface ArtifactMarkdownEditorLabels {
|
|
3
|
+
/** The accessible name of the editor region. */
|
|
4
|
+
editor: string;
|
|
5
|
+
placeholder: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS: ArtifactMarkdownEditorLabels;
|
|
8
|
+
export interface ArtifactMarkdownEditorProps {
|
|
9
|
+
/** Current markdown (controlled by the parent). */
|
|
10
|
+
markdown: string;
|
|
11
|
+
/** Called with the new markdown whenever the document changes. */
|
|
12
|
+
onChange: (markdown: string) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Fired exactly once per editor instance, with the markdown the editor produces on mount.
|
|
15
|
+
* MDXEditor canonicalises the source as it parses (table padding, escapes, thematic-break
|
|
16
|
+
* style), so the first `onChange` after mount is the round-tripped form of the input, not a
|
|
17
|
+
* user edit. Use it to adopt the normalised form as the baseline so entering edit mode does
|
|
18
|
+
* not look dirty. Remount via `key` to receive it for the next document.
|
|
19
|
+
*/
|
|
20
|
+
onNormalized?: (normalized: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* A dictation control for the toolbar (the host owns recording and transcription, for example
|
|
23
|
+
* `@arbidocs/react`'s `InlineMicButton`). It gets a function that inserts text at the cursor.
|
|
24
|
+
*/
|
|
25
|
+
dictation?: (insert: (markdown: string) => void) => ReactNode;
|
|
26
|
+
labels?: Partial<ArtifactMarkdownEditorLabels>;
|
|
27
|
+
testId?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* WYSIWYG editor for artifact documents: the user edits the rendered document directly and the
|
|
31
|
+
* editor round-trips Markdown, so `onChange` always yields markdown a save can persist unchanged.
|
|
32
|
+
*
|
|
33
|
+
*
|
|
34
|
+
* Heavy (Lexical via MDXEditor): mount it behind a lazy boundary. The host imports
|
|
35
|
+
* `@mdxeditor/editor/style.css` once and, from the module that lazily imports this one, a module
|
|
36
|
+
* that defines the global `Prism` FIRST (assign the prismjs core to `globalThis.Prism`):
|
|
37
|
+
* `@lexical/code` reads it while it evaluates, and a library cannot order that in every bundler.
|
|
38
|
+
*/
|
|
39
|
+
export declare function ArtifactMarkdownEditor({ markdown, onChange, onNormalized, dictation, labels, testId, }: ArtifactMarkdownEditorProps): React.ReactElement;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
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');
|
|
8
|
+
|
|
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
|
+
|
|
86
|
+
exports.ArtifactMarkdownEditor = ArtifactMarkdownEditor;
|
|
87
|
+
exports.DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS = DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS;
|
|
88
|
+
//# sourceMappingURL=index.cjs.map
|
|
89
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ArtifactMarkdownEditor, DEFAULT_ARTIFACT_MARKDOWN_EDITOR_LABELS, type ArtifactMarkdownEditorLabels, type ArtifactMarkdownEditorProps, } from './ArtifactMarkdownEditor';
|
|
@@ -0,0 +1,86 @@
|
|
|
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 };
|
|
85
|
+
//# sourceMappingURL=index.js.map
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"]}
|