@bendyline/squisq-editor-react 2.2.0 → 2.3.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/NOTICE.md +30 -30
- package/dist/chunk-54UGTQBO.js +862 -0
- package/dist/chunk-5JMHFAVW.js +2408 -0
- package/dist/chunk-5Q4JN4I5.js +132 -0
- package/dist/chunk-6VDYKI3L.js +49 -0
- package/dist/chunk-GS7QWYFT.js +9 -0
- package/dist/chunk-MJJK7YQB.js +949 -0
- package/dist/chunk-NITZVAXL.js +986 -0
- package/dist/chunk-TRCKHRBS.js +35234 -0
- package/dist/chunk-V44VP242.js +3256 -0
- package/dist/image-editor/index.d.ts +223 -0
- package/dist/image-editor/index.js +15 -0
- package/dist/index.d.ts +2310 -4423
- package/dist/index.js +494 -42158
- package/dist/json-editor/index.d.ts +27 -0
- package/dist/json-editor/index.js +7 -0
- package/dist/monaco.d.ts +1 -1
- package/dist/monaco.js +1 -1
- package/dist/recorder/index.d.ts +407 -0
- package/dist/recorder/index.js +43 -0
- package/dist/shell/index.d.ts +9 -0
- package/dist/shell/index.js +22 -0
- package/dist/shell-BxSCBm4H.d.ts +1064 -0
- package/dist/styles/index.css +367 -19
- package/dist/teleprompter/index.d.ts +497 -0
- package/dist/teleprompter/index.js +57 -0
- package/package.json +29 -6
|
@@ -0,0 +1,1064 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { Doc, MediaProvider, Theme } from '@bendyline/squisq/schemas';
|
|
4
|
+
import { MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
5
|
+
import { ContentContainer } from '@bendyline/squisq/storage';
|
|
6
|
+
import { DocumentVersionManager, SaveVersionOptions, SaveVersionResult, PrunePolicy } from '@bendyline/squisq/versions';
|
|
7
|
+
import { Editor } from '@tiptap/core';
|
|
8
|
+
import { editor } from 'monaco-editor';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Configuration a Scene host (diagram / drawing / layout widget) supplies
|
|
12
|
+
* so the shared inline text editor knows how to read and write the text of
|
|
13
|
+
* a given layer. The Scene owns the editing UI (overlay + positioning);
|
|
14
|
+
* the host owns persistence (markdown heading vs. layout JSON blob).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
type SceneTextLevel = 'inline' | 'block' | 'rich';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* sceneTextChannel — an editor-owned channel that bridges the canvas's inline
|
|
21
|
+
* text editor (which renders in a **detached React root** created by the
|
|
22
|
+
* Diagram/SceneBlock ProseMirror extensions, outside `<EditorProvider>`)
|
|
23
|
+
* to the provider, so the top formatting toolbar can target it.
|
|
24
|
+
*
|
|
25
|
+
* The active textbox's `SceneTextOverlay` publishes its Tiptap editor here
|
|
26
|
+
* on focus and clears it on blur/unmount; `EditorProvider` subscribes and
|
|
27
|
+
* mirrors the handle into `activeSceneText`. Each EditorProvider creates its
|
|
28
|
+
* own channel, preventing focus in one editor from mutating another editor.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
interface SceneTextHandle {
|
|
32
|
+
editor: Editor;
|
|
33
|
+
level: SceneTextLevel;
|
|
34
|
+
}
|
|
35
|
+
type Listener = (handle: SceneTextHandle | null) => void;
|
|
36
|
+
interface SceneTextChannel {
|
|
37
|
+
set(handle: SceneTextHandle | null): void;
|
|
38
|
+
get(): SceneTextHandle | null;
|
|
39
|
+
subscribe(listener: Listener): () => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Monaco standalone code editor instance type */
|
|
43
|
+
type MonacoEditor = editor.IStandaloneCodeEditor;
|
|
44
|
+
/**
|
|
45
|
+
* One candidate returned by a {@link MentionProvider}. Shown in the editor's
|
|
46
|
+
* `@` popover. `id` is the stable identifier (serialized into the mention
|
|
47
|
+
* wire format); `label` is what the reader sees; `scheme` is the namespace
|
|
48
|
+
* (e.g. `'user'`, `'issue'`) written into the markdown as `@[label](scheme:id)`;
|
|
49
|
+
* `description` and `group` are optional hints for richer suggestion UIs.
|
|
50
|
+
*
|
|
51
|
+
* Different candidates in the same result set may carry different schemes —
|
|
52
|
+
* a provider that returns both users and issues, for example, tags each
|
|
53
|
+
* candidate with its own namespace and the editor emits mentions accordingly.
|
|
54
|
+
*/
|
|
55
|
+
interface MentionCandidate {
|
|
56
|
+
id: string;
|
|
57
|
+
label: string;
|
|
58
|
+
scheme: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
group?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Looks up mention candidates matching a query. Called as the user types
|
|
64
|
+
* after `@`. The provider is free to do server-side or client-side filtering;
|
|
65
|
+
* the editor only cares that candidates come back in relevance order.
|
|
66
|
+
*/
|
|
67
|
+
type MentionProvider = (query: string) => Promise<MentionCandidate[]>;
|
|
68
|
+
/**
|
|
69
|
+
* A document that the link dialog's "Browse documents" picker can offer.
|
|
70
|
+
* `path` is what lands in the markdown URL (typically relative to the
|
|
71
|
+
* current document so `home.md → resume.md` round-trips through file-
|
|
72
|
+
* system serializers). `label` is the human name shown in the list.
|
|
73
|
+
* `description` is an optional secondary line (e.g. workspace folder,
|
|
74
|
+
* last-modified date).
|
|
75
|
+
*/
|
|
76
|
+
interface DocumentLinkCandidate {
|
|
77
|
+
path: string;
|
|
78
|
+
label: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Resolves sibling / workspace document candidates for the link dialog.
|
|
83
|
+
* The editor itself has no notion of "neighbors" — hosts that organize
|
|
84
|
+
* docs in a workspace (e.g. docblocks) implement this to power the
|
|
85
|
+
* dialog's document picker. Pass `''` as the query for an initial list
|
|
86
|
+
* (the dialog calls it once on open); subsequent calls narrow by user
|
|
87
|
+
* input.
|
|
88
|
+
*/
|
|
89
|
+
type DocumentLinkProvider = (query: string) => Promise<DocumentLinkCandidate[]>;
|
|
90
|
+
type EditorView = 'raw' | 'wysiwyg' | 'preview';
|
|
91
|
+
/**
|
|
92
|
+
* Light/dark chrome mode for the editor shell (toolbar, tabs, status bar,
|
|
93
|
+
* side panes). This is the editor's *UI color scheme* — distinct from a
|
|
94
|
+
* Squisq `Theme` object, which styles the rendered document. Renamed from
|
|
95
|
+
* the former `EditorTheme` to remove that ambiguity.
|
|
96
|
+
*/
|
|
97
|
+
type EditorColorScheme = 'light' | 'dark';
|
|
98
|
+
/**
|
|
99
|
+
* Document layout mode. `'document'` shows the whole markdown document in
|
|
100
|
+
* the active view (the historical behavior). `'block'` is the
|
|
101
|
+
* block-at-a-time view — one heading-defined block on a card at a time,
|
|
102
|
+
* with the editor scoped to just that block. `'timeline'` is block mode plus
|
|
103
|
+
* a horizontal timeline track for editing block durations and media slices.
|
|
104
|
+
* See {@link useBlockNavigator}.
|
|
105
|
+
*/
|
|
106
|
+
type LayoutMode = 'document' | 'block' | 'timeline';
|
|
107
|
+
/**
|
|
108
|
+
* How much of the active Squisq theme the WYSIWYG editing surface
|
|
109
|
+
* mirrors. `'fonts'` is the historical default — body and heading
|
|
110
|
+
* fonts only. `'fonts-colors'` also borrows the theme canvas / text
|
|
111
|
+
* colors. `'none'` opts out completely.
|
|
112
|
+
*/
|
|
113
|
+
type ThemeInheritance = 'none' | 'fonts' | 'fonts-colors';
|
|
114
|
+
/**
|
|
115
|
+
* When inline block-template tags are shown in the WYSIWYG surface.
|
|
116
|
+
* `'active'` shows tags for the cursor's block and the block under the pointer.
|
|
117
|
+
*/
|
|
118
|
+
type BlockTagVisibility = 'none' | 'active' | 'always';
|
|
119
|
+
/**
|
|
120
|
+
* Editor operating mode. `markdown` is the full experience (WYSIWYG +
|
|
121
|
+
* Preview tabs, formatting toolbar). `code` is a Monaco-only view used
|
|
122
|
+
* when the content represents a non-markdown file like `foo.ts`.
|
|
123
|
+
*/
|
|
124
|
+
type EditorMode = 'markdown' | 'code' | 'image';
|
|
125
|
+
interface EditorState {
|
|
126
|
+
/** Raw markdown source string */
|
|
127
|
+
markdownSource: string;
|
|
128
|
+
/** Parsed markdown document (JSON DOM) */
|
|
129
|
+
markdownDoc: MarkdownDocument | null;
|
|
130
|
+
/** Generated Doc (block hierarchy) */
|
|
131
|
+
doc: Doc | null;
|
|
132
|
+
/** Currently active editor view */
|
|
133
|
+
activeView: EditorView;
|
|
134
|
+
/** Parse error, if any */
|
|
135
|
+
parseError: string | null;
|
|
136
|
+
/** Whether a parse is pending */
|
|
137
|
+
isParsing: boolean;
|
|
138
|
+
/** Current light/dark chrome color scheme for the editor shell. */
|
|
139
|
+
colorScheme: EditorColorScheme;
|
|
140
|
+
/** Operating mode — 'markdown' for the full shell, 'code' for Monaco-only. */
|
|
141
|
+
editorMode: EditorMode;
|
|
142
|
+
/** Whether the host-triggered Find toolbar is active. */
|
|
143
|
+
findMode: boolean;
|
|
144
|
+
/** Monaco language ID for the Raw editor. */
|
|
145
|
+
language: string;
|
|
146
|
+
/**
|
|
147
|
+
* Whether the inline preview gutter (per-block card previews next to the
|
|
148
|
+
* WYSIWYG surface) is currently visible. Initialized from the EditorShell
|
|
149
|
+
* `inlinePreview` prop; the View menu in the toolbar can toggle it at
|
|
150
|
+
* runtime.
|
|
151
|
+
*/
|
|
152
|
+
inlinePreviewVisible: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether the bottom status bar is currently visible. Initialized from
|
|
155
|
+
* the EditorShell `showStatusBar` prop (default true); the View menu in
|
|
156
|
+
* the toolbar can toggle it at runtime.
|
|
157
|
+
*/
|
|
158
|
+
statusBarVisible: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Whether the left-side outline pane is currently visible. Initialized
|
|
161
|
+
* from the EditorShell `outline` prop (default false); the View menu in
|
|
162
|
+
* the toolbar can toggle it at runtime.
|
|
163
|
+
*/
|
|
164
|
+
outlineVisible: boolean;
|
|
165
|
+
/** When inline block-template tags are shown in the WYSIWYG view. */
|
|
166
|
+
blockTagVisibility: BlockTagVisibility;
|
|
167
|
+
/**
|
|
168
|
+
* Whether inline block-template tags can currently be visible.
|
|
169
|
+
* Kept for compatibility; prefer {@link blockTagVisibility}.
|
|
170
|
+
*/
|
|
171
|
+
blockTagsVisible: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* How much of the active Squisq theme the WYSIWYG editing surface should
|
|
174
|
+
* inherit. `'none'` shows the default editor styling, `'fonts'` (the
|
|
175
|
+
* default) matches body and heading fonts only, and `'fonts-colors'`
|
|
176
|
+
* also borrows the theme's canvas / text colors so authors get a
|
|
177
|
+
* closer preview while editing.
|
|
178
|
+
*/
|
|
179
|
+
themeInheritance: ThemeInheritance;
|
|
180
|
+
/**
|
|
181
|
+
* Relative path of an image the user requested to edit, or `null` when
|
|
182
|
+
* no editor is open. Surfaced by `<ImageNodeView>`'s hover affordance
|
|
183
|
+
* and consumed by `<EditorShell>` to render the modal `<ImageEditor>`.
|
|
184
|
+
*/
|
|
185
|
+
imageEditTarget: string | null;
|
|
186
|
+
/**
|
|
187
|
+
* Monotonic counter bumped whenever a managed media asset is rewritten
|
|
188
|
+
* (e.g. after the image-editor modal saves back). Image render paths
|
|
189
|
+
* that cache resolved blob URLs should include this in their effect
|
|
190
|
+
* deps so the new bytes get picked up.
|
|
191
|
+
*/
|
|
192
|
+
mediaRevision: number;
|
|
193
|
+
/**
|
|
194
|
+
* Whether the in-editor media recorder should be available. Defaults
|
|
195
|
+
* to true when a `mediaProvider` is wired; hosts that explicitly
|
|
196
|
+
* don't want the affordance (e.g. read-only embeds, surfaces where
|
|
197
|
+
* camera/screen prompts would be jarring) can pass `false` on the
|
|
198
|
+
* shell.
|
|
199
|
+
*/
|
|
200
|
+
allowRecording: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* Whether the Narrate (teleprompter) display mode is offered under the
|
|
203
|
+
* Use tab. Orthogonal to `allowRecording`: the teleprompter is useful
|
|
204
|
+
* without any capture (reading for external recording software), and a
|
|
205
|
+
* host may allow the recorder modal but not want a prompter surface.
|
|
206
|
+
*/
|
|
207
|
+
allowNarrate: boolean;
|
|
208
|
+
/**
|
|
209
|
+
* Document layout mode. `'document'` (default) edits the whole document;
|
|
210
|
+
* `'block'` activates the block-at-a-time card view. Initialized from the
|
|
211
|
+
* EditorShell `layoutMode` prop; the View menu can toggle it at runtime.
|
|
212
|
+
*/
|
|
213
|
+
layoutMode: LayoutMode;
|
|
214
|
+
/**
|
|
215
|
+
* The markdown the active text editor should bind to: the full source in
|
|
216
|
+
* `'document'` mode, or just the active block's slice in `'block'` mode.
|
|
217
|
+
* Editors read this instead of `markdownSource` so the same surfaces work
|
|
218
|
+
* in both layouts.
|
|
219
|
+
*/
|
|
220
|
+
editorSource: string;
|
|
221
|
+
/** Number of navigable blocks (cards) in the current document. */
|
|
222
|
+
blockCount: number;
|
|
223
|
+
/** Index of the block currently shown on the card (block mode). */
|
|
224
|
+
activeBlockKey: number;
|
|
225
|
+
/** 1-based source line where the active block begins, or null. */
|
|
226
|
+
activeBlockStartLine: number | null;
|
|
227
|
+
}
|
|
228
|
+
interface EditorActions {
|
|
229
|
+
/** Set markdown source and trigger re-parse */
|
|
230
|
+
setMarkdownSource: (source: string) => void;
|
|
231
|
+
/**
|
|
232
|
+
* Write through the active editor channel. In `'document'` mode this is
|
|
233
|
+
* `setMarkdownSource`; in `'block'` mode it splices the edited block back
|
|
234
|
+
* into the full document. Editors call this instead of `setMarkdownSource`.
|
|
235
|
+
*/
|
|
236
|
+
setEditorSource: (source: string) => void;
|
|
237
|
+
/** Switch between Document and Block-at-a-time layouts. */
|
|
238
|
+
setLayoutMode: (mode: LayoutMode) => void;
|
|
239
|
+
/** Show a block by index in block mode (clamped to range). */
|
|
240
|
+
goToBlock: (key: number) => void;
|
|
241
|
+
/** Show the block that owns a given 1-based source line (used by the outline). */
|
|
242
|
+
goToBlockByLine: (line: number) => void;
|
|
243
|
+
/** Move the card to the previous block. */
|
|
244
|
+
prevBlock: () => void;
|
|
245
|
+
/** Move the card to the next block. */
|
|
246
|
+
nextBlock: () => void;
|
|
247
|
+
/** Insert a new heading block after the active one and move to it. */
|
|
248
|
+
addBlock: () => void;
|
|
249
|
+
/** Set markdown from a MarkdownDocument (e.g. from WYSIWYG) */
|
|
250
|
+
setMarkdownDoc: (doc: MarkdownDocument) => void;
|
|
251
|
+
/** Switch the active view */
|
|
252
|
+
setActiveView: (view: EditorView) => void;
|
|
253
|
+
/** Enter or leave the host-triggered Find toolbar mode. */
|
|
254
|
+
setFindMode: (active: boolean) => void;
|
|
255
|
+
/** Register / unregister the Tiptap editor instance (called by WysiwygEditor) */
|
|
256
|
+
setTiptapEditor: (editor: Editor | null) => void;
|
|
257
|
+
/** Register / unregister the Monaco editor instance (called by RawEditor) */
|
|
258
|
+
setMonacoEditor: (editor: MonacoEditor | null) => void;
|
|
259
|
+
/** Set the light/dark chrome color scheme for the editor shell. */
|
|
260
|
+
setColorScheme: (colorScheme: EditorColorScheme) => void;
|
|
261
|
+
/** Show or hide the inline preview gutter at runtime (driven by the View menu). */
|
|
262
|
+
setInlinePreviewVisible: (visible: boolean) => void;
|
|
263
|
+
/** Show or hide the bottom status bar at runtime (driven by the View menu). */
|
|
264
|
+
setStatusBarVisible: (visible: boolean) => void;
|
|
265
|
+
/** Show or hide the left-side outline pane at runtime (driven by the View menu). */
|
|
266
|
+
setOutlineVisible: (visible: boolean) => void;
|
|
267
|
+
/** Show or hide inline block-template tags at runtime (driven by the View menu). */
|
|
268
|
+
setBlockTagsVisible: (visible: boolean) => void;
|
|
269
|
+
/** Choose when inline block-template tags are shown. */
|
|
270
|
+
setBlockTagVisibility: (visibility: BlockTagVisibility) => void;
|
|
271
|
+
/** Change how much of the active Squisq theme the WYSIWYG surface mirrors. */
|
|
272
|
+
setThemeInheritance: (mode: ThemeInheritance) => void;
|
|
273
|
+
/** Insert text at the current cursor position in the active editor */
|
|
274
|
+
insertAtCursor: (text: string) => void;
|
|
275
|
+
/** Replace all editor content with the given text */
|
|
276
|
+
replaceAll: (text: string) => void;
|
|
277
|
+
/**
|
|
278
|
+
* Request the modal image editor open on the given relative media path.
|
|
279
|
+
* The path must resolve through the active `mediaProvider`. No-op when
|
|
280
|
+
* no provider is wired — callers should hide the affordance in that
|
|
281
|
+
* case.
|
|
282
|
+
*/
|
|
283
|
+
openImageEdit: (relativePath: string) => void;
|
|
284
|
+
/** Close the image editor modal without saving. */
|
|
285
|
+
closeImageEdit: () => void;
|
|
286
|
+
/**
|
|
287
|
+
* Bump `mediaRevision`. Called after the image editor writes back to
|
|
288
|
+
* the original media path so dependent `<img>` nodes re-resolve their
|
|
289
|
+
* blob URL.
|
|
290
|
+
*/
|
|
291
|
+
bumpMediaRevision: () => void;
|
|
292
|
+
}
|
|
293
|
+
interface EditorContextValue extends EditorState, EditorActions {
|
|
294
|
+
/** The live Tiptap editor instance (null when WYSIWYG is not mounted) */
|
|
295
|
+
tiptapEditor: Editor | null;
|
|
296
|
+
/** The live Monaco editor instance (null when Raw is not mounted) */
|
|
297
|
+
monacoEditor: MonacoEditor | null;
|
|
298
|
+
/**
|
|
299
|
+
* The focused canvas textbox editor, if any — a small Tiptap instance for
|
|
300
|
+
* a diagram/drawing/layout textbox being edited inline. Published via
|
|
301
|
+
* `sceneTextChannel` (the canvas renders in a detached React root). The
|
|
302
|
+
* top formatting toolbar retargets to this when set. `level` gates which
|
|
303
|
+
* buttons apply (`inline` = marks only; `rich` = headings/lists too).
|
|
304
|
+
*/
|
|
305
|
+
activeSceneText: SceneTextHandle | null;
|
|
306
|
+
/** Instance-owned bridge used by detached scene widget roots. */
|
|
307
|
+
sceneTextChannel: SceneTextChannel;
|
|
308
|
+
/**
|
|
309
|
+
* Workspace-scoped `ContentContainer` for this document — the folder
|
|
310
|
+
* holding the doc, its `_files/` sidecar, sibling documents, and any
|
|
311
|
+
* version snapshots. Drives audio mapping, version history, and
|
|
312
|
+
* sibling-doc reads for the recursive HTML export.
|
|
313
|
+
*/
|
|
314
|
+
workspaceContainer: ContentContainer | null;
|
|
315
|
+
/**
|
|
316
|
+
* Version manager — non-null only when the host opted into versioning
|
|
317
|
+
* (`allowVersioning` + a `workspaceContainer`). Components can call
|
|
318
|
+
* `saveVersion` directly, or render the version-history panel which
|
|
319
|
+
* reads it from here.
|
|
320
|
+
*/
|
|
321
|
+
versioning: DocumentVersionManager | null;
|
|
322
|
+
/**
|
|
323
|
+
* Stamp a new snapshot of the current document. No-op (returns
|
|
324
|
+
* `unchanged`) when content matches the latest version. Always safe
|
|
325
|
+
* to call — when versioning is disabled, returns `no-document`
|
|
326
|
+
* without writing.
|
|
327
|
+
*/
|
|
328
|
+
saveVersion: (options?: SaveVersionOptions) => Promise<SaveVersionResult>;
|
|
329
|
+
/** MediaProvider for resolving image URLs in the WYSIWYG editor */
|
|
330
|
+
mediaProvider: MediaProvider | null;
|
|
331
|
+
/**
|
|
332
|
+
* How pasted/inserted images should be displayed in the WYSIWYG view.
|
|
333
|
+
* `'inline'` (default) lets them flow at natural size up to the editor
|
|
334
|
+
* width; `'thumbnail'` constrains them to a 100×100 box so chat
|
|
335
|
+
* composers and other dense surfaces don't get dominated by a single
|
|
336
|
+
* pasted screenshot. The stored image bytes are unchanged — this is a
|
|
337
|
+
* pure render-time decision.
|
|
338
|
+
*/
|
|
339
|
+
imageDisplayMode: ImageDisplayMode;
|
|
340
|
+
/**
|
|
341
|
+
* Optional provider for `@`-mention suggestions. When set, both the
|
|
342
|
+
* WYSIWYG (Tiptap) and Raw (Monaco) editors show a mention popover as
|
|
343
|
+
* the user types `@<query>`. When unset, `@` is just a literal character.
|
|
344
|
+
*/
|
|
345
|
+
mentionProvider: MentionProvider | null;
|
|
346
|
+
/**
|
|
347
|
+
* Optional provider for sibling-document suggestions in the link
|
|
348
|
+
* dialog. When set, the dialog shows a "Browse documents" picker that
|
|
349
|
+
* lets authors search neighbor docs by name and insert a relative-
|
|
350
|
+
* path link. When unset, the dialog falls back to URL-only.
|
|
351
|
+
*/
|
|
352
|
+
documentLinkProvider: DocumentLinkProvider | null;
|
|
353
|
+
/**
|
|
354
|
+
* Extra link schemes the host intercepts itself (e.g. an app-internal
|
|
355
|
+
* navigation protocol). The link dialog validates against core's
|
|
356
|
+
* `sanitizeUrl` with these allowed, so authors aren't told a scheme the
|
|
357
|
+
* host DOES resolve is unsupported. Executable schemes stay refused.
|
|
358
|
+
*/
|
|
359
|
+
linkSchemes: readonly string[] | undefined;
|
|
360
|
+
}
|
|
361
|
+
type ImageDisplayMode = 'inline' | 'thumbnail';
|
|
362
|
+
/**
|
|
363
|
+
* Hook to access the editor context. Must be used within an EditorProvider.
|
|
364
|
+
*/
|
|
365
|
+
declare function useEditorContext(): EditorContextValue;
|
|
366
|
+
interface EditorProviderProps {
|
|
367
|
+
/** Initial markdown content */
|
|
368
|
+
initialMarkdown?: string;
|
|
369
|
+
/** Initial active view */
|
|
370
|
+
initialView?: EditorView;
|
|
371
|
+
/** Article ID used when generating the Doc */
|
|
372
|
+
articleId?: string;
|
|
373
|
+
/** Light/dark chrome color scheme for the editor shell. */
|
|
374
|
+
colorScheme?: EditorColorScheme;
|
|
375
|
+
/**
|
|
376
|
+
* Workspace-scoped `ContentContainer` for this document — the folder
|
|
377
|
+
* holding the doc, its `_files/` sidecar, sibling documents, and any
|
|
378
|
+
* version snapshots. Required for `allowVersioning` to take effect.
|
|
379
|
+
*/
|
|
380
|
+
workspaceContainer?: ContentContainer | null;
|
|
381
|
+
/**
|
|
382
|
+
* Enable version history. Snapshots are stored at
|
|
383
|
+
* `.versions/<basename>.<timestamp>.md` inside `workspaceContainer`.
|
|
384
|
+
* Auto-save fires after `versioningAutoSaveIdleMs` of idle; hosts can
|
|
385
|
+
* also call `saveVersion()` from the context. Without a
|
|
386
|
+
* `workspaceContainer`, this prop is ignored (and a `console.warn` is
|
|
387
|
+
* emitted).
|
|
388
|
+
*/
|
|
389
|
+
allowVersioning?: boolean;
|
|
390
|
+
/** Override the basename used in version filenames. Defaults to the
|
|
391
|
+
* basename of the container's primary document path. */
|
|
392
|
+
versionBasename?: string;
|
|
393
|
+
/**
|
|
394
|
+
* Prune policy applied after each successful auto-save. Defaults to
|
|
395
|
+
* keeping the last 50 snapshots so the count doesn't grow unbounded.
|
|
396
|
+
*/
|
|
397
|
+
versioningPrunePolicy?: PrunePolicy;
|
|
398
|
+
/**
|
|
399
|
+
* Idle delay (ms) before auto-saving a version. `0` disables auto-save
|
|
400
|
+
* entirely (versions are saved only via host-driven `saveVersion`
|
|
401
|
+
* calls). Default: 5000.
|
|
402
|
+
*/
|
|
403
|
+
versioningAutoSaveIdleMs?: number;
|
|
404
|
+
/**
|
|
405
|
+
* Notified after each `saveVersion` attempt — both successful saves
|
|
406
|
+
* (`reason: 'saved'`) and skips (`'unchanged'`, `'no-document'`,
|
|
407
|
+
* `'empty'`). Useful for hosts that want a "Last saved" indicator.
|
|
408
|
+
*/
|
|
409
|
+
onSaveVersion?: (result: SaveVersionResult) => void;
|
|
410
|
+
/** MediaProvider for resolving image URLs */
|
|
411
|
+
mediaProvider?: MediaProvider | null;
|
|
412
|
+
/** Display mode for images in the WYSIWYG view. Defaults to `'inline'`. */
|
|
413
|
+
imageDisplayMode?: ImageDisplayMode;
|
|
414
|
+
/**
|
|
415
|
+
* Async provider for `@`-mention suggestions. Omit to disable mentions
|
|
416
|
+
* entirely — typing `@` becomes just a literal character again.
|
|
417
|
+
*/
|
|
418
|
+
mentionProvider?: MentionProvider | null;
|
|
419
|
+
/**
|
|
420
|
+
* Async provider for sibling-document suggestions in the link dialog.
|
|
421
|
+
* Omit to fall back to URL-only link insertion.
|
|
422
|
+
*/
|
|
423
|
+
documentLinkProvider?: DocumentLinkProvider | null;
|
|
424
|
+
/**
|
|
425
|
+
* Extra link schemes this host resolves itself. Threaded into the link
|
|
426
|
+
* dialog's `sanitizeUrl` check so a host-custom protocol is accepted;
|
|
427
|
+
* executable schemes are refused regardless.
|
|
428
|
+
*/
|
|
429
|
+
linkSchemes?: readonly string[];
|
|
430
|
+
/**
|
|
431
|
+
* Whether the in-editor media recorder is available in the toolbar.
|
|
432
|
+
* Defaults to true. Set to false to suppress the recorder affordance
|
|
433
|
+
* even when a `mediaProvider` is wired (e.g. read-only embeds,
|
|
434
|
+
* surfaces where camera/screen prompts would be jarring).
|
|
435
|
+
*/
|
|
436
|
+
allowRecording?: boolean;
|
|
437
|
+
/**
|
|
438
|
+
* Whether the Narrate (teleprompter) display mode is offered under the
|
|
439
|
+
* Use tab. Defaults to true. When false the mode button is hidden and a
|
|
440
|
+
* frontmatter-forced `display-mode: narrate` clamps back to video.
|
|
441
|
+
*/
|
|
442
|
+
allowNarrate?: boolean;
|
|
443
|
+
/**
|
|
444
|
+
* File name (e.g. `foo.ts`) or bare extension — used to pick a Monaco
|
|
445
|
+
* language and decide between markdown vs. code mode.
|
|
446
|
+
*/
|
|
447
|
+
fileName?: string;
|
|
448
|
+
/** Explicit Monaco language ID — wins over the fileName-derived one. */
|
|
449
|
+
language?: string;
|
|
450
|
+
/**
|
|
451
|
+
* Controlled Find-mode state. No trigger button is rendered by default;
|
|
452
|
+
* hosts can set this prop or call `setFindMode` from editor context.
|
|
453
|
+
*/
|
|
454
|
+
findMode?: boolean;
|
|
455
|
+
/** Notified when Find mode requests a state change (for example, its X button). */
|
|
456
|
+
onFindModeChange?: (active: boolean) => void;
|
|
457
|
+
/**
|
|
458
|
+
* Initial visibility of the inline preview gutter. Defaults to false.
|
|
459
|
+
* The toolbar's View menu can toggle it at runtime.
|
|
460
|
+
*/
|
|
461
|
+
inlinePreview?: boolean;
|
|
462
|
+
/**
|
|
463
|
+
* Initial visibility of the bottom status bar. Defaults to true.
|
|
464
|
+
* The toolbar's View menu can toggle it at runtime.
|
|
465
|
+
*/
|
|
466
|
+
showStatusBar?: boolean;
|
|
467
|
+
/**
|
|
468
|
+
* Initial visibility of the left-side outline pane. Defaults to false.
|
|
469
|
+
* The toolbar's View menu can toggle it at runtime.
|
|
470
|
+
*/
|
|
471
|
+
outline?: boolean;
|
|
472
|
+
/**
|
|
473
|
+
* Legacy initial visibility of inline block-template tags on headings.
|
|
474
|
+
* `true` maps to always visible and `false` maps to hidden. When omitted,
|
|
475
|
+
* {@link blockTagVisibility} defaults to `'active'`.
|
|
476
|
+
*/
|
|
477
|
+
blockTags?: boolean;
|
|
478
|
+
/**
|
|
479
|
+
* Initial block-tag visibility mode. When set, this takes precedence over
|
|
480
|
+
* the legacy boolean {@link blockTags} prop. Defaults to `'active'`.
|
|
481
|
+
*/
|
|
482
|
+
blockTagVisibility?: BlockTagVisibility;
|
|
483
|
+
/**
|
|
484
|
+
* Initial value for how much of the active Squisq theme the WYSIWYG
|
|
485
|
+
* editing surface should mirror. Defaults to `'fonts'` — the
|
|
486
|
+
* historical behavior of inheriting body / heading fonts only. The
|
|
487
|
+
* toolbar's View menu can change it at runtime.
|
|
488
|
+
*/
|
|
489
|
+
themeInheritance?: ThemeInheritance;
|
|
490
|
+
/**
|
|
491
|
+
* Initial layout mode. Defaults to `'document'` (whole-document editing).
|
|
492
|
+
* `'block'` boots into the block-at-a-time card view. The toolbar's View
|
|
493
|
+
* menu can toggle it at runtime.
|
|
494
|
+
*/
|
|
495
|
+
layoutMode?: LayoutMode;
|
|
496
|
+
/**
|
|
497
|
+
* Bundled view preferences — a serializable JSON blob covering all
|
|
498
|
+
* runtime-toggleable view options. When provided, individual values
|
|
499
|
+
* here override the matching individual props (`inlinePreview`,
|
|
500
|
+
* `showStatusBar`, `outline`, `blockTagVisibility`, `blockTags`). Hosts
|
|
501
|
+
* wiring this up typically load the blob from their own preferences storage
|
|
502
|
+
* and pair it with {@link onViewPreferencesChange}.
|
|
503
|
+
*/
|
|
504
|
+
viewPreferences?: ViewPreferences;
|
|
505
|
+
/**
|
|
506
|
+
* Notified after each user-driven toggle in the View menu (or any
|
|
507
|
+
* programmatic call to the corresponding context setters). The
|
|
508
|
+
* argument is a full snapshot — hosts can persist it as-is.
|
|
509
|
+
* Not called when {@link viewPreferences} is changed externally.
|
|
510
|
+
*/
|
|
511
|
+
onViewPreferencesChange?: (prefs: ViewPreferences) => void;
|
|
512
|
+
children: ReactNode;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Serializable bundle of all runtime-toggleable view preferences for
|
|
516
|
+
* the editor shell. Hosts can persist this verbatim (e.g. to
|
|
517
|
+
* localStorage) and pass it back via {@link EditorProviderProps.viewPreferences}
|
|
518
|
+
* to restore the user's last view configuration.
|
|
519
|
+
*/
|
|
520
|
+
interface ViewPreferences {
|
|
521
|
+
/** Whether the left-side outline pane is visible. */
|
|
522
|
+
outline?: boolean;
|
|
523
|
+
/** Whether the inline preview gutter (per-block cards) is visible. */
|
|
524
|
+
inlinePreview?: boolean;
|
|
525
|
+
/** Whether the bottom status bar is visible. */
|
|
526
|
+
showStatusBar?: boolean;
|
|
527
|
+
/** Whether inline block-template tags on headings are visible. */
|
|
528
|
+
blockTags?: boolean;
|
|
529
|
+
/** When inline block-template tags are shown. Takes precedence over `blockTags`. */
|
|
530
|
+
blockTagVisibility?: BlockTagVisibility;
|
|
531
|
+
/** How much of the active Squisq theme the WYSIWYG surface mirrors. */
|
|
532
|
+
themeInheritance?: ThemeInheritance;
|
|
533
|
+
/** Document vs. block-at-a-time layout. */
|
|
534
|
+
layoutMode?: LayoutMode;
|
|
535
|
+
}
|
|
536
|
+
declare function EditorProvider({ initialMarkdown, initialView, articleId, colorScheme: initialColorScheme, workspaceContainer, allowVersioning, versionBasename, versioningPrunePolicy, versioningAutoSaveIdleMs, onSaveVersion, mediaProvider, imageDisplayMode, mentionProvider, documentLinkProvider, linkSchemes, allowRecording, allowNarrate, fileName, language, findMode: controlledFindMode, onFindModeChange, inlinePreview, showStatusBar, outline, blockTags, blockTagVisibility: initialBlockTagVisibility, themeInheritance, layoutMode, viewPreferences, onViewPreferencesChange, children, }: EditorProviderProps): react_jsx_runtime.JSX.Element;
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Host-supplied context sections rendered INSIDE the Monaco (raw/code)
|
|
540
|
+
* surface: collapsible markdown blurbs injected above anchor lines, plus an
|
|
541
|
+
* optional file-top summary. Squisq stays host-agnostic — anchors are plain
|
|
542
|
+
* line numbers, ids are opaque strings, links are intercepted via callback.
|
|
543
|
+
*
|
|
544
|
+
* Accessibility note: Monaco marks its view-zone layer `aria-hidden`, so
|
|
545
|
+
* sections are invisible to screen readers in v1.
|
|
546
|
+
*/
|
|
547
|
+
/**
|
|
548
|
+
* One host-supplied markdown blurb anchored above a line of the code buffer.
|
|
549
|
+
* Rendered as a compact one-line strip that expands in place to the full
|
|
550
|
+
* markdown body.
|
|
551
|
+
*/
|
|
552
|
+
interface CodeContextSection {
|
|
553
|
+
/**
|
|
554
|
+
* Stable identity used to reconcile zones across prop updates — e.g. a
|
|
555
|
+
* symbol id like 'resolveImportEdges@60'. Zones are diffed by id: same id +
|
|
556
|
+
* new line moves the zone; same id + new markdown re-renders in place; a
|
|
557
|
+
* new id creates a new zone.
|
|
558
|
+
*/
|
|
559
|
+
id: string;
|
|
560
|
+
/**
|
|
561
|
+
* 1-based line the section renders ABOVE. Out-of-range values are clamped
|
|
562
|
+
* by Monaco. In editable buffers the zone rides Monaco's whitespace
|
|
563
|
+
* semantics — it shifts as lines are inserted/deleted above it and
|
|
564
|
+
* collapses onto the previous line if its anchor lines are deleted. Squisq
|
|
565
|
+
* never re-derives anchors from edits; the host re-supplies lines when it
|
|
566
|
+
* re-analyzes the file.
|
|
567
|
+
*/
|
|
568
|
+
line: number;
|
|
569
|
+
/**
|
|
570
|
+
* Compact markdown for the collapsed strip. Rendered on one line (block
|
|
571
|
+
* structure flattened, overflow ellipsized). Links work here too and go
|
|
572
|
+
* through `onLinkClick`.
|
|
573
|
+
*/
|
|
574
|
+
summaryMarkdown: string;
|
|
575
|
+
/**
|
|
576
|
+
* Full markdown body shown when expanded. Omit while still loading — the
|
|
577
|
+
* expanded view shows a muted loading row and fills in when a later prop
|
|
578
|
+
* update supplies it.
|
|
579
|
+
*/
|
|
580
|
+
markdown?: string;
|
|
581
|
+
/** Start expanded. The user's toggle wins after first interaction. Default false. */
|
|
582
|
+
defaultExpanded?: boolean;
|
|
583
|
+
}
|
|
584
|
+
/** The full context dictionary passed to `EditorShell.codeContext`. */
|
|
585
|
+
interface CodeContext {
|
|
586
|
+
/**
|
|
587
|
+
* Section pinned above line 1 (file summary). Rendered before any line-1
|
|
588
|
+
* `sections` entry. `line` is implicit.
|
|
589
|
+
*/
|
|
590
|
+
fileTop?: Omit<CodeContextSection, 'line'>;
|
|
591
|
+
/** Line-anchored sections. Array order is preserved for equal lines. */
|
|
592
|
+
sections?: CodeContextSection[];
|
|
593
|
+
/**
|
|
594
|
+
* Extra URI schemes section links may use (e.g. `['workspace-nav']`).
|
|
595
|
+
* http/https/mailto/tel are always allowed; executable schemes
|
|
596
|
+
* (javascript:, data:) are never allowed regardless.
|
|
597
|
+
*/
|
|
598
|
+
linkSchemes?: readonly string[];
|
|
599
|
+
/**
|
|
600
|
+
* Intercepts link clicks inside sections, receiving the href exactly as
|
|
601
|
+
* authored in the markdown. Return `false` to let the browser's default
|
|
602
|
+
* navigation proceed; any other return (or void) suppresses it. Fragment
|
|
603
|
+
* links of the form `#L<digits>` are handled natively by squisq (reveal
|
|
604
|
+
* that line in the editor) and never reach this callback. When omitted:
|
|
605
|
+
* http(s)/mailto links open normally, custom-scheme links do nothing.
|
|
606
|
+
*/
|
|
607
|
+
onLinkClick?: (href: string, meta: {
|
|
608
|
+
sectionId: string;
|
|
609
|
+
}) => boolean | undefined;
|
|
610
|
+
/** Notified on expand/collapse — lets hosts lazy-load bodies on first expand. */
|
|
611
|
+
onToggleSection?: (sectionId: string, expanded: boolean) => void;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/** Host-controlled typography for the markdown Write canvas. */
|
|
615
|
+
interface WriteCanvasSettings {
|
|
616
|
+
/** Base text size in CSS pixels. Headings continue to scale relative to it. */
|
|
617
|
+
textSize?: number;
|
|
618
|
+
/** Unitless line-height multiplier for body text. */
|
|
619
|
+
lineSpacing?: number;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
interface EditorShellProps {
|
|
623
|
+
/** Initial markdown content */
|
|
624
|
+
initialMarkdown?: string;
|
|
625
|
+
/** Initial active view */
|
|
626
|
+
/** Initial active view (default: 'wysiwyg') */
|
|
627
|
+
initialView?: EditorView;
|
|
628
|
+
/** Article ID for Doc generation */
|
|
629
|
+
articleId?: string;
|
|
630
|
+
/** Base path for media URLs in preview */
|
|
631
|
+
basePath?: string;
|
|
632
|
+
/** Called when markdown source changes */
|
|
633
|
+
onChange?: (source: string) => void;
|
|
634
|
+
/**
|
|
635
|
+
* Light/dark chrome color scheme for the editor shell — toolbar, tabs,
|
|
636
|
+
* status bar, and side panes (default: `'light'`). This is the editor's
|
|
637
|
+
* UI mode, **not** a Squisq `Theme` object; the rendered document's
|
|
638
|
+
* styling is controlled separately via `themeOverride` / `Doc.themeId`.
|
|
639
|
+
*/
|
|
640
|
+
colorScheme?: 'light' | 'dark';
|
|
641
|
+
/** Additional class name */
|
|
642
|
+
className?: string;
|
|
643
|
+
/** CSS height for the shell container (default: '100vh') */
|
|
644
|
+
height?: string;
|
|
645
|
+
/**
|
|
646
|
+
* Minimum CSS height for the shell. When either `minHeight` or
|
|
647
|
+
* `maxHeight` is set, the shell switches to **auto-grow mode**:
|
|
648
|
+
* `height` is ignored, the root becomes `height: auto` between the
|
|
649
|
+
* bounds, and the content area scrolls internally when content
|
|
650
|
+
* exceeds `maxHeight`. Useful for chat composers that should grow
|
|
651
|
+
* with content up to some cap.
|
|
652
|
+
*/
|
|
653
|
+
minHeight?: string;
|
|
654
|
+
/** See `minHeight`. Upper bound of the auto-grow range. */
|
|
655
|
+
maxHeight?: string;
|
|
656
|
+
/** Optional MediaProvider for the Files panel. When set (even to null), a Files toggle appears in the toolbar. */
|
|
657
|
+
mediaProvider?: MediaProvider | null;
|
|
658
|
+
/**
|
|
659
|
+
* The workspace-scoped `ContentContainer` for this document — the
|
|
660
|
+
* folder that contains the doc, its `_files/` sidecar, sibling
|
|
661
|
+
* documents, and any version snapshots. Used for:
|
|
662
|
+
* - audio mapping (MP3 discovery + timing.json reading);
|
|
663
|
+
* - version history snapshots (when `allowVersioning` is true);
|
|
664
|
+
* - reading sibling `.md` files for the recursive HTML export;
|
|
665
|
+
* - resolving per-document scoped views (e.g. the image-edit
|
|
666
|
+
* sidecar derived via `scopeContainer`).
|
|
667
|
+
* Doc-scoped concerns (per-doc media URLs, per-doc asset writes)
|
|
668
|
+
* flow through `mediaProvider` instead — typically derived from
|
|
669
|
+
* this container via `createMediaProviderFromContainer`.
|
|
670
|
+
*/
|
|
671
|
+
workspaceContainer?: ContentContainer | null;
|
|
672
|
+
/**
|
|
673
|
+
* Enable version history. Snapshots are stored at
|
|
674
|
+
* `.versions/<basename>.<timestamp>.md` inside the same
|
|
675
|
+
* `workspaceContainer`, so they ride along with the document when
|
|
676
|
+
* the host serializes.
|
|
677
|
+
*
|
|
678
|
+
* Snapshots fire on idle (controlled by `versioningAutoSaveIdleMs`)
|
|
679
|
+
* and can also be triggered host-side via the manager exposed in the
|
|
680
|
+
* context (`useEditorContext().versioning`). Has no effect without a
|
|
681
|
+
* `workspaceContainer` — a `console.warn` flags the misconfiguration
|
|
682
|
+
* in dev.
|
|
683
|
+
*/
|
|
684
|
+
allowVersioning?: boolean;
|
|
685
|
+
/**
|
|
686
|
+
* Override the document basename used in version filenames. Defaults
|
|
687
|
+
* to the basename of the container's primary document path.
|
|
688
|
+
*/
|
|
689
|
+
versionBasename?: string;
|
|
690
|
+
/**
|
|
691
|
+
* Prune policy applied after each successful save. Defaults to
|
|
692
|
+
* `{ type: 'keep-last-n', n: 50 }` so the snapshot count stays bounded.
|
|
693
|
+
*/
|
|
694
|
+
versioningPrunePolicy?: PrunePolicy;
|
|
695
|
+
/**
|
|
696
|
+
* Idle delay (ms) before the editor auto-saves a version. `0` disables
|
|
697
|
+
* auto-save entirely (snapshots are then only saved when the host
|
|
698
|
+
* calls `versioning.saveVersion()` from the context). Default: 5000.
|
|
699
|
+
*/
|
|
700
|
+
versioningAutoSaveIdleMs?: number;
|
|
701
|
+
/**
|
|
702
|
+
* Notified after each `saveVersion` attempt. Fires for both successful
|
|
703
|
+
* saves (`reason: 'saved'`) and skips (`'unchanged'`, `'no-document'`,
|
|
704
|
+
* `'empty'`). Useful for hosts that want a "Last saved" indicator.
|
|
705
|
+
*/
|
|
706
|
+
onSaveVersion?: (result: SaveVersionResult) => void;
|
|
707
|
+
/** Show the Files toggle in the toolbar. Defaults to true when mediaProvider is passed. */
|
|
708
|
+
showFilesToggle?: boolean;
|
|
709
|
+
/** Content rendered at the left edge of the toolbar, before the view tabs. */
|
|
710
|
+
toolbarSlotLeft?: ReactNode;
|
|
711
|
+
/** Content rendered after the formatting controls (in the middle area of the toolbar). */
|
|
712
|
+
toolbarSlotAfterActions?: ReactNode;
|
|
713
|
+
/** Content rendered at the rightmost end of the toolbar, after all other elements. */
|
|
714
|
+
toolbarSlotRight?: ReactNode;
|
|
715
|
+
/** Host-supplied content rendered at the right edge of the bottom status bar. */
|
|
716
|
+
statusBarSlotRight?: ReactNode;
|
|
717
|
+
/**
|
|
718
|
+
* Whether to show the "Play" (preview) tab in the toolbar. When false, the
|
|
719
|
+
* tab and its preview panel are hidden, and ⌘3 becomes a no-op. Use this
|
|
720
|
+
* when embedding the editor somewhere the slideshow preview doesn't make
|
|
721
|
+
* sense (e.g. editing free-form prompt documents). Defaults to true.
|
|
722
|
+
*/
|
|
723
|
+
showPlayTab?: boolean;
|
|
724
|
+
/**
|
|
725
|
+
* Optional "submit on Enter" callback. When provided, a plain Enter
|
|
726
|
+
* keypress fires this callback instead of inserting a newline, and
|
|
727
|
+
* Cmd/Ctrl+Enter inserts a newline instead. Matches chat-composer UX
|
|
728
|
+
* (Slack, Discord). When omitted, the editor behaves normally.
|
|
729
|
+
*/
|
|
730
|
+
submitOnEnter?: () => void;
|
|
731
|
+
/**
|
|
732
|
+
* Host-supplied context dictionary rendered inside the Monaco (raw / code)
|
|
733
|
+
* surface: collapsible markdown sections injected above anchor lines, plus
|
|
734
|
+
* an optional file-top summary. See {@link CodeContext}. Ignored in
|
|
735
|
+
* WYSIWYG / preview / image surfaces.
|
|
736
|
+
*/
|
|
737
|
+
codeContext?: CodeContext;
|
|
738
|
+
/**
|
|
739
|
+
* Let the WYSIWYG editing surface fill its container instead of rendering
|
|
740
|
+
* as a centered 800px "page" column. Useful when embedding in chat
|
|
741
|
+
* composers, side panels, or any layout where the page metaphor doesn't
|
|
742
|
+
* fit. Defaults to false (page mode).
|
|
743
|
+
*/
|
|
744
|
+
fullWidth?: boolean;
|
|
745
|
+
/**
|
|
746
|
+
* Font-family stack applied to the editor **chrome** — toolbar buttons,
|
|
747
|
+
* tabs, status bar, and control surfaces. The actual editing areas
|
|
748
|
+
* (Tiptap / Monaco) keep their own fonts so document editing isn't
|
|
749
|
+
* affected. Use this when the editor is embedded in a larger product
|
|
750
|
+
* that has its own UX type system and you want the controls to blend in.
|
|
751
|
+
*
|
|
752
|
+
* @example
|
|
753
|
+
* ```tsx
|
|
754
|
+
* <EditorShell uxFont="'Hanken Grotesk', system-ui, sans-serif" ... />
|
|
755
|
+
* ```
|
|
756
|
+
*/
|
|
757
|
+
uxFont?: string;
|
|
758
|
+
/**
|
|
759
|
+
* Drop the editor's generous page-style padding in favor of a tight
|
|
760
|
+
* layout that hugs its container. The default WYSIWYG surface uses
|
|
761
|
+
* 16×24px padding suitable for editing long-form documents; chat
|
|
762
|
+
* composers want much less. Applies to the editing area only — the
|
|
763
|
+
* toolbar, tabs, and status bar keep their normal sizing.
|
|
764
|
+
*/
|
|
765
|
+
thinMargins?: boolean;
|
|
766
|
+
/**
|
|
767
|
+
* Host-controlled typography for the markdown Write canvas. `textSize` is
|
|
768
|
+
* measured in CSS pixels and `lineSpacing` is a unitless line-height
|
|
769
|
+
* multiplier. This is presentation-only and does not modify the markdown.
|
|
770
|
+
*/
|
|
771
|
+
writeCanvasSettings?: WriteCanvasSettings;
|
|
772
|
+
/**
|
|
773
|
+
* Render the bottom status bar (word / character / line / block counts,
|
|
774
|
+
* parse errors, and optional host status). Defaults to `true`. Set to `false` in
|
|
775
|
+
* embedded surfaces — chat composers and other short-form inputs —
|
|
776
|
+
* where the stats are noise.
|
|
777
|
+
*/
|
|
778
|
+
showStatusBar?: boolean;
|
|
779
|
+
/**
|
|
780
|
+
* How images should be displayed in the WYSIWYG view. `'inline'`
|
|
781
|
+
* (default) flows them at natural size up to the container width;
|
|
782
|
+
* `'thumbnail'` constrains each image to a 100×100 box with
|
|
783
|
+
* aspect-preserving containment — useful for chat composers and other
|
|
784
|
+
* dense surfaces where a full-resolution paste would dominate the
|
|
785
|
+
* layout. Storage bytes are unchanged either way.
|
|
786
|
+
*/
|
|
787
|
+
imageDisplayMode?: ImageDisplayMode;
|
|
788
|
+
/**
|
|
789
|
+
* File name (e.g. `foo.ts`) or bare extension that the content
|
|
790
|
+
* represents. When set to a non-markdown/text extension, the shell
|
|
791
|
+
* enters **code mode**: Monaco picks the right language based on the
|
|
792
|
+
* extension, the WYSIWYG and Preview tabs disappear, and the toolbar
|
|
793
|
+
* drops its markdown-specific formatting buttons. Markdown-ish
|
|
794
|
+
* extensions (`.md`, `.markdown`, `.mdown`, `.txt`) keep the full
|
|
795
|
+
* experience. Omit to get today's markdown behavior unchanged.
|
|
796
|
+
*/
|
|
797
|
+
fileName?: string;
|
|
798
|
+
/**
|
|
799
|
+
* Explicit Monaco language ID override (e.g. `'typescript'`,
|
|
800
|
+
* `'python'`, `'json'`). Wins over the language derived from
|
|
801
|
+
* `fileName`. Anything other than `'markdown'` or `'plaintext'`
|
|
802
|
+
* switches the shell into code mode.
|
|
803
|
+
*/
|
|
804
|
+
language?: string;
|
|
805
|
+
/**
|
|
806
|
+
* Controlled Find-mode state. Find has no built-in trigger button; hosts
|
|
807
|
+
* opt in by setting this prop (or by calling `setFindMode` from a toolbar
|
|
808
|
+
* slot rendered inside the editor context).
|
|
809
|
+
*/
|
|
810
|
+
findMode?: boolean;
|
|
811
|
+
/** Called when Find mode requests a state change, including its X button. */
|
|
812
|
+
onFindModeChange?: (active: boolean) => void;
|
|
813
|
+
/**
|
|
814
|
+
* Optional async provider for `@`-mention suggestions. When supplied,
|
|
815
|
+
* typing `@` inside the editor opens a popover of candidates; selecting
|
|
816
|
+
* one inserts a `@[Label](scheme:id)` mention token. Used by chat
|
|
817
|
+
* composers and any other surface that wants to address named entities
|
|
818
|
+
* inline. Omit to disable mentions entirely.
|
|
819
|
+
*/
|
|
820
|
+
mentionProvider?: MentionProvider | null;
|
|
821
|
+
/**
|
|
822
|
+
* Optional async provider for sibling-document suggestions in the
|
|
823
|
+
* link insert dialog. When supplied, the dialog gains a "Browse
|
|
824
|
+
* documents" picker so authors can pick a neighbor `.md` by name and
|
|
825
|
+
* insert a relative-path link without typing the URL by hand. Hosts
|
|
826
|
+
* that organize docs in a workspace (file-system, IndexedDB slot,
|
|
827
|
+
* remote API, …) implement this; the editor stays agnostic.
|
|
828
|
+
*/
|
|
829
|
+
documentLinkProvider?: DocumentLinkProvider | null;
|
|
830
|
+
/**
|
|
831
|
+
* Extra link schemes this host resolves itself (e.g. an app-internal
|
|
832
|
+
* navigation protocol). The link dialog validates typed URLs against
|
|
833
|
+
* core's `sanitizeUrl` with these allowed, so an author isn't told a
|
|
834
|
+
* scheme the host DOES handle is unsupported. Executable schemes
|
|
835
|
+
* (`javascript:`, `vbscript:`, `data:`) are refused regardless.
|
|
836
|
+
*/
|
|
837
|
+
linkSchemes?: readonly string[];
|
|
838
|
+
/**
|
|
839
|
+
* Whether the in-editor media recorder is surfaced in the toolbar.
|
|
840
|
+
* Defaults to true — when a `mediaProvider` is wired, a record
|
|
841
|
+
* button appears next to the version history. Pass `false` to
|
|
842
|
+
* suppress it (read-only embeds, surfaces where camera/screen
|
|
843
|
+
* permission prompts would be jarring). Without a `mediaProvider`,
|
|
844
|
+
* the button is hidden regardless of this prop.
|
|
845
|
+
*/
|
|
846
|
+
allowRecording?: boolean;
|
|
847
|
+
/**
|
|
848
|
+
* Whether the Narrate (teleprompter) display mode is offered under the
|
|
849
|
+
* Use tab. Defaults to true. Orthogonal to `allowRecording` — the
|
|
850
|
+
* prompter is useful without capture (reading for external recording
|
|
851
|
+
* software), and the in-mode Record affordance additionally requires
|
|
852
|
+
* `allowRecording` + a `mediaProvider`.
|
|
853
|
+
*/
|
|
854
|
+
allowNarrate?: boolean;
|
|
855
|
+
/**
|
|
856
|
+
* Placeholder text shown in the WYSIWYG editor while the document is
|
|
857
|
+
* empty. When omitted, the editor rotates through its own generic
|
|
858
|
+
* "start typing…" prompts; pass a value here to override with copy
|
|
859
|
+
* that fits the embedding surface (e.g. a chat composer knows who
|
|
860
|
+
* the message is going to and can say so).
|
|
861
|
+
*/
|
|
862
|
+
placeholder?: string;
|
|
863
|
+
/**
|
|
864
|
+
* When true, both editing surfaces become non-editable: Monaco runs in
|
|
865
|
+
* `readOnly` mode and Tiptap is set to `editable: false`. The toolbar
|
|
866
|
+
* still renders — hide it from the host side if you want a pure preview.
|
|
867
|
+
* Useful for reference panels that show file content without inviting
|
|
868
|
+
* accidental edits.
|
|
869
|
+
*/
|
|
870
|
+
readOnly?: boolean;
|
|
871
|
+
/**
|
|
872
|
+
* Image source URL used when the resolved file mode is `image` (PNG,
|
|
873
|
+
* JPEG, GIF, WebP, BMP, ICO, AVIF). When this prop is set, the shell
|
|
874
|
+
* replaces its text-editing surfaces with a dedicated `ImageViewer`.
|
|
875
|
+
*
|
|
876
|
+
* Lifecycle of the URL is the caller's responsibility — when fed a
|
|
877
|
+
* `blob:` URL, the host should `URL.revokeObjectURL` on unmount or
|
|
878
|
+
* src change.
|
|
879
|
+
*/
|
|
880
|
+
imageSrc?: string;
|
|
881
|
+
/** Alt text passed through to the underlying ImageViewer. */
|
|
882
|
+
imageAlt?: string;
|
|
883
|
+
/**
|
|
884
|
+
* Whether the image surface should render as a read-only viewer
|
|
885
|
+
* (`'view'`, default) or as the editable {@link ImageEditor}
|
|
886
|
+
* (`'edit'`). Editing requires {@link EditorShellProps.imageEditorContainer}
|
|
887
|
+
* — without it the shell falls back to view mode and logs a warning.
|
|
888
|
+
*/
|
|
889
|
+
imageMode?: 'view' | 'edit';
|
|
890
|
+
/**
|
|
891
|
+
* Sidecar `ContentContainer` for the image being edited. Conventionally
|
|
892
|
+
* scoped to `<basename>_files/` via
|
|
893
|
+
* `scopeContainer(parentContainer, basename + '_files')`. The image
|
|
894
|
+
* editor persists `state.json`, layer assets in `assets/`, and (when
|
|
895
|
+
* `allowVersioning` is true) snapshots in `.versions/` inside it.
|
|
896
|
+
*/
|
|
897
|
+
imageEditorContainer?: ContentContainer;
|
|
898
|
+
/**
|
|
899
|
+
* Called after the user clicks Export in the image editor and the
|
|
900
|
+
* raster blob is produced. When omitted, the editor triggers a
|
|
901
|
+
* default browser download.
|
|
902
|
+
*/
|
|
903
|
+
onImageExport?: (blob: Blob, format: 'png' | 'jpeg' | 'webp') => void;
|
|
904
|
+
/**
|
|
905
|
+
* Show an inline preview gutter to the right of the WYSIWYG editor.
|
|
906
|
+
* The gutter renders one small SVG card per template-annotated block in
|
|
907
|
+
* the document, letting authors see their rendered output without
|
|
908
|
+
* leaving Edit mode. Auto-hidden via container query when the editor
|
|
909
|
+
* body is narrower than ~720px. Defaults to `false`.
|
|
910
|
+
*/
|
|
911
|
+
inlinePreview?: boolean;
|
|
912
|
+
/**
|
|
913
|
+
* Width in pixels for the inline preview gutter. Defaults to 320.
|
|
914
|
+
* Only takes effect when {@link EditorShellProps.inlinePreview} is true.
|
|
915
|
+
*/
|
|
916
|
+
inlinePreviewWidth?: number;
|
|
917
|
+
/**
|
|
918
|
+
* Show an outline pane on the left of the WYSIWYG editor — a
|
|
919
|
+
* hierarchical tree of the document's headings (h1 → h2 → h3) with
|
|
920
|
+
* click-to-scroll. Auto-hidden via container query on narrow editors.
|
|
921
|
+
* Defaults to `false`. The toolbar's View menu can toggle this at
|
|
922
|
+
* runtime regardless of the initial value.
|
|
923
|
+
*/
|
|
924
|
+
outline?: boolean;
|
|
925
|
+
/**
|
|
926
|
+
* Fixed width in pixels for the outline pane. When omitted, the pane sizes
|
|
927
|
+
* responsively — never narrower than 260px, growing with the window and
|
|
928
|
+
* capped at 460px — so it stretches out when there's horizontal space to
|
|
929
|
+
* spare. Only takes effect when {@link EditorShellProps.outline} is true (or
|
|
930
|
+
* the View menu has toggled it on).
|
|
931
|
+
*/
|
|
932
|
+
outlineWidth?: number;
|
|
933
|
+
/**
|
|
934
|
+
* Legacy initial visibility of inline block-template tags on headings.
|
|
935
|
+
* `true` maps to always visible and `false` maps to hidden. When omitted,
|
|
936
|
+
* {@link blockTagVisibility} defaults to `'active'`.
|
|
937
|
+
*/
|
|
938
|
+
blockTags?: boolean;
|
|
939
|
+
/**
|
|
940
|
+
* Initial block-tag visibility mode. Takes precedence over `blockTags`.
|
|
941
|
+
* Defaults to `'active'` (selected/hovered block only).
|
|
942
|
+
*/
|
|
943
|
+
blockTagVisibility?: BlockTagVisibility;
|
|
944
|
+
/**
|
|
945
|
+
* How much of the active Squisq theme the WYSIWYG editing surface
|
|
946
|
+
* mirrors. Defaults to `'fonts'` — the historical behavior of
|
|
947
|
+
* inheriting body / heading fonts only. The View menu can change it
|
|
948
|
+
* at runtime.
|
|
949
|
+
*/
|
|
950
|
+
themeInheritance?: ThemeInheritance;
|
|
951
|
+
/**
|
|
952
|
+
* Bundled view preferences — a serializable JSON blob covering the
|
|
953
|
+
* runtime-toggleable view options surfaced in the View menu. When
|
|
954
|
+
* provided, fields here override the corresponding individual props
|
|
955
|
+
* (`outline`, `inlinePreview`, `showStatusBar`, `blockTagVisibility`,
|
|
956
|
+
* `blockTags`). Pair with
|
|
957
|
+
* {@link onViewPreferencesChange} to externalize storage of these
|
|
958
|
+
* preferences in the host.
|
|
959
|
+
*/
|
|
960
|
+
viewPreferences?: ViewPreferences;
|
|
961
|
+
/**
|
|
962
|
+
* Notified after each user-driven toggle in the View menu. The
|
|
963
|
+
* argument is a full snapshot of all view preferences — hosts can
|
|
964
|
+
* persist it as-is. Not called when {@link viewPreferences} is
|
|
965
|
+
* changed externally.
|
|
966
|
+
*/
|
|
967
|
+
onViewPreferencesChange?: (prefs: ViewPreferences) => void;
|
|
968
|
+
/**
|
|
969
|
+
* Override the preview theme with an explicit `Theme` object. When set,
|
|
970
|
+
* `Doc.themeId` and the user's theme dropdown selection are ignored for
|
|
971
|
+
* the preview surface. Used by the theme customizer to live-preview an
|
|
972
|
+
* in-progress theme without mutating the document.
|
|
973
|
+
*/
|
|
974
|
+
themeOverride?: Theme | null;
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Complete markdown editor shell with toolbar, view switcher, and three
|
|
978
|
+
* editing modes: Raw (Monaco), WYSIWYG (Tiptap), and Preview.
|
|
979
|
+
*/
|
|
980
|
+
declare function EditorShell({ initialMarkdown, initialView, articleId, basePath, onChange, colorScheme, className, height, minHeight, maxHeight, mediaProvider, workspaceContainer, allowVersioning, versionBasename, versioningPrunePolicy, versioningAutoSaveIdleMs, onSaveVersion, showFilesToggle, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, statusBarSlotRight, showPlayTab, submitOnEnter, codeContext, fullWidth, uxFont, thinMargins, writeCanvasSettings, showStatusBar, imageDisplayMode, fileName, language, findMode, onFindModeChange, mentionProvider, documentLinkProvider, linkSchemes, allowRecording, allowNarrate, placeholder, readOnly, imageSrc, imageAlt, imageMode, imageEditorContainer, onImageExport, inlinePreview, inlinePreviewWidth, outline, outlineWidth, blockTags, blockTagVisibility, themeInheritance, viewPreferences, onViewPreferencesChange, themeOverride, }: EditorShellProps): react_jsx_runtime.JSX.Element;
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* RawEditor
|
|
984
|
+
*
|
|
985
|
+
* Monaco-based raw markdown editor. Provides full VS Code-like editing
|
|
986
|
+
* experience with syntax highlighting, minimap, and bracket matching.
|
|
987
|
+
* Syncs changes back to EditorContext on every keystroke (debounced).
|
|
988
|
+
*/
|
|
989
|
+
interface RawEditorProps {
|
|
990
|
+
/**
|
|
991
|
+
* Monaco editor theme name (default: `'vs'`). Accepts Monaco's built-in
|
|
992
|
+
* theme ids (`'vs'`, `'vs-dark'`, `'hc-black'`) — which are transparently
|
|
993
|
+
* mapped to the Squisq-tinted variants — or any custom theme registered
|
|
994
|
+
* via `monaco.editor.defineTheme`. This is the *code editor* color
|
|
995
|
+
* theme, distinct from the shell's light/dark `colorScheme`.
|
|
996
|
+
*/
|
|
997
|
+
monacoTheme?: string;
|
|
998
|
+
/** Show minimap (default: false) */
|
|
999
|
+
minimap?: boolean;
|
|
1000
|
+
/** Font size in pixels (default: 14) */
|
|
1001
|
+
fontSize?: number;
|
|
1002
|
+
/** Word wrap setting (default: 'on') */
|
|
1003
|
+
wordWrap?: 'on' | 'off' | 'wordWrapColumn' | 'bounded';
|
|
1004
|
+
/** Additional class name for the container */
|
|
1005
|
+
className?: string;
|
|
1006
|
+
/**
|
|
1007
|
+
* Chat-composer mode: Enter fires this callback (submit) and Cmd/Ctrl+Enter
|
|
1008
|
+
* inserts a newline. When undefined, behaves normally.
|
|
1009
|
+
*/
|
|
1010
|
+
submitOnEnter?: () => void;
|
|
1011
|
+
/** Make Monaco read-only (no edits, no cursor blink). */
|
|
1012
|
+
readOnly?: boolean;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Raw markdown editor using Monaco Editor.
|
|
1016
|
+
* Binds to the shared EditorContext for source synchronization.
|
|
1017
|
+
*/
|
|
1018
|
+
declare function RawEditor({ monacoTheme, minimap, fontSize, wordWrap, className, submitOnEnter, readOnly, }: RawEditorProps): react_jsx_runtime.JSX.Element;
|
|
1019
|
+
|
|
1020
|
+
interface WysiwygEditorProps {
|
|
1021
|
+
/**
|
|
1022
|
+
* Placeholder text when the editor is empty. If omitted, one of several
|
|
1023
|
+
* rotating prompts is picked at random on mount. Pass a fixed string to
|
|
1024
|
+
* override with a host-specific call to action.
|
|
1025
|
+
*/
|
|
1026
|
+
placeholder?: string;
|
|
1027
|
+
/** Additional class name for the container */
|
|
1028
|
+
className?: string;
|
|
1029
|
+
/**
|
|
1030
|
+
* If set, a plain Enter keypress fires this callback instead of inserting
|
|
1031
|
+
* a newline, and Cmd/Ctrl+Enter inserts a soft break. Chat-composer UX.
|
|
1032
|
+
*/
|
|
1033
|
+
submitOnEnter?: () => void;
|
|
1034
|
+
/** Disable Tiptap editing — renders content but blocks input. */
|
|
1035
|
+
readOnly?: boolean;
|
|
1036
|
+
/** Host-controlled base text size and line spacing for the Write canvas. */
|
|
1037
|
+
writeCanvasSettings?: WriteCanvasSettings;
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Rich WYSIWYG markdown editor built on Tiptap (ProseMirror).
|
|
1041
|
+
* Binds to the shared EditorContext for source synchronization.
|
|
1042
|
+
*/
|
|
1043
|
+
declare function WysiwygEditor({ placeholder, className, submitOnEnter, readOnly, writeCanvasSettings, }: WysiwygEditorProps): react_jsx_runtime.JSX.Element;
|
|
1044
|
+
|
|
1045
|
+
interface PreviewPanelProps {
|
|
1046
|
+
/** Base path for resolving media URLs in DocPlayer */
|
|
1047
|
+
basePath?: string;
|
|
1048
|
+
/** Additional class name for the container */
|
|
1049
|
+
className?: string;
|
|
1050
|
+
/**
|
|
1051
|
+
* Workspace-scoped `ContentContainer` (the folder holding the doc and
|
|
1052
|
+
* its siblings). Used here for audio mapping — MP3 discovery and
|
|
1053
|
+
* `timing.json` reading.
|
|
1054
|
+
*/
|
|
1055
|
+
workspaceContainer?: ContentContainer | null;
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Live preview panel that renders the current document as a slideshow
|
|
1059
|
+
* or document view. Controls (viewport, mode, theme, transform, captions)
|
|
1060
|
+
* are rendered in the main toolbar via PreviewToolbarControls.
|
|
1061
|
+
*/
|
|
1062
|
+
declare function PreviewPanel({ basePath, className, workspaceContainer }: PreviewPanelProps): react_jsx_runtime.JSX.Element;
|
|
1063
|
+
|
|
1064
|
+
export { type BlockTagVisibility as B, type CodeContext as C, type DocumentLinkCandidate as D, type EditorActions as E, type ImageDisplayMode as I, type LayoutMode as L, type MentionCandidate as M, PreviewPanel as P, RawEditor as R, type SceneTextChannel as S, type ThemeInheritance as T, type ViewPreferences as V, type WriteCanvasSettings as W, type CodeContextSection as a, type DocumentLinkProvider as b, type EditorColorScheme as c, type EditorContextValue as d, type EditorMode as e, EditorProvider as f, type EditorProviderProps as g, EditorShell as h, type EditorShellProps as i, type EditorState as j, type EditorView as k, type MentionProvider as l, type PreviewPanelProps as m, type RawEditorProps as n, WysiwygEditor as o, type WysiwygEditorProps as p, useEditorContext as u };
|