{
  "version": 3,
  "sources": ["../src/undo-manager.ts"],
  "sourcesContent": ["/**\n * External dependencies\n */\nimport type * as Y from 'yjs';\n\n/**\n * WordPress dependencies\n */\nimport type { HistoryRecord } from '@wordpress/undo-manager';\n\n/**\n * Internal dependencies\n */\nimport { LOCAL_EDITOR_ORIGIN } from './config';\nimport { YMultiDocUndoManager } from './y-utilities/y-multidoc-undomanager';\nimport type { ObjectData, RecordHandlers, SyncUndoManager } from './types';\n\ninterface StackItemEvent {\n\tstackItem: { meta: Map< any, any > };\n\torigin: any;\n\ttype: 'undo' | 'redo';\n\tchangedParentTypes: Map< Y.AbstractType< any >, Y.YEvent< any >[] >;\n\tydoc: Y.Doc;\n}\n\n/**\n * Implementation of the WordPress UndoManager interface using YMultiDocUndoManager\n * internally. This allows undo/redo operations to be transacted against multiple\n * CRDT documents (one per entity) and giving each peer their own undo/redo stack\n * without conflicts.\n */\nexport function createUndoManager(): SyncUndoManager {\n\tconst yUndoManager = new YMultiDocUndoManager( [], {\n\t\t// Throttle undo/redo captures after 500ms of inactivity.\n\t\t// 500 was selected from subjective local UX testing, shorter timeouts\n\t\t// may cause mid-word undo stack items.\n\t\tcaptureTimeout: 500,\n\t\t// Ensure that we only scope the undo/redo to the current editor.\n\t\t// The yjs document's clientID is added once it's available.\n\t\ttrackedOrigins: new Set( [ LOCAL_EDITOR_ORIGIN ] ),\n\t} );\n\n\treturn {\n\t\t/**\n\t\t * Record changes into the history.\n\t\t * Since Yjs automatically tracks changes, this method translates the WordPress\n\t\t * HistoryRecord format into Yjs operations.\n\t\t *\n\t\t * @param _record   A record of changes to record.\n\t\t * @param _isStaged Whether to immediately create an undo point or not.\n\t\t */\n\t\taddRecord(\n\t\t\t_record?: HistoryRecord< ObjectData >,\n\t\t\t_isStaged = false // eslint-disable-line @typescript-eslint/no-unused-vars\n\t\t): void {\n\t\t\t// This is a no-op for Yjs since it automatically tracks changes.\n\t\t\t// If needed, we could implement custom logic to handle specific records.\n\t\t},\n\n\t\t/**\n\t\t * Add a Yjs map to the scope of the undo manager.\n\t\t *\n\t\t * @param {Y.Map< any >} ymap                     The Yjs map to add to the scope.\n\t\t * @param                handlers\n\t\t * @param                handlers.addUndoMeta\n\t\t * @param                handlers.restoreUndoMeta\n\t\t */\n\t\taddToScope(\n\t\t\tymap: Y.Map< any >,\n\t\t\thandlers: Pick< RecordHandlers, 'addUndoMeta' | 'restoreUndoMeta' >\n\t\t): void {\n\t\t\tif ( ymap.doc === null ) {\n\t\t\t\t// Necessary for a type check, but this shouldn't happen.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst ydoc = ymap.doc;\n\t\t\tyUndoManager.addToScope( ymap );\n\n\t\t\tconst { addUndoMeta, restoreUndoMeta } = handlers;\n\n\t\t\tyUndoManager.on( 'stack-item-added', ( event: StackItemEvent ) => {\n\t\t\t\taddUndoMeta( ydoc, event.stackItem.meta );\n\t\t\t} );\n\n\t\t\tyUndoManager.on( 'stack-item-popped', ( event: StackItemEvent ) => {\n\t\t\t\trestoreUndoMeta( ydoc, event.stackItem.meta );\n\t\t\t} );\n\t\t},\n\n\t\t/**\n\t\t * Undo the last recorded changes.\n\t\t *\n\t\t */\n\t\tundo(): HistoryRecord< ObjectData > | undefined {\n\t\t\tif ( ! yUndoManager.canUndo() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Perform the undo operation\n\t\t\tyUndoManager.undo();\n\n\t\t\t// Intentionally return an empty array, because the SyncProvider will update\n\t\t\t// the entity record based on the Yjs document changes.\n\t\t\treturn [];\n\t\t},\n\n\t\t/**\n\t\t * Redo the last undone changes.\n\t\t */\n\t\tredo(): HistoryRecord< ObjectData > | undefined {\n\t\t\tif ( ! yUndoManager.canRedo() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Perform the redo operation\n\t\t\tyUndoManager.redo();\n\n\t\t\t// Intentionally return an empty array, because the SyncProvider will update\n\t\t\t// the entity record based on the Yjs document changes.\n\t\t\treturn [];\n\t\t},\n\n\t\t/**\n\t\t * Check if there are changes that can be undone.\n\t\t *\n\t\t * @return {boolean} Whether there are changes to undo.\n\t\t */\n\t\thasUndo(): boolean {\n\t\t\treturn yUndoManager.canUndo();\n\t\t},\n\n\t\t/**\n\t\t * Check if there are changes that can be redone.\n\t\t *\n\t\t * @return {boolean} Whether there are changes to redo.\n\t\t */\n\t\thasRedo(): boolean {\n\t\t\treturn yUndoManager.canRedo();\n\t\t},\n\n\t\t/**\n\t\t * Stop capturing changes into the current undo item.\n\t\t * The next change will create a new undo item.\n\t\t */\n\t\tstopCapturing(): void {\n\t\t\tyUndoManager.stopCapturing();\n\t\t},\n\t};\n}\n"],
  "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAaA,oBAAoC;AACpC,oCAAqC;AAiB9B,SAAS,oBAAqC;AACpD,QAAM,eAAe,IAAI,mDAAsB,CAAC,GAAG;AAAA;AAAA;AAAA;AAAA,IAIlD,gBAAgB;AAAA;AAAA;AAAA,IAGhB,gBAAgB,oBAAI,IAAK,CAAE,iCAAoB,CAAE;AAAA,EAClD,CAAE;AAEF,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASN,UACC,SACA,YAAY,OACL;AAAA,IAGR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,WACC,MACA,UACO;AACP,UAAK,KAAK,QAAQ,MAAO;AAExB;AAAA,MACD;AAEA,YAAM,OAAO,KAAK;AAClB,mBAAa,WAAY,IAAK;AAE9B,YAAM,EAAE,aAAa,gBAAgB,IAAI;AAEzC,mBAAa,GAAI,oBAAoB,CAAE,UAA2B;AACjE,oBAAa,MAAM,MAAM,UAAU,IAAK;AAAA,MACzC,CAAE;AAEF,mBAAa,GAAI,qBAAqB,CAAE,UAA2B;AAClE,wBAAiB,MAAM,MAAM,UAAU,IAAK;AAAA,MAC7C,CAAE;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAgD;AAC/C,UAAK,CAAE,aAAa,QAAQ,GAAI;AAC/B;AAAA,MACD;AAGA,mBAAa,KAAK;AAIlB,aAAO,CAAC;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,OAAgD;AAC/C,UAAK,CAAE,aAAa,QAAQ,GAAI;AAC/B;AAAA,MACD;AAGA,mBAAa,KAAK;AAIlB,aAAO,CAAC;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,UAAmB;AAClB,aAAO,aAAa,QAAQ;AAAA,IAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,UAAmB;AAClB,aAAO,aAAa,QAAQ;AAAA,IAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,gBAAsB;AACrB,mBAAa,cAAc;AAAA,IAC5B;AAAA,EACD;AACD;",
  "names": []
}
