@tiptap/extensions 3.0.0-next.4 → 3.0.0-next.5

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.
Files changed (39) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/character-count/index.cjs +129 -0
  3. package/dist/character-count/index.cjs.map +1 -0
  4. package/dist/character-count/index.d.cts +62 -0
  5. package/dist/character-count/index.d.ts +62 -0
  6. package/dist/character-count/index.js +102 -0
  7. package/dist/character-count/index.js.map +1 -0
  8. package/dist/drop-cursor/index.cjs +47 -0
  9. package/dist/drop-cursor/index.cjs.map +1 -0
  10. package/dist/drop-cursor/index.d.cts +31 -0
  11. package/dist/drop-cursor/index.d.ts +31 -0
  12. package/dist/drop-cursor/index.js +20 -0
  13. package/dist/drop-cursor/index.js.map +1 -0
  14. package/dist/history/index.cjs +66 -0
  15. package/dist/history/index.cjs.map +1 -0
  16. package/dist/history/index.d.cts +44 -0
  17. package/dist/history/index.d.ts +44 -0
  18. package/dist/history/index.js +39 -0
  19. package/dist/history/index.js.map +1 -0
  20. package/dist/index.cjs +222 -23
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +157 -2
  23. package/dist/index.d.ts +157 -2
  24. package/dist/index.js +218 -22
  25. package/dist/index.js.map +1 -1
  26. package/dist/placeholder/index.cjs +88 -0
  27. package/dist/placeholder/index.cjs.map +1 -0
  28. package/dist/placeholder/index.d.cts +59 -0
  29. package/dist/placeholder/index.d.ts +59 -0
  30. package/dist/placeholder/index.js +61 -0
  31. package/dist/placeholder/index.js.map +1 -0
  32. package/package.json +27 -3
  33. package/src/character-count/character-count.ts +195 -0
  34. package/src/character-count/index.ts +1 -0
  35. package/src/history/history.ts +86 -0
  36. package/src/history/index.ts +1 -0
  37. package/src/index.ts +3 -0
  38. package/src/placeholder/index.ts +1 -0
  39. package/src/placeholder/placeholder.ts +128 -0
package/dist/index.d.cts CHANGED
@@ -1,4 +1,63 @@
1
- import { Extension, ParentConfig } from '@tiptap/core';
1
+ import { Extension, ParentConfig, Editor } from '@tiptap/core';
2
+ import { Node } from '@tiptap/pm/model';
3
+
4
+ interface CharacterCountOptions {
5
+ /**
6
+ * The maximum number of characters that should be allowed. Defaults to `0`.
7
+ * @default null
8
+ * @example 180
9
+ */
10
+ limit: number | null | undefined;
11
+ /**
12
+ * The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.
13
+ * If set to `nodeSize`, the nodeSize of the document is used.
14
+ * @default 'textSize'
15
+ * @example 'textSize'
16
+ */
17
+ mode: 'textSize' | 'nodeSize';
18
+ /**
19
+ * The text counter function to use. Defaults to a simple character count.
20
+ * @default (text) => text.length
21
+ * @example (text) => [...new Intl.Segmenter().segment(text)].length
22
+ */
23
+ textCounter: (text: string) => number;
24
+ /**
25
+ * The word counter function to use. Defaults to a simple word count.
26
+ * @default (text) => text.split(' ').filter(word => word !== '').length
27
+ * @example (text) => text.split(/\s+/).filter(word => word !== '').length
28
+ */
29
+ wordCounter: (text: string) => number;
30
+ }
31
+ interface CharacterCountStorage {
32
+ /**
33
+ * Get the number of characters for the current document.
34
+ * @param options The options for the character count. (optional)
35
+ * @param options.node The node to get the characters from. Defaults to the current document.
36
+ * @param options.mode The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.
37
+ */
38
+ characters: (options?: {
39
+ node?: Node;
40
+ mode?: 'textSize' | 'nodeSize';
41
+ }) => number;
42
+ /**
43
+ * Get the number of words for the current document.
44
+ * @param options The options for the character count. (optional)
45
+ * @param options.node The node to get the words from. Defaults to the current document.
46
+ */
47
+ words: (options?: {
48
+ node?: Node;
49
+ }) => number;
50
+ }
51
+ declare module '@tiptap/core' {
52
+ interface Storage {
53
+ characterCount: CharacterCountStorage;
54
+ }
55
+ }
56
+ /**
57
+ * This extension allows you to count the characters and words of your document.
58
+ * @see https://tiptap.dev/api/extensions/character-count
59
+ */
60
+ declare const CharacterCount: Extension<CharacterCountOptions, CharacterCountStorage>;
2
61
 
3
62
  interface DropcursorOptions {
4
63
  /**
@@ -75,6 +134,102 @@ declare module '@tiptap/core' {
75
134
  */
76
135
  declare const Gapcursor: Extension<any, any>;
77
136
 
137
+ interface HistoryOptions {
138
+ /**
139
+ * The amount of history events that are collected before the oldest events are discarded.
140
+ * @default 100
141
+ * @example 50
142
+ */
143
+ depth: number;
144
+ /**
145
+ * The delay (in milliseconds) between changes after which a new group should be started.
146
+ * @default 500
147
+ * @example 1000
148
+ */
149
+ newGroupDelay: number;
150
+ }
151
+ declare module '@tiptap/core' {
152
+ interface Commands<ReturnType> {
153
+ history: {
154
+ /**
155
+ * Undo recent changes
156
+ * @example editor.commands.undo()
157
+ */
158
+ undo: () => ReturnType;
159
+ /**
160
+ * Reapply reverted changes
161
+ * @example editor.commands.redo()
162
+ */
163
+ redo: () => ReturnType;
164
+ };
165
+ }
166
+ }
167
+ /**
168
+ * This extension allows you to undo and redo recent changes.
169
+ * @see https://www.tiptap.dev/api/extensions/history
170
+ *
171
+ * **Important**: If the `@tiptap/extension-collaboration` package is used, make sure to remove
172
+ * the `history` extension, as it is not compatible with the `collaboration` extension.
173
+ *
174
+ * `@tiptap/extension-collaboration` uses its own history implementation.
175
+ */
176
+ declare const History: Extension<HistoryOptions, any>;
177
+
178
+ interface PlaceholderOptions {
179
+ /**
180
+ * **The class name for the empty editor**
181
+ * @default 'is-editor-empty'
182
+ */
183
+ emptyEditorClass: string;
184
+ /**
185
+ * **The class name for empty nodes**
186
+ * @default 'is-empty'
187
+ */
188
+ emptyNodeClass: string;
189
+ /**
190
+ * **The placeholder content**
191
+ *
192
+ * You can use a function to return a dynamic placeholder or a string.
193
+ * @default 'Write something …'
194
+ */
195
+ placeholder: ((PlaceholderProps: {
196
+ editor: Editor;
197
+ node: Node;
198
+ pos: number;
199
+ hasAnchor: boolean;
200
+ }) => string) | string;
201
+ /**
202
+ * **Checks if the placeholder should be only shown when the editor is editable.**
203
+ *
204
+ * If true, the placeholder will only be shown when the editor is editable.
205
+ * If false, the placeholder will always be shown.
206
+ * @default true
207
+ */
208
+ showOnlyWhenEditable: boolean;
209
+ /**
210
+ * **Checks if the placeholder should be only shown when the current node is empty.**
211
+ *
212
+ * If true, the placeholder will only be shown when the current node is empty.
213
+ * If false, the placeholder will be shown when any node is empty.
214
+ * @default true
215
+ */
216
+ showOnlyCurrent: boolean;
217
+ /**
218
+ * **Controls if the placeholder should be shown for all descendents.**
219
+ *
220
+ * If true, the placeholder will be shown for all descendents.
221
+ * If false, the placeholder will only be shown for the current node.
222
+ * @default false
223
+ */
224
+ includeChildren: boolean;
225
+ }
226
+ /**
227
+ * This extension allows you to add a placeholder to your editor.
228
+ * A placeholder is a text that appears when the editor or a node is empty.
229
+ * @see https://www.tiptap.dev/api/extensions/placeholder
230
+ */
231
+ declare const Placeholder: Extension<PlaceholderOptions, any>;
232
+
78
233
  type SelectionOptions = {
79
234
  /**
80
235
  * The class name that should be added to the selected text.
@@ -114,4 +269,4 @@ interface TrailingNodeOptions {
114
269
  */
115
270
  declare const TrailingNode: Extension<TrailingNodeOptions, any>;
116
271
 
117
- export { Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions };
272
+ export { CharacterCount, type CharacterCountOptions, type CharacterCountStorage, Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, History, type HistoryOptions, Placeholder, type PlaceholderOptions, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,63 @@
1
- import { Extension, ParentConfig } from '@tiptap/core';
1
+ import { Extension, ParentConfig, Editor } from '@tiptap/core';
2
+ import { Node } from '@tiptap/pm/model';
3
+
4
+ interface CharacterCountOptions {
5
+ /**
6
+ * The maximum number of characters that should be allowed. Defaults to `0`.
7
+ * @default null
8
+ * @example 180
9
+ */
10
+ limit: number | null | undefined;
11
+ /**
12
+ * The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.
13
+ * If set to `nodeSize`, the nodeSize of the document is used.
14
+ * @default 'textSize'
15
+ * @example 'textSize'
16
+ */
17
+ mode: 'textSize' | 'nodeSize';
18
+ /**
19
+ * The text counter function to use. Defaults to a simple character count.
20
+ * @default (text) => text.length
21
+ * @example (text) => [...new Intl.Segmenter().segment(text)].length
22
+ */
23
+ textCounter: (text: string) => number;
24
+ /**
25
+ * The word counter function to use. Defaults to a simple word count.
26
+ * @default (text) => text.split(' ').filter(word => word !== '').length
27
+ * @example (text) => text.split(/\s+/).filter(word => word !== '').length
28
+ */
29
+ wordCounter: (text: string) => number;
30
+ }
31
+ interface CharacterCountStorage {
32
+ /**
33
+ * Get the number of characters for the current document.
34
+ * @param options The options for the character count. (optional)
35
+ * @param options.node The node to get the characters from. Defaults to the current document.
36
+ * @param options.mode The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.
37
+ */
38
+ characters: (options?: {
39
+ node?: Node;
40
+ mode?: 'textSize' | 'nodeSize';
41
+ }) => number;
42
+ /**
43
+ * Get the number of words for the current document.
44
+ * @param options The options for the character count. (optional)
45
+ * @param options.node The node to get the words from. Defaults to the current document.
46
+ */
47
+ words: (options?: {
48
+ node?: Node;
49
+ }) => number;
50
+ }
51
+ declare module '@tiptap/core' {
52
+ interface Storage {
53
+ characterCount: CharacterCountStorage;
54
+ }
55
+ }
56
+ /**
57
+ * This extension allows you to count the characters and words of your document.
58
+ * @see https://tiptap.dev/api/extensions/character-count
59
+ */
60
+ declare const CharacterCount: Extension<CharacterCountOptions, CharacterCountStorage>;
2
61
 
3
62
  interface DropcursorOptions {
4
63
  /**
@@ -75,6 +134,102 @@ declare module '@tiptap/core' {
75
134
  */
76
135
  declare const Gapcursor: Extension<any, any>;
77
136
 
137
+ interface HistoryOptions {
138
+ /**
139
+ * The amount of history events that are collected before the oldest events are discarded.
140
+ * @default 100
141
+ * @example 50
142
+ */
143
+ depth: number;
144
+ /**
145
+ * The delay (in milliseconds) between changes after which a new group should be started.
146
+ * @default 500
147
+ * @example 1000
148
+ */
149
+ newGroupDelay: number;
150
+ }
151
+ declare module '@tiptap/core' {
152
+ interface Commands<ReturnType> {
153
+ history: {
154
+ /**
155
+ * Undo recent changes
156
+ * @example editor.commands.undo()
157
+ */
158
+ undo: () => ReturnType;
159
+ /**
160
+ * Reapply reverted changes
161
+ * @example editor.commands.redo()
162
+ */
163
+ redo: () => ReturnType;
164
+ };
165
+ }
166
+ }
167
+ /**
168
+ * This extension allows you to undo and redo recent changes.
169
+ * @see https://www.tiptap.dev/api/extensions/history
170
+ *
171
+ * **Important**: If the `@tiptap/extension-collaboration` package is used, make sure to remove
172
+ * the `history` extension, as it is not compatible with the `collaboration` extension.
173
+ *
174
+ * `@tiptap/extension-collaboration` uses its own history implementation.
175
+ */
176
+ declare const History: Extension<HistoryOptions, any>;
177
+
178
+ interface PlaceholderOptions {
179
+ /**
180
+ * **The class name for the empty editor**
181
+ * @default 'is-editor-empty'
182
+ */
183
+ emptyEditorClass: string;
184
+ /**
185
+ * **The class name for empty nodes**
186
+ * @default 'is-empty'
187
+ */
188
+ emptyNodeClass: string;
189
+ /**
190
+ * **The placeholder content**
191
+ *
192
+ * You can use a function to return a dynamic placeholder or a string.
193
+ * @default 'Write something …'
194
+ */
195
+ placeholder: ((PlaceholderProps: {
196
+ editor: Editor;
197
+ node: Node;
198
+ pos: number;
199
+ hasAnchor: boolean;
200
+ }) => string) | string;
201
+ /**
202
+ * **Checks if the placeholder should be only shown when the editor is editable.**
203
+ *
204
+ * If true, the placeholder will only be shown when the editor is editable.
205
+ * If false, the placeholder will always be shown.
206
+ * @default true
207
+ */
208
+ showOnlyWhenEditable: boolean;
209
+ /**
210
+ * **Checks if the placeholder should be only shown when the current node is empty.**
211
+ *
212
+ * If true, the placeholder will only be shown when the current node is empty.
213
+ * If false, the placeholder will be shown when any node is empty.
214
+ * @default true
215
+ */
216
+ showOnlyCurrent: boolean;
217
+ /**
218
+ * **Controls if the placeholder should be shown for all descendents.**
219
+ *
220
+ * If true, the placeholder will be shown for all descendents.
221
+ * If false, the placeholder will only be shown for the current node.
222
+ * @default false
223
+ */
224
+ includeChildren: boolean;
225
+ }
226
+ /**
227
+ * This extension allows you to add a placeholder to your editor.
228
+ * A placeholder is a text that appears when the editor or a node is empty.
229
+ * @see https://www.tiptap.dev/api/extensions/placeholder
230
+ */
231
+ declare const Placeholder: Extension<PlaceholderOptions, any>;
232
+
78
233
  type SelectionOptions = {
79
234
  /**
80
235
  * The class name that should be added to the selected text.
@@ -114,4 +269,4 @@ interface TrailingNodeOptions {
114
269
  */
115
270
  declare const TrailingNode: Extension<TrailingNodeOptions, any>;
116
271
 
117
- export { Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions };
272
+ export { CharacterCount, type CharacterCountOptions, type CharacterCountStorage, Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, History, type HistoryOptions, Placeholder, type PlaceholderOptions, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions };
package/dist/index.js CHANGED
@@ -1,7 +1,106 @@
1
- // src/drop-cursor/drop-cursor.ts
1
+ // src/character-count/character-count.ts
2
2
  import { Extension } from "@tiptap/core";
3
+ import { Plugin, PluginKey } from "@tiptap/pm/state";
4
+ var CharacterCount = Extension.create({
5
+ name: "characterCount",
6
+ addOptions() {
7
+ return {
8
+ limit: null,
9
+ mode: "textSize",
10
+ textCounter: (text) => text.length,
11
+ wordCounter: (text) => text.split(" ").filter((word) => word !== "").length
12
+ };
13
+ },
14
+ addStorage() {
15
+ return {
16
+ characters: () => 0,
17
+ words: () => 0
18
+ };
19
+ },
20
+ onBeforeCreate() {
21
+ this.storage.characters = (options) => {
22
+ const node = (options == null ? void 0 : options.node) || this.editor.state.doc;
23
+ const mode = (options == null ? void 0 : options.mode) || this.options.mode;
24
+ if (mode === "textSize") {
25
+ const text = node.textBetween(0, node.content.size, void 0, " ");
26
+ return this.options.textCounter(text);
27
+ }
28
+ return node.nodeSize;
29
+ };
30
+ this.storage.words = (options) => {
31
+ const node = (options == null ? void 0 : options.node) || this.editor.state.doc;
32
+ const text = node.textBetween(0, node.content.size, " ", " ");
33
+ return this.options.wordCounter(text);
34
+ };
35
+ },
36
+ addProseMirrorPlugins() {
37
+ let initialEvaluationDone = false;
38
+ return [
39
+ new Plugin({
40
+ key: new PluginKey("characterCount"),
41
+ appendTransaction: (transactions, oldState, newState) => {
42
+ if (initialEvaluationDone) {
43
+ return;
44
+ }
45
+ const limit = this.options.limit;
46
+ if (limit === null || limit === void 0 || limit === 0) {
47
+ initialEvaluationDone = true;
48
+ return;
49
+ }
50
+ const initialContentSize = this.storage.characters({ node: newState.doc });
51
+ if (initialContentSize > limit) {
52
+ const over = initialContentSize - limit;
53
+ const from = 0;
54
+ const to = over;
55
+ console.warn(
56
+ `[CharacterCount] Initial content exceeded limit of ${limit} characters. Content was automatically trimmed.`
57
+ );
58
+ const tr = newState.tr.deleteRange(from, to);
59
+ initialEvaluationDone = true;
60
+ return tr;
61
+ }
62
+ initialEvaluationDone = true;
63
+ },
64
+ filterTransaction: (transaction, state) => {
65
+ const limit = this.options.limit;
66
+ if (!transaction.docChanged || limit === 0 || limit === null || limit === void 0) {
67
+ return true;
68
+ }
69
+ const oldSize = this.storage.characters({ node: state.doc });
70
+ const newSize = this.storage.characters({ node: transaction.doc });
71
+ if (newSize <= limit) {
72
+ return true;
73
+ }
74
+ if (oldSize > limit && newSize > limit && newSize <= oldSize) {
75
+ return true;
76
+ }
77
+ if (oldSize > limit && newSize > limit && newSize > oldSize) {
78
+ return false;
79
+ }
80
+ const isPaste = transaction.getMeta("paste");
81
+ if (!isPaste) {
82
+ return false;
83
+ }
84
+ const pos = transaction.selection.$head.pos;
85
+ const over = newSize - limit;
86
+ const from = pos - over;
87
+ const to = pos;
88
+ transaction.deleteRange(from, to);
89
+ const updatedSize = this.storage.characters({ node: transaction.doc });
90
+ if (updatedSize > limit) {
91
+ return false;
92
+ }
93
+ return true;
94
+ }
95
+ })
96
+ ];
97
+ }
98
+ });
99
+
100
+ // src/drop-cursor/drop-cursor.ts
101
+ import { Extension as Extension2 } from "@tiptap/core";
3
102
  import { dropCursor } from "@tiptap/pm/dropcursor";
4
- var Dropcursor = Extension.create({
103
+ var Dropcursor = Extension2.create({
5
104
  name: "dropCursor",
6
105
  addOptions() {
7
106
  return {
@@ -16,10 +115,10 @@ var Dropcursor = Extension.create({
16
115
  });
17
116
 
18
117
  // src/focus/focus.ts
19
- import { Extension as Extension2 } from "@tiptap/core";
20
- import { Plugin, PluginKey } from "@tiptap/pm/state";
118
+ import { Extension as Extension3 } from "@tiptap/core";
119
+ import { Plugin as Plugin2, PluginKey as PluginKey2 } from "@tiptap/pm/state";
21
120
  import { Decoration, DecorationSet } from "@tiptap/pm/view";
22
- var Focus = Extension2.create({
121
+ var Focus = Extension3.create({
23
122
  name: "focus",
24
123
  addOptions() {
25
124
  return {
@@ -29,8 +128,8 @@ var Focus = Extension2.create({
29
128
  },
30
129
  addProseMirrorPlugins() {
31
130
  return [
32
- new Plugin({
33
- key: new PluginKey("focus"),
131
+ new Plugin2({
132
+ key: new PluginKey2("focus"),
34
133
  props: {
35
134
  decorations: ({ doc, selection }) => {
36
135
  const { isEditable, isFocused } = this.editor;
@@ -81,9 +180,9 @@ var Focus = Extension2.create({
81
180
  });
82
181
 
83
182
  // src/gap-cursor/gap-cursor.ts
84
- import { callOrReturn, Extension as Extension3, getExtensionField } from "@tiptap/core";
183
+ import { callOrReturn, Extension as Extension4, getExtensionField } from "@tiptap/core";
85
184
  import { gapCursor } from "@tiptap/pm/gapcursor";
86
- var Gapcursor = Extension3.create({
185
+ var Gapcursor = Extension4.create({
87
186
  name: "gapCursor",
88
187
  addProseMirrorPlugins() {
89
188
  return [gapCursor()];
@@ -101,11 +200,105 @@ var Gapcursor = Extension3.create({
101
200
  }
102
201
  });
103
202
 
104
- // src/selection/selection.ts
105
- import { Extension as Extension4 } from "@tiptap/core";
106
- import { Plugin as Plugin2, PluginKey as PluginKey2 } from "@tiptap/pm/state";
203
+ // src/history/history.ts
204
+ import { Extension as Extension5 } from "@tiptap/core";
205
+ import { history, redo, undo } from "@tiptap/pm/history";
206
+ var History = Extension5.create({
207
+ name: "history",
208
+ addOptions() {
209
+ return {
210
+ depth: 100,
211
+ newGroupDelay: 500
212
+ };
213
+ },
214
+ addCommands() {
215
+ return {
216
+ undo: () => ({ state, dispatch }) => {
217
+ return undo(state, dispatch);
218
+ },
219
+ redo: () => ({ state, dispatch }) => {
220
+ return redo(state, dispatch);
221
+ }
222
+ };
223
+ },
224
+ addProseMirrorPlugins() {
225
+ return [history(this.options)];
226
+ },
227
+ addKeyboardShortcuts() {
228
+ return {
229
+ "Mod-z": () => this.editor.commands.undo(),
230
+ "Shift-Mod-z": () => this.editor.commands.redo(),
231
+ "Mod-y": () => this.editor.commands.redo(),
232
+ // Russian keyboard layouts
233
+ "Mod-\u044F": () => this.editor.commands.undo(),
234
+ "Shift-Mod-\u044F": () => this.editor.commands.redo()
235
+ };
236
+ }
237
+ });
238
+
239
+ // src/placeholder/placeholder.ts
240
+ import { Extension as Extension6, isNodeEmpty } from "@tiptap/core";
241
+ import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@tiptap/pm/state";
107
242
  import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "@tiptap/pm/view";
108
- var Selection = Extension4.create({
243
+ var Placeholder = Extension6.create({
244
+ name: "placeholder",
245
+ addOptions() {
246
+ return {
247
+ emptyEditorClass: "is-editor-empty",
248
+ emptyNodeClass: "is-empty",
249
+ placeholder: "Write something \u2026",
250
+ showOnlyWhenEditable: true,
251
+ showOnlyCurrent: true,
252
+ includeChildren: false
253
+ };
254
+ },
255
+ addProseMirrorPlugins() {
256
+ return [
257
+ new Plugin3({
258
+ key: new PluginKey3("placeholder"),
259
+ props: {
260
+ decorations: ({ doc, selection }) => {
261
+ const active = this.editor.isEditable || !this.options.showOnlyWhenEditable;
262
+ const { anchor } = selection;
263
+ const decorations = [];
264
+ if (!active) {
265
+ return null;
266
+ }
267
+ const isEmptyDoc = this.editor.isEmpty;
268
+ doc.descendants((node, pos) => {
269
+ const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
270
+ const isEmpty = !node.isLeaf && isNodeEmpty(node);
271
+ if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
272
+ const classes = [this.options.emptyNodeClass];
273
+ if (isEmptyDoc) {
274
+ classes.push(this.options.emptyEditorClass);
275
+ }
276
+ const decoration = Decoration2.node(pos, pos + node.nodeSize, {
277
+ class: classes.join(" "),
278
+ "data-placeholder": typeof this.options.placeholder === "function" ? this.options.placeholder({
279
+ editor: this.editor,
280
+ node,
281
+ pos,
282
+ hasAnchor
283
+ }) : this.options.placeholder
284
+ });
285
+ decorations.push(decoration);
286
+ }
287
+ return this.options.includeChildren;
288
+ });
289
+ return DecorationSet2.create(doc, decorations);
290
+ }
291
+ }
292
+ })
293
+ ];
294
+ }
295
+ });
296
+
297
+ // src/selection/selection.ts
298
+ import { Extension as Extension7 } from "@tiptap/core";
299
+ import { Plugin as Plugin4, PluginKey as PluginKey4 } from "@tiptap/pm/state";
300
+ import { Decoration as Decoration3, DecorationSet as DecorationSet3 } from "@tiptap/pm/view";
301
+ var Selection = Extension7.create({
109
302
  name: "selection",
110
303
  addOptions() {
111
304
  return {
@@ -115,15 +308,15 @@ var Selection = Extension4.create({
115
308
  addProseMirrorPlugins() {
116
309
  const { editor, options } = this;
117
310
  return [
118
- new Plugin2({
119
- key: new PluginKey2("selection"),
311
+ new Plugin4({
312
+ key: new PluginKey4("selection"),
120
313
  props: {
121
314
  decorations(state) {
122
315
  if (state.selection.empty || editor.isFocused) {
123
316
  return null;
124
317
  }
125
- return DecorationSet2.create(state.doc, [
126
- Decoration2.inline(state.selection.from, state.selection.to, {
318
+ return DecorationSet3.create(state.doc, [
319
+ Decoration3.inline(state.selection.from, state.selection.to, {
127
320
  class: options.className
128
321
  })
129
322
  ]);
@@ -135,12 +328,12 @@ var Selection = Extension4.create({
135
328
  });
136
329
 
137
330
  // src/trailing-node/trailing-node.ts
138
- import { Extension as Extension5 } from "@tiptap/core";
139
- import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@tiptap/pm/state";
331
+ import { Extension as Extension8 } from "@tiptap/core";
332
+ import { Plugin as Plugin5, PluginKey as PluginKey5 } from "@tiptap/pm/state";
140
333
  function nodeEqualsType({ types, node }) {
141
334
  return node && Array.isArray(types) && types.includes(node.type) || (node == null ? void 0 : node.type) === types;
142
335
  }
143
- var TrailingNode = Extension5.create({
336
+ var TrailingNode = Extension8.create({
144
337
  name: "trailingNode",
145
338
  addOptions() {
146
339
  return {
@@ -149,10 +342,10 @@ var TrailingNode = Extension5.create({
149
342
  };
150
343
  },
151
344
  addProseMirrorPlugins() {
152
- const plugin = new PluginKey3(this.name);
345
+ const plugin = new PluginKey5(this.name);
153
346
  const disabledNodes = Object.entries(this.editor.schema.nodes).map(([, value]) => value).filter((node) => (this.options.notAfter || []).concat(this.options.node).includes(node.name));
154
347
  return [
155
- new Plugin3({
348
+ new Plugin5({
156
349
  key: plugin,
157
350
  appendTransaction: (_, __, state) => {
158
351
  const { doc, tr, schema } = state;
@@ -182,9 +375,12 @@ var TrailingNode = Extension5.create({
182
375
  }
183
376
  });
184
377
  export {
378
+ CharacterCount,
185
379
  Dropcursor,
186
380
  Focus,
187
381
  Gapcursor,
382
+ History,
383
+ Placeholder,
188
384
  Selection,
189
385
  TrailingNode
190
386
  };