@blocknote/core 0.30.1 → 0.31.1
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/blocknote.cjs +9 -9
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +2793 -2213
- package/dist/blocknote.js.map +1 -1
- package/dist/{en-D4taoCs4.cjs → en-BXVKCwYt.cjs} +2 -2
- package/dist/en-BXVKCwYt.cjs.map +1 -0
- package/dist/{en-B7ycW7c8.js → en-qGo6sk9V.js} +2 -3
- package/dist/en-qGo6sk9V.js.map +1 -0
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +20 -39
- package/dist/locales.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +5 -6
- package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +2 -3
- package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +1 -1
- package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +2816 -0
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +158 -0
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +87 -17
- package/src/api/blockManipulation/selections/selection.ts +48 -1
- package/src/api/blockManipulation/selections/{textCursorPosition/textCursorPosition.ts → textCursorPosition.ts} +7 -7
- package/src/api/getBlockInfoFromPos.ts +1 -1
- package/src/api/nodeConversions/blockToNode.ts +5 -2
- package/src/api/nodeConversions/nodeToBlock.ts +203 -8
- package/src/api/pmUtil.ts +3 -3
- package/src/blocks/CodeBlockContent/CodeBlockContent.ts +6 -6
- package/src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts +1 -1
- package/src/blocks/TableBlockContent/TableBlockContent.ts +32 -2
- package/src/editor/Block.css +27 -1
- package/src/editor/BlockNoteEditor.test.ts +7 -0
- package/src/editor/BlockNoteEditor.ts +124 -39
- package/src/editor/BlockNoteExtension.ts +26 -0
- package/src/editor/BlockNoteExtensions.ts +28 -12
- package/src/editor/BlockNoteTipTapEditor.ts +23 -2
- package/src/extensions/Collaboration/CursorPlugin.ts +13 -7
- package/src/extensions/Collaboration/ForkYDocPlugin.test.ts +166 -0
- package/src/extensions/Collaboration/ForkYDocPlugin.ts +174 -0
- package/src/extensions/Collaboration/SyncPlugin.ts +7 -4
- package/src/extensions/Collaboration/UndoPlugin.ts +7 -4
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor-forked.json +30 -0
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor.json +30 -0
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-forked.html +1 -0
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap.html +1 -0
- package/src/extensions/Comments/CommentsPlugin.ts +79 -70
- package/src/extensions/FilePanel/FilePanelPlugin.ts +54 -49
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +60 -26
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +26 -21
- package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts +49 -42
- package/src/extensions/Placeholder/PlaceholderPlugin.ts +115 -108
- package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +183 -170
- package/src/extensions/ShowSelection/ShowSelectionPlugin.ts +26 -19
- package/src/extensions/SideMenu/SideMenuPlugin.ts +23 -18
- package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +172 -168
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +4 -4
- package/src/extensions/Suggestions/SuggestionMarks.ts +175 -0
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +157 -150
- package/src/i18n/locales/ar.ts +0 -1
- package/src/i18n/locales/de.ts +0 -1
- package/src/i18n/locales/en.ts +0 -1
- package/src/i18n/locales/es.ts +0 -1
- package/src/i18n/locales/fr.ts +0 -1
- package/src/i18n/locales/hr.ts +0 -1
- package/src/i18n/locales/is.ts +0 -1
- package/src/i18n/locales/it.ts +0 -1
- package/src/i18n/locales/ja.ts +0 -1
- package/src/i18n/locales/ko.ts +0 -1
- package/src/i18n/locales/nl.ts +0 -1
- package/src/i18n/locales/no.ts +0 -1
- package/src/i18n/locales/pl.ts +0 -1
- package/src/i18n/locales/pt.ts +0 -1
- package/src/i18n/locales/ru.ts +0 -1
- package/src/i18n/locales/sk.ts +0 -1
- package/src/i18n/locales/uk.ts +0 -1
- package/src/i18n/locales/vi.ts +0 -1
- package/src/i18n/locales/zh-tw.ts +0 -1
- package/src/i18n/locales/zh.ts +0 -1
- package/src/index.ts +18 -8
- package/src/pm-nodes/BlockContainer.ts +1 -1
- package/src/pm-nodes/BlockGroup.ts +1 -1
- package/src/pm-nodes/Doc.ts +1 -0
- package/types/src/api/blockManipulation/commands/insertBlocks/insertBlocks.d.ts +1 -1
- package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.d.ts +3 -1
- package/types/src/api/blockManipulation/selections/selection.d.ts +10 -0
- package/types/src/api/blockManipulation/selections/{textCursorPosition/textCursorPosition.d.ts → textCursorPosition.d.ts} +2 -2
- package/types/src/api/nodeConversions/nodeToBlock.d.ts +39 -2
- package/types/src/api/pmUtil.d.ts +3 -3
- package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +9 -1
- package/types/src/editor/BlockNoteEditor.d.ts +62 -10
- package/types/src/editor/BlockNoteExtension.d.ts +9 -0
- package/types/src/editor/BlockNoteExtensions.d.ts +2 -2
- package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -2
- package/types/src/extensions/Collaboration/CursorPlugin.d.ts +3 -3
- package/types/src/extensions/Collaboration/ForkYDocPlugin.d.ts +41 -0
- package/types/src/extensions/Collaboration/SyncPlugin.d.ts +3 -3
- package/types/src/extensions/Collaboration/UndoPlugin.d.ts +3 -3
- package/types/src/extensions/Comments/CommentsPlugin.d.ts +3 -4
- package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +4 -4
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +6 -5
- package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +4 -4
- package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +3 -3
- package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +3 -3
- package/types/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.d.ts +3 -3
- package/types/src/extensions/ShowSelection/ShowSelectionPlugin.d.ts +3 -3
- package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +4 -4
- package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +3 -4
- package/types/src/extensions/Suggestions/SuggestionMarks.d.ts +4 -0
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +6 -6
- package/types/src/i18n/locales/en.d.ts +0 -1
- package/types/src/i18n/locales/sk.d.ts +0 -1
- package/types/src/index.d.ts +15 -8
- package/dist/en-B7ycW7c8.js.map +0 -1
- package/dist/en-D4taoCs4.cjs.map +0 -1
- package/src/api/blockManipulation/selections/__snapshots__/selection.test.ts.snap +0 -844
- package/src/api/blockManipulation/selections/selection.test.ts +0 -72
- package/src/api/blockManipulation/selections/textCursorPosition/__snapshots__/textCursorPosition.test.ts.snap +0 -316
- package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.ts +0 -74
- package/types/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.d.ts +0 -1
- /package/types/src/{api/blockManipulation/selections/selection.test.d.ts → extensions/Collaboration/ForkYDocPlugin.test.d.ts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { findChildren } from "@tiptap/core";
|
|
2
2
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
3
3
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
4
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
4
5
|
|
|
5
6
|
const PLUGIN_KEY = new PluginKey(`previous-blocks`);
|
|
6
7
|
|
|
@@ -23,199 +24,211 @@ const nodeAttributes: Record<string, string> = {
|
|
|
23
24
|
*
|
|
24
25
|
* Solution: When attributes change on a node, this plugin sets a data-* attribute with the "previous" value. This way we can still use CSS transitions. (See block.module.css)
|
|
25
26
|
*/
|
|
26
|
-
export class PreviousBlockTypePlugin {
|
|
27
|
-
public
|
|
27
|
+
export class PreviousBlockTypePlugin extends BlockNoteExtension {
|
|
28
|
+
public static key() {
|
|
29
|
+
return "previousBlockType";
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
constructor() {
|
|
33
|
+
super();
|
|
29
34
|
let timeout: ReturnType<typeof setTimeout>;
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
update: async (view, _prevState) => {
|
|
35
|
-
if (this.key?.getState(view.state).updatedBlocks.size > 0) {
|
|
36
|
-
// use setTimeout 0 to clear the decorations so that at least
|
|
37
|
-
// for one DOM-render the decorations have been applied
|
|
38
|
-
timeout = setTimeout(() => {
|
|
39
|
-
view.dispatch(
|
|
40
|
-
view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true }),
|
|
41
|
-
);
|
|
42
|
-
}, 0);
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
destroy: () => {
|
|
46
|
-
if (timeout) {
|
|
47
|
-
clearTimeout(timeout);
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
},
|
|
52
|
-
state: {
|
|
53
|
-
init() {
|
|
35
|
+
this.addProsemirrorPlugin(
|
|
36
|
+
new Plugin({
|
|
37
|
+
key: PLUGIN_KEY,
|
|
38
|
+
view(_editorView) {
|
|
54
39
|
return {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
40
|
+
update: async (view, _prevState) => {
|
|
41
|
+
if (this.key?.getState(view.state).updatedBlocks.size > 0) {
|
|
42
|
+
// use setTimeout 0 to clear the decorations so that at least
|
|
43
|
+
// for one DOM-render the decorations have been applied
|
|
44
|
+
timeout = setTimeout(() => {
|
|
45
|
+
view.dispatch(
|
|
46
|
+
view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true }),
|
|
47
|
+
);
|
|
48
|
+
}, 0);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
destroy: () => {
|
|
52
|
+
if (timeout) {
|
|
53
|
+
clearTimeout(timeout);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
61
56
|
};
|
|
62
57
|
},
|
|
58
|
+
state: {
|
|
59
|
+
init() {
|
|
60
|
+
return {
|
|
61
|
+
// Block attributes, by block ID, from just before the previous transaction.
|
|
62
|
+
prevTransactionOldBlockAttrs: {} as any,
|
|
63
|
+
// Block attributes, by block ID, from just before the current transaction.
|
|
64
|
+
currentTransactionOldBlockAttrs: {} as any,
|
|
65
|
+
// Set of IDs of blocks whose attributes changed from the current transaction.
|
|
66
|
+
updatedBlocks: new Set<string>(),
|
|
67
|
+
};
|
|
68
|
+
},
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
apply(transaction, prev, oldState, newState) {
|
|
71
|
+
prev.currentTransactionOldBlockAttrs = {};
|
|
72
|
+
prev.updatedBlocks.clear();
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const currentTransactionOriginalOldBlockAttrs = {} as any;
|
|
93
|
-
|
|
94
|
-
const oldNodes = findChildren(oldState.doc, (node) => node.attrs.id);
|
|
95
|
-
const oldNodesById = new Map(
|
|
96
|
-
oldNodes.map((node) => [node.node.attrs.id, node]),
|
|
97
|
-
);
|
|
98
|
-
const newNodes = findChildren(newState.doc, (node) => node.attrs.id);
|
|
99
|
-
|
|
100
|
-
// Traverses all block containers in the new editor state.
|
|
101
|
-
for (const node of newNodes) {
|
|
102
|
-
const oldNode = oldNodesById.get(node.node.attrs.id);
|
|
103
|
-
|
|
104
|
-
const oldContentNode = oldNode?.node.firstChild;
|
|
105
|
-
const newContentNode = node.node.firstChild;
|
|
106
|
-
|
|
107
|
-
if (oldNode && oldContentNode && newContentNode) {
|
|
108
|
-
const newAttrs = {
|
|
109
|
-
index: newContentNode.attrs.index,
|
|
110
|
-
level: newContentNode.attrs.level,
|
|
111
|
-
type: newContentNode.type.name,
|
|
112
|
-
depth: newState.doc.resolve(node.pos).depth,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
let oldAttrs = {
|
|
116
|
-
index: oldContentNode.attrs.index,
|
|
117
|
-
level: oldContentNode.attrs.level,
|
|
118
|
-
type: oldContentNode.type.name,
|
|
119
|
-
depth: oldState.doc.resolve(oldNode.pos).depth,
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
currentTransactionOriginalOldBlockAttrs[node.node.attrs.id] =
|
|
123
|
-
oldAttrs;
|
|
124
|
-
|
|
125
|
-
// Whenever a transaction is appended by the OrderedListItemIndexPlugin, it's given the metadata:
|
|
126
|
-
// { "orderedListIndexing": true }
|
|
127
|
-
// These appended transactions happen immediately after any transaction which causes ordered list item
|
|
128
|
-
// indices to require updating, including those which trigger animations. Therefore, these animations are
|
|
129
|
-
// immediately overridden when the PreviousBlockTypePlugin processes the appended transaction, despite only
|
|
130
|
-
// the listItemIndex attribute changing. To solve this, oldAttrs must be edited for transactions with the
|
|
131
|
-
// "orderedListIndexing" metadata, so the correct animation can be re-triggered.
|
|
132
|
-
if (transaction.getMeta("numberedListIndexing")) {
|
|
133
|
-
// If the block existed before the transaction, gets the attributes from before the previous transaction
|
|
134
|
-
// (i.e. the transaction that caused list item indices to need updating).
|
|
135
|
-
if (node.node.attrs.id in prev.prevTransactionOldBlockAttrs) {
|
|
136
|
-
oldAttrs =
|
|
137
|
-
prev.prevTransactionOldBlockAttrs[node.node.attrs.id];
|
|
138
|
-
}
|
|
74
|
+
if (!transaction.docChanged || oldState.doc.eq(newState.doc)) {
|
|
75
|
+
return prev;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// TODO: Instead of iterating through the entire document, only check nodes affected by the transactions. Will
|
|
79
|
+
// also probably require checking nodes affected by the previous transaction too.
|
|
80
|
+
// We didn't get this to work yet:
|
|
81
|
+
// const transform = combineTransactionSteps(oldState.doc, [transaction]);
|
|
82
|
+
// // const { mapping } = transform;
|
|
83
|
+
// const changes = getChangedRanges(transform);
|
|
84
|
+
//
|
|
85
|
+
// changes.forEach(({ oldRange, newRange }) => {
|
|
86
|
+
// const oldNodes = findChildrenInRange(
|
|
87
|
+
// oldState.doc,
|
|
88
|
+
// oldRange,
|
|
89
|
+
// (node) => node.attrs.id
|
|
90
|
+
// );
|
|
91
|
+
//
|
|
92
|
+
// const newNodes = findChildrenInRange(
|
|
93
|
+
// newState.doc,
|
|
94
|
+
// newRange,
|
|
95
|
+
// (node) => node.attrs.id
|
|
96
|
+
// );
|
|
139
97
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
98
|
+
const currentTransactionOriginalOldBlockAttrs = {} as any;
|
|
99
|
+
|
|
100
|
+
const oldNodes = findChildren(
|
|
101
|
+
oldState.doc,
|
|
102
|
+
(node) => node.attrs.id,
|
|
103
|
+
);
|
|
104
|
+
const oldNodesById = new Map(
|
|
105
|
+
oldNodes.map((node) => [node.node.attrs.id, node]),
|
|
106
|
+
);
|
|
107
|
+
const newNodes = findChildren(
|
|
108
|
+
newState.doc,
|
|
109
|
+
(node) => node.attrs.id,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// Traverses all block containers in the new editor state.
|
|
113
|
+
for (const node of newNodes) {
|
|
114
|
+
const oldNode = oldNodesById.get(node.node.attrs.id);
|
|
115
|
+
|
|
116
|
+
const oldContentNode = oldNode?.node.firstChild;
|
|
117
|
+
const newContentNode = node.node.firstChild;
|
|
118
|
+
|
|
119
|
+
if (oldNode && oldContentNode && newContentNode) {
|
|
120
|
+
const newAttrs = {
|
|
121
|
+
index: newContentNode.attrs.index,
|
|
122
|
+
level: newContentNode.attrs.level,
|
|
123
|
+
type: newContentNode.type.name,
|
|
124
|
+
depth: newState.doc.resolve(node.pos).depth,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
let oldAttrs = {
|
|
128
|
+
index: oldContentNode.attrs.index,
|
|
129
|
+
level: oldContentNode.attrs.level,
|
|
130
|
+
type: oldContentNode.type.name,
|
|
131
|
+
depth: oldState.doc.resolve(oldNode.pos).depth,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
currentTransactionOriginalOldBlockAttrs[node.node.attrs.id] =
|
|
135
|
+
oldAttrs;
|
|
136
|
+
|
|
137
|
+
// Whenever a transaction is appended by the OrderedListItemIndexPlugin, it's given the metadata:
|
|
138
|
+
// { "orderedListIndexing": true }
|
|
139
|
+
// These appended transactions happen immediately after any transaction which causes ordered list item
|
|
140
|
+
// indices to require updating, including those which trigger animations. Therefore, these animations are
|
|
141
|
+
// immediately overridden when the PreviousBlockTypePlugin processes the appended transaction, despite only
|
|
142
|
+
// the listItemIndex attribute changing. To solve this, oldAttrs must be edited for transactions with the
|
|
143
|
+
// "orderedListIndexing" metadata, so the correct animation can be re-triggered.
|
|
144
|
+
if (transaction.getMeta("numberedListIndexing")) {
|
|
145
|
+
// If the block existed before the transaction, gets the attributes from before the previous transaction
|
|
146
|
+
// (i.e. the transaction that caused list item indices to need updating).
|
|
147
|
+
if (node.node.attrs.id in prev.prevTransactionOldBlockAttrs) {
|
|
148
|
+
oldAttrs =
|
|
149
|
+
prev.prevTransactionOldBlockAttrs[node.node.attrs.id];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Stops list item indices themselves being animated (looks smoother), unless the block's content type is
|
|
153
|
+
// changing from a numbered list item to something else.
|
|
154
|
+
if (newAttrs.type === "numberedListItem") {
|
|
155
|
+
oldAttrs.index = newAttrs.index;
|
|
156
|
+
}
|
|
144
157
|
}
|
|
145
|
-
}
|
|
146
158
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
159
|
+
prev.currentTransactionOldBlockAttrs[node.node.attrs.id] =
|
|
160
|
+
oldAttrs;
|
|
161
|
+
|
|
162
|
+
// TODO: faster deep equal?
|
|
163
|
+
if (JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs)) {
|
|
164
|
+
(oldAttrs as any)["depth-change"] =
|
|
165
|
+
oldAttrs.depth - newAttrs.depth;
|
|
166
|
+
|
|
167
|
+
// for debugging:
|
|
168
|
+
// console.log(
|
|
169
|
+
// "id:",
|
|
170
|
+
// node.node.attrs.id,
|
|
171
|
+
// "previousBlockTypePlugin changes detected, oldAttrs",
|
|
172
|
+
// oldAttrs,
|
|
173
|
+
// "new",
|
|
174
|
+
// newAttrs
|
|
175
|
+
// );
|
|
176
|
+
|
|
177
|
+
prev.updatedBlocks.add(node.node.attrs.id);
|
|
178
|
+
}
|
|
166
179
|
}
|
|
167
180
|
}
|
|
168
|
-
}
|
|
169
181
|
|
|
170
|
-
|
|
171
|
-
|
|
182
|
+
prev.prevTransactionOldBlockAttrs =
|
|
183
|
+
currentTransactionOriginalOldBlockAttrs;
|
|
172
184
|
|
|
173
|
-
|
|
185
|
+
return prev;
|
|
186
|
+
},
|
|
174
187
|
},
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return undefined;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const decorations: Decoration[] = [];
|
|
184
|
-
|
|
185
|
-
state.doc.descendants((node, pos) => {
|
|
186
|
-
if (!node.attrs.id) {
|
|
187
|
-
return;
|
|
188
|
+
props: {
|
|
189
|
+
decorations(state) {
|
|
190
|
+
const pluginState = (this as Plugin).getState(state);
|
|
191
|
+
if (pluginState.updatedBlocks.size === 0) {
|
|
192
|
+
return undefined;
|
|
188
193
|
}
|
|
189
194
|
|
|
190
|
-
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
195
|
+
const decorations: Decoration[] = [];
|
|
193
196
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
+
state.doc.descendants((node, pos) => {
|
|
198
|
+
if (!node.attrs.id) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
197
201
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
+
if (!pluginState.updatedBlocks.has(node.attrs.id)) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
202
205
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
// decorationAttrs
|
|
207
|
-
// );
|
|
206
|
+
const prevAttrs =
|
|
207
|
+
pluginState.currentTransactionOldBlockAttrs[node.attrs.id];
|
|
208
|
+
const decorationAttrs: any = {};
|
|
208
209
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
for (const [nodeAttr, val] of Object.entries(prevAttrs)) {
|
|
211
|
+
decorationAttrs["data-prev-" + nodeAttributes[nodeAttr]] =
|
|
212
|
+
val || "none";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// for debugging:
|
|
216
|
+
// console.log(
|
|
217
|
+
// "previousBlockTypePlugin committing decorations",
|
|
218
|
+
// decorationAttrs
|
|
219
|
+
// );
|
|
212
220
|
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
const decoration = Decoration.node(pos, pos + node.nodeSize, {
|
|
222
|
+
...decorationAttrs,
|
|
223
|
+
});
|
|
215
224
|
|
|
216
|
-
|
|
225
|
+
decorations.push(decoration);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
return DecorationSet.create(state.doc, decorations);
|
|
229
|
+
},
|
|
217
230
|
},
|
|
218
|
-
},
|
|
219
|
-
|
|
231
|
+
}),
|
|
232
|
+
);
|
|
220
233
|
}
|
|
221
234
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2
2
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
3
3
|
import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
|
|
4
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
4
5
|
|
|
5
6
|
const PLUGIN_KEY = new PluginKey(`blocknote-show-selection`);
|
|
6
7
|
|
|
@@ -9,29 +10,35 @@ const PLUGIN_KEY = new PluginKey(`blocknote-show-selection`);
|
|
|
9
10
|
* This can be used to highlight the current selection in the UI even when the
|
|
10
11
|
* text editor is not focused.
|
|
11
12
|
*/
|
|
12
|
-
export class ShowSelectionPlugin {
|
|
13
|
-
public
|
|
13
|
+
export class ShowSelectionPlugin extends BlockNoteExtension {
|
|
14
|
+
public static key() {
|
|
15
|
+
return "showSelection";
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
private enabled = false;
|
|
15
19
|
|
|
16
20
|
public constructor(private readonly editor: BlockNoteEditor<any, any, any>) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
super();
|
|
22
|
+
this.addProsemirrorPlugin(
|
|
23
|
+
new Plugin({
|
|
24
|
+
key: PLUGIN_KEY,
|
|
25
|
+
props: {
|
|
26
|
+
decorations: (state) => {
|
|
27
|
+
const { doc, selection } = state;
|
|
28
|
+
|
|
29
|
+
if (!this.enabled) {
|
|
30
|
+
return DecorationSet.empty;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const dec = Decoration.inline(selection.from, selection.to, {
|
|
34
|
+
"data-show-selection": "true",
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return DecorationSet.create(doc, [dec]);
|
|
38
|
+
},
|
|
32
39
|
},
|
|
33
|
-
},
|
|
34
|
-
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
public setEnabled(enabled: boolean) {
|
|
@@ -3,20 +3,20 @@ import {
|
|
|
3
3
|
EditorState,
|
|
4
4
|
Plugin,
|
|
5
5
|
PluginKey,
|
|
6
|
-
TextSelection,
|
|
7
6
|
PluginView,
|
|
7
|
+
TextSelection,
|
|
8
8
|
} from "@tiptap/pm/state";
|
|
9
9
|
import { EditorView } from "@tiptap/pm/view";
|
|
10
10
|
|
|
11
11
|
import { Block } from "../../blocks/defaultBlocks.js";
|
|
12
12
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
|
|
13
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
13
14
|
import { UiElementPosition } from "../../extensions-shared/UiElementPosition.js";
|
|
14
15
|
import {
|
|
15
16
|
BlockSchema,
|
|
16
17
|
InlineContentSchema,
|
|
17
18
|
StyleSchema,
|
|
18
19
|
} from "../../schema/index.js";
|
|
19
|
-
import { EventEmitter } from "../../util/EventEmitter.js";
|
|
20
20
|
import { initializeESMDependencies } from "../../util/esmDependencies.js";
|
|
21
21
|
import { getDraggableBlockFromElement } from "../getDraggableBlockFromElement.js";
|
|
22
22
|
import { dragStart, unsetDragImage } from "./dragging.js";
|
|
@@ -608,29 +608,34 @@ export class SideMenuProsemirrorPlugin<
|
|
|
608
608
|
BSchema extends BlockSchema,
|
|
609
609
|
I extends InlineContentSchema,
|
|
610
610
|
S extends StyleSchema,
|
|
611
|
-
> extends
|
|
611
|
+
> extends BlockNoteExtension {
|
|
612
|
+
public static key() {
|
|
613
|
+
return "sideMenu";
|
|
614
|
+
}
|
|
615
|
+
|
|
612
616
|
public view: SideMenuView<BSchema, I, S> | undefined;
|
|
613
|
-
public readonly plugin: Plugin;
|
|
614
617
|
|
|
615
618
|
constructor(
|
|
616
619
|
private readonly editor: BlockNoteEditor<BSchema, I, S>,
|
|
617
620
|
sideMenuDetection: "viewport" | "editor",
|
|
618
621
|
) {
|
|
619
622
|
super();
|
|
620
|
-
this.
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
623
|
+
this.addProsemirrorPlugin(
|
|
624
|
+
new Plugin({
|
|
625
|
+
key: sideMenuPluginKey,
|
|
626
|
+
view: (editorView) => {
|
|
627
|
+
this.view = new SideMenuView(
|
|
628
|
+
editor,
|
|
629
|
+
sideMenuDetection,
|
|
630
|
+
editorView,
|
|
631
|
+
(state) => {
|
|
632
|
+
this.emit("update", state);
|
|
633
|
+
},
|
|
634
|
+
);
|
|
635
|
+
return this.view;
|
|
636
|
+
},
|
|
637
|
+
}),
|
|
638
|
+
);
|
|
634
639
|
}
|
|
635
640
|
|
|
636
641
|
public onUpdate(callback: (state: SideMenuState<BSchema, I, S>) => void) {
|