@blocknote/core 0.30.1 → 0.31.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.
Files changed (139) hide show
  1. package/dist/blocknote.cjs +9 -9
  2. package/dist/blocknote.cjs.map +1 -1
  3. package/dist/blocknote.js +2754 -2230
  4. package/dist/blocknote.js.map +1 -1
  5. package/dist/{en-D4taoCs4.cjs → en-BXVKCwYt.cjs} +2 -2
  6. package/dist/en-BXVKCwYt.cjs.map +1 -0
  7. package/dist/{en-B7ycW7c8.js → en-qGo6sk9V.js} +2 -3
  8. package/dist/en-qGo6sk9V.js.map +1 -0
  9. package/dist/locales.cjs +1 -1
  10. package/dist/locales.cjs.map +1 -1
  11. package/dist/locales.js +20 -39
  12. package/dist/locales.js.map +1 -1
  13. package/dist/style.css +1 -1
  14. package/dist/webpack-stats.json +1 -1
  15. package/package.json +4 -5
  16. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +2 -3
  17. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +1 -1
  18. package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +2816 -0
  19. package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +158 -0
  20. package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +87 -17
  21. package/src/api/blockManipulation/selections/selection.ts +48 -1
  22. package/src/api/blockManipulation/selections/{textCursorPosition/textCursorPosition.ts → textCursorPosition.ts} +7 -7
  23. package/src/api/getBlockInfoFromPos.ts +1 -1
  24. package/src/api/nodeConversions/blockToNode.ts +5 -2
  25. package/src/api/nodeConversions/nodeToBlock.ts +203 -8
  26. package/src/api/pmUtil.ts +3 -3
  27. package/src/blocks/CodeBlockContent/CodeBlockContent.ts +6 -6
  28. package/src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts +1 -1
  29. package/src/blocks/TableBlockContent/TableBlockContent.ts +32 -2
  30. package/src/editor/Block.css +27 -1
  31. package/src/editor/BlockNoteEditor.test.ts +7 -0
  32. package/src/editor/BlockNoteEditor.ts +88 -37
  33. package/src/editor/BlockNoteExtension.ts +26 -0
  34. package/src/editor/BlockNoteExtensions.ts +28 -12
  35. package/src/editor/BlockNoteTipTapEditor.ts +23 -2
  36. package/src/extensions/Collaboration/CursorPlugin.ts +13 -7
  37. package/src/extensions/Collaboration/ForkYDocPlugin.test.ts +166 -0
  38. package/src/extensions/Collaboration/ForkYDocPlugin.ts +174 -0
  39. package/src/extensions/Collaboration/SyncPlugin.ts +7 -4
  40. package/src/extensions/Collaboration/UndoPlugin.ts +7 -4
  41. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor-forked.json +30 -0
  42. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor.json +30 -0
  43. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-forked.html +1 -0
  44. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap.html +1 -0
  45. package/src/extensions/Comments/CommentsPlugin.ts +75 -70
  46. package/src/extensions/FilePanel/FilePanelPlugin.ts +50 -49
  47. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +56 -26
  48. package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +22 -21
  49. package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts +45 -42
  50. package/src/extensions/Placeholder/PlaceholderPlugin.ts +111 -108
  51. package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +179 -170
  52. package/src/extensions/ShowSelection/ShowSelectionPlugin.ts +22 -19
  53. package/src/extensions/SideMenu/SideMenuPlugin.ts +19 -18
  54. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +168 -168
  55. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +4 -4
  56. package/src/extensions/Suggestions/SuggestionMarks.ts +175 -0
  57. package/src/extensions/TableHandles/TableHandlesPlugin.ts +153 -150
  58. package/src/i18n/locales/ar.ts +0 -1
  59. package/src/i18n/locales/de.ts +0 -1
  60. package/src/i18n/locales/en.ts +0 -1
  61. package/src/i18n/locales/es.ts +0 -1
  62. package/src/i18n/locales/fr.ts +0 -1
  63. package/src/i18n/locales/hr.ts +0 -1
  64. package/src/i18n/locales/is.ts +0 -1
  65. package/src/i18n/locales/it.ts +0 -1
  66. package/src/i18n/locales/ja.ts +0 -1
  67. package/src/i18n/locales/ko.ts +0 -1
  68. package/src/i18n/locales/nl.ts +0 -1
  69. package/src/i18n/locales/no.ts +0 -1
  70. package/src/i18n/locales/pl.ts +0 -1
  71. package/src/i18n/locales/pt.ts +0 -1
  72. package/src/i18n/locales/ru.ts +0 -1
  73. package/src/i18n/locales/sk.ts +0 -1
  74. package/src/i18n/locales/uk.ts +0 -1
  75. package/src/i18n/locales/vi.ts +0 -1
  76. package/src/i18n/locales/zh-tw.ts +0 -1
  77. package/src/i18n/locales/zh.ts +0 -1
  78. package/src/index.ts +18 -8
  79. package/src/pm-nodes/BlockContainer.ts +1 -1
  80. package/src/pm-nodes/BlockGroup.ts +1 -1
  81. package/src/pm-nodes/Doc.ts +1 -0
  82. package/types/src/api/blockManipulation/commands/insertBlocks/insertBlocks.d.ts +1 -1
  83. package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.d.ts +4 -0
  84. package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.test.d.ts +1 -0
  85. package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.d.ts +3 -1
  86. package/types/src/api/blockManipulation/selections/selection.d.ts +10 -0
  87. package/types/src/api/blockManipulation/selections/textCursorPosition.d.ts +5 -0
  88. package/types/src/api/blockManipulation/transactions.test.d.ts +0 -0
  89. package/types/src/api/clipboard/clipboardExternal.test.d.ts +1 -0
  90. package/types/src/api/clipboard/clipboardInternal.test.d.ts +1 -0
  91. package/types/src/api/clipboard/testUtil.d.ts +541 -0
  92. package/types/src/api/exporters/html/htmlConversion.test.d.ts +1 -0
  93. package/types/src/api/exporters/markdown/markdownExporter.test.d.ts +1 -0
  94. package/types/src/api/nodeConversions/nodeConversions.test.d.ts +1 -0
  95. package/types/src/api/nodeConversions/nodeToBlock.d.ts +39 -2
  96. package/types/src/api/parsers/html/parseHTML.test.d.ts +1 -0
  97. package/types/src/api/parsers/markdown/parseMarkdown.test.d.ts +1 -0
  98. package/types/src/api/pmUtil.d.ts +3 -3
  99. package/types/src/api/testUtil/cases/customBlocks.d.ts +670 -0
  100. package/types/src/api/testUtil/cases/customInlineContent.d.ts +558 -0
  101. package/types/src/api/testUtil/cases/customStyles.d.ts +552 -0
  102. package/types/src/api/testUtil/cases/defaultSchema.d.ts +4 -0
  103. package/types/src/api/testUtil/index.d.ts +14 -0
  104. package/types/src/api/testUtil/partialBlockTestUtil.d.ts +9 -0
  105. package/types/src/api/testUtil/paste.d.ts +2 -0
  106. package/types/src/blocks/CodeBlockContent/defaultSupportedLanguages.d.ts +6 -0
  107. package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +9 -1
  108. package/types/src/editor/BlockNoteEditor.d.ts +55 -9
  109. package/types/src/editor/BlockNoteExtension.d.ts +9 -0
  110. package/types/src/editor/BlockNoteExtensions.d.ts +2 -2
  111. package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -2
  112. package/types/src/extensions/Collaboration/CursorPlugin.d.ts +3 -3
  113. package/types/src/extensions/Collaboration/ForkYDocPlugin.d.ts +41 -0
  114. package/types/src/extensions/Collaboration/ForkYDocPlugin.test.d.ts +1 -0
  115. package/types/src/extensions/Collaboration/SyncPlugin.d.ts +3 -3
  116. package/types/src/extensions/Collaboration/UndoPlugin.d.ts +3 -3
  117. package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +17 -0
  118. package/types/src/extensions/Comments/CommentsPlugin.d.ts +2 -4
  119. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +3 -4
  120. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -5
  121. package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +3 -4
  122. package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +2 -3
  123. package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +2 -3
  124. package/types/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.d.ts +2 -3
  125. package/types/src/extensions/ShowSelection/ShowSelectionPlugin.d.ts +2 -3
  126. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +3 -4
  127. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +2 -4
  128. package/types/src/extensions/Suggestions/SuggestionMarks.d.ts +4 -0
  129. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +5 -6
  130. package/types/src/i18n/locales/en.d.ts +0 -1
  131. package/types/src/i18n/locales/sk.d.ts +0 -1
  132. package/types/src/index.d.ts +15 -8
  133. package/dist/en-B7ycW7c8.js.map +0 -1
  134. package/dist/en-D4taoCs4.cjs.map +0 -1
  135. package/dist/tsconfig.tsbuildinfo +0 -1
  136. package/src/api/blockManipulation/selections/__snapshots__/selection.test.ts.snap +0 -844
  137. package/src/api/blockManipulation/selections/selection.test.ts +0 -72
  138. package/src/api/blockManipulation/selections/textCursorPosition/__snapshots__/textCursorPosition.test.ts.snap +0 -316
  139. package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.ts +0 -74
@@ -0,0 +1,175 @@
1
+ import { Mark } from "@tiptap/core";
2
+ import { MarkSpec } from "prosemirror-model";
3
+
4
+ // This copies the marks from @handlewithcare/prosemirror-suggest-changes,
5
+ // but uses the Tiptap Mark API instead so we can use them in BlockNote
6
+
7
+ // The ideal solution would be to not depend on tiptap nodes / marks, but be able to use prosemirror nodes / marks directly
8
+ // this way we could directly use the exported marks from @handlewithcare/prosemirror-suggest-changes
9
+ export const SuggestionAddMark = Mark.create({
10
+ name: "insertion",
11
+ inclusive: false,
12
+ excludes: "deletion modification insertion",
13
+ addAttributes() {
14
+ return {
15
+ id: { default: null, validate: "number" }, // note: validate is supported in prosemirror but not in tiptap, so this doesn't actually work (considered not critical)
16
+ };
17
+ },
18
+ extendMarkSchema(extension) {
19
+ if (extension.name !== "insertion") {
20
+ return {};
21
+ }
22
+ return {
23
+ blocknoteIgnore: true,
24
+ inclusive: false,
25
+
26
+ toDOM(mark, inline) {
27
+ return [
28
+ "ins",
29
+ {
30
+ "data-id": String(mark.attrs["id"]),
31
+ "data-inline": String(inline),
32
+ ...(!inline && { style: "display: contents" }), // changed to "contents" to make this work for table rows
33
+ },
34
+ 0,
35
+ ];
36
+ },
37
+ parseDOM: [
38
+ {
39
+ tag: "ins",
40
+ getAttrs(node) {
41
+ if (!node.dataset["id"]) {
42
+ return false;
43
+ }
44
+ return {
45
+ id: parseInt(node.dataset["id"], 10),
46
+ };
47
+ },
48
+ },
49
+ ],
50
+ } satisfies MarkSpec;
51
+ },
52
+ });
53
+
54
+ export const SuggestionDeleteMark = Mark.create({
55
+ name: "deletion",
56
+ inclusive: false,
57
+ excludes: "insertion modification deletion",
58
+ addAttributes() {
59
+ return {
60
+ id: { default: null, validate: "number" }, // note: validate is supported in prosemirror but not in tiptap
61
+ };
62
+ },
63
+ extendMarkSchema(extension) {
64
+ if (extension.name !== "deletion") {
65
+ return {};
66
+ }
67
+ return {
68
+ blocknoteIgnore: true,
69
+ inclusive: false,
70
+
71
+ // attrs: {
72
+ // id: { validate: "number" },
73
+ // },
74
+ toDOM(mark, inline) {
75
+ return [
76
+ "del",
77
+ {
78
+ "data-id": String(mark.attrs["id"]),
79
+ "data-inline": String(inline),
80
+ ...(!inline && { style: "display: contents" }), // changed to "contents" to make this work for table rows
81
+ },
82
+ 0,
83
+ ];
84
+ },
85
+ parseDOM: [
86
+ {
87
+ tag: "del",
88
+ getAttrs(node) {
89
+ if (!node.dataset["id"]) {
90
+ return false;
91
+ }
92
+ return {
93
+ id: parseInt(node.dataset["id"], 10),
94
+ };
95
+ },
96
+ },
97
+ ],
98
+ } satisfies MarkSpec;
99
+ },
100
+ });
101
+
102
+ export const SuggestionModificationMark = Mark.create({
103
+ name: "modification",
104
+ inclusive: false,
105
+ excludes: "deletion insertion",
106
+ addAttributes() {
107
+ // note: validate is supported in prosemirror but not in tiptap
108
+ return {
109
+ id: { default: null, validate: "number" },
110
+ type: { validate: "string" },
111
+ attrName: { default: null, validate: "string|null" },
112
+ previousValue: { default: null },
113
+ newValue: { default: null },
114
+ };
115
+ },
116
+ extendMarkSchema(extension) {
117
+ if (extension.name !== "modification") {
118
+ return {};
119
+ }
120
+ return {
121
+ blocknoteIgnore: true,
122
+ inclusive: false,
123
+ // attrs: {
124
+ // id: { validate: "number" },
125
+ // type: { validate: "string" },
126
+ // attrName: { default: null, validate: "string|null" },
127
+ // previousValue: { default: null },
128
+ // newValue: { default: null },
129
+ // },
130
+ toDOM(mark, inline) {
131
+ return [
132
+ inline ? "span" : "div",
133
+ {
134
+ "data-type": "modification",
135
+ "data-id": String(mark.attrs["id"]),
136
+ "data-mod-type": mark.attrs["type"] as string,
137
+ "data-mod-prev-val": JSON.stringify(mark.attrs["previousValue"]),
138
+ // TODO: Try to serialize marks with toJSON?
139
+ "data-mod-new-val": JSON.stringify(mark.attrs["newValue"]),
140
+ },
141
+ 0,
142
+ ];
143
+ },
144
+ parseDOM: [
145
+ {
146
+ tag: "span[data-type='modification']",
147
+ getAttrs(node) {
148
+ if (!node.dataset["id"]) {
149
+ return false;
150
+ }
151
+ return {
152
+ id: parseInt(node.dataset["id"], 10),
153
+ type: node.dataset["modType"],
154
+ previousValue: node.dataset["modPrevVal"],
155
+ newValue: node.dataset["modNewVal"],
156
+ };
157
+ },
158
+ },
159
+ {
160
+ tag: "div[data-type='modification']",
161
+ getAttrs(node) {
162
+ if (!node.dataset["id"]) {
163
+ return false;
164
+ }
165
+ return {
166
+ id: parseInt(node.dataset["id"], 10),
167
+ type: node.dataset["modType"],
168
+ previousValue: node.dataset["modPrevVal"],
169
+ };
170
+ },
171
+ },
172
+ ],
173
+ } satisfies MarkSpec;
174
+ },
175
+ });
@@ -32,13 +32,13 @@ import {
32
32
  } from "../../blocks/defaultBlockTypeGuards.js";
33
33
  import { DefaultBlockSchema } from "../../blocks/defaultBlocks.js";
34
34
  import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
35
+ import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
35
36
  import {
36
37
  BlockFromConfigNoChildren,
37
38
  BlockSchemaWithBlock,
38
39
  InlineContentSchema,
39
40
  StyleSchema,
40
41
  } from "../../schema/index.js";
41
- import { EventEmitter } from "../../util/EventEmitter.js";
42
42
  import { getDraggableBlockFromElement } from "../getDraggableBlockFromElement.js";
43
43
 
44
44
  let dragImageElement: HTMLElement | undefined;
@@ -617,9 +617,8 @@ export const tableHandlesPluginKey = new PluginKey("TableHandlesPlugin");
617
617
  export class TableHandlesProsemirrorPlugin<
618
618
  I extends InlineContentSchema,
619
619
  S extends StyleSchema,
620
- > extends EventEmitter<any> {
620
+ > extends BlockNoteExtension {
621
621
  private view: TableHandlesView<I, S> | undefined;
622
- public readonly plugin: Plugin;
623
622
 
624
623
  constructor(
625
624
  private readonly editor: BlockNoteEditor<
@@ -629,159 +628,163 @@ export class TableHandlesProsemirrorPlugin<
629
628
  >,
630
629
  ) {
631
630
  super();
632
- this.plugin = new Plugin({
633
- key: tableHandlesPluginKey,
634
- view: (editorView) => {
635
- this.view = new TableHandlesView(editor, editorView, (state) => {
636
- this.emit("update", state);
637
- });
638
- return this.view;
639
- },
640
- // We use decorations to render the drop cursor when dragging a table row
641
- // or column. The decorations are updated in the `dragOverHandler` method.
642
- props: {
643
- decorations: (state) => {
644
- if (
645
- this.view === undefined ||
646
- this.view.state === undefined ||
647
- this.view.state.draggingState === undefined ||
648
- this.view.tablePos === undefined
649
- ) {
650
- return;
651
- }
652
-
653
- const newIndex =
654
- this.view.state.draggingState.draggedCellOrientation === "row"
655
- ? this.view.state.rowIndex
656
- : this.view.state.colIndex;
657
-
658
- if (newIndex === undefined) {
659
- return;
660
- }
661
-
662
- const decorations: Decoration[] = [];
663
- const { block, draggingState } = this.view.state;
664
- const { originalIndex, draggedCellOrientation } = draggingState;
665
-
666
- // Return empty decorations if:
667
- // - Dragging to same position
668
- // - No block exists
669
- // - Row drag not allowed
670
- // - Column drag not allowed
671
- if (
672
- newIndex === originalIndex ||
673
- !block ||
674
- (draggedCellOrientation === "row" &&
675
- !canRowBeDraggedInto(block, originalIndex, newIndex)) ||
676
- (draggedCellOrientation === "col" &&
677
- !canColumnBeDraggedInto(block, originalIndex, newIndex))
678
- ) {
679
- return DecorationSet.create(state.doc, decorations);
680
- }
681
-
682
- // Gets the table to show the drop cursor in.
683
- const tableResolvedPos = state.doc.resolve(this.view.tablePos + 1);
684
-
685
- if (this.view.state.draggingState.draggedCellOrientation === "row") {
686
- const cellsInRow = getCellsAtRowHandle(
687
- this.view.state.block,
688
- newIndex,
689
- );
690
-
691
- cellsInRow.forEach(({ row, col }) => {
692
- // Gets each row in the table.
693
- const rowResolvedPos = state.doc.resolve(
694
- tableResolvedPos.posAtIndex(row) + 1,
631
+ this.addProsemirrorPlugin(
632
+ new Plugin({
633
+ key: tableHandlesPluginKey,
634
+ view: (editorView) => {
635
+ this.view = new TableHandlesView(editor, editorView, (state) => {
636
+ this.emit("update", state);
637
+ });
638
+ return this.view;
639
+ },
640
+ // We use decorations to render the drop cursor when dragging a table row
641
+ // or column. The decorations are updated in the `dragOverHandler` method.
642
+ props: {
643
+ decorations: (state) => {
644
+ if (
645
+ this.view === undefined ||
646
+ this.view.state === undefined ||
647
+ this.view.state.draggingState === undefined ||
648
+ this.view.tablePos === undefined
649
+ ) {
650
+ return;
651
+ }
652
+
653
+ const newIndex =
654
+ this.view.state.draggingState.draggedCellOrientation === "row"
655
+ ? this.view.state.rowIndex
656
+ : this.view.state.colIndex;
657
+
658
+ if (newIndex === undefined) {
659
+ return;
660
+ }
661
+
662
+ const decorations: Decoration[] = [];
663
+ const { block, draggingState } = this.view.state;
664
+ const { originalIndex, draggedCellOrientation } = draggingState;
665
+
666
+ // Return empty decorations if:
667
+ // - Dragging to same position
668
+ // - No block exists
669
+ // - Row drag not allowed
670
+ // - Column drag not allowed
671
+ if (
672
+ newIndex === originalIndex ||
673
+ !block ||
674
+ (draggedCellOrientation === "row" &&
675
+ !canRowBeDraggedInto(block, originalIndex, newIndex)) ||
676
+ (draggedCellOrientation === "col" &&
677
+ !canColumnBeDraggedInto(block, originalIndex, newIndex))
678
+ ) {
679
+ return DecorationSet.create(state.doc, decorations);
680
+ }
681
+
682
+ // Gets the table to show the drop cursor in.
683
+ const tableResolvedPos = state.doc.resolve(this.view.tablePos + 1);
684
+
685
+ if (
686
+ this.view.state.draggingState.draggedCellOrientation === "row"
687
+ ) {
688
+ const cellsInRow = getCellsAtRowHandle(
689
+ this.view.state.block,
690
+ newIndex,
695
691
  );
696
692
 
697
- // Gets the cell within the row.
698
- const cellResolvedPos = state.doc.resolve(
699
- rowResolvedPos.posAtIndex(col) + 1,
700
- );
701
- const cellNode = cellResolvedPos.node();
702
- // Creates a decoration at the start or end of each cell,
703
- // depending on whether the new index is before or after the
704
- // original index.
705
- const decorationPos =
706
- cellResolvedPos.pos +
707
- (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);
708
- decorations.push(
709
- // The widget is a small bar which spans the width of the cell.
710
- Decoration.widget(decorationPos, () => {
711
- const widget = document.createElement("div");
712
- widget.className = "bn-table-drop-cursor";
713
- widget.style.left = "0";
714
- widget.style.right = "0";
715
- // This is only necessary because the drop indicator's height
716
- // is an even number of pixels, whereas the border between
717
- // table cells is an odd number of pixels. So this makes the
718
- // positioning slightly more consistent regardless of where
719
- // the row is being dropped.
720
- if (newIndex > originalIndex) {
721
- widget.style.bottom = "-2px";
722
- } else {
723
- widget.style.top = "-3px";
724
- }
725
- widget.style.height = "4px";
726
-
727
- return widget;
728
- }),
729
- );
730
- });
731
- } else {
732
- const cellsInColumn = getCellsAtColumnHandle(
733
- this.view.state.block,
734
- newIndex,
735
- );
736
-
737
- cellsInColumn.forEach(({ row, col }) => {
738
- // Gets each row in the table.
739
- const rowResolvedPos = state.doc.resolve(
740
- tableResolvedPos.posAtIndex(row) + 1,
693
+ cellsInRow.forEach(({ row, col }) => {
694
+ // Gets each row in the table.
695
+ const rowResolvedPos = state.doc.resolve(
696
+ tableResolvedPos.posAtIndex(row) + 1,
697
+ );
698
+
699
+ // Gets the cell within the row.
700
+ const cellResolvedPos = state.doc.resolve(
701
+ rowResolvedPos.posAtIndex(col) + 1,
702
+ );
703
+ const cellNode = cellResolvedPos.node();
704
+ // Creates a decoration at the start or end of each cell,
705
+ // depending on whether the new index is before or after the
706
+ // original index.
707
+ const decorationPos =
708
+ cellResolvedPos.pos +
709
+ (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);
710
+ decorations.push(
711
+ // The widget is a small bar which spans the width of the cell.
712
+ Decoration.widget(decorationPos, () => {
713
+ const widget = document.createElement("div");
714
+ widget.className = "bn-table-drop-cursor";
715
+ widget.style.left = "0";
716
+ widget.style.right = "0";
717
+ // This is only necessary because the drop indicator's height
718
+ // is an even number of pixels, whereas the border between
719
+ // table cells is an odd number of pixels. So this makes the
720
+ // positioning slightly more consistent regardless of where
721
+ // the row is being dropped.
722
+ if (newIndex > originalIndex) {
723
+ widget.style.bottom = "-2px";
724
+ } else {
725
+ widget.style.top = "-3px";
726
+ }
727
+ widget.style.height = "4px";
728
+
729
+ return widget;
730
+ }),
731
+ );
732
+ });
733
+ } else {
734
+ const cellsInColumn = getCellsAtColumnHandle(
735
+ this.view.state.block,
736
+ newIndex,
741
737
  );
742
738
 
743
- // Gets the cell within the row.
744
- const cellResolvedPos = state.doc.resolve(
745
- rowResolvedPos.posAtIndex(col) + 1,
746
- );
747
- const cellNode = cellResolvedPos.node();
748
-
749
- // Creates a decoration at the start or end of each cell,
750
- // depending on whether the new index is before or after the
751
- // original index.
752
- const decorationPos =
753
- cellResolvedPos.pos +
754
- (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);
755
-
756
- decorations.push(
757
- // The widget is a small bar which spans the height of the cell.
758
- Decoration.widget(decorationPos, () => {
759
- const widget = document.createElement("div");
760
- widget.className = "bn-table-drop-cursor";
761
- widget.style.top = "0";
762
- widget.style.bottom = "0";
763
- // This is only necessary because the drop indicator's width
764
- // is an even number of pixels, whereas the border between
765
- // table cells is an odd number of pixels. So this makes the
766
- // positioning slightly more consistent regardless of where
767
- // the column is being dropped.
768
- if (newIndex > originalIndex) {
769
- widget.style.right = "-2px";
770
- } else {
771
- widget.style.left = "-3px";
772
- }
773
- widget.style.width = "4px";
774
-
775
- return widget;
776
- }),
777
- );
778
- });
779
- }
739
+ cellsInColumn.forEach(({ row, col }) => {
740
+ // Gets each row in the table.
741
+ const rowResolvedPos = state.doc.resolve(
742
+ tableResolvedPos.posAtIndex(row) + 1,
743
+ );
744
+
745
+ // Gets the cell within the row.
746
+ const cellResolvedPos = state.doc.resolve(
747
+ rowResolvedPos.posAtIndex(col) + 1,
748
+ );
749
+ const cellNode = cellResolvedPos.node();
750
+
751
+ // Creates a decoration at the start or end of each cell,
752
+ // depending on whether the new index is before or after the
753
+ // original index.
754
+ const decorationPos =
755
+ cellResolvedPos.pos +
756
+ (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);
757
+
758
+ decorations.push(
759
+ // The widget is a small bar which spans the height of the cell.
760
+ Decoration.widget(decorationPos, () => {
761
+ const widget = document.createElement("div");
762
+ widget.className = "bn-table-drop-cursor";
763
+ widget.style.top = "0";
764
+ widget.style.bottom = "0";
765
+ // This is only necessary because the drop indicator's width
766
+ // is an even number of pixels, whereas the border between
767
+ // table cells is an odd number of pixels. So this makes the
768
+ // positioning slightly more consistent regardless of where
769
+ // the column is being dropped.
770
+ if (newIndex > originalIndex) {
771
+ widget.style.right = "-2px";
772
+ } else {
773
+ widget.style.left = "-3px";
774
+ }
775
+ widget.style.width = "4px";
776
+
777
+ return widget;
778
+ }),
779
+ );
780
+ });
781
+ }
780
782
 
781
- return DecorationSet.create(state.doc, decorations);
783
+ return DecorationSet.create(state.doc, decorations);
784
+ },
782
785
  },
783
- },
784
- });
786
+ }),
787
+ );
785
788
  }
786
789
 
787
790
  public onUpdate(callback: (state: TableHandlesState<I, S>) => void) {
@@ -163,7 +163,6 @@ export const ar: Dictionary = {
163
163
  },
164
164
  suggestion_menu: {
165
165
  no_items_title: "لم يتم العثور على عناصر",
166
- loading: "جارٍ التحميل…",
167
166
  },
168
167
  color_picker: {
169
168
  text_title: "نص",
@@ -178,7 +178,6 @@ export const de: Dictionary = {
178
178
  },
179
179
  suggestion_menu: {
180
180
  no_items_title: "Keine Elemente gefunden",
181
- loading: "Laden …",
182
181
  },
183
182
  color_picker: {
184
183
  text_title: "Text",
@@ -178,7 +178,6 @@ export const en = {
178
178
  },
179
179
  suggestion_menu: {
180
180
  no_items_title: "No items found",
181
- loading: "Loading…",
182
181
  },
183
182
  color_picker: {
184
183
  text_title: "Text",
@@ -177,7 +177,6 @@ export const es: Dictionary = {
177
177
  },
178
178
  suggestion_menu: {
179
179
  no_items_title: "No se encontraron elementos",
180
- loading: "Cargando…",
181
180
  },
182
181
  color_picker: {
183
182
  text_title: "Texto",
@@ -202,7 +202,6 @@ export const fr: Dictionary = {
202
202
  },
203
203
  suggestion_menu: {
204
204
  no_items_title: "Aucun élément trouvé",
205
- loading: "Chargement…",
206
205
  },
207
206
  color_picker: {
208
207
  text_title: "Texte",
@@ -191,7 +191,6 @@ export const hr: Dictionary = {
191
191
  },
192
192
  suggestion_menu: {
193
193
  no_items_title: "Stavke nisu pronađene",
194
- loading: "Učitavanje…",
195
194
  },
196
195
  color_picker: {
197
196
  text_title: "Tekst",
@@ -170,7 +170,6 @@ export const is: Dictionary = {
170
170
  },
171
171
  suggestion_menu: {
172
172
  no_items_title: "Engir hlutir fundust",
173
- loading: "Hleður…",
174
173
  },
175
174
  color_picker: {
176
175
  text_title: "Texti",
@@ -179,7 +179,6 @@ export const it: Dictionary = {
179
179
  },
180
180
  suggestion_menu: {
181
181
  no_items_title: "Nessun elemento trovato",
182
- loading: "Caricamento…",
183
182
  },
184
183
  color_picker: {
185
184
  text_title: "Testo",
@@ -198,7 +198,6 @@ export const ja: Dictionary = {
198
198
  },
199
199
  suggestion_menu: {
200
200
  no_items_title: "アイテムが見つかりません",
201
- loading: "読込中…",
202
201
  },
203
202
  color_picker: {
204
203
  text_title: "文字色",
@@ -191,7 +191,6 @@ export const ko: Dictionary = {
191
191
  },
192
192
  suggestion_menu: {
193
193
  no_items_title: "항목을 찾을 수 없음",
194
- loading: "로딩 중…",
195
194
  },
196
195
  color_picker: {
197
196
  text_title: "텍스트",
@@ -178,7 +178,6 @@ export const nl: Dictionary = {
178
178
  },
179
179
  suggestion_menu: {
180
180
  no_items_title: "Geen items gevonden",
181
- loading: "Laden…",
182
181
  },
183
182
  color_picker: {
184
183
  text_title: "Tekst",
@@ -178,7 +178,6 @@ export const no: Dictionary = {
178
178
  },
179
179
  suggestion_menu: {
180
180
  no_items_title: "Ingen elementer funnet",
181
- loading: "Laster…",
182
181
  },
183
182
  color_picker: {
184
183
  text_title: "Tekst",
@@ -162,7 +162,6 @@ export const pl: Dictionary = {
162
162
  },
163
163
  suggestion_menu: {
164
164
  no_items_title: "Nie znaleziono elementów",
165
- loading: "Ładowanie…",
166
165
  },
167
166
  color_picker: {
168
167
  text_title: "Tekst",
@@ -170,7 +170,6 @@ export const pt: Dictionary = {
170
170
  },
171
171
  suggestion_menu: {
172
172
  no_items_title: "Nenhum item encontrado",
173
- loading: "Carregando…",
174
173
  },
175
174
  color_picker: {
176
175
  text_title: "Texto",
@@ -205,7 +205,6 @@ export const ru: Dictionary = {
205
205
  },
206
206
  suggestion_menu: {
207
207
  no_items_title: "ничего не найдено",
208
- loading: "Загрузка…",
209
208
  },
210
209
  color_picker: {
211
210
  text_title: "Текст",