@portabletext/editor 1.0.19 → 1.1.1
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.d.mts +142 -67
- package/lib/index.d.ts +142 -67
- package/lib/index.esm.js +1130 -371
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1130 -371
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1130 -371
- package/lib/index.mjs.map +1 -1
- package/package.json +4 -18
- package/src/editor/Editable.tsx +128 -55
- package/src/editor/PortableTextEditor.tsx +66 -32
- package/src/editor/__tests__/PortableTextEditor.test.tsx +44 -18
- package/src/editor/__tests__/PortableTextEditorTester.tsx +50 -38
- package/src/editor/__tests__/RangeDecorations.test.tsx +4 -6
- package/src/editor/__tests__/handleClick.test.tsx +28 -9
- package/src/editor/__tests__/insert-block.test.tsx +24 -8
- package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +31 -63
- package/src/editor/__tests__/utils.ts +10 -4
- package/src/editor/components/DraggableBlock.tsx +36 -13
- package/src/editor/components/Element.tsx +73 -33
- package/src/editor/components/Leaf.tsx +114 -76
- package/src/editor/components/SlateContainer.tsx +14 -7
- package/src/editor/components/Synchronizer.tsx +8 -5
- package/src/editor/hooks/usePortableTextEditor.ts +3 -3
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +10 -4
- package/src/editor/hooks/useSyncValue.test.tsx +9 -4
- package/src/editor/hooks/useSyncValue.ts +198 -133
- package/src/editor/nodes/DefaultAnnotation.tsx +6 -4
- package/src/editor/nodes/DefaultObject.tsx +1 -1
- package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +23 -8
- package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +26 -9
- package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +15 -5
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +60 -19
- package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +5 -3
- package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +4 -2
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +61 -19
- package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +6 -3
- package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +30 -13
- package/src/editor/plugins/createWithEditableAPI.ts +361 -131
- package/src/editor/plugins/createWithHotKeys.ts +46 -130
- package/src/editor/plugins/createWithInsertBreak.ts +167 -28
- package/src/editor/plugins/createWithInsertData.ts +66 -30
- package/src/editor/plugins/createWithMaxBlocks.ts +6 -3
- package/src/editor/plugins/createWithObjectKeys.ts +7 -3
- package/src/editor/plugins/createWithPatches.ts +66 -24
- package/src/editor/plugins/createWithPlaceholderBlock.ts +9 -5
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +17 -7
- package/src/editor/plugins/createWithPortableTextLists.ts +21 -9
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +217 -52
- package/src/editor/plugins/createWithPortableTextSelections.ts +11 -9
- package/src/editor/plugins/createWithSchemaTypes.ts +26 -10
- package/src/editor/plugins/createWithUndoRedo.ts +106 -27
- package/src/editor/plugins/createWithUtils.ts +33 -11
- package/src/editor/plugins/index.ts +34 -13
- package/src/types/editor.ts +73 -44
- package/src/types/options.ts +7 -5
- package/src/types/slate.ts +6 -6
- package/src/utils/__tests__/dmpToOperations.test.ts +41 -16
- package/src/utils/__tests__/operationToPatches.test.ts +4 -3
- package/src/utils/__tests__/patchToOperations.test.ts +16 -5
- package/src/utils/__tests__/ranges.test.ts +9 -4
- package/src/utils/__tests__/valueNormalization.test.tsx +12 -4
- package/src/utils/__tests__/values.test.ts +0 -1
- package/src/utils/applyPatch.ts +78 -29
- package/src/utils/getPortableTextMemberSchemaTypes.ts +38 -23
- package/src/utils/operationToPatches.ts +123 -44
- package/src/utils/paths.ts +26 -9
- package/src/utils/ranges.ts +16 -10
- package/src/utils/selection.ts +21 -9
- package/src/utils/ucs2Indices.ts +2 -2
- package/src/utils/validateValue.ts +118 -45
- package/src/utils/values.ts +38 -17
- package/src/utils/weakMaps.ts +20 -10
- package/src/utils/withChanges.ts +5 -3
- package/src/utils/withUndoRedo.ts +1 -1
- package/src/utils/withoutPatching.ts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
2
2
|
import {isChangingRemotely} from '../../utils/withChanges'
|
|
3
3
|
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
4
4
|
|
|
@@ -7,7 +7,9 @@ import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
9
9
|
export function createWithMaxBlocks(maxBlocks: number) {
|
|
10
|
-
return function withMaxBlocks(
|
|
10
|
+
return function withMaxBlocks(
|
|
11
|
+
editor: PortableTextSlateEditor,
|
|
12
|
+
): PortableTextSlateEditor {
|
|
11
13
|
const {apply} = editor
|
|
12
14
|
editor.apply = (operation) => {
|
|
13
15
|
/**
|
|
@@ -31,7 +33,8 @@ export function createWithMaxBlocks(maxBlocks: number) {
|
|
|
31
33
|
const rows = maxBlocks
|
|
32
34
|
if (rows > 0 && editor.children.length >= rows) {
|
|
33
35
|
if (
|
|
34
|
-
(operation.type === 'insert_node' ||
|
|
36
|
+
(operation.type === 'insert_node' ||
|
|
37
|
+
operation.type === 'split_node') &&
|
|
35
38
|
operation.path.length === 1
|
|
36
39
|
) {
|
|
37
40
|
return
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {Editor, Element, Node, Transforms} from 'slate'
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type {
|
|
3
|
+
PortableTextMemberSchemaTypes,
|
|
4
|
+
PortableTextSlateEditor,
|
|
5
|
+
} from '../../types/editor'
|
|
4
6
|
import {isChangingRemotely} from '../../utils/withChanges'
|
|
5
7
|
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
6
8
|
|
|
@@ -12,7 +14,9 @@ export function createWithObjectKeys(
|
|
|
12
14
|
schemaTypes: PortableTextMemberSchemaTypes,
|
|
13
15
|
keyGenerator: () => string,
|
|
14
16
|
) {
|
|
15
|
-
return function withKeys(
|
|
17
|
+
return function withKeys(
|
|
18
|
+
editor: PortableTextSlateEditor,
|
|
19
|
+
): PortableTextSlateEditor {
|
|
16
20
|
const {apply, normalizeNode} = editor
|
|
17
21
|
|
|
18
22
|
// The default behavior is to always generate a new key here.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {type Subject} from 'rxjs'
|
|
1
|
+
import {insert, setIfMissing, unset, type Patch} from '@portabletext/patches'
|
|
2
|
+
import type {Subject} from 'rxjs'
|
|
4
3
|
import {
|
|
5
|
-
type Descendant,
|
|
6
4
|
Editor,
|
|
5
|
+
type Descendant,
|
|
7
6
|
type InsertNodeOperation,
|
|
8
7
|
type InsertTextOperation,
|
|
9
8
|
type MergeNodeOperation,
|
|
@@ -14,19 +13,25 @@ import {
|
|
|
14
13
|
type SetNodeOperation,
|
|
15
14
|
type SplitNodeOperation,
|
|
16
15
|
} from 'slate'
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type PortableTextSlateEditor,
|
|
16
|
+
import type {
|
|
17
|
+
EditorChange,
|
|
18
|
+
PatchObservable,
|
|
19
|
+
PortableTextMemberSchemaTypes,
|
|
20
|
+
PortableTextSlateEditor,
|
|
23
21
|
} from '../../types/editor'
|
|
24
22
|
import {createApplyPatch} from '../../utils/applyPatch'
|
|
25
23
|
import {debugWithName} from '../../utils/debug'
|
|
26
24
|
import {fromSlateValue, isEqualToEmptyEditor} from '../../utils/values'
|
|
27
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
IS_PROCESSING_REMOTE_CHANGES,
|
|
27
|
+
KEY_TO_VALUE_ELEMENT,
|
|
28
|
+
} from '../../utils/weakMaps'
|
|
28
29
|
import {withRemoteChanges} from '../../utils/withChanges'
|
|
29
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
isPatching,
|
|
32
|
+
PATCHING,
|
|
33
|
+
withoutPatching,
|
|
34
|
+
} from '../../utils/withoutPatching'
|
|
30
35
|
import {withoutSaving} from './createWithUndoRedo'
|
|
31
36
|
|
|
32
37
|
const debug = debugWithName('plugin:withPatches')
|
|
@@ -117,7 +122,8 @@ export function createWithPatches({
|
|
|
117
122
|
withoutPatching(editor, () => {
|
|
118
123
|
withoutSaving(editor, () => {
|
|
119
124
|
patches.forEach((patch) => {
|
|
120
|
-
if (debug.enabled)
|
|
125
|
+
if (debug.enabled)
|
|
126
|
+
debug(`Handling remote patch ${JSON.stringify(patch)}`)
|
|
121
127
|
changed = applyPatch(editor, patch)
|
|
122
128
|
})
|
|
123
129
|
})
|
|
@@ -169,12 +175,19 @@ export function createWithPatches({
|
|
|
169
175
|
|
|
170
176
|
if (!isPatching(editor)) {
|
|
171
177
|
if (debugVerbose && debug.enabled)
|
|
172
|
-
debug(
|
|
178
|
+
debug(
|
|
179
|
+
`Editor is not producing patch for operation ${operation.type}`,
|
|
180
|
+
operation,
|
|
181
|
+
)
|
|
173
182
|
return editor
|
|
174
183
|
}
|
|
175
184
|
|
|
176
185
|
// If the editor was empty and now isn't, insert the placeholder into it.
|
|
177
|
-
if (
|
|
186
|
+
if (
|
|
187
|
+
editorWasEmpty &&
|
|
188
|
+
!editorIsEmpty &&
|
|
189
|
+
operation.type !== 'set_selection'
|
|
190
|
+
) {
|
|
178
191
|
patches.push(insert(previousChildren, 'before', [0]))
|
|
179
192
|
}
|
|
180
193
|
|
|
@@ -182,31 +195,51 @@ export function createWithPatches({
|
|
|
182
195
|
case 'insert_text':
|
|
183
196
|
patches = [
|
|
184
197
|
...patches,
|
|
185
|
-
...patchFunctions.insertTextPatch(
|
|
198
|
+
...patchFunctions.insertTextPatch(
|
|
199
|
+
editor,
|
|
200
|
+
operation,
|
|
201
|
+
previousChildren,
|
|
202
|
+
),
|
|
186
203
|
]
|
|
187
204
|
break
|
|
188
205
|
case 'remove_text':
|
|
189
206
|
patches = [
|
|
190
207
|
...patches,
|
|
191
|
-
...patchFunctions.removeTextPatch(
|
|
208
|
+
...patchFunctions.removeTextPatch(
|
|
209
|
+
editor,
|
|
210
|
+
operation,
|
|
211
|
+
previousChildren,
|
|
212
|
+
),
|
|
192
213
|
]
|
|
193
214
|
break
|
|
194
215
|
case 'remove_node':
|
|
195
216
|
patches = [
|
|
196
217
|
...patches,
|
|
197
|
-
...patchFunctions.removeNodePatch(
|
|
218
|
+
...patchFunctions.removeNodePatch(
|
|
219
|
+
editor,
|
|
220
|
+
operation,
|
|
221
|
+
previousChildren,
|
|
222
|
+
),
|
|
198
223
|
]
|
|
199
224
|
break
|
|
200
225
|
case 'split_node':
|
|
201
226
|
patches = [
|
|
202
227
|
...patches,
|
|
203
|
-
...patchFunctions.splitNodePatch(
|
|
228
|
+
...patchFunctions.splitNodePatch(
|
|
229
|
+
editor,
|
|
230
|
+
operation,
|
|
231
|
+
previousChildren,
|
|
232
|
+
),
|
|
204
233
|
]
|
|
205
234
|
break
|
|
206
235
|
case 'insert_node':
|
|
207
236
|
patches = [
|
|
208
237
|
...patches,
|
|
209
|
-
...patchFunctions.insertNodePatch(
|
|
238
|
+
...patchFunctions.insertNodePatch(
|
|
239
|
+
editor,
|
|
240
|
+
operation,
|
|
241
|
+
previousChildren,
|
|
242
|
+
),
|
|
210
243
|
]
|
|
211
244
|
break
|
|
212
245
|
case 'set_node':
|
|
@@ -218,16 +251,23 @@ export function createWithPatches({
|
|
|
218
251
|
case 'merge_node':
|
|
219
252
|
patches = [
|
|
220
253
|
...patches,
|
|
221
|
-
...patchFunctions.mergeNodePatch(
|
|
254
|
+
...patchFunctions.mergeNodePatch(
|
|
255
|
+
editor,
|
|
256
|
+
operation,
|
|
257
|
+
previousChildren,
|
|
258
|
+
),
|
|
222
259
|
]
|
|
223
260
|
break
|
|
224
261
|
case 'move_node':
|
|
225
262
|
patches = [
|
|
226
263
|
...patches,
|
|
227
|
-
...patchFunctions.moveNodePatch(
|
|
264
|
+
...patchFunctions.moveNodePatch(
|
|
265
|
+
editor,
|
|
266
|
+
operation,
|
|
267
|
+
previousChildren,
|
|
268
|
+
),
|
|
228
269
|
]
|
|
229
270
|
break
|
|
230
|
-
case 'set_selection':
|
|
231
271
|
default:
|
|
232
272
|
// Do nothing
|
|
233
273
|
}
|
|
@@ -236,7 +276,9 @@ export function createWithPatches({
|
|
|
236
276
|
if (
|
|
237
277
|
!editorWasEmpty &&
|
|
238
278
|
editorIsEmpty &&
|
|
239
|
-
['merge_node', 'set_node', 'remove_text', 'remove_node'].includes(
|
|
279
|
+
['merge_node', 'set_node', 'remove_text', 'remove_node'].includes(
|
|
280
|
+
operation.type,
|
|
281
|
+
)
|
|
240
282
|
) {
|
|
241
283
|
patches = [...patches, unset([])]
|
|
242
284
|
change$.next({
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {Editor, Path} from 'slate'
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import {type SlateTextBlock, type VoidElement} from '../../types/slate'
|
|
2
|
+
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
3
|
+
import type {SlateTextBlock, VoidElement} from '../../types/slate'
|
|
5
4
|
import {debugWithName} from '../../utils/debug'
|
|
6
5
|
import {isChangingRemotely} from '../../utils/withChanges'
|
|
7
6
|
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
@@ -15,7 +14,9 @@ const debug = debugWithName('plugin:withPlaceholderBlock')
|
|
|
15
14
|
export function createWithPlaceholderBlock(): (
|
|
16
15
|
editor: PortableTextSlateEditor,
|
|
17
16
|
) => PortableTextSlateEditor {
|
|
18
|
-
return function withPlaceholderBlock(
|
|
17
|
+
return function withPlaceholderBlock(
|
|
18
|
+
editor: PortableTextSlateEditor,
|
|
19
|
+
): PortableTextSlateEditor {
|
|
19
20
|
const {apply} = editor
|
|
20
21
|
|
|
21
22
|
editor.apply = (op) => {
|
|
@@ -45,7 +46,10 @@ export function createWithPlaceholderBlock(): (
|
|
|
45
46
|
// Is removing the first block which is a void (not a text block), add a new empty text block in it, if there is no other element in the next path
|
|
46
47
|
if (!editor.children[nextPath[0]]) {
|
|
47
48
|
debug('Adding placeholder block')
|
|
48
|
-
Editor.insertNode(
|
|
49
|
+
Editor.insertNode(
|
|
50
|
+
editor,
|
|
51
|
+
editor.pteCreateTextBlock({decorators: []}),
|
|
52
|
+
)
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {Editor,
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {Editor, Path, Text as SlateText, Transforms, type Node} from 'slate'
|
|
2
|
+
import type {
|
|
3
|
+
PortableTextMemberSchemaTypes,
|
|
4
|
+
PortableTextSlateEditor,
|
|
5
|
+
} from '../../types/editor'
|
|
4
6
|
import {debugWithName} from '../../utils/debug'
|
|
5
7
|
|
|
6
8
|
const debug = debugWithName('plugin:withPortableTextBlockStyle')
|
|
@@ -30,7 +32,11 @@ export function createWithPortableTextBlockStyle(
|
|
|
30
32
|
const [child] = Editor.node(editor, [op.path[0] + 1, 0])
|
|
31
33
|
if (SlateText.isText(child) && child.text === '') {
|
|
32
34
|
debug(`Normalizing split node to ${defaultStyle} style`, op)
|
|
33
|
-
Transforms.setNodes(
|
|
35
|
+
Transforms.setNodes(
|
|
36
|
+
editor,
|
|
37
|
+
{style: defaultStyle},
|
|
38
|
+
{at: [op.path[0] + 1], voids: false},
|
|
39
|
+
)
|
|
34
40
|
break
|
|
35
41
|
}
|
|
36
42
|
}
|
|
@@ -65,9 +71,13 @@ export function createWithPortableTextBlockStyle(
|
|
|
65
71
|
selectedBlocks.forEach(([node, path]) => {
|
|
66
72
|
if (editor.isTextBlock(node) && node.style === blockStyle) {
|
|
67
73
|
debug(`Unsetting block style '${blockStyle}'`)
|
|
68
|
-
Transforms.setNodes(
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
Transforms.setNodes(
|
|
75
|
+
editor,
|
|
76
|
+
{...node, style: defaultStyle} as Partial<Node>,
|
|
77
|
+
{
|
|
78
|
+
at: path,
|
|
79
|
+
},
|
|
80
|
+
)
|
|
71
81
|
} else {
|
|
72
82
|
if (blockStyle) {
|
|
73
83
|
debug(`Setting style '${blockStyle}'`)
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import {Editor, Element,
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {Editor, Element, Text, Transforms, type Node} from 'slate'
|
|
2
|
+
import type {
|
|
3
|
+
PortableTextMemberSchemaTypes,
|
|
4
|
+
PortableTextSlateEditor,
|
|
5
|
+
} from '../../types/editor'
|
|
4
6
|
import {debugWithName} from '../../utils/debug'
|
|
5
7
|
|
|
6
8
|
const debug = debugWithName('plugin:withPortableTextLists')
|
|
7
9
|
const MAX_LIST_LEVEL = 10
|
|
8
10
|
|
|
9
|
-
export function createWithPortableTextLists(
|
|
10
|
-
|
|
11
|
+
export function createWithPortableTextLists(
|
|
12
|
+
types: PortableTextMemberSchemaTypes,
|
|
13
|
+
) {
|
|
14
|
+
return function withPortableTextLists(
|
|
15
|
+
editor: PortableTextSlateEditor,
|
|
16
|
+
): PortableTextSlateEditor {
|
|
11
17
|
editor.pteToggleListItem = (listItemStyle: string) => {
|
|
12
18
|
const isActive = editor.pteHasListStyle(listItemStyle)
|
|
13
19
|
if (isActive) {
|
|
@@ -26,12 +32,12 @@ export function createWithPortableTextLists(types: PortableTextMemberSchemaTypes
|
|
|
26
32
|
const selectedBlocks = [
|
|
27
33
|
...Editor.nodes(editor, {
|
|
28
34
|
at: editor.selection,
|
|
29
|
-
match: (node) =>
|
|
35
|
+
match: (node) =>
|
|
36
|
+
Element.isElement(node) && node._type === types.block.name,
|
|
30
37
|
}),
|
|
31
38
|
]
|
|
32
39
|
selectedBlocks.forEach(([node, path]) => {
|
|
33
40
|
if (editor.isListBlock(node)) {
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
35
41
|
const {listItem, level, ...rest} = node
|
|
36
42
|
const newNode = {
|
|
37
43
|
...rest,
|
|
@@ -121,10 +127,16 @@ export function createWithPortableTextLists(types: PortableTextMemberSchemaTypes
|
|
|
121
127
|
let level = node.level || 1
|
|
122
128
|
if (reverse) {
|
|
123
129
|
level--
|
|
124
|
-
debug(
|
|
130
|
+
debug(
|
|
131
|
+
'Decrementing list level',
|
|
132
|
+
Math.min(MAX_LIST_LEVEL, Math.max(1, level)),
|
|
133
|
+
)
|
|
125
134
|
} else {
|
|
126
135
|
level++
|
|
127
|
-
debug(
|
|
136
|
+
debug(
|
|
137
|
+
'Incrementing list level',
|
|
138
|
+
Math.min(MAX_LIST_LEVEL, Math.max(1, level)),
|
|
139
|
+
)
|
|
128
140
|
}
|
|
129
141
|
Transforms.setNodes(
|
|
130
142
|
editor,
|