File tree Expand file tree Collapse file tree 3 files changed +95
-0
lines changed Expand file tree Collapse file tree 3 files changed +95
-0
lines changed Original file line number Diff line number Diff line change @@ -120,6 +120,7 @@ import { EventEmitter } from "../util/EventEmitter.js";
120
120
import { BlockNoteExtension } from "./BlockNoteExtension.js" ;
121
121
122
122
import "../style.css" ;
123
+ import { BlockChangePlugin } from "../extensions/BlockChange/BlockChangePlugin.js" ;
123
124
124
125
/**
125
126
* A factory function that returns a BlockNoteExtension
@@ -1596,6 +1597,32 @@ export class BlockNoteEditor<
1596
1597
( this . extensions [ "yCursorPlugin" ] as CursorPlugin ) . updateUser ( user ) ;
1597
1598
}
1598
1599
1600
+ /**
1601
+ * Registers a callback which will be called before any change is applied to the editor, allowing you to cancel the change.
1602
+ */
1603
+ public beforeChange (
1604
+ /**
1605
+ * If the callback returns `false`, the change will be canceled & not applied to the editor.
1606
+ */
1607
+ callback : (
1608
+ editor : BlockNoteEditor < BSchema , ISchema , SSchema > ,
1609
+ context : {
1610
+ getChanges : ( ) => BlocksChanged < BSchema , ISchema , SSchema > ;
1611
+ tr : Transaction ;
1612
+ } ,
1613
+ ) => boolean | void ,
1614
+ ) : ( ) => void {
1615
+ if ( this . headless ) {
1616
+ return ( ) => {
1617
+ // noop
1618
+ } ;
1619
+ }
1620
+
1621
+ return ( this . extensions [ "blockChange" ] as BlockChangePlugin ) . subscribe (
1622
+ ( context ) => callback ( this , context ) ,
1623
+ ) ;
1624
+ }
1625
+
1599
1626
/**
1600
1627
* A callback function that runs whenever the editor's contents change.
1601
1628
*
Original file line number Diff line number Diff line change @@ -11,6 +11,7 @@ import { createPasteFromClipboardExtension } from "../api/clipboard/fromClipboar
11
11
import { createCopyToClipboardExtension } from "../api/clipboard/toClipboard/copyExtension.js" ;
12
12
import type { ThreadStore } from "../comments/index.js" ;
13
13
import { BackgroundColorExtension } from "../extensions/BackgroundColor/BackgroundColorExtension.js" ;
14
+ import { BlockChangePlugin } from "../extensions/BlockChange/BlockChangePlugin.js" ;
14
15
import { CursorPlugin } from "../extensions/Collaboration/CursorPlugin.js" ;
15
16
import { SyncPlugin } from "../extensions/Collaboration/SyncPlugin.js" ;
16
17
import { UndoPlugin } from "../extensions/Collaboration/UndoPlugin.js" ;
@@ -146,6 +147,7 @@ export const getBlockNoteExtensions = <
146
147
}
147
148
148
149
ret [ "nodeSelectionKeyboard" ] = new NodeSelectionKeyboardPlugin ( ) ;
150
+ ret [ "blockChange" ] = new BlockChangePlugin ( ) ;
149
151
150
152
ret [ "showSelection" ] = new ShowSelectionPlugin ( opts . editor ) ;
151
153
Original file line number Diff line number Diff line change
1
+ import { Plugin , Transaction } from "prosemirror-state" ;
2
+ import { getBlocksChangedByTransaction } from "../../api/nodeUtil.js" ;
3
+ import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js" ;
4
+ import { BlocksChanged } from "../../index.js" ;
5
+
6
+ /**
7
+ * This plugin can filter transactions before they are applied to the editor, but with a higher-level API than `filterTransaction` from prosemirror.
8
+ */
9
+ export class BlockChangePlugin extends BlockNoteExtension {
10
+ public static key ( ) {
11
+ return "blockChange" ;
12
+ }
13
+
14
+ private beforeChangeCallbacks : ( ( context : {
15
+ getChanges : ( ) => BlocksChanged < any , any , any > ;
16
+ tr : Transaction ;
17
+ } ) => boolean | void ) [ ] = [ ] ;
18
+
19
+ constructor ( ) {
20
+ super ( ) ;
21
+
22
+ this . addProsemirrorPlugin (
23
+ new Plugin ( {
24
+ filterTransaction : ( tr ) => {
25
+ let changes :
26
+ | ReturnType < typeof getBlocksChangedByTransaction >
27
+ | undefined = undefined ;
28
+
29
+ return this . beforeChangeCallbacks . reduce ( ( acc , cb ) => {
30
+ if ( acc === false ) {
31
+ // We only care that we hit a `false` result, so we can stop iterating.
32
+ return acc ;
33
+ }
34
+ return (
35
+ cb ( {
36
+ getChanges ( ) {
37
+ if ( changes ) {
38
+ return changes ;
39
+ }
40
+ changes = getBlocksChangedByTransaction ( tr ) ;
41
+ return changes ;
42
+ } ,
43
+ tr,
44
+ } ) !== false
45
+ ) ;
46
+ } , true ) ;
47
+ } ,
48
+ } ) ,
49
+ ) ;
50
+ }
51
+
52
+ public subscribe (
53
+ callback : ( context : {
54
+ getChanges : ( ) => BlocksChanged < any , any , any > ;
55
+ tr : Transaction ;
56
+ } ) => boolean | void ,
57
+ ) {
58
+ this . beforeChangeCallbacks . push ( callback ) ;
59
+
60
+ return ( ) => {
61
+ this . beforeChangeCallbacks = this . beforeChangeCallbacks . filter (
62
+ ( cb ) => cb !== callback ,
63
+ ) ;
64
+ } ;
65
+ }
66
+ }
You can’t perform that action at this time.
0 commit comments