@elabs-ai/components-editor 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/chunk-LBC5VJBD.js +3748 -0
- package/dist/chunk-LBC5VJBD.js.map +1 -0
- package/dist/index.css +233 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +199 -0
- package/dist/index.js +362 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/monaco-environment.d.ts +2 -0
- package/dist/lib/monaco-environment.js +44 -0
- package/dist/lib/monaco-environment.js.map +1 -0
- package/dist/markdown/frontmatter.d.ts +11 -0
- package/dist/markdown/frontmatter.js +33 -0
- package/dist/markdown/frontmatter.js.map +1 -0
- package/dist/markdown/index.css +233 -0
- package/dist/markdown/index.css.map +1 -0
- package/dist/markdown/index.d.ts +1486 -0
- package/dist/markdown/index.js +4882 -0
- package/dist/markdown/index.js.map +1 -0
- package/dist/markdown/parse.d.ts +25 -0
- package/dist/markdown/parse.js +14 -0
- package/dist/markdown/parse.js.map +1 -0
- package/dist/markdown-editor-DfBZibAn.d.ts +702 -0
- package/package.json +101 -0
- package/src/ai-objects/ai-objects-integration.test.tsx +128 -0
- package/src/ai-objects/ai-objects.stories.tsx +233 -0
- package/src/ai-objects/ai-objects.test.tsx +205 -0
- package/src/ai-objects/decision-card.tsx +178 -0
- package/src/ai-objects/directives.ts +136 -0
- package/src/ai-objects/entity.tsx +181 -0
- package/src/ai-objects/index.ts +34 -0
- package/src/ai-objects/knowledge-card.tsx +143 -0
- package/src/calc-block/calc-block.stories.tsx +297 -0
- package/src/calc-block/calc-block.test.tsx +164 -0
- package/src/calc-block/calc-block.tsx +398 -0
- package/src/calc-block/calc-editor-monaco.ts +214 -0
- package/src/calc-block/calc-editor-prose.ts +128 -0
- package/src/calc-block/calc-editor.css +80 -0
- package/src/calc-block/calc-editor.stories.tsx +272 -0
- package/src/calc-block/calc-editor.test.ts +228 -0
- package/src/calc-block/calc-editor.ts +270 -0
- package/src/calc-block/calc-inline.stories.tsx +44 -0
- package/src/calc-block/calc-inline.test.tsx +44 -0
- package/src/calc-block/calc-inline.tsx +75 -0
- package/src/calc-block/index.ts +20 -0
- package/src/calc-block/types.ts +164 -0
- package/src/code-editor/code-editor.stories.tsx +218 -0
- package/src/code-editor/code-editor.test.tsx +134 -0
- package/src/code-editor/code-editor.tsx +250 -0
- package/src/code-editor/index.ts +6 -0
- package/src/code-workspace/code-workspace.stories.tsx +51 -0
- package/src/code-workspace/code-workspace.test.tsx +146 -0
- package/src/code-workspace/code-workspace.tsx +253 -0
- package/src/code-workspace/index.ts +6 -0
- package/src/copy-button/copy-button.tsx +51 -0
- package/src/copy-button/index.ts +1 -0
- package/src/css.d.ts +3 -0
- package/src/diff-editor/diff-editor.stories.tsx +44 -0
- package/src/diff-editor/diff-editor.test.tsx +68 -0
- package/src/diff-editor/diff-editor.tsx +151 -0
- package/src/diff-editor/index.ts +1 -0
- package/src/editor-context-menu/editor-context-menu.tsx +120 -0
- package/src/editor-context-menu/index.ts +1 -0
- package/src/editor-toolbar/editor-toolbar.tsx +83 -0
- package/src/editor-toolbar/index.ts +1 -0
- package/src/index.ts +48 -0
- package/src/lib/editor-completions-monaco.test.ts +206 -0
- package/src/lib/editor-completions-monaco.ts +127 -0
- package/src/lib/editor-completions.test.ts +156 -0
- package/src/lib/editor-completions.ts +153 -0
- package/src/lib/editor-content-access-prose.test.ts +411 -0
- package/src/lib/editor-content-access-prose.ts +172 -0
- package/src/lib/editor-content-access.test.ts +182 -0
- package/src/lib/editor-content-access.ts +109 -0
- package/src/lib/languages.ts +32 -0
- package/src/lib/markdown/diff.test.ts +80 -0
- package/src/lib/markdown/diff.ts +194 -0
- package/src/lib/markdown/directives.ts +342 -0
- package/src/lib/markdown/frontmatter.ts +50 -0
- package/src/lib/markdown/markdown-scale.test.ts +65 -0
- package/src/lib/markdown/markdown-scale.ts +62 -0
- package/src/lib/markdown/merge.test.ts +64 -0
- package/src/lib/markdown/merge.ts +158 -0
- package/src/lib/markdown/slugify.test.ts +156 -0
- package/src/lib/markdown/slugify.ts +47 -0
- package/src/lib/monaco-environment.ts +103 -0
- package/src/lib/monaco-theme-bridge.ts +293 -0
- package/src/lib/use-data-theme.ts +61 -0
- package/src/markdown/frontmatter.ts +14 -0
- package/src/markdown/index.ts +323 -0
- package/src/markdown/parse.test.ts +60 -0
- package/src/markdown/parse.ts +38 -0
- package/src/markdown-academic/citations.test.ts +77 -0
- package/src/markdown-academic/citations.tsx +442 -0
- package/src/markdown-academic/footnotes.tsx +235 -0
- package/src/markdown-academic/index.ts +32 -0
- package/src/markdown-academic/math.tsx +163 -0
- package/src/markdown-academic/toc.tsx +88 -0
- package/src/markdown-editor/completions/completions-menu.tsx +96 -0
- package/src/markdown-editor/completions/completions-prose.test.ts +356 -0
- package/src/markdown-editor/completions/completions-prose.ts +313 -0
- package/src/markdown-editor/completions/completions-widget.tsx +75 -0
- package/src/markdown-editor/completions/index.ts +37 -0
- package/src/markdown-editor/directive-nodes.ts +151 -0
- package/src/markdown-editor/directive-views.test.tsx +189 -0
- package/src/markdown-editor/directive-views.tsx +795 -0
- package/src/markdown-editor/exit-keymap.test.ts +88 -0
- package/src/markdown-editor/exit-keymap.ts +87 -0
- package/src/markdown-editor/index.ts +6 -0
- package/src/markdown-editor/markdown-editor.css +250 -0
- package/src/markdown-editor/markdown-editor.directives.test.tsx +105 -0
- package/src/markdown-editor/markdown-editor.fill.test.ts +34 -0
- package/src/markdown-editor/markdown-editor.paste-embed.test.tsx +297 -0
- package/src/markdown-editor/markdown-editor.stories.tsx +560 -0
- package/src/markdown-editor/markdown-editor.strictmode.test.tsx +38 -0
- package/src/markdown-editor/markdown-editor.table.test.tsx +287 -0
- package/src/markdown-editor/markdown-editor.tsx +560 -0
- package/src/markdown-editor/milkdown-react/editor.tsx +33 -0
- package/src/markdown-editor/milkdown-react/index.ts +8 -0
- package/src/markdown-editor/milkdown-react/types.ts +27 -0
- package/src/markdown-editor/milkdown-react/use-editor.ts +27 -0
- package/src/markdown-editor/milkdown-react/use-get-editor.ts +56 -0
- package/src/markdown-editor/milkdown-react/use-instance.ts +23 -0
- package/src/markdown-editor/paste-embed.ts +355 -0
- package/src/markdown-editor/slash/brand-slash-commands.test.ts +194 -0
- package/src/markdown-editor/slash/brand-slash-commands.ts +324 -0
- package/src/markdown-editor/slash/brand-slash-plugin.test.ts +254 -0
- package/src/markdown-editor/slash/brand-slash-plugin.ts +385 -0
- package/src/markdown-editor/slash/index.ts +107 -0
- package/src/markdown-editor/slash/insert-directive.test.ts +263 -0
- package/src/markdown-editor/slash/insert-directive.ts +345 -0
- package/src/markdown-editor/slash/monaco-slash-menu.test.tsx +198 -0
- package/src/markdown-editor/slash/monaco-slash-menu.tsx +356 -0
- package/src/markdown-editor/slash/shortcut-monaco.ts +69 -0
- package/src/markdown-editor/slash/shortcut.test.ts +157 -0
- package/src/markdown-editor/slash/shortcut.ts +57 -0
- package/src/markdown-editor/slash/slash-menu.stories.tsx +139 -0
- package/src/markdown-editor/slash/slash-menu.tsx +115 -0
- package/src/markdown-editor/slash/slash-scroll.test.tsx +52 -0
- package/src/markdown-editor/slash/slash-widget.tsx +97 -0
- package/src/markdown-editor/slash/source-slash-trigger.test.ts +42 -0
- package/src/markdown-editor/slash/source-slash-trigger.ts +46 -0
- package/src/markdown-editor/table-view.tsx +249 -0
- package/src/markdown-iteration/directive.tsx +92 -0
- package/src/markdown-iteration/edit-context.ts +56 -0
- package/src/markdown-iteration/index.ts +24 -0
- package/src/markdown-iteration/iteration-block.test.tsx +138 -0
- package/src/markdown-iteration/iteration-builder-dialog.stories.tsx +293 -0
- package/src/markdown-iteration/iteration-builder-dialog.tsx +312 -0
- package/src/markdown-iteration/iteration-builder.test.ts +252 -0
- package/src/markdown-iteration/iteration-builder.ts +303 -0
- package/src/markdown-iteration/iteration.test.ts +56 -0
- package/src/markdown-iteration/iteration.tsx +333 -0
- package/src/markdown-iteration/template-dialog.stories.tsx +63 -0
- package/src/markdown-iteration/template-dialog.test.tsx +104 -0
- package/src/markdown-iteration/template-dialog.tsx +116 -0
- package/src/markdown-outline/document-outline.stories.tsx +76 -0
- package/src/markdown-outline/document-outline.tsx +83 -0
- package/src/markdown-outline/index.ts +2 -0
- package/src/markdown-outline/markdown-outline.test.ts +49 -0
- package/src/markdown-outline/markdown-outline.ts +60 -0
- package/src/markdown-preview/code-fence.tsx +193 -0
- package/src/markdown-preview/index.ts +8 -0
- package/src/markdown-preview/markdown-preview-academic.stories.tsx +203 -0
- package/src/markdown-preview/markdown-preview-academic.test.tsx +257 -0
- package/src/markdown-preview/markdown-preview-iteration-calc.test.tsx +71 -0
- package/src/markdown-preview/markdown-preview-iteration-nested.test.tsx +58 -0
- package/src/markdown-preview/markdown-preview-iteration.stories.tsx +187 -0
- package/src/markdown-preview/markdown-preview-iteration.test.tsx +90 -0
- package/src/markdown-preview/markdown-preview-linking.test.tsx +61 -0
- package/src/markdown-preview/markdown-preview-transclusion.test.tsx +33 -0
- package/src/markdown-preview/markdown-preview.stories.tsx +108 -0
- package/src/markdown-preview/markdown-preview.test.tsx +411 -0
- package/src/markdown-preview/markdown-preview.tsx +1541 -0
- package/src/markdown-toolbar/index.ts +8 -0
- package/src/markdown-toolbar/markdown-commands.test.ts +84 -0
- package/src/markdown-toolbar/markdown-commands.ts +104 -0
- package/src/markdown-toolbar/markdown-toolbar.stories.tsx +56 -0
- package/src/markdown-toolbar/markdown-toolbar.tsx +263 -0
- package/src/markdown-workspace/focus-writing.test.ts +52 -0
- package/src/markdown-workspace/focus-writing.ts +38 -0
- package/src/markdown-workspace/index.ts +6 -0
- package/src/markdown-workspace/markdown-workspace.stories.tsx +688 -0
- package/src/markdown-workspace/markdown-workspace.test.tsx +326 -0
- package/src/markdown-workspace/markdown-workspace.tsx +787 -0
- package/src/mermaid-diagram/index.ts +1 -0
- package/src/mermaid-diagram/mermaid-diagram.stories.tsx +42 -0
- package/src/mermaid-diagram/mermaid-diagram.test.tsx +86 -0
- package/src/mermaid-diagram/mermaid-diagram.tsx +318 -0
- package/src/mermaid-diagram/mermaid-viewer.test.tsx +89 -0
- package/src/mermaid-diagram/mermaid-viewer.tsx +367 -0
- package/src/mermaid-diagram/real-parse.test.ts +42 -0
- package/src/mermaid-diagram/remediate.test.ts +60 -0
- package/src/mermaid-diagram/remediate.ts +124 -0
- package/src/mermaid-workspace/index.ts +1 -0
- package/src/mermaid-workspace/mermaid-workspace.stories.tsx +28 -0
- package/src/mermaid-workspace/mermaid-workspace.tsx +71 -0
- package/src/metric-block/index.ts +1 -0
- package/src/metric-block/metric-block.stories.tsx +40 -0
- package/src/metric-block/metric-block.tsx +14 -0
- package/src/monaco-workers.d.ts +10 -0
- package/src/prose/index.ts +14 -0
- package/src/prose/prose.stories.tsx +44 -0
- package/src/prose/prose.test.tsx +44 -0
- package/src/prose/prose.tsx +21 -0
- package/src/timeline/index.ts +18 -0
|
@@ -0,0 +1,702 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
import * as monaco from 'monaco-editor';
|
|
4
|
+
import { IRange } from 'monaco-editor';
|
|
5
|
+
import { Ctx } from '@milkdown/kit/ctx';
|
|
6
|
+
import { Schema, NodeType } from '@milkdown/kit/prose/model';
|
|
7
|
+
import { Command } from '@milkdown/kit/prose/state';
|
|
8
|
+
|
|
9
|
+
type MonacoCodeEditor = monaco.editor.IStandaloneCodeEditor;
|
|
10
|
+
/** A Monaco editor action (system command + optional hotkey + palette/menu entry). */
|
|
11
|
+
type EditorAction = monaco.editor.IActionDescriptor;
|
|
12
|
+
interface CodeEditorProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
|
|
13
|
+
/** Controlled content. Pair with `onChange`. */
|
|
14
|
+
value?: string;
|
|
15
|
+
/** Initial content for uncontrolled use. */
|
|
16
|
+
defaultValue?: string;
|
|
17
|
+
/** Fires on every edit with the full document text. */
|
|
18
|
+
onChange?: (value: string) => void;
|
|
19
|
+
/** Monaco language id (e.g. "typescript", "json"). Defaults to "typescript". */
|
|
20
|
+
language?: string;
|
|
21
|
+
/** Model path/URI — drives per-file language services + diagnostics. */
|
|
22
|
+
path?: string;
|
|
23
|
+
/** Render the editor read-only. */
|
|
24
|
+
readOnly?: boolean;
|
|
25
|
+
/** Editor height. Number → px. Defaults to "100%" (size via the parent). */
|
|
26
|
+
height?: number | string;
|
|
27
|
+
/** Passthrough Monaco construction options (merged over the defaults). */
|
|
28
|
+
options?: monaco.editor.IStandaloneEditorConstructionOptions;
|
|
29
|
+
/**
|
|
30
|
+
* Accessible name for the editor. Maps onto Monaco's `ariaLabel` construction
|
|
31
|
+
* option AND the inner screen-reader `<textarea>` (`aria-label`), so assistive
|
|
32
|
+
* tech announces a name. Spreading `aria-label` via `...props` only lands on the
|
|
33
|
+
* wrapper div and never reaches Monaco's focusable textarea — use this instead.
|
|
34
|
+
*/
|
|
35
|
+
ariaLabel?: string;
|
|
36
|
+
/** Sets `aria-invalid` on Monaco's inner `<textarea>` to convey validity. */
|
|
37
|
+
ariaInvalid?: boolean;
|
|
38
|
+
/** Sets `aria-describedby` on Monaco's inner `<textarea>` (e.g. an error id). */
|
|
39
|
+
ariaDescribedBy?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Right-click menu. `"brand"` (default) replaces Monaco's built-in menu with
|
|
42
|
+
* brand-ui's `ContextMenu`; `"monaco"` keeps Monaco's themed menu; `"none"`
|
|
43
|
+
* disables it.
|
|
44
|
+
*/
|
|
45
|
+
contextMenu?: "brand" | "monaco" | "none";
|
|
46
|
+
/** Called once the editor instance + monaco namespace are ready. */
|
|
47
|
+
onMount?: (editor: MonacoCodeEditor, monacoApi: typeof monaco) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Declarative Monaco editor actions — each registers a command (run on its
|
|
50
|
+
* `keybindings`, in the command palette, and optionally the context menu via
|
|
51
|
+
* `contextMenuGroupId`). Wraps `editor.addAction`; re-registered when the array
|
|
52
|
+
* identity changes, disposed on unmount. Build keybindings with the re-exported
|
|
53
|
+
* `monaco` namespace, e.g. `keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Slash]`.
|
|
54
|
+
*
|
|
55
|
+
* Note: a context-menu entry only shows when `contextMenu="monaco"`, but the
|
|
56
|
+
* keybinding and command palette work regardless. Memoize `actions` to avoid
|
|
57
|
+
* re-registering on every render.
|
|
58
|
+
*/
|
|
59
|
+
actions?: EditorAction[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A token-themed Monaco editor wrapped as a brand-ui React component. Monaco
|
|
63
|
+
* renders its own editing surface + widgets; this wrapper owns lifecycle,
|
|
64
|
+
* controlled/uncontrolled value, and applies the brand theme bridge so the
|
|
65
|
+
* editor matches the active `data-theme` (all three themes).
|
|
66
|
+
*
|
|
67
|
+
* Workers (for completions/diagnostics) are wired by importing
|
|
68
|
+
* `@elabs-ai/components-editor/monaco-environment` once at the app entry.
|
|
69
|
+
*/
|
|
70
|
+
declare const CodeEditor: react.ForwardRefExoticComponent<CodeEditorProps & react.RefAttributes<monaco.editor.IStandaloneCodeEditor | null>>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* CalcBlock contracts — the shape the consumer's `evaluate` hook returns.
|
|
74
|
+
*
|
|
75
|
+
* The library RENDERS; the consumer EVALUATES. The math engine is app/domain
|
|
76
|
+
* logic and must NOT live in the design system — so these are pure types and the
|
|
77
|
+
* library never bundles a calculator (mirrors how `resolveUrl` keeps URL
|
|
78
|
+
* resolution in the consumer). A consumer produces a `CalcSheet` from a ```calc
|
|
79
|
+
* source; CalcBlock paints it.
|
|
80
|
+
*/
|
|
81
|
+
type CalcValueKind = "number" | "quantity" | "currency" | "date" | "duration" | "percent" | "text" | "error";
|
|
82
|
+
/** A typed result value; `display` is the locale-formatted, tabular-ready string. */
|
|
83
|
+
interface CalcValue {
|
|
84
|
+
kind: CalcValueKind;
|
|
85
|
+
raw: number | string;
|
|
86
|
+
unit?: string;
|
|
87
|
+
display: string;
|
|
88
|
+
}
|
|
89
|
+
type CalcTokenKind = "number" | "unit" | "currency" | "operator" | "function" | "constant" | "comment" | "var-def" | "var-ref" | "line-ref" | "unknown";
|
|
90
|
+
/** One highlighted span within a source line — 0-based columns, `end` exclusive. */
|
|
91
|
+
interface CalcToken {
|
|
92
|
+
start: number;
|
|
93
|
+
end: number;
|
|
94
|
+
kind: CalcTokenKind;
|
|
95
|
+
/** `false` → a non-fatal warning style (unknown identifier / dangling ref). */
|
|
96
|
+
resolved: boolean;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Presentation hint: a rule (horizontal divider) drawn below a row — a `"dotted"`
|
|
100
|
+
* hairline, a `"single"` solid line, or a `"double"` line (e.g. above a subtotal).
|
|
101
|
+
* Pure presentation: the library renders it; the evaluator decides which rows get one.
|
|
102
|
+
*/
|
|
103
|
+
type CalcRule = "dotted" | "single" | "double";
|
|
104
|
+
/**
|
|
105
|
+
* Presentation hint: tint a row's background with a semantic status wash
|
|
106
|
+
* (theme-safe `bg-<token>/10`, matching the house status vocabulary). `"muted"`
|
|
107
|
+
* is a neutral, non-status tint. The evaluator decides; the library paints.
|
|
108
|
+
*/
|
|
109
|
+
type CalcTint = "primary" | "success" | "warning" | "destructive" | "info" | "muted";
|
|
110
|
+
/** One evaluated source line: its highlight tokens, and a value OR an error. */
|
|
111
|
+
interface CalcLineResult {
|
|
112
|
+
/** 1-based line within the calc source. */
|
|
113
|
+
line: number;
|
|
114
|
+
tokens: CalcToken[];
|
|
115
|
+
value?: CalcValue;
|
|
116
|
+
/** A per-line error rendered inline; never thrown. */
|
|
117
|
+
error?: {
|
|
118
|
+
message: string;
|
|
119
|
+
};
|
|
120
|
+
/** Presentation hint: draw a rule (divider) below this row. */
|
|
121
|
+
rule?: CalcRule;
|
|
122
|
+
/** Presentation hint: tint this row's background with a semantic wash. */
|
|
123
|
+
tint?: CalcTint;
|
|
124
|
+
}
|
|
125
|
+
interface CalcSheet {
|
|
126
|
+
results: CalcLineResult[];
|
|
127
|
+
/** Running total for the block. */
|
|
128
|
+
total?: CalcValue;
|
|
129
|
+
}
|
|
130
|
+
interface CalcContext {
|
|
131
|
+
docPath?: string;
|
|
132
|
+
}
|
|
133
|
+
/** The consumer-supplied evaluator (sync, like `resolveUrl`). */
|
|
134
|
+
type EvaluateCalc = (source: string, ctx?: CalcContext) => CalcSheet;
|
|
135
|
+
/**
|
|
136
|
+
* Tokenize ONE calc source line into highlight spans (the columns the library
|
|
137
|
+
* paints). Called per line, so the returned {@link CalcToken} `start`/`end`
|
|
138
|
+
* columns are relative to `line` — the same shape `evaluate` already returns on
|
|
139
|
+
* each `CalcLineResult.tokens`. Sync, like `resolveUrl`.
|
|
140
|
+
*/
|
|
141
|
+
type CalcTokenize = (line: string, ctx?: CalcContext) => CalcToken[];
|
|
142
|
+
/** A completion category — drives the icon (Monaco) / glyph + label (WYSIWYG). */
|
|
143
|
+
type CalcCompletionKind = "variable" | "function" | "unit" | "currency" | "constant" | "reference" | "keyword" | "snippet";
|
|
144
|
+
/** One autocomplete suggestion offered inside a ```calc fence. */
|
|
145
|
+
interface CalcCompletion {
|
|
146
|
+
/** Text shown in the completion list. */
|
|
147
|
+
label: string;
|
|
148
|
+
/** Text inserted when the item is chosen (replaces the typed `prefix`). */
|
|
149
|
+
insert: string;
|
|
150
|
+
/** Secondary detail shown muted beside the label (e.g. a type or preview). */
|
|
151
|
+
detail?: string;
|
|
152
|
+
/** Category; selects the suggestion icon. Defaults to `"variable"`. */
|
|
153
|
+
kind?: CalcCompletionKind;
|
|
154
|
+
}
|
|
155
|
+
/** What the editor knows at the caret when it asks the consumer for completions. */
|
|
156
|
+
interface CalcCompletionContext extends CalcContext {
|
|
157
|
+
/** The full calc fence body (all lines). */
|
|
158
|
+
source: string;
|
|
159
|
+
/** The current line's text (the line the caret is on). */
|
|
160
|
+
line: string;
|
|
161
|
+
/** 1-based line of the caret within the fence body. */
|
|
162
|
+
lineNumber: number;
|
|
163
|
+
/** 0-based caret column within `line`. */
|
|
164
|
+
column: number;
|
|
165
|
+
/** The identifier characters immediately before the caret (the word typed). */
|
|
166
|
+
prefix: string;
|
|
167
|
+
}
|
|
168
|
+
/** Suggest completions at the caret inside a ```calc fence (sync). */
|
|
169
|
+
type CalcComplete = (ctx: CalcCompletionContext) => CalcCompletion[];
|
|
170
|
+
/**
|
|
171
|
+
* The opt-in authoring hooks threaded onto `MarkdownEditor` / `MarkdownWorkspace`
|
|
172
|
+
* via the `calc` prop (off by default). Each capability is independent:
|
|
173
|
+
* - `tokenize` → syntax highlighting (falls back to `evaluate`'s per-line
|
|
174
|
+
* `tokens` when omitted, so a consumer who already wrote `evaluate` gets
|
|
175
|
+
* highlighting for free).
|
|
176
|
+
* - `evaluate` → per-line result inlays (the computed answer, shown after the
|
|
177
|
+
* line). Reuses the existing {@link EvaluateCalc} contract.
|
|
178
|
+
* - `complete` → autocomplete inside the fence (Monaco surface).
|
|
179
|
+
*/
|
|
180
|
+
interface CalcEditorHooks {
|
|
181
|
+
tokenize?: CalcTokenize;
|
|
182
|
+
complete?: CalcComplete;
|
|
183
|
+
evaluate?: EvaluateCalc;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Engine-agnostic completion-provider contract (#283) — the `completions` prop
|
|
188
|
+
* on `MarkdownWorkspace` (and, via it, the WYSIWYG `MarkdownEditor`).
|
|
189
|
+
*
|
|
190
|
+
* ISOLATION INVARIANT (mirrors `editor-content-access.ts`): this file imports
|
|
191
|
+
* NOTHING engine-specific — no `monaco-editor`, no `@milkdown`. It is the
|
|
192
|
+
* dependency-light leaf both engine adapters (`editor-completions-monaco.ts` for
|
|
193
|
+
* Monaco, `markdown-editor/completions/` for Milkdown/ProseMirror) build on, so a
|
|
194
|
+
* consumer can import the TYPES with zero engine imports (#283 acceptance: "zero
|
|
195
|
+
* `monaco-editor` imports in app code").
|
|
196
|
+
*
|
|
197
|
+
* D5 / the calc `complete` hook precedent: the library only REGISTERS the
|
|
198
|
+
* provider and RENDERS its suggestions — candidate list, filtering/ranking, and
|
|
199
|
+
* insert text are entirely consumer-owned. Nothing here fetches anything; a
|
|
200
|
+
* throwing/rejecting `provide()` degrades to "no suggestions" (never blanks or
|
|
201
|
+
* throws), the same degrade-safely contract as `resolveResults`/`CalcBlock`.
|
|
202
|
+
*/
|
|
203
|
+
/** One completion candidate a provider offers at the caret. */
|
|
204
|
+
interface EditorCompletionItem {
|
|
205
|
+
/** Text shown in the suggestion list. */
|
|
206
|
+
label: string;
|
|
207
|
+
/** Text inserted when the item is chosen. */
|
|
208
|
+
insertText: string;
|
|
209
|
+
/** Secondary detail shown muted beside the label. */
|
|
210
|
+
detail?: string;
|
|
211
|
+
/**
|
|
212
|
+
* Start column (1-based, Monaco convention) of the already-typed token to
|
|
213
|
+
* replace. Defaults to the start of the "trigger query" — the run of text
|
|
214
|
+
* typed since the provider's trigger character (see {@link triggerQueryStart}).
|
|
215
|
+
*/
|
|
216
|
+
replaceFrom?: number;
|
|
217
|
+
}
|
|
218
|
+
/** What a provider knows at the caret when it is asked for completions. */
|
|
219
|
+
interface EditorCompletionContext {
|
|
220
|
+
/** The full document text. */
|
|
221
|
+
source: string;
|
|
222
|
+
/** 1-based line number. */
|
|
223
|
+
line: number;
|
|
224
|
+
/** 1-based column. */
|
|
225
|
+
column: number;
|
|
226
|
+
/** The full text of the current line. */
|
|
227
|
+
lineText: string;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* A declarative completion source. Registered ONCE per `MarkdownWorkspace` (or
|
|
231
|
+
* `MarkdownEditor`) tree via the `completions` prop — the library owns the
|
|
232
|
+
* engine registration lifecycle (Monaco's `registerCompletionItemProvider` is
|
|
233
|
+
* global-per-language, refcounted here; see `editor-completions-monaco.ts`).
|
|
234
|
+
*/
|
|
235
|
+
interface EditorCompletionProvider {
|
|
236
|
+
/** Stable id — surfaced for consumer bookkeeping (not currently rendered). */
|
|
237
|
+
id: string;
|
|
238
|
+
/** Characters that (re)open the suggestion list, e.g. `["["]`. */
|
|
239
|
+
triggerCharacters?: string[];
|
|
240
|
+
/** Return the candidates for the caret described by `ctx`. May be async. */
|
|
241
|
+
provide(ctx: EditorCompletionContext): EditorCompletionItem[] | Promise<EditorCompletionItem[]>;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Find the 1-based column right after the LAST occurrence, before `column`, of
|
|
245
|
+
* any of `triggerCharacters` in `lineText` — the start of the "trigger query"
|
|
246
|
+
* (the text typed since the trigger character). `null` when no trigger
|
|
247
|
+
* character precedes the caret on this line (falls back to inserting at the
|
|
248
|
+
* bare caret — see {@link resolveReplaceRange}).
|
|
249
|
+
*
|
|
250
|
+
* Deliberately the LAST occurrence, not the first: `[[note` (triggerCharacters
|
|
251
|
+
* `["["]`) resolves the query start to right after the SECOND `[`, so the
|
|
252
|
+
* inserted text replaces only `note`, preserving the `[[` the user typed.
|
|
253
|
+
*/
|
|
254
|
+
declare function triggerQueryStart(lineText: string, column: number, triggerCharacters: string[] | undefined): number | null;
|
|
255
|
+
/** A 1-based, Monaco-`IRange`-shaped span (structural — no monaco import). */
|
|
256
|
+
interface CompletionReplaceRange {
|
|
257
|
+
startLineNumber: number;
|
|
258
|
+
startColumn: number;
|
|
259
|
+
endLineNumber: number;
|
|
260
|
+
endColumn: number;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Resolve the range an item's `insertText` replaces: `item.replaceFrom` when
|
|
264
|
+
* given, else the trigger-query start (see {@link triggerQueryStart}), else the
|
|
265
|
+
* bare caret (a pure insert, nothing replaced). Always ends at the caret, on
|
|
266
|
+
* the caret's line — a completion never spans multiple lines.
|
|
267
|
+
*/
|
|
268
|
+
declare function resolveReplaceRange(item: EditorCompletionItem, position: {
|
|
269
|
+
lineNumber: number;
|
|
270
|
+
column: number;
|
|
271
|
+
}, lineText: string, triggerCharacters: string[] | undefined): CompletionReplaceRange;
|
|
272
|
+
/** One resolved completion item, paired with the provider that produced it. */
|
|
273
|
+
interface CompletionMatch {
|
|
274
|
+
provider: EditorCompletionProvider;
|
|
275
|
+
item: EditorCompletionItem;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Call every provider's `provide(ctx)`, collect the results, and pair each item
|
|
279
|
+
* back with its provider (so a caller can resolve a per-provider replace range
|
|
280
|
+
* via that provider's `triggerCharacters`). Never throws: a provider whose
|
|
281
|
+
* `provide()` throws or whose returned promise rejects contributes zero items
|
|
282
|
+
* (mirrors `resolveResults`'s calc-hook degrade-safely contract) — one bad
|
|
283
|
+
* provider never blanks another's suggestions.
|
|
284
|
+
*/
|
|
285
|
+
declare function collectCompletions(providers: EditorCompletionProvider[], ctx: EditorCompletionContext): Promise<CompletionMatch[]>;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Engine-agnostic editor content-access interface + Monaco adapter.
|
|
289
|
+
*
|
|
290
|
+
* ISOLATION INVARIANT: this file imports ONLY `monaco-editor` and the
|
|
291
|
+
* `MonacoCodeEditor` type from `../code-editor`. It MUST NOT import
|
|
292
|
+
* `editor-content-access-prose.ts` or anything from `@milkdown`, or the
|
|
293
|
+
* `@milkdown` graph leaks into the `.` barrel (#271-inverse).
|
|
294
|
+
*/
|
|
295
|
+
|
|
296
|
+
/** A snapshot of the editor's current selection. Text, not engine positions —
|
|
297
|
+
* that is what an AI assistant needs and it keeps the interface engine-agnostic. */
|
|
298
|
+
interface EditorSelection {
|
|
299
|
+
/**
|
|
300
|
+
* The selected text. Plain text for Monaco. For the Milkdown WYSIWYG it is the
|
|
301
|
+
* selection SERIALIZED TO MARKDOWN by default (so `**bold**`, links, lists round-trip);
|
|
302
|
+
* pass `{ fidelity: "plainText" }` to the adapter to get `doc.textBetween` instead.
|
|
303
|
+
*/
|
|
304
|
+
text: string;
|
|
305
|
+
/** `true` when the selection is collapsed (a bare caret, nothing highlighted). */
|
|
306
|
+
empty: boolean;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Engine-agnostic, text-oriented access to an editor's content + selection — the
|
|
310
|
+
* uniform surface an external AI assistant drives across the Monaco code editors
|
|
311
|
+
* AND the Milkdown WYSIWYG markdown editor.
|
|
312
|
+
*
|
|
313
|
+
* D5: this manipulates EDITOR CONTENT only. It performs no model calls, no transport,
|
|
314
|
+
* no fetch. The app owns the AI call and APPLIES the result via these methods.
|
|
315
|
+
*
|
|
316
|
+
* `replaceSelection` and `insertAtCursor` are equivalent primitives (both replace the
|
|
317
|
+
* active range; an empty range is the caret) — two names for two reader intents.
|
|
318
|
+
*/
|
|
319
|
+
interface EditorContentAccess {
|
|
320
|
+
/** The full document text (Monaco: source; Milkdown: serialized markdown). */
|
|
321
|
+
getText(): string;
|
|
322
|
+
/** A snapshot of the current selection (selected text + whether collapsed). */
|
|
323
|
+
getSelection(): EditorSelection;
|
|
324
|
+
/** Replace the current selection; a collapsed selection inserts at the caret. */
|
|
325
|
+
replaceSelection(text: string): void;
|
|
326
|
+
/**
|
|
327
|
+
* Insert at the caret; a non-empty selection is replaced (platform "typing" semantics).
|
|
328
|
+
* Equivalent to `replaceSelection` — two names for two reader intents (agent-legibility).
|
|
329
|
+
*/
|
|
330
|
+
insertAtCursor(text: string): void;
|
|
331
|
+
/** Move focus to the editing surface (so the user can keep typing after an apply). */
|
|
332
|
+
focus(): void;
|
|
333
|
+
/**
|
|
334
|
+
* Subscribe to selection changes. Fires with a fresh `EditorSelection` whenever the
|
|
335
|
+
* selection or caret moves. Returns an unsubscribe function — the caller MUST call it
|
|
336
|
+
* (e.g. in a React effect cleanup) to dispose the underlying engine listener.
|
|
337
|
+
*/
|
|
338
|
+
onSelectionChange(listener: (selection: EditorSelection) => void): () => void;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Wrap a live Monaco `IStandaloneCodeEditor` as the engine-agnostic
|
|
342
|
+
* {@link EditorContentAccess}. The `CodeEditor` / `DiffEditor` / `CodeWorkspace`
|
|
343
|
+
* `ref` already exposes the raw Monaco instance — pass it here to get the
|
|
344
|
+
* uniform shape used by the markdown surfaces.
|
|
345
|
+
*
|
|
346
|
+
* For a `DiffEditor`, pass the modified (editable) side:
|
|
347
|
+
* `monacoContentAccess(diffRef.current!.getModifiedEditor())`.
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* const editorRef = useRef<MonacoCodeEditor>(null);
|
|
351
|
+
* // ...later
|
|
352
|
+
* const access = monacoContentAccess(editorRef.current!);
|
|
353
|
+
* access.insertAtCursor(aiText);
|
|
354
|
+
*/
|
|
355
|
+
declare function monacoContentAccess(editor: MonacoCodeEditor): EditorContentAccess;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* paste-embed — ProseMirror plugin + helper for image paste/drop embedding.
|
|
359
|
+
*
|
|
360
|
+
* When `onEmbedAsset` is provided by the host:
|
|
361
|
+
* 1. Intercepts paste (from clipboard) or drop events carrying image files.
|
|
362
|
+
* 2. Inserts an inline "uploading…" widget Decoration at the caret/drop position.
|
|
363
|
+
* 3. Calls `onEmbedAsset(file)` and on resolve inserts a real image node, removing
|
|
364
|
+
* the placeholder.
|
|
365
|
+
* 4. On reject removes the placeholder and renders a transient inline error
|
|
366
|
+
* decoration (role="alert", auto-dismissed after 4 s) + toast.error().
|
|
367
|
+
*
|
|
368
|
+
* The plugin is a raw `$prose` ProseMirror plugin (same pattern as the slash menu),
|
|
369
|
+
* so it pulls zero new dependencies beyond what Milkdown already provides.
|
|
370
|
+
*
|
|
371
|
+
* A11y:
|
|
372
|
+
* - Upload placeholder: role="status" aria-live="polite"
|
|
373
|
+
* - Error decoration: role="alert" (assertive; fires once and auto-dismisses)
|
|
374
|
+
*
|
|
375
|
+
* Motion: gated via `duration-normal ease-standard motion-reduce:transition-none`
|
|
376
|
+
* token utilities (defined in @elabs-ai/components-tokens).
|
|
377
|
+
*/
|
|
378
|
+
|
|
379
|
+
/** The host-provided hook: receives a File, resolves to a URL/path string. */
|
|
380
|
+
type EmbedAssetFn = (file: File) => Promise<string>;
|
|
381
|
+
|
|
382
|
+
interface IterationEditRequest {
|
|
383
|
+
/** Which directive asked to be edited. */
|
|
384
|
+
kind: "iterate" | "pivot";
|
|
385
|
+
/** The current template markdown (the node body, serialized). */
|
|
386
|
+
template: string;
|
|
387
|
+
/** Apply the edited template back to the node. */
|
|
388
|
+
onSave: (template: string) => void;
|
|
389
|
+
/**
|
|
390
|
+
* The directive's current attributes (value lists, bind name, layout) — present
|
|
391
|
+
* when the node-view supports GUIDED re-editing (A5). The
|
|
392
|
+
* `IterationBuilderProvider` reads these to reopen the builder with its data;
|
|
393
|
+
* the template-only `IterationTemplateProvider` ignores them.
|
|
394
|
+
*/
|
|
395
|
+
attributes?: Record<string, string>;
|
|
396
|
+
/**
|
|
397
|
+
* Write back BOTH the attributes and the template (the guided builder path). When
|
|
398
|
+
* present it is preferred over {@link onSave} (which only rewrites the body).
|
|
399
|
+
*/
|
|
400
|
+
onSaveData?: (next: {
|
|
401
|
+
attributes: Record<string, string>;
|
|
402
|
+
template: string;
|
|
403
|
+
}) => void;
|
|
404
|
+
/**
|
|
405
|
+
* Directly rewrite the node's attributes (e.g. the node-menu's "Change layout" /
|
|
406
|
+
* "Transpose" actions) without touching the template body. Additive (#223) —
|
|
407
|
+
* present alongside {@link onSave}/{@link onSaveData} for back-compat; a
|
|
408
|
+
* consumer-side surface (a future dialog action) can reach the same write the
|
|
409
|
+
* node-view's own menu uses.
|
|
410
|
+
*/
|
|
411
|
+
onSetAttributes?: (attributes: Record<string, string>) => void;
|
|
412
|
+
/**
|
|
413
|
+
* Replace the ENTIRE directive node with plain markdown — e.g. the node-menu's
|
|
414
|
+
* "Convert to static" action (the evaluated, populated result). After this the
|
|
415
|
+
* node stops being a `:::iterate`/`:::pivot` directive. Additive (#223).
|
|
416
|
+
*/
|
|
417
|
+
onReplaceWithMarkdown?: (markdown: string) => void;
|
|
418
|
+
}
|
|
419
|
+
/** A consumer handler that opens the template editor for a request. */
|
|
420
|
+
type IterationEditHandler = (request: IterationEditRequest) => void;
|
|
421
|
+
/** Provide a handler to enable the node-view `⋯` re-edit affordance. */
|
|
422
|
+
declare const IterationEditContext: react.Context<IterationEditHandler | null>;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Pure ProseMirror insertion commands for the slash menu.
|
|
426
|
+
*
|
|
427
|
+
* The load-bearing logic of the slash menu lives here, deliberately decoupled
|
|
428
|
+
* from Milkdown's context and from React: an `insertBrandDirective` factory that
|
|
429
|
+
* builds the right `brand_container_directive` / `brand_leaf_directive` node (from
|
|
430
|
+
* the schemas in `directive-nodes.ts`) with sensible default attrs + a placeholder
|
|
431
|
+
* body, replaces the active slash range (or inserts at the cursor), and drops the
|
|
432
|
+
* caret into the first editable field. Because it takes the NodeTypes/Schema as
|
|
433
|
+
* arguments (not a Milkdown `Ctx`), it is unit-testable against a hand-built
|
|
434
|
+
* ProseMirror state and its output round-trips losslessly through the editor's
|
|
435
|
+
* existing `toMarkdown` runners (asserted in insert-directive.test.ts).
|
|
436
|
+
*
|
|
437
|
+
* `resolveBrandInsert` is the thin Milkdown-aware adapter: it reads the NodeTypes
|
|
438
|
+
* from the editor `Ctx` and returns the same pure command — so the slash plugin
|
|
439
|
+
* and any direct caller share one implementation.
|
|
440
|
+
*/
|
|
441
|
+
|
|
442
|
+
/** A `[from, to)` document range to replace (the typed `/query`), or `null`. */
|
|
443
|
+
interface SlashRange {
|
|
444
|
+
from: number;
|
|
445
|
+
to: number;
|
|
446
|
+
}
|
|
447
|
+
/** The directive names the slash menu can insert as brand blocks. */
|
|
448
|
+
type InsertableDirective = "card" | "callout" | "timeline" | "metric" | "iterate" | "pivot";
|
|
449
|
+
/**
|
|
450
|
+
* The pure insertion command. Builds the directive node from the given
|
|
451
|
+
* NodeTypes + schema and replaces `range` (or the current selection when
|
|
452
|
+
* `range` is null), then positions the caret in the first editable field
|
|
453
|
+
* (the body's start for containers; just after the atomic leaf for metric).
|
|
454
|
+
*
|
|
455
|
+
* Returns a ProseMirror `Command` `(state, dispatch?) => boolean`.
|
|
456
|
+
*/
|
|
457
|
+
declare function insertBrandDirective(name: InsertableDirective, containerType: NodeType, leafType: NodeType, schema: Schema, range: SlashRange | null): Command;
|
|
458
|
+
/** Map a basic-block id to a ProseMirror command that inserts the native node. */
|
|
459
|
+
declare function insertBasicBlock(id: BasicBlockId, schema: Schema, range: SlashRange | null): Command;
|
|
460
|
+
/** Seed body for a fresh ```calc fence — a tiny ledger so highlight + inlays show at once. */
|
|
461
|
+
declare const CALC_FENCE_SEED: string;
|
|
462
|
+
/**
|
|
463
|
+
* Insert a ```calc fence (a `code_block` with `language: "calc"`) seeded with a
|
|
464
|
+
* short example, then drop the caret into the body. The editor's calc layer
|
|
465
|
+
* (`calc-editor-prose`) highlights + adds result inlays once `calc` hooks are wired;
|
|
466
|
+
* with none it is just a fenced code block (and renders as a `CalcBlock` in preview
|
|
467
|
+
* when `evaluate` is supplied) — so inserting one is always safe.
|
|
468
|
+
*/
|
|
469
|
+
declare function insertCalcFence(schema: Schema, range: SlashRange | null, seed?: string): Command;
|
|
470
|
+
/** Milkdown-aware adapter for {@link insertCalcFence}. */
|
|
471
|
+
declare function resolveCalcInsert(ctx: Ctx, range: SlashRange | null): boolean;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* The brand slash-command registry — pure, typed, tree-shakeable data.
|
|
475
|
+
*
|
|
476
|
+
* Each command is a label + group + match keywords + an icon + a `run` that
|
|
477
|
+
* inserts the corresponding block at the caret. `run` is given a
|
|
478
|
+
* {@link SlashInsertContext} (the Milkdown `Ctx` + the active `/query` range);
|
|
479
|
+
* brand directives delegate to `resolveBrandInsert`, basic blocks to
|
|
480
|
+
* `resolveBasicInsert` — so the SAME registry drives the menu and any
|
|
481
|
+
* programmatic insert, and the load-bearing insertion logic stays in
|
|
482
|
+
* `insert-directive.ts` (unit-tested there).
|
|
483
|
+
*
|
|
484
|
+
* Defaults: card · callout · metric · timeline ("Brand blocks") +
|
|
485
|
+
* heading · bullet-list · ordered-list · quote · code · divider ("Basic").
|
|
486
|
+
* Consumers can extend or replace the list via the `slashMenu` prop.
|
|
487
|
+
*
|
|
488
|
+
* `runInSource` (#299) is an OPTIONAL, ADDITIVE second handler for the Monaco
|
|
489
|
+
* source pane — `run` (Milkdown) stays untouched, so the 12 default commands
|
|
490
|
+
* need zero migration. `MonacoCodeEditor` / `IRange` / `EditorContentAccess`
|
|
491
|
+
* below are TYPE-ONLY imports (erased at build) — this file stays free of any
|
|
492
|
+
* `monaco-editor` RUNTIME import, so the Milkdown-facing `slash/index.ts`
|
|
493
|
+
* barrel this file feeds still pulls zero Monaco code.
|
|
494
|
+
*/
|
|
495
|
+
|
|
496
|
+
/** The native (non-directive) blocks the slash menu can insert. */
|
|
497
|
+
type BasicBlockId = "heading" | "bullet-list" | "ordered-list" | "quote" | "code" | "divider";
|
|
498
|
+
/**
|
|
499
|
+
* Context handed to a {@link SlashCommand.run}. `ctx` is the live Milkdown editor
|
|
500
|
+
* context; `range` is the `[from, to)` document range of the typed trigger +
|
|
501
|
+
* query (so the command replaces it), or `null` to insert at the caret.
|
|
502
|
+
*/
|
|
503
|
+
interface SlashInsertContext {
|
|
504
|
+
ctx: Ctx;
|
|
505
|
+
range: SlashRange | null;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Context handed to a {@link SlashCommand.runInSource} (#299) — the Monaco
|
|
509
|
+
* SOURCE-pane counterpart to {@link SlashInsertContext}. By the time this runs,
|
|
510
|
+
* the typed `/query` trigger has already been stripped from the document (the
|
|
511
|
+
* same edit `cancel` uses), so the handler starts from a clean doc.
|
|
512
|
+
*/
|
|
513
|
+
interface SourceSlashContext {
|
|
514
|
+
/** The raw Monaco editor instance — full imperative access when needed. */
|
|
515
|
+
editor: MonacoCodeEditor;
|
|
516
|
+
/**
|
|
517
|
+
* Model range the typed `/query` trigger occupied (already removed by the
|
|
518
|
+
* time this fires) — `null` on the hotkey path, where no `/` was ever typed.
|
|
519
|
+
*/
|
|
520
|
+
range: IRange | null;
|
|
521
|
+
/** Engine-agnostic content access (get/replace-selection/insert-at-cursor). */
|
|
522
|
+
content: EditorContentAccess;
|
|
523
|
+
}
|
|
524
|
+
/** One entry in the slash menu. Pure data + an insertion `run`. */
|
|
525
|
+
interface SlashCommand {
|
|
526
|
+
/** Stable id (used as the React key + `aria-activedescendant` target). */
|
|
527
|
+
id: string;
|
|
528
|
+
/** Visible label, e.g. "Card". */
|
|
529
|
+
label: string;
|
|
530
|
+
/** Grouping header, e.g. "Brand blocks" | "Basic". */
|
|
531
|
+
group?: string;
|
|
532
|
+
/** A short description shown under the label. */
|
|
533
|
+
description?: string;
|
|
534
|
+
/** Extra fuzzy-match aids beyond the label (matched case-insensitively). */
|
|
535
|
+
keywords?: string[];
|
|
536
|
+
/** Leading icon (a Lucide glyph or any node). */
|
|
537
|
+
icon?: ReactNode;
|
|
538
|
+
/**
|
|
539
|
+
* Markdown SNIPPET the source / split toolbar's Insert menu inserts (text mode).
|
|
540
|
+
* Optional: commands without one — the basic blocks, which already have their
|
|
541
|
+
* own toolbar buttons — don't appear in that menu. Brand blocks set this so the
|
|
542
|
+
* source toolbar inserts the SAME directive / fence the WYSIWYG `run` builds, so
|
|
543
|
+
* the two surfaces stay at parity. (A4)
|
|
544
|
+
*/
|
|
545
|
+
snippet?: string;
|
|
546
|
+
/** Insert the block at the caret. WYSIWYG (Milkdown) — UNCHANGED (#299). */
|
|
547
|
+
run: (ctx: SlashInsertContext) => void;
|
|
548
|
+
/**
|
|
549
|
+
* OPTIONAL source-pane (Monaco) handler (#299) — for a RUN-ONLY command (no
|
|
550
|
+
* `snippet`, e.g. an "Ask AI" entry) that can't express itself as a markdown
|
|
551
|
+
* insert. When present, selecting the command in the Monaco source-pane menu
|
|
552
|
+
* (`MonacoSlashMenu`) strips the typed `/query` first, then calls this with
|
|
553
|
+
* the live editor + the (now-stripped) trigger range + engine-agnostic
|
|
554
|
+
* content access — instead of the `snippet`-only `commitSnippet` fallback. A
|
|
555
|
+
* command needs only ONE of `snippet` / `runInSource` to appear in source (both
|
|
556
|
+
* is fine too — `runInSource` wins there since it's the more capable handler).
|
|
557
|
+
*/
|
|
558
|
+
runInSource?: (ctx: SourceSlashContext) => void;
|
|
559
|
+
/**
|
|
560
|
+
* OPTIONAL guided variant (#223, WYSIWYG only). When present AND the
|
|
561
|
+
* consumer has wired an `IterationEditContext` handler (an
|
|
562
|
+
* `IterationBuilderProvider` / `IterationTemplateProvider` above the
|
|
563
|
+
* editor), this REPLACES `run` — it opens the guided modal seeded blank
|
|
564
|
+
* instead of inserting a bare directive. Falls back to `run` when no
|
|
565
|
+
* handler is available, so the 12 non-guided default commands need zero
|
|
566
|
+
* changes. Set on the `iterate` / `pivot` commands only.
|
|
567
|
+
*/
|
|
568
|
+
guided?: (insert: SlashInsertContext, handler: IterationEditHandler) => void;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* The default command list. Brand blocks first (the wedge), then the basics.
|
|
572
|
+
* The brand-block icons reuse the `data-brand-directive` chrome look via Lucide
|
|
573
|
+
* stand-ins (the editor renders the real component once inserted).
|
|
574
|
+
*/
|
|
575
|
+
declare const BRAND_SLASH_COMMANDS: SlashCommand[];
|
|
576
|
+
/**
|
|
577
|
+
* Filter a command list by a query (case-insensitive substring over label +
|
|
578
|
+
* keywords). An empty query returns the full list (in registry order).
|
|
579
|
+
*/
|
|
580
|
+
declare function filterSlashCommands(commands: SlashCommand[], query: string): SlashCommand[];
|
|
581
|
+
/** Preserve registry order while grouping; used by the menu to render headers. */
|
|
582
|
+
declare function groupSlashCommands(commands: SlashCommand[]): {
|
|
583
|
+
group: string;
|
|
584
|
+
commands: SlashCommand[];
|
|
585
|
+
}[];
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Imperative handle exposed via `ref`.
|
|
589
|
+
*
|
|
590
|
+
* Extends {@link EditorContentAccess} so any consumer of a `MarkdownEditor`
|
|
591
|
+
* ref can drive AI editing operations (insert, replace, subscribe to selection)
|
|
592
|
+
* through the engine-agnostic interface, alongside the markdown-specific helpers.
|
|
593
|
+
*
|
|
594
|
+
* `getText()` is an alias for `getMarkdown()` (same output; both return the full
|
|
595
|
+
* document serialized to markdown). The duplication is intentional: `getText`
|
|
596
|
+
* satisfies the `EditorContentAccess` interface contract; `getMarkdown` is the
|
|
597
|
+
* historically-named markdown-specific method. JSDoc notes the equivalence.
|
|
598
|
+
*/
|
|
599
|
+
interface MarkdownEditorHandle extends EditorContentAccess {
|
|
600
|
+
/**
|
|
601
|
+
* Serialize the current document to a markdown string.
|
|
602
|
+
* Equivalent to `getText()` — both return the full document as markdown.
|
|
603
|
+
*/
|
|
604
|
+
getMarkdown: () => string;
|
|
605
|
+
/**
|
|
606
|
+
* Serialize the current document, or `null` while the engine is still
|
|
607
|
+
* booting. Used to capture the pre-edit normalization BASELINE for the
|
|
608
|
+
* lossless-edit merge (WI-1) — unlike `getMarkdown` it never falls back to
|
|
609
|
+
* the raw input, so a non-null result is always the editor's own output.
|
|
610
|
+
*/
|
|
611
|
+
serialized: () => string | null;
|
|
612
|
+
/**
|
|
613
|
+
* Best-effort: scroll the heading whose outline slug matches into view (#273).
|
|
614
|
+
* Walks the ProseMirror doc for `heading` nodes, slugifies their text with the
|
|
615
|
+
* same algorithm as `parseMarkdownOutline`, and scrolls the first match into
|
|
616
|
+
* view. No-op (never throws) while the engine is booting or if no match.
|
|
617
|
+
*/
|
|
618
|
+
scrollToHeading: (slug: string) => void;
|
|
619
|
+
/**
|
|
620
|
+
* Best-effort: scroll toward FULL-SOURCE 1-based `line` by resolving the
|
|
621
|
+
* nearest preceding heading in the ProseMirror doc (no exact source map in
|
|
622
|
+
* WYSIWYG — Milkdown keeps no `data-sourcepos`). No-op when no preceding
|
|
623
|
+
* heading is found or while booting. (#273)
|
|
624
|
+
*
|
|
625
|
+
* For precise navigation, prefer `scrollToHeading(slug)` — the workspace
|
|
626
|
+
* resolves the slug from the line via `parseMarkdownOutline` + `fmOffset`
|
|
627
|
+
* before forwarding here.
|
|
628
|
+
*/
|
|
629
|
+
revealLine: (line: number, opts?: {
|
|
630
|
+
center?: boolean;
|
|
631
|
+
}) => void;
|
|
632
|
+
}
|
|
633
|
+
interface MarkdownEditorProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
|
|
634
|
+
/** Controlled markdown value. Pair with `onChange`. */
|
|
635
|
+
value?: string;
|
|
636
|
+
/** Initial markdown for uncontrolled use. */
|
|
637
|
+
defaultValue?: string;
|
|
638
|
+
/** Fires on every edit with the full markdown document. */
|
|
639
|
+
onChange?: (markdown: string) => void;
|
|
640
|
+
/** Render the editor read-only (still selectable, not editable). */
|
|
641
|
+
readOnly?: boolean;
|
|
642
|
+
/**
|
|
643
|
+
* Accessible name for the editable surface. Milkdown/ProseMirror renders an ARIA
|
|
644
|
+
* `textbox` (`contenteditable`); without a name, screen readers announce an
|
|
645
|
+
* unlabeled field. Set onto the ProseMirror view's `attributes`. Default
|
|
646
|
+
* `"Markdown editor"`.
|
|
647
|
+
*/
|
|
648
|
+
ariaLabel?: string;
|
|
649
|
+
/**
|
|
650
|
+
* Enable the `/` command menu (insert brand `:::` directives + basic blocks
|
|
651
|
+
* live at the caret). `true` (default) uses the built-in
|
|
652
|
+
* {@link BRAND_SLASH_COMMANDS}; pass a `commands` array to extend/replace them,
|
|
653
|
+
* or `false` to disable. The `trigger` defaults to `"/"`.
|
|
654
|
+
*
|
|
655
|
+
* Pass `shortcut` (default `"Mod-Shift-O"`) to control the keyboard shortcut that
|
|
656
|
+
* opens the menu at the caret without typing the trigger character — works in
|
|
657
|
+
* BOTH the WYSIWYG pane and the Monaco source pane (#271).
|
|
658
|
+
*/
|
|
659
|
+
slashMenu?: boolean | {
|
|
660
|
+
commands?: SlashCommand[];
|
|
661
|
+
trigger?: string;
|
|
662
|
+
shortcut?: string;
|
|
663
|
+
};
|
|
664
|
+
/**
|
|
665
|
+
* Opt-in calc authoring inside ```calc fences (off by default). Supply the
|
|
666
|
+
* consumer's hooks — `tokenize` (highlight), `evaluate` (result inlays), and/or
|
|
667
|
+
* `complete` (autocomplete; Monaco surface). The library DECORATES, the consumer
|
|
668
|
+
* COMPUTES — no calc engine is bundled. Mirrors `MarkdownPreview`'s `evaluate`.
|
|
669
|
+
*/
|
|
670
|
+
calc?: CalcEditorHooks;
|
|
671
|
+
/**
|
|
672
|
+
* Declarative completion providers (#283) — e.g. `[[wikilink]]` autocomplete.
|
|
673
|
+
* Off by default; mirrors the `slashMenu`/`calc` opt-in pattern. Each provider
|
|
674
|
+
* registers a `triggerCharacters` set + a `provide(ctx)` that returns
|
|
675
|
+
* candidates; the library owns detecting the trigger and rendering/inserting.
|
|
676
|
+
*
|
|
677
|
+
* This is a DELIBERATELY MINIMAL, best-effort mirror of the Monaco source-pane
|
|
678
|
+
* behavior (see `markdown-editor/completions/completions-prose.ts` for the
|
|
679
|
+
* exact gaps — no real cross-block line/column, a plain listbox instead of a
|
|
680
|
+
* native suggest widget). Forwarded from `MarkdownWorkspace`'s `completions`
|
|
681
|
+
* prop, which also wires the FULL Monaco/source-pane path.
|
|
682
|
+
*/
|
|
683
|
+
completions?: EditorCompletionProvider[];
|
|
684
|
+
/**
|
|
685
|
+
* Host-provided callback for image paste/drop embedding.
|
|
686
|
+
*
|
|
687
|
+
* When set, the editor intercepts paste and drop events that contain image
|
|
688
|
+
* files, shows an inline "uploading…" placeholder, calls this function with
|
|
689
|
+
* the `File`, and on resolve inserts `` in the
|
|
690
|
+
* document. On reject the placeholder is removed and an inline error chip
|
|
691
|
+
* (+ toast) is shown — the document never contains a broken image.
|
|
692
|
+
*
|
|
693
|
+
* If not set, the editor's default paste/drop behavior is unchanged.
|
|
694
|
+
*
|
|
695
|
+
* The library NEVER stores assets — all persistence is the host's responsibility.
|
|
696
|
+
*/
|
|
697
|
+
onEmbedAsset?: EmbedAssetFn;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
declare const MarkdownEditor: react.ForwardRefExoticComponent<MarkdownEditorProps & react.RefAttributes<MarkdownEditorHandle>>;
|
|
701
|
+
|
|
702
|
+
export { type CalcValueKind as A, BRAND_SLASH_COMMANDS as B, CodeEditor as C, type CompletionMatch as D, type EditorContentAccess as E, type CompletionReplaceRange as F, type EditorCompletionContext as G, type EditorCompletionItem as H, type IterationEditHandler as I, type InsertableDirective as J, IterationEditContext as K, type IterationEditRequest as L, type MonacoCodeEditor as M, type SlashInsertContext as N, type SlashRange as O, type SourceSlashContext as P, collectCompletions as Q, filterSlashCommands as R, type SlashCommand as S, groupSlashCommands as T, insertBasicBlock as U, insertBrandDirective as V, insertCalcFence as W, resolveCalcInsert as X, resolveReplaceRange as Y, triggerQueryStart as Z, type CodeEditorProps as a, type EditorAction as b, type EditorSelection as c, type EmbedAssetFn as d, MarkdownEditor as e, type MarkdownEditorHandle as f, type MarkdownEditorProps as g, type EditorCompletionProvider as h, type CalcEditorHooks as i, type EvaluateCalc as j, type CalcValue as k, type CalcTokenKind as l, monacoContentAccess as m, type BasicBlockId as n, CALC_FENCE_SEED as o, type CalcComplete as p, type CalcCompletion as q, type CalcCompletionContext as r, type CalcCompletionKind as s, type CalcContext as t, type CalcLineResult as u, type CalcRule as v, type CalcSheet as w, type CalcTint as x, type CalcToken as y, type CalcTokenize as z };
|