@bendyline/squisq-editor-react 2.2.0 → 2.3.1

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.
@@ -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 };