@slash-editor/core 0.0.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,1191 @@
1
+ import { Editor, Extension, Extensions, Mark, Node, Range } from "@tiptap/core";
2
+ import { Node as Node$1, NodeType } from "@tiptap/pm/model";
3
+ import { EditorState, PluginKey } from "@tiptap/pm/state";
4
+ import { SuggestionProps } from "@tiptap/suggestion";
5
+ import { TableKit, TableKitOptions } from "@tiptap/extension-table";
6
+ import { Doc } from "yjs";
7
+ //#region src/slash-items.d.ts
8
+ interface SlashContext {
9
+ editor: Editor;
10
+ /** Document range covering the trigger character and the typed query. */
11
+ range: Range;
12
+ }
13
+ interface SlashItem {
14
+ /** Stable identity used for keyboard selection and analytics. */
15
+ id: string;
16
+ title: string;
17
+ /** Section the item is listed under. */
18
+ group: string;
19
+ /** One-line hint rendered next to the title. */
20
+ description?: string;
21
+ /** Alternative names matched with the same weight as the title. */
22
+ aliases?: string[];
23
+ /** Lower-weight search terms that are never displayed. */
24
+ keywords?: string[];
25
+ /** Icon key resolved by the UI layer; the core ships no components. */
26
+ icon?: string;
27
+ /** Hides the item when the current editor cannot run it. */
28
+ when?: (editor: Editor) => boolean;
29
+ run: (context: SlashContext) => void;
30
+ }
31
+ /**
32
+ * Ranks items against a slash query. Ties keep declaration order, so the item
33
+ * list doubles as the default ordering of the menu.
34
+ */
35
+ declare function filterSlashItems(items: SlashItem[], query: string, editor?: Editor): SlashItem[];
36
+ declare const defaultSlashItems: SlashItem[];
37
+ //#endregion
38
+ //#region src/ai-block.d.ts
39
+ /** Lifecycle of a transient `aiBlock` node. */
40
+ type AiActionStatus = "streaming" | "done" | "error";
41
+ interface StreamContext {
42
+ /** Aborted when the request is superseded by a retry or the block is discarded. */
43
+ signal: AbortSignal;
44
+ }
45
+ interface AiRequest {
46
+ /** Slash action id that triggered this request, e.g. `"continue-writing"`. */
47
+ action: string;
48
+ /** Instruction sent to the model. */
49
+ prompt: string;
50
+ /** Plain-text context the instruction operates on. */
51
+ context: string;
52
+ }
53
+ /**
54
+ * Bring-your-own AI backend. `stream` yields incremental text chunks — core
55
+ * has no opinion on the wire format (SSE, `fetch` streaming, WebSocket),
56
+ * only on the async-iterable contract, so a real deployment can proxy any
57
+ * provider behind one endpoint and the demo can swap in a mock for tests.
58
+ */
59
+ interface StreamAdapter {
60
+ stream(request: AiRequest, context: StreamContext): AsyncIterable<string>;
61
+ }
62
+ interface PendingEntry$1 {
63
+ request: AiRequest;
64
+ adapter: StreamAdapter;
65
+ controller: AbortController;
66
+ }
67
+ /**
68
+ * Per-node registry of in-flight/completed AI requests, keyed by the node's
69
+ * `id`. Unlike `PendingUploadRegistry`, entries are kept on success too —
70
+ * "try again" always needs the last request/adapter to replay — and are
71
+ * only dropped (aborting anything still in flight) when the block is
72
+ * discarded or its streamed text is accepted into the document.
73
+ */
74
+ declare class PendingAiRegistry {
75
+ private readonly pending;
76
+ set(id: string, entry: PendingEntry$1): void;
77
+ get(id: string): PendingEntry$1 | undefined;
78
+ delete(id: string): void;
79
+ }
80
+ interface RunAiActionOptions {
81
+ action: string;
82
+ prompt: string;
83
+ context: string;
84
+ adapter: StreamAdapter;
85
+ }
86
+ declare module "@tiptap/core" {
87
+ interface Commands<ReturnType> {
88
+ aiBlock: {
89
+ /** Inserts a transient AI block and starts streaming through `adapter`. */
90
+ runAiAction: (options: RunAiActionOptions) => ReturnType;
91
+ /** Re-runs the last request for the node with this id, from scratch. */
92
+ retryAiAction: (id: string) => ReturnType;
93
+ /** Replaces the transient node with real paragraph(s) built from its streamed text. */
94
+ acceptAiAction: (id: string) => ReturnType;
95
+ /** Removes the transient node without applying anything. */
96
+ discardAiAction: (id: string) => ReturnType;
97
+ };
98
+ }
99
+ }
100
+ interface AiBlockOptions {
101
+ HTMLAttributes: Record<string, unknown>;
102
+ }
103
+ interface AiBlockStorage {
104
+ pending: PendingAiRegistry;
105
+ }
106
+ /**
107
+ * A transient block that streams an AI response into the document: never
108
+ * meant to be the doc's final shape, only a staging area. `status`/`text`/
109
+ * `error` live in node attrs (part of the doc) so streaming re-renders
110
+ * through the normal transaction pipeline, the same reasoning `Image`
111
+ * documents for upload progress — until the user accepts (replaced by real
112
+ * paragraphs) or discards (removed) it.
113
+ */
114
+ declare const AiBlock: Node<AiBlockOptions, AiBlockStorage>;
115
+ /** Configures the AI block node. */
116
+ declare function aiBlock(options?: Partial<AiBlockOptions>): Node<AiBlockOptions, AiBlockStorage>;
117
+ interface AiSlashAction {
118
+ id: string;
119
+ title: string;
120
+ description?: string;
121
+ icon?: string;
122
+ /** Instruction sent to the model. */
123
+ prompt: string;
124
+ }
125
+ declare const defaultAiSlashActions: AiSlashAction[];
126
+ interface AiKitOptions {
127
+ adapter: StreamAdapter;
128
+ /** @default defaultAiSlashActions */
129
+ actions: AiSlashAction[];
130
+ /** Opts out of registering the built-in `aiBlock` node — for a host supplying its own via `extend`. @default true */
131
+ node: boolean;
132
+ }
133
+ /**
134
+ * Builds slash items for each configured action, bound to `options.adapter`.
135
+ * Every action operates on the document text up to the slash trigger — a
136
+ * slash command never carries a real user text selection the way a bubble
137
+ * toolbar action does, so there is nothing else to extract context from.
138
+ */
139
+ declare function createAiSlashItems(options: Pick<AiKitOptions, "adapter" | "actions">): SlashItem[];
140
+ //#endregion
141
+ //#region src/block-drag.d.ts
142
+ type DropMode = "before" | "after" | "inside";
143
+ /** A drag unit's geometry at the moment it was measured. No DOM access, so this is what keeps `resolveDropTarget` pure. */
144
+ interface BlockRect {
145
+ pos: number;
146
+ size: number;
147
+ type: string;
148
+ left: number;
149
+ right: number;
150
+ top: number;
151
+ bottom: number;
152
+ /** Immediate container's type — `"doc"` for a top-level block, the list's type for a list item. */
153
+ parentType: string;
154
+ /**
155
+ * Bounds of the nearest ancestor-or-self that is itself a direct doc
156
+ * child — this block for a top-level block, the enclosing list for a
157
+ * list item. The escape hatch when `source` can't sit beside `closest`.
158
+ */
159
+ containerPos: number;
160
+ containerSize: number;
161
+ }
162
+ interface DropTarget {
163
+ /** Document position to insert at, already in the pre-move coordinate space. */
164
+ pos: number;
165
+ mode: DropMode;
166
+ /** The block the decision was made against, so a caller can draw an indicator without another DOM lookup. */
167
+ rect: BlockRect;
168
+ }
169
+ interface ResolveDropTargetOptions {
170
+ /** Rightward pointer travel, in px, from the source's left edge that turns a drop into a nest. */
171
+ indentThreshold: number;
172
+ /** Whether `target` can legally contain `source` as a child, per the live schema. */
173
+ canNest: (source: BlockRect, target: BlockRect) => boolean;
174
+ /** Whether `source` can legally sit next to `target` — i.e. `target`'s own container accepts `source`. */
175
+ canPlaceBeside: (source: BlockRect, target: BlockRect) => boolean;
176
+ }
177
+ /**
178
+ * Pure geometry: given the current block rects, the pointer position, and
179
+ * the block being dragged, decides where it would land. No DOM or schema
180
+ * access beyond the injected `canNest` predicate, so the gesture rules are
181
+ * testable without a browser.
182
+ */
183
+ declare function resolveDropTarget(blocks: readonly BlockRect[], point: {
184
+ x: number;
185
+ y: number;
186
+ }, source: BlockRect, options: ResolveDropTargetOptions): DropTarget | null;
187
+ /** Whether `source` can be inserted as one more child at the end of `target`'s existing content. */
188
+ declare function canAppendChild(target: Node$1, source: NodeType): boolean;
189
+ interface BlockTarget {
190
+ pos: number;
191
+ size: number;
192
+ type: string;
193
+ id: string | null;
194
+ /** Live rect lookup; re-evaluated on every read so scroll/resize never leaves it stale. */
195
+ getClientRect: () => DOMRect | null;
196
+ }
197
+ interface BlockDragState {
198
+ hovered: BlockTarget | null;
199
+ dragging: BlockTarget | null;
200
+ drop: (DropTarget & {
201
+ getClientRect: () => DOMRect | null;
202
+ }) | null;
203
+ }
204
+ interface BlockDragStorage {
205
+ state: BlockDragState;
206
+ /** @internal Subscribers notified after every state change. */
207
+ listeners: Set<() => void>;
208
+ /** @internal Set once in `onCreate`; lets `setDragging` nudge a decoration recompute. */
209
+ editor: Editor | null;
210
+ /** Subscribes to drag state changes. Returns an unsubscribe function. */
211
+ subscribe(this: BlockDragStorage, listener: () => void): () => void;
212
+ setHovered(this: BlockDragStorage, target: BlockTarget | null): void;
213
+ setDragging(this: BlockDragStorage, target: BlockTarget | null): void;
214
+ setDrop(this: BlockDragStorage, drop: BlockDragState["drop"]): void;
215
+ }
216
+ declare module "@tiptap/core" {
217
+ interface Storage {
218
+ blockDrag: BlockDragStorage;
219
+ }
220
+ interface Commands<ReturnType> {
221
+ blockDrag: {
222
+ /** Moves the node at `from`/`size` to `to`, as one undo step. */
223
+ moveBlock: (options: {
224
+ from: number;
225
+ size: number;
226
+ to: number;
227
+ }) => ReturnType;
228
+ /** Swaps the block under the selection with its previous sibling. */
229
+ moveBlockUp: () => ReturnType;
230
+ /** Swaps the block under the selection with its next sibling. */
231
+ moveBlockDown: () => ReturnType;
232
+ /** Inserts a copy of the node at `pos`/`size` right after it. */
233
+ duplicateBlock: (options: {
234
+ pos: number;
235
+ size: number;
236
+ }) => ReturnType;
237
+ /** Deletes the node at `pos`/`size`. */
238
+ deleteBlock: (options: {
239
+ pos: number;
240
+ size: number;
241
+ }) => ReturnType;
242
+ };
243
+ }
244
+ }
245
+ declare const blockDragPluginKey: PluginKey<null>;
246
+ interface BlockDragOptions {
247
+ /**
248
+ * Pixels to the left of the content box that still resolve to a block,
249
+ * so hovering the gutter (which is rendered outside the editor DOM)
250
+ * highlights the row underneath it.
251
+ *
252
+ * @default 48
253
+ */
254
+ gutterWidth: number;
255
+ /**
256
+ * Pixels of rightward pointer travel that turns a drop into a nest.
257
+ *
258
+ * @default 32
259
+ */
260
+ indentThreshold: number;
261
+ /**
262
+ * Pixels from the nearest scrollable ancestor's edge that scrolls it
263
+ * during a drag.
264
+ *
265
+ * @default 48
266
+ */
267
+ autoScrollMargin: number;
268
+ onError?: (error: unknown, context: {
269
+ editor: Editor;
270
+ }) => void;
271
+ }
272
+ /**
273
+ * Hover targeting, pointer-driven reordering, and list nesting for the
274
+ * block gutter. Geometry is pointer-driven (not HTML5 DnD) so the drop
275
+ * indicator and the nest gesture stay fully in our control; the gutter
276
+ * itself is rendered by the registry layer, anchored to `state.hovered`.
277
+ */
278
+ declare const BlockDrag: Extension<BlockDragOptions, BlockDragStorage>;
279
+ /** Configures the block drag extension. */
280
+ declare function blockDrag(options?: Partial<BlockDragOptions>): Extension<BlockDragOptions, BlockDragStorage>;
281
+ //#endregion
282
+ //#region src/block-id.d.ts
283
+ interface BlockIdOptions {
284
+ /**
285
+ * Node type names that receive an id, or `"auto"` to derive them from
286
+ * every registered extension whose resolved `group` or `content`
287
+ * expression contains `block`. Mirrors how `getSchemaByResolvedExtensions`
288
+ * resolves those fields, so function-valued extensions resolve the same
289
+ * way here as they do in the schema.
290
+ *
291
+ * @default "auto"
292
+ */
293
+ types: string[] | "auto";
294
+ /** Node type names excluded from an `"auto"` derivation. */
295
+ exclude: string[];
296
+ }
297
+ declare const blockIdPluginKey: PluginKey<null>;
298
+ /**
299
+ * Transactions carrying this meta flag are skipped by the assignment pass.
300
+ * A future collaboration provider sets it on transactions that apply a
301
+ * remote change, keeping ids deterministic across peers.
302
+ */
303
+ declare const BLOCK_ID_REMOTE_META = "blockId:remote";
304
+ /**
305
+ * Injects a stable `attrs.id` into every block-capable node and renders it
306
+ * as `data-block-id`, alongside a constant `data-block-type` per node type
307
+ * for the styling seam. Ids are assigned on insert/parse only, never
308
+ * regenerated on attribute update or remote change — the invariant the
309
+ * eventual Yjs identity (M4) depends on.
310
+ */
311
+ declare const BlockId: Extension<BlockIdOptions, any>;
312
+ /** Configures the block id extension. */
313
+ declare function blockId(options?: Partial<BlockIdOptions>): Extension<BlockIdOptions, any>;
314
+ //#endregion
315
+ //#region src/bubble-toolbar.d.ts
316
+ interface BubbleToolbarItem {
317
+ /** Stable identity for React keys. */
318
+ id: string;
319
+ label: string;
320
+ /** Icon key resolved by the UI layer; the core ships no components. */
321
+ icon?: string;
322
+ /** Whether the button should render pressed for the current selection. */
323
+ isActive: (editor: Editor) => boolean;
324
+ run: (editor: Editor) => void;
325
+ /** Hides the item when the current editor cannot run it. */
326
+ when?: (editor: Editor) => boolean;
327
+ }
328
+ interface BubbleToolbarState {
329
+ open: boolean;
330
+ /** Items visible for the current editor; already filtered by `when`. */
331
+ items: BubbleToolbarItem[];
332
+ /** Selection rectangle the toolbar anchors to; `null` while closed. */
333
+ getClientRect: (() => DOMRect | null) | null;
334
+ }
335
+ interface BubbleToolbarStorage {
336
+ state: BubbleToolbarState;
337
+ /** @internal Subscribers notified after every state change. */
338
+ listeners: Set<() => void>;
339
+ /** Subscribes to toolbar state changes. Returns an unsubscribe function. */
340
+ subscribe(this: BubbleToolbarStorage, listener: () => void): () => void;
341
+ /** @internal Replaces state and notifies subscribers, skipping no-op closed transitions. */
342
+ setState(this: BubbleToolbarStorage, next: BubbleToolbarState): void;
343
+ }
344
+ interface BubbleToolbarOptions {
345
+ items: BubbleToolbarItem[] | ((editor: Editor) => BubbleToolbarItem[]);
346
+ }
347
+ declare module "@tiptap/core" {
348
+ interface Storage {
349
+ bubbleToolbar: BubbleToolbarStorage;
350
+ }
351
+ }
352
+ /**
353
+ * Ranks are irrelevant here (there's no query to match against); this just
354
+ * hides items the current schema or selection context can't run.
355
+ */
356
+ declare function filterBubbleToolbarItems(items: BubbleToolbarItem[], editor: Editor): BubbleToolbarItem[];
357
+ declare const defaultBubbleToolbarItems: BubbleToolbarItem[];
358
+ /**
359
+ * Selection-anchored inline formatting toolbar. Unlike the slash menu, there
360
+ * is no query to rank: core only decides *whether* the toolbar is visible
361
+ * and *which* items apply, and the React layer renders it fully controlled
362
+ * (`item.isActive`/`item.run` are called straight from the demo on click).
363
+ */
364
+ declare const BubbleToolbar: Extension<BubbleToolbarOptions, BubbleToolbarStorage>;
365
+ /** Configures the bubble toolbar extension. */
366
+ declare function bubbleToolbar(options?: Partial<BubbleToolbarOptions>): Extension<BubbleToolbarOptions, BubbleToolbarStorage>;
367
+ //#endregion
368
+ //#region src/collaboration.d.ts
369
+ /** Local user attributes broadcast to every connected peer's awareness state. */
370
+ interface CollaborationUser {
371
+ name: string;
372
+ /** Hex color (`#RRGGBB`); an invalid value renders as `transparent`. */
373
+ color: string;
374
+ [key: string]: unknown;
375
+ }
376
+ /**
377
+ * The awareness surface `collaboration()` needs from a network provider.
378
+ * `HocuspocusProvider`, `y-websocket`'s `WebsocketProvider`, and `y-webrtc`'s
379
+ * `WebrtcProvider` all satisfy this shape without a direct dependency on any
380
+ * one of them — the host picks the transport, core only touches awareness.
381
+ */
382
+ interface CollaborationProvider {
383
+ awareness: {
384
+ setLocalStateField(field: string, value: unknown): void;
385
+ getStates(): Map<number, Record<string, unknown>>;
386
+ on(event: "update" | "change", listener: () => void): void;
387
+ off(event: "update" | "change", listener: () => void): void;
388
+ };
389
+ }
390
+ interface CollaborationOptions {
391
+ /** Shared Yjs document. The host owns its lifecycle: creation, persistence, provider wiring. */
392
+ document: Doc;
393
+ /**
394
+ * Name of the Yjs XML fragment within `document` this editor instance
395
+ * syncs. Change it to sync more than one editor off the same document.
396
+ *
397
+ * @default "content"
398
+ */
399
+ field?: string;
400
+ /**
401
+ * Network/awareness provider. Enables presence carets via
402
+ * `CollaborationCaret`; omit to sync the document with no presence UI
403
+ * (e.g. an offline-first `IndexeddbPersistence`-only setup).
404
+ */
405
+ provider?: CollaborationProvider;
406
+ /**
407
+ * Local user's presence attributes. Only meaningful with `provider` set.
408
+ *
409
+ * @default { name: "Anonymous", color: "#94A3B8" }
410
+ */
411
+ user?: CollaborationUser;
412
+ }
413
+ /**
414
+ * Wires a shared Yjs document into the editor via Tiptap's official
415
+ * `Collaboration`/`CollaborationCaret` extensions (themselves a thin layer
416
+ * over `y-prosemirror`). `BlockId`'s remote-skip check already recognizes
417
+ * the `"y-sync$"` transaction meta these extensions set, so ids stay
418
+ * deterministic across peers with no further wiring.
419
+ *
420
+ * Callers must disable local undo/redo (`createBlockKit`'s `history:
421
+ * false`): Yjs owns the undo stack once a document is shared, and running
422
+ * both corrupts it.
423
+ */
424
+ declare function collaboration(options: CollaborationOptions): Extensions;
425
+ //#endregion
426
+ //#region src/columns.d.ts
427
+ interface ColumnsOptions {
428
+ HTMLAttributes: Record<string, unknown>;
429
+ }
430
+ interface ColumnOptions {
431
+ HTMLAttributes: Record<string, unknown>;
432
+ }
433
+ declare module "@tiptap/core" {
434
+ interface Commands<ReturnType> {
435
+ columns: {
436
+ /** Inserts a `columns` container with `count` empty columns, clamped to 2–6. */
437
+ setColumns: (count?: number) => ReturnType;
438
+ };
439
+ }
440
+ }
441
+ /**
442
+ * A single column inside `Columns`. Not a `block`-group node itself — it
443
+ * only exists as `columns`'s child — but its `block+` content still picks
444
+ * up a `BlockId` (auto mode matches on `content`, not just `group`), giving
445
+ * every nesting depth stable identity for comment anchoring (M4).
446
+ */
447
+ declare const Column: Node<ColumnOptions, any>;
448
+ /**
449
+ * Side-by-side layout container: the first M2 nesting surface beyond
450
+ * lists. `content: "column{2,}"` bakes the two-column floor into the
451
+ * schema itself, so there is no separate "remove last column" guard to
452
+ * maintain — deleting a column below the minimum is simply not a legal
453
+ * document.
454
+ */
455
+ declare const Columns: Node<ColumnsOptions, any>;
456
+ /** Configures the columns container node. */
457
+ declare function columns(options?: Partial<ColumnsOptions>): Node<ColumnsOptions, any>;
458
+ /** Configures the column node. */
459
+ declare function column(options?: Partial<ColumnOptions>): Node<ColumnOptions, any>;
460
+ //#endregion
461
+ //#region src/comment.d.ts
462
+ /** A single reply in a comment thread. */
463
+ interface CommentMessage {
464
+ id: string;
465
+ author: string;
466
+ body: string;
467
+ createdAt: number;
468
+ }
469
+ /** A comment thread as the host's store persists it. Bodies never enter the document. */
470
+ interface CommentThread {
471
+ id: string;
472
+ status: "open" | "resolved";
473
+ messages: CommentMessage[];
474
+ }
475
+ /**
476
+ * Bring-your-own comment backend. Core anchors comments in the document
477
+ * (the `comment` mark carries only a `threadId`); thread bodies, authors,
478
+ * and resolution state live entirely outside the document in a host-owned
479
+ * store, the same way `UploadAdapter`/`StreamAdapter` keep binary/model
480
+ * work out of doc attrs. Deleting the anchored text drops the mark but
481
+ * never the thread — an orphaned thread is a store-side concern, not a
482
+ * document one.
483
+ */
484
+ interface CommentThreadStore {
485
+ createThread(input: {
486
+ body: string;
487
+ }): CommentThread | Promise<CommentThread>;
488
+ addMessage(threadId: string, input: {
489
+ body: string;
490
+ }): CommentThread | Promise<CommentThread>;
491
+ resolveThread(threadId: string): void | Promise<void>;
492
+ reopenThread(threadId: string): void | Promise<void>;
493
+ getThread(threadId: string): CommentThread | undefined | Promise<CommentThread | undefined>;
494
+ listThreads(): CommentThread[] | Promise<CommentThread[]>;
495
+ }
496
+ interface CommentOptions {
497
+ HTMLAttributes: Record<string, unknown>;
498
+ }
499
+ interface CommentState {
500
+ /** Distinct thread ids anchored under the current selection, in mark order. */
501
+ activeThreadIds: string[];
502
+ }
503
+ interface CommentStorage {
504
+ state: CommentState;
505
+ /** @internal Subscribers notified after every state change. */
506
+ listeners: Set<() => void>;
507
+ /** Subscribes to selection-driven comment state. Returns an unsubscribe function. */
508
+ subscribe(this: CommentStorage, listener: () => void): () => void;
509
+ /** @internal Replaces state and notifies subscribers, skipping no-op empty transitions. */
510
+ setState(this: CommentStorage, next: CommentState): void;
511
+ }
512
+ declare module "@tiptap/core" {
513
+ interface Commands<ReturnType> {
514
+ comment: {
515
+ /** Anchors `threadId` over the current selection. */
516
+ setComment: (threadId: string) => ReturnType;
517
+ /** Removes only `threadId`'s anchors from the current selection. */
518
+ unsetComment: (threadId: string) => ReturnType;
519
+ /** Anchors `threadId` if absent from the selection, removes it if present. */
520
+ toggleComment: (threadId: string) => ReturnType;
521
+ };
522
+ }
523
+ interface Storage {
524
+ comment: CommentStorage;
525
+ }
526
+ }
527
+ /**
528
+ * Distinct `threadId`s anchored under `state`'s selection: every mark
529
+ * instance touching a non-empty range, or the marks that would apply to
530
+ * text typed at a collapsed cursor. Pure and DOM-free so it is testable
531
+ * against a bare `EditorState`.
532
+ */
533
+ declare function activeThreadIds(state: EditorState): string[];
534
+ /**
535
+ * Comment anchors are a mark, not a node: `threadId` is the only attribute,
536
+ * so multiple distinct threads can anchor overlapping ranges (`excludes:
537
+ * ""` opts out of ProseMirror's default same-type exclusion). Thread
538
+ * bodies, authors, and resolved state never live here — see
539
+ * `CommentThreadStore`.
540
+ */
541
+ declare const Comment: Mark<CommentOptions, CommentStorage>;
542
+ /** Configures the comment mark. */
543
+ declare function comment(options?: Partial<CommentOptions>): Mark<CommentOptions, CommentStorage>;
544
+ //#endregion
545
+ //#region src/embed.d.ts
546
+ interface EmbedOptions {
547
+ HTMLAttributes: Record<string, unknown>;
548
+ }
549
+ type EmbedMode = "bookmark" | "iframe";
550
+ interface SetEmbedOptions {
551
+ /** Omit to insert an empty placeholder a `NodeView` can fill in later. */
552
+ url?: string;
553
+ /** @default "bookmark" */
554
+ mode?: EmbedMode;
555
+ title?: string;
556
+ description?: string;
557
+ thumbnail?: string;
558
+ }
559
+ declare module "@tiptap/core" {
560
+ interface Commands<ReturnType> {
561
+ embed: {
562
+ /** Inserts a bookmark or iframe embed node. */
563
+ setEmbed: (options?: SetEmbedOptions) => ReturnType;
564
+ };
565
+ }
566
+ }
567
+ /**
568
+ * A block-level external embed: a bookmark link card or a sandboxed
569
+ * iframe, chosen by `mode`. No upload adapter — the URL (and, for
570
+ * bookmarks, the optional title/description/thumbnail metadata) is set
571
+ * directly, either at insert time or later by a `NodeView` reading a
572
+ * pasted link.
573
+ */
574
+ declare const Embed: Node<EmbedOptions, any>;
575
+ /** Configures the embed node. */
576
+ declare function embed(options?: Partial<EmbedOptions>): Node<EmbedOptions, any>;
577
+ //#endregion
578
+ //#region src/upload.d.ts
579
+ /** Lifecycle of a media node backed by an {@link UploadAdapter}. */
580
+ type UploadStatus = "uploading" | "ready" | "error";
581
+ interface UploadContext {
582
+ /** Aborted when the node carrying this upload is deleted before it settles. */
583
+ signal: AbortSignal;
584
+ }
585
+ interface UploadResult {
586
+ url: string;
587
+ }
588
+ /**
589
+ * Bring-your-own upload backend. Nodes never talk to a network directly —
590
+ * every image/file/video command takes an adapter instance explicitly, so
591
+ * core stays backend-agnostic and the demo can swap in a mock for tests.
592
+ */
593
+ interface UploadAdapter<TResult extends UploadResult = UploadResult> {
594
+ upload(file: File, context: UploadContext): Promise<TResult>;
595
+ }
596
+ interface BlockLocation {
597
+ pos: number;
598
+ node: Node$1;
599
+ }
600
+ /**
601
+ * Finds a node by its `BlockId`-assigned `id` attribute. Pure: takes a doc,
602
+ * not an editor, so it is testable without a live view.
603
+ */
604
+ declare function findNodeById(doc: Node$1, id: string): BlockLocation | null;
605
+ interface PendingEntry {
606
+ file: File;
607
+ adapter: UploadAdapter;
608
+ controller: AbortController;
609
+ }
610
+ /**
611
+ * Per-node-type registry of in-flight/failed uploads, keyed by the node's
612
+ * `id`. Retrying re-sends the same `File` without asking the user to pick it
613
+ * again; entries are dropped on success, kept on failure and on abort.
614
+ *
615
+ * Files are never stored in node attrs: attrs must stay JSON-serializable
616
+ * for Yjs (M4), so the pending `File` lives here instead.
617
+ */
618
+ declare class PendingUploadRegistry {
619
+ private readonly pending;
620
+ set(id: string, entry: PendingEntry): void;
621
+ get(id: string): PendingEntry | undefined;
622
+ delete(id: string): void;
623
+ }
624
+ interface RunUploadOptions<TResult extends UploadResult> {
625
+ editor: Editor;
626
+ typeName: string;
627
+ id: string;
628
+ file: File;
629
+ adapter: UploadAdapter<TResult>;
630
+ pending: PendingUploadRegistry;
631
+ /** Maps a successful result onto the node-specific attrs to persist (e.g. `{ src: result.url }`). */
632
+ toAttrs: (result: TResult) => Record<string, unknown>;
633
+ }
634
+ /**
635
+ * Starts (or restarts) an upload for a node already present in the
636
+ * document. Resolves by locating the node through `id` — not a captured
637
+ * position — since the doc may change while the network request is in
638
+ * flight. Completion never creates a separate undo step.
639
+ */
640
+ declare function runUpload<TResult extends UploadResult>(options: RunUploadOptions<TResult>): void;
641
+ interface RetryUploadOptions<TResult extends UploadResult> {
642
+ editor: Editor;
643
+ typeName: string;
644
+ id: string;
645
+ pending: PendingUploadRegistry;
646
+ toAttrs: (result: TResult) => Record<string, unknown>;
647
+ /**
648
+ * Starts from this file/adapter instead of the last one recorded in
649
+ * `pending` — the same machinery also covers "attach a file to an empty
650
+ * placeholder node" (nothing has been attempted yet, so there is no
651
+ * pending entry to fall back on).
652
+ */
653
+ override?: {
654
+ file: File;
655
+ adapter: UploadAdapter<TResult>;
656
+ };
657
+ }
658
+ /**
659
+ * (Re)starts an upload for a node already in the document: from the last
660
+ * `File` passed to `runUpload` for this id, or from `override` when the
661
+ * node has never had an upload attempt (e.g. a placeholder that just had a
662
+ * file attached). Returns `false` — a no-op — when neither is available.
663
+ */
664
+ declare function retryUpload<TResult extends UploadResult>(options: RetryUploadOptions<TResult>): boolean;
665
+ //#endregion
666
+ //#region src/file.d.ts
667
+ interface FileOptions {
668
+ HTMLAttributes: Record<string, unknown>;
669
+ }
670
+ interface FileStorage {
671
+ pending: PendingUploadRegistry;
672
+ }
673
+ /** Inserted with a picked file: uploads through `adapter`; name/size/mime read from the `File` immediately. */
674
+ interface SetFileFromFile {
675
+ file: File$1;
676
+ adapter: UploadAdapter;
677
+ }
678
+ /** Inserted directly from a known URL. */
679
+ interface SetFileFromSrc {
680
+ src: string;
681
+ name?: string;
682
+ size?: number | null;
683
+ mime?: string | null;
684
+ }
685
+ type SetFileOptions = SetFileFromFile | SetFileFromSrc;
686
+ declare module "@tiptap/core" {
687
+ interface Commands<ReturnType> {
688
+ file: {
689
+ /** Inserts a file node. Omit the options to insert an empty placeholder. */
690
+ setFile: (options?: SetFileOptions) => ReturnType;
691
+ /**
692
+ * Re-sends the last `File` for the node with this id, or `override`
693
+ * to attach a file to a node that has never had an upload attempt
694
+ * (e.g. an empty placeholder).
695
+ */
696
+ retryFile: (id: string, override?: {
697
+ file: File$1;
698
+ adapter: UploadAdapter;
699
+ }) => ReturnType;
700
+ };
701
+ }
702
+ }
703
+ /**
704
+ * A block-level generic-file attachment. Same upload/retry shape as
705
+ * `Image`: `status`/`error` live in doc attrs, the picked `File` lives in
706
+ * `storage.pending` keyed by `id`. See `image.ts` for the full rationale.
707
+ */
708
+ declare const File$1: Node<FileOptions, FileStorage>;
709
+ /** Configures the file node. */
710
+ declare function file(options?: Partial<FileOptions>): Node<FileOptions, FileStorage>;
711
+ //#endregion
712
+ //#region src/image.d.ts
713
+ interface ImageOptions {
714
+ HTMLAttributes: Record<string, unknown>;
715
+ }
716
+ interface ImageStorage {
717
+ pending: PendingUploadRegistry;
718
+ }
719
+ /** Inserted with a picked file: uploads through `adapter`, no `src` until it resolves. */
720
+ interface SetImageFromFile {
721
+ file: File;
722
+ adapter: UploadAdapter;
723
+ alt?: string;
724
+ }
725
+ /** Inserted directly from a known URL: skips the upload adapter entirely. */
726
+ interface SetImageFromSrc {
727
+ src: string;
728
+ alt?: string;
729
+ width?: number | null;
730
+ }
731
+ type SetImageOptions = SetImageFromFile | SetImageFromSrc;
732
+ declare module "@tiptap/core" {
733
+ interface Commands<ReturnType> {
734
+ image: {
735
+ /** Inserts an image node. Omit the options to insert an empty placeholder. */
736
+ setImage: (options?: SetImageOptions) => ReturnType;
737
+ /**
738
+ * Re-sends the last `File` for the node with this id, or `override`
739
+ * to attach a file to a node that has never had an upload attempt
740
+ * (e.g. an empty placeholder).
741
+ */
742
+ retryImage: (id: string, override?: {
743
+ file: File;
744
+ adapter: UploadAdapter;
745
+ }) => ReturnType;
746
+ };
747
+ }
748
+ }
749
+ /**
750
+ * A block-level image, optionally backed by an in-flight `UploadAdapter`
751
+ * upload. `status`/`error` live in node attrs (part of the doc) so a
752
+ * completed or failed upload re-renders through the normal transaction
753
+ * pipeline — no separate subscribe/storage channel like the slash menu or
754
+ * bubble toolbar, which track ephemeral UI state instead of document state.
755
+ *
756
+ * The picked `File` itself never touches attrs (not JSON-serializable, not
757
+ * Yjs-safe); it lives in `storage.pending`, keyed by the node's `BlockId`,
758
+ * so `retryImage` can resend it without the user picking again.
759
+ */
760
+ declare const Image: Node<ImageOptions, ImageStorage>;
761
+ /** Configures the image node. */
762
+ declare function image(options?: Partial<ImageOptions>): Node<ImageOptions, ImageStorage>;
763
+ //#endregion
764
+ //#region src/link-editor.d.ts
765
+ interface LinkEditorState {
766
+ open: boolean;
767
+ /** Draft href shown in the popover input. */
768
+ href: string;
769
+ /** `true` when editing a link already on the selection; `false` when drafting one over new text. */
770
+ editing: boolean;
771
+ /** Selection rectangle the popover anchors to; `null` while closed. */
772
+ getClientRect: (() => DOMRect | null) | null;
773
+ }
774
+ interface LinkEditorStorage {
775
+ state: LinkEditorState;
776
+ /** @internal Subscribers notified after every state change. */
777
+ listeners: Set<() => void>;
778
+ /** Subscribes to popover state changes. Returns an unsubscribe function. */
779
+ subscribe(this: LinkEditorStorage, listener: () => void): () => void;
780
+ /** @internal Replaces state and notifies subscribers, skipping no-op closed transitions. */
781
+ setState(this: LinkEditorStorage, next: LinkEditorState): void;
782
+ }
783
+ interface LinkEditorOptions {
784
+ /** Opens automatically when the selection lands inside an existing link. @default true */
785
+ autoOpenOnLinkActive: boolean;
786
+ }
787
+ declare module "@tiptap/core" {
788
+ interface Storage {
789
+ linkEditor: LinkEditorStorage;
790
+ }
791
+ interface Commands<ReturnType> {
792
+ linkEditor: {
793
+ /** Opens the popover: prefilled with the active link's href, or empty over a fresh text selection. */
794
+ openLinkEditor: () => ReturnType;
795
+ /** Updates the draft href. Local UI state only — it never touches the document. */
796
+ setLinkEditorHref: (href: string) => ReturnType;
797
+ /** Closes without applying, refocusing the document. */
798
+ closeLinkEditor: () => ReturnType;
799
+ };
800
+ }
801
+ }
802
+ /** Whether a link can be created (non-empty text selection) or edited (cursor inside one) right now. */
803
+ declare function canOpenLinkEditor(editor: Editor): boolean;
804
+ /**
805
+ * Selection-anchored link editing popover. Two entry points feed the same
806
+ * state: a bubble-toolbar "Link" button calls `openLinkEditor` over a fresh
807
+ * text selection (`editing: false`), and this extension auto-opens itself
808
+ * (`editing: true`) whenever the cursor lands inside an existing link — a
809
+ * case a plain "selection is non-empty" check (à la `BubbleToolbar`) can't
810
+ * catch, since placing a cursor inside a link selects no text.
811
+ *
812
+ * Applying or removing the link itself is not a custom command here: once
813
+ * open, a UI layer calls the `link` mark's own `setLink`/`unsetLink` (from
814
+ * `@tiptap/extension-link`) directly, the same way `BubbleToolbarItem.run`
815
+ * calls `toggleBold` directly — this extension only owns popover
816
+ * visibility and the draft href.
817
+ *
818
+ * The popover is never closed by `onTransaction`/`onBlur` alone once open:
819
+ * its own input needs real DOM focus to type a URL, and a blur there must
820
+ * not read as "dismiss". Only an explicit command (`closeLinkEditor`, or a
821
+ * document selection change while `editing`) closes it.
822
+ */
823
+ declare const LinkEditor: Extension<LinkEditorOptions, LinkEditorStorage>;
824
+ /** Configures the link editor extension. */
825
+ declare function linkEditor(options?: Partial<LinkEditorOptions>): Extension<LinkEditorOptions, LinkEditorStorage>;
826
+ //#endregion
827
+ //#region src/mention.d.ts
828
+ interface MentionItem {
829
+ /** Stable identity of the mentioned entity (user id, page id, …). */
830
+ id: string;
831
+ /** Rendered label, e.g. a display name. */
832
+ label: string;
833
+ /** One-line hint rendered next to the label (e.g. an email or handle). */
834
+ description?: string;
835
+ /** Icon key resolved by the UI layer; the core ships no components. */
836
+ icon?: string;
837
+ }
838
+ interface MentionState {
839
+ open: boolean;
840
+ /** Text typed after the trigger character. */
841
+ query: string;
842
+ /** Items returned by the provider for the current query. */
843
+ items: MentionItem[];
844
+ /** Index of the keyboard-highlighted item; `-1` when there are no items. */
845
+ activeIndex: number;
846
+ /** `true` while the provider's promise for the current query is in flight. */
847
+ loading: boolean;
848
+ /** Caret rectangle the menu anchors to; `null` while closed. */
849
+ getClientRect: (() => DOMRect | null) | null;
850
+ }
851
+ interface MentionStorage {
852
+ state: MentionState;
853
+ /** @internal Subscribers notified after every state change. */
854
+ listeners: Set<() => void>;
855
+ /** @internal Live suggestion handle; `null` while the menu is closed. */
856
+ active: SuggestionProps<MentionItem, MentionItem> | null;
857
+ /** Subscribes to menu state changes. Returns an unsubscribe function. */
858
+ subscribe(this: MentionStorage, listener: () => void): () => void;
859
+ /** Moves the keyboard highlight; the index wraps around the item list. */
860
+ setActiveIndex(this: MentionStorage, index: number): void;
861
+ /** Runs an item, defaulting to the highlighted one. */
862
+ select(this: MentionStorage, index?: number): void;
863
+ /** Closes the menu and leaves the typed text in the document. */
864
+ close(this: MentionStorage): void;
865
+ /** @internal Called by the suggestion plugin on start/update/exit. */
866
+ setActive(this: MentionStorage, props: SuggestionProps<MentionItem, MentionItem> | null): void;
867
+ }
868
+ interface MentionOptions {
869
+ /** Trigger character. @default "@" */
870
+ char: string;
871
+ /**
872
+ * Async provider, called for every query with the current query text and
873
+ * an `AbortSignal` for the in-flight request. `@tiptap/suggestion` aborts
874
+ * a call itself as soon as a newer keystroke supersedes it.
875
+ */
876
+ items: (query: string, context: {
877
+ editor: Editor;
878
+ signal: AbortSignal;
879
+ }) => MentionItem[] | Promise<MentionItem[]>;
880
+ /** Debounce, in ms, before `items` runs after the user stops typing. @default 150 */
881
+ debounce: number;
882
+ /** Minimum query length before `items` runs. @default 0 */
883
+ minQueryLength: number;
884
+ HTMLAttributes: Record<string, unknown>;
885
+ /**
886
+ * Called when `items` rejects. The menu shows an empty result set either
887
+ * way, so a mention query never gets stuck loading forever.
888
+ */
889
+ onError?: (error: unknown, context: {
890
+ editor: Editor;
891
+ }) => void;
892
+ }
893
+ declare module "@tiptap/core" {
894
+ interface Storage {
895
+ mention: MentionStorage;
896
+ }
897
+ interface Commands<ReturnType> {
898
+ mention: {
899
+ /** Inserts a mention node for `item` at the current selection. */
900
+ insertMention: (item: MentionItem) => ReturnType;
901
+ };
902
+ }
903
+ }
904
+ declare const mentionPluginKey: PluginKey<any>;
905
+ /**
906
+ * `@`-mention node backed by an async, bring-your-own provider. Mirrors
907
+ * `SlashCommand`'s architecture (a `Suggestion` plugin, per-editor storage
908
+ * with a `subscribe`/state-machine shape) with one addition: `items` may
909
+ * return a `Promise`, so `state.loading` reflects an in-flight request the
910
+ * slash menu never has to model.
911
+ */
912
+ declare const Mention: Node<MentionOptions, MentionStorage>;
913
+ /** Configures the mention node. `items` is required — there is no default provider. */
914
+ declare function mention(options: Partial<MentionOptions> & Pick<MentionOptions, "items">): Node<MentionOptions, MentionStorage>;
915
+ //#endregion
916
+ //#region src/slash-command.d.ts
917
+ interface SlashMenuState {
918
+ open: boolean;
919
+ /** Text typed after the trigger character. */
920
+ query: string;
921
+ /** Ranked items for the current query. */
922
+ items: SlashItem[];
923
+ /** Index of the keyboard-highlighted item; `-1` when there are no items. */
924
+ activeIndex: number;
925
+ /** Caret rectangle the menu anchors to; `null` while closed. */
926
+ getClientRect: (() => DOMRect | null) | null;
927
+ }
928
+ interface SlashCommandStorage {
929
+ state: SlashMenuState;
930
+ /** @internal Subscribers notified after every state change. */
931
+ listeners: Set<() => void>;
932
+ /** @internal Live suggestion handle; `null` while the menu is closed. */
933
+ active: SuggestionProps<SlashItem, SlashItem> | null;
934
+ /** Subscribes to menu state changes. Returns an unsubscribe function. */
935
+ subscribe(this: SlashCommandStorage, listener: () => void): () => void;
936
+ /** Moves the keyboard highlight; the index wraps around the item list. */
937
+ setActiveIndex(this: SlashCommandStorage, index: number): void;
938
+ /** Runs an item, defaulting to the highlighted one. */
939
+ select(this: SlashCommandStorage, index?: number): void;
940
+ /** Closes the menu and leaves the typed text in the document. */
941
+ close(this: SlashCommandStorage): void;
942
+ /** @internal Called by the suggestion plugin on start/update/exit. */
943
+ setActive(this: SlashCommandStorage, props: SuggestionProps<SlashItem, SlashItem> | null): void;
944
+ }
945
+ interface SlashCommandOptions {
946
+ /** Trigger character. */
947
+ char: string;
948
+ /** Item registry, or a resolver called with the live editor. */
949
+ items: SlashItem[] | ((editor: Editor) => SlashItem[]);
950
+ /**
951
+ * Called when an item's `run` throws. The failing transaction is never
952
+ * applied, so the document keeps the state it had before the item ran.
953
+ */
954
+ onError?: (error: unknown, context: {
955
+ item: SlashItem;
956
+ editor: Editor;
957
+ }) => void;
958
+ }
959
+ declare module "@tiptap/core" {
960
+ interface Storage {
961
+ slashCommand: SlashCommandStorage;
962
+ }
963
+ }
964
+ declare const slashCommandPluginKey: PluginKey<any>;
965
+ declare const SlashCommand: Extension<SlashCommandOptions, SlashCommandStorage>;
966
+ /** Configures the slash menu extension. */
967
+ declare function slashCommand(options?: Partial<SlashCommandOptions>): Extension<SlashCommandOptions, SlashCommandStorage>;
968
+ //#endregion
969
+ //#region src/table.d.ts
970
+ /**
971
+ * Configures Tiptap's table kit (table/tableRow/tableHeader/tableCell) with
972
+ * resizable columns on by default — the one behavior worth diverging from
973
+ * upstream's default, since a fixed-width table is the common Notion-parity
974
+ * expectation. `insertTable`/`addColumnBefore`/`deleteRow`/… ship from the
975
+ * upstream extension; slash-editor adds no table-specific commands.
976
+ */
977
+ declare function table(options?: Partial<TableKitOptions>): import("@tiptap/core").Extension<TableKitOptions, any>;
978
+ //#endregion
979
+ //#region src/video.d.ts
980
+ interface VideoOptions {
981
+ HTMLAttributes: Record<string, unknown>;
982
+ }
983
+ interface VideoStorage {
984
+ pending: PendingUploadRegistry;
985
+ }
986
+ /** Inserted with a picked file: uploads through `adapter`, no `src` until it resolves. */
987
+ interface SetVideoFromFile {
988
+ file: File;
989
+ adapter: UploadAdapter;
990
+ poster?: string;
991
+ }
992
+ /** Inserted directly from a known URL. */
993
+ interface SetVideoFromSrc {
994
+ src: string;
995
+ poster?: string;
996
+ }
997
+ type SetVideoOptions = SetVideoFromFile | SetVideoFromSrc;
998
+ declare module "@tiptap/core" {
999
+ interface Commands<ReturnType> {
1000
+ video: {
1001
+ /** Inserts a video node. Omit the options to insert an empty placeholder. */
1002
+ setVideo: (options?: SetVideoOptions) => ReturnType;
1003
+ /**
1004
+ * Re-sends the last `File` for the node with this id, or `override`
1005
+ * to attach a file to a node that has never had an upload attempt
1006
+ * (e.g. an empty placeholder).
1007
+ */
1008
+ retryVideo: (id: string, override?: {
1009
+ file: File;
1010
+ adapter: UploadAdapter;
1011
+ }) => ReturnType;
1012
+ };
1013
+ }
1014
+ }
1015
+ /**
1016
+ * A block-level video, same upload/retry shape as `Image`: `status`/`error`
1017
+ * live in doc attrs, the picked `File` lives in `storage.pending` keyed by
1018
+ * `id`. See `image.ts` for the full rationale.
1019
+ */
1020
+ declare const Video: Node<VideoOptions, VideoStorage>;
1021
+ /** Configures the video node. */
1022
+ declare function video(options?: Partial<VideoOptions>): Node<VideoOptions, VideoStorage>;
1023
+ //#endregion
1024
+ //#region src/block-kit.d.ts
1025
+ type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
1026
+ interface BlockKitOptions {
1027
+ /**
1028
+ * Heading levels offered by the editor.
1029
+ *
1030
+ * @default [1, 2, 3]
1031
+ */
1032
+ headingLevels?: HeadingLevel[];
1033
+ /**
1034
+ * Local undo/redo history.
1035
+ *
1036
+ * Set to `false` when a collaboration provider owns history: Yjs ships its
1037
+ * own undo manager and running both corrupts the undo stack.
1038
+ *
1039
+ * @default true
1040
+ */
1041
+ history?: boolean;
1042
+ /**
1043
+ * Slash menu configuration, or `false` to leave the trigger character inert.
1044
+ *
1045
+ * @default { char: "/", items: defaultSlashItems }
1046
+ */
1047
+ slash?: Partial<SlashCommandOptions> | false;
1048
+ /**
1049
+ * Stable per-block id configuration, or `false` to opt out. Drag
1050
+ * targeting and the future comment/collaboration surfaces depend on it.
1051
+ *
1052
+ * @default { types: "auto" }
1053
+ */
1054
+ blockId?: Partial<BlockIdOptions> | false;
1055
+ /**
1056
+ * Block gutter drag handle: reorder and list nesting. Requires
1057
+ * `blockId`, since drag targets are addressed by id.
1058
+ *
1059
+ * @default {}
1060
+ */
1061
+ drag?: Partial<BlockDragOptions> | false;
1062
+ /**
1063
+ * Selection-anchored inline formatting toolbar, or `false` to opt out.
1064
+ *
1065
+ * @default { items: defaultBubbleToolbarItems }
1066
+ */
1067
+ bubbleToolbar?: Partial<BubbleToolbarOptions> | false;
1068
+ /**
1069
+ * Extensions appended after the baseline set. Later extensions win on
1070
+ * conflicting keymaps, so this is the seam for overriding defaults.
1071
+ */
1072
+ extend?: Extensions;
1073
+ /**
1074
+ * Image node configuration, or `false` to opt out and supply a
1075
+ * `NodeView`-augmented variant via `extend` instead (see `Image`,
1076
+ * exported for `.extend()`).
1077
+ *
1078
+ * @default {}
1079
+ */
1080
+ image?: Partial<ImageOptions> | false;
1081
+ /**
1082
+ * File attachment node configuration, or `false` to opt out.
1083
+ *
1084
+ * @default {}
1085
+ */
1086
+ file?: Partial<FileOptions> | false;
1087
+ /**
1088
+ * Video node configuration, or `false` to opt out.
1089
+ *
1090
+ * @default {}
1091
+ */
1092
+ video?: Partial<VideoOptions> | false;
1093
+ /**
1094
+ * Bookmark/iframe embed node configuration, or `false` to opt out.
1095
+ *
1096
+ * @default {}
1097
+ */
1098
+ embed?: Partial<EmbedOptions> | false;
1099
+ /**
1100
+ * Table kit configuration (resizable columns on by default), or `false`
1101
+ * to opt out.
1102
+ *
1103
+ * @default { table: { resizable: true } }
1104
+ */
1105
+ table?: Partial<TableKitOptions> | false;
1106
+ /**
1107
+ * Columns container configuration, or `false` to opt out.
1108
+ *
1109
+ * @default {}
1110
+ */
1111
+ columns?: Partial<ColumnsOptions> | false;
1112
+ /**
1113
+ * Selection-anchored link editing popover, or `false` to opt out.
1114
+ * Requires the `link` mark, configured on by `createBlockKit` with
1115
+ * `openOnClick: false, enableClickSelection: true` so clicking a link
1116
+ * while editing selects it instead of navigating away.
1117
+ *
1118
+ * @default {}
1119
+ */
1120
+ linkEditor?: Partial<LinkEditorOptions> | false;
1121
+ /**
1122
+ * `@`-mention node with an async, bring-your-own provider. Omit to leave
1123
+ * the trigger character inert — there is no default provider to fall
1124
+ * back to, unlike the always-on `slash` menu.
1125
+ */
1126
+ mention?: (Partial<MentionOptions> & Pick<MentionOptions, "items">) | false;
1127
+ /**
1128
+ * AI slash actions (`Continue writing`, `Summarize`, …) streamed through
1129
+ * a bring-your-own `StreamAdapter`. Omit to leave those slash items out —
1130
+ * there is no default adapter to fall back to.
1131
+ */
1132
+ ai?: (Partial<AiKitOptions> & Pick<AiKitOptions, "adapter">) | false;
1133
+ /**
1134
+ * Shared Yjs document, network provider, and presence config. No
1135
+ * default — omit to run local-only. Forces `history: false` (Yjs owns
1136
+ * the undo stack once a document is shared) regardless of the `history`
1137
+ * option.
1138
+ */
1139
+ collaboration?: CollaborationOptions | false;
1140
+ /**
1141
+ * Comment mark (`threadId` anchor) plus the selection-driven active-thread
1142
+ * state a UI reads to open a thread panel. Thread bodies live in a
1143
+ * host-provided `CommentThreadStore`, never in the document.
1144
+ *
1145
+ * @default {}
1146
+ */
1147
+ comment?: Partial<CommentOptions> | false;
1148
+ }
1149
+ /**
1150
+ * The baseline block schema: document, text, paragraph, headings, lists,
1151
+ * task lists, blockquote, callout, toggle (details), code block, horizontal
1152
+ * rule, hard break, and the inline marks.
1153
+ *
1154
+ * Emits no class names. UI layers style content through element selectors and
1155
+ * the `data-*` attributes rendered by slash-editor nodes.
1156
+ */
1157
+ declare function createBlockKit(options?: BlockKitOptions): Extensions;
1158
+ //#endregion
1159
+ //#region src/callout.d.ts
1160
+ interface CalloutOptions {
1161
+ /**
1162
+ * Emoji shown when a callout is created and no icon attribute is parsed
1163
+ * from HTML.
1164
+ *
1165
+ * @default "💡"
1166
+ */
1167
+ defaultIcon: string;
1168
+ HTMLAttributes: Record<string, unknown>;
1169
+ }
1170
+ declare module "@tiptap/core" {
1171
+ interface Commands<ReturnType> {
1172
+ callout: {
1173
+ /** Wraps the current block range in a callout. */
1174
+ setCallout: () => ReturnType;
1175
+ /** Wraps in a callout, or lifts out of one if already inside. */
1176
+ toggleCallout: () => ReturnType;
1177
+ /** Lifts the current block out of its enclosing callout. */
1178
+ unsetCallout: () => ReturnType;
1179
+ };
1180
+ }
1181
+ }
1182
+ /**
1183
+ * A highlighted aside with a leading emoji, wrapping arbitrary block content
1184
+ * (`content: block+`) rather than a flat textblock. Nesting follows the
1185
+ * container-node approach used across M1: no universal block wrapper.
1186
+ */
1187
+ declare const Callout: Node<CalloutOptions, any>;
1188
+ /** Configures the callout node. */
1189
+ declare function callout(options?: Partial<CalloutOptions>): Node<CalloutOptions, any>;
1190
+ //#endregion
1191
+ export { type AiActionStatus, AiBlock, type AiBlockOptions, type AiBlockStorage, type AiKitOptions, type AiRequest, type AiSlashAction, BLOCK_ID_REMOTE_META, BlockDrag, type BlockDragOptions, type BlockDragState, type BlockDragStorage, BlockId, type BlockIdOptions, type BlockKitOptions, type BlockLocation, type BlockRect, type BlockTarget, BubbleToolbar, type BubbleToolbarItem, type BubbleToolbarOptions, type BubbleToolbarState, type BubbleToolbarStorage, Callout, type CalloutOptions, type CollaborationOptions, type CollaborationProvider, type CollaborationUser, Column, type ColumnOptions, Columns, type ColumnsOptions, Comment, type CommentMessage, type CommentOptions, type CommentState, type CommentStorage, type CommentThread, type CommentThreadStore, type DropMode, type DropTarget, Embed, type EmbedMode, type EmbedOptions, File$1 as File, type FileOptions, type FileStorage, type HeadingLevel, Image, type ImageOptions, type ImageStorage, LinkEditor, type LinkEditorOptions, type LinkEditorState, type LinkEditorStorage, Mention, type MentionItem, type MentionOptions, type MentionState, type MentionStorage, PendingAiRegistry, PendingUploadRegistry, type RetryUploadOptions, type RunAiActionOptions, type RunUploadOptions, type SetEmbedOptions, type SetFileFromFile, type SetFileFromSrc, type SetFileOptions, type SetImageFromFile, type SetImageFromSrc, type SetImageOptions, type SetVideoFromFile, type SetVideoFromSrc, type SetVideoOptions, SlashCommand, type SlashCommandOptions, type SlashCommandStorage, type SlashContext, type SlashItem, type SlashMenuState, type StreamAdapter, type StreamContext, TableKit, type TableKitOptions, type UploadAdapter, type UploadContext, type UploadResult, type UploadStatus, Video, type VideoOptions, type VideoStorage, activeThreadIds, aiBlock, blockDrag, blockDragPluginKey, blockId, blockIdPluginKey, bubbleToolbar, callout, canAppendChild, canOpenLinkEditor, collaboration, column, columns, comment, createAiSlashItems, createBlockKit, defaultAiSlashActions, defaultBubbleToolbarItems, defaultSlashItems, embed, file, filterBubbleToolbarItems, filterSlashItems, findNodeById, image, linkEditor, mention, mentionPluginKey, resolveDropTarget, retryUpload, runUpload, slashCommand, slashCommandPluginKey, table, video };