@tiptap/extensions 3.23.5 → 3.23.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +220 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -9
- package/dist/index.d.ts +12 -9
- package/dist/index.js +216 -24
- package/dist/index.js.map +1 -1
- package/dist/placeholder/index.cjs +217 -24
- package/dist/placeholder/index.cjs.map +1 -1
- package/dist/placeholder/index.d.cts +13 -10
- package/dist/placeholder/index.d.ts +13 -10
- package/dist/placeholder/index.js +216 -24
- package/dist/placeholder/index.js.map +1 -1
- package/package.json +5 -5
- package/src/placeholder/index.ts +1 -0
- package/src/placeholder/placeholder.ts +144 -90
- package/src/placeholder/types.ts +60 -0
- package/src/placeholder/utils/createPlaceholderDecoration.ts +61 -0
- package/src/placeholder/utils/findScrollParent.ts +38 -0
- package/src/placeholder/utils/getViewportBoundaryPositions.ts +45 -0
- package/src/placeholder/utils/throttle.ts +25 -0
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
Dropcursor: () => Dropcursor,
|
|
25
25
|
Focus: () => Focus,
|
|
26
26
|
Gapcursor: () => Gapcursor,
|
|
27
|
+
PLUGIN_KEY: () => PLUGIN_KEY,
|
|
27
28
|
Placeholder: () => Placeholder,
|
|
28
29
|
Selection: () => Selection,
|
|
29
30
|
TrailingNode: () => TrailingNode,
|
|
@@ -240,11 +241,118 @@ var Gapcursor = import_core4.Extension.create({
|
|
|
240
241
|
// src/placeholder/placeholder.ts
|
|
241
242
|
var import_core5 = require("@tiptap/core");
|
|
242
243
|
var import_state3 = require("@tiptap/pm/state");
|
|
244
|
+
var import_view3 = require("@tiptap/pm/view");
|
|
245
|
+
|
|
246
|
+
// src/placeholder/utils/createPlaceholderDecoration.ts
|
|
243
247
|
var import_view2 = require("@tiptap/pm/view");
|
|
248
|
+
function createPlaceholderDecoration(options) {
|
|
249
|
+
const {
|
|
250
|
+
editor,
|
|
251
|
+
placeholder,
|
|
252
|
+
dataAttribute,
|
|
253
|
+
pos,
|
|
254
|
+
node,
|
|
255
|
+
isEmptyDoc,
|
|
256
|
+
hasAnchor,
|
|
257
|
+
classes: { emptyNode, emptyEditor }
|
|
258
|
+
} = options;
|
|
259
|
+
const classes = [emptyNode];
|
|
260
|
+
if (isEmptyDoc) {
|
|
261
|
+
classes.push(emptyEditor);
|
|
262
|
+
}
|
|
263
|
+
return import_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
264
|
+
class: classes.join(" "),
|
|
265
|
+
[dataAttribute]: typeof placeholder === "function" ? placeholder({
|
|
266
|
+
editor,
|
|
267
|
+
node,
|
|
268
|
+
pos,
|
|
269
|
+
hasAnchor
|
|
270
|
+
}) : placeholder
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/placeholder/utils/findScrollParent.ts
|
|
275
|
+
function isScrollable(el) {
|
|
276
|
+
const style = getComputedStyle(el);
|
|
277
|
+
const overflow = `${style.overflow} ${style.overflowY} ${style.overflowX}`;
|
|
278
|
+
return /auto|scroll|overlay/.test(overflow);
|
|
279
|
+
}
|
|
280
|
+
function findScrollParent(element) {
|
|
281
|
+
let el = element;
|
|
282
|
+
while (el) {
|
|
283
|
+
if (isScrollable(el)) {
|
|
284
|
+
return el;
|
|
285
|
+
}
|
|
286
|
+
const parent = el.parentElement;
|
|
287
|
+
if (!parent) {
|
|
288
|
+
const root = el.getRootNode();
|
|
289
|
+
if (root instanceof ShadowRoot) {
|
|
290
|
+
el = root.host;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
return window;
|
|
294
|
+
}
|
|
295
|
+
el = parent;
|
|
296
|
+
}
|
|
297
|
+
return window;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// src/placeholder/utils/getViewportBoundaryPositions.ts
|
|
301
|
+
function getContainerRect(container) {
|
|
302
|
+
if (container === window) {
|
|
303
|
+
return { top: 0, bottom: window.innerHeight };
|
|
304
|
+
}
|
|
305
|
+
return container.getBoundingClientRect();
|
|
306
|
+
}
|
|
307
|
+
function getViewportBoundaryPositions({
|
|
308
|
+
doc,
|
|
309
|
+
view,
|
|
310
|
+
scrollContainer
|
|
311
|
+
}) {
|
|
312
|
+
const editorRect = view.dom.getBoundingClientRect();
|
|
313
|
+
const containerRect = scrollContainer ? getContainerRect(scrollContainer) : { top: 0, bottom: window.innerHeight };
|
|
314
|
+
const visibleTop = Math.max(editorRect.top, containerRect.top);
|
|
315
|
+
const visibleBottom = Math.min(editorRect.bottom, containerRect.bottom);
|
|
316
|
+
if (visibleTop >= visibleBottom) {
|
|
317
|
+
return { top: 0, bottom: doc.content.size };
|
|
318
|
+
}
|
|
319
|
+
const isRTL = getComputedStyle(view.dom).direction === "rtl";
|
|
320
|
+
const x = isRTL ? Math.max(editorRect.right - 2, editorRect.left + 2) : editorRect.left + 2;
|
|
321
|
+
const topPos = view.posAtCoords({ left: x, top: visibleTop + 2 });
|
|
322
|
+
const bottomPos = view.posAtCoords({ left: x, top: visibleBottom - 2 });
|
|
323
|
+
return {
|
|
324
|
+
top: topPos ? topPos.pos : 0,
|
|
325
|
+
bottom: bottomPos ? bottomPos.pos : doc.content.size
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/placeholder/utils/throttle.ts
|
|
330
|
+
function throttle(fn, delay) {
|
|
331
|
+
let timer = null;
|
|
332
|
+
const call = ((...args) => {
|
|
333
|
+
if (timer) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
fn(...args);
|
|
337
|
+
timer = setTimeout(() => {
|
|
338
|
+
timer = null;
|
|
339
|
+
}, delay);
|
|
340
|
+
});
|
|
341
|
+
const cancel = () => {
|
|
342
|
+
if (timer) {
|
|
343
|
+
clearTimeout(timer);
|
|
344
|
+
timer = null;
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
return { call, cancel };
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/placeholder/placeholder.ts
|
|
244
351
|
var DEFAULT_DATA_ATTRIBUTE = "placeholder";
|
|
245
352
|
function preparePlaceholderAttribute(attr) {
|
|
246
353
|
return attr.replace(/\s+/g, "-").replace(/[^a-zA-Z0-9-]/g, "").replace(/^[0-9-]+/, "").replace(/^-+/, "").toLowerCase();
|
|
247
354
|
}
|
|
355
|
+
var PLUGIN_KEY = new import_state3.PluginKey("tiptap__placeholder");
|
|
248
356
|
var Placeholder = import_core5.Extension.create({
|
|
249
357
|
name: "placeholder",
|
|
250
358
|
addOptions() {
|
|
@@ -262,41 +370,125 @@ var Placeholder = import_core5.Extension.create({
|
|
|
262
370
|
const dataAttribute = this.options.dataAttribute ? `data-${preparePlaceholderAttribute(this.options.dataAttribute)}` : `data-${DEFAULT_DATA_ATTRIBUTE}`;
|
|
263
371
|
return [
|
|
264
372
|
new import_state3.Plugin({
|
|
265
|
-
|
|
373
|
+
state: {
|
|
374
|
+
init() {
|
|
375
|
+
return {
|
|
376
|
+
// null means "no viewport info yet" — decoration callback falls
|
|
377
|
+
// back to full document scan until the scroll handler fires.
|
|
378
|
+
topPos: null,
|
|
379
|
+
bottomPos: null
|
|
380
|
+
};
|
|
381
|
+
},
|
|
382
|
+
apply(tr, prev) {
|
|
383
|
+
const meta = tr.getMeta(PLUGIN_KEY);
|
|
384
|
+
if (meta == null ? void 0 : meta.positions) {
|
|
385
|
+
return {
|
|
386
|
+
topPos: meta.positions.top,
|
|
387
|
+
bottomPos: meta.positions.bottom
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
if (!tr.docChanged) {
|
|
391
|
+
return prev;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
topPos: prev.topPos !== null ? tr.mapping.map(prev.topPos) : null,
|
|
395
|
+
bottomPos: prev.bottomPos !== null ? tr.mapping.map(prev.bottomPos) : null
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
key: PLUGIN_KEY,
|
|
400
|
+
view(view) {
|
|
401
|
+
const scrollContainer = findScrollParent(view.dom);
|
|
402
|
+
const computeAndDispatch = () => {
|
|
403
|
+
const positions = getViewportBoundaryPositions({
|
|
404
|
+
view,
|
|
405
|
+
doc: view.state.doc,
|
|
406
|
+
scrollContainer
|
|
407
|
+
});
|
|
408
|
+
const prev = PLUGIN_KEY.getState(view.state);
|
|
409
|
+
if (prev.topPos === positions.top && prev.bottomPos === positions.bottom) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const tr = view.state.tr.setMeta(PLUGIN_KEY, { positions }).setMeta("tiptap__viewportUpdate", true);
|
|
413
|
+
view.dispatch(tr);
|
|
414
|
+
};
|
|
415
|
+
const { call: throttledUpdate, cancel: cancelThrottle } = throttle(computeAndDispatch, 250);
|
|
416
|
+
const scrollParent = scrollContainer;
|
|
417
|
+
scrollParent.addEventListener("scroll", throttledUpdate, { passive: true });
|
|
418
|
+
computeAndDispatch();
|
|
419
|
+
return {
|
|
420
|
+
update(_, prevState) {
|
|
421
|
+
if (view.state.doc.content.size !== prevState.doc.content.size) {
|
|
422
|
+
computeAndDispatch();
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
destroy: () => {
|
|
426
|
+
cancelThrottle();
|
|
427
|
+
scrollParent.removeEventListener("scroll", throttledUpdate);
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
},
|
|
266
431
|
props: {
|
|
267
432
|
decorations: ({ doc, selection }) => {
|
|
433
|
+
var _a, _b;
|
|
268
434
|
const active = this.editor.isEditable || !this.options.showOnlyWhenEditable;
|
|
269
|
-
const { anchor } = selection;
|
|
270
|
-
const decorations = [];
|
|
271
435
|
if (!active) {
|
|
272
436
|
return null;
|
|
273
437
|
}
|
|
438
|
+
const { anchor } = selection;
|
|
439
|
+
const decorations = [];
|
|
274
440
|
const isEmptyDoc = this.editor.isEmpty;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
if (
|
|
279
|
-
|
|
441
|
+
const useResolvedPath = this.options.showOnlyCurrent && !this.options.includeChildren;
|
|
442
|
+
if (useResolvedPath) {
|
|
443
|
+
const resolved = doc.resolve(anchor);
|
|
444
|
+
if (resolved.depth > 0) {
|
|
445
|
+
const node = resolved.node(1);
|
|
446
|
+
const nodeStart = resolved.before(1);
|
|
447
|
+
if (node.type.isTextblock && (0, import_core5.isNodeEmpty)(node)) {
|
|
448
|
+
const hasAnchor = anchor >= nodeStart && anchor <= nodeStart + node.nodeSize;
|
|
449
|
+
const decoration = createPlaceholderDecoration({
|
|
450
|
+
node,
|
|
451
|
+
dataAttribute,
|
|
452
|
+
hasAnchor,
|
|
453
|
+
placeholder: this.options.placeholder,
|
|
454
|
+
classes: {
|
|
455
|
+
emptyEditor: this.options.emptyEditorClass,
|
|
456
|
+
emptyNode: this.options.emptyNodeClass
|
|
457
|
+
},
|
|
458
|
+
editor: this.editor,
|
|
459
|
+
isEmptyDoc,
|
|
460
|
+
pos: resolved.before(1)
|
|
461
|
+
});
|
|
462
|
+
decorations.push(decoration);
|
|
463
|
+
}
|
|
280
464
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
465
|
+
} else {
|
|
466
|
+
const pluginState = PLUGIN_KEY.getState(this.editor.state);
|
|
467
|
+
const from = (_a = pluginState.topPos) != null ? _a : 0;
|
|
468
|
+
const to = (_b = pluginState.bottomPos) != null ? _b : doc.content.size;
|
|
469
|
+
doc.nodesBetween(from, to, (node, pos) => {
|
|
470
|
+
const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
|
|
471
|
+
const isEmpty = !node.isLeaf && (0, import_core5.isNodeEmpty)(node);
|
|
472
|
+
if (!node.type.isTextblock) {
|
|
473
|
+
return this.options.includeChildren;
|
|
285
474
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
475
|
+
if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
|
|
476
|
+
const decoration = createPlaceholderDecoration({
|
|
477
|
+
classes: { emptyEditor: this.options.emptyEditorClass, emptyNode: this.options.emptyNodeClass },
|
|
289
478
|
editor: this.editor,
|
|
479
|
+
isEmptyDoc,
|
|
480
|
+
dataAttribute,
|
|
481
|
+
hasAnchor,
|
|
482
|
+
placeholder: this.options.placeholder,
|
|
290
483
|
node,
|
|
291
|
-
pos
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
return import_view2.DecorationSet.create(doc, decorations);
|
|
484
|
+
pos
|
|
485
|
+
});
|
|
486
|
+
decorations.push(decoration);
|
|
487
|
+
}
|
|
488
|
+
return this.options.includeChildren;
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
return import_view3.DecorationSet.create(doc, decorations);
|
|
300
492
|
}
|
|
301
493
|
}
|
|
302
494
|
})
|
|
@@ -307,7 +499,7 @@ var Placeholder = import_core5.Extension.create({
|
|
|
307
499
|
// src/selection/selection.ts
|
|
308
500
|
var import_core6 = require("@tiptap/core");
|
|
309
501
|
var import_state4 = require("@tiptap/pm/state");
|
|
310
|
-
var
|
|
502
|
+
var import_view4 = require("@tiptap/pm/view");
|
|
311
503
|
var Selection = import_core6.Extension.create({
|
|
312
504
|
name: "selection",
|
|
313
505
|
addOptions() {
|
|
@@ -325,8 +517,8 @@ var Selection = import_core6.Extension.create({
|
|
|
325
517
|
if (state.selection.empty || editor.isFocused || !editor.isEditable || (0, import_core6.isNodeSelection)(state.selection) || editor.view.dragging) {
|
|
326
518
|
return null;
|
|
327
519
|
}
|
|
328
|
-
return
|
|
329
|
-
|
|
520
|
+
return import_view4.DecorationSet.create(state.doc, [
|
|
521
|
+
import_view4.Decoration.inline(state.selection.from, state.selection.to, {
|
|
330
522
|
class: options.className
|
|
331
523
|
})
|
|
332
524
|
]);
|
|
@@ -435,6 +627,7 @@ var UndoRedo = import_core8.Extension.create({
|
|
|
435
627
|
Dropcursor,
|
|
436
628
|
Focus,
|
|
437
629
|
Gapcursor,
|
|
630
|
+
PLUGIN_KEY,
|
|
438
631
|
Placeholder,
|
|
439
632
|
Selection,
|
|
440
633
|
TrailingNode,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/character-count/character-count.ts","../src/drop-cursor/drop-cursor.ts","../src/focus/focus.ts","../src/gap-cursor/gap-cursor.ts","../src/placeholder/placeholder.ts","../src/selection/selection.ts","../src/trailing-node/trailing-node.ts","../src/undo-redo/undo-redo.ts"],"sourcesContent":["export * from './character-count/index.js'\nexport * from './drop-cursor/index.js'\nexport * from './focus/index.js'\nexport * from './gap-cursor/index.js'\nexport * from './placeholder/index.js'\nexport * from './selection/index.js'\nexport * from './trailing-node/index.js'\nexport * from './undo-redo/index.js'\n","import { Extension } from '@tiptap/core'\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\nexport interface CharacterCountOptions {\n /**\n * The maximum number of characters that should be allowed. Defaults to `0`.\n * @default null\n * @example 180\n */\n limit: number | null | undefined\n /**\n * The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.\n * If set to `nodeSize`, the nodeSize of the document is used.\n * @default 'textSize'\n * @example 'textSize'\n */\n mode: 'textSize' | 'nodeSize'\n /**\n * Sets whether the content will be automatically trimmed when programatically setting content over the limit.\n * If set to false, the user will be able to trim the text manually.\n * @default true\n * @example false\n */\n autoTrim?: boolean\n /**\n * The text counter function to use. Defaults to a simple character count.\n * @default (text) => text.length\n * @example (text) => [...new Intl.Segmenter().segment(text)].length\n */\n textCounter: (text: string) => number\n /**\n * The word counter function to use. Defaults to a simple word count.\n * @default (text) => text.split(' ').filter(word => word !== '').length\n * @example (text) => text.split(/\\s+/).filter(word => word !== '').length\n */\n wordCounter: (text: string) => number\n}\n\nexport interface CharacterCountStorage {\n /**\n * Get the number of characters for the current document.\n * @param options The options for the character count. (optional)\n * @param options.node The node to get the characters from. Defaults to the current document.\n * @param options.mode The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.\n */\n characters: (options?: { node?: ProseMirrorNode; mode?: 'textSize' | 'nodeSize' }) => number\n\n /**\n * Get the number of words for the current document.\n * @param options The options for the character count. (optional)\n * @param options.node The node to get the words from. Defaults to the current document.\n */\n words: (options?: { node?: ProseMirrorNode }) => number\n}\n\ndeclare module '@tiptap/core' {\n interface Storage {\n characterCount: CharacterCountStorage\n }\n}\n\n/**\n * This extension allows you to count the characters and words of your document.\n * @see https://tiptap.dev/api/extensions/character-count\n */\nexport const CharacterCount = Extension.create<CharacterCountOptions, CharacterCountStorage>({\n name: 'characterCount',\n\n addOptions() {\n return {\n limit: null,\n autoTrim: true,\n mode: 'textSize',\n textCounter: text => text.length,\n wordCounter: text => text.split(' ').filter(word => word !== '').length,\n }\n },\n\n addStorage() {\n return {\n characters: () => 0,\n words: () => 0,\n }\n },\n\n onBeforeCreate() {\n this.storage.characters = options => {\n const node = options?.node || this.editor.state.doc\n const mode = options?.mode || this.options.mode\n\n if (mode === 'textSize') {\n const text = node.textBetween(0, node.content.size, undefined, ' ')\n\n return this.options.textCounter(text)\n }\n\n return node.nodeSize\n }\n\n this.storage.words = options => {\n const node = options?.node || this.editor.state.doc\n const text = node.textBetween(0, node.content.size, ' ', ' ')\n\n return this.options.wordCounter(text)\n }\n },\n\n addProseMirrorPlugins() {\n let initialEvaluationDone = false\n\n return [\n new Plugin({\n key: new PluginKey('characterCount'),\n appendTransaction: (transactions, oldState, newState) => {\n if (initialEvaluationDone) {\n return\n }\n\n const limit = this.options.limit\n const autoTrim = this.options.autoTrim\n\n if (limit === null || limit === undefined || limit === 0 || autoTrim === false) {\n initialEvaluationDone = true\n return\n }\n\n const initialContentSize = this.storage.characters({ node: newState.doc })\n\n if (initialContentSize > limit) {\n const over = initialContentSize - limit\n const from = 0\n const to = over\n\n console.warn(\n `[CharacterCount] Initial content exceeded limit of ${limit} characters. Content was automatically trimmed.`,\n )\n const tr = newState.tr.deleteRange(from, to)\n initialEvaluationDone = true\n return tr\n }\n\n initialEvaluationDone = true\n },\n filterTransaction: (transaction, state) => {\n const limit = this.options.limit\n\n // Nothing has changed or no limit is defined. Ignore it.\n if (!transaction.docChanged || limit === 0 || limit === null || limit === undefined) {\n return true\n }\n\n const oldSize = this.storage.characters({ node: state.doc })\n const newSize = this.storage.characters({ node: transaction.doc })\n\n // Everything is in the limit. Good.\n if (newSize <= limit) {\n return true\n }\n\n // The limit has already been exceeded but will be reduced.\n if (oldSize > limit && newSize > limit && newSize <= oldSize) {\n return true\n }\n\n // The limit has already been exceeded and will be increased further.\n if (oldSize > limit && newSize > limit && newSize > oldSize) {\n return false\n }\n\n const isPaste = transaction.getMeta('paste')\n\n // Block all exceeding transactions that were not pasted.\n if (!isPaste) {\n return false\n }\n\n // For pasted content, we try to remove the exceeding content.\n const pos = transaction.selection.$head.pos\n const over = newSize - limit\n const from = pos - over\n const to = pos\n\n // It’s probably a bad idea to mutate transactions within `filterTransaction`\n // but for now this is working fine.\n transaction.deleteRange(from, to)\n\n // In some situations, the limit will continue to be exceeded after trimming.\n // This happens e.g. when truncating within a complex node (e.g. table)\n // and ProseMirror has to close this node again.\n // If this is the case, we prevent the transaction completely.\n const updatedSize = this.storage.characters({ node: transaction.doc })\n\n if (updatedSize > limit) {\n return false\n }\n\n return true\n },\n }),\n ]\n },\n})\n","import { Extension } from '@tiptap/core'\nimport { dropCursor } from '@tiptap/pm/dropcursor'\n\nexport interface DropcursorOptions {\n /**\n * The color of the drop cursor. Use `false` to apply no color and rely only on class.\n * @default 'currentColor'\n * @example 'red'\n */\n color?: string | false\n\n /**\n * The width of the drop cursor\n * @default 1\n * @example 2\n */\n width: number | undefined\n\n /**\n * The class of the drop cursor\n * @default undefined\n * @example 'drop-cursor'\n */\n class: string | undefined\n}\n\n/**\n * This extension allows you to add a drop cursor to your editor.\n * A drop cursor is a line that appears when you drag and drop content\n * in-between nodes.\n * @see https://tiptap.dev/api/extensions/dropcursor\n */\nexport const Dropcursor = Extension.create<DropcursorOptions>({\n name: 'dropCursor',\n\n addOptions() {\n return {\n color: 'currentColor',\n width: 1,\n class: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n return [dropCursor(this.options)]\n },\n})\n","import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\nexport interface FocusOptions {\n /**\n * The class name that should be added to the focused node.\n * @default 'has-focus'\n * @example 'is-focused'\n */\n className: string\n\n /**\n * The mode by which the focused node is determined.\n * - All: All nodes are marked as focused.\n * - Deepest: Only the deepest node is marked as focused.\n * - Shallowest: Only the shallowest node is marked as focused.\n *\n * @default 'all'\n * @example 'deepest'\n * @example 'shallowest'\n */\n mode: 'all' | 'deepest' | 'shallowest'\n}\n\n/**\n * This extension allows you to add a class to the focused node.\n * @see https://www.tiptap.dev/api/extensions/focus\n */\nexport const Focus = Extension.create<FocusOptions>({\n name: 'focus',\n\n addOptions() {\n return {\n className: 'has-focus',\n mode: 'all',\n }\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: new PluginKey('focus'),\n props: {\n decorations: ({ doc, selection }) => {\n const { isEditable, isFocused } = this.editor\n const { anchor } = selection\n const decorations: Decoration[] = []\n\n if (!isEditable || !isFocused) {\n return DecorationSet.create(doc, [])\n }\n\n // Maximum Levels\n let maxLevels = 0\n\n if (this.options.mode === 'deepest') {\n doc.descendants((node, pos) => {\n if (node.isText) {\n return\n }\n\n const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1\n\n if (!isCurrent) {\n return false\n }\n\n maxLevels += 1\n })\n }\n\n // Loop through current\n let currentLevel = 0\n\n doc.descendants((node, pos) => {\n if (node.isText) {\n return false\n }\n\n const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1\n\n if (!isCurrent) {\n return false\n }\n\n currentLevel += 1\n\n const outOfScope =\n (this.options.mode === 'deepest' && maxLevels - currentLevel > 0) ||\n (this.options.mode === 'shallowest' && currentLevel > 1)\n\n if (outOfScope) {\n return this.options.mode === 'deepest'\n }\n\n decorations.push(\n Decoration.node(pos, pos + node.nodeSize, {\n class: this.options.className,\n }),\n )\n })\n\n return DecorationSet.create(doc, decorations)\n },\n },\n }),\n ]\n },\n})\n","import type { ParentConfig } from '@tiptap/core'\nimport { callOrReturn, Extension, getExtensionField } from '@tiptap/core'\nimport { gapCursor } from '@tiptap/pm/gapcursor'\n\ndeclare module '@tiptap/core' {\n interface NodeConfig<Options, Storage> {\n /**\n * A function to determine whether the gap cursor is allowed at the current position. Must return `true` or `false`.\n * @default null\n */\n allowGapCursor?:\n | boolean\n | null\n | ((this: {\n name: string\n options: Options\n storage: Storage\n parent: ParentConfig<NodeConfig<Options>>['allowGapCursor']\n }) => boolean | null)\n }\n}\n\n/**\n * This extension allows you to add a gap cursor to your editor.\n * A gap cursor is a cursor that appears when you click on a place\n * where no content is present, for example inbetween nodes.\n * @see https://tiptap.dev/api/extensions/gapcursor\n */\nexport const Gapcursor = Extension.create({\n name: 'gapCursor',\n\n addProseMirrorPlugins() {\n return [gapCursor()]\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n }\n\n return {\n allowGapCursor: callOrReturn(getExtensionField(extension, 'allowGapCursor', context)) ?? null,\n }\n },\n})\n","import type { Editor } from '@tiptap/core'\nimport { Extension, isNodeEmpty } from '@tiptap/core'\nimport type { Node as ProsemirrorNode } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\n/**\n * The default data attribute label\n */\nconst DEFAULT_DATA_ATTRIBUTE = 'placeholder'\n\n/**\n * Prepares the placeholder attribute by ensuring it is properly formatted.\n * @param attr - The placeholder attribute string.\n * @returns The prepared placeholder attribute string.\n */\nexport function preparePlaceholderAttribute(attr: string): string {\n return (\n attr\n // replace whitespace with dashes\n .replace(/\\s+/g, '-')\n // replace non-alphanumeric characters\n // or special chars like $, %, &, etc.\n // but not dashes\n .replace(/[^a-zA-Z0-9-]/g, '')\n // and replace any numeric character at the start\n .replace(/^[0-9-]+/, '')\n // and finally replace any stray, leading dashes\n .replace(/^-+/, '')\n .toLowerCase()\n )\n}\n\nexport interface PlaceholderOptions {\n /**\n * **The class name for the empty editor**\n * @default 'is-editor-empty'\n */\n emptyEditorClass: string\n\n /**\n * **The class name for empty nodes**\n * @default 'is-empty'\n */\n emptyNodeClass: string\n\n /**\n * **The data-attribute used for the placeholder label**\n * Will be prepended with `data-` and converted to kebab-case and cleaned of special characters.\n * @default 'placeholder'\n */\n dataAttribute: string\n\n /**\n * **The placeholder content**\n *\n * You can use a function to return a dynamic placeholder or a string.\n * @default 'Write something …'\n */\n placeholder:\n | ((PlaceholderProps: { editor: Editor; node: ProsemirrorNode; pos: number; hasAnchor: boolean }) => string)\n | string\n\n /**\n * **Checks if the placeholder should be only shown when the editor is editable.**\n *\n * If true, the placeholder will only be shown when the editor is editable.\n * If false, the placeholder will always be shown.\n * @default true\n */\n showOnlyWhenEditable: boolean\n\n /**\n * **Checks if the placeholder should be only shown when the current node is empty.**\n *\n * If true, the placeholder will only be shown when the current node is empty.\n * If false, the placeholder will be shown when any node is empty.\n * @default true\n */\n showOnlyCurrent: boolean\n\n /**\n * **Controls if the placeholder should be shown for all descendents.**\n *\n * If true, the placeholder will be shown for all descendents.\n * If false, the placeholder will only be shown for the current node.\n * @default false\n */\n includeChildren: boolean\n}\n\n/**\n * This extension allows you to add a placeholder to your editor.\n * A placeholder is a text that appears when the editor or a node is empty.\n * @see https://www.tiptap.dev/api/extensions/placeholder\n */\nexport const Placeholder = Extension.create<PlaceholderOptions>({\n name: 'placeholder',\n\n addOptions() {\n return {\n emptyEditorClass: 'is-editor-empty',\n emptyNodeClass: 'is-empty',\n dataAttribute: DEFAULT_DATA_ATTRIBUTE,\n placeholder: 'Write something …',\n showOnlyWhenEditable: true,\n showOnlyCurrent: true,\n includeChildren: false,\n }\n },\n\n addProseMirrorPlugins() {\n const dataAttribute = this.options.dataAttribute\n ? `data-${preparePlaceholderAttribute(this.options.dataAttribute)}`\n : `data-${DEFAULT_DATA_ATTRIBUTE}`\n\n return [\n new Plugin({\n key: new PluginKey('placeholder'),\n props: {\n decorations: ({ doc, selection }) => {\n const active = this.editor.isEditable || !this.options.showOnlyWhenEditable\n const { anchor } = selection\n const decorations: Decoration[] = []\n\n if (!active) {\n return null\n }\n\n const isEmptyDoc = this.editor.isEmpty\n\n doc.descendants((node, pos) => {\n const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize\n const isEmpty = !node.isLeaf && isNodeEmpty(node)\n\n if (!node.type.isTextblock) {\n return this.options.includeChildren\n }\n\n if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {\n const classes = [this.options.emptyNodeClass]\n\n if (isEmptyDoc) {\n classes.push(this.options.emptyEditorClass)\n }\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n class: classes.join(' '),\n [dataAttribute]:\n typeof this.options.placeholder === 'function'\n ? this.options.placeholder({\n editor: this.editor,\n node,\n pos,\n hasAnchor,\n })\n : this.options.placeholder,\n })\n\n decorations.push(decoration)\n }\n\n return this.options.includeChildren\n })\n\n return DecorationSet.create(doc, decorations)\n },\n },\n }),\n ]\n },\n})\n","import { Extension, isNodeSelection } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\nexport type SelectionOptions = {\n /**\n * The class name that should be added to the selected text.\n * @default 'selection'\n * @example 'is-selected'\n */\n className: string\n}\n\n/**\n * This extension allows you to add a class to the selected text.\n * @see https://www.tiptap.dev/api/extensions/selection\n */\nexport const Selection = Extension.create<SelectionOptions>({\n name: 'selection',\n\n addOptions() {\n return {\n className: 'selection',\n }\n },\n\n addProseMirrorPlugins() {\n const { editor, options } = this\n\n return [\n new Plugin({\n key: new PluginKey('selection'),\n props: {\n decorations(state) {\n if (\n state.selection.empty ||\n editor.isFocused ||\n !editor.isEditable ||\n isNodeSelection(state.selection) ||\n editor.view.dragging\n ) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(state.selection.from, state.selection.to, {\n class: options.className,\n }),\n ])\n },\n },\n }),\n ]\n },\n})\n\nexport default Selection\n","import { Extension } from '@tiptap/core'\nimport type { Node, NodeType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\nexport const skipTrailingNodeMeta = 'skipTrailingNode'\n\nfunction nodeEqualsType({ types, node }: { types: NodeType | NodeType[]; node: Node | null | undefined }) {\n return (node && Array.isArray(types) && types.includes(node.type)) || node?.type === types\n}\n\n/**\n * Extension based on:\n * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js\n * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts\n */\n\nexport interface TrailingNodeOptions {\n /**\n * The node type that should be inserted at the end of the document.\n * @note the node will always be added to the `notAfter` lists to\n * prevent an infinite loop.\n * @default undefined\n */\n node?: string\n /**\n * The node types after which the trailing node should not be inserted.\n * @default ['paragraph']\n */\n notAfter?: string | string[]\n}\n\n/**\n * This extension allows you to add an extra node at the end of the document.\n * @see https://www.tiptap.dev/api/extensions/trailing-node\n */\nexport const TrailingNode = Extension.create<TrailingNodeOptions>({\n name: 'trailingNode',\n\n addOptions() {\n return {\n node: undefined,\n notAfter: [],\n }\n },\n\n addProseMirrorPlugins() {\n const plugin = new PluginKey(this.name)\n const defaultNode =\n this.options.node || this.editor.schema.topNodeType.contentMatch.defaultType?.name || 'paragraph'\n\n const disabledNodes = Object.entries(this.editor.schema.nodes)\n .map(([, value]) => value)\n .filter(node => (this.options.notAfter || []).concat(defaultNode).includes(node.name))\n\n return [\n new Plugin({\n key: plugin,\n appendTransaction: (transactions, __, state) => {\n const { doc, tr, schema } = state\n const shouldInsertNodeAtEnd = plugin.getState(state)\n const endPosition = doc.content.size\n const type = schema.nodes[defaultNode]\n\n if (transactions.some(transaction => transaction.getMeta(skipTrailingNodeMeta))) {\n return\n }\n\n if (!shouldInsertNodeAtEnd) {\n return\n }\n\n return tr.insert(endPosition, type.create())\n },\n state: {\n init: (_, state) => {\n const lastNode = state.tr.doc.lastChild\n\n return !nodeEqualsType({ node: lastNode, types: disabledNodes })\n },\n apply: (tr, value) => {\n if (!tr.docChanged) {\n return value\n }\n\n // Ignore transactions from UniqueID extension to prevent infinite loops\n // when UniqueID adds IDs to newly inserted trailing nodes\n if (tr.getMeta('__uniqueIDTransaction')) {\n return value\n }\n\n const lastNode = tr.doc.lastChild\n\n return !nodeEqualsType({ node: lastNode, types: disabledNodes })\n },\n },\n }),\n ]\n },\n})\n","import { Extension } from '@tiptap/core'\nimport { history, redo, undo } from '@tiptap/pm/history'\n\nexport interface UndoRedoOptions {\n /**\n * The amount of history events that are collected before the oldest events are discarded.\n * @default 100\n * @example 50\n */\n depth: number\n\n /**\n * The delay (in milliseconds) between changes after which a new group should be started.\n * @default 500\n * @example 1000\n */\n newGroupDelay: number\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n undoRedo: {\n /**\n * Undo recent changes\n * @example editor.commands.undo()\n */\n undo: () => ReturnType\n /**\n * Reapply reverted changes\n * @example editor.commands.redo()\n */\n redo: () => ReturnType\n }\n }\n}\n\n/**\n * This extension allows you to undo and redo recent changes.\n * @see https://www.tiptap.dev/api/extensions/undo-redo\n *\n * **Important**: If the `@tiptap/extension-collaboration` package is used, make sure to remove\n * the `undo-redo` extension, as it is not compatible with the `collaboration` extension.\n *\n * `@tiptap/extension-collaboration` uses its own history implementation.\n */\nexport const UndoRedo = Extension.create<UndoRedoOptions>({\n name: 'undoRedo',\n\n addOptions() {\n return {\n depth: 100,\n newGroupDelay: 500,\n }\n },\n\n addCommands() {\n return {\n undo:\n () =>\n ({ state, dispatch }) => {\n return undo(state, dispatch)\n },\n redo:\n () =>\n ({ state, dispatch }) => {\n return redo(state, dispatch)\n },\n }\n },\n\n addProseMirrorPlugins() {\n return [history(this.options)]\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-z': () => this.editor.commands.undo(),\n 'Shift-Mod-z': () => this.editor.commands.redo(),\n 'Mod-y': () => this.editor.commands.redo(),\n\n // Russian keyboard layouts\n 'Mod-я': () => this.editor.commands.undo(),\n 'Shift-Mod-я': () => this.editor.commands.redo(),\n }\n },\n})\n"],"mappings":"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","names":["import_core","import_core","import_state","import_core","import_core","import_state","import_view","import_core","import_state","import_view","import_core","import_state","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/character-count/character-count.ts","../src/drop-cursor/drop-cursor.ts","../src/focus/focus.ts","../src/gap-cursor/gap-cursor.ts","../src/placeholder/placeholder.ts","../src/placeholder/utils/createPlaceholderDecoration.ts","../src/placeholder/utils/findScrollParent.ts","../src/placeholder/utils/getViewportBoundaryPositions.ts","../src/placeholder/utils/throttle.ts","../src/selection/selection.ts","../src/trailing-node/trailing-node.ts","../src/undo-redo/undo-redo.ts"],"sourcesContent":["export * from './character-count/index.js'\nexport * from './drop-cursor/index.js'\nexport * from './focus/index.js'\nexport * from './gap-cursor/index.js'\nexport * from './placeholder/index.js'\nexport * from './selection/index.js'\nexport * from './trailing-node/index.js'\nexport * from './undo-redo/index.js'\n","import { Extension } from '@tiptap/core'\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\nexport interface CharacterCountOptions {\n /**\n * The maximum number of characters that should be allowed. Defaults to `0`.\n * @default null\n * @example 180\n */\n limit: number | null | undefined\n /**\n * The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.\n * If set to `nodeSize`, the nodeSize of the document is used.\n * @default 'textSize'\n * @example 'textSize'\n */\n mode: 'textSize' | 'nodeSize'\n /**\n * Sets whether the content will be automatically trimmed when programatically setting content over the limit.\n * If set to false, the user will be able to trim the text manually.\n * @default true\n * @example false\n */\n autoTrim?: boolean\n /**\n * The text counter function to use. Defaults to a simple character count.\n * @default (text) => text.length\n * @example (text) => [...new Intl.Segmenter().segment(text)].length\n */\n textCounter: (text: string) => number\n /**\n * The word counter function to use. Defaults to a simple word count.\n * @default (text) => text.split(' ').filter(word => word !== '').length\n * @example (text) => text.split(/\\s+/).filter(word => word !== '').length\n */\n wordCounter: (text: string) => number\n}\n\nexport interface CharacterCountStorage {\n /**\n * Get the number of characters for the current document.\n * @param options The options for the character count. (optional)\n * @param options.node The node to get the characters from. Defaults to the current document.\n * @param options.mode The mode by which the size is calculated. If set to `textSize`, the textContent of the document is used.\n */\n characters: (options?: { node?: ProseMirrorNode; mode?: 'textSize' | 'nodeSize' }) => number\n\n /**\n * Get the number of words for the current document.\n * @param options The options for the character count. (optional)\n * @param options.node The node to get the words from. Defaults to the current document.\n */\n words: (options?: { node?: ProseMirrorNode }) => number\n}\n\ndeclare module '@tiptap/core' {\n interface Storage {\n characterCount: CharacterCountStorage\n }\n}\n\n/**\n * This extension allows you to count the characters and words of your document.\n * @see https://tiptap.dev/api/extensions/character-count\n */\nexport const CharacterCount = Extension.create<CharacterCountOptions, CharacterCountStorage>({\n name: 'characterCount',\n\n addOptions() {\n return {\n limit: null,\n autoTrim: true,\n mode: 'textSize',\n textCounter: text => text.length,\n wordCounter: text => text.split(' ').filter(word => word !== '').length,\n }\n },\n\n addStorage() {\n return {\n characters: () => 0,\n words: () => 0,\n }\n },\n\n onBeforeCreate() {\n this.storage.characters = options => {\n const node = options?.node || this.editor.state.doc\n const mode = options?.mode || this.options.mode\n\n if (mode === 'textSize') {\n const text = node.textBetween(0, node.content.size, undefined, ' ')\n\n return this.options.textCounter(text)\n }\n\n return node.nodeSize\n }\n\n this.storage.words = options => {\n const node = options?.node || this.editor.state.doc\n const text = node.textBetween(0, node.content.size, ' ', ' ')\n\n return this.options.wordCounter(text)\n }\n },\n\n addProseMirrorPlugins() {\n let initialEvaluationDone = false\n\n return [\n new Plugin({\n key: new PluginKey('characterCount'),\n appendTransaction: (transactions, oldState, newState) => {\n if (initialEvaluationDone) {\n return\n }\n\n const limit = this.options.limit\n const autoTrim = this.options.autoTrim\n\n if (limit === null || limit === undefined || limit === 0 || autoTrim === false) {\n initialEvaluationDone = true\n return\n }\n\n const initialContentSize = this.storage.characters({ node: newState.doc })\n\n if (initialContentSize > limit) {\n const over = initialContentSize - limit\n const from = 0\n const to = over\n\n console.warn(\n `[CharacterCount] Initial content exceeded limit of ${limit} characters. Content was automatically trimmed.`,\n )\n const tr = newState.tr.deleteRange(from, to)\n initialEvaluationDone = true\n return tr\n }\n\n initialEvaluationDone = true\n },\n filterTransaction: (transaction, state) => {\n const limit = this.options.limit\n\n // Nothing has changed or no limit is defined. Ignore it.\n if (!transaction.docChanged || limit === 0 || limit === null || limit === undefined) {\n return true\n }\n\n const oldSize = this.storage.characters({ node: state.doc })\n const newSize = this.storage.characters({ node: transaction.doc })\n\n // Everything is in the limit. Good.\n if (newSize <= limit) {\n return true\n }\n\n // The limit has already been exceeded but will be reduced.\n if (oldSize > limit && newSize > limit && newSize <= oldSize) {\n return true\n }\n\n // The limit has already been exceeded and will be increased further.\n if (oldSize > limit && newSize > limit && newSize > oldSize) {\n return false\n }\n\n const isPaste = transaction.getMeta('paste')\n\n // Block all exceeding transactions that were not pasted.\n if (!isPaste) {\n return false\n }\n\n // For pasted content, we try to remove the exceeding content.\n const pos = transaction.selection.$head.pos\n const over = newSize - limit\n const from = pos - over\n const to = pos\n\n // It’s probably a bad idea to mutate transactions within `filterTransaction`\n // but for now this is working fine.\n transaction.deleteRange(from, to)\n\n // In some situations, the limit will continue to be exceeded after trimming.\n // This happens e.g. when truncating within a complex node (e.g. table)\n // and ProseMirror has to close this node again.\n // If this is the case, we prevent the transaction completely.\n const updatedSize = this.storage.characters({ node: transaction.doc })\n\n if (updatedSize > limit) {\n return false\n }\n\n return true\n },\n }),\n ]\n },\n})\n","import { Extension } from '@tiptap/core'\nimport { dropCursor } from '@tiptap/pm/dropcursor'\n\nexport interface DropcursorOptions {\n /**\n * The color of the drop cursor. Use `false` to apply no color and rely only on class.\n * @default 'currentColor'\n * @example 'red'\n */\n color?: string | false\n\n /**\n * The width of the drop cursor\n * @default 1\n * @example 2\n */\n width: number | undefined\n\n /**\n * The class of the drop cursor\n * @default undefined\n * @example 'drop-cursor'\n */\n class: string | undefined\n}\n\n/**\n * This extension allows you to add a drop cursor to your editor.\n * A drop cursor is a line that appears when you drag and drop content\n * in-between nodes.\n * @see https://tiptap.dev/api/extensions/dropcursor\n */\nexport const Dropcursor = Extension.create<DropcursorOptions>({\n name: 'dropCursor',\n\n addOptions() {\n return {\n color: 'currentColor',\n width: 1,\n class: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n return [dropCursor(this.options)]\n },\n})\n","import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\nexport interface FocusOptions {\n /**\n * The class name that should be added to the focused node.\n * @default 'has-focus'\n * @example 'is-focused'\n */\n className: string\n\n /**\n * The mode by which the focused node is determined.\n * - All: All nodes are marked as focused.\n * - Deepest: Only the deepest node is marked as focused.\n * - Shallowest: Only the shallowest node is marked as focused.\n *\n * @default 'all'\n * @example 'deepest'\n * @example 'shallowest'\n */\n mode: 'all' | 'deepest' | 'shallowest'\n}\n\n/**\n * This extension allows you to add a class to the focused node.\n * @see https://www.tiptap.dev/api/extensions/focus\n */\nexport const Focus = Extension.create<FocusOptions>({\n name: 'focus',\n\n addOptions() {\n return {\n className: 'has-focus',\n mode: 'all',\n }\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: new PluginKey('focus'),\n props: {\n decorations: ({ doc, selection }) => {\n const { isEditable, isFocused } = this.editor\n const { anchor } = selection\n const decorations: Decoration[] = []\n\n if (!isEditable || !isFocused) {\n return DecorationSet.create(doc, [])\n }\n\n // Maximum Levels\n let maxLevels = 0\n\n if (this.options.mode === 'deepest') {\n doc.descendants((node, pos) => {\n if (node.isText) {\n return\n }\n\n const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1\n\n if (!isCurrent) {\n return false\n }\n\n maxLevels += 1\n })\n }\n\n // Loop through current\n let currentLevel = 0\n\n doc.descendants((node, pos) => {\n if (node.isText) {\n return false\n }\n\n const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1\n\n if (!isCurrent) {\n return false\n }\n\n currentLevel += 1\n\n const outOfScope =\n (this.options.mode === 'deepest' && maxLevels - currentLevel > 0) ||\n (this.options.mode === 'shallowest' && currentLevel > 1)\n\n if (outOfScope) {\n return this.options.mode === 'deepest'\n }\n\n decorations.push(\n Decoration.node(pos, pos + node.nodeSize, {\n class: this.options.className,\n }),\n )\n })\n\n return DecorationSet.create(doc, decorations)\n },\n },\n }),\n ]\n },\n})\n","import type { ParentConfig } from '@tiptap/core'\nimport { callOrReturn, Extension, getExtensionField } from '@tiptap/core'\nimport { gapCursor } from '@tiptap/pm/gapcursor'\n\ndeclare module '@tiptap/core' {\n interface NodeConfig<Options, Storage> {\n /**\n * A function to determine whether the gap cursor is allowed at the current position. Must return `true` or `false`.\n * @default null\n */\n allowGapCursor?:\n | boolean\n | null\n | ((this: {\n name: string\n options: Options\n storage: Storage\n parent: ParentConfig<NodeConfig<Options>>['allowGapCursor']\n }) => boolean | null)\n }\n}\n\n/**\n * This extension allows you to add a gap cursor to your editor.\n * A gap cursor is a cursor that appears when you click on a place\n * where no content is present, for example inbetween nodes.\n * @see https://tiptap.dev/api/extensions/gapcursor\n */\nexport const Gapcursor = Extension.create({\n name: 'gapCursor',\n\n addProseMirrorPlugins() {\n return [gapCursor()]\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n }\n\n return {\n allowGapCursor: callOrReturn(getExtensionField(extension, 'allowGapCursor', context)) ?? null,\n }\n },\n})\n","import { Extension, isNodeEmpty } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { Decoration } from '@tiptap/pm/view'\nimport { DecorationSet } from '@tiptap/pm/view'\n\nimport type { PlaceholderOptions } from './types.js'\nimport { createPlaceholderDecoration } from './utils/createPlaceholderDecoration.js'\nimport { findScrollParent } from './utils/findScrollParent.js'\nimport { getViewportBoundaryPositions } from './utils/getViewportBoundaryPositions.js'\nimport { throttle } from './utils/throttle.js'\n\n/**\n * The default data attribute label\n */\nconst DEFAULT_DATA_ATTRIBUTE = 'placeholder'\n\n/**\n * Prepares the placeholder attribute by ensuring it is properly formatted.\n * @param attr - The placeholder attribute string.\n * @returns The prepared placeholder attribute string.\n */\nexport function preparePlaceholderAttribute(attr: string): string {\n return (\n attr\n // replace whitespace with dashes\n .replace(/\\s+/g, '-')\n // replace non-alphanumeric characters\n // or special chars like $, %, &, etc.\n // but not dashes\n .replace(/[^a-zA-Z0-9-]/g, '')\n // and replace any numeric character at the start\n .replace(/^[0-9-]+/, '')\n // and finally replace any stray, leading dashes\n .replace(/^-+/, '')\n .toLowerCase()\n )\n}\n\nexport const PLUGIN_KEY = new PluginKey('tiptap__placeholder')\n\n/**\n * This extension allows you to add a placeholder to your editor.\n * A placeholder is a text that appears when the editor or a node is empty.\n * @see https://www.tiptap.dev/api/extensions/placeholder\n */\nexport const Placeholder = Extension.create<PlaceholderOptions>({\n name: 'placeholder',\n\n addOptions() {\n return {\n emptyEditorClass: 'is-editor-empty',\n emptyNodeClass: 'is-empty',\n dataAttribute: DEFAULT_DATA_ATTRIBUTE,\n placeholder: 'Write something …',\n showOnlyWhenEditable: true,\n showOnlyCurrent: true,\n includeChildren: false,\n }\n },\n\n addProseMirrorPlugins() {\n const dataAttribute = this.options.dataAttribute\n ? `data-${preparePlaceholderAttribute(this.options.dataAttribute)}`\n : `data-${DEFAULT_DATA_ATTRIBUTE}`\n\n return [\n new Plugin({\n state: {\n init() {\n return {\n // null means \"no viewport info yet\" — decoration callback falls\n // back to full document scan until the scroll handler fires.\n topPos: null as number | null,\n bottomPos: null as number | null,\n }\n },\n apply(tr, prev) {\n const meta = tr.getMeta(PLUGIN_KEY) as { positions?: { top: number; bottom: number } } | undefined\n\n if (meta?.positions) {\n return {\n topPos: meta.positions.top,\n bottomPos: meta.positions.bottom,\n }\n }\n\n if (!tr.docChanged) {\n return prev\n }\n\n // Preserve last known viewport positions across transactions.\n // Without this, every keystroke resets back to a full document\n // scan, defeating the viewport optimisation.\n // Only map when we have actual positions — null means \"no viewport\n // info yet\" and should stay null to fall back to full doc scan.\n return {\n topPos: prev.topPos !== null ? tr.mapping.map(prev.topPos) : null,\n bottomPos: prev.bottomPos !== null ? tr.mapping.map(prev.bottomPos) : null,\n }\n },\n },\n key: PLUGIN_KEY,\n view(view) {\n const scrollContainer = findScrollParent(view.dom)\n\n const computeAndDispatch = () => {\n const positions = getViewportBoundaryPositions({\n view,\n doc: view.state.doc,\n scrollContainer,\n })\n\n const prev = PLUGIN_KEY.getState(view.state)\n if (prev.topPos === positions.top && prev.bottomPos === positions.bottom) {\n return\n }\n\n const tr = view.state.tr\n .setMeta(PLUGIN_KEY, { positions })\n // Flag this transaction so the update() method can detect\n // it and avoid re-entrant computation.\n .setMeta('tiptap__viewportUpdate', true)\n view.dispatch(tr)\n }\n\n const { call: throttledUpdate, cancel: cancelThrottle } = throttle(computeAndDispatch, 250)\n const scrollParent = scrollContainer\n\n scrollParent.addEventListener('scroll', throttledUpdate, { passive: true })\n\n // Fire once to populate initial viewport (bypass throttle)\n computeAndDispatch()\n\n return {\n update(_, prevState) {\n // Skip re-entry: the dispatch inside computeAndDispatch would\n // trigger this update again, but the doc didn't change so the\n // size guard catches that. The meta flag is an extra safeguard.\n if (view.state.doc.content.size !== prevState.doc.content.size) {\n computeAndDispatch()\n }\n },\n destroy: () => {\n cancelThrottle()\n scrollParent.removeEventListener('scroll', throttledUpdate)\n },\n }\n },\n props: {\n decorations: ({ doc, selection }) => {\n const active = this.editor.isEditable || !this.options.showOnlyWhenEditable\n\n if (!active) {\n return null\n }\n\n const { anchor } = selection\n const decorations: Decoration[] = []\n const isEmptyDoc = this.editor.isEmpty\n\n const useResolvedPath = this.options.showOnlyCurrent && !this.options.includeChildren\n\n if (useResolvedPath) {\n const resolved = doc.resolve(anchor)\n\n if (resolved.depth > 0) {\n const node = resolved.node(1)\n const nodeStart = resolved.before(1)\n\n if (node.type.isTextblock && isNodeEmpty(node)) {\n const hasAnchor = anchor >= nodeStart && anchor <= nodeStart + node.nodeSize\n const decoration = createPlaceholderDecoration({\n node,\n dataAttribute,\n hasAnchor,\n placeholder: this.options.placeholder,\n classes: {\n emptyEditor: this.options.emptyEditorClass,\n emptyNode: this.options.emptyNodeClass,\n },\n editor: this.editor,\n isEmptyDoc,\n pos: resolved.before(1),\n })\n\n decorations.push(decoration)\n }\n }\n } else {\n const pluginState = PLUGIN_KEY.getState(this.editor.state)\n const from = pluginState.topPos ?? 0\n const to = pluginState.bottomPos ?? doc.content.size\n\n doc.nodesBetween(from, to, (node, pos) => {\n const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize\n const isEmpty = !node.isLeaf && isNodeEmpty(node)\n\n if (!node.type.isTextblock) {\n return this.options.includeChildren\n }\n\n if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {\n const decoration = createPlaceholderDecoration({\n classes: { emptyEditor: this.options.emptyEditorClass, emptyNode: this.options.emptyNodeClass },\n editor: this.editor,\n isEmptyDoc,\n dataAttribute,\n hasAnchor,\n placeholder: this.options.placeholder,\n node,\n pos,\n })\n decorations.push(decoration)\n }\n\n return this.options.includeChildren\n })\n }\n\n return DecorationSet.create(doc, decorations)\n },\n },\n }),\n ]\n },\n})\n","import type { Editor } from '@tiptap/core'\nimport type { Node } from '@tiptap/pm/model'\nimport { Decoration } from '@tiptap/pm/view'\n\nimport type { PlaceholderOptions } from '../types.js'\n\n/**\n * Creates a ProseMirror node decoration that applies a placeholder\n * CSS class and data attribute to an empty node.\n * @param options.editor - The editor instance\n * @param options.pos - The position of the node in the document\n * @param options.node - The ProseMirror node\n * @param options.isEmptyDoc - Whether the entire document is empty\n * @param options.hasAnchor - Whether the selection anchor is within the node\n * @param options.dataAttribute - The data attribute name (e.g. `data-placeholder`)\n * @param options.classes - CSS classes for empty nodes and the empty editor\n * @param options.placeholder - The placeholder text or a function that returns it\n * @returns A ProseMirror node decoration with placeholder classes and data attribute\n */\nexport function createPlaceholderDecoration(options: {\n editor: Editor\n pos: number\n node: Node\n isEmptyDoc: boolean\n hasAnchor: boolean\n dataAttribute: string\n classes: {\n emptyEditor: PlaceholderOptions['emptyEditorClass']\n emptyNode: PlaceholderOptions['emptyNodeClass']\n }\n placeholder: PlaceholderOptions['placeholder']\n}) {\n const {\n editor,\n placeholder,\n dataAttribute,\n pos,\n node,\n isEmptyDoc,\n hasAnchor,\n classes: { emptyNode, emptyEditor },\n } = options\n const classes = [emptyNode]\n\n if (isEmptyDoc) {\n classes.push(emptyEditor)\n }\n\n return Decoration.node(pos, pos + node.nodeSize, {\n class: classes.join(' '),\n [dataAttribute]:\n typeof placeholder === 'function'\n ? placeholder({\n editor,\n node,\n pos,\n hasAnchor,\n })\n : placeholder,\n })\n}\n","/**\n * Checks if an element is scrollable by testing its overflow properties.\n * Elements with `overflow: hidden` or `overflow: clip` are intentionally\n * excluded — they clip content but don't emit scroll events.\n */\nfunction isScrollable(el: HTMLElement): boolean {\n const style = getComputedStyle(el)\n const overflow = `${style.overflow} ${style.overflowY} ${style.overflowX}`\n\n return /auto|scroll|overlay/.test(overflow)\n}\n\nexport function findScrollParent(element: HTMLElement): HTMLElement | Window {\n let el: HTMLElement | null = element\n\n while (el) {\n if (isScrollable(el)) {\n return el\n }\n\n // Check if we hit a Shadow DOM boundary. If so, jump to the shadow host\n // and continue traversing the light DOM.\n const parent = el.parentElement\n if (!parent) {\n const root = el.getRootNode()\n if (root instanceof ShadowRoot) {\n el = root.host as HTMLElement\n continue\n }\n\n return window\n }\n\n el = parent\n }\n\n return window\n}\n","import type { Node } from '@tiptap/pm/model'\nimport type { EditorView } from '@tiptap/pm/view'\n\nfunction getContainerRect(container: HTMLElement | Window): { top: number; bottom: number } {\n if (container === window) {\n return { top: 0, bottom: window.innerHeight }\n }\n\n return (container as HTMLElement).getBoundingClientRect()\n}\n\nexport function getViewportBoundaryPositions({\n doc,\n view,\n scrollContainer,\n}: {\n doc: Node\n view: EditorView\n scrollContainer?: HTMLElement | Window\n}) {\n const editorRect = view.dom.getBoundingClientRect()\n const containerRect = scrollContainer ? getContainerRect(scrollContainer) : { top: 0, bottom: window.innerHeight }\n\n const visibleTop = Math.max(editorRect.top, containerRect.top)\n const visibleBottom = Math.min(editorRect.bottom, containerRect.bottom)\n\n if (visibleTop >= visibleBottom) {\n // Editor is not visible — fall back to full document range\n return { top: 0, bottom: doc.content.size }\n }\n\n // Pick the x-coordinate based on text direction. In LTR the content\n // starts at the left edge; in RTL it starts at the right edge.\n // Clamp to ensure the coordinate stays inside the editor bounds.\n const isRTL = getComputedStyle(view.dom).direction === 'rtl'\n const x = isRTL ? Math.max(editorRect.right - 2, editorRect.left + 2) : editorRect.left + 2\n\n const topPos = view.posAtCoords({ left: x, top: visibleTop + 2 })\n const bottomPos = view.posAtCoords({ left: x, top: visibleBottom - 2 })\n\n return {\n top: topPos ? topPos.pos : 0,\n bottom: bottomPos ? bottomPos.pos : doc.content.size,\n }\n}\n","export function throttle<T extends (...args: any[]) => void>(fn: T, delay: number): { call: T; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const call = ((...args: any[]) => {\n if (timer) {\n return\n }\n\n // Leading-edge: fire immediately, then prevent subsequent calls\n // until the timer fires and resets.\n fn(...args)\n timer = setTimeout(() => {\n timer = null\n }, delay)\n }) as T\n\n const cancel = () => {\n if (timer) {\n clearTimeout(timer)\n timer = null\n }\n }\n\n return { call, cancel }\n}\n","import { Extension, isNodeSelection } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\nexport type SelectionOptions = {\n /**\n * The class name that should be added to the selected text.\n * @default 'selection'\n * @example 'is-selected'\n */\n className: string\n}\n\n/**\n * This extension allows you to add a class to the selected text.\n * @see https://www.tiptap.dev/api/extensions/selection\n */\nexport const Selection = Extension.create<SelectionOptions>({\n name: 'selection',\n\n addOptions() {\n return {\n className: 'selection',\n }\n },\n\n addProseMirrorPlugins() {\n const { editor, options } = this\n\n return [\n new Plugin({\n key: new PluginKey('selection'),\n props: {\n decorations(state) {\n if (\n state.selection.empty ||\n editor.isFocused ||\n !editor.isEditable ||\n isNodeSelection(state.selection) ||\n editor.view.dragging\n ) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(state.selection.from, state.selection.to, {\n class: options.className,\n }),\n ])\n },\n },\n }),\n ]\n },\n})\n\nexport default Selection\n","import { Extension } from '@tiptap/core'\nimport type { Node, NodeType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\nexport const skipTrailingNodeMeta = 'skipTrailingNode'\n\nfunction nodeEqualsType({ types, node }: { types: NodeType | NodeType[]; node: Node | null | undefined }) {\n return (node && Array.isArray(types) && types.includes(node.type)) || node?.type === types\n}\n\n/**\n * Extension based on:\n * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js\n * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts\n */\n\nexport interface TrailingNodeOptions {\n /**\n * The node type that should be inserted at the end of the document.\n * @note the node will always be added to the `notAfter` lists to\n * prevent an infinite loop.\n * @default undefined\n */\n node?: string\n /**\n * The node types after which the trailing node should not be inserted.\n * @default ['paragraph']\n */\n notAfter?: string | string[]\n}\n\n/**\n * This extension allows you to add an extra node at the end of the document.\n * @see https://www.tiptap.dev/api/extensions/trailing-node\n */\nexport const TrailingNode = Extension.create<TrailingNodeOptions>({\n name: 'trailingNode',\n\n addOptions() {\n return {\n node: undefined,\n notAfter: [],\n }\n },\n\n addProseMirrorPlugins() {\n const plugin = new PluginKey(this.name)\n const defaultNode =\n this.options.node || this.editor.schema.topNodeType.contentMatch.defaultType?.name || 'paragraph'\n\n const disabledNodes = Object.entries(this.editor.schema.nodes)\n .map(([, value]) => value)\n .filter(node => (this.options.notAfter || []).concat(defaultNode).includes(node.name))\n\n return [\n new Plugin({\n key: plugin,\n appendTransaction: (transactions, __, state) => {\n const { doc, tr, schema } = state\n const shouldInsertNodeAtEnd = plugin.getState(state)\n const endPosition = doc.content.size\n const type = schema.nodes[defaultNode]\n\n if (transactions.some(transaction => transaction.getMeta(skipTrailingNodeMeta))) {\n return\n }\n\n if (!shouldInsertNodeAtEnd) {\n return\n }\n\n return tr.insert(endPosition, type.create())\n },\n state: {\n init: (_, state) => {\n const lastNode = state.tr.doc.lastChild\n\n return !nodeEqualsType({ node: lastNode, types: disabledNodes })\n },\n apply: (tr, value) => {\n if (!tr.docChanged) {\n return value\n }\n\n // Ignore transactions from UniqueID extension to prevent infinite loops\n // when UniqueID adds IDs to newly inserted trailing nodes\n if (tr.getMeta('__uniqueIDTransaction')) {\n return value\n }\n\n const lastNode = tr.doc.lastChild\n\n return !nodeEqualsType({ node: lastNode, types: disabledNodes })\n },\n },\n }),\n ]\n },\n})\n","import { Extension } from '@tiptap/core'\nimport { history, redo, undo } from '@tiptap/pm/history'\n\nexport interface UndoRedoOptions {\n /**\n * The amount of history events that are collected before the oldest events are discarded.\n * @default 100\n * @example 50\n */\n depth: number\n\n /**\n * The delay (in milliseconds) between changes after which a new group should be started.\n * @default 500\n * @example 1000\n */\n newGroupDelay: number\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n undoRedo: {\n /**\n * Undo recent changes\n * @example editor.commands.undo()\n */\n undo: () => ReturnType\n /**\n * Reapply reverted changes\n * @example editor.commands.redo()\n */\n redo: () => ReturnType\n }\n }\n}\n\n/**\n * This extension allows you to undo and redo recent changes.\n * @see https://www.tiptap.dev/api/extensions/undo-redo\n *\n * **Important**: If the `@tiptap/extension-collaboration` package is used, make sure to remove\n * the `undo-redo` extension, as it is not compatible with the `collaboration` extension.\n *\n * `@tiptap/extension-collaboration` uses its own history implementation.\n */\nexport const UndoRedo = Extension.create<UndoRedoOptions>({\n name: 'undoRedo',\n\n addOptions() {\n return {\n depth: 100,\n newGroupDelay: 500,\n }\n },\n\n addCommands() {\n return {\n undo:\n () =>\n ({ state, dispatch }) => {\n return undo(state, dispatch)\n },\n redo:\n () =>\n ({ state, dispatch }) => {\n return redo(state, dispatch)\n },\n }\n },\n\n addProseMirrorPlugins() {\n return [history(this.options)]\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-z': () => this.editor.commands.undo(),\n 'Shift-Mod-z': () => this.editor.commands.redo(),\n 'Mod-y': () => this.editor.commands.redo(),\n\n // Russian keyboard layouts\n 'Mod-я': () => this.editor.commands.undo(),\n 'Shift-Mod-я': () => this.editor.commands.redo(),\n }\n },\n})\n"],"mappings":"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","names":["import_core","import_core","import_state","import_core","import_core","import_state","import_view","import_view","import_core","import_state","import_view","import_core","import_state","import_core"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Extension, ParentConfig, Editor } from '@tiptap/core';
|
|
2
2
|
import { Node } from '@tiptap/pm/model';
|
|
3
|
+
import { PluginKey } from '@tiptap/pm/state';
|
|
3
4
|
|
|
4
5
|
interface CharacterCountOptions {
|
|
5
6
|
/**
|
|
@@ -141,12 +142,6 @@ declare module '@tiptap/core' {
|
|
|
141
142
|
*/
|
|
142
143
|
declare const Gapcursor: Extension<any, any>;
|
|
143
144
|
|
|
144
|
-
/**
|
|
145
|
-
* Prepares the placeholder attribute by ensuring it is properly formatted.
|
|
146
|
-
* @param attr - The placeholder attribute string.
|
|
147
|
-
* @returns The prepared placeholder attribute string.
|
|
148
|
-
*/
|
|
149
|
-
declare function preparePlaceholderAttribute(attr: string): string;
|
|
150
145
|
interface PlaceholderOptions {
|
|
151
146
|
/**
|
|
152
147
|
* **The class name for the empty editor**
|
|
@@ -193,14 +188,22 @@ interface PlaceholderOptions {
|
|
|
193
188
|
*/
|
|
194
189
|
showOnlyCurrent: boolean;
|
|
195
190
|
/**
|
|
196
|
-
* **Controls if the placeholder should be shown for all
|
|
191
|
+
* **Controls if the placeholder should be shown for all descendants.**
|
|
197
192
|
*
|
|
198
|
-
* If true, the placeholder will be shown for all
|
|
193
|
+
* If true, the placeholder will be shown for all descendants.
|
|
199
194
|
* If false, the placeholder will only be shown for the current node.
|
|
200
195
|
* @default false
|
|
201
196
|
*/
|
|
202
197
|
includeChildren: boolean;
|
|
203
198
|
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Prepares the placeholder attribute by ensuring it is properly formatted.
|
|
202
|
+
* @param attr - The placeholder attribute string.
|
|
203
|
+
* @returns The prepared placeholder attribute string.
|
|
204
|
+
*/
|
|
205
|
+
declare function preparePlaceholderAttribute(attr: string): string;
|
|
206
|
+
declare const PLUGIN_KEY: PluginKey<any>;
|
|
204
207
|
/**
|
|
205
208
|
* This extension allows you to add a placeholder to your editor.
|
|
206
209
|
* A placeholder is a text that appears when the editor or a node is empty.
|
|
@@ -289,4 +292,4 @@ declare module '@tiptap/core' {
|
|
|
289
292
|
*/
|
|
290
293
|
declare const UndoRedo: Extension<UndoRedoOptions, any>;
|
|
291
294
|
|
|
292
|
-
export { CharacterCount, type CharacterCountOptions, type CharacterCountStorage, Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, Placeholder, type PlaceholderOptions, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions, UndoRedo, type UndoRedoOptions, preparePlaceholderAttribute, skipTrailingNodeMeta };
|
|
295
|
+
export { CharacterCount, type CharacterCountOptions, type CharacterCountStorage, Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, PLUGIN_KEY, Placeholder, type PlaceholderOptions, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions, UndoRedo, type UndoRedoOptions, preparePlaceholderAttribute, skipTrailingNodeMeta };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Extension, ParentConfig, Editor } from '@tiptap/core';
|
|
2
2
|
import { Node } from '@tiptap/pm/model';
|
|
3
|
+
import { PluginKey } from '@tiptap/pm/state';
|
|
3
4
|
|
|
4
5
|
interface CharacterCountOptions {
|
|
5
6
|
/**
|
|
@@ -141,12 +142,6 @@ declare module '@tiptap/core' {
|
|
|
141
142
|
*/
|
|
142
143
|
declare const Gapcursor: Extension<any, any>;
|
|
143
144
|
|
|
144
|
-
/**
|
|
145
|
-
* Prepares the placeholder attribute by ensuring it is properly formatted.
|
|
146
|
-
* @param attr - The placeholder attribute string.
|
|
147
|
-
* @returns The prepared placeholder attribute string.
|
|
148
|
-
*/
|
|
149
|
-
declare function preparePlaceholderAttribute(attr: string): string;
|
|
150
145
|
interface PlaceholderOptions {
|
|
151
146
|
/**
|
|
152
147
|
* **The class name for the empty editor**
|
|
@@ -193,14 +188,22 @@ interface PlaceholderOptions {
|
|
|
193
188
|
*/
|
|
194
189
|
showOnlyCurrent: boolean;
|
|
195
190
|
/**
|
|
196
|
-
* **Controls if the placeholder should be shown for all
|
|
191
|
+
* **Controls if the placeholder should be shown for all descendants.**
|
|
197
192
|
*
|
|
198
|
-
* If true, the placeholder will be shown for all
|
|
193
|
+
* If true, the placeholder will be shown for all descendants.
|
|
199
194
|
* If false, the placeholder will only be shown for the current node.
|
|
200
195
|
* @default false
|
|
201
196
|
*/
|
|
202
197
|
includeChildren: boolean;
|
|
203
198
|
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Prepares the placeholder attribute by ensuring it is properly formatted.
|
|
202
|
+
* @param attr - The placeholder attribute string.
|
|
203
|
+
* @returns The prepared placeholder attribute string.
|
|
204
|
+
*/
|
|
205
|
+
declare function preparePlaceholderAttribute(attr: string): string;
|
|
206
|
+
declare const PLUGIN_KEY: PluginKey<any>;
|
|
204
207
|
/**
|
|
205
208
|
* This extension allows you to add a placeholder to your editor.
|
|
206
209
|
* A placeholder is a text that appears when the editor or a node is empty.
|
|
@@ -289,4 +292,4 @@ declare module '@tiptap/core' {
|
|
|
289
292
|
*/
|
|
290
293
|
declare const UndoRedo: Extension<UndoRedoOptions, any>;
|
|
291
294
|
|
|
292
|
-
export { CharacterCount, type CharacterCountOptions, type CharacterCountStorage, Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, Placeholder, type PlaceholderOptions, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions, UndoRedo, type UndoRedoOptions, preparePlaceholderAttribute, skipTrailingNodeMeta };
|
|
295
|
+
export { CharacterCount, type CharacterCountOptions, type CharacterCountStorage, Dropcursor, type DropcursorOptions, Focus, type FocusOptions, Gapcursor, PLUGIN_KEY, Placeholder, type PlaceholderOptions, Selection, type SelectionOptions, TrailingNode, type TrailingNodeOptions, UndoRedo, type UndoRedoOptions, preparePlaceholderAttribute, skipTrailingNodeMeta };
|