@portabletext/editor 1.0.13 → 1.0.14
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/lib/index.esm.js +100 -66
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +100 -66
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +100 -66
- package/lib/index.mjs.map +1 -1
- package/package.json +12 -12
- package/src/editor/hooks/useSyncValue.ts +8 -17
- package/src/editor/plugins/createWithMaxBlocks.ts +20 -0
- package/src/editor/plugins/createWithObjectKeys.ts +22 -11
- package/src/editor/plugins/createWithPatches.ts +3 -6
- package/src/editor/plugins/createWithPlaceholderBlock.ts +20 -0
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +41 -15
- package/src/editor/plugins/createWithUndoRedo.ts +5 -3
- package/src/utils/withUndoRedo.ts +34 -0
- package/src/utils/withPreserveKeys.ts +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -47,22 +47,22 @@
|
|
|
47
47
|
"is-hotkey-esm": "^1.0.0",
|
|
48
48
|
"lodash": "^4.17.21",
|
|
49
49
|
"slate": "0.103.0",
|
|
50
|
-
"slate-react": "0.
|
|
50
|
+
"slate-react": "0.108.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@jest/globals": "^29.7.0",
|
|
54
54
|
"@playwright/test": "1.46.0",
|
|
55
55
|
"@portabletext/toolkit": "^2.0.15",
|
|
56
|
-
"@sanity/block-tools": "^3.
|
|
56
|
+
"@sanity/block-tools": "^3.54.0",
|
|
57
57
|
"@sanity/diff-match-patch": "^3.1.1",
|
|
58
58
|
"@sanity/eslint-config-i18n": "^1.1.0",
|
|
59
59
|
"@sanity/eslint-config-studio": "^4.0.0",
|
|
60
60
|
"@sanity/pkg-utils": "^6.10.9",
|
|
61
|
-
"@sanity/schema": "^3.
|
|
61
|
+
"@sanity/schema": "^3.54.0",
|
|
62
62
|
"@sanity/test": "0.0.1-alpha.1",
|
|
63
|
-
"@sanity/types": "^3.
|
|
63
|
+
"@sanity/types": "^3.54.0",
|
|
64
64
|
"@sanity/ui": "^2.8.8",
|
|
65
|
-
"@sanity/util": "^3.
|
|
65
|
+
"@sanity/util": "^3.54.0",
|
|
66
66
|
"@testing-library/dom": "^10.4.0",
|
|
67
67
|
"@testing-library/react": "^16.0.0",
|
|
68
68
|
"@types/debug": "^4.1.5",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"@types/react": "^18.3.3",
|
|
75
75
|
"@types/react-dom": "^18.3.0",
|
|
76
76
|
"@types/ws": "~8.5.12",
|
|
77
|
-
"@typescript-eslint/eslint-plugin": "^8.0
|
|
78
|
-
"@typescript-eslint/parser": "^8.0
|
|
77
|
+
"@typescript-eslint/eslint-plugin": "^8.1.0",
|
|
78
|
+
"@typescript-eslint/parser": "^8.1.0",
|
|
79
79
|
"@vitejs/plugin-react": "^4.3.1",
|
|
80
80
|
"dotenv": "^16.4.5",
|
|
81
81
|
"eslint": "^8.57.0",
|
|
@@ -84,10 +84,10 @@
|
|
|
84
84
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
85
85
|
"eslint-plugin-import": "^2.29.1",
|
|
86
86
|
"eslint-plugin-prettier": "^5.2.1",
|
|
87
|
-
"eslint-plugin-react-compiler": "0.0.0-experimental-
|
|
87
|
+
"eslint-plugin-react-compiler": "0.0.0-experimental-d0e920e-20240815",
|
|
88
88
|
"eslint-plugin-tsdoc": "^0.3.0",
|
|
89
89
|
"eslint-plugin-unicorn": "^55.0.0",
|
|
90
|
-
"eslint-plugin-unused-imports": "^4.
|
|
90
|
+
"eslint-plugin-unused-imports": "^4.1.3",
|
|
91
91
|
"express": "^4.19.2",
|
|
92
92
|
"express-ws": "^5.0.2",
|
|
93
93
|
"jest": "^29.7.0",
|
|
@@ -99,9 +99,9 @@
|
|
|
99
99
|
"react-dom": "^18.3.1",
|
|
100
100
|
"rxjs": "^7.8.1",
|
|
101
101
|
"styled-components": "^6.1.12",
|
|
102
|
-
"tsx": "^4.
|
|
102
|
+
"tsx": "^4.17.0",
|
|
103
103
|
"typescript": "5.5.4",
|
|
104
|
-
"vite": "^5.
|
|
104
|
+
"vite": "^5.4.1"
|
|
105
105
|
},
|
|
106
106
|
"peerDependencies": {
|
|
107
107
|
"@sanity/block-tools": "^3.47.1",
|
|
@@ -11,7 +11,6 @@ import {validateValue} from '../../utils/validateValue'
|
|
|
11
11
|
import {toSlateValue, VOID_CHILD_KEY} from '../../utils/values'
|
|
12
12
|
import {isChangingLocally, isChangingRemotely, withRemoteChanges} from '../../utils/withChanges'
|
|
13
13
|
import {withoutPatching} from '../../utils/withoutPatching'
|
|
14
|
-
import {withPreserveKeys} from '../../utils/withPreserveKeys'
|
|
15
14
|
import {withoutSaving} from '../plugins/createWithUndoRedo'
|
|
16
15
|
import {type PortableTextEditor} from '../PortableTextEditor'
|
|
17
16
|
|
|
@@ -184,10 +183,8 @@ export function useSyncValue(
|
|
|
184
183
|
currentBlock,
|
|
185
184
|
)
|
|
186
185
|
if (validation.valid || validation.resolution?.autoResolve) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
at: [currentBlockIndex],
|
|
190
|
-
})
|
|
186
|
+
Transforms.insertNodes(slateEditor, currentBlock, {
|
|
187
|
+
at: [currentBlockIndex],
|
|
191
188
|
})
|
|
192
189
|
} else {
|
|
193
190
|
debug('Invalid', validation)
|
|
@@ -267,9 +264,7 @@ function _replaceBlock(
|
|
|
267
264
|
Transforms.deselect(slateEditor)
|
|
268
265
|
}
|
|
269
266
|
Transforms.removeNodes(slateEditor, {at: [currentBlockIndex]})
|
|
270
|
-
|
|
271
|
-
Transforms.insertNodes(slateEditor, currentBlock, {at: [currentBlockIndex]})
|
|
272
|
-
})
|
|
267
|
+
Transforms.insertNodes(slateEditor, currentBlock, {at: [currentBlockIndex]})
|
|
273
268
|
slateEditor.onChange()
|
|
274
269
|
if (selectionFocusOnBlock) {
|
|
275
270
|
Transforms.select(slateEditor, currentSelection)
|
|
@@ -350,21 +345,17 @@ function _updateBlock(
|
|
|
350
345
|
Transforms.removeNodes(slateEditor, {
|
|
351
346
|
at: [currentBlockIndex, currentBlockChildIndex],
|
|
352
347
|
})
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
at: [currentBlockIndex, currentBlockChildIndex],
|
|
356
|
-
})
|
|
348
|
+
Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
|
|
349
|
+
at: [currentBlockIndex, currentBlockChildIndex],
|
|
357
350
|
})
|
|
358
351
|
slateEditor.onChange()
|
|
359
352
|
// Insert it if it didn't exist before
|
|
360
353
|
} else if (!oldBlockChild) {
|
|
361
354
|
debug('Inserting new child', currentBlockChild)
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
at: [currentBlockIndex, currentBlockChildIndex],
|
|
365
|
-
})
|
|
366
|
-
slateEditor.onChange()
|
|
355
|
+
Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
|
|
356
|
+
at: [currentBlockIndex, currentBlockChildIndex],
|
|
367
357
|
})
|
|
358
|
+
slateEditor.onChange()
|
|
368
359
|
}
|
|
369
360
|
}
|
|
370
361
|
})
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {type PortableTextSlateEditor} from '../../types/editor'
|
|
2
|
+
import {isChangingRemotely} from '../../utils/withChanges'
|
|
3
|
+
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* This plugin makes sure that the PTE maxBlocks prop is respected
|
|
@@ -8,6 +10,24 @@ export function createWithMaxBlocks(maxBlocks: number) {
|
|
|
8
10
|
return function withMaxBlocks(editor: PortableTextSlateEditor): PortableTextSlateEditor {
|
|
9
11
|
const {apply} = editor
|
|
10
12
|
editor.apply = (operation) => {
|
|
13
|
+
/**
|
|
14
|
+
* We don't want to run any side effects when the editor is processing
|
|
15
|
+
* remote changes.
|
|
16
|
+
*/
|
|
17
|
+
if (isChangingRemotely(editor)) {
|
|
18
|
+
apply(operation)
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* We don't want to run any side effects when the editor is undoing or
|
|
24
|
+
* redoing operations.
|
|
25
|
+
*/
|
|
26
|
+
if (isUndoing(editor) || isRedoing(editor)) {
|
|
27
|
+
apply(operation)
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
11
31
|
const rows = maxBlocks
|
|
12
32
|
if (rows > 0 && editor.children.length >= rows) {
|
|
13
33
|
if (
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {Editor, Element, Node, Transforms} from 'slate'
|
|
2
2
|
|
|
3
3
|
import {type PortableTextMemberSchemaTypes, type PortableTextSlateEditor} from '../../types/editor'
|
|
4
|
-
import {
|
|
4
|
+
import {isChangingRemotely} from '../../utils/withChanges'
|
|
5
|
+
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* This plugin makes sure that every new node in the editor get a new _key prop when created
|
|
@@ -12,23 +13,36 @@ export function createWithObjectKeys(
|
|
|
12
13
|
keyGenerator: () => string,
|
|
13
14
|
) {
|
|
14
15
|
return function withKeys(editor: PortableTextSlateEditor): PortableTextSlateEditor {
|
|
15
|
-
PRESERVE_KEYS.set(editor, false)
|
|
16
16
|
const {apply, normalizeNode} = editor
|
|
17
17
|
|
|
18
|
-
// The apply function can be called with a scope (withPreserveKeys) that will
|
|
19
|
-
// preserve keys for the produced nodes if they have a _key property set already.
|
|
20
18
|
// The default behavior is to always generate a new key here.
|
|
21
19
|
// For example, when undoing and redoing we want to retain the keys, but
|
|
22
20
|
// when we create a new bold span by splitting a non-bold-span we want the produced node to get a new key.
|
|
23
21
|
editor.apply = (operation) => {
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
/**
|
|
23
|
+
* We don't want to run any side effects when the editor is processing
|
|
24
|
+
* remote changes.
|
|
25
|
+
*/
|
|
26
|
+
if (isChangingRemotely(editor)) {
|
|
27
|
+
apply(operation)
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* We don't want to run any side effects when the editor is undoing or
|
|
33
|
+
* redoing operations.
|
|
34
|
+
*/
|
|
35
|
+
if (isUndoing(editor) || isRedoing(editor)) {
|
|
36
|
+
apply(operation)
|
|
37
|
+
return
|
|
38
|
+
}
|
|
26
39
|
|
|
40
|
+
if (operation.type === 'split_node') {
|
|
27
41
|
apply({
|
|
28
42
|
...operation,
|
|
29
43
|
properties: {
|
|
30
44
|
...operation.properties,
|
|
31
|
-
|
|
45
|
+
_key: keyGenerator(),
|
|
32
46
|
},
|
|
33
47
|
})
|
|
34
48
|
|
|
@@ -36,15 +50,12 @@ export function createWithObjectKeys(
|
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
if (operation.type === 'insert_node') {
|
|
39
|
-
// Must be given a new key or adding/removing marks while typing gets in trouble (duped keys)!
|
|
40
|
-
const withNewKey = !isPreservingKeys(editor) || !('_key' in operation.node)
|
|
41
|
-
|
|
42
53
|
if (!Editor.isEditor(operation.node)) {
|
|
43
54
|
apply({
|
|
44
55
|
...operation,
|
|
45
56
|
node: {
|
|
46
57
|
...operation.node,
|
|
47
|
-
|
|
58
|
+
_key: keyGenerator(),
|
|
48
59
|
},
|
|
49
60
|
})
|
|
50
61
|
|
|
@@ -27,7 +27,6 @@ import {fromSlateValue, isEqualToEmptyEditor} from '../../utils/values'
|
|
|
27
27
|
import {IS_PROCESSING_REMOTE_CHANGES, KEY_TO_VALUE_ELEMENT} from '../../utils/weakMaps'
|
|
28
28
|
import {withRemoteChanges} from '../../utils/withChanges'
|
|
29
29
|
import {isPatching, PATCHING, withoutPatching} from '../../utils/withoutPatching'
|
|
30
|
-
import {withPreserveKeys} from '../../utils/withPreserveKeys'
|
|
31
30
|
import {withoutSaving} from './createWithUndoRedo'
|
|
32
31
|
|
|
33
32
|
const debug = debugWithName('plugin:withPatches')
|
|
@@ -117,11 +116,9 @@ export function createWithPatches({
|
|
|
117
116
|
Editor.withoutNormalizing(editor, () => {
|
|
118
117
|
withoutPatching(editor, () => {
|
|
119
118
|
withoutSaving(editor, () => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
changed = applyPatch(editor, patch)
|
|
124
|
-
})
|
|
119
|
+
patches.forEach((patch) => {
|
|
120
|
+
if (debug.enabled) debug(`Handling remote patch ${JSON.stringify(patch)}`)
|
|
121
|
+
changed = applyPatch(editor, patch)
|
|
125
122
|
})
|
|
126
123
|
})
|
|
127
124
|
})
|
|
@@ -3,6 +3,8 @@ import {Editor, Path} from 'slate'
|
|
|
3
3
|
import {type PortableTextSlateEditor} from '../../types/editor'
|
|
4
4
|
import {type SlateTextBlock, type VoidElement} from '../../types/slate'
|
|
5
5
|
import {debugWithName} from '../../utils/debug'
|
|
6
|
+
import {isChangingRemotely} from '../../utils/withChanges'
|
|
7
|
+
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
6
8
|
|
|
7
9
|
const debug = debugWithName('plugin:withPlaceholderBlock')
|
|
8
10
|
|
|
@@ -17,6 +19,24 @@ export function createWithPlaceholderBlock(): (
|
|
|
17
19
|
const {apply} = editor
|
|
18
20
|
|
|
19
21
|
editor.apply = (op) => {
|
|
22
|
+
/**
|
|
23
|
+
* We don't want to run any side effects when the editor is processing
|
|
24
|
+
* remote changes.
|
|
25
|
+
*/
|
|
26
|
+
if (isChangingRemotely(editor)) {
|
|
27
|
+
apply(op)
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* We don't want to run any side effects when the editor is undoing or
|
|
33
|
+
* redoing operations.
|
|
34
|
+
*/
|
|
35
|
+
if (isUndoing(editor) || isRedoing(editor)) {
|
|
36
|
+
apply(op)
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
20
40
|
if (op.type === 'remove_node') {
|
|
21
41
|
const node = op.node as SlateTextBlock | VoidElement
|
|
22
42
|
if (op.path[0] === 0 && Editor.isVoid(editor, node)) {
|
|
@@ -19,7 +19,8 @@ import {
|
|
|
19
19
|
import {debugWithName} from '../../utils/debug'
|
|
20
20
|
import {toPortableTextRange} from '../../utils/ranges'
|
|
21
21
|
import {EMPTY_MARKS} from '../../utils/values'
|
|
22
|
-
import {
|
|
22
|
+
import {isChangingRemotely} from '../../utils/withChanges'
|
|
23
|
+
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
23
24
|
|
|
24
25
|
const debug = debugWithName('plugin:withPortableTextMarkModel')
|
|
25
26
|
|
|
@@ -234,6 +235,24 @@ export function createWithPortableTextMarkModel(
|
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
editor.apply = (op) => {
|
|
238
|
+
/**
|
|
239
|
+
* We don't want to run any side effects when the editor is processing
|
|
240
|
+
* remote changes.
|
|
241
|
+
*/
|
|
242
|
+
if (isChangingRemotely(editor)) {
|
|
243
|
+
apply(op)
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* We don't want to run any side effects when the editor is undoing or
|
|
249
|
+
* redoing operations.
|
|
250
|
+
*/
|
|
251
|
+
if (isUndoing(editor) || isRedoing(editor)) {
|
|
252
|
+
apply(op)
|
|
253
|
+
return
|
|
254
|
+
}
|
|
255
|
+
|
|
237
256
|
// Special hook before inserting text at the end of an annotation.
|
|
238
257
|
if (op.type === 'insert_text') {
|
|
239
258
|
const {selection} = editor
|
|
@@ -295,21 +314,10 @@ export function createWithPortableTextMarkModel(
|
|
|
295
314
|
const deletingFromTheEnd = op.offset + op.text.length === node.text.length
|
|
296
315
|
|
|
297
316
|
if (nodeHasAnnotations && deletingPartOfTheNode && deletingFromTheEnd) {
|
|
298
|
-
/**
|
|
299
|
-
* If all of these conditions match then override the ordinary
|
|
300
|
-
* `remove_text` operation and turn it into `split_nodes` followed
|
|
301
|
-
* by `remove_nodes`. This is so if the operation can be properly
|
|
302
|
-
* undone. Undoing a `remove_text` results in an `insert_text` and
|
|
303
|
-
* we want to bail out of that in this exact scenario to make sure
|
|
304
|
-
* the inserted text is annotated. (See custom logic regarding
|
|
305
|
-
* `insert_text`)
|
|
306
|
-
*/
|
|
307
317
|
Editor.withoutNormalizing(editor, () => {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
at: {path: op.path, offset: op.offset},
|
|
312
|
-
})
|
|
318
|
+
Transforms.splitNodes(editor, {
|
|
319
|
+
match: Text.isText,
|
|
320
|
+
at: {path: op.path, offset: op.offset},
|
|
313
321
|
})
|
|
314
322
|
Transforms.removeNodes(editor, {at: Path.next(op.path)})
|
|
315
323
|
})
|
|
@@ -317,6 +325,24 @@ export function createWithPortableTextMarkModel(
|
|
|
317
325
|
editor.onChange()
|
|
318
326
|
return
|
|
319
327
|
}
|
|
328
|
+
|
|
329
|
+
const deletingAllText = op.offset === 0 && deletingFromTheEnd
|
|
330
|
+
|
|
331
|
+
if (nodeHasAnnotations && deletingAllText) {
|
|
332
|
+
const marksWithoutAnnotationMarks: string[] = (
|
|
333
|
+
{
|
|
334
|
+
...(Editor.marks(editor) || {}),
|
|
335
|
+
}.marks || []
|
|
336
|
+
).filter((mark) => decorators.includes(mark))
|
|
337
|
+
|
|
338
|
+
Editor.withoutNormalizing(editor, () => {
|
|
339
|
+
apply(op)
|
|
340
|
+
Transforms.setNodes(editor, {marks: marksWithoutAnnotationMarks}, {at: op.path})
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
editor.onChange()
|
|
344
|
+
return
|
|
345
|
+
}
|
|
320
346
|
}
|
|
321
347
|
}
|
|
322
348
|
|
|
@@ -12,7 +12,7 @@ import {type Descendant, Editor, Operation, Path, type SelectionOperation, Trans
|
|
|
12
12
|
import {type PatchObservable, type PortableTextSlateEditor} from '../../types/editor'
|
|
13
13
|
import {debugWithName} from '../../utils/debug'
|
|
14
14
|
import {fromSlateValue} from '../../utils/values'
|
|
15
|
-
import {
|
|
15
|
+
import {setIsRedoing, setIsUndoing, withRedoing, withUndoing} from '../../utils/withUndoRedo'
|
|
16
16
|
|
|
17
17
|
const debug = debugWithName('plugin:withUndoRedo')
|
|
18
18
|
const debugVerbose = debug.enabled && false
|
|
@@ -150,7 +150,7 @@ export function createWithUndoRedo(
|
|
|
150
150
|
|
|
151
151
|
try {
|
|
152
152
|
Editor.withoutNormalizing(editor, () => {
|
|
153
|
-
|
|
153
|
+
withUndoing(editor, () => {
|
|
154
154
|
withoutSaving(editor, () => {
|
|
155
155
|
reversedOperations.forEach((op) => {
|
|
156
156
|
editor.apply(op)
|
|
@@ -166,6 +166,7 @@ export function createWithUndoRedo(
|
|
|
166
166
|
Transforms.deselect(editor)
|
|
167
167
|
editor.history = {undos: [], redos: []}
|
|
168
168
|
SAVING.set(editor, true)
|
|
169
|
+
setIsUndoing(editor, false)
|
|
169
170
|
editor.onChange()
|
|
170
171
|
return
|
|
171
172
|
}
|
|
@@ -195,7 +196,7 @@ export function createWithUndoRedo(
|
|
|
195
196
|
})
|
|
196
197
|
try {
|
|
197
198
|
Editor.withoutNormalizing(editor, () => {
|
|
198
|
-
|
|
199
|
+
withRedoing(editor, () => {
|
|
199
200
|
withoutSaving(editor, () => {
|
|
200
201
|
// eslint-disable-next-line max-nested-callbacks
|
|
201
202
|
transformedOperations.forEach((op) => {
|
|
@@ -212,6 +213,7 @@ export function createWithUndoRedo(
|
|
|
212
213
|
Transforms.deselect(editor)
|
|
213
214
|
editor.history = {undos: [], redos: []}
|
|
214
215
|
SAVING.set(editor, true)
|
|
216
|
+
setIsRedoing(editor, false)
|
|
215
217
|
editor.onChange()
|
|
216
218
|
return
|
|
217
219
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {type Editor} from 'slate'
|
|
2
|
+
|
|
3
|
+
const IS_UDOING: WeakMap<Editor, boolean | undefined> = new WeakMap()
|
|
4
|
+
const IS_REDOING: WeakMap<Editor, boolean | undefined> = new WeakMap()
|
|
5
|
+
|
|
6
|
+
export function withUndoing(editor: Editor, fn: () => void) {
|
|
7
|
+
const prev = isUndoing(editor)
|
|
8
|
+
IS_UDOING.set(editor, true)
|
|
9
|
+
fn()
|
|
10
|
+
IS_UDOING.set(editor, prev)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isUndoing(editor: Editor) {
|
|
14
|
+
return IS_UDOING.get(editor) ?? false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function setIsUndoing(editor: Editor, isUndoing: boolean) {
|
|
18
|
+
IS_UDOING.set(editor, isUndoing)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function withRedoing(editor: Editor, fn: () => void) {
|
|
22
|
+
const prev = isRedoing(editor)
|
|
23
|
+
IS_REDOING.set(editor, true)
|
|
24
|
+
fn()
|
|
25
|
+
IS_REDOING.set(editor, prev)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function isRedoing(editor: Editor) {
|
|
29
|
+
return IS_REDOING.get(editor) ?? false
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function setIsRedoing(editor: Editor, isRedoing: boolean) {
|
|
33
|
+
IS_REDOING.set(editor, isRedoing)
|
|
34
|
+
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {type Editor} from 'slate'
|
|
2
|
-
|
|
3
|
-
export const PRESERVE_KEYS: WeakMap<Editor, boolean | undefined> = new WeakMap()
|
|
4
|
-
|
|
5
|
-
export function withPreserveKeys(editor: Editor, fn: () => void): void {
|
|
6
|
-
const prev = isPreservingKeys(editor)
|
|
7
|
-
PRESERVE_KEYS.set(editor, true)
|
|
8
|
-
fn()
|
|
9
|
-
PRESERVE_KEYS.set(editor, prev)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function withoutPreserveKeys(editor: Editor, fn: () => void): void {
|
|
13
|
-
const prev = isPreservingKeys(editor)
|
|
14
|
-
PRESERVE_KEYS.set(editor, false)
|
|
15
|
-
fn()
|
|
16
|
-
PRESERVE_KEYS.set(editor, prev)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isPreservingKeys(editor: Editor): boolean | undefined {
|
|
20
|
-
return PRESERVE_KEYS.get(editor)
|
|
21
|
-
}
|