@notectl/core 0.0.2 → 0.0.6

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,1816 @@
1
+ /**
2
+ * @notectl/core — State-first rich text editor Web Component.
3
+ * @packageDocumentation
4
+ */
5
+
6
+ /**
7
+ * Branded (nominal) types for semantic string distinctions.
8
+ * Prevents accidental interchange of structurally identical IDs.
9
+ */
10
+ declare const __brand: unique symbol;
11
+
12
+ export declare interface AddMarkStep {
13
+ readonly type: 'addMark';
14
+ readonly blockId: BlockId;
15
+ readonly from: number;
16
+ readonly to: number;
17
+ readonly mark: Mark;
18
+ readonly path?: readonly BlockId[];
19
+ }
20
+
21
+ /** Applies a single step to a document and returns the new document. */
22
+ export declare function applyStep(doc: Document_2, step: Step): Document_2;
23
+
24
+ export declare interface AttrSpec {
25
+ readonly default?: string | number | boolean;
26
+ }
27
+
28
+ export declare interface BlockAttrs {
29
+ readonly [key: string]: string | number | boolean;
30
+ }
31
+
32
+ /** Unique identifier for a block node in the document tree. */
33
+ export declare type BlockId = Brand<string, 'BlockId'>;
34
+
35
+ export declare function blockId(id: string): BlockId;
36
+
37
+ export declare interface BlockNode {
38
+ readonly id: BlockId;
39
+ readonly type: NodeTypeName;
40
+ readonly attrs?: BlockAttrs;
41
+ readonly children: readonly ChildNode_2[];
42
+ }
43
+
44
+ export declare interface BlockquoteConfig {
45
+ /** When true, a separator is rendered after the blockquote toolbar item. */
46
+ readonly separatorAfter?: boolean;
47
+ }
48
+
49
+ export declare class BlockquotePlugin implements Plugin_2 {
50
+ readonly id = "blockquote";
51
+ readonly name = "Blockquote";
52
+ readonly priority = 35;
53
+ private readonly config;
54
+ constructor(config?: Partial<BlockquoteConfig>);
55
+ init(context: PluginContext): void;
56
+ private registerNodeSpec;
57
+ private registerCommands;
58
+ private registerKeymap;
59
+ private registerInputRule;
60
+ private registerToolbarItem;
61
+ /**
62
+ * Toggles between blockquote and paragraph.
63
+ * If the block is already a blockquote, resets to paragraph.
64
+ */
65
+ private toggleBlockquote;
66
+ private setBlockType;
67
+ }
68
+
69
+ export declare interface BoldMark extends Mark {
70
+ readonly type: MarkTypeName & 'bold';
71
+ }
72
+
73
+ declare type Brand<T, B extends string> = T & {
74
+ readonly [__brand]: B;
75
+ };
76
+
77
+ /**
78
+ * Checks if a parent node type can contain a child node type,
79
+ * using the content rules and group system from NodeSpec.
80
+ */
81
+ export declare function canContain(registry: SchemaRegistry, parentType: string, childType: string): boolean;
82
+
83
+ /** Rectangular range of cells within a table. */
84
+ export declare interface CellRange {
85
+ readonly tableId: BlockId;
86
+ readonly fromRow: number;
87
+ readonly fromCol: number;
88
+ readonly toRow: number;
89
+ readonly toCol: number;
90
+ }
91
+
92
+ /** A child of a BlockNode: text, inline element, or nested block. */
93
+ declare type ChildNode_2 = TextNode | InlineNode | BlockNode;
94
+ export { ChildNode_2 as ChildNode }
95
+
96
+ export declare interface CommandEntry {
97
+ readonly name: string;
98
+ readonly handler: CommandHandler;
99
+ readonly pluginId: string;
100
+ }
101
+
102
+ export declare type CommandHandler = () => boolean;
103
+
104
+ /** Registered command name. */
105
+ export declare type CommandName = Brand<string, 'CommandName'>;
106
+
107
+ export declare function commandName(name: string): CommandName;
108
+
109
+ /** Describes which children a node type is allowed to contain. */
110
+ export declare interface ContentRule {
111
+ /** Allowed child types or group names. */
112
+ readonly allow: readonly string[];
113
+ readonly min?: number;
114
+ readonly max?: number;
115
+ }
116
+
117
+ /** A content segment: either text (with marks) or an inline node. */
118
+ export declare type ContentSegment = {
119
+ readonly kind: 'text';
120
+ readonly text: string;
121
+ readonly marks: readonly Mark[];
122
+ } | {
123
+ readonly kind: 'inline';
124
+ readonly node: InlineNode;
125
+ };
126
+
127
+ /** Creates an HTMLElement with the required `data-block-id` attribute. */
128
+ export declare function createBlockElement(tag: string, blockId: BlockId): HTMLElement;
129
+
130
+ /** Creates a new {@link BlockNode}. */
131
+ export declare function createBlockNode(type: NodeTypeName, children?: readonly ChildNode_2[], id?: BlockId, attrs?: BlockAttrs): BlockNode;
132
+
133
+ /** Creates a collapsed selection (cursor) at the given position. */
134
+ export declare function createCollapsedSelection(blockId: BlockId, offset: number): Selection_2;
135
+
136
+ /** Creates a new empty {@link Document} with a single empty paragraph. */
137
+ export declare function createDocument(children?: readonly BlockNode[]): Document_2;
138
+
139
+ /** Factory function to create and configure a NotectlEditor instance. */
140
+ export declare function createEditor(config?: NotectlEditorConfig): Promise<NotectlEditor>;
141
+
142
+ /** Creates a new {@link InlineNode}. */
143
+ export declare function createInlineNode(inlineType: InlineTypeName, attrs?: Readonly<Record<string, string | number | boolean>>): InlineNode;
144
+
145
+ /** Creates a Position, optionally with a path. */
146
+ export declare function createPosition(blockId: BlockId, offset: number, path?: readonly BlockId[]): Position;
147
+
148
+ /** Creates a selection with distinct anchor and head. */
149
+ export declare function createSelection(anchor: Position, head: Position): Selection_2;
150
+
151
+ /** Creates a new {@link TextNode}. */
152
+ export declare function createTextNode(text: string, marks?: readonly Mark[]): TextNode;
153
+
154
+ export declare type Decoration = InlineDecoration | NodeDecoration | WidgetDecoration;
155
+
156
+ export declare interface DecorationAttrs {
157
+ readonly class?: string;
158
+ readonly style?: string;
159
+ readonly nodeName?: string;
160
+ readonly [key: string]: string | undefined;
161
+ }
162
+
163
+ /**
164
+ * Immutable set of decorations indexed by block ID.
165
+ * Provides efficient lookup and merging of decoration collections.
166
+ */
167
+ export declare class DecorationSet {
168
+ private readonly byBlock;
169
+ static readonly empty: DecorationSet;
170
+ private constructor();
171
+ /** Creates a DecorationSet from a flat array of decorations. */
172
+ static create(decorations: readonly Decoration[]): DecorationSet;
173
+ /** Returns all decorations for a given block. */
174
+ find(blockId: BlockId): readonly Decoration[];
175
+ /** Returns only inline decorations for a given block. */
176
+ findInline(blockId: BlockId): readonly InlineDecoration[];
177
+ /** Returns only node decorations for a given block. */
178
+ findNode(blockId: BlockId): readonly NodeDecoration[];
179
+ /** Returns only widget decorations for a given block. */
180
+ findWidget(blockId: BlockId): readonly WidgetDecoration[];
181
+ /** Returns a new DecorationSet with the given decorations added. */
182
+ add(decorations: readonly Decoration[]): DecorationSet;
183
+ /** Returns a new DecorationSet with decorations matching the predicate removed. */
184
+ remove(predicate: (d: Decoration) => boolean): DecorationSet;
185
+ /** Returns a new DecorationSet merging this set with another. */
186
+ merge(other: DecorationSet): DecorationSet;
187
+ /** Checks equality — reference first, then structural comparison. */
188
+ equals(other: DecorationSet): boolean;
189
+ /** True if the set contains no decorations. */
190
+ get isEmpty(): boolean;
191
+ /**
192
+ * Maps decorations through document changes described by a transaction.
193
+ * Decorations that become invalid (e.g. fully deleted range) are removed.
194
+ * Decorations that span a split point are split into two.
195
+ */
196
+ map(tr: Transaction): DecorationSet;
197
+ }
198
+
199
+ /** Creates the default schema with paragraph nodes and bold/italic/underline marks. */
200
+ export declare function defaultSchema(): Schema;
201
+
202
+ /** Handles backspace key. */
203
+ export declare function deleteBackward(state: EditorState): Transaction | null;
204
+
205
+ /** Handles delete key. */
206
+ export declare function deleteForward(state: EditorState): Transaction | null;
207
+
208
+ /** Deletes the current selection. */
209
+ export declare function deleteSelectionCommand(state: EditorState): Transaction | null;
210
+
211
+ export declare interface DeleteTextStep {
212
+ readonly type: 'deleteText';
213
+ readonly blockId: BlockId;
214
+ readonly from: number;
215
+ readonly to: number;
216
+ readonly deletedText: string;
217
+ readonly deletedMarks: readonly Mark[];
218
+ readonly deletedSegments: readonly TextSegment[];
219
+ readonly path?: readonly BlockId[];
220
+ }
221
+
222
+ declare interface Document_2 {
223
+ readonly children: readonly BlockNode[];
224
+ }
225
+ export { Document_2 as Document }
226
+
227
+ export declare interface DropdownConfig {
228
+ readonly items: readonly {
229
+ label: string;
230
+ command: string;
231
+ icon?: string;
232
+ }[];
233
+ }
234
+
235
+ export declare class EditorState {
236
+ readonly doc: Document_2;
237
+ readonly selection: Selection_2;
238
+ readonly storedMarks: readonly Mark[] | null;
239
+ readonly schema: Schema;
240
+ private _blockMap;
241
+ private _blockOrder;
242
+ private constructor();
243
+ /** Creates a new EditorState with default document. */
244
+ static create(options?: {
245
+ doc?: Document_2;
246
+ selection?: Selection_2;
247
+ schema?: Schema;
248
+ }): EditorState;
249
+ /** Creates a TransactionBuilder from this state. */
250
+ transaction(origin?: 'input' | 'paste' | 'command' | 'history' | 'api'): TransactionBuilder;
251
+ /** Applies a transaction and returns a new EditorState. */
252
+ apply(tr: Transaction): EditorState;
253
+ /** Finds a block by its ID anywhere in the tree. Uses a lazy-built Map for O(1) lookup. */
254
+ getBlock(blockId: BlockId): BlockNode | undefined;
255
+ /** Returns leaf-block IDs in depth-first order. Cached after first call. */
256
+ getBlockOrder(): readonly BlockId[];
257
+ /** Returns the path (array of block IDs) to a node. */
258
+ getNodePath(nodeId: BlockId): BlockId[] | undefined;
259
+ /** Returns the parent BlockNode of a node, or undefined for top-level blocks. */
260
+ getParent(nodeId: BlockId): BlockNode | undefined;
261
+ /** Serializes the state to JSON. */
262
+ toJSON(): object;
263
+ /** Deserializes a state from JSON. */
264
+ static fromJSON(json: {
265
+ doc: Document_2;
266
+ selection: Selection_2;
267
+ }, schema?: Schema): EditorState;
268
+ }
269
+
270
+ export declare class EventBus {
271
+ private readonly listeners;
272
+ /** Emits an event to all registered listeners. Errors are caught per listener. */
273
+ emit<T>(key: EventKey<T>, payload: T): void;
274
+ /** Subscribes to an event. Returns an unsubscribe function. */
275
+ on<T>(key: EventKey<T>, callback: PluginEventCallback<T>): () => void;
276
+ /** Removes a specific listener from an event. */
277
+ off<T>(key: EventKey<T>, callback: PluginEventCallback<T>): void;
278
+ /** Removes all listeners for all events. */
279
+ clear(): void;
280
+ }
281
+
282
+ declare type EventCallback<T> = (payload: T) => void;
283
+
284
+ /** Type-safe event key for compile-time payload checking. */
285
+ export declare class EventKey<T> {
286
+ readonly id: string;
287
+ readonly _type: T;
288
+ constructor(id: string);
289
+ }
290
+
291
+ declare type EventMap = {
292
+ stateChange: StateChangeEvent;
293
+ selectionChange: {
294
+ selection: Selection_2;
295
+ };
296
+ focus: undefined;
297
+ blur: undefined;
298
+ ready: undefined;
299
+ };
300
+
301
+ export declare interface FeatureConfig {
302
+ readonly bold: boolean;
303
+ readonly italic: boolean;
304
+ readonly underline: boolean;
305
+ }
306
+
307
+ /**
308
+ * Finds a block node by ID anywhere in the document tree (recursive DFS).
309
+ */
310
+ export declare function findNode(doc: Document_2, nodeId: string): BlockNode | undefined;
311
+
312
+ /**
313
+ * Finds the path (array of block IDs) to a node by its ID.
314
+ * Performs recursive DFS through the document tree.
315
+ */
316
+ export declare function findNodePath(doc: Document_2, nodeId: string): string[] | undefined;
317
+
318
+ /**
319
+ * Finds a block node and returns it together with its path.
320
+ */
321
+ export declare function findNodeWithPath(doc: Document_2, nodeId: string): {
322
+ node: BlockNode;
323
+ path: string[];
324
+ } | undefined;
325
+
326
+ /**
327
+ * Finds table context for a given block ID.
328
+ * Returns null if the block is not inside a table.
329
+ */
330
+ export declare function findTableContext(state: EditorState, blockId: BlockId): TableContext | null;
331
+
332
+ /** Fira Code — a monospace font with programming ligatures. */
333
+ export declare const FIRA_CODE: FontDefinition;
334
+
335
+ /** Fira Sans — a humanist sans-serif typeface. */
336
+ export declare const FIRA_SANS: FontDefinition;
337
+
338
+ export declare interface FontConfig {
339
+ /**
340
+ * Fonts available in the editor. System fonts require no `fontFaces`.
341
+ * Custom fonts with `fontFaces` get their `@font-face` rules auto-injected.
342
+ *
343
+ * Use `STARTER_FONTS` for a pre-configured set of fonts:
344
+ * ```ts
345
+ * new FontPlugin({ fonts: [...STARTER_FONTS] })
346
+ * ```
347
+ */
348
+ readonly fonts: readonly FontDefinition[];
349
+ /**
350
+ * Name of the font that acts as the editor's default.
351
+ * Selecting this font removes the mark (since the editor already uses it).
352
+ * Defaults to the first font in the list.
353
+ */
354
+ readonly defaultFont?: string;
355
+ /** When true, a separator is rendered after the font toolbar item. */
356
+ readonly separatorAfter?: boolean;
357
+ }
358
+
359
+ /** Defines a font available in the editor. */
360
+ export declare interface FontDefinition {
361
+ /** Display name shown in the toolbar dropdown. */
362
+ readonly name: string;
363
+ /** CSS `font-family` value, e.g. `"'Fira Code', monospace"`. */
364
+ readonly family: string;
365
+ /** Font category for grouping in the UI. */
366
+ readonly category?: 'serif' | 'sans-serif' | 'monospace' | 'display' | 'handwriting';
367
+ /**
368
+ * Optional `@font-face` descriptors. When provided, the plugin
369
+ * auto-injects the corresponding CSS rules into the document.
370
+ */
371
+ readonly fontFaces?: readonly FontFaceDescriptor[];
372
+ }
373
+
374
+ /** Describes a single @font-face source. */
375
+ export declare interface FontFaceDescriptor {
376
+ /** CSS `src` value, e.g. `"url('/fonts/My.woff2') format('woff2')"`. */
377
+ readonly src: string;
378
+ /** Font weight, e.g. `'400'` or `'300 700'` for variable fonts. */
379
+ readonly weight?: string;
380
+ /** Font style, e.g. `'normal'` or `'italic'`. */
381
+ readonly style?: string;
382
+ /** Font display strategy. Defaults to `'swap'`. */
383
+ readonly display?: string;
384
+ }
385
+
386
+ export declare class FontPlugin implements Plugin_2 {
387
+ readonly id = "font";
388
+ readonly name = "Font";
389
+ readonly priority = 22;
390
+ private readonly config;
391
+ private injectedStyleElement;
392
+ private context;
393
+ private comboLabel;
394
+ constructor(config: FontConfig);
395
+ init(context: PluginContext): void;
396
+ destroy(): void;
397
+ onStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void;
398
+ private registerMarkSpec;
399
+ private registerCommands;
400
+ private get defaultFont();
401
+ private registerToolbarItem;
402
+ private updateComboLabel;
403
+ private resolveFontName;
404
+ private isFontActive;
405
+ getActiveFont(state: EditorState): string | null;
406
+ applyFont(context: PluginContext, state: EditorState, family: string): boolean;
407
+ private removeFont;
408
+ /** Finds the first font mark in a block's text range (for proper step inversion). */
409
+ private findFontMarkInRange;
410
+ private injectFontFaces;
411
+ private dismissPopup;
412
+ private renderFontPopup;
413
+ private createFontItem;
414
+ }
415
+
416
+ export declare interface FontSizeConfig {
417
+ /**
418
+ * Preset sizes shown in the font size dropdown.
419
+ * Must contain positive integers. Values are sorted and deduplicated automatically.
420
+ * Defaults to {@link DEFAULT_FONT_SIZES} when omitted or empty.
421
+ */
422
+ readonly sizes?: readonly number[];
423
+ /**
424
+ * The base font size that text has when no fontSize mark is applied.
425
+ * Shown as the initial value in the toolbar combo and used as the
426
+ * "neutral" size — selecting it removes the mark instead of applying one.
427
+ * Defaults to 16.
428
+ */
429
+ readonly defaultSize?: number;
430
+ /** When true, a separator is rendered after the fontSize toolbar item. */
431
+ readonly separatorAfter?: boolean;
432
+ }
433
+
434
+ export declare class FontSizePlugin implements Plugin_2 {
435
+ readonly id = "fontSize";
436
+ readonly name = "Font Size";
437
+ readonly priority = 21;
438
+ private readonly config;
439
+ private readonly sizes;
440
+ private readonly defaultSize;
441
+ private context;
442
+ private comboLabel;
443
+ constructor(config?: Partial<FontSizeConfig>);
444
+ init(context: PluginContext): void;
445
+ destroy(): void;
446
+ onStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void;
447
+ private registerMarkSpec;
448
+ private registerCommands;
449
+ private registerKeymaps;
450
+ private registerToolbarItem;
451
+ private updateComboLabel;
452
+ private isFontSizeActive;
453
+ private getActiveSize;
454
+ private getActiveSizeNumeric;
455
+ private applyFontSize;
456
+ private removeFontSize;
457
+ private stepFontSize;
458
+ private getNextPresetSize;
459
+ private dismissPopup;
460
+ private renderFontSizePopup;
461
+ private selectSize;
462
+ }
463
+
464
+ /**
465
+ * Formats a keymap binding string into a human-readable shortcut,
466
+ * using platform-appropriate modifier symbols (⌘ on Mac, Ctrl on others).
467
+ *
468
+ * @example formatShortcut('Mod-B') → "Ctrl+B" or "⌘B"
469
+ * @example formatShortcut('Mod-Shift-X') → "Ctrl+Shift+X" or "⌘⇧X"
470
+ */
471
+ export declare function formatShortcut(binding: string): string;
472
+
473
+ /** Returns only the BlockNode children of a block. */
474
+ export declare function getBlockChildren(node: BlockNode): readonly BlockNode[];
475
+
476
+ /** Returns the length of a block's inline content (InlineNodes count as 1). */
477
+ export declare function getBlockLength(block: BlockNode): number;
478
+
479
+ /** Returns the marks active at the given offset (empty for InlineNode offsets). */
480
+ export declare function getBlockMarksAtOffset(block: BlockNode, offset: number): readonly Mark[];
481
+
482
+ /** Extracts plain text from a block (InlineNodes are skipped). */
483
+ export declare function getBlockText(block: BlockNode): string;
484
+
485
+ /** Returns the content at a specific offset: text char, inline node, or null. */
486
+ export declare function getContentAtOffset(block: BlockNode, offset: number): {
487
+ readonly kind: 'text';
488
+ readonly char: string;
489
+ readonly marks: readonly Mark[];
490
+ } | {
491
+ readonly kind: 'inline';
492
+ readonly node: InlineNode;
493
+ } | null;
494
+
495
+ /** Returns the inline content children (TextNode | InlineNode) of a block. */
496
+ export declare function getInlineChildren(node: BlockNode): readonly (TextNode | InlineNode)[];
497
+
498
+ /** Returns only the TextNode children of a block. */
499
+ export declare function getTextChildren(node: BlockNode): readonly TextNode[];
500
+
501
+ export declare interface GridPickerConfig {
502
+ readonly maxRows: number;
503
+ readonly maxCols: number;
504
+ onSelect(rows: number, cols: number): void;
505
+ }
506
+
507
+ /** Returns true if the mark set contains a mark of the given type. */
508
+ export declare function hasMark(marks: readonly Mark[], markType: MarkTypeName): boolean;
509
+
510
+ export declare interface HeadingConfig {
511
+ /** Which heading levels to enable. Defaults to [1, 2, 3, 4, 5, 6]. */
512
+ readonly levels: readonly HeadingLevel[];
513
+ /** When true, a separator is rendered after the heading toolbar item. */
514
+ readonly separatorAfter?: boolean;
515
+ }
516
+
517
+ export declare type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
518
+
519
+ export declare class HeadingPlugin implements Plugin_2 {
520
+ readonly id = "heading";
521
+ readonly name = "Heading";
522
+ readonly priority = 30;
523
+ private readonly config;
524
+ private context;
525
+ private comboLabel;
526
+ constructor(config?: Partial<HeadingConfig>);
527
+ init(context: PluginContext): void;
528
+ destroy(): void;
529
+ onStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void;
530
+ private registerNodeSpecs;
531
+ private registerCommands;
532
+ private registerKeymaps;
533
+ private registerInputRules;
534
+ private registerToolbarItem;
535
+ private updateComboLabel;
536
+ private getActiveLabel;
537
+ private dismissPopup;
538
+ private renderHeadingPopup;
539
+ private createPickerItem;
540
+ /**
541
+ * Toggles between a special block type (title/subtitle) and paragraph.
542
+ * If the block is already that type, resets to paragraph.
543
+ */
544
+ private toggleSpecialBlock;
545
+ /**
546
+ * Toggles between heading (at given level) and paragraph.
547
+ * If the block is already a heading at the same level, resets to paragraph.
548
+ */
549
+ private toggleHeading;
550
+ private setBlockType;
551
+ }
552
+
553
+ export declare interface HighlightConfig {
554
+ /**
555
+ * Restricts the color picker to a specific set of hex colors.
556
+ * Each value must be a valid hex color code (`#RGB` or `#RRGGBB`).
557
+ * Duplicates are removed automatically (case-insensitive).
558
+ * When omitted, the full default palette is shown.
559
+ */
560
+ readonly colors?: readonly string[];
561
+ /** When true, a separator is rendered after the highlight toolbar item. */
562
+ readonly separatorAfter?: boolean;
563
+ }
564
+
565
+ export declare class HighlightPlugin implements Plugin_2 {
566
+ readonly id = "highlight";
567
+ readonly name = "Highlight";
568
+ readonly priority = 24;
569
+ private readonly config;
570
+ private readonly colors;
571
+ constructor(config?: Partial<HighlightConfig>);
572
+ init(context: PluginContext): void;
573
+ private registerMarkSpec;
574
+ private registerCommands;
575
+ private registerToolbarItem;
576
+ private isHighlightActive;
577
+ private getActiveColor;
578
+ private applyHighlight;
579
+ private removeHighlight;
580
+ private renderHighlightPopup;
581
+ }
582
+
583
+ export declare class HistoryManager {
584
+ private undoStack;
585
+ private redoStack;
586
+ private readonly groupTimeoutMs;
587
+ private readonly maxDepth;
588
+ private lastOrigin;
589
+ constructor(options?: {
590
+ groupTimeoutMs?: number;
591
+ maxDepth?: number;
592
+ });
593
+ /**
594
+ * Pushes a transaction onto the undo stack.
595
+ * Groups consecutive input transactions within the timeout window.
596
+ */
597
+ push(tr: Transaction): void;
598
+ /** Undoes the last group and returns the new state with transaction, or null if nothing to undo. */
599
+ undo(state: EditorState): HistoryResult | null;
600
+ /** Redoes the last undone group and returns the new state with transaction, or null if nothing to redo. */
601
+ redo(state: EditorState): HistoryResult | null;
602
+ /** Returns true if there are entries to undo. */
603
+ canUndo(): boolean;
604
+ /** Returns true if there are entries to redo. */
605
+ canRedo(): boolean;
606
+ /** Clears all history. */
607
+ clear(): void;
608
+ /**
609
+ * Checks if consecutive transactions are of the same "type" for grouping.
610
+ * Groups text insertion together, deletion together, but not mixed.
611
+ */
612
+ private isSameInputType;
613
+ }
614
+
615
+ export declare interface HistoryResult {
616
+ readonly state: EditorState;
617
+ readonly transaction: Transaction;
618
+ }
619
+
620
+ export declare interface HorizontalRuleConfig {
621
+ /** When true, a separator is rendered after the toolbar item. */
622
+ readonly separatorAfter?: boolean;
623
+ }
624
+
625
+ export declare class HorizontalRulePlugin implements Plugin_2 {
626
+ readonly id = "horizontal-rule";
627
+ readonly name = "Horizontal Rule";
628
+ readonly priority = 40;
629
+ private readonly config;
630
+ constructor(config?: Partial<HorizontalRuleConfig>);
631
+ init(context: PluginContext): void;
632
+ private registerNodeSpec;
633
+ private registerCommands;
634
+ private registerInputRule;
635
+ private registerToolbarItem;
636
+ /**
637
+ * Inserts a horizontal rule after the current block,
638
+ * followed by a new paragraph for continued editing.
639
+ */
640
+ private insertHorizontalRule;
641
+ }
642
+
643
+ export declare interface InlineDecoration {
644
+ readonly type: 'inline';
645
+ readonly blockId: BlockId;
646
+ readonly from: number;
647
+ readonly to: number;
648
+ readonly attrs: DecorationAttrs;
649
+ }
650
+
651
+ /** Creates an inline decoration for a text range within a block. */
652
+ export declare function inlineDecoration(blockId: BlockId, from: number, to: number, attrs: DecorationAttrs): InlineDecoration;
653
+
654
+ /** Atomic inline element (width 1 in offset space). */
655
+ export declare interface InlineNode {
656
+ readonly type: 'inline';
657
+ readonly inlineType: InlineTypeName;
658
+ readonly attrs: Readonly<Record<string, string | number | boolean>>;
659
+ }
660
+
661
+ /** Plugins augment this interface to register typed inline node attributes. */
662
+ export declare interface InlineNodeAttrRegistry {
663
+ }
664
+
665
+ /** Resolves typed attributes for known inline node types, falls back for unknown. */
666
+ export declare type InlineNodeAttrsFor<T extends string> = T extends keyof InlineNodeAttrRegistry ? InlineNodeAttrRegistry[T] : Record<string, string | number | boolean>;
667
+
668
+ export declare interface InlineNodeSpec<T extends string = string> {
669
+ readonly type: T;
670
+ /** Renders the InlineNode as a DOM element (should set contentEditable="false"). */
671
+ toDOM(node: InlineNode): HTMLElement;
672
+ /** Allowed attributes with defaults. */
673
+ readonly attrs?: Readonly<Record<string, AttrSpec>>;
674
+ /** Group membership (default: 'inline'). For content rules. */
675
+ readonly group?: string;
676
+ }
677
+
678
+ export declare function inlineType(name: string): InlineTypeName;
679
+
680
+ /** Semantic name for an inline node type (e.g. 'image', 'mention'). */
681
+ export declare type InlineTypeName = Brand<string, 'InlineTypeName'>;
682
+
683
+ export declare interface InputRule {
684
+ /** Must end with `$` — matched against the text before the cursor. */
685
+ readonly pattern: RegExp;
686
+ /** Returns a transaction to apply, or null to skip this rule. */
687
+ handler(state: EditorState, match: RegExpMatchArray, start: number, end: number): Transaction | null;
688
+ }
689
+
690
+ export declare interface InsertInlineNodeStep {
691
+ readonly type: 'insertInlineNode';
692
+ readonly blockId: BlockId;
693
+ readonly offset: number;
694
+ readonly node: InlineNode;
695
+ readonly path?: readonly BlockId[];
696
+ }
697
+
698
+ export declare interface InsertNodeStep {
699
+ readonly type: 'insertNode';
700
+ readonly parentPath: readonly BlockId[];
701
+ readonly index: number;
702
+ readonly node: BlockNode;
703
+ }
704
+
705
+ /** Inserts text at the current selection, replacing any selected range. */
706
+ export declare function insertTextCommand(state: EditorState, text: string, origin?: 'input' | 'paste'): Transaction;
707
+
708
+ export declare interface InsertTextStep {
709
+ readonly type: 'insertText';
710
+ readonly blockId: BlockId;
711
+ readonly offset: number;
712
+ readonly text: string;
713
+ readonly marks: readonly Mark[];
714
+ readonly segments?: readonly TextSegment[];
715
+ readonly path?: readonly BlockId[];
716
+ }
717
+
718
+ /** Inverts a single step for undo. */
719
+ export declare function invertStep(step: Step): Step;
720
+
721
+ /** Inverts an entire transaction (reverses step order and swaps selections). */
722
+ export declare function invertTransaction(tr: Transaction): Transaction;
723
+
724
+ /** Checks whether a value is a {@link BlockNode}. */
725
+ export declare function isBlockNode(node: unknown): node is BlockNode;
726
+
727
+ /** Returns true if the selection is collapsed (cursor with no range). */
728
+ export declare function isCollapsed(sel: Selection_2): boolean;
729
+
730
+ /**
731
+ * Returns true if the selection direction is forward (anchor before head).
732
+ * When anchor and head are in the same block, compares offsets.
733
+ * Cross-block ordering uses document order (not determinable here — caller provides block order).
734
+ */
735
+ export declare function isForward(sel: Selection_2, blockOrder?: readonly BlockId[]): boolean;
736
+
737
+ /** Checks whether a value is an {@link InlineNode}. */
738
+ export declare function isInlineNode(node: unknown): node is InlineNode;
739
+
740
+ /** Narrows an InlineNode to a typed variant with known attributes. */
741
+ export declare function isInlineNodeOfType<T extends keyof InlineNodeAttrRegistry>(node: InlineNode, inlineNodeType: T): node is InlineNode & {
742
+ readonly inlineType: T;
743
+ readonly attrs: InlineNodeAttrRegistry[T];
744
+ };
745
+
746
+ /** Checks whether a block is inside an isolating node (e.g. table_cell). */
747
+ export declare function isInsideIsolating(state: EditorState, blockId: BlockId): boolean;
748
+
749
+ /** Checks whether a block is inside a table. */
750
+ export declare function isInsideTable(state: EditorState, blockId: BlockId): boolean;
751
+
752
+ /** Returns true if a block has only inline content (TextNodes and InlineNodes). */
753
+ export declare function isLeafBlock(node: BlockNode): boolean;
754
+
755
+ /** Checks if a mark is active at the current selection. */
756
+ export declare function isMarkActive(state: EditorState, markType: MarkType): boolean;
757
+
758
+ /** Checks whether the given mark type is allowed by the schema. */
759
+ export declare function isMarkAllowed(schema: Schema, markType: string): boolean;
760
+
761
+ /** Narrows a Mark to a typed variant with known attributes. */
762
+ export declare function isMarkOfType<T extends keyof MarkAttrRegistry>(mark: Mark, type: T): mark is Mark & {
763
+ readonly type: T;
764
+ readonly attrs: MarkAttrRegistry[T];
765
+ };
766
+
767
+ /** Narrows a BlockNode to a typed variant with known attributes. */
768
+ export declare function isNodeOfType<T extends keyof NodeAttrRegistry>(node: BlockNode, type: T): node is BlockNode & {
769
+ readonly type: T;
770
+ readonly attrs: NodeAttrRegistry[T];
771
+ };
772
+
773
+ /** Checks whether a value is a {@link TextNode}. */
774
+ export declare function isTextNode(node: unknown): node is TextNode;
775
+
776
+ export declare interface ItalicMark extends Mark {
777
+ readonly type: MarkTypeName & 'italic';
778
+ }
779
+
780
+ /**
781
+ * A mapping from key descriptors to handler functions.
782
+ * Key descriptor format: `"Mod-B"`, `"Mod-Shift-1"`, `"Tab"`, `"Enter"`.
783
+ * `Mod` resolves to Ctrl on Linux/Windows and Cmd on macOS.
784
+ */
785
+ export declare type Keymap = Readonly<Record<string, KeymapHandler>>;
786
+
787
+ /**
788
+ * Keymap types for plugin-registered keyboard shortcuts.
789
+ */
790
+ export declare type KeymapHandler = () => boolean;
791
+
792
+ export declare interface LinkConfig {
793
+ /** Whether to add rel="noopener noreferrer" and target="_blank" by default. */
794
+ readonly openInNewTab: boolean;
795
+ /** When true, a separator is rendered after the link toolbar item. */
796
+ readonly separatorAfter?: boolean;
797
+ }
798
+
799
+ export declare class LinkPlugin implements Plugin_2 {
800
+ readonly id = "link";
801
+ readonly name = "Link";
802
+ readonly priority = 25;
803
+ private readonly config;
804
+ constructor(config?: Partial<LinkConfig>);
805
+ init(context: PluginContext): void;
806
+ private registerMarkSpec;
807
+ private registerCommands;
808
+ private registerKeymap;
809
+ private registerToolbarItem;
810
+ private isLinkActive;
811
+ private toggleLink;
812
+ private addLink;
813
+ private removeLink;
814
+ private renderLinkPopup;
815
+ }
816
+
817
+ export declare interface ListConfig {
818
+ /** Which list types to enable. Defaults to all. */
819
+ readonly types: readonly ListType[];
820
+ /** Maximum indent depth. Defaults to 4. */
821
+ readonly maxIndent: number;
822
+ /** When true, a separator is rendered after the last list toolbar item. */
823
+ readonly separatorAfter?: boolean;
824
+ }
825
+
826
+ export declare class ListPlugin implements Plugin_2 {
827
+ readonly id = "list";
828
+ readonly name = "List";
829
+ readonly priority = 35;
830
+ private readonly config;
831
+ constructor(config?: Partial<ListConfig>);
832
+ init(context: PluginContext): void;
833
+ private registerNodeSpec;
834
+ private registerCommands;
835
+ private registerKeymaps;
836
+ private registerInputRules;
837
+ private registerToolbarItems;
838
+ private toggleList;
839
+ private indent;
840
+ private outdent;
841
+ private setIndent;
842
+ private toggleChecked;
843
+ /**
844
+ * Handles Backspace at the start of a list item.
845
+ * Converts the list item back to a paragraph, preserving text.
846
+ */
847
+ private handleBackspace;
848
+ /**
849
+ * Handles Enter inside a list item.
850
+ * Empty item → exit list (convert to paragraph).
851
+ * Non-empty item → split and create a new list item with the same type.
852
+ */
853
+ private handleEnter;
854
+ private isListActive;
855
+ private getEnabledTypes;
856
+ }
857
+
858
+ export declare type ListType = 'bullet' | 'ordered' | 'checklist';
859
+
860
+ export declare interface Mark {
861
+ readonly type: MarkTypeName;
862
+ readonly attrs?: Readonly<Record<string, string | number | boolean>>;
863
+ }
864
+
865
+ /** Plugins augment this interface to register typed mark attributes. */
866
+ export declare interface MarkAttrRegistry {
867
+ bold: Record<string, never>;
868
+ italic: Record<string, never>;
869
+ underline: Record<string, never>;
870
+ }
871
+
872
+ /** Resolves typed attributes for known mark types, falls back for unknown. */
873
+ export declare type MarkAttrsFor<T extends string> = T extends keyof MarkAttrRegistry ? MarkAttrRegistry[T] : Record<string, string | number | boolean>;
874
+
875
+ /** Checks whether two mark arrays contain the same marks (order-independent). */
876
+ export declare function markSetsEqual(a: readonly Mark[], b: readonly Mark[]): boolean;
877
+
878
+ export declare interface MarkSpec<T extends string = string> {
879
+ readonly type: T;
880
+ /** Wraps text content in a DOM element for this mark. */
881
+ toDOM(mark: Omit<Mark, 'attrs'> & {
882
+ readonly attrs: MarkAttrsFor<T>;
883
+ }): HTMLElement;
884
+ /** Nesting priority — lower rank renders closer to the text content. */
885
+ readonly rank?: number;
886
+ readonly attrs?: Readonly<Record<string, AttrSpec>>;
887
+ }
888
+
889
+ /** @deprecated Use {@link MarkTypeName} for new code. */
890
+ export declare type MarkType = MarkTypeName;
891
+
892
+ export declare function markType(name: string): MarkTypeName;
893
+
894
+ /** Semantic name for a mark type (e.g. 'bold', 'link'). */
895
+ export declare type MarkTypeName = Brand<string, 'MarkTypeName'>;
896
+
897
+ /** Merges the current block with the previous block, respecting isolating boundaries. */
898
+ export declare function mergeBlockBackward(state: EditorState): Transaction | null;
899
+
900
+ export declare interface MergeBlocksStep {
901
+ readonly type: 'mergeBlocks';
902
+ readonly targetBlockId: BlockId;
903
+ readonly sourceBlockId: BlockId;
904
+ readonly targetLengthBefore: number;
905
+ readonly path?: readonly BlockId[];
906
+ }
907
+
908
+ export declare type MiddlewareNext = (tr: Transaction) => void;
909
+
910
+ /** Plugins augment this interface to register typed node attributes. */
911
+ export declare interface NodeAttrRegistry {
912
+ paragraph: {
913
+ textAlign?: TextAlignment;
914
+ };
915
+ }
916
+
917
+ /** Resolves typed attributes for known node types, falls back for unknown. */
918
+ export declare type NodeAttrsFor<T extends string> = T extends keyof NodeAttrRegistry ? NodeAttrRegistry[T] : Record<string, string | number | boolean>;
919
+
920
+ export declare interface NodeDecoration {
921
+ readonly type: 'node';
922
+ readonly blockId: BlockId;
923
+ readonly attrs: DecorationAttrs;
924
+ }
925
+
926
+ /** Creates a node decoration that applies to a whole block element. */
927
+ export declare function nodeDecoration(blockId: BlockId, attrs: DecorationAttrs): NodeDecoration;
928
+
929
+ /** A selection that selects an entire node (e.g. for table selection). */
930
+ export declare interface NodeSelection {
931
+ readonly type: 'node';
932
+ readonly nodeId: BlockId;
933
+ readonly path: readonly BlockId[];
934
+ }
935
+
936
+ export declare interface NodeSpec<T extends string = string> {
937
+ readonly type: T;
938
+ /** Renders the block to a DOM element. Must set `data-block-id` on the root. */
939
+ toDOM(node: Omit<BlockNode, 'attrs'> & {
940
+ readonly attrs: NodeAttrsFor<T>;
941
+ }): HTMLElement;
942
+ readonly attrs?: Readonly<Record<string, AttrSpec>>;
943
+ /** If true, the node contains no editable text (e.g. Image, HR). */
944
+ readonly isVoid?: boolean;
945
+ /** Content model: which children this node can contain. */
946
+ readonly content?: ContentRule;
947
+ /** Group membership: 'block' | 'inline' | custom. */
948
+ readonly group?: string;
949
+ /** If true, selection cannot cross this node's boundary (e.g. table_cell). */
950
+ readonly isolating?: boolean;
951
+ }
952
+
953
+ /** @deprecated Use {@link NodeTypeName} for new code. */
954
+ export declare type NodeType = NodeTypeName;
955
+
956
+ export declare function nodeType(name: string): NodeTypeName;
957
+
958
+ /** Semantic name for a node type (e.g. 'paragraph', 'heading'). */
959
+ export declare type NodeTypeName = Brand<string, 'NodeTypeName'>;
960
+
961
+ export declare interface NodeView {
962
+ /** Root DOM element. Must have `data-block-id` set. */
963
+ readonly dom: HTMLElement;
964
+ /** Where text children are rendered. Null for void nodes. */
965
+ readonly contentDOM: HTMLElement | null;
966
+ /** For nodes with multiple content areas (e.g. table cells), returns the DOM for a specific child. */
967
+ getContentDOM?(childId: string): HTMLElement | null;
968
+ /** Returns true if the update was handled, false to re-create the NodeView. */
969
+ update?(node: BlockNode): boolean;
970
+ destroy?(): void;
971
+ selectNode?(): void;
972
+ deselectNode?(): void;
973
+ }
974
+
975
+ export declare type NodeViewFactory = (node: BlockNode, getState: () => EditorState, dispatch: (tr: Transaction) => void) => NodeView;
976
+
977
+ /**
978
+ * Normalizes a KeyboardEvent into a consistent key descriptor string.
979
+ * Format: `"Mod-Shift-Alt-Key"` where Mod = Ctrl/Cmd.
980
+ */
981
+ export declare function normalizeKeyDescriptor(e: KeyboardEvent): string;
982
+
983
+ export declare class NotectlEditor extends HTMLElement {
984
+ private view;
985
+ private pluginManager;
986
+ private contentElement;
987
+ private editorWrapper;
988
+ private topPluginContainer;
989
+ private bottomPluginContainer;
990
+ private announcer;
991
+ private config;
992
+ private eventListeners;
993
+ private readyPromiseResolve;
994
+ private readonly readyPromise;
995
+ private initialized;
996
+ private preInitPlugins;
997
+ constructor();
998
+ static get observedAttributes(): string[];
999
+ connectedCallback(): void;
1000
+ disconnectedCallback(): void;
1001
+ attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
1002
+ /** Registers a plugin before initialization. */
1003
+ registerPlugin(plugin: Plugin_2): void;
1004
+ /** Initializes the editor with the given config. */
1005
+ init(config?: NotectlEditorConfig): Promise<void>;
1006
+ /** Returns the document as JSON. */
1007
+ getJSON(): Document_2;
1008
+ /** Sets the document from JSON. */
1009
+ setJSON(doc: Document_2): void;
1010
+ /** Returns sanitized HTML representation of the document. */
1011
+ getHTML(): string;
1012
+ /** Sets content from HTML (sanitized). */
1013
+ setHTML(html: string): void;
1014
+ /** Returns plain text content. */
1015
+ getText(): string;
1016
+ /** Returns true if the editor is empty (single empty paragraph). */
1017
+ isEmpty(): boolean;
1018
+ readonly commands: {
1019
+ toggleBold: () => boolean;
1020
+ toggleItalic: () => boolean;
1021
+ toggleUnderline: () => boolean;
1022
+ undo: () => void | undefined;
1023
+ redo: () => void | undefined;
1024
+ selectAll: () => void;
1025
+ };
1026
+ /** Checks whether a command can be executed. */
1027
+ can(): {
1028
+ toggleBold: () => boolean;
1029
+ toggleItalic: () => boolean;
1030
+ toggleUnderline: () => boolean;
1031
+ undo: () => boolean;
1032
+ redo: () => boolean;
1033
+ };
1034
+ /** Executes a named command registered by a plugin. */
1035
+ executeCommand(name: string): boolean;
1036
+ /** Configures a plugin at runtime. */
1037
+ configurePlugin(pluginId: string, config: PluginConfig): void;
1038
+ /** Returns the current editor state. */
1039
+ getState(): EditorState;
1040
+ /** Dispatches a transaction (routed through middleware if any). */
1041
+ dispatch(tr: Transaction): void;
1042
+ /** Registers an event listener. */
1043
+ on<K extends keyof EventMap>(event: K, callback: EventCallback<EventMap[K]>): void;
1044
+ /** Removes an event listener. */
1045
+ off<K extends keyof EventMap>(event: K, callback: EventCallback<EventMap[K]>): void;
1046
+ /** Waits for the editor to be ready. */
1047
+ whenReady(): Promise<void>;
1048
+ /** Updates configuration at runtime. */
1049
+ configure(config: Partial<NotectlEditorConfig>): void;
1050
+ /** Cleans up the editor. Awaiting ensures async plugin teardown completes. */
1051
+ destroy(): Promise<void>;
1052
+ /**
1053
+ * Processes the declarative `toolbar` config: registers a ToolbarPlugin
1054
+ * with layout groups, then registers all plugins from the toolbar groups.
1055
+ */
1056
+ private processToolbarConfig;
1057
+ /**
1058
+ * Auto-registers TextFormattingPlugin if no plugin with id 'text-formatting'
1059
+ * was explicitly registered. Uses the `features` config to determine which marks to enable.
1060
+ */
1061
+ private ensureTextFormattingPlugin;
1062
+ private emit;
1063
+ private onStateChange;
1064
+ private updateEmptyState;
1065
+ private announceFormatChange;
1066
+ private replaceState;
1067
+ private blockToHTML;
1068
+ private textNodeToHTML;
1069
+ private getMarkOrder;
1070
+ private escapeHTML;
1071
+ private parseHTMLToDocument;
1072
+ private parseElementToTextNodes;
1073
+ private walkElement;
1074
+ }
1075
+
1076
+ export declare interface NotectlEditorConfig {
1077
+ /** Controls which inline marks are enabled. Used to auto-configure TextFormattingPlugin. */
1078
+ features?: Partial<TextFormattingConfig>;
1079
+ plugins?: Plugin_2[];
1080
+ /**
1081
+ * Declarative toolbar layout. Each inner array is a visual group;
1082
+ * separators are rendered between groups. Order = array order.
1083
+ * When set, a ToolbarPlugin is created internally — do not add one to `plugins`.
1084
+ */
1085
+ toolbar?: ReadonlyArray<ReadonlyArray<Plugin_2>>;
1086
+ placeholder?: string;
1087
+ readonly?: boolean;
1088
+ autofocus?: boolean;
1089
+ maxHistoryDepth?: number;
1090
+ }
1091
+
1092
+ declare interface Plugin_2<TConfig extends Record<string, unknown> = Record<string, unknown>> {
1093
+ readonly id: string;
1094
+ readonly name: string;
1095
+ readonly priority?: number;
1096
+ readonly dependencies?: readonly string[];
1097
+ init(context: PluginContext): void | Promise<void>;
1098
+ destroy?(): void | Promise<void>;
1099
+ onStateChange?(oldState: EditorState, newState: EditorState, tr: Transaction): void;
1100
+ onConfigure?(config: TConfig): void;
1101
+ /** Called after ALL plugins have been initialized. */
1102
+ onReady?(): void | Promise<void>;
1103
+ /**
1104
+ * Returns decorations for the given state.
1105
+ * Called after state.apply() but BEFORE reconciliation.
1106
+ * Plugins should cache and only recompute when needed.
1107
+ */
1108
+ decorations?(state: EditorState, tr?: Transaction): DecorationSet;
1109
+ }
1110
+ export { Plugin_2 as Plugin }
1111
+
1112
+ export declare type PluginConfig = Record<string, unknown>;
1113
+
1114
+ export declare interface PluginContext {
1115
+ getState(): EditorState;
1116
+ dispatch(transaction: Transaction): void;
1117
+ getContainer(): HTMLElement;
1118
+ getPluginContainer(position: 'top' | 'bottom'): HTMLElement;
1119
+ registerCommand(name: string, handler: CommandHandler): void;
1120
+ executeCommand(name: string): boolean;
1121
+ getEventBus(): PluginEventBus;
1122
+ registerMiddleware(middleware: TransactionMiddleware, priority?: number): void;
1123
+ registerService<T>(key: ServiceKey<T>, service: T): void;
1124
+ getService<T>(key: ServiceKey<T>): T | undefined;
1125
+ updateConfig(config: PluginConfig): void;
1126
+ registerNodeSpec<T extends string>(spec: NodeSpec<T>): void;
1127
+ registerMarkSpec<T extends string>(spec: MarkSpec<T>): void;
1128
+ registerNodeView(type: string, factory: NodeViewFactory): void;
1129
+ registerKeymap(keymap: Keymap): void;
1130
+ registerInputRule(rule: InputRule): void;
1131
+ registerToolbarItem(item: ToolbarItem): void;
1132
+ registerInlineNodeSpec<T extends string>(spec: InlineNodeSpec<T>): void;
1133
+ getSchemaRegistry(): SchemaRegistry;
1134
+ }
1135
+
1136
+ export declare interface PluginEventBus {
1137
+ emit<T>(key: EventKey<T>, payload: T): void;
1138
+ on<T>(key: EventKey<T>, callback: PluginEventCallback<T>): () => void;
1139
+ off<T>(key: EventKey<T>, callback: PluginEventCallback<T>): void;
1140
+ }
1141
+
1142
+ export declare type PluginEventCallback<T = unknown> = (payload: T) => void;
1143
+
1144
+ /** Unique identifier for a plugin. */
1145
+ export declare type PluginId = Brand<string, 'PluginId'>;
1146
+
1147
+ export declare function pluginId(id: string): PluginId;
1148
+
1149
+ export declare class PluginManager {
1150
+ private readonly plugins;
1151
+ private readonly commands;
1152
+ private readonly services;
1153
+ private readonly middlewares;
1154
+ private readonly registrations;
1155
+ private readonly eventBus;
1156
+ readonly schemaRegistry: SchemaRegistry;
1157
+ private middlewareSorted;
1158
+ private initOrder;
1159
+ private initialized;
1160
+ private initializing;
1161
+ /** Registers a plugin. Must be called before init(). */
1162
+ register(plugin: Plugin_2): void;
1163
+ /** Initializes all registered plugins in dependency/priority order. */
1164
+ init(options: PluginManagerInitOptions): Promise<void>;
1165
+ /** Notifies all plugins of a state change, in init order. */
1166
+ notifyStateChange(oldState: EditorState, newState: EditorState, tr: Transaction): void;
1167
+ /** Collects and merges decorations from all plugins. */
1168
+ collectDecorations(state: EditorState, tr?: Transaction): DecorationSet;
1169
+ /**
1170
+ * Dispatches a transaction through the middleware chain, then calls the final dispatch.
1171
+ * If no middleware is registered, calls finalDispatch directly.
1172
+ */
1173
+ dispatchWithMiddleware(tr: Transaction, state: EditorState, finalDispatch: (tr: Transaction) => void): void;
1174
+ /** Executes a named command. Returns false if command not found. */
1175
+ executeCommand(name: string): boolean;
1176
+ /** Configures a plugin at runtime via onConfigure(). */
1177
+ configurePlugin(pluginId: string, config: PluginConfig): void;
1178
+ /** Returns all registered plugin IDs. */
1179
+ getPluginIds(): string[];
1180
+ /** Gets a plugin by ID. */
1181
+ get(id: string): Plugin_2 | undefined;
1182
+ /** Gets a registered service by typed key. */
1183
+ getService<T>(key: ServiceKey<T>): T | undefined;
1184
+ /** Destroys all plugins in reverse init order. */
1185
+ destroy(): Promise<void>;
1186
+ private destroyPlugin;
1187
+ private cleanupRegistrations;
1188
+ private getSortedMiddleware;
1189
+ private createContext;
1190
+ /**
1191
+ * Resolves plugin initialization order via topological sort + priority.
1192
+ * Throws on dependency cycles or missing dependencies.
1193
+ */
1194
+ private resolveOrder;
1195
+ }
1196
+
1197
+ export declare interface PluginManagerInitOptions {
1198
+ getState(): EditorState;
1199
+ dispatch(transaction: Transaction): void;
1200
+ getContainer(): HTMLElement;
1201
+ getPluginContainer(position: 'top' | 'bottom'): HTMLElement;
1202
+ /** Called after all plugin init() calls complete, before onReady(). */
1203
+ onBeforeReady?(): void | Promise<void>;
1204
+ }
1205
+
1206
+ export declare type PopupType = 'gridPicker' | 'dropdown' | 'custom';
1207
+
1208
+ export declare interface Position {
1209
+ readonly blockId: BlockId;
1210
+ readonly offset: number;
1211
+ /** Path from root block to leaf block (optional, for nested structures). */
1212
+ readonly path?: readonly BlockId[];
1213
+ }
1214
+
1215
+ /** Registers the built-in paragraph NodeSpec. */
1216
+ export declare function registerBuiltinSpecs(registry: SchemaRegistry): void;
1217
+
1218
+ export declare interface RemoveInlineNodeStep {
1219
+ readonly type: 'removeInlineNode';
1220
+ readonly blockId: BlockId;
1221
+ readonly offset: number;
1222
+ readonly removedNode: InlineNode;
1223
+ readonly path?: readonly BlockId[];
1224
+ }
1225
+
1226
+ export declare interface RemoveMarkStep {
1227
+ readonly type: 'removeMark';
1228
+ readonly blockId: BlockId;
1229
+ readonly from: number;
1230
+ readonly to: number;
1231
+ readonly mark: Mark;
1232
+ readonly path?: readonly BlockId[];
1233
+ }
1234
+
1235
+ export declare interface RemoveNodeStep {
1236
+ readonly type: 'removeNode';
1237
+ readonly parentPath: readonly BlockId[];
1238
+ readonly index: number;
1239
+ readonly removedNode: BlockNode;
1240
+ }
1241
+
1242
+ /**
1243
+ * Resolves a node in the document tree by its path (array of block IDs).
1244
+ * The path traces the lineage from the root block down to the target.
1245
+ */
1246
+ export declare function resolveNodeByPath(doc: Document_2, path: readonly string[]): BlockNode | undefined;
1247
+
1248
+ /**
1249
+ * Resolves the parent of a node at the given path.
1250
+ * Returns the parent container (Document or BlockNode) and the child's index within it.
1251
+ */
1252
+ export declare function resolveParentByPath(doc: Document_2, path: readonly string[]): {
1253
+ parent: Document_2 | BlockNode;
1254
+ index: number;
1255
+ } | undefined;
1256
+
1257
+ export declare interface Schema {
1258
+ readonly nodeTypes: readonly string[];
1259
+ readonly markTypes: readonly string[];
1260
+ /** Looks up the full NodeSpec for a given type. Available when created via schemaFromRegistry. */
1261
+ readonly getNodeSpec?: (type: string) => NodeSpec | undefined;
1262
+ }
1263
+
1264
+ /** Derives a Schema from a SchemaRegistry's registered specs. */
1265
+ export declare function schemaFromRegistry(registry: SchemaRegistry): Schema;
1266
+
1267
+ export declare class SchemaRegistry {
1268
+ private readonly _nodeSpecs;
1269
+ private readonly _markSpecs;
1270
+ private readonly _inlineNodeSpecs;
1271
+ private readonly _nodeViews;
1272
+ private readonly _keymaps;
1273
+ private readonly _inputRules;
1274
+ private readonly _toolbarItems;
1275
+ private readonly _toolbarItemPluginMap;
1276
+ registerNodeSpec<T extends string>(spec: NodeSpec<T>): void;
1277
+ getNodeSpec(type: string): NodeSpec | undefined;
1278
+ removeNodeSpec(type: string): void;
1279
+ getNodeTypes(): string[];
1280
+ registerMarkSpec<T extends string>(spec: MarkSpec<T>): void;
1281
+ getMarkSpec(type: string): MarkSpec | undefined;
1282
+ removeMarkSpec(type: string): void;
1283
+ getMarkTypes(): string[];
1284
+ registerInlineNodeSpec<T extends string>(spec: InlineNodeSpec<T>): void;
1285
+ getInlineNodeSpec(type: string): InlineNodeSpec | undefined;
1286
+ removeInlineNodeSpec(type: string): void;
1287
+ getInlineNodeTypes(): string[];
1288
+ registerNodeView(type: string, factory: NodeViewFactory): void;
1289
+ getNodeViewFactory(type: string): NodeViewFactory | undefined;
1290
+ removeNodeView(type: string): void;
1291
+ registerKeymap(keymap: Keymap): void;
1292
+ getKeymaps(): readonly Keymap[];
1293
+ removeKeymap(keymap: Keymap): void;
1294
+ registerInputRule(rule: InputRule): void;
1295
+ getInputRules(): readonly InputRule[];
1296
+ removeInputRule(rule: InputRule): void;
1297
+ registerToolbarItem(item: ToolbarItem, pluginId?: string): void;
1298
+ getToolbarItemsByPlugin(pluginId: string): ToolbarItem[];
1299
+ getToolbarItem(id: string): ToolbarItem | undefined;
1300
+ getToolbarItems(): ToolbarItem[];
1301
+ removeToolbarItem(id: string): void;
1302
+ clear(): void;
1303
+ }
1304
+
1305
+ /** Selects all content in the editor. */
1306
+ export declare function selectAll(state: EditorState): Transaction;
1307
+
1308
+ declare interface Selection_2 {
1309
+ readonly anchor: Position;
1310
+ readonly head: Position;
1311
+ }
1312
+ export { Selection_2 as Selection }
1313
+
1314
+ export declare interface SelectionRange {
1315
+ readonly from: Position;
1316
+ readonly to: Position;
1317
+ }
1318
+
1319
+ /**
1320
+ * Returns a normalized range where `from` is always before `to`.
1321
+ */
1322
+ export declare function selectionRange(sel: Selection_2, blockOrder?: readonly BlockId[]): SelectionRange;
1323
+
1324
+ /** Type-safe service key for compile-time type checking. */
1325
+ export declare class ServiceKey<T> {
1326
+ readonly id: string;
1327
+ readonly _type: T;
1328
+ constructor(id: string);
1329
+ }
1330
+
1331
+ export declare interface SetBlockTypeStep {
1332
+ readonly type: 'setBlockType';
1333
+ readonly blockId: BlockId;
1334
+ readonly nodeType: NodeTypeName;
1335
+ readonly attrs?: BlockAttrs;
1336
+ readonly previousNodeType: NodeTypeName;
1337
+ readonly previousAttrs?: BlockAttrs;
1338
+ readonly path?: readonly BlockId[];
1339
+ }
1340
+
1341
+ export declare interface SetInlineNodeAttrStep {
1342
+ readonly type: 'setInlineNodeAttr';
1343
+ readonly blockId: BlockId;
1344
+ readonly offset: number;
1345
+ readonly attrs: Readonly<Record<string, string | number | boolean>>;
1346
+ readonly previousAttrs: Readonly<Record<string, string | number | boolean>>;
1347
+ readonly path?: readonly BlockId[];
1348
+ }
1349
+
1350
+ export declare interface SetNodeAttrStep {
1351
+ readonly type: 'setNodeAttr';
1352
+ readonly path: readonly BlockId[];
1353
+ readonly attrs: BlockAttrs | undefined;
1354
+ readonly previousAttrs?: BlockAttrs;
1355
+ }
1356
+
1357
+ declare interface SetStoredMarksStep {
1358
+ readonly type: 'setStoredMarks';
1359
+ readonly marks: readonly Mark[] | null;
1360
+ readonly previousMarks: readonly Mark[] | null;
1361
+ }
1362
+
1363
+ /** Checks whether two blocks share the same parent in the document tree. */
1364
+ export declare function sharesParent(state: EditorState, blockIdA: BlockId, blockIdB: BlockId): boolean;
1365
+
1366
+ /** Splits the current block at the cursor position (Enter key). */
1367
+ export declare function splitBlockCommand(state: EditorState): Transaction | null;
1368
+
1369
+ export declare interface SplitBlockStep {
1370
+ readonly type: 'splitBlock';
1371
+ readonly blockId: BlockId;
1372
+ readonly offset: number;
1373
+ readonly newBlockId: BlockId;
1374
+ readonly path?: readonly BlockId[];
1375
+ }
1376
+
1377
+ /** All starter fonts bundled with notectl. */
1378
+ export declare const STARTER_FONTS: readonly FontDefinition[];
1379
+
1380
+ export declare interface StateChangeEvent {
1381
+ oldState: EditorState;
1382
+ newState: EditorState;
1383
+ transaction: Transaction;
1384
+ }
1385
+
1386
+ export declare type Step = InsertTextStep | DeleteTextStep | SplitBlockStep | MergeBlocksStep | AddMarkStep | RemoveMarkStep | SetStoredMarksStep | SetBlockTypeStep | InsertNodeStep | RemoveNodeStep | SetNodeAttrStep | InsertInlineNodeStep | RemoveInlineNodeStep | SetInlineNodeAttrStep;
1387
+
1388
+ export declare interface StrikethroughConfig {
1389
+ /** When true, a separator is rendered after the strikethrough toolbar item. */
1390
+ readonly separatorAfter?: boolean;
1391
+ }
1392
+
1393
+ export declare class StrikethroughPlugin implements Plugin_2 {
1394
+ readonly id = "strikethrough";
1395
+ readonly name = "Strikethrough";
1396
+ readonly priority = 22;
1397
+ private readonly config;
1398
+ constructor(config?: Partial<StrikethroughConfig>);
1399
+ init(context: PluginContext): void;
1400
+ private registerMarkSpec;
1401
+ private registerCommand;
1402
+ private registerKeymap;
1403
+ private registerToolbarItem;
1404
+ }
1405
+
1406
+ /** Controls which marks are enabled and which toolbar buttons are shown. */
1407
+ export declare interface SuperSubConfig {
1408
+ readonly superscript: boolean;
1409
+ readonly subscript: boolean;
1410
+ readonly toolbar?: SuperSubToolbarConfig;
1411
+ /** When true, a separator is rendered after the last toolbar item. */
1412
+ readonly separatorAfter?: boolean;
1413
+ }
1414
+
1415
+ export declare class SuperSubPlugin implements Plugin_2 {
1416
+ readonly id = "super-sub";
1417
+ readonly name = "Superscript & Subscript";
1418
+ readonly priority = 23;
1419
+ private readonly config;
1420
+ constructor(config?: Partial<SuperSubConfig>);
1421
+ init(context: PluginContext): void;
1422
+ private registerMark;
1423
+ private registerKeymaps;
1424
+ /**
1425
+ * Ensures superscript and subscript are mutually exclusive.
1426
+ * When an addMark step for one type is found, a removeMark step
1427
+ * for the opposite type is injected. For stored marks, the opposite
1428
+ * mark is filtered out.
1429
+ */
1430
+ private registerExclusivityMiddleware;
1431
+ /**
1432
+ * Registers disabled toolbar buttons for marks whose feature is disabled
1433
+ * but whose toolbar button is explicitly requested.
1434
+ */
1435
+ private registerDisabledToolbarItems;
1436
+ private isToolbarVisible;
1437
+ }
1438
+
1439
+ /** Controls toolbar button visibility per mark. */
1440
+ export declare interface SuperSubToolbarConfig {
1441
+ readonly superscript?: boolean;
1442
+ readonly subscript?: boolean;
1443
+ }
1444
+
1445
+ export declare interface TableConfig {
1446
+ /** Maximum rows in grid picker. Defaults to 8. */
1447
+ readonly maxPickerRows?: number;
1448
+ /** Maximum columns in grid picker. Defaults to 8. */
1449
+ readonly maxPickerCols?: number;
1450
+ /** When true, a separator is rendered after the table toolbar item. */
1451
+ readonly separatorAfter?: boolean;
1452
+ }
1453
+
1454
+ /** Context information about a cell within a table. */
1455
+ export declare interface TableContext {
1456
+ readonly tableId: BlockId;
1457
+ readonly tableIndex: number;
1458
+ readonly rowId: BlockId;
1459
+ readonly rowIndex: number;
1460
+ readonly cellId: BlockId;
1461
+ readonly colIndex: number;
1462
+ readonly totalRows: number;
1463
+ readonly totalCols: number;
1464
+ }
1465
+
1466
+ export declare class TablePlugin implements Plugin_2 {
1467
+ readonly id = "table";
1468
+ readonly name = "Table";
1469
+ readonly priority = 40;
1470
+ private readonly config;
1471
+ private selectionService;
1472
+ private cleanupMouseSelection;
1473
+ private context;
1474
+ constructor(config?: Partial<TableConfig>);
1475
+ init(context: PluginContext): void;
1476
+ onReady(): void;
1477
+ destroy(): void;
1478
+ onStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void;
1479
+ private registerNodeSpecs;
1480
+ private registerNodeViews;
1481
+ private registerToolbarItem;
1482
+ }
1483
+
1484
+ /** Service for managing multi-cell selection. */
1485
+ export declare interface TableSelectionService {
1486
+ getSelectedRange(): CellRange | null;
1487
+ setSelectedRange(range: CellRange | null): void;
1488
+ getSelectedCellIds(): readonly BlockId[];
1489
+ isSelected(cellId: BlockId): boolean;
1490
+ }
1491
+
1492
+ export declare const TableSelectionServiceKey: ServiceKey<TableSelectionService>;
1493
+
1494
+ export declare type TextAlignment = 'left' | 'center' | 'right' | 'justify';
1495
+
1496
+ export declare interface TextAlignmentConfig {
1497
+ /** Which alignments to expose. Defaults to all four. */
1498
+ readonly alignments: readonly TextAlignment[];
1499
+ /** Block types that support alignment. Defaults to paragraph + heading. */
1500
+ readonly alignableTypes: readonly string[];
1501
+ /** When true, a separator is rendered after the toolbar item. */
1502
+ readonly separatorAfter?: boolean;
1503
+ }
1504
+
1505
+ export declare class TextAlignmentPlugin implements Plugin_2 {
1506
+ readonly id = "text-alignment";
1507
+ readonly name = "Text Alignment";
1508
+ readonly priority = 90;
1509
+ private readonly config;
1510
+ private alignableTypes;
1511
+ constructor(config?: Partial<TextAlignmentConfig>);
1512
+ init(context: PluginContext): void;
1513
+ /**
1514
+ * Patches existing NodeSpecs for alignable block types to support the
1515
+ * `textAlign` attribute and render it as an inline style.
1516
+ */
1517
+ private patchNodeSpecs;
1518
+ private registerCommands;
1519
+ private registerKeymaps;
1520
+ private registerToolbarItem;
1521
+ /**
1522
+ * Preserves the `textAlign` attribute when other plugins change the block
1523
+ * type (e.g. paragraph → heading) via `setBlockType`, which replaces attrs.
1524
+ */
1525
+ private registerMiddleware;
1526
+ private setAlignment;
1527
+ private isNonDefaultAlignment;
1528
+ private isAlignable;
1529
+ }
1530
+
1531
+ export declare interface TextColorConfig {
1532
+ /**
1533
+ * Restricts the color picker to a specific set of hex colors.
1534
+ * Each value must be a valid hex color code (`#RGB` or `#RRGGBB`).
1535
+ * Duplicates are removed automatically (case-insensitive).
1536
+ * When omitted, the full default palette is shown.
1537
+ */
1538
+ readonly colors?: readonly string[];
1539
+ /** When true, a separator is rendered after the textColor toolbar item. */
1540
+ readonly separatorAfter?: boolean;
1541
+ }
1542
+
1543
+ export declare class TextColorPlugin implements Plugin_2 {
1544
+ readonly id = "textColor";
1545
+ readonly name = "Text Color";
1546
+ readonly priority = 23;
1547
+ private readonly config;
1548
+ private readonly colors;
1549
+ constructor(config?: Partial<TextColorConfig>);
1550
+ init(context: PluginContext): void;
1551
+ private registerMarkSpec;
1552
+ private registerCommands;
1553
+ private registerToolbarItem;
1554
+ private isTextColorActive;
1555
+ private getActiveColor;
1556
+ private applyColor;
1557
+ private removeColor;
1558
+ private renderColorPopup;
1559
+ }
1560
+
1561
+ /** Controls which inline marks are enabled and which toolbar buttons are shown. */
1562
+ export declare interface TextFormattingConfig {
1563
+ readonly bold: boolean;
1564
+ readonly italic: boolean;
1565
+ readonly underline: boolean;
1566
+ readonly toolbar?: TextFormattingToolbarConfig;
1567
+ /** When true, a separator is rendered after the last text-formatting toolbar item. */
1568
+ readonly separatorAfter?: boolean;
1569
+ }
1570
+
1571
+ export declare class TextFormattingPlugin implements Plugin_2 {
1572
+ readonly id = "text-formatting";
1573
+ readonly name = "Text Formatting";
1574
+ readonly priority = 20;
1575
+ private readonly config;
1576
+ constructor(config?: Partial<TextFormattingConfig>);
1577
+ init(context: PluginContext): void;
1578
+ private registerMark;
1579
+ private registerKeymaps;
1580
+ /**
1581
+ * Registers disabled toolbar buttons for marks whose feature is disabled
1582
+ * but whose toolbar button is explicitly requested.
1583
+ */
1584
+ private registerDisabledToolbarItems;
1585
+ /** Checks if a toolbar button should be visible for a given mark. */
1586
+ private isToolbarVisible;
1587
+ }
1588
+
1589
+ /** Controls toolbar button visibility per mark. */
1590
+ export declare interface TextFormattingToolbarConfig {
1591
+ readonly bold?: boolean;
1592
+ readonly italic?: boolean;
1593
+ readonly underline?: boolean;
1594
+ }
1595
+
1596
+ export declare interface TextNode {
1597
+ readonly type: 'text';
1598
+ readonly text: string;
1599
+ readonly marks: readonly Mark[];
1600
+ }
1601
+
1602
+ export declare interface TextSegment {
1603
+ readonly text: string;
1604
+ readonly marks: readonly Mark[];
1605
+ }
1606
+
1607
+ export declare function toggleBold(state: EditorState, features?: FeatureConfig): Transaction | null;
1608
+
1609
+ export declare function toggleItalic(state: EditorState, features?: FeatureConfig): Transaction | null;
1610
+
1611
+ /**
1612
+ * Toggles a mark on the current selection.
1613
+ * If collapsed, toggles stored marks. If range, applies/removes from text.
1614
+ */
1615
+ export declare function toggleMark(state: EditorState, markType: MarkType, features?: FeatureConfig): Transaction | null;
1616
+
1617
+ export declare function toggleUnderline(state: EditorState, features?: FeatureConfig): Transaction | null;
1618
+
1619
+ export declare type ToolbarGroup = 'format' | 'block' | 'insert' | (string & {});
1620
+
1621
+ export declare type ToolbarItem = ToolbarItemNoPopup | ToolbarItemGridPicker | ToolbarItemDropdown | ToolbarItemCustomPopup;
1622
+
1623
+ declare interface ToolbarItemBase {
1624
+ readonly id: string;
1625
+ /** Grouping key: 'format' | 'insert' | 'block' or custom. */
1626
+ readonly group: ToolbarGroup;
1627
+ /** Icon content: inline SVG markup or plain text. Rendered via innerHTML. */
1628
+ readonly icon: string;
1629
+ readonly label: string;
1630
+ /** Tooltip shown on hover, e.g. "Bold (Ctrl+B)". Falls back to label. */
1631
+ readonly tooltip?: string;
1632
+ /** Command name to execute on click. */
1633
+ readonly command: string;
1634
+ /**
1635
+ * Lower priority renders further left.
1636
+ * @deprecated Use the declarative `toolbar` config on `createEditor()` instead.
1637
+ */
1638
+ readonly priority?: number;
1639
+ /**
1640
+ * When true, a visual separator is rendered after this item.
1641
+ * @deprecated Use the declarative `toolbar` config on `createEditor()` instead.
1642
+ */
1643
+ readonly separatorAfter?: boolean;
1644
+ isActive?(state: EditorState): boolean;
1645
+ isEnabled?(state: EditorState): boolean;
1646
+ }
1647
+
1648
+ declare interface ToolbarItemCustomPopup extends ToolbarItemBase {
1649
+ readonly popupType: 'custom';
1650
+ renderPopup(container: HTMLElement, context: PluginContext): void;
1651
+ }
1652
+
1653
+ declare interface ToolbarItemDropdown extends ToolbarItemBase {
1654
+ readonly popupType: 'dropdown';
1655
+ readonly popupConfig: DropdownConfig;
1656
+ }
1657
+
1658
+ declare interface ToolbarItemGridPicker extends ToolbarItemBase {
1659
+ readonly popupType: 'gridPicker';
1660
+ readonly popupConfig: GridPickerConfig;
1661
+ }
1662
+
1663
+ declare interface ToolbarItemNoPopup extends ToolbarItemBase {
1664
+ readonly popupType?: undefined;
1665
+ }
1666
+
1667
+ export declare interface ToolbarLayoutConfig {
1668
+ readonly groups: ReadonlyArray<ReadonlyArray<string>>;
1669
+ }
1670
+
1671
+ export declare class ToolbarPlugin implements Plugin_2 {
1672
+ readonly id = "toolbar";
1673
+ readonly name = "Toolbar";
1674
+ readonly priority = 10;
1675
+ private context;
1676
+ private toolbarElement;
1677
+ private buttons;
1678
+ private activePopup;
1679
+ private closePopupHandler;
1680
+ private readonly hiddenItems;
1681
+ private tooltipElement;
1682
+ private tooltipTimer;
1683
+ private readonly layoutConfig;
1684
+ constructor(layoutConfig?: ToolbarLayoutConfig);
1685
+ init(context: PluginContext): void;
1686
+ onReady(): void;
1687
+ destroy(): void;
1688
+ onStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void;
1689
+ onConfigure(config: PluginConfig): void;
1690
+ private createTooltipElement;
1691
+ private showTooltip;
1692
+ private hideTooltip;
1693
+ private createToolbarElement;
1694
+ private renderItems;
1695
+ private renderItemsByLayout;
1696
+ private renderItemsByPriority;
1697
+ private createButton;
1698
+ private activePopupButton;
1699
+ private togglePopup;
1700
+ private closePopup;
1701
+ private renderGridPicker;
1702
+ private renderDropdown;
1703
+ private updateButtonStates;
1704
+ }
1705
+
1706
+ export declare interface ToolbarServiceAPI {
1707
+ /** Re-reads isActive/isEnabled from state and updates all buttons. */
1708
+ refresh(): void;
1709
+ }
1710
+
1711
+ export declare const ToolbarServiceKey: ServiceKey<ToolbarServiceAPI>;
1712
+
1713
+ export declare interface Transaction {
1714
+ readonly steps: readonly Step[];
1715
+ readonly selectionBefore: Selection_2;
1716
+ readonly selectionAfter: Selection_2;
1717
+ readonly storedMarksAfter: readonly Mark[] | null;
1718
+ readonly metadata: TransactionMetadata;
1719
+ }
1720
+
1721
+ /** Fluent API for building transactions. */
1722
+ export declare class TransactionBuilder {
1723
+ private readonly steps;
1724
+ private selection;
1725
+ private storedMarks;
1726
+ private readonly selectionBefore;
1727
+ private readonly origin;
1728
+ private workingDoc;
1729
+ constructor(currentSelection: Selection_2, currentStoredMarks: readonly Mark[] | null, origin?: TransactionOrigin, doc?: Document_2);
1730
+ /** Adds an insert-text step. Updates workingDoc if available. */
1731
+ insertText(blockId: BlockId, offset: number, text: string, marks: readonly Mark[], segments?: readonly TextSegment[]): this;
1732
+ /** Adds a delete-text step with explicit data. Updates workingDoc if available. */
1733
+ deleteText(blockId: BlockId, from: number, to: number, deletedText: string, deletedMarks: readonly Mark[], deletedSegments?: readonly TextSegment[]): this;
1734
+ /**
1735
+ * Deletes text at the given range, auto-deriving deletedText, deletedMarks, and deletedSegments
1736
+ * from the working document. Requires a document to be provided at construction.
1737
+ */
1738
+ deleteTextAt(blockId: BlockId, from: number, to: number): this;
1739
+ /** Adds a split-block step. Updates workingDoc if available. */
1740
+ splitBlock(blockId: BlockId, offset: number, newBlockId: BlockId): this;
1741
+ /** Adds a merge-blocks step with explicit targetLengthBefore. Updates workingDoc if available. */
1742
+ mergeBlocks(targetBlockId: BlockId, sourceBlockId: BlockId, targetLengthBefore: number): this;
1743
+ /**
1744
+ * Merges two blocks, auto-deriving targetLengthBefore from the working document.
1745
+ * Requires a document to be provided at construction.
1746
+ */
1747
+ mergeBlocksAt(targetBlockId: BlockId, sourceBlockId: BlockId): this;
1748
+ /** Adds an add-mark step. Updates workingDoc if available. */
1749
+ addMark(blockId: BlockId, from: number, to: number, mark: Mark): this;
1750
+ /** Adds a remove-mark step. Updates workingDoc if available. */
1751
+ removeMark(blockId: BlockId, from: number, to: number, mark: Mark): this;
1752
+ /** Adds a set-block-type step, changing a block's node type and optionally its attrs. */
1753
+ setBlockType(blockId: BlockId, nodeType: NodeTypeName, attrs?: BlockAttrs): this;
1754
+ /** Inserts a node as a child of the parent at the given path and index. */
1755
+ insertNode(parentPath: readonly BlockId[], index: number, node: BlockNode): this;
1756
+ /** Removes a node at the given index from the parent at the given path. */
1757
+ removeNode(parentPath: readonly BlockId[], index: number): this;
1758
+ /** Sets attributes on a node at the given path. */
1759
+ setNodeAttr(path: readonly BlockId[], attrs: BlockAttrs): this;
1760
+ /** Inserts an InlineNode at the given offset within a block. */
1761
+ insertInlineNode(blockId: BlockId, offset: number, node: InlineNode): this;
1762
+ /** Removes an InlineNode at the given offset, deriving removedNode from workingDoc. */
1763
+ removeInlineNode(blockId: BlockId, offset: number): this;
1764
+ /** Sets attributes on an InlineNode at the given offset. */
1765
+ setInlineNodeAttr(blockId: BlockId, offset: number, attrs: Readonly<Record<string, string | number | boolean>>): this;
1766
+ /** Sets the selection for the resulting state. */
1767
+ setSelection(selection: Selection_2): this;
1768
+ /** Sets stored marks for the resulting state. */
1769
+ setStoredMarks(marks: readonly Mark[] | null, previousMarks: readonly Mark[] | null): this;
1770
+ /** Builds the final transaction. */
1771
+ build(): Transaction;
1772
+ /** Advances the working document by applying a step. */
1773
+ private advanceDoc;
1774
+ }
1775
+
1776
+ export declare interface TransactionMetadata {
1777
+ readonly origin: TransactionOrigin;
1778
+ readonly timestamp: number;
1779
+ }
1780
+
1781
+ export declare type TransactionMiddleware = (tr: Transaction, state: EditorState, next: MiddlewareNext) => void;
1782
+
1783
+ export declare type TransactionOrigin = 'input' | 'paste' | 'command' | 'history' | 'api';
1784
+
1785
+ export declare interface UnderlineMark extends Mark {
1786
+ readonly type: MarkTypeName & 'underline';
1787
+ }
1788
+
1789
+ /**
1790
+ * Validates whether the given children types are valid for a parent node type.
1791
+ * Checks allow list, min/max constraints.
1792
+ */
1793
+ export declare function validateContent(registry: SchemaRegistry, parentType: string, childTypes: readonly string[]): boolean;
1794
+
1795
+ /**
1796
+ * Walks all block nodes in the document tree in depth-first order.
1797
+ * Visits every BlockNode, including nested ones, with their full path.
1798
+ */
1799
+ export declare function walkNodes(doc: Document_2, callback: (node: BlockNode, path: string[]) => void): void;
1800
+
1801
+ export declare interface WidgetDecoration {
1802
+ readonly type: 'widget';
1803
+ readonly blockId: BlockId;
1804
+ readonly offset: number;
1805
+ readonly toDOM: () => HTMLElement;
1806
+ readonly side: -1 | 1;
1807
+ readonly key?: string;
1808
+ }
1809
+
1810
+ /** Creates a widget decoration that inserts a DOM element at a position. */
1811
+ export declare function widgetDecoration(blockId: BlockId, offset: number, toDOM: () => HTMLElement, options?: {
1812
+ readonly side?: -1 | 1;
1813
+ readonly key?: string;
1814
+ }): WidgetDecoration;
1815
+
1816
+ export { }