@tiptap/core 2.10.3 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.umd.js CHANGED
@@ -994,6 +994,8 @@
994
994
  const success = handlers.every(handler => handler !== null);
995
995
  return success;
996
996
  }
997
+ // When dragging across editors, must get another editor instance to delete selection content.
998
+ let tiptapDragFromOtherEditor = null;
997
999
  const createClipboardPasteEvent = (text) => {
998
1000
  var _a;
999
1001
  const event = new ClipboardEvent('paste', {
@@ -1056,11 +1058,21 @@
1056
1058
  dragSourceElement = ((_a = view.dom.parentElement) === null || _a === void 0 ? void 0 : _a.contains(event.target))
1057
1059
  ? view.dom.parentElement
1058
1060
  : null;
1061
+ if (dragSourceElement) {
1062
+ tiptapDragFromOtherEditor = editor;
1063
+ }
1064
+ };
1065
+ const handleDragend = () => {
1066
+ if (tiptapDragFromOtherEditor) {
1067
+ tiptapDragFromOtherEditor = null;
1068
+ }
1059
1069
  };
1060
1070
  window.addEventListener('dragstart', handleDragstart);
1071
+ window.addEventListener('dragend', handleDragend);
1061
1072
  return {
1062
1073
  destroy() {
1063
1074
  window.removeEventListener('dragstart', handleDragstart);
1075
+ window.removeEventListener('dragend', handleDragend);
1064
1076
  },
1065
1077
  };
1066
1078
  },
@@ -1069,6 +1081,18 @@
1069
1081
  drop: (view, event) => {
1070
1082
  isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
1071
1083
  dropEvent = event;
1084
+ if (!isDroppedFromProseMirror) {
1085
+ const dragFromOtherEditor = tiptapDragFromOtherEditor;
1086
+ if (dragFromOtherEditor) {
1087
+ // setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
1088
+ setTimeout(() => {
1089
+ const selection = dragFromOtherEditor.state.selection;
1090
+ if (selection) {
1091
+ dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to });
1092
+ }
1093
+ }, 10);
1094
+ }
1095
+ }
1072
1096
  return false;
1073
1097
  },
1074
1098
  paste: (_view, event) => {
@@ -1827,30 +1851,13 @@
1827
1851
  return state.TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
1828
1852
  }
1829
1853
 
1830
- function isiOS() {
1831
- return [
1832
- 'iPad Simulator',
1833
- 'iPhone Simulator',
1834
- 'iPod Simulator',
1835
- 'iPad',
1836
- 'iPhone',
1837
- 'iPod',
1838
- ].includes(navigator.platform)
1839
- // iPad on iOS 13 detection
1840
- || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
1841
- }
1842
-
1843
1854
  const focus = (position = null, options = {}) => ({ editor, view, tr, dispatch, }) => {
1844
1855
  options = {
1845
1856
  scrollIntoView: true,
1846
1857
  ...options,
1847
1858
  };
1848
1859
  const delayedFocus = () => {
1849
- // focus within `requestAnimationFrame` breaks focus on iOS
1850
- // so we have to call this
1851
- if (isiOS()) {
1852
- view.dom.focus();
1853
- }
1860
+ view.dom.focus();
1854
1861
  // For React we have to focus asynchronously. Otherwise wild things happen.
1855
1862
  // see: https://github.com/ueberdosis/tiptap/issues/1520
1856
1863
  requestAnimationFrame(() => {
@@ -2181,6 +2188,19 @@
2181
2188
  return commands$1.joinTextblockForward(state, dispatch);
2182
2189
  };
2183
2190
 
2191
+ function isiOS() {
2192
+ return [
2193
+ 'iPad Simulator',
2194
+ 'iPhone Simulator',
2195
+ 'iPod Simulator',
2196
+ 'iPad',
2197
+ 'iPhone',
2198
+ 'iPod',
2199
+ ].includes(navigator.platform)
2200
+ // iPad on iOS 13 detection
2201
+ || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
2202
+ }
2203
+
2184
2204
  function isMacOS() {
2185
2205
  return typeof navigator !== 'undefined'
2186
2206
  ? /Mac/.test(navigator.platform)
@@ -2391,11 +2411,12 @@
2391
2411
  return true;
2392
2412
  };
2393
2413
 
2394
- const selectAll = () => ({ tr, commands }) => {
2395
- return commands.setTextSelection({
2396
- from: 0,
2397
- to: tr.doc.content.size,
2398
- });
2414
+ const selectAll = () => ({ tr, dispatch }) => {
2415
+ if (dispatch) {
2416
+ const selection = new state.AllSelection(tr.doc);
2417
+ tr.setSelection(selection);
2418
+ }
2419
+ return true;
2399
2420
  };
2400
2421
 
2401
2422
  const selectNodeBackward = () => ({ state, dispatch }) => {
@@ -3082,6 +3103,81 @@
3082
3103
  };
3083
3104
  }
3084
3105
 
3106
+ /**
3107
+ * The actual implementation of the rewriteUnknownContent function
3108
+ */
3109
+ function rewriteUnknownContentInner({ json, validMarks, validNodes, options, rewrittenContent = [], }) {
3110
+ if (json.marks && Array.isArray(json.marks)) {
3111
+ json.marks = json.marks.filter(mark => {
3112
+ const name = typeof mark === 'string' ? mark : mark.type;
3113
+ if (validMarks.has(name)) {
3114
+ return true;
3115
+ }
3116
+ rewrittenContent.push({
3117
+ original: JSON.parse(JSON.stringify(mark)),
3118
+ unsupported: name,
3119
+ });
3120
+ // Just ignore any unknown marks
3121
+ return false;
3122
+ });
3123
+ }
3124
+ if (json.content && Array.isArray(json.content)) {
3125
+ json.content = json.content
3126
+ .map(value => rewriteUnknownContentInner({
3127
+ json: value,
3128
+ validMarks,
3129
+ validNodes,
3130
+ options,
3131
+ rewrittenContent,
3132
+ }).json)
3133
+ .filter(a => a !== null && a !== undefined);
3134
+ }
3135
+ if (json.type && !validNodes.has(json.type)) {
3136
+ rewrittenContent.push({
3137
+ original: JSON.parse(JSON.stringify(json)),
3138
+ unsupported: json.type,
3139
+ });
3140
+ if (json.content && Array.isArray(json.content) && ((options === null || options === void 0 ? void 0 : options.fallbackToParagraph) !== false)) {
3141
+ // Just treat it like a paragraph and hope for the best
3142
+ json.type = 'paragraph';
3143
+ return {
3144
+ json,
3145
+ rewrittenContent,
3146
+ };
3147
+ }
3148
+ // or just omit it entirely
3149
+ return {
3150
+ json: null,
3151
+ rewrittenContent,
3152
+ };
3153
+ }
3154
+ return { json, rewrittenContent };
3155
+ }
3156
+ /**
3157
+ * Rewrite unknown nodes and marks within JSON content
3158
+ * Allowing for user within the editor
3159
+ */
3160
+ function rewriteUnknownContent(
3161
+ /**
3162
+ * The JSON content to clean of unknown nodes and marks
3163
+ */
3164
+ json,
3165
+ /**
3166
+ * The schema to use for validation
3167
+ */
3168
+ schema,
3169
+ /**
3170
+ * Options for the cleaning process
3171
+ */
3172
+ options) {
3173
+ return rewriteUnknownContentInner({
3174
+ json,
3175
+ validNodes: new Set(Object.keys(schema.nodes)),
3176
+ validMarks: new Set(Object.keys(schema.marks)),
3177
+ options,
3178
+ });
3179
+ }
3180
+
3085
3181
  function canSetMark(state, tr, newMarkType) {
3086
3182
  var _a;
3087
3183
  const { selection } = tr;
@@ -5077,10 +5173,10 @@ img.ProseMirror-separator {
5077
5173
  // ProseMirror tries to drag selectable nodes
5078
5174
  // even if `draggable` is set to `false`
5079
5175
  // this fix prevents that
5080
- if (!isDraggable && isSelectable && isDragEvent) {
5176
+ if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
5081
5177
  event.preventDefault();
5082
5178
  }
5083
- if (isDraggable && isDragEvent && !isDragging) {
5179
+ if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
5084
5180
  event.preventDefault();
5085
5181
  return false;
5086
5182
  }
@@ -5406,6 +5502,7 @@ img.ProseMirror-separator {
5406
5502
  exports.posToDOMRect = posToDOMRect;
5407
5503
  exports.removeDuplicates = removeDuplicates;
5408
5504
  exports.resolveFocusPosition = resolveFocusPosition;
5505
+ exports.rewriteUnknownContent = rewriteUnknownContent;
5409
5506
  exports.selectionToInsertionEnd = selectionToInsertionEnd;
5410
5507
  exports.splitExtensions = splitExtensions;
5411
5508
  exports.textInputRule = textInputRule;