@tiptap/extension-drag-handle-vue-2 3.29.2 → 3.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -2,9 +2,9 @@ import * as vue_types_vue from 'vue/types/vue';
2
2
  import * as prosemirror_model from 'prosemirror-model';
3
3
  import * as prosemirror_state from 'prosemirror-state';
4
4
  import * as vue from 'vue';
5
- import { MarkType as MarkType$1, MarkSpec, Mark as Mark$1, DOMOutputSpec, NodeType as NodeType$1, NodeSpec, Node as Node$2, Slice, ParseOptions, Schema, ResolvedPos, Fragment } from '@tiptap/pm/model';
6
- import { EditorState, Plugin, Transaction, PluginKey } from '@tiptap/pm/state';
7
- import { NodeViewConstructor, NodeView, MarkViewConstructor, MarkView, EditorProps, EditorView } from '@tiptap/pm/view';
5
+ import { Mark as Mark$1, MarkType as MarkType$1, MarkSpec, DOMOutputSpec, NodeType as NodeType$1, NodeSpec, Node as Node$2, Slice, ParseOptions, Schema, ResolvedPos, Fragment } from '@tiptap/pm/model';
6
+ import { EditorState, Transaction, Plugin, PluginKey } from '@tiptap/pm/state';
7
+ import { Decoration as Decoration$1, DecorationAttrs, EditorView, DecorationSet, NodeViewConstructor, NodeView, MarkViewConstructor, MarkView, EditorProps } from '@tiptap/pm/view';
8
8
  import { MapResult, Transform } from '@tiptap/pm/transform';
9
9
  import { NestedOptions, DragHandlePluginProps } from '@tiptap/extension-drag-handle';
10
10
 
@@ -20,6 +20,256 @@ declare class EventEmitter<T extends Record<string, any>> {
20
20
  removeAllListeners(): void;
21
21
  }
22
22
 
23
+ interface WidgetDecorationOptions {
24
+ side?: number;
25
+ relaxedSide?: boolean;
26
+ marks?: readonly Mark$1[];
27
+ stopEvent?: (event: Event) => boolean;
28
+ ignoreSelection?: boolean;
29
+ /**
30
+ * runs when ProseMirror drops the widget, also on editor destroy and unmount.
31
+ * skipped on teardown for widgets made with the React or Vue widget renderer.
32
+ * receives the DOM node, not a ProseMirror node.
33
+ */
34
+ destroy?: (node: globalThis.Node) => void;
35
+ }
36
+ type DecorationKind = 'inline' | 'node' | 'widget';
37
+ /**
38
+ * Base class for decorations built in `addDecorations()`. Shadows `Decoration`
39
+ * from `@tiptap/pm/view`, like core's `Node` and `Mark` do, so alias one of them
40
+ * in files that need both.
41
+ *
42
+ * @example
43
+ * import { Decoration } from '@tiptap/core'
44
+ * import { Decoration as PMDecoration } from '@tiptap/pm/view'
45
+ *
46
+ * const highlight = Decoration.Inline(1, 5, { class: 'highlight' })
47
+ */
48
+ declare abstract class Decoration {
49
+ abstract kind: DecorationKind;
50
+ abstract get anchor(): number;
51
+ /**
52
+ * Builds the ProseMirror decoration. When `extensionName` is provided,
53
+ * it is embedded into the decoration spec for incremental merge tracking.
54
+ * @param extensionName The name of the extension that produced this decoration.
55
+ * @returns The ProseMirror decoration.
56
+ */
57
+ abstract toPMDecoration(extensionName?: string): Decoration$1;
58
+ static Inline(from: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>): InlineDecoration;
59
+ static Node(pos: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>): NodeDecoration;
60
+ /**
61
+ * Creates a widget decoration: a DOM node drawn at a document position.
62
+ *
63
+ * The `key` is the widget's identity. While it stays the same, ProseMirror
64
+ * keeps the widget mounted and only its position tracks the document.
65
+ * `render`, `side`, `destroy` and other options are fixed on first mount.
66
+ * Change the key to remount with new options.
67
+ *
68
+ * @param pos The document position where the widget is drawn.
69
+ * @param render Called once on first mount. Returns the DOM node.
70
+ * @param options Must include a unique `key`. See `WidgetDecorationOptions`.
71
+ * @returns The widget decoration.
72
+ */
73
+ static Widget(pos: number, render: (view: EditorView, getPos: () => number | undefined) => HTMLElement, options: {
74
+ key: string;
75
+ } & WidgetDecorationOptions & Record<string, any>): WidgetDecoration;
76
+ }
77
+ /**
78
+ * Represents an inline decoration (text-level highlighting, etc.).
79
+ */
80
+ declare class InlineDecoration extends Decoration {
81
+ kind: "inline";
82
+ from: number;
83
+ to: number;
84
+ attrs: DecorationAttrs;
85
+ spec?: Record<string, any>;
86
+ constructor(from: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>);
87
+ get anchor(): number;
88
+ toPMDecoration(extensionName?: string): Decoration$1;
89
+ }
90
+ /**
91
+ * Represents a node-level decoration (block-level highlights, etc.).
92
+ */
93
+ declare class NodeDecoration extends Decoration {
94
+ kind: "node";
95
+ from: number;
96
+ to: number;
97
+ attrs: DecorationAttrs;
98
+ spec?: Record<string, any>;
99
+ constructor(pos: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>);
100
+ get anchor(): number;
101
+ toPMDecoration(extensionName?: string): Decoration$1;
102
+ }
103
+ /**
104
+ * Represents a widget decoration (inline widgets, etc.).
105
+ */
106
+ declare class WidgetDecoration extends Decoration {
107
+ kind: "widget";
108
+ pos: number;
109
+ key: string;
110
+ render: (view: EditorView, getPos: () => number | undefined) => HTMLElement;
111
+ spec?: WidgetDecorationOptions & Record<string, any>;
112
+ constructor(pos: number, render: (view: EditorView, getPos: () => number | undefined) => HTMLElement, key: string, spec?: WidgetDecorationOptions & Record<string, any>);
113
+ get anchor(): number;
114
+ toPMDecoration(extensionName?: string): Decoration$1;
115
+ }
116
+
117
+ interface DecorationCreateProps {
118
+ /**
119
+ * The editor instance. Read `state` from the `state` argument, not
120
+ * `editor.state` — during `create()` the editor's view state has not been
121
+ * updated yet, so `editor.state` points at the pre-transaction document.
122
+ */
123
+ editor: Editor;
124
+ /**
125
+ * The editor state being built. This is the correct state to read from
126
+ * inside `create()`; `editor.state` is stale until the transaction finishes
127
+ * applying.
128
+ */
129
+ state: EditorState;
130
+ /** The editor view, or `null` while the editor is not mounted. */
131
+ view: EditorView | null;
132
+ }
133
+ interface DecorationShouldUpdateProps {
134
+ editor: Editor;
135
+ tr: Transaction;
136
+ oldState: EditorState;
137
+ newState: EditorState;
138
+ }
139
+ interface DecorationRangeProps extends DecorationCreateProps {
140
+ /** Start of the block range to scan, inclusive. */
141
+ from: number;
142
+ /**
143
+ * End of the block range to scan, exclusive. `to` is the next block's start
144
+ * and that block rebuilds it, so decorations anchored there are ignored.
145
+ * The last block is the exception: it owns the end of the document.
146
+ */
147
+ to: number;
148
+ }
149
+ interface BaseDecorationSpec {
150
+ create: (props: DecorationCreateProps) => Decoration[];
151
+ shouldUpdate?: (props: DecorationShouldUpdateProps) => boolean;
152
+ }
153
+ interface DocumentDecorationSpec extends BaseDecorationSpec {
154
+ update?: 'document';
155
+ createInRange?: never;
156
+ }
157
+ interface ChangedRangesDecorationSpec extends BaseDecorationSpec {
158
+ update: 'changedRanges';
159
+ createInRange: (props: DecorationRangeProps) => Decoration[];
160
+ }
161
+ interface ManualDecorationSpec extends BaseDecorationSpec {
162
+ update: 'manual';
163
+ shouldUpdate?: never;
164
+ createInRange?: never;
165
+ }
166
+ type DecorationSpec = DocumentDecorationSpec | ChangedRangesDecorationSpec | ManualDecorationSpec;
167
+ interface DecorationManagerState {
168
+ decorationSetsByExtension: Record<string, DecorationSet>;
169
+ widgetKeysByExtension: Record<string, Set<string>>;
170
+ mergedDecorationSet: DecorationSet;
171
+ widgetKeys: Set<string>;
172
+ }
173
+ interface ResolvedDecorationEntry {
174
+ name: string;
175
+ spec: DecorationSpec;
176
+ }
177
+ interface DecorationManagerEntry {
178
+ name: string;
179
+ addDecorations: () => DecorationSpec | null;
180
+ }
181
+
182
+ declare class DecorationManager {
183
+ editor: Editor;
184
+ entries: ResolvedDecorationEntry[];
185
+ plugin: Plugin<DecorationManagerState> | null;
186
+ private warnedWidgetKeys;
187
+ private warnedOutOfRangeExtensions;
188
+ private readonly handleBeforeTransaction;
189
+ constructor(options: {
190
+ editor: Editor;
191
+ entries: DecorationManagerEntry[];
192
+ });
193
+ destroy(): void;
194
+ /**
195
+ * Returns the set of live widget keys from all decoration extensions.
196
+ * @returns A readonly set of widget keys
197
+ */
198
+ liveWidgetKeys(): ReadonlySet<string>;
199
+ /**
200
+ * The mounted editor view, or `null` when destroyed. Decoration callbacks
201
+ * must never receive the placeholder view `editor.view` falls back to.
202
+ * @returns The mounted editor view, or `null`
203
+ */
204
+ private get mountedView();
205
+ /**
206
+ * Resolves decoration entries by calling the addDecorations function for each extension entry.
207
+ * @param entries The decoration manager entries to resolve
208
+ * @returns An array of resolved decoration entries
209
+ */
210
+ private resolveEntries;
211
+ /**
212
+ * Creates the ProseMirror plugin for managing decorations.
213
+ * @returns A ProseMirror plugin with state management
214
+ */
215
+ private createPlugin;
216
+ /**
217
+ * Applies changed ranges recomputation to a decoration set, dropping stale decorations and rebuilding only the touched blocks.
218
+ * @param name The name of the decoration extension
219
+ * @param spec The decoration spec
220
+ * @param previous The previous decoration manager state
221
+ * @param tr The transaction to apply
222
+ * @param newState The new editor state
223
+ * @returns The updated decoration set and widget keys
224
+ */
225
+ private applyChangedRangesRecompute;
226
+ /**
227
+ * Rebuilds decorations for the changed block ranges: maps the previous set
228
+ * forward, then for each range removes stale decorations, calls
229
+ * `createInRange`, and adds the new ones while syncing widget keys.
230
+ * @param name The extension name.
231
+ * @param spec The decoration spec.
232
+ * @param previous The previous decoration manager state.
233
+ * @param tr The transaction to apply.
234
+ * @param newState The new editor state.
235
+ * @param ranges The block ranges to rebuild.
236
+ * @returns The updated decoration set and widget keys.
237
+ */
238
+ private rebuildRanges;
239
+ /**
240
+ * Builds a full decoration set for the entire document.
241
+ * @param name The name of the decoration extension
242
+ * @param spec The decoration spec
243
+ * @param state The editor state
244
+ * @returns The decoration set and widget keys
245
+ */
246
+ private buildFullSet;
247
+ /**
248
+ * Runs a decoration callback and swallows anything it throws. These run inside
249
+ * `state.apply`, where an uncaught error would abort the whole transaction.
250
+ * @param name The extension name.
251
+ * @param method The callback name, used in the error message.
252
+ * @param create The callback to run.
253
+ * @returns The decorations, or an empty array if the callback threw.
254
+ */
255
+ private runCreate;
256
+ private warnDuplicateWidgetKeys;
257
+ /**
258
+ * Builds the merged DecorationSet during init. Skips the merge for a
259
+ * single extension since its per-extension set is already correct.
260
+ * @param doc The document to build the merged set for.
261
+ * @param decorationSetsByExtension The per-extension decoration sets.
262
+ * @returns The merged decoration set.
263
+ */
264
+ private buildMergedSet;
265
+ /**
266
+ * Computes the merged DecorationSet after apply. Single extension skips the
267
+ * merge; nothing recomputed maps the previous merged set forward; otherwise
268
+ * the merge is rebuilt from the per-extension sets.
269
+ */
270
+ private mergeAfterApply;
271
+ }
272
+
23
273
  type InputRuleMatch = {
24
274
  index: number;
25
275
  text: string;
@@ -694,6 +944,36 @@ interface ExtendableConfig<Options = any, Storage = any, Config extends Extensio
694
944
  type: PMType;
695
945
  parent: ParentConfig<Config>['addProseMirrorPlugins'];
696
946
  }) => Plugin[];
947
+ /**
948
+ * Adds editor decorations (node, inline, widget). Return a spec with a `create`
949
+ * function that builds instances via `Decoration.Node`/`Inline`/`Widget`. Use
950
+ * `shouldUpdate`, `update: 'changedRanges'` + `createInRange`, or `update: 'manual'` to control recomputation.
951
+ * @see https://tiptap.dev/docs/editor/core-concepts/decorations
952
+ * @example
953
+ * addDecorations() {
954
+ * return {
955
+ * create: ({ state }) =>
956
+ * findChildren(state.doc, node => node.type.name === 'heading').map(
957
+ * ({ pos, node }) =>
958
+ * Decoration.Node(pos, pos + node.nodeSize, { class: 'is-heading' }),
959
+ * ),
960
+ * }
961
+ * }
962
+ *
963
+ * For framework widgets, use `ReactWidgetRenderer` or `VueWidgetRenderer`
964
+ * from the matching framework package. Give stateful widgets a stable key.
965
+ *
966
+ * `create` and `createInRange` must not throw. An exception escapes through
967
+ * `editor.commands.*` and stops the document from updating until it stops.
968
+ */
969
+ addDecorations?: (this: {
970
+ name: string;
971
+ options: Options;
972
+ storage: Storage;
973
+ editor: Editor;
974
+ type: PMType;
975
+ parent: ParentConfig<Config>['addDecorations'];
976
+ }) => DecorationSpec | null;
697
977
  /**
698
978
  * This function transforms pasted HTML content before it's parsed.
699
979
  * Extensions can use this to modify or clean up pasted HTML.
@@ -1829,6 +2109,7 @@ declare class ExtensionManager {
1829
2109
  baseExtensions: Extensions;
1830
2110
  splittableMarks: string[];
1831
2111
  nonClearableMarks: string[];
2112
+ decorationManager: DecorationManager | null;
1832
2113
  constructor(extensions: Extensions, editor: Editor);
1833
2114
  static resolve: typeof resolveExtensions;
1834
2115
  static sort: typeof sortExtensions;
@@ -1843,6 +2124,14 @@ declare class ExtensionManager {
1843
2124
  * @returns An array of Prosemirror plugins
1844
2125
  */
1845
2126
  get plugins(): Plugin[];
2127
+ /**
2128
+ * Aggregates decorations from extensions into a single plugin, or returns null
2129
+ * if none exist. Destroys the previous manager to avoid orphaned listeners.
2130
+ * @returns A ProseMirror plugin or `null`
2131
+ * @example
2132
+ * const plugin = editor.extensionManager.createDecorationPlugin()
2133
+ */
2134
+ createDecorationPlugin(): Plugin | null;
1846
2135
  /**
1847
2136
  * Get all attributes from the extensions.
1848
2137
  * @returns An array of attributes
@@ -2858,6 +3147,22 @@ declare module '@tiptap/core' {
2858
3147
  }
2859
3148
  }
2860
3149
 
3150
+ declare module '@tiptap/core' {
3151
+ interface Commands<ReturnType> {
3152
+ updateDecorations: {
3153
+ /**
3154
+ * Force declarative decorations to recompute, bypassing each extension's
3155
+ * `shouldUpdate` gate. Pass an extension name to recompute only that
3156
+ * extension's decorations, or omit it to recompute all of them.
3157
+ * @param extensionName The name of the extension to recompute (optional).
3158
+ * @example editor.commands.updateDecorations()
3159
+ * @example editor.commands.updateDecorations('myExtension')
3160
+ */
3161
+ updateDecorations: (extensionName?: string) => ReturnType;
3162
+ };
3163
+ }
3164
+ }
3165
+
2861
3166
  declare module '@tiptap/core' {
2862
3167
  interface Commands<ReturnType> {
2863
3168
  wrapIn: {
@@ -2905,6 +3210,7 @@ declare class Editor extends EventEmitter<EditorEvents> {
2905
3210
  * A unique ID for this editor instance.
2906
3211
  */
2907
3212
  instanceId: string;
3213
+ private hasWarnedStaleDecorationRead;
2908
3214
  options: EditorOptions;
2909
3215
  constructor(options?: Partial<EditorOptions>);
2910
3216
  /**
package/dist/index.d.ts CHANGED
@@ -2,9 +2,9 @@ import * as vue_types_vue from 'vue/types/vue';
2
2
  import * as prosemirror_model from 'prosemirror-model';
3
3
  import * as prosemirror_state from 'prosemirror-state';
4
4
  import * as vue from 'vue';
5
- import { MarkType as MarkType$1, MarkSpec, Mark as Mark$1, DOMOutputSpec, NodeType as NodeType$1, NodeSpec, Node as Node$2, Slice, ParseOptions, Schema, ResolvedPos, Fragment } from '@tiptap/pm/model';
6
- import { EditorState, Plugin, Transaction, PluginKey } from '@tiptap/pm/state';
7
- import { NodeViewConstructor, NodeView, MarkViewConstructor, MarkView, EditorProps, EditorView } from '@tiptap/pm/view';
5
+ import { Mark as Mark$1, MarkType as MarkType$1, MarkSpec, DOMOutputSpec, NodeType as NodeType$1, NodeSpec, Node as Node$2, Slice, ParseOptions, Schema, ResolvedPos, Fragment } from '@tiptap/pm/model';
6
+ import { EditorState, Transaction, Plugin, PluginKey } from '@tiptap/pm/state';
7
+ import { Decoration as Decoration$1, DecorationAttrs, EditorView, DecorationSet, NodeViewConstructor, NodeView, MarkViewConstructor, MarkView, EditorProps } from '@tiptap/pm/view';
8
8
  import { MapResult, Transform } from '@tiptap/pm/transform';
9
9
  import { NestedOptions, DragHandlePluginProps } from '@tiptap/extension-drag-handle';
10
10
 
@@ -20,6 +20,256 @@ declare class EventEmitter<T extends Record<string, any>> {
20
20
  removeAllListeners(): void;
21
21
  }
22
22
 
23
+ interface WidgetDecorationOptions {
24
+ side?: number;
25
+ relaxedSide?: boolean;
26
+ marks?: readonly Mark$1[];
27
+ stopEvent?: (event: Event) => boolean;
28
+ ignoreSelection?: boolean;
29
+ /**
30
+ * runs when ProseMirror drops the widget, also on editor destroy and unmount.
31
+ * skipped on teardown for widgets made with the React or Vue widget renderer.
32
+ * receives the DOM node, not a ProseMirror node.
33
+ */
34
+ destroy?: (node: globalThis.Node) => void;
35
+ }
36
+ type DecorationKind = 'inline' | 'node' | 'widget';
37
+ /**
38
+ * Base class for decorations built in `addDecorations()`. Shadows `Decoration`
39
+ * from `@tiptap/pm/view`, like core's `Node` and `Mark` do, so alias one of them
40
+ * in files that need both.
41
+ *
42
+ * @example
43
+ * import { Decoration } from '@tiptap/core'
44
+ * import { Decoration as PMDecoration } from '@tiptap/pm/view'
45
+ *
46
+ * const highlight = Decoration.Inline(1, 5, { class: 'highlight' })
47
+ */
48
+ declare abstract class Decoration {
49
+ abstract kind: DecorationKind;
50
+ abstract get anchor(): number;
51
+ /**
52
+ * Builds the ProseMirror decoration. When `extensionName` is provided,
53
+ * it is embedded into the decoration spec for incremental merge tracking.
54
+ * @param extensionName The name of the extension that produced this decoration.
55
+ * @returns The ProseMirror decoration.
56
+ */
57
+ abstract toPMDecoration(extensionName?: string): Decoration$1;
58
+ static Inline(from: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>): InlineDecoration;
59
+ static Node(pos: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>): NodeDecoration;
60
+ /**
61
+ * Creates a widget decoration: a DOM node drawn at a document position.
62
+ *
63
+ * The `key` is the widget's identity. While it stays the same, ProseMirror
64
+ * keeps the widget mounted and only its position tracks the document.
65
+ * `render`, `side`, `destroy` and other options are fixed on first mount.
66
+ * Change the key to remount with new options.
67
+ *
68
+ * @param pos The document position where the widget is drawn.
69
+ * @param render Called once on first mount. Returns the DOM node.
70
+ * @param options Must include a unique `key`. See `WidgetDecorationOptions`.
71
+ * @returns The widget decoration.
72
+ */
73
+ static Widget(pos: number, render: (view: EditorView, getPos: () => number | undefined) => HTMLElement, options: {
74
+ key: string;
75
+ } & WidgetDecorationOptions & Record<string, any>): WidgetDecoration;
76
+ }
77
+ /**
78
+ * Represents an inline decoration (text-level highlighting, etc.).
79
+ */
80
+ declare class InlineDecoration extends Decoration {
81
+ kind: "inline";
82
+ from: number;
83
+ to: number;
84
+ attrs: DecorationAttrs;
85
+ spec?: Record<string, any>;
86
+ constructor(from: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>);
87
+ get anchor(): number;
88
+ toPMDecoration(extensionName?: string): Decoration$1;
89
+ }
90
+ /**
91
+ * Represents a node-level decoration (block-level highlights, etc.).
92
+ */
93
+ declare class NodeDecoration extends Decoration {
94
+ kind: "node";
95
+ from: number;
96
+ to: number;
97
+ attrs: DecorationAttrs;
98
+ spec?: Record<string, any>;
99
+ constructor(pos: number, to: number, attrs?: DecorationAttrs, spec?: Record<string, any>);
100
+ get anchor(): number;
101
+ toPMDecoration(extensionName?: string): Decoration$1;
102
+ }
103
+ /**
104
+ * Represents a widget decoration (inline widgets, etc.).
105
+ */
106
+ declare class WidgetDecoration extends Decoration {
107
+ kind: "widget";
108
+ pos: number;
109
+ key: string;
110
+ render: (view: EditorView, getPos: () => number | undefined) => HTMLElement;
111
+ spec?: WidgetDecorationOptions & Record<string, any>;
112
+ constructor(pos: number, render: (view: EditorView, getPos: () => number | undefined) => HTMLElement, key: string, spec?: WidgetDecorationOptions & Record<string, any>);
113
+ get anchor(): number;
114
+ toPMDecoration(extensionName?: string): Decoration$1;
115
+ }
116
+
117
+ interface DecorationCreateProps {
118
+ /**
119
+ * The editor instance. Read `state` from the `state` argument, not
120
+ * `editor.state` — during `create()` the editor's view state has not been
121
+ * updated yet, so `editor.state` points at the pre-transaction document.
122
+ */
123
+ editor: Editor;
124
+ /**
125
+ * The editor state being built. This is the correct state to read from
126
+ * inside `create()`; `editor.state` is stale until the transaction finishes
127
+ * applying.
128
+ */
129
+ state: EditorState;
130
+ /** The editor view, or `null` while the editor is not mounted. */
131
+ view: EditorView | null;
132
+ }
133
+ interface DecorationShouldUpdateProps {
134
+ editor: Editor;
135
+ tr: Transaction;
136
+ oldState: EditorState;
137
+ newState: EditorState;
138
+ }
139
+ interface DecorationRangeProps extends DecorationCreateProps {
140
+ /** Start of the block range to scan, inclusive. */
141
+ from: number;
142
+ /**
143
+ * End of the block range to scan, exclusive. `to` is the next block's start
144
+ * and that block rebuilds it, so decorations anchored there are ignored.
145
+ * The last block is the exception: it owns the end of the document.
146
+ */
147
+ to: number;
148
+ }
149
+ interface BaseDecorationSpec {
150
+ create: (props: DecorationCreateProps) => Decoration[];
151
+ shouldUpdate?: (props: DecorationShouldUpdateProps) => boolean;
152
+ }
153
+ interface DocumentDecorationSpec extends BaseDecorationSpec {
154
+ update?: 'document';
155
+ createInRange?: never;
156
+ }
157
+ interface ChangedRangesDecorationSpec extends BaseDecorationSpec {
158
+ update: 'changedRanges';
159
+ createInRange: (props: DecorationRangeProps) => Decoration[];
160
+ }
161
+ interface ManualDecorationSpec extends BaseDecorationSpec {
162
+ update: 'manual';
163
+ shouldUpdate?: never;
164
+ createInRange?: never;
165
+ }
166
+ type DecorationSpec = DocumentDecorationSpec | ChangedRangesDecorationSpec | ManualDecorationSpec;
167
+ interface DecorationManagerState {
168
+ decorationSetsByExtension: Record<string, DecorationSet>;
169
+ widgetKeysByExtension: Record<string, Set<string>>;
170
+ mergedDecorationSet: DecorationSet;
171
+ widgetKeys: Set<string>;
172
+ }
173
+ interface ResolvedDecorationEntry {
174
+ name: string;
175
+ spec: DecorationSpec;
176
+ }
177
+ interface DecorationManagerEntry {
178
+ name: string;
179
+ addDecorations: () => DecorationSpec | null;
180
+ }
181
+
182
+ declare class DecorationManager {
183
+ editor: Editor;
184
+ entries: ResolvedDecorationEntry[];
185
+ plugin: Plugin<DecorationManagerState> | null;
186
+ private warnedWidgetKeys;
187
+ private warnedOutOfRangeExtensions;
188
+ private readonly handleBeforeTransaction;
189
+ constructor(options: {
190
+ editor: Editor;
191
+ entries: DecorationManagerEntry[];
192
+ });
193
+ destroy(): void;
194
+ /**
195
+ * Returns the set of live widget keys from all decoration extensions.
196
+ * @returns A readonly set of widget keys
197
+ */
198
+ liveWidgetKeys(): ReadonlySet<string>;
199
+ /**
200
+ * The mounted editor view, or `null` when destroyed. Decoration callbacks
201
+ * must never receive the placeholder view `editor.view` falls back to.
202
+ * @returns The mounted editor view, or `null`
203
+ */
204
+ private get mountedView();
205
+ /**
206
+ * Resolves decoration entries by calling the addDecorations function for each extension entry.
207
+ * @param entries The decoration manager entries to resolve
208
+ * @returns An array of resolved decoration entries
209
+ */
210
+ private resolveEntries;
211
+ /**
212
+ * Creates the ProseMirror plugin for managing decorations.
213
+ * @returns A ProseMirror plugin with state management
214
+ */
215
+ private createPlugin;
216
+ /**
217
+ * Applies changed ranges recomputation to a decoration set, dropping stale decorations and rebuilding only the touched blocks.
218
+ * @param name The name of the decoration extension
219
+ * @param spec The decoration spec
220
+ * @param previous The previous decoration manager state
221
+ * @param tr The transaction to apply
222
+ * @param newState The new editor state
223
+ * @returns The updated decoration set and widget keys
224
+ */
225
+ private applyChangedRangesRecompute;
226
+ /**
227
+ * Rebuilds decorations for the changed block ranges: maps the previous set
228
+ * forward, then for each range removes stale decorations, calls
229
+ * `createInRange`, and adds the new ones while syncing widget keys.
230
+ * @param name The extension name.
231
+ * @param spec The decoration spec.
232
+ * @param previous The previous decoration manager state.
233
+ * @param tr The transaction to apply.
234
+ * @param newState The new editor state.
235
+ * @param ranges The block ranges to rebuild.
236
+ * @returns The updated decoration set and widget keys.
237
+ */
238
+ private rebuildRanges;
239
+ /**
240
+ * Builds a full decoration set for the entire document.
241
+ * @param name The name of the decoration extension
242
+ * @param spec The decoration spec
243
+ * @param state The editor state
244
+ * @returns The decoration set and widget keys
245
+ */
246
+ private buildFullSet;
247
+ /**
248
+ * Runs a decoration callback and swallows anything it throws. These run inside
249
+ * `state.apply`, where an uncaught error would abort the whole transaction.
250
+ * @param name The extension name.
251
+ * @param method The callback name, used in the error message.
252
+ * @param create The callback to run.
253
+ * @returns The decorations, or an empty array if the callback threw.
254
+ */
255
+ private runCreate;
256
+ private warnDuplicateWidgetKeys;
257
+ /**
258
+ * Builds the merged DecorationSet during init. Skips the merge for a
259
+ * single extension since its per-extension set is already correct.
260
+ * @param doc The document to build the merged set for.
261
+ * @param decorationSetsByExtension The per-extension decoration sets.
262
+ * @returns The merged decoration set.
263
+ */
264
+ private buildMergedSet;
265
+ /**
266
+ * Computes the merged DecorationSet after apply. Single extension skips the
267
+ * merge; nothing recomputed maps the previous merged set forward; otherwise
268
+ * the merge is rebuilt from the per-extension sets.
269
+ */
270
+ private mergeAfterApply;
271
+ }
272
+
23
273
  type InputRuleMatch = {
24
274
  index: number;
25
275
  text: string;
@@ -694,6 +944,36 @@ interface ExtendableConfig<Options = any, Storage = any, Config extends Extensio
694
944
  type: PMType;
695
945
  parent: ParentConfig<Config>['addProseMirrorPlugins'];
696
946
  }) => Plugin[];
947
+ /**
948
+ * Adds editor decorations (node, inline, widget). Return a spec with a `create`
949
+ * function that builds instances via `Decoration.Node`/`Inline`/`Widget`. Use
950
+ * `shouldUpdate`, `update: 'changedRanges'` + `createInRange`, or `update: 'manual'` to control recomputation.
951
+ * @see https://tiptap.dev/docs/editor/core-concepts/decorations
952
+ * @example
953
+ * addDecorations() {
954
+ * return {
955
+ * create: ({ state }) =>
956
+ * findChildren(state.doc, node => node.type.name === 'heading').map(
957
+ * ({ pos, node }) =>
958
+ * Decoration.Node(pos, pos + node.nodeSize, { class: 'is-heading' }),
959
+ * ),
960
+ * }
961
+ * }
962
+ *
963
+ * For framework widgets, use `ReactWidgetRenderer` or `VueWidgetRenderer`
964
+ * from the matching framework package. Give stateful widgets a stable key.
965
+ *
966
+ * `create` and `createInRange` must not throw. An exception escapes through
967
+ * `editor.commands.*` and stops the document from updating until it stops.
968
+ */
969
+ addDecorations?: (this: {
970
+ name: string;
971
+ options: Options;
972
+ storage: Storage;
973
+ editor: Editor;
974
+ type: PMType;
975
+ parent: ParentConfig<Config>['addDecorations'];
976
+ }) => DecorationSpec | null;
697
977
  /**
698
978
  * This function transforms pasted HTML content before it's parsed.
699
979
  * Extensions can use this to modify or clean up pasted HTML.
@@ -1829,6 +2109,7 @@ declare class ExtensionManager {
1829
2109
  baseExtensions: Extensions;
1830
2110
  splittableMarks: string[];
1831
2111
  nonClearableMarks: string[];
2112
+ decorationManager: DecorationManager | null;
1832
2113
  constructor(extensions: Extensions, editor: Editor);
1833
2114
  static resolve: typeof resolveExtensions;
1834
2115
  static sort: typeof sortExtensions;
@@ -1843,6 +2124,14 @@ declare class ExtensionManager {
1843
2124
  * @returns An array of Prosemirror plugins
1844
2125
  */
1845
2126
  get plugins(): Plugin[];
2127
+ /**
2128
+ * Aggregates decorations from extensions into a single plugin, or returns null
2129
+ * if none exist. Destroys the previous manager to avoid orphaned listeners.
2130
+ * @returns A ProseMirror plugin or `null`
2131
+ * @example
2132
+ * const plugin = editor.extensionManager.createDecorationPlugin()
2133
+ */
2134
+ createDecorationPlugin(): Plugin | null;
1846
2135
  /**
1847
2136
  * Get all attributes from the extensions.
1848
2137
  * @returns An array of attributes
@@ -2858,6 +3147,22 @@ declare module '@tiptap/core' {
2858
3147
  }
2859
3148
  }
2860
3149
 
3150
+ declare module '@tiptap/core' {
3151
+ interface Commands<ReturnType> {
3152
+ updateDecorations: {
3153
+ /**
3154
+ * Force declarative decorations to recompute, bypassing each extension's
3155
+ * `shouldUpdate` gate. Pass an extension name to recompute only that
3156
+ * extension's decorations, or omit it to recompute all of them.
3157
+ * @param extensionName The name of the extension to recompute (optional).
3158
+ * @example editor.commands.updateDecorations()
3159
+ * @example editor.commands.updateDecorations('myExtension')
3160
+ */
3161
+ updateDecorations: (extensionName?: string) => ReturnType;
3162
+ };
3163
+ }
3164
+ }
3165
+
2861
3166
  declare module '@tiptap/core' {
2862
3167
  interface Commands<ReturnType> {
2863
3168
  wrapIn: {
@@ -2905,6 +3210,7 @@ declare class Editor extends EventEmitter<EditorEvents> {
2905
3210
  * A unique ID for this editor instance.
2906
3211
  */
2907
3212
  instanceId: string;
3213
+ private hasWarnedStaleDecorationRead;
2908
3214
  options: EditorOptions;
2909
3215
  constructor(options?: Partial<EditorOptions>);
2910
3216
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiptap/extension-drag-handle-vue-2",
3
- "version": "3.29.2",
3
+ "version": "3.30.0",
4
4
  "description": "drag handle extension for tiptap with vue 2",
5
5
  "keywords": [
6
6
  "tiptap",
@@ -41,15 +41,15 @@
41
41
  "devDependencies": {
42
42
  "vue": "^2.0.0",
43
43
  "vue-ts-types": "1.6.2",
44
- "@tiptap/extension-drag-handle": "^3.29.2",
45
- "@tiptap/pm": "^3.29.2",
46
- "@tiptap/vue-2": "^3.29.2"
44
+ "@tiptap/extension-drag-handle": "^3.30.0",
45
+ "@tiptap/pm": "^3.30.0",
46
+ "@tiptap/vue-2": "^3.30.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "vue": "^2.0.0",
50
- "@tiptap/pm": "3.29.2",
51
- "@tiptap/extension-drag-handle": "3.29.2",
52
- "@tiptap/vue-2": "3.29.2"
50
+ "@tiptap/extension-drag-handle": "3.30.0",
51
+ "@tiptap/pm": "3.30.0",
52
+ "@tiptap/vue-2": "3.30.0"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "tsup"