@tiptap/core 3.22.0 → 3.22.2

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 CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  Tracker: () => Tracker,
39
39
  callOrReturn: () => callOrReturn,
40
40
  canInsertNode: () => canInsertNode,
41
+ cancelPositionCheck: () => cancelPositionCheck,
41
42
  combineTransactionSteps: () => combineTransactionSteps,
42
43
  commands: () => commands_exports,
43
44
  createAtomBlockMarkdownSpec: () => createAtomBlockMarkdownSpec,
@@ -132,6 +133,7 @@ __export(index_exports, {
132
133
  resolveExtensions: () => resolveExtensions,
133
134
  resolveFocusPosition: () => resolveFocusPosition,
134
135
  rewriteUnknownContent: () => rewriteUnknownContent,
136
+ schedulePositionCheck: () => schedulePositionCheck,
135
137
  selectionToInsertionEnd: () => selectionToInsertionEnd,
136
138
  serializeAttributes: () => serializeAttributes,
137
139
  sortExtensions: () => sortExtensions,
@@ -2791,6 +2793,7 @@ var splitListItem = (typeOrName, overrideAttrs = {}) => ({ tr, state, dispatch,
2791
2793
  };
2792
2794
 
2793
2795
  // src/commands/toggleList.ts
2796
+ var import_state12 = require("@tiptap/pm/state");
2794
2797
  var import_transform8 = require("@tiptap/pm/transform");
2795
2798
  var joinListBackwards = (tr, listType) => {
2796
2799
  const list = findParentNode((node) => node.type === listType)(tr.selection);
@@ -2826,6 +2829,16 @@ var joinListForwards = (tr, listType) => {
2826
2829
  tr.join(after);
2827
2830
  return true;
2828
2831
  };
2832
+ function createInnerSelectionForWholeDocList(tr) {
2833
+ const doc = tr.doc;
2834
+ const list = doc.firstChild;
2835
+ if (!list) {
2836
+ return null;
2837
+ }
2838
+ const from = 1;
2839
+ const to = list.nodeSize - 1;
2840
+ return import_state12.TextSelection.create(doc, from, to);
2841
+ }
2829
2842
  var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({ editor, tr, state, dispatch, chain, commands, can }) => {
2830
2843
  const { extensions, splittableMarks } = editor.extensionManager;
2831
2844
  const listType = getNodeType(listTypeOrName, state.schema);
@@ -2838,13 +2851,37 @@ var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) =>
2838
2851
  return false;
2839
2852
  }
2840
2853
  const parentList = findParentNode((node) => isList(node.type.name, extensions))(selection);
2841
- if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
2842
- if (parentList.node.type === listType) {
2854
+ const isAllSelection = selection.from === 0 && selection.to === state.doc.content.size;
2855
+ const topLevelNodes = state.doc.content.content;
2856
+ const soleTopLevelNode = topLevelNodes.length === 1 ? topLevelNodes[0] : null;
2857
+ const allSelectionList = isAllSelection && soleTopLevelNode && isList(soleTopLevelNode.type.name, extensions) ? {
2858
+ node: soleTopLevelNode,
2859
+ pos: 0,
2860
+ depth: 0
2861
+ } : null;
2862
+ const currentList = parentList != null ? parentList : allSelectionList;
2863
+ const isInsideExistingList = !!parentList && range.depth >= 1 && range.depth - parentList.depth <= 1;
2864
+ const hasWholeDocSelectedList = !!allSelectionList;
2865
+ if ((isInsideExistingList || hasWholeDocSelectedList) && currentList) {
2866
+ if (currentList.node.type === listType) {
2867
+ if (isAllSelection && hasWholeDocSelectedList) {
2868
+ return chain().command(({ tr: trx, dispatch: disp }) => {
2869
+ const nextSelection = createInnerSelectionForWholeDocList(trx);
2870
+ if (!nextSelection) {
2871
+ return false;
2872
+ }
2873
+ trx.setSelection(nextSelection);
2874
+ if (disp) {
2875
+ disp(trx);
2876
+ }
2877
+ return true;
2878
+ }).liftListItem(itemType).run();
2879
+ }
2843
2880
  return commands.liftListItem(itemType);
2844
2881
  }
2845
- if (isList(parentList.node.type.name, extensions) && listType.validContent(parentList.node.content) && dispatch) {
2882
+ if (isList(currentList.node.type.name, extensions) && listType.validContent(currentList.node.content)) {
2846
2883
  return chain().command(() => {
2847
- tr.setNodeMarkup(parentList.pos, listType);
2884
+ tr.setNodeMarkup(currentList.pos, listType);
2848
2885
  return true;
2849
2886
  }).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
2850
2887
  }
@@ -3119,7 +3156,7 @@ var wrapInList = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
3119
3156
  };
3120
3157
 
3121
3158
  // src/Editor.ts
3122
- var import_state22 = require("@tiptap/pm/state");
3159
+ var import_state23 = require("@tiptap/pm/state");
3123
3160
  var import_view = require("@tiptap/pm/view");
3124
3161
 
3125
3162
  // src/EventEmitter.ts
@@ -3169,7 +3206,7 @@ var import_keymap = require("@tiptap/pm/keymap");
3169
3206
 
3170
3207
  // src/InputRule.ts
3171
3208
  var import_model9 = require("@tiptap/pm/model");
3172
- var import_state12 = require("@tiptap/pm/state");
3209
+ var import_state13 = require("@tiptap/pm/state");
3173
3210
  var InputRule = class {
3174
3211
  constructor(config) {
3175
3212
  var _a;
@@ -3262,7 +3299,7 @@ function run(config) {
3262
3299
  }
3263
3300
  function inputRulesPlugin(props) {
3264
3301
  const { editor, rules } = props;
3265
- const plugin = new import_state12.Plugin({
3302
+ const plugin = new import_state13.Plugin({
3266
3303
  state: {
3267
3304
  init() {
3268
3305
  return null;
@@ -3478,7 +3515,7 @@ var Mark = class _Mark extends Extendable {
3478
3515
 
3479
3516
  // src/PasteRule.ts
3480
3517
  var import_model10 = require("@tiptap/pm/model");
3481
- var import_state13 = require("@tiptap/pm/state");
3518
+ var import_state14 = require("@tiptap/pm/state");
3482
3519
 
3483
3520
  // src/utilities/isNumber.ts
3484
3521
  function isNumber(value) {
@@ -3614,7 +3651,7 @@ function pasteRulesPlugin(props) {
3614
3651
  return tr;
3615
3652
  };
3616
3653
  const plugins = rules.map((rule) => {
3617
- return new import_state13.Plugin({
3654
+ return new import_state14.Plugin({
3618
3655
  // we register a global drag handler to track the current drag source element
3619
3656
  view(view) {
3620
3657
  const handleDragstart = (event) => {
@@ -4045,7 +4082,7 @@ __export(extensions_exports, {
4045
4082
  });
4046
4083
 
4047
4084
  // src/extensions/clipboardTextSerializer.ts
4048
- var import_state14 = require("@tiptap/pm/state");
4085
+ var import_state15 = require("@tiptap/pm/state");
4049
4086
 
4050
4087
  // src/Extension.ts
4051
4088
  var Extension = class _Extension extends Extendable {
@@ -4080,8 +4117,8 @@ var ClipboardTextSerializer = Extension.create({
4080
4117
  },
4081
4118
  addProseMirrorPlugins() {
4082
4119
  return [
4083
- new import_state14.Plugin({
4084
- key: new import_state14.PluginKey("clipboardTextSerializer"),
4120
+ new import_state15.Plugin({
4121
+ key: new import_state15.PluginKey("clipboardTextSerializer"),
4085
4122
  props: {
4086
4123
  clipboardTextSerializer: () => {
4087
4124
  const { editor } = this;
@@ -4188,13 +4225,13 @@ var Delete = Extension.create({
4188
4225
  });
4189
4226
 
4190
4227
  // src/extensions/drop.ts
4191
- var import_state15 = require("@tiptap/pm/state");
4228
+ var import_state16 = require("@tiptap/pm/state");
4192
4229
  var Drop = Extension.create({
4193
4230
  name: "drop",
4194
4231
  addProseMirrorPlugins() {
4195
4232
  return [
4196
- new import_state15.Plugin({
4197
- key: new import_state15.PluginKey("tiptapDrop"),
4233
+ new import_state16.Plugin({
4234
+ key: new import_state16.PluginKey("tiptapDrop"),
4198
4235
  props: {
4199
4236
  handleDrop: (_, e, slice, moved) => {
4200
4237
  this.editor.emit("drop", {
@@ -4211,13 +4248,13 @@ var Drop = Extension.create({
4211
4248
  });
4212
4249
 
4213
4250
  // src/extensions/editable.ts
4214
- var import_state16 = require("@tiptap/pm/state");
4251
+ var import_state17 = require("@tiptap/pm/state");
4215
4252
  var Editable = Extension.create({
4216
4253
  name: "editable",
4217
4254
  addProseMirrorPlugins() {
4218
4255
  return [
4219
- new import_state16.Plugin({
4220
- key: new import_state16.PluginKey("editable"),
4256
+ new import_state17.Plugin({
4257
+ key: new import_state17.PluginKey("editable"),
4221
4258
  props: {
4222
4259
  editable: () => this.editor.options.editable
4223
4260
  }
@@ -4227,14 +4264,14 @@ var Editable = Extension.create({
4227
4264
  });
4228
4265
 
4229
4266
  // src/extensions/focusEvents.ts
4230
- var import_state17 = require("@tiptap/pm/state");
4231
- var focusEventsPluginKey = new import_state17.PluginKey("focusEvents");
4267
+ var import_state18 = require("@tiptap/pm/state");
4268
+ var focusEventsPluginKey = new import_state18.PluginKey("focusEvents");
4232
4269
  var FocusEvents = Extension.create({
4233
4270
  name: "focusEvents",
4234
4271
  addProseMirrorPlugins() {
4235
4272
  const { editor } = this;
4236
4273
  return [
4237
- new import_state17.Plugin({
4274
+ new import_state18.Plugin({
4238
4275
  key: focusEventsPluginKey,
4239
4276
  props: {
4240
4277
  handleDOMEvents: {
@@ -4258,7 +4295,7 @@ var FocusEvents = Extension.create({
4258
4295
  });
4259
4296
 
4260
4297
  // src/extensions/keymap.ts
4261
- var import_state18 = require("@tiptap/pm/state");
4298
+ var import_state19 = require("@tiptap/pm/state");
4262
4299
  var Keymap = Extension.create({
4263
4300
  name: "keymap",
4264
4301
  addKeyboardShortcuts() {
@@ -4272,7 +4309,7 @@ var Keymap = Extension.create({
4272
4309
  const $parentPos = $anchor.parent.isTextblock && pos > 0 ? tr.doc.resolve(pos - 1) : $anchor;
4273
4310
  const parentIsIsolating = $parentPos.parent.type.spec.isolating;
4274
4311
  const parentPos = $anchor.pos - $anchor.parentOffset;
4275
- const isAtStart = parentIsIsolating && $parentPos.parent.childCount === 1 ? parentPos === $anchor.pos : import_state18.Selection.atStart(doc).from === pos;
4312
+ const isAtStart = parentIsIsolating && $parentPos.parent.childCount === 1 ? parentPos === $anchor.pos : import_state19.Selection.atStart(doc).from === pos;
4276
4313
  if (!empty || !parent.type.isTextblock || parent.textContent.length || !isAtStart || isAtStart && $anchor.parent.type.name === "paragraph") {
4277
4314
  return false;
4278
4315
  }
@@ -4330,8 +4367,8 @@ var Keymap = Extension.create({
4330
4367
  // to a paragraph if necessary.
4331
4368
  // This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
4332
4369
  // with many other commands.
4333
- new import_state18.Plugin({
4334
- key: new import_state18.PluginKey("clearDocument"),
4370
+ new import_state19.Plugin({
4371
+ key: new import_state19.PluginKey("clearDocument"),
4335
4372
  appendTransaction: (transactions, oldState, newState) => {
4336
4373
  if (transactions.some((tr2) => tr2.getMeta("composition"))) {
4337
4374
  return;
@@ -4342,8 +4379,8 @@ var Keymap = Extension.create({
4342
4379
  return;
4343
4380
  }
4344
4381
  const { empty, from, to } = oldState.selection;
4345
- const allFrom = import_state18.Selection.atStart(oldState.doc).from;
4346
- const allEnd = import_state18.Selection.atEnd(oldState.doc).to;
4382
+ const allFrom = import_state19.Selection.atStart(oldState.doc).from;
4383
+ const allEnd = import_state19.Selection.atEnd(oldState.doc).to;
4347
4384
  const allWasSelected = from === allFrom && to === allEnd;
4348
4385
  if (empty || !allWasSelected) {
4349
4386
  return;
@@ -4373,13 +4410,13 @@ var Keymap = Extension.create({
4373
4410
  });
4374
4411
 
4375
4412
  // src/extensions/paste.ts
4376
- var import_state19 = require("@tiptap/pm/state");
4413
+ var import_state20 = require("@tiptap/pm/state");
4377
4414
  var Paste = Extension.create({
4378
4415
  name: "paste",
4379
4416
  addProseMirrorPlugins() {
4380
4417
  return [
4381
- new import_state19.Plugin({
4382
- key: new import_state19.PluginKey("tiptapPaste"),
4418
+ new import_state20.Plugin({
4419
+ key: new import_state20.PluginKey("tiptapPaste"),
4383
4420
  props: {
4384
4421
  handlePaste: (_view, e, slice) => {
4385
4422
  this.editor.emit("paste", {
@@ -4395,13 +4432,13 @@ var Paste = Extension.create({
4395
4432
  });
4396
4433
 
4397
4434
  // src/extensions/tabindex.ts
4398
- var import_state20 = require("@tiptap/pm/state");
4435
+ var import_state21 = require("@tiptap/pm/state");
4399
4436
  var Tabindex = Extension.create({
4400
4437
  name: "tabindex",
4401
4438
  addProseMirrorPlugins() {
4402
4439
  return [
4403
- new import_state20.Plugin({
4404
- key: new import_state20.PluginKey("tabindex"),
4440
+ new import_state21.Plugin({
4441
+ key: new import_state21.PluginKey("tabindex"),
4405
4442
  props: {
4406
4443
  attributes: () => this.editor.isEditable ? { tabindex: "0" } : {}
4407
4444
  }
@@ -4411,7 +4448,7 @@ var Tabindex = Extension.create({
4411
4448
  });
4412
4449
 
4413
4450
  // src/extensions/textDirection.ts
4414
- var import_state21 = require("@tiptap/pm/state");
4451
+ var import_state22 = require("@tiptap/pm/state");
4415
4452
  var TextDirection = Extension.create({
4416
4453
  name: "textDirection",
4417
4454
  addOptions() {
@@ -4452,8 +4489,8 @@ var TextDirection = Extension.create({
4452
4489
  },
4453
4490
  addProseMirrorPlugins() {
4454
4491
  return [
4455
- new import_state21.Plugin({
4456
- key: new import_state21.PluginKey("textDirection"),
4492
+ new import_state22.Plugin({
4493
+ key: new import_state22.PluginKey("textDirection"),
4457
4494
  props: {
4458
4495
  attributes: () => {
4459
4496
  const direction = this.options.direction;
@@ -4819,7 +4856,7 @@ var Editor = class extends EventEmitter {
4819
4856
  this.on("delete", this.options.onDelete);
4820
4857
  const initialDoc = this.createDoc();
4821
4858
  const selection = resolveFocusPosition(initialDoc, this.options.autofocus);
4822
- this.editorState = import_state22.EditorState.create({
4859
+ this.editorState = import_state23.EditorState.create({
4823
4860
  doc: initialDoc,
4824
4861
  schema: this.schema,
4825
4862
  selection: selection || void 0
@@ -6054,11 +6091,11 @@ var ResizableNodeView = class {
6054
6091
  var ResizableNodeview = ResizableNodeView;
6055
6092
 
6056
6093
  // src/utilities/canInsertNode.ts
6057
- var import_state23 = require("@tiptap/pm/state");
6094
+ var import_state24 = require("@tiptap/pm/state");
6058
6095
  function canInsertNode(state, nodeType) {
6059
6096
  const { selection } = state;
6060
6097
  const { $from } = selection;
6061
- if (selection instanceof import_state23.NodeSelection) {
6098
+ if (selection instanceof import_state24.NodeSelection) {
6062
6099
  const index = $from.index();
6063
6100
  const parent = $from.parent;
6064
6101
  return parent.canReplaceWith(index, index + 1, nodeType);
@@ -6592,6 +6629,45 @@ ${indentedChild}`;
6592
6629
  return output;
6593
6630
  }
6594
6631
 
6632
+ // src/utilities/nodeViewPositionRegistry.ts
6633
+ var positionUpdateRegistries = /* @__PURE__ */ new WeakMap();
6634
+ function schedulePositionCheck(editor, callback) {
6635
+ let registry = positionUpdateRegistries.get(editor);
6636
+ if (!registry) {
6637
+ const newRegistry = {
6638
+ callbacks: /* @__PURE__ */ new Set(),
6639
+ rafId: null,
6640
+ handler: () => {
6641
+ if (newRegistry.rafId !== null) {
6642
+ cancelAnimationFrame(newRegistry.rafId);
6643
+ }
6644
+ newRegistry.rafId = requestAnimationFrame(() => {
6645
+ newRegistry.rafId = null;
6646
+ newRegistry.callbacks.forEach((cb) => cb());
6647
+ });
6648
+ }
6649
+ };
6650
+ positionUpdateRegistries.set(editor, newRegistry);
6651
+ editor.on("update", newRegistry.handler);
6652
+ registry = newRegistry;
6653
+ }
6654
+ registry.callbacks.add(callback);
6655
+ }
6656
+ function cancelPositionCheck(editor, callback) {
6657
+ const registry = positionUpdateRegistries.get(editor);
6658
+ if (!registry) {
6659
+ return;
6660
+ }
6661
+ registry.callbacks.delete(callback);
6662
+ if (registry.callbacks.size === 0) {
6663
+ if (registry.rafId !== null) {
6664
+ cancelAnimationFrame(registry.rafId);
6665
+ }
6666
+ editor.off("update", registry.handler);
6667
+ positionUpdateRegistries.delete(editor);
6668
+ }
6669
+ }
6670
+
6595
6671
  // src/MarkView.ts
6596
6672
  function updateMarkViewAttributes(checkMark, editor, attrs = {}) {
6597
6673
  const { state } = editor;
@@ -6700,7 +6776,7 @@ var Node3 = class _Node extends Extendable {
6700
6776
  };
6701
6777
 
6702
6778
  // src/NodeView.ts
6703
- var import_state24 = require("@tiptap/pm/state");
6779
+ var import_state25 = require("@tiptap/pm/state");
6704
6780
  var NodeView = class {
6705
6781
  constructor(component, props, options) {
6706
6782
  this.isDragging = false;
@@ -6780,7 +6856,7 @@ var NodeView = class {
6780
6856
  if (typeof pos !== "number") {
6781
6857
  return;
6782
6858
  }
6783
- const selection = import_state24.NodeSelection.create(view.state.doc, pos);
6859
+ const selection = import_state25.NodeSelection.create(view.state.doc, pos);
6784
6860
  const transaction = view.state.tr.setSelection(selection);
6785
6861
  view.dispatch(transaction);
6786
6862
  }
@@ -6798,6 +6874,7 @@ var NodeView = class {
6798
6874
  return false;
6799
6875
  }
6800
6876
  const isDragEvent = event.type.startsWith("drag");
6877
+ const isDragOverEnterEvent = event.type === "dragover" || event.type === "dragenter";
6801
6878
  const isDropEvent = event.type === "drop";
6802
6879
  const isInput = ["INPUT", "BUTTON", "SELECT", "TEXTAREA"].includes(target.tagName) || target.isContentEditable;
6803
6880
  if (isInput && !isDropEvent && !isDragEvent) {
@@ -6806,7 +6883,7 @@ var NodeView = class {
6806
6883
  const { isEditable } = this.editor;
6807
6884
  const { isDragging } = this;
6808
6885
  const isDraggable = !!this.node.type.spec.draggable;
6809
- const isSelectable = import_state24.NodeSelection.isSelectable(this.node);
6886
+ const isSelectable = import_state25.NodeSelection.isSelectable(this.node);
6810
6887
  const isCopyEvent = event.type === "copy";
6811
6888
  const isPasteEvent = event.type === "paste";
6812
6889
  const isCutEvent = event.type === "cut";
@@ -6846,7 +6923,7 @@ var NodeView = class {
6846
6923
  );
6847
6924
  }
6848
6925
  }
6849
- if (isDragging || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
6926
+ if (isDragging || isDragOverEnterEvent || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
6850
6927
  return false;
6851
6928
  }
6852
6929
  return true;
@@ -6944,7 +7021,10 @@ function markPasteRule(config) {
6944
7021
  }
6945
7022
  markEnd = range.from + startSpaces + captureGroup.length;
6946
7023
  tr.addMark(range.from + startSpaces, markEnd, config.type.create(attributes || {}));
6947
- tr.removeStoredMark(config.type);
7024
+ const isMatchAtEndOfText = match.index !== void 0 && match.input !== void 0 && match.index + match[0].length >= match.input.length;
7025
+ if (!isMatchAtEndOfText) {
7026
+ tr.removeStoredMark(config.type);
7027
+ }
6948
7028
  }
6949
7029
  }
6950
7030
  });
@@ -7035,6 +7115,7 @@ var Tracker = class {
7035
7115
  Tracker,
7036
7116
  callOrReturn,
7037
7117
  canInsertNode,
7118
+ cancelPositionCheck,
7038
7119
  combineTransactionSteps,
7039
7120
  commands,
7040
7121
  createAtomBlockMarkdownSpec,
@@ -7129,6 +7210,7 @@ var Tracker = class {
7129
7210
  resolveExtensions,
7130
7211
  resolveFocusPosition,
7131
7212
  rewriteUnknownContent,
7213
+ schedulePositionCheck,
7132
7214
  selectionToInsertionEnd,
7133
7215
  serializeAttributes,
7134
7216
  sortExtensions,