@blocknote/core 0.8.1 → 0.8.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/blocknote.js +199 -174
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +3 -3
- package/dist/blocknote.umd.cjs.map +1 -1
- package/package.json +3 -3
- package/src/BlockNoteEditor.ts +14 -0
- package/src/extensions/Blocks/nodes/BlockContainer.ts +12 -3
- package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +2 -2
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +22 -29
- package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +4 -6
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +20 -19
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +2 -2
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +22 -13
- package/src/shared/EditorElement.ts +3 -3
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +23 -17
- package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +2 -2
- package/types/src/BlockNoteEditor.d.ts +1 -0
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +1 -1
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +1 -1
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +2 -3
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +2 -3
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +1 -1
- package/types/src/shared/EditorElement.d.ts +3 -3
- package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +1 -1
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://github.com/TypeCellOS/BlockNote",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
|
-
"version": "0.8.
|
|
6
|
+
"version": "0.8.2",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"types",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"build-bundled": "tsc && vite build --config vite.config.bundled.ts && git checkout tmp-releases && rm -rf ../../release && mv ../../release-tmp ../../release",
|
|
46
46
|
"preview": "vite preview",
|
|
47
47
|
"lint": "eslint src --max-warnings 0",
|
|
48
|
-
"test": "vitest",
|
|
48
|
+
"test": "vitest --run",
|
|
49
49
|
"test-watch": "vitest watch"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"access": "public",
|
|
111
111
|
"registry": "https://registry.npmjs.org/"
|
|
112
112
|
},
|
|
113
|
-
"gitHead": "
|
|
113
|
+
"gitHead": "8971bf90c88b71c0e1c52fc4f8b35579a2b82e28"
|
|
114
114
|
}
|
package/src/BlockNoteEditor.ts
CHANGED
|
@@ -149,6 +149,7 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
149
149
|
public readonly _tiptapEditor: TiptapEditor & { contentComponent: any };
|
|
150
150
|
public blockCache = new WeakMap<Node, Block<BSchema>>();
|
|
151
151
|
public readonly schema: BSchema;
|
|
152
|
+
private ready = false;
|
|
152
153
|
|
|
153
154
|
public get domElement() {
|
|
154
155
|
return this._tiptapEditor.view.dom as HTMLDivElement;
|
|
@@ -204,11 +205,24 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
204
205
|
newOptions.onEditorReady?.(this);
|
|
205
206
|
newOptions.initialContent &&
|
|
206
207
|
this.replaceBlocks(this.topLevelBlocks, newOptions.initialContent);
|
|
208
|
+
this.ready = true;
|
|
207
209
|
},
|
|
208
210
|
onUpdate: () => {
|
|
211
|
+
// This seems to be necessary due to a bug in TipTap:
|
|
212
|
+
// https://github.com/ueberdosis/tiptap/issues/2583
|
|
213
|
+
if (!this.ready) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
209
217
|
newOptions.onEditorContentChange?.(this);
|
|
210
218
|
},
|
|
211
219
|
onSelectionUpdate: () => {
|
|
220
|
+
// This seems to be necessary due to a bug in TipTap:
|
|
221
|
+
// https://github.com/ueberdosis/tiptap/issues/2583
|
|
222
|
+
if (!this.ready) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
212
226
|
newOptions.onTextCursorPositionChange?.(this);
|
|
213
227
|
},
|
|
214
228
|
editable: options.editable === undefined ? true : options.editable,
|
|
@@ -281,10 +281,19 @@ export const BlockContainer = Node.create<IBlock>({
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
// Deletes next block and adds its text content to the nearest previous block.
|
|
284
|
-
|
|
284
|
+
|
|
285
285
|
if (dispatch) {
|
|
286
|
-
|
|
287
|
-
|
|
286
|
+
dispatch(
|
|
287
|
+
state.tr
|
|
288
|
+
.deleteRange(startPos, startPos + contentNode.nodeSize)
|
|
289
|
+
.replace(
|
|
290
|
+
prevBlockEndPos - 1,
|
|
291
|
+
startPos,
|
|
292
|
+
new Slice(contentNode.content, 0, 0)
|
|
293
|
+
)
|
|
294
|
+
.scrollIntoView()
|
|
295
|
+
);
|
|
296
|
+
|
|
288
297
|
state.tr.setSelection(
|
|
289
298
|
new TextSelection(state.doc.resolve(prevBlockEndPos - 1))
|
|
290
299
|
);
|
|
@@ -12,12 +12,12 @@ export type BlockSideMenuStaticParams<BSchema extends BlockSchema> = {
|
|
|
12
12
|
|
|
13
13
|
freezeMenu: () => void;
|
|
14
14
|
unfreezeMenu: () => void;
|
|
15
|
+
|
|
16
|
+
getReferenceRect: () => DOMRect;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
export type BlockSideMenuDynamicParams<BSchema extends BlockSchema> = {
|
|
18
20
|
block: Block<BSchema>;
|
|
19
|
-
|
|
20
|
-
referenceRect: DOMRect;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export type BlockSideMenu<BSchema extends BlockSchema> = EditorElement<
|
|
@@ -250,6 +250,8 @@ export class BlockMenuView<BSchema extends BlockSchema> {
|
|
|
250
250
|
menuOpen = false;
|
|
251
251
|
menuFrozen = false;
|
|
252
252
|
|
|
253
|
+
private lastPosition: DOMRect | undefined;
|
|
254
|
+
|
|
253
255
|
constructor({
|
|
254
256
|
tiptapEditor,
|
|
255
257
|
editor,
|
|
@@ -272,9 +274,6 @@ export class BlockMenuView<BSchema extends BlockSchema> {
|
|
|
272
274
|
// Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.
|
|
273
275
|
document.body.addEventListener("mousemove", this.onMouseMove, true);
|
|
274
276
|
|
|
275
|
-
// Makes menu scroll with the page.
|
|
276
|
-
document.addEventListener("scroll", this.onScroll);
|
|
277
|
-
|
|
278
277
|
// Hides and unfreezes the menu whenever the user selects the editor with the mouse or presses a key.
|
|
279
278
|
// TODO: Better integration with suggestions menu and only editor scope?
|
|
280
279
|
document.body.addEventListener("mousedown", this.onMouseDown, true);
|
|
@@ -463,20 +462,6 @@ export class BlockMenuView<BSchema extends BlockSchema> {
|
|
|
463
462
|
}
|
|
464
463
|
};
|
|
465
464
|
|
|
466
|
-
onScroll = () => {
|
|
467
|
-
// Editor itself may have padding or other styling which affects size/position, so we get the boundingRect of
|
|
468
|
-
// the first child (i.e. the blockGroup that wraps all blocks in the editor) for a more accurate bounding box.
|
|
469
|
-
const editorBoundingBox = (
|
|
470
|
-
this.ttEditor.view.dom.firstChild! as HTMLElement
|
|
471
|
-
).getBoundingClientRect();
|
|
472
|
-
|
|
473
|
-
this.horizontalPosAnchor = editorBoundingBox.x;
|
|
474
|
-
|
|
475
|
-
if (this.menuOpen) {
|
|
476
|
-
this.blockMenu.render(this.getDynamicParams(), false);
|
|
477
|
-
}
|
|
478
|
-
};
|
|
479
|
-
|
|
480
465
|
destroy() {
|
|
481
466
|
if (this.menuOpen) {
|
|
482
467
|
this.menuOpen = false;
|
|
@@ -487,7 +472,6 @@ export class BlockMenuView<BSchema extends BlockSchema> {
|
|
|
487
472
|
this.ttEditor.view.dom.removeEventListener("dragstart", this.onDragStart);
|
|
488
473
|
document.body.removeEventListener("drop", this.onDrop);
|
|
489
474
|
document.body.removeEventListener("mousedown", this.onMouseDown);
|
|
490
|
-
document.removeEventListener("scroll", this.onScroll);
|
|
491
475
|
document.body.removeEventListener("keydown", this.onKeyDown);
|
|
492
476
|
}
|
|
493
477
|
|
|
@@ -556,23 +540,32 @@ export class BlockMenuView<BSchema extends BlockSchema> {
|
|
|
556
540
|
unfreezeMenu: () => {
|
|
557
541
|
this.menuFrozen = false;
|
|
558
542
|
},
|
|
543
|
+
getReferenceRect: () => {
|
|
544
|
+
if (!this.menuOpen) {
|
|
545
|
+
if (this.lastPosition === undefined) {
|
|
546
|
+
throw new Error(
|
|
547
|
+
"Attempted to access block reference rect before rendering block side menu."
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return this.lastPosition;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const blockContent = this.hoveredBlock!.firstChild! as HTMLElement;
|
|
555
|
+
const blockContentBoundingBox = blockContent.getBoundingClientRect();
|
|
556
|
+
if (this.horizontalPosAnchoredAtRoot) {
|
|
557
|
+
blockContentBoundingBox.x = this.horizontalPosAnchor;
|
|
558
|
+
}
|
|
559
|
+
this.lastPosition = blockContentBoundingBox;
|
|
560
|
+
|
|
561
|
+
return blockContentBoundingBox;
|
|
562
|
+
},
|
|
559
563
|
};
|
|
560
564
|
}
|
|
561
565
|
|
|
562
566
|
getDynamicParams(): BlockSideMenuDynamicParams<BSchema> {
|
|
563
|
-
const blockContent = this.hoveredBlock!.firstChild! as HTMLElement;
|
|
564
|
-
const blockContentBoundingBox = blockContent.getBoundingClientRect();
|
|
565
|
-
|
|
566
567
|
return {
|
|
567
568
|
block: this.editor.getBlock(this.hoveredBlock!.getAttribute("data-id")!)!,
|
|
568
|
-
referenceRect: new DOMRect(
|
|
569
|
-
this.horizontalPosAnchoredAtRoot
|
|
570
|
-
? this.horizontalPosAnchor
|
|
571
|
-
: blockContentBoundingBox.x,
|
|
572
|
-
blockContentBoundingBox.y,
|
|
573
|
-
blockContentBoundingBox.width,
|
|
574
|
-
blockContentBoundingBox.height
|
|
575
|
-
),
|
|
576
569
|
};
|
|
577
570
|
}
|
|
578
571
|
}
|
|
@@ -4,15 +4,13 @@ import { BlockSchema } from "../Blocks/api/blockTypes";
|
|
|
4
4
|
|
|
5
5
|
export type FormattingToolbarStaticParams<BSchema extends BlockSchema> = {
|
|
6
6
|
editor: BlockNoteEditor<BSchema>;
|
|
7
|
-
};
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
referenceRect: DOMRect;
|
|
8
|
+
getReferenceRect: () => DOMRect;
|
|
11
9
|
};
|
|
12
10
|
|
|
13
|
-
export type
|
|
14
|
-
|
|
15
|
-
>;
|
|
11
|
+
export type FormattingToolbarDynamicParams = {};
|
|
12
|
+
|
|
13
|
+
export type FormattingToolbar = EditorElement<FormattingToolbarDynamicParams>;
|
|
16
14
|
export type FormattingToolbarFactory<BSchema extends BlockSchema> =
|
|
17
15
|
ElementFactory<
|
|
18
16
|
FormattingToolbarStaticParams<BSchema>,
|
|
@@ -9,7 +9,6 @@ import { EditorView } from "prosemirror-view";
|
|
|
9
9
|
import { BlockNoteEditor, BlockSchema } from "../..";
|
|
10
10
|
import {
|
|
11
11
|
FormattingToolbar,
|
|
12
|
-
FormattingToolbarDynamicParams,
|
|
13
12
|
FormattingToolbarFactory,
|
|
14
13
|
FormattingToolbarStaticParams,
|
|
15
14
|
} from "./FormattingToolbarFactoryTypes";
|
|
@@ -44,6 +43,8 @@ export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
44
43
|
|
|
45
44
|
public prevWasEditable: boolean | null = null;
|
|
46
45
|
|
|
46
|
+
private lastPosition: DOMRect | undefined;
|
|
47
|
+
|
|
47
48
|
public shouldShow: (props: {
|
|
48
49
|
view: EditorView;
|
|
49
50
|
state: EditorState;
|
|
@@ -80,8 +81,6 @@ export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
80
81
|
|
|
81
82
|
this.ttEditor.on("focus", this.focusHandler);
|
|
82
83
|
this.ttEditor.on("blur", this.blurHandler);
|
|
83
|
-
|
|
84
|
-
document.addEventListener("scroll", this.scrollHandler);
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
viewMousedownHandler = () => {
|
|
@@ -129,12 +128,6 @@ export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
129
128
|
}
|
|
130
129
|
};
|
|
131
130
|
|
|
132
|
-
scrollHandler = () => {
|
|
133
|
-
if (this.toolbarIsOpen) {
|
|
134
|
-
this.formattingToolbar.render(this.getDynamicParams(), false);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
131
|
update(view: EditorView, oldState?: EditorState) {
|
|
139
132
|
const { state, composing } = view;
|
|
140
133
|
const { doc, selection } = state;
|
|
@@ -170,7 +163,7 @@ export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
170
163
|
!this.preventShow &&
|
|
171
164
|
(shouldShow || this.preventHide)
|
|
172
165
|
) {
|
|
173
|
-
this.formattingToolbar.render(
|
|
166
|
+
this.formattingToolbar.render({}, true);
|
|
174
167
|
this.toolbarIsOpen = true;
|
|
175
168
|
|
|
176
169
|
return;
|
|
@@ -182,7 +175,7 @@ export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
182
175
|
!this.preventShow &&
|
|
183
176
|
(shouldShow || this.preventHide)
|
|
184
177
|
) {
|
|
185
|
-
this.formattingToolbar.render(
|
|
178
|
+
this.formattingToolbar.render({}, false);
|
|
186
179
|
return;
|
|
187
180
|
}
|
|
188
181
|
|
|
@@ -206,8 +199,6 @@ export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
206
199
|
|
|
207
200
|
this.ttEditor.off("focus", this.focusHandler);
|
|
208
201
|
this.ttEditor.off("blur", this.blurHandler);
|
|
209
|
-
|
|
210
|
-
document.removeEventListener("scroll", this.scrollHandler);
|
|
211
202
|
}
|
|
212
203
|
|
|
213
204
|
getSelectionBoundingBox() {
|
|
@@ -233,12 +224,22 @@ export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
233
224
|
getStaticParams(): FormattingToolbarStaticParams<BSchema> {
|
|
234
225
|
return {
|
|
235
226
|
editor: this.editor,
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
227
|
+
getReferenceRect: () => {
|
|
228
|
+
if (!this.toolbarIsOpen) {
|
|
229
|
+
if (this.lastPosition === undefined) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
"Attempted to access selection reference rect before rendering formatting toolbar."
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return this.lastPosition;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const selectionBoundingBox = this.getSelectionBoundingBox();
|
|
239
|
+
this.lastPosition = selectionBoundingBox;
|
|
240
|
+
|
|
241
|
+
return selectionBoundingBox;
|
|
242
|
+
},
|
|
242
243
|
};
|
|
243
244
|
}
|
|
244
245
|
}
|
|
@@ -3,13 +3,13 @@ import { EditorElement, ElementFactory } from "../../shared/EditorElement";
|
|
|
3
3
|
export type HyperlinkToolbarStaticParams = {
|
|
4
4
|
editHyperlink: (url: string, text: string) => void;
|
|
5
5
|
deleteHyperlink: () => void;
|
|
6
|
+
|
|
7
|
+
getReferenceRect: () => DOMRect;
|
|
6
8
|
};
|
|
7
9
|
|
|
8
10
|
export type HyperlinkToolbarDynamicParams = {
|
|
9
11
|
url: string;
|
|
10
12
|
text: string;
|
|
11
|
-
|
|
12
|
-
referenceRect: DOMRect;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export type HyperlinkToolbar = EditorElement<HyperlinkToolbarDynamicParams>;
|
|
@@ -36,6 +36,8 @@ class HyperlinkToolbarView {
|
|
|
36
36
|
hyperlinkMark: Mark | undefined;
|
|
37
37
|
hyperlinkMarkRange: Range | undefined;
|
|
38
38
|
|
|
39
|
+
private lastPosition: DOMRect | undefined;
|
|
40
|
+
|
|
39
41
|
constructor({ editor, hyperlinkToolbarFactory }: HyperlinkToolbarViewProps) {
|
|
40
42
|
this.editor = editor;
|
|
41
43
|
|
|
@@ -58,7 +60,6 @@ class HyperlinkToolbarView {
|
|
|
58
60
|
|
|
59
61
|
this.editor.view.dom.addEventListener("mouseover", this.mouseOverHandler);
|
|
60
62
|
document.addEventListener("click", this.clickHandler, true);
|
|
61
|
-
document.addEventListener("scroll", this.scrollHandler);
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
mouseOverHandler = (event: MouseEvent) => {
|
|
@@ -120,12 +121,6 @@ class HyperlinkToolbarView {
|
|
|
120
121
|
}
|
|
121
122
|
};
|
|
122
123
|
|
|
123
|
-
scrollHandler = () => {
|
|
124
|
-
if (this.hyperlinkMark !== undefined) {
|
|
125
|
-
this.hyperlinkToolbar.render(this.getDynamicParams(), false);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
|
|
129
124
|
update() {
|
|
130
125
|
if (!this.editor.view.hasFocus()) {
|
|
131
126
|
return;
|
|
@@ -220,7 +215,6 @@ class HyperlinkToolbarView {
|
|
|
220
215
|
"mouseover",
|
|
221
216
|
this.mouseOverHandler
|
|
222
217
|
);
|
|
223
|
-
document.removeEventListener("scroll", this.scrollHandler);
|
|
224
218
|
}
|
|
225
219
|
|
|
226
220
|
getStaticParams(): HyperlinkToolbarStaticParams {
|
|
@@ -255,6 +249,26 @@ class HyperlinkToolbarView {
|
|
|
255
249
|
|
|
256
250
|
this.hyperlinkToolbar.hide();
|
|
257
251
|
},
|
|
252
|
+
getReferenceRect: () => {
|
|
253
|
+
if (!this.hyperlinkMark) {
|
|
254
|
+
if (this.lastPosition === undefined) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
"Attempted to access hyperlink reference rect before rendering hyperlink toolbar."
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return this.lastPosition;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const hyperlinkBoundingBox = posToDOMRect(
|
|
264
|
+
this.editor.view,
|
|
265
|
+
this.hyperlinkMarkRange!.from,
|
|
266
|
+
this.hyperlinkMarkRange!.to
|
|
267
|
+
);
|
|
268
|
+
this.lastPosition = hyperlinkBoundingBox;
|
|
269
|
+
|
|
270
|
+
return hyperlinkBoundingBox;
|
|
271
|
+
},
|
|
258
272
|
};
|
|
259
273
|
}
|
|
260
274
|
|
|
@@ -265,11 +279,6 @@ class HyperlinkToolbarView {
|
|
|
265
279
|
this.hyperlinkMarkRange!.from,
|
|
266
280
|
this.hyperlinkMarkRange!.to
|
|
267
281
|
),
|
|
268
|
-
referenceRect: posToDOMRect(
|
|
269
|
-
this.editor.view,
|
|
270
|
-
this.hyperlinkMarkRange!.from,
|
|
271
|
-
this.hyperlinkMarkRange!.to
|
|
272
|
-
),
|
|
273
282
|
};
|
|
274
283
|
}
|
|
275
284
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type RequiredStaticParams = Record<string, any
|
|
2
|
-
|
|
3
|
-
referenceRect: DOMRect;
|
|
1
|
+
export type RequiredStaticParams = Record<string, any> & {
|
|
2
|
+
getReferenceRect: () => DOMRect;
|
|
4
3
|
};
|
|
4
|
+
export type RequiredDynamicParams = Record<string, any> & {};
|
|
5
5
|
|
|
6
6
|
export type EditorElement<ElementDynamicParams extends RequiredDynamicParams> =
|
|
7
7
|
{
|
|
@@ -107,6 +107,8 @@ class SuggestionPluginView<
|
|
|
107
107
|
pluginState: SuggestionPluginState<T>;
|
|
108
108
|
itemCallback: (item: T) => void;
|
|
109
109
|
|
|
110
|
+
private lastPosition: DOMRect | undefined;
|
|
111
|
+
|
|
110
112
|
constructor({
|
|
111
113
|
editor,
|
|
112
114
|
pluginKey,
|
|
@@ -137,16 +139,8 @@ class SuggestionPluginView<
|
|
|
137
139
|
};
|
|
138
140
|
|
|
139
141
|
this.suggestionsMenu = suggestionsMenuFactory(this.getStaticParams());
|
|
140
|
-
|
|
141
|
-
document.addEventListener("scroll", this.handleScroll);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
handleScroll = () => {
|
|
145
|
-
if (this.pluginKey.getState(this.editor._tiptapEditor.state).active) {
|
|
146
|
-
this.suggestionsMenu.render(this.getDynamicParams(), false);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
144
|
update(view: EditorView, prevState: EditorState) {
|
|
151
145
|
const prev = this.pluginKey.getState(prevState);
|
|
152
146
|
const next = this.pluginKey.getState(view.state);
|
|
@@ -188,25 +182,37 @@ class SuggestionPluginView<
|
|
|
188
182
|
}
|
|
189
183
|
}
|
|
190
184
|
|
|
191
|
-
destroy() {
|
|
192
|
-
document.removeEventListener("scroll", this.handleScroll);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
185
|
getStaticParams(): SuggestionsMenuStaticParams<T> {
|
|
196
186
|
return {
|
|
197
187
|
itemCallback: (item: T) => this.itemCallback(item),
|
|
188
|
+
getReferenceRect: () => {
|
|
189
|
+
const decorationNode = document.querySelector(
|
|
190
|
+
`[data-decoration-id="${this.pluginState.decorationId}"]`
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
if (!decorationNode) {
|
|
194
|
+
if (this.lastPosition === undefined) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
"Attempted to access trigger character reference rect before rendering suggestions menu."
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return this.lastPosition;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const triggerCharacterBoundingBox =
|
|
204
|
+
decorationNode.getBoundingClientRect();
|
|
205
|
+
this.lastPosition = triggerCharacterBoundingBox;
|
|
206
|
+
|
|
207
|
+
return triggerCharacterBoundingBox;
|
|
208
|
+
},
|
|
198
209
|
};
|
|
199
210
|
}
|
|
200
211
|
|
|
201
212
|
getDynamicParams(): SuggestionsMenuDynamicParams<T> {
|
|
202
|
-
const decorationNode = document.querySelector(
|
|
203
|
-
`[data-decoration-id="${this.pluginState.decorationId}"]`
|
|
204
|
-
);
|
|
205
|
-
|
|
206
213
|
return {
|
|
207
214
|
items: this.pluginState.items,
|
|
208
215
|
keyboardHoveredItemIndex: this.pluginState.keyboardHoveredItemIndex!,
|
|
209
|
-
referenceRect: decorationNode!.getBoundingClientRect(),
|
|
210
216
|
};
|
|
211
217
|
}
|
|
212
218
|
}
|
|
@@ -3,13 +3,13 @@ import { SuggestionItem } from "./SuggestionItem";
|
|
|
3
3
|
|
|
4
4
|
export type SuggestionsMenuStaticParams<T extends SuggestionItem> = {
|
|
5
5
|
itemCallback: (item: T) => void;
|
|
6
|
+
|
|
7
|
+
getReferenceRect: () => DOMRect;
|
|
6
8
|
};
|
|
7
9
|
|
|
8
10
|
export type SuggestionsMenuDynamicParams<T extends SuggestionItem> = {
|
|
9
11
|
items: T[];
|
|
10
12
|
keyboardHoveredItemIndex: number;
|
|
11
|
-
|
|
12
|
-
referenceRect: DOMRect;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export type SuggestionsMenu<T extends SuggestionItem> = EditorElement<
|
|
@@ -104,6 +104,7 @@ export declare class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockS
|
|
|
104
104
|
};
|
|
105
105
|
blockCache: WeakMap<Node, Block<BSchema>>;
|
|
106
106
|
readonly schema: BSchema;
|
|
107
|
+
private ready;
|
|
107
108
|
get domElement(): HTMLDivElement;
|
|
108
109
|
isFocused(): boolean;
|
|
109
110
|
focus(): void;
|
|
@@ -8,10 +8,10 @@ export type BlockSideMenuStaticParams<BSchema extends BlockSchema> = {
|
|
|
8
8
|
blockDragEnd: () => void;
|
|
9
9
|
freezeMenu: () => void;
|
|
10
10
|
unfreezeMenu: () => void;
|
|
11
|
+
getReferenceRect: () => DOMRect;
|
|
11
12
|
};
|
|
12
13
|
export type BlockSideMenuDynamicParams<BSchema extends BlockSchema> = {
|
|
13
14
|
block: Block<BSchema>;
|
|
14
|
-
referenceRect: DOMRect;
|
|
15
15
|
};
|
|
16
16
|
export type BlockSideMenu<BSchema extends BlockSchema> = EditorElement<BlockSideMenuDynamicParams<BSchema>>;
|
|
17
17
|
export type BlockSideMenuFactory<BSchema extends BlockSchema> = ElementFactory<BlockSideMenuStaticParams<BSchema>, BlockSideMenuDynamicParams<BSchema>>;
|
|
@@ -20,6 +20,7 @@ export declare class BlockMenuView<BSchema extends BlockSchema> {
|
|
|
20
20
|
isDragging: boolean;
|
|
21
21
|
menuOpen: boolean;
|
|
22
22
|
menuFrozen: boolean;
|
|
23
|
+
private lastPosition;
|
|
23
24
|
constructor({ tiptapEditor, editor, blockMenuFactory, horizontalPosAnchoredAtRoot, }: BlockMenuViewProps<BSchema>);
|
|
24
25
|
/**
|
|
25
26
|
* Sets isDragging when dragging text.
|
|
@@ -40,7 +41,6 @@ export declare class BlockMenuView<BSchema extends BlockSchema> {
|
|
|
40
41
|
onKeyDown: (_event: KeyboardEvent) => void;
|
|
41
42
|
onMouseDown: (event: MouseEvent) => void;
|
|
42
43
|
onMouseMove: (event: MouseEvent) => void;
|
|
43
|
-
onScroll: () => void;
|
|
44
44
|
destroy(): void;
|
|
45
45
|
addBlock(): void;
|
|
46
46
|
getStaticParams(): BlockSideMenuStaticParams<BSchema>;
|
|
@@ -3,9 +3,8 @@ import { BlockNoteEditor } from "../../BlockNoteEditor";
|
|
|
3
3
|
import { BlockSchema } from "../Blocks/api/blockTypes";
|
|
4
4
|
export type FormattingToolbarStaticParams<BSchema extends BlockSchema> = {
|
|
5
5
|
editor: BlockNoteEditor<BSchema>;
|
|
6
|
+
getReferenceRect: () => DOMRect;
|
|
6
7
|
};
|
|
7
|
-
export type FormattingToolbarDynamicParams = {
|
|
8
|
-
referenceRect: DOMRect;
|
|
9
|
-
};
|
|
8
|
+
export type FormattingToolbarDynamicParams = {};
|
|
10
9
|
export type FormattingToolbar = EditorElement<FormattingToolbarDynamicParams>;
|
|
11
10
|
export type FormattingToolbarFactory<BSchema extends BlockSchema> = ElementFactory<FormattingToolbarStaticParams<BSchema>, FormattingToolbarDynamicParams>;
|
|
@@ -2,7 +2,7 @@ import { Editor } from "@tiptap/core";
|
|
|
2
2
|
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
3
3
|
import { EditorView } from "prosemirror-view";
|
|
4
4
|
import { BlockNoteEditor, BlockSchema } from "../..";
|
|
5
|
-
import { FormattingToolbar,
|
|
5
|
+
import { FormattingToolbar, FormattingToolbarFactory, FormattingToolbarStaticParams } from "./FormattingToolbarFactoryTypes";
|
|
6
6
|
export interface FormattingToolbarPluginProps<BSchema extends BlockSchema> {
|
|
7
7
|
pluginKey: PluginKey;
|
|
8
8
|
tiptapEditor: Editor;
|
|
@@ -21,6 +21,7 @@ export declare class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
21
21
|
preventShow: boolean;
|
|
22
22
|
toolbarIsOpen: boolean;
|
|
23
23
|
prevWasEditable: boolean | null;
|
|
24
|
+
private lastPosition;
|
|
24
25
|
shouldShow: (props: {
|
|
25
26
|
view: EditorView;
|
|
26
27
|
state: EditorState;
|
|
@@ -35,11 +36,9 @@ export declare class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
|
35
36
|
blurHandler: ({ event }: {
|
|
36
37
|
event: FocusEvent;
|
|
37
38
|
}) => void;
|
|
38
|
-
scrollHandler: () => void;
|
|
39
39
|
update(view: EditorView, oldState?: EditorState): void;
|
|
40
40
|
destroy(): void;
|
|
41
41
|
getSelectionBoundingBox(): DOMRect;
|
|
42
42
|
getStaticParams(): FormattingToolbarStaticParams<BSchema>;
|
|
43
|
-
getDynamicParams(): FormattingToolbarDynamicParams;
|
|
44
43
|
}
|
|
45
44
|
export declare const createFormattingToolbarPlugin: <BSchema extends Record<string, import("../..").BlockSpec<string, import("../..").PropSchema>>>(options: FormattingToolbarPluginProps<BSchema>) => Plugin<any>;
|
|
@@ -2,11 +2,11 @@ import { EditorElement, ElementFactory } from "../../shared/EditorElement";
|
|
|
2
2
|
export type HyperlinkToolbarStaticParams = {
|
|
3
3
|
editHyperlink: (url: string, text: string) => void;
|
|
4
4
|
deleteHyperlink: () => void;
|
|
5
|
+
getReferenceRect: () => DOMRect;
|
|
5
6
|
};
|
|
6
7
|
export type HyperlinkToolbarDynamicParams = {
|
|
7
8
|
url: string;
|
|
8
9
|
text: string;
|
|
9
|
-
referenceRect: DOMRect;
|
|
10
10
|
};
|
|
11
11
|
export type HyperlinkToolbar = EditorElement<HyperlinkToolbarDynamicParams>;
|
|
12
12
|
export type HyperlinkToolbarFactory = ElementFactory<HyperlinkToolbarStaticParams, HyperlinkToolbarDynamicParams>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type RequiredStaticParams = Record<string, any
|
|
2
|
-
|
|
3
|
-
referenceRect: DOMRect;
|
|
1
|
+
export type RequiredStaticParams = Record<string, any> & {
|
|
2
|
+
getReferenceRect: () => DOMRect;
|
|
4
3
|
};
|
|
4
|
+
export type RequiredDynamicParams = Record<string, any> & {};
|
|
5
5
|
export type EditorElement<ElementDynamicParams extends RequiredDynamicParams> = {
|
|
6
6
|
element: HTMLElement | undefined;
|
|
7
7
|
render: (params: ElementDynamicParams, isHidden: boolean) => void;
|
|
@@ -2,11 +2,11 @@ import { EditorElement, ElementFactory } from "../../EditorElement";
|
|
|
2
2
|
import { SuggestionItem } from "./SuggestionItem";
|
|
3
3
|
export type SuggestionsMenuStaticParams<T extends SuggestionItem> = {
|
|
4
4
|
itemCallback: (item: T) => void;
|
|
5
|
+
getReferenceRect: () => DOMRect;
|
|
5
6
|
};
|
|
6
7
|
export type SuggestionsMenuDynamicParams<T extends SuggestionItem> = {
|
|
7
8
|
items: T[];
|
|
8
9
|
keyboardHoveredItemIndex: number;
|
|
9
|
-
referenceRect: DOMRect;
|
|
10
10
|
};
|
|
11
11
|
export type SuggestionsMenu<T extends SuggestionItem> = EditorElement<SuggestionsMenuDynamicParams<T>>;
|
|
12
12
|
export type SuggestionsMenuFactory<T extends SuggestionItem> = ElementFactory<SuggestionsMenuStaticParams<T>, SuggestionsMenuDynamicParams<T>>;
|