@blocknote/core 0.3.0 → 0.4.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 +12698 -1341
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +50 -1
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +16 -5
- package/src/BlockNoteEditor.test.ts +12 -0
- package/src/BlockNoteEditor.ts +39 -15
- package/src/BlockNoteExtensions.ts +36 -32
- package/src/api/Editor.ts +226 -0
- package/src/api/blockManipulation/__snapshots__/blockManipulation.test.ts.snap +616 -0
- package/src/api/blockManipulation/blockManipulation.test.ts +172 -0
- package/src/api/blockManipulation/blockManipulation.ts +125 -0
- package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +346 -0
- package/src/api/formatConversions/formatConversions.test.ts +766 -0
- package/src/api/formatConversions/formatConversions.ts +86 -0
- package/src/api/formatConversions/removeUnderlinesRehypePlugin.ts +39 -0
- package/src/api/formatConversions/simplifyBlocksRehypePlugin.ts +125 -0
- package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +268 -0
- package/src/api/nodeConversions/nodeConversions.test.ts +244 -0
- package/src/api/nodeConversions/nodeConversions.ts +279 -0
- package/src/api/nodeConversions/testUtil.ts +61 -0
- package/src/api/util/nodeUtil.ts +38 -0
- package/src/editor.module.css +8 -1
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +7 -1
- package/src/extensions/Blocks/api/blockTypes.ts +90 -0
- package/src/extensions/Blocks/api/cursorPositionTypes.ts +5 -0
- package/src/extensions/Blocks/api/inlineContentTypes.ts +35 -0
- package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +4 -4
- package/src/extensions/Blocks/nodes/Block.module.css +39 -36
- package/src/extensions/Blocks/nodes/BlockContainer.ts +74 -23
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +23 -5
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +28 -6
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +149 -87
- package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +2 -2
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +3 -3
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +7 -12
- package/src/extensions/SlashMenu/SlashMenuItem.ts +4 -1
- package/src/extensions/SlashMenu/{defaultCommands.tsx → defaultSlashCommands.tsx} +34 -17
- package/src/extensions/SlashMenu/index.ts +7 -4
- package/src/extensions/UniqueID/UniqueID.ts +1 -1
- package/src/index.ts +4 -2
- package/src/shared/utils.ts +6 -0
- package/types/src/BlockNoteEditor.d.ts +13 -4
- package/types/src/BlockNoteEditor.test.d.ts +1 -0
- package/types/src/BlockNoteExtensions.d.ts +7 -3
- package/types/src/api/Editor.d.ts +93 -0
- package/types/src/api/blockManipulation/blockManipulation.d.ts +6 -0
- package/types/src/api/blockManipulation/blockManipulation.test.d.ts +1 -0
- package/types/src/api/formatConversions/formatConversions.d.ts +6 -0
- package/types/src/api/formatConversions/formatConversions.test.d.ts +1 -0
- package/types/src/api/formatConversions/removeUnderlinesRehypePlugin.d.ts +6 -0
- package/types/src/api/formatConversions/simplifyBlocksRehypePlugin.d.ts +16 -0
- package/types/src/api/nodeConversions/nodeConversions.d.ts +15 -0
- package/types/src/api/nodeConversions/nodeConversions.test.d.ts +1 -0
- package/types/src/api/nodeConversions/testUtil.d.ts +2 -0
- package/types/src/api/util/nodeUtil.d.ts +8 -0
- package/types/src/extensions/Blocks/api/blockTypes.d.ts +37 -0
- package/types/src/extensions/Blocks/api/cursorPositionTypes.d.ts +4 -0
- package/types/src/extensions/Blocks/api/inlineContentTypes.d.ts +29 -0
- package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +3 -3
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +15 -0
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +2 -2
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +1 -3
- package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +4 -1
- package/types/src/extensions/SlashMenu/index.d.ts +3 -3
- package/types/src/index.d.ts +4 -2
- package/types/src/shared/utils.d.ts +3 -0
- package/src/extensions/Blocks/apiTypes.ts +0 -48
- package/types/src/EditorElement.d.ts +0 -7
- package/types/src/api/Document.d.ts +0 -5
- package/types/src/extensions/Blocks/BlockAttributes.d.ts +0 -2
- package/types/src/extensions/Blocks/MultipleNodeSelection.d.ts +0 -24
- package/types/src/extensions/Blocks/apiTypes.d.ts +0 -16
- package/types/src/extensions/Blocks/nodes/Block.d.ts +0 -24
- package/types/src/extensions/Blocks/nodes/BlockContent/BlockContentTypes.d.ts +0 -4
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContentTypes.d.ts +0 -4
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContentTypes.d.ts +0 -2
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContentTypes.d.ts +0 -2
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContentTypes.d.ts +0 -2
- package/types/src/extensions/Blocks/nodes/BlockTypes/HeadingBlock/HeadingContent.d.ts +0 -8
- package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.d.ts +0 -8
- package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.d.ts +0 -2
- package/types/src/extensions/Blocks/nodes/BlockTypes/TextBlock/TextContent.d.ts +0 -6
- package/types/src/extensions/BubbleMenu/BubbleMenuExtension.d.ts +0 -8
- package/types/src/extensions/BubbleMenu/BubbleMenuFactoryTypes.d.ts +0 -27
- package/types/src/extensions/BubbleMenu/BubbleMenuPlugin.d.ts +0 -44
- package/types/src/extensions/DraggableBlocks/BlockMenuFactoryTypes.d.ts +0 -12
- package/types/src/extensions/DraggableBlocks/DragMenuFactoryTypes.d.ts +0 -18
- package/types/src/extensions/Hyperlinks/HyperlinkMark.d.ts +0 -8
- package/types/src/extensions/Hyperlinks/HyperlinkMenuFactoryTypes.d.ts +0 -11
- package/types/src/extensions/Hyperlinks/HyperlinkMenuPlugin.d.ts +0 -11
- package/types/src/extensions/Paragraph/FixedParagraph.d.ts +0 -1
- package/types/src/extensions/SlashMenu/defaultCommands.d.ts +0 -8
- package/types/src/utils.d.ts +0 -2
|
@@ -150,8 +150,10 @@ function setDragImage(view: EditorView, from: number, to = from) {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
// dataTransfer.setDragImage(element) only works if element is attached to the DOM.
|
|
153
|
+
unsetDragImage();
|
|
153
154
|
dragImageElement = parentClone;
|
|
154
|
-
dragImageElement.className =
|
|
155
|
+
dragImageElement.className =
|
|
156
|
+
dragImageElement.className + " " + styles.dragPreview;
|
|
155
157
|
document.body.appendChild(dragImageElement);
|
|
156
158
|
}
|
|
157
159
|
|
|
@@ -245,104 +247,164 @@ export class BlockMenuView {
|
|
|
245
247
|
|
|
246
248
|
this.blockMenu = blockMenuFactory(this.getStaticParams());
|
|
247
249
|
|
|
250
|
+
document.body.addEventListener("drop", this.onDrop, true);
|
|
251
|
+
document.body.addEventListener("dragover", this.onDragOver);
|
|
252
|
+
|
|
248
253
|
// Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.
|
|
249
|
-
document.body.addEventListener(
|
|
250
|
-
"mousemove",
|
|
251
|
-
(event) => {
|
|
252
|
-
if (this.menuFrozen) {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Editor itself may have padding or other styling which affects size/position, so we get the boundingRect of
|
|
257
|
-
// the first child (i.e. the blockGroup that wraps all blocks in the editor) for a more accurate bounding box.
|
|
258
|
-
const editorBoundingBox = (
|
|
259
|
-
this.editor.view.dom.firstChild! as HTMLElement
|
|
260
|
-
).getBoundingClientRect();
|
|
261
|
-
|
|
262
|
-
this.horizontalPosAnchor = editorBoundingBox.x;
|
|
263
|
-
|
|
264
|
-
// Gets block at mouse cursor's vertical position.
|
|
265
|
-
const coords = {
|
|
266
|
-
left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
|
|
267
|
-
top: event.clientY,
|
|
268
|
-
};
|
|
269
|
-
const block = getDraggableBlockFromCoords(coords, this.editor.view);
|
|
270
|
-
|
|
271
|
-
// Closes the menu if the mouse cursor is beyond the editor vertically.
|
|
272
|
-
if (!block) {
|
|
273
|
-
if (this.menuOpen) {
|
|
274
|
-
this.menuOpen = false;
|
|
275
|
-
this.blockMenu.hide();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.
|
|
282
|
-
if (
|
|
283
|
-
this.menuOpen &&
|
|
284
|
-
this.hoveredBlockContent?.hasAttribute("data-id") &&
|
|
285
|
-
this.hoveredBlockContent?.getAttribute("data-id") === block.id
|
|
286
|
-
) {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.
|
|
291
|
-
const blockContent = block.node.firstChild as HTMLElement;
|
|
292
|
-
this.hoveredBlockContent = blockContent;
|
|
293
|
-
|
|
294
|
-
if (!blockContent) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Shows or updates elements.
|
|
299
|
-
if (!this.menuOpen) {
|
|
300
|
-
this.menuOpen = true;
|
|
301
|
-
this.blockMenu.render(this.getDynamicParams(), true);
|
|
302
|
-
} else {
|
|
303
|
-
this.blockMenu.render(this.getDynamicParams(), false);
|
|
304
|
-
}
|
|
305
|
-
},
|
|
306
|
-
true
|
|
307
|
-
);
|
|
254
|
+
document.body.addEventListener("mousemove", this.onMouseMove, true);
|
|
308
255
|
|
|
309
256
|
// Hides and unfreezes the menu whenever the user selects the editor with the mouse or presses a key.
|
|
310
257
|
// TODO: Better integration with suggestions menu and only editor scope?
|
|
311
|
-
document.body.addEventListener(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (this.blockMenu.element?.contains(event.target as HTMLElement)) {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
if (this.menuOpen) {
|
|
319
|
-
this.menuOpen = false;
|
|
320
|
-
this.blockMenu.hide();
|
|
321
|
-
}
|
|
258
|
+
document.body.addEventListener("mousedown", this.onMouseDown, true);
|
|
259
|
+
document.body.addEventListener("keydown", this.onKeyDown, true);
|
|
260
|
+
}
|
|
322
261
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
262
|
+
/**
|
|
263
|
+
* If the event is outside of the editor contents,
|
|
264
|
+
* we dispatch a fake event, so that we can still drop the content
|
|
265
|
+
* when dragging / dropping to the side of the editor
|
|
266
|
+
*/
|
|
267
|
+
onDrop = (event: DragEvent) => {
|
|
268
|
+
if ((event as any).synthetic) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
let pos = this.editor.view.posAtCoords({
|
|
272
|
+
left: event.clientX,
|
|
273
|
+
top: event.clientY,
|
|
274
|
+
});
|
|
334
275
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
276
|
+
if (!pos || pos.inside === -1) {
|
|
277
|
+
const evt = new Event("drop", event) as any;
|
|
278
|
+
const editorBoundingBox = (
|
|
279
|
+
this.editor.view.dom.firstChild! as HTMLElement
|
|
280
|
+
).getBoundingClientRect();
|
|
281
|
+
evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;
|
|
282
|
+
evt.clientY = event.clientY;
|
|
283
|
+
evt.dataTransfer = event.dataTransfer;
|
|
284
|
+
evt.preventDefault = () => event.preventDefault();
|
|
285
|
+
evt.synthetic = true; // prevent recursion
|
|
286
|
+
// console.log("dispatch fake drop");
|
|
287
|
+
this.editor.view.dom.dispatchEvent(evt);
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* If the event is outside of the editor contents,
|
|
293
|
+
* we dispatch a fake event, so that we can still drop the content
|
|
294
|
+
* when dragging / dropping to the side of the editor
|
|
295
|
+
*/
|
|
296
|
+
onDragOver = (event: DragEvent) => {
|
|
297
|
+
if ((event as any).synthetic) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
let pos = this.editor.view.posAtCoords({
|
|
301
|
+
left: event.clientX,
|
|
302
|
+
top: event.clientY,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
if (!pos || pos.inside === -1) {
|
|
306
|
+
const evt = new Event("dragover", event) as any;
|
|
307
|
+
const editorBoundingBox = (
|
|
308
|
+
this.editor.view.dom.firstChild! as HTMLElement
|
|
309
|
+
).getBoundingClientRect();
|
|
310
|
+
evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;
|
|
311
|
+
evt.clientY = event.clientY;
|
|
312
|
+
evt.dataTransfer = event.dataTransfer;
|
|
313
|
+
evt.preventDefault = () => event.preventDefault();
|
|
314
|
+
evt.synthetic = true; // prevent recursion
|
|
315
|
+
// console.log("dispatch fake dragover");
|
|
316
|
+
this.editor.view.dom.dispatchEvent(evt);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
onKeyDown = (_event: KeyboardEvent) => {
|
|
321
|
+
if (this.menuOpen) {
|
|
322
|
+
this.menuOpen = false;
|
|
323
|
+
this.blockMenu.hide();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
this.menuFrozen = false;
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
onMouseDown = (event: MouseEvent) => {
|
|
330
|
+
if (this.blockMenu.element?.contains(event.target as HTMLElement)) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (this.menuOpen) {
|
|
335
|
+
this.menuOpen = false;
|
|
336
|
+
this.blockMenu.hide();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
this.menuFrozen = false;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
onMouseMove = (event: MouseEvent) => {
|
|
343
|
+
if (this.menuFrozen) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Editor itself may have padding or other styling which affects size/position, so we get the boundingRect of
|
|
348
|
+
// the first child (i.e. the blockGroup that wraps all blocks in the editor) for a more accurate bounding box.
|
|
349
|
+
const editorBoundingBox = (
|
|
350
|
+
this.editor.view.dom.firstChild! as HTMLElement
|
|
351
|
+
).getBoundingClientRect();
|
|
352
|
+
|
|
353
|
+
this.horizontalPosAnchor = editorBoundingBox.x;
|
|
354
|
+
|
|
355
|
+
// Gets block at mouse cursor's vertical position.
|
|
356
|
+
const coords = {
|
|
357
|
+
left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
|
|
358
|
+
top: event.clientY,
|
|
359
|
+
};
|
|
360
|
+
const block = getDraggableBlockFromCoords(coords, this.editor.view);
|
|
361
|
+
|
|
362
|
+
// Closes the menu if the mouse cursor is beyond the editor vertically.
|
|
363
|
+
if (!block) {
|
|
364
|
+
if (this.menuOpen) {
|
|
365
|
+
this.menuOpen = false;
|
|
366
|
+
this.blockMenu.hide();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.
|
|
373
|
+
if (
|
|
374
|
+
this.menuOpen &&
|
|
375
|
+
this.hoveredBlockContent?.hasAttribute("data-id") &&
|
|
376
|
+
this.hoveredBlockContent?.getAttribute("data-id") === block.id
|
|
377
|
+
) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.
|
|
382
|
+
const blockContent = block.node.firstChild as HTMLElement;
|
|
383
|
+
this.hoveredBlockContent = blockContent;
|
|
384
|
+
|
|
385
|
+
if (!blockContent) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Shows or updates elements.
|
|
390
|
+
if (!this.menuOpen) {
|
|
391
|
+
this.menuOpen = true;
|
|
392
|
+
this.blockMenu.render(this.getDynamicParams(), true);
|
|
393
|
+
} else {
|
|
394
|
+
this.blockMenu.render(this.getDynamicParams(), false);
|
|
395
|
+
}
|
|
396
|
+
};
|
|
340
397
|
|
|
341
398
|
destroy() {
|
|
342
399
|
if (this.menuOpen) {
|
|
343
400
|
this.menuOpen = false;
|
|
344
401
|
this.blockMenu.hide();
|
|
345
402
|
}
|
|
403
|
+
document.body.removeEventListener("mousemove", this.onMouseMove);
|
|
404
|
+
document.body.removeEventListener("dragover", this.onDragOver);
|
|
405
|
+
document.body.removeEventListener("drop", this.onDrop);
|
|
406
|
+
document.body.removeEventListener("mousedown", this.onMouseDown);
|
|
407
|
+
document.body.removeEventListener("keydown", this.onKeyDown);
|
|
346
408
|
}
|
|
347
409
|
|
|
348
410
|
addBlock() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EditorElement, ElementFactory } from "../../shared/EditorElement";
|
|
2
|
-
import { Block,
|
|
2
|
+
import { Block, PartialBlock } from "../Blocks/api/blockTypes";
|
|
3
3
|
|
|
4
4
|
export type FormattingToolbarStaticParams = {
|
|
5
5
|
toggleBold: () => void;
|
|
@@ -17,7 +17,7 @@ export type FormattingToolbarStaticParams = {
|
|
|
17
17
|
increaseBlockIndent: () => void;
|
|
18
18
|
decreaseBlockIndent: () => void;
|
|
19
19
|
|
|
20
|
-
updateBlock: (
|
|
20
|
+
updateBlock: (updatedBlock: PartialBlock) => void;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export type FormattingToolbarDynamicParams = {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "@tiptap/core";
|
|
7
7
|
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
8
8
|
import { EditorView } from "prosemirror-view";
|
|
9
|
-
import { Block,
|
|
9
|
+
import { Block, PartialBlock } from "../Blocks/api/blockTypes";
|
|
10
10
|
import { getBlockInfoFromPos } from "../Blocks/helpers/getBlockInfoFromPos";
|
|
11
11
|
import {
|
|
12
12
|
FormattingToolbar,
|
|
@@ -288,11 +288,11 @@ export class FormattingToolbarView {
|
|
|
288
288
|
this.editor.view.focus();
|
|
289
289
|
this.editor.commands.liftListItem("blockContainer");
|
|
290
290
|
},
|
|
291
|
-
updateBlock: (
|
|
291
|
+
updateBlock: (updatedBlock: PartialBlock) => {
|
|
292
292
|
this.editor.view.focus();
|
|
293
293
|
this.editor.commands.BNUpdateBlock(
|
|
294
294
|
this.editor.state.selection.from,
|
|
295
|
-
|
|
295
|
+
updatedBlock
|
|
296
296
|
);
|
|
297
297
|
},
|
|
298
298
|
};
|
|
@@ -2,11 +2,10 @@ import { Extension } from "@tiptap/core";
|
|
|
2
2
|
import { PluginKey } from "prosemirror-state";
|
|
3
3
|
import { createSuggestionPlugin } from "../../shared/plugins/suggestion/SuggestionPlugin";
|
|
4
4
|
import { SuggestionsMenuFactory } from "../../shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
|
|
5
|
-
import defaultCommands from "./defaultCommands";
|
|
6
5
|
import { SlashMenuItem } from "./SlashMenuItem";
|
|
7
6
|
|
|
8
7
|
export type SlashMenuOptions = {
|
|
9
|
-
commands:
|
|
8
|
+
commands: SlashMenuItem[] | undefined;
|
|
10
9
|
slashMenuFactory: SuggestionsMenuFactory<any> | undefined;
|
|
11
10
|
};
|
|
12
11
|
|
|
@@ -17,16 +16,18 @@ export const SlashMenuExtension = Extension.create<SlashMenuOptions>({
|
|
|
17
16
|
|
|
18
17
|
addOptions() {
|
|
19
18
|
return {
|
|
20
|
-
commands:
|
|
21
|
-
slashMenuFactory: undefined,
|
|
19
|
+
commands: undefined,
|
|
20
|
+
slashMenuFactory: undefined,
|
|
22
21
|
};
|
|
23
22
|
},
|
|
24
23
|
|
|
25
24
|
addProseMirrorPlugins() {
|
|
26
|
-
if (!this.options.slashMenuFactory) {
|
|
27
|
-
throw new Error("
|
|
25
|
+
if (!this.options.slashMenuFactory || !this.options.commands) {
|
|
26
|
+
throw new Error("required args not defined for SlashMenuExtension");
|
|
28
27
|
}
|
|
29
28
|
|
|
29
|
+
const commands = this.options.commands;
|
|
30
|
+
|
|
30
31
|
return [
|
|
31
32
|
createSuggestionPlugin<SlashMenuItem>({
|
|
32
33
|
pluginKey: SlashMenuPluginKey,
|
|
@@ -34,12 +35,6 @@ export const SlashMenuExtension = Extension.create<SlashMenuOptions>({
|
|
|
34
35
|
defaultTriggerCharacter: "/",
|
|
35
36
|
suggestionsMenuFactory: this.options.slashMenuFactory!,
|
|
36
37
|
items: (query) => {
|
|
37
|
-
const commands = [];
|
|
38
|
-
|
|
39
|
-
for (const key in this.options.commands) {
|
|
40
|
-
commands.push(this.options.commands[key]);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
38
|
return commands.filter((cmd: SlashMenuItem) => cmd.match(query));
|
|
44
39
|
},
|
|
45
40
|
onSelectItem: ({ item, editor, range }) => {
|
|
@@ -17,7 +17,10 @@ export class SlashMenuItem implements SuggestionItem {
|
|
|
17
17
|
constructor(
|
|
18
18
|
public readonly name: string,
|
|
19
19
|
public readonly execute: (editor: Editor, range: Range) => void,
|
|
20
|
-
public readonly aliases: string[] = []
|
|
20
|
+
public readonly aliases: string[] = [],
|
|
21
|
+
public readonly group: string,
|
|
22
|
+
public readonly hint?: string,
|
|
23
|
+
public readonly shortcut?: string
|
|
21
24
|
) {}
|
|
22
25
|
|
|
23
26
|
match(query: string): boolean {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { SlashMenuItem } from "./SlashMenuItem";
|
|
2
1
|
import { Editor, Range } from "@tiptap/core";
|
|
2
|
+
import { formatKeyboardShortcut } from "../../shared/utils";
|
|
3
|
+
import { SlashMenuItem } from "./SlashMenuItem";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* An array containing commands for creating all default blocks.
|
|
6
7
|
*/
|
|
7
|
-
const
|
|
8
|
+
export const defaultSlashCommands: SlashMenuItem[] = [
|
|
8
9
|
// Command for creating a level 1 heading
|
|
9
|
-
|
|
10
|
+
new SlashMenuItem(
|
|
10
11
|
"Heading",
|
|
11
12
|
(editor: Editor, range: Range) => {
|
|
12
13
|
return editor
|
|
@@ -21,11 +22,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
|
21
22
|
})
|
|
22
23
|
.run();
|
|
23
24
|
},
|
|
24
|
-
["h", "heading1", "h1"]
|
|
25
|
+
["h", "heading1", "h1"],
|
|
26
|
+
"Headings",
|
|
27
|
+
"Used for a top-level heading",
|
|
28
|
+
formatKeyboardShortcut("Mod-Alt-1")
|
|
25
29
|
),
|
|
26
30
|
|
|
27
31
|
// Command for creating a level 2 heading
|
|
28
|
-
|
|
32
|
+
new SlashMenuItem(
|
|
29
33
|
"Heading 2",
|
|
30
34
|
(editor: Editor, range: Range) => {
|
|
31
35
|
return editor
|
|
@@ -40,11 +44,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
|
40
44
|
})
|
|
41
45
|
.run();
|
|
42
46
|
},
|
|
43
|
-
["h2", "heading2", "subheading"]
|
|
47
|
+
["h2", "heading2", "subheading"],
|
|
48
|
+
"Headings",
|
|
49
|
+
"Used for key sections",
|
|
50
|
+
formatKeyboardShortcut("Mod-Alt-2")
|
|
44
51
|
),
|
|
45
52
|
|
|
46
53
|
// Command for creating a level 3 heading
|
|
47
|
-
|
|
54
|
+
new SlashMenuItem(
|
|
48
55
|
"Heading 3",
|
|
49
56
|
(editor: Editor, range: Range) => {
|
|
50
57
|
return editor
|
|
@@ -59,11 +66,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
|
59
66
|
})
|
|
60
67
|
.run();
|
|
61
68
|
},
|
|
62
|
-
["h3", "heading3", "subheading"]
|
|
69
|
+
["h3", "heading3", "subheading"],
|
|
70
|
+
"Headings",
|
|
71
|
+
"Used for subsections and group headings",
|
|
72
|
+
formatKeyboardShortcut("Mod-Alt-3")
|
|
63
73
|
),
|
|
64
74
|
|
|
65
75
|
// Command for creating an ordered list
|
|
66
|
-
|
|
76
|
+
new SlashMenuItem(
|
|
67
77
|
"Numbered List",
|
|
68
78
|
(editor: Editor, range: Range) => {
|
|
69
79
|
return editor
|
|
@@ -76,11 +86,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
|
76
86
|
})
|
|
77
87
|
.run();
|
|
78
88
|
},
|
|
79
|
-
["li", "list", "numberedlist", "numbered list"]
|
|
89
|
+
["li", "list", "numberedlist", "numbered list"],
|
|
90
|
+
"Basic blocks",
|
|
91
|
+
"Used to display a numbered list",
|
|
92
|
+
"Mod-Alt-7"
|
|
80
93
|
),
|
|
81
94
|
|
|
82
95
|
// Command for creating a bullet list
|
|
83
|
-
|
|
96
|
+
new SlashMenuItem(
|
|
84
97
|
"Bullet List",
|
|
85
98
|
(editor: Editor, range: Range) => {
|
|
86
99
|
return editor
|
|
@@ -93,11 +106,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
|
93
106
|
})
|
|
94
107
|
.run();
|
|
95
108
|
},
|
|
96
|
-
["ul", "list", "bulletlist", "bullet list"]
|
|
109
|
+
["ul", "list", "bulletlist", "bullet list"],
|
|
110
|
+
"Basic blocks",
|
|
111
|
+
"Used to display an unordered list",
|
|
112
|
+
"Mod-Alt-9"
|
|
97
113
|
),
|
|
98
114
|
|
|
99
115
|
// Command for creating a paragraph (pretty useless)
|
|
100
|
-
|
|
116
|
+
new SlashMenuItem(
|
|
101
117
|
"Paragraph",
|
|
102
118
|
(editor: Editor, range: Range) => {
|
|
103
119
|
return editor
|
|
@@ -110,7 +126,10 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
|
110
126
|
})
|
|
111
127
|
.run();
|
|
112
128
|
},
|
|
113
|
-
["p"]
|
|
129
|
+
["p"],
|
|
130
|
+
"Basic blocks",
|
|
131
|
+
"Used for the body of your document",
|
|
132
|
+
"Mod-Alt-0"
|
|
114
133
|
),
|
|
115
134
|
|
|
116
135
|
// replaceRangeWithNode(editor, range, node);
|
|
@@ -216,6 +235,4 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
|
216
235
|
// TableIcon,
|
|
217
236
|
// "Used to create a simple table"
|
|
218
237
|
// ),
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
export default defaultCommands;
|
|
238
|
+
];
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { defaultSlashCommands } from "./defaultSlashCommands";
|
|
1
2
|
import { SlashMenuExtension } from "./SlashMenuExtension";
|
|
2
|
-
import
|
|
3
|
+
import { SlashMenuItem } from "./SlashMenuItem";
|
|
3
4
|
|
|
4
|
-
export {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
export {
|
|
6
|
+
defaultSlashCommands,
|
|
7
|
+
SlashMenuItem as SlashCommand,
|
|
8
|
+
SlashMenuExtension,
|
|
9
|
+
};
|
|
@@ -123,7 +123,7 @@ const UniqueID = Extension.create({
|
|
|
123
123
|
new Plugin({
|
|
124
124
|
key: new PluginKey("uniqueID"),
|
|
125
125
|
appendTransaction: (transactions, oldState, newState) => {
|
|
126
|
-
console.log("appendTransaction");
|
|
126
|
+
// console.log("appendTransaction");
|
|
127
127
|
const docChanges =
|
|
128
128
|
transactions.some((transaction) => transaction.docChanged) &&
|
|
129
129
|
!oldState.doc.eq(newState.doc);
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export * from "./BlockNoteEditor";
|
|
2
2
|
export * from "./BlockNoteExtensions";
|
|
3
|
-
export
|
|
4
|
-
export * from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
|
|
3
|
+
export * from "./extensions/Blocks/api/blockTypes";
|
|
5
4
|
export * from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
|
|
5
|
+
export * from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
|
|
6
6
|
export * from "./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes";
|
|
7
|
+
export { defaultSlashCommands } from "./extensions/SlashMenu/defaultSlashCommands";
|
|
7
8
|
export * from "./extensions/SlashMenu/SlashMenuItem";
|
|
8
9
|
export * from "./shared/EditorElement";
|
|
9
10
|
export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
|
|
10
11
|
export * from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
|
|
12
|
+
export * from "../src/api/Editor";
|
package/src/shared/utils.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import { Editor
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
import { Editor as EditorAPI } from "./api/Editor";
|
|
2
3
|
import { UiFactories } from "./BlockNoteExtensions";
|
|
3
|
-
|
|
4
|
+
import { SlashCommand } from "./extensions/SlashMenu";
|
|
5
|
+
export type BlockNoteEditorOptions = {
|
|
4
6
|
enableBlockNoteExtensions: boolean;
|
|
5
7
|
disableHistoryExtension: boolean;
|
|
6
8
|
uiFactories: UiFactories;
|
|
9
|
+
slashCommands: SlashCommand[];
|
|
10
|
+
parentElement: HTMLElement;
|
|
11
|
+
editorDOMAttributes: Record<string, string>;
|
|
12
|
+
onUpdate: (editor: BlockNoteEditor) => void;
|
|
13
|
+
onCreate: (editor: BlockNoteEditor) => void;
|
|
14
|
+
_tiptapOptions: any;
|
|
7
15
|
};
|
|
8
|
-
export declare class BlockNoteEditor {
|
|
9
|
-
readonly
|
|
16
|
+
export declare class BlockNoteEditor extends EditorAPI {
|
|
17
|
+
readonly _tiptapEditor: Editor & {
|
|
10
18
|
contentComponent: any;
|
|
11
19
|
};
|
|
20
|
+
get domElement(): HTMLDivElement;
|
|
12
21
|
constructor(options?: Partial<BlockNoteEditorOptions>);
|
|
13
22
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Extensions } from "@tiptap/core";
|
|
2
|
+
import { BlockSideMenuFactory } from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
|
|
2
3
|
import { FormattingToolbarFactory } from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
|
|
3
4
|
import { HyperlinkToolbarFactory } from "./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes";
|
|
4
|
-
import {
|
|
5
|
-
import { BlockSideMenuFactory } from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
|
|
5
|
+
import { SlashCommand } from "./extensions/SlashMenu";
|
|
6
6
|
import { SlashMenuItem } from "./extensions/SlashMenu/SlashMenuItem";
|
|
7
|
+
import { SuggestionsMenuFactory } from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
|
|
7
8
|
export type UiFactories = Partial<{
|
|
8
9
|
formattingToolbarFactory: FormattingToolbarFactory;
|
|
9
10
|
hyperlinkToolbarFactory: HyperlinkToolbarFactory;
|
|
@@ -13,4 +14,7 @@ export type UiFactories = Partial<{
|
|
|
13
14
|
/**
|
|
14
15
|
* Get all the Tiptap extensions BlockNote is configured with by default
|
|
15
16
|
*/
|
|
16
|
-
export declare const getBlockNoteExtensions: (
|
|
17
|
+
export declare const getBlockNoteExtensions: (opts: {
|
|
18
|
+
uiFactories: UiFactories;
|
|
19
|
+
slashCommands: SlashCommand[];
|
|
20
|
+
}) => Extensions;
|