1- import { Plugin } from 'prosemirror-state' // eslint-disable-line
1+ import { Plugin } from 'prosemirror-state'
22
33import { getRelativeSelection } from './sync-plugin.js'
44import { UndoManager , Item , ContentType , XmlElement , Text } from 'yjs'
55import { yUndoPluginKey , ySyncPluginKey } from './keys.js'
66
7- export const undo = state => {
7+ /**
8+ * @typedef {Object } UndoPluginState
9+ * @property {import('yjs').UndoManager } undoManager
10+ * @property {ReturnType<typeof getRelativeSelection> | null } prevSel
11+ * @property {boolean } hasUndoOps
12+ * @property {boolean } hasRedoOps
13+ */
14+
15+ /**
16+ * Undo the last user action if there are undo operations available
17+ * @type {import('prosemirror-state').Command }
18+ */
19+ export const undoCommand = ( state , dispatch ) => {
820 const undoManager = yUndoPluginKey . getState ( state ) . undoManager
9- if ( undoManager != null ) {
21+ if ( undoManager == null || ! undoManager . undoStack . length ) {
22+ return false
23+ }
24+
25+ if ( dispatch ) {
1026 undoManager . undo ( )
11- return true
1227 }
28+ return true
1329}
1430
15- export const redo = state => {
31+ /**
32+ * Redo the last user action if there are redo operations available
33+ * @type {import('prosemirror-state').Command }
34+ */
35+ export const redoCommand = ( state , dispatch ) => {
1636 const undoManager = yUndoPluginKey . getState ( state ) . undoManager
17- if ( undoManager != null ) {
37+ if ( undoManager == null || ! undoManager . redoStack . length ) {
38+ return false
39+ }
40+
41+ if ( dispatch ) {
1842 undoManager . redo ( )
19- return true
2043 }
44+ return true
45+ }
46+
47+ /**
48+ * Undo the last user action
49+ * @param {import('prosemirror-state').EditorState } state
50+ * @returns {boolean }
51+ */
52+ export const undo = ( state ) => {
53+ return undoCommand ( state , ( ) => { } )
54+ }
55+
56+ /**
57+ * Redo the last user action
58+ * @param {import('prosemirror-state').EditorState } state
59+ * @returns {boolean }
60+ */
61+ export const redo = ( state ) => {
62+ return redoCommand ( state , ( ) => { } )
2163}
2264
2365export const defaultProtectedNodes = new Set ( [ 'paragraph' ] )
2466
67+ /**
68+ * @param {import('yjs').Item } item
69+ * @param {Set<string> } protectedNodes
70+ * @returns {boolean }
71+ */
2572export const defaultDeleteFilter = ( item , protectedNodes ) => ! ( item instanceof Item ) ||
2673! ( item . content instanceof ContentType ) ||
2774! ( item . content . type instanceof Text ||
2875 ( item . content . type instanceof XmlElement && protectedNodes . has ( item . content . type . nodeName ) ) ) ||
2976item . content . type . _length === 0
3077
78+ /**
79+ * @param {object } [options]
80+ * @param {Set<string> } [options.protectedNodes]
81+ * @param {any[] } [options.trackedOrigins]
82+ * @param {import('yjs').UndoManager | null } [options.undoManager]
83+ */
3184export const yUndoPlugin = ( { protectedNodes = defaultProtectedNodes , trackedOrigins = [ ] , undoManager = null } = { } ) => new Plugin ( {
3285 key : yUndoPluginKey ,
3386 state : {
@@ -46,9 +99,6 @@ export const yUndoPlugin = ({ protectedNodes = defaultProtectedNodes, trackedOri
4699 hasRedoOps : _undoManager . redoStack . length > 0
47100 }
48101 } ,
49- /**
50- * @returns {any }
51- */
52102 apply : ( tr , val , oldState , state ) => {
53103 const binding = ySyncPluginKey . getState ( state ) . binding
54104 const undoManager = val . undoManager
0 commit comments