@portabletext/editor 1.0.18 → 1.1.0
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 +140 -66
- package/lib/index.d.ts +140 -66
- package/lib/index.esm.js +1164 -410
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1164 -410
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1164 -410
- package/lib/index.mjs.map +1 -1
- package/package.json +8 -4
- package/src/editor/Editable.tsx +107 -36
- package/src/editor/PortableTextEditor.tsx +47 -12
- package/src/editor/__tests__/PortableTextEditor.test.tsx +42 -15
- package/src/editor/__tests__/PortableTextEditorTester.tsx +50 -38
- package/src/editor/__tests__/RangeDecorations.test.tsx +0 -1
- package/src/editor/__tests__/handleClick.test.tsx +28 -9
- package/src/editor/__tests__/insert-block.test.tsx +22 -6
- package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +30 -62
- package/src/editor/__tests__/utils.ts +10 -3
- package/src/editor/components/DraggableBlock.tsx +36 -13
- package/src/editor/components/Element.tsx +59 -17
- package/src/editor/components/Leaf.tsx +106 -68
- package/src/editor/components/SlateContainer.tsx +12 -5
- package/src/editor/components/Synchronizer.tsx +5 -2
- package/src/editor/hooks/usePortableTextEditor.ts +2 -2
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +9 -3
- package/src/editor/hooks/useSyncValue.test.tsx +9 -4
- package/src/editor/hooks/useSyncValue.ts +199 -130
- package/src/editor/nodes/DefaultAnnotation.tsx +6 -3
- package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +25 -7
- 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 +4 -2
- package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +4 -2
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +61 -550
- 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 +354 -115
- package/src/editor/plugins/createWithHotKeys.ts +41 -121
- package/src/editor/plugins/createWithInsertBreak.ts +166 -27
- package/src/editor/plugins/createWithInsertData.ts +60 -23
- package/src/editor/plugins/createWithMaxBlocks.ts +5 -2
- package/src/editor/plugins/createWithObjectKeys.ts +7 -3
- package/src/editor/plugins/createWithPatches.ts +60 -16
- package/src/editor/plugins/createWithPlaceholderBlock.ts +7 -3
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +17 -7
- package/src/editor/plugins/createWithPortableTextLists.ts +21 -8
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +301 -155
- package/src/editor/plugins/createWithPortableTextSelections.ts +4 -2
- package/src/editor/plugins/createWithSchemaTypes.ts +25 -9
- package/src/editor/plugins/createWithUndoRedo.ts +107 -24
- package/src/editor/plugins/createWithUtils.ts +32 -10
- package/src/editor/plugins/index.ts +31 -10
- package/src/types/editor.ts +44 -15
- package/src/types/options.ts +4 -2
- package/src/types/slate.ts +2 -2
- package/src/utils/__tests__/dmpToOperations.test.ts +38 -13
- package/src/utils/__tests__/operationToPatches.test.ts +3 -2
- package/src/utils/__tests__/patchToOperations.test.ts +15 -4
- package/src/utils/__tests__/ranges.test.ts +8 -3
- package/src/utils/__tests__/valueNormalization.test.tsx +12 -4
- package/src/utils/__tests__/values.test.ts +0 -1
- package/src/utils/applyPatch.ts +71 -20
- package/src/utils/getPortableTextMemberSchemaTypes.ts +30 -15
- package/src/utils/operationToPatches.ts +126 -43
- package/src/utils/paths.ts +24 -7
- package/src/utils/ranges.ts +12 -5
- package/src/utils/selection.ts +19 -7
- package/src/utils/validateValue.ts +118 -45
- package/src/utils/values.ts +31 -10
- package/src/utils/weakMaps.ts +18 -8
- package/src/utils/withChanges.ts +4 -2
- package/src/editor/plugins/__tests__/withHotkeys.test.tsx +0 -212
- package/src/editor/plugins/__tests__/withInsertBreak.test.tsx +0 -220
- package/src/editor/plugins/__tests__/withPlaceholderBlock.test.tsx +0 -133
|
@@ -6,9 +6,11 @@ import {
|
|
|
6
6
|
type PortableTextSpan,
|
|
7
7
|
type PortableTextTextBlock,
|
|
8
8
|
} from '@sanity/types'
|
|
9
|
-
import {type Element
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import {Transforms, type Element} from 'slate'
|
|
10
|
+
import {
|
|
11
|
+
type PortableTextMemberSchemaTypes,
|
|
12
|
+
type PortableTextSlateEditor,
|
|
13
|
+
} from '../../types/editor'
|
|
12
14
|
import {debugWithName} from '../../utils/debug'
|
|
13
15
|
|
|
14
16
|
const debug = debugWithName('plugin:withSchemaTypes')
|
|
@@ -23,21 +25,31 @@ export function createWithSchemaTypes({
|
|
|
23
25
|
schemaTypes: PortableTextMemberSchemaTypes
|
|
24
26
|
keyGenerator: () => string
|
|
25
27
|
}) {
|
|
26
|
-
return function withSchemaTypes(
|
|
28
|
+
return function withSchemaTypes(
|
|
29
|
+
editor: PortableTextSlateEditor,
|
|
30
|
+
): PortableTextSlateEditor {
|
|
27
31
|
editor.isTextBlock = (value: unknown): value is PortableTextTextBlock => {
|
|
28
|
-
return
|
|
32
|
+
return (
|
|
33
|
+
isPortableTextTextBlock(value) && value._type === schemaTypes.block.name
|
|
34
|
+
)
|
|
29
35
|
}
|
|
30
36
|
editor.isTextSpan = (value: unknown): value is PortableTextSpan => {
|
|
31
37
|
return isPortableTextSpan(value) && value._type == schemaTypes.span.name
|
|
32
38
|
}
|
|
33
39
|
editor.isListBlock = (value: unknown): value is PortableTextListBlock => {
|
|
34
|
-
return
|
|
40
|
+
return (
|
|
41
|
+
isPortableTextListBlock(value) && value._type === schemaTypes.block.name
|
|
42
|
+
)
|
|
35
43
|
}
|
|
36
44
|
editor.isVoid = (element: Element): boolean => {
|
|
37
45
|
return (
|
|
38
46
|
schemaTypes.block.name !== element._type &&
|
|
39
|
-
(schemaTypes.blockObjects
|
|
40
|
-
|
|
47
|
+
(schemaTypes.blockObjects
|
|
48
|
+
.map((obj) => obj.name)
|
|
49
|
+
.includes(element._type) ||
|
|
50
|
+
schemaTypes.inlineObjects
|
|
51
|
+
.map((obj) => obj.name)
|
|
52
|
+
.includes(element._type))
|
|
41
53
|
)
|
|
42
54
|
}
|
|
43
55
|
editor.isInline = (element: Element): boolean => {
|
|
@@ -59,7 +71,11 @@ export function createWithSchemaTypes({
|
|
|
59
71
|
debug('Setting span type on text node without a type')
|
|
60
72
|
const span = node as PortableTextSpan
|
|
61
73
|
const key = span._key || keyGenerator()
|
|
62
|
-
Transforms.setNodes(
|
|
74
|
+
Transforms.setNodes(
|
|
75
|
+
editor,
|
|
76
|
+
{...span, _type: schemaTypes.span.name, _key: key},
|
|
77
|
+
{at: path},
|
|
78
|
+
)
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
// catches cases when the children are missing keys but excludes it when the normalize is running the node as the editor object
|
|
@@ -4,15 +4,34 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {type Patch} from '@portabletext/patches'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
DIFF_DELETE,
|
|
9
|
+
DIFF_EQUAL,
|
|
10
|
+
DIFF_INSERT,
|
|
11
|
+
parsePatch,
|
|
12
|
+
} from '@sanity/diff-match-patch'
|
|
8
13
|
import {type ObjectSchemaType, type PortableTextBlock} from '@sanity/types'
|
|
9
14
|
import {flatten, isEqual} from 'lodash'
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
import {
|
|
16
|
+
Editor,
|
|
17
|
+
Operation,
|
|
18
|
+
Path,
|
|
19
|
+
Transforms,
|
|
20
|
+
type Descendant,
|
|
21
|
+
type SelectionOperation,
|
|
22
|
+
} from 'slate'
|
|
23
|
+
import {
|
|
24
|
+
type PatchObservable,
|
|
25
|
+
type PortableTextSlateEditor,
|
|
26
|
+
} from '../../types/editor'
|
|
13
27
|
import {debugWithName} from '../../utils/debug'
|
|
14
28
|
import {fromSlateValue} from '../../utils/values'
|
|
15
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
setIsRedoing,
|
|
31
|
+
setIsUndoing,
|
|
32
|
+
withRedoing,
|
|
33
|
+
withUndoing,
|
|
34
|
+
} from '../../utils/withUndoRedo'
|
|
16
35
|
|
|
17
36
|
const debug = debugWithName('plugin:withUndoRedo')
|
|
18
37
|
const debugVerbose = debug.enabled && false
|
|
@@ -66,14 +85,21 @@ export function createWithUndoRedo(
|
|
|
66
85
|
patches.forEach((patch) => {
|
|
67
86
|
if (!reset && patch.origin !== 'local' && remotePatches) {
|
|
68
87
|
if (patch.type === 'unset' && patch.path.length === 0) {
|
|
69
|
-
debug(
|
|
88
|
+
debug(
|
|
89
|
+
'Someone else cleared the content, resetting undo/redo history',
|
|
90
|
+
)
|
|
70
91
|
editor.history = {undos: [], redos: []}
|
|
71
92
|
remotePatches.splice(0, remotePatches.length)
|
|
72
93
|
SAVING.set(editor, true)
|
|
73
94
|
reset = true
|
|
74
95
|
return
|
|
75
96
|
}
|
|
76
|
-
remotePatches.push({
|
|
97
|
+
remotePatches.push({
|
|
98
|
+
patch,
|
|
99
|
+
time: new Date(),
|
|
100
|
+
snapshot,
|
|
101
|
+
previousSnapshot,
|
|
102
|
+
})
|
|
77
103
|
}
|
|
78
104
|
})
|
|
79
105
|
previousSnapshot = snapshot
|
|
@@ -94,7 +120,8 @@ export function createWithUndoRedo(
|
|
|
94
120
|
const {operations, history} = editor
|
|
95
121
|
const {undos} = history
|
|
96
122
|
const step = undos[undos.length - 1]
|
|
97
|
-
const lastOp =
|
|
123
|
+
const lastOp =
|
|
124
|
+
step && step.operations && step.operations[step.operations.length - 1]
|
|
98
125
|
const overwrite = shouldOverwrite(op, lastOp)
|
|
99
126
|
const save = isSaving(editor)
|
|
100
127
|
|
|
@@ -110,7 +137,12 @@ export function createWithUndoRedo(
|
|
|
110
137
|
step.operations.push(op)
|
|
111
138
|
} else {
|
|
112
139
|
const newStep = {
|
|
113
|
-
operations: [
|
|
140
|
+
operations: [
|
|
141
|
+
...(editor.selection === null
|
|
142
|
+
? []
|
|
143
|
+
: [createSelectOperation(editor)]),
|
|
144
|
+
op,
|
|
145
|
+
],
|
|
114
146
|
timestamp: new Date(),
|
|
115
147
|
}
|
|
116
148
|
undos.push(newStep)
|
|
@@ -137,16 +169,26 @@ export function createWithUndoRedo(
|
|
|
137
169
|
const step = undos[undos.length - 1]
|
|
138
170
|
debug('Undoing', step)
|
|
139
171
|
if (step.operations.length > 0) {
|
|
140
|
-
const otherPatches = remotePatches.filter(
|
|
172
|
+
const otherPatches = remotePatches.filter(
|
|
173
|
+
(item) => item.time >= step.timestamp,
|
|
174
|
+
)
|
|
141
175
|
let transformedOperations = step.operations
|
|
142
176
|
otherPatches.forEach((item) => {
|
|
143
177
|
transformedOperations = flatten(
|
|
144
178
|
transformedOperations.map((op) =>
|
|
145
|
-
transformOperation(
|
|
179
|
+
transformOperation(
|
|
180
|
+
editor,
|
|
181
|
+
item.patch,
|
|
182
|
+
op,
|
|
183
|
+
item.snapshot,
|
|
184
|
+
item.previousSnapshot,
|
|
185
|
+
),
|
|
146
186
|
),
|
|
147
187
|
)
|
|
148
188
|
})
|
|
149
|
-
const reversedOperations = transformedOperations
|
|
189
|
+
const reversedOperations = transformedOperations
|
|
190
|
+
.map(Operation.inverse)
|
|
191
|
+
.reverse()
|
|
150
192
|
|
|
151
193
|
try {
|
|
152
194
|
Editor.withoutNormalizing(editor, () => {
|
|
@@ -185,12 +227,20 @@ export function createWithUndoRedo(
|
|
|
185
227
|
const step = redos[redos.length - 1]
|
|
186
228
|
debug('Redoing', step)
|
|
187
229
|
if (step.operations.length > 0) {
|
|
188
|
-
const otherPatches = remotePatches.filter(
|
|
230
|
+
const otherPatches = remotePatches.filter(
|
|
231
|
+
(item) => item.time >= step.timestamp,
|
|
232
|
+
)
|
|
189
233
|
let transformedOperations = step.operations
|
|
190
234
|
otherPatches.forEach((item) => {
|
|
191
235
|
transformedOperations = flatten(
|
|
192
236
|
transformedOperations.map((op) =>
|
|
193
|
-
transformOperation(
|
|
237
|
+
transformOperation(
|
|
238
|
+
editor,
|
|
239
|
+
item.patch,
|
|
240
|
+
op,
|
|
241
|
+
item.snapshot,
|
|
242
|
+
item.previousSnapshot,
|
|
243
|
+
),
|
|
194
244
|
),
|
|
195
245
|
)
|
|
196
246
|
})
|
|
@@ -240,7 +290,9 @@ function transformOperation(
|
|
|
240
290
|
previousSnapshot: PortableTextBlock[] | undefined,
|
|
241
291
|
): Operation[] {
|
|
242
292
|
if (debugVerbose) {
|
|
243
|
-
debug(
|
|
293
|
+
debug(
|
|
294
|
+
`Adjusting '${operation.type}' operation paths for '${patch.type}' patch`,
|
|
295
|
+
)
|
|
244
296
|
debug(`Operation ${JSON.stringify(operation)}`)
|
|
245
297
|
debug(`Patch ${JSON.stringify(patch)}`)
|
|
246
298
|
}
|
|
@@ -254,7 +306,13 @@ function transformOperation(
|
|
|
254
306
|
debug(
|
|
255
307
|
`Adjusting block path (+${patch.items.length}) for '${transformedOperation.type}' operation and patch '${patch.type}'`,
|
|
256
308
|
)
|
|
257
|
-
return [
|
|
309
|
+
return [
|
|
310
|
+
adjustBlockPath(
|
|
311
|
+
transformedOperation,
|
|
312
|
+
patch.items.length,
|
|
313
|
+
insertBlockIndex,
|
|
314
|
+
),
|
|
315
|
+
]
|
|
258
316
|
}
|
|
259
317
|
|
|
260
318
|
if (patch.type === 'unset' && patch.path.length === 1) {
|
|
@@ -281,13 +339,21 @@ function transformOperation(
|
|
|
281
339
|
|
|
282
340
|
// Someone reset the whole value
|
|
283
341
|
if (patch.type === 'unset' && patch.path.length === 0) {
|
|
284
|
-
debug(
|
|
342
|
+
debug(
|
|
343
|
+
`Adjusting selection for unset everything patch and ${operation.type} operation`,
|
|
344
|
+
)
|
|
285
345
|
return []
|
|
286
346
|
}
|
|
287
347
|
|
|
288
348
|
if (patch.type === 'diffMatchPatch') {
|
|
289
|
-
const operationTargetBlock = findOperationTargetBlock(
|
|
290
|
-
|
|
349
|
+
const operationTargetBlock = findOperationTargetBlock(
|
|
350
|
+
editor,
|
|
351
|
+
transformedOperation,
|
|
352
|
+
)
|
|
353
|
+
if (
|
|
354
|
+
!operationTargetBlock ||
|
|
355
|
+
!isEqual({_key: operationTargetBlock._key}, patch.path[0])
|
|
356
|
+
) {
|
|
291
357
|
return [transformedOperation]
|
|
292
358
|
}
|
|
293
359
|
const diffPatches = parsePatch(patch.value)
|
|
@@ -318,7 +384,10 @@ function transformOperation(
|
|
|
318
384
|
}
|
|
319
385
|
// Adjust accordingly if someone removed text in the same node before us
|
|
320
386
|
if (transformedOperation.type === 'remove_text') {
|
|
321
|
-
if (
|
|
387
|
+
if (
|
|
388
|
+
changedOffset <=
|
|
389
|
+
transformedOperation.offset - transformedOperation.text.length
|
|
390
|
+
) {
|
|
322
391
|
transformedOperation.offset += adjustOffsetBy
|
|
323
392
|
}
|
|
324
393
|
}
|
|
@@ -365,7 +434,11 @@ function transformOperation(
|
|
|
365
434
|
/**
|
|
366
435
|
* Adjust the block path for a operation
|
|
367
436
|
*/
|
|
368
|
-
function adjustBlockPath(
|
|
437
|
+
function adjustBlockPath(
|
|
438
|
+
operation: Operation,
|
|
439
|
+
level: number,
|
|
440
|
+
blockIndex: number,
|
|
441
|
+
): Operation {
|
|
369
442
|
const transformedOperation = {...operation}
|
|
370
443
|
if (
|
|
371
444
|
blockIndex >= 0 &&
|
|
@@ -374,7 +447,10 @@ function adjustBlockPath(operation: Operation, level: number, blockIndex: number
|
|
|
374
447
|
transformedOperation.path[0] >= blockIndex + level &&
|
|
375
448
|
transformedOperation.path[0] + level > -1
|
|
376
449
|
) {
|
|
377
|
-
const newPath = [
|
|
450
|
+
const newPath = [
|
|
451
|
+
transformedOperation.path[0] + level,
|
|
452
|
+
...transformedOperation.path.slice(1),
|
|
453
|
+
]
|
|
378
454
|
transformedOperation.path = newPath
|
|
379
455
|
}
|
|
380
456
|
if (transformedOperation.type === 'set_selection') {
|
|
@@ -393,7 +469,11 @@ function adjustBlockPath(operation: Operation, level: number, blockIndex: number
|
|
|
393
469
|
if ((currentFocus && currentAnchor) || (newFocus && newAnchor)) {
|
|
394
470
|
const points = [currentFocus, currentAnchor, newFocus, newAnchor]
|
|
395
471
|
points.forEach((point) => {
|
|
396
|
-
if (
|
|
472
|
+
if (
|
|
473
|
+
point &&
|
|
474
|
+
point.path[0] >= blockIndex + level &&
|
|
475
|
+
point.path[0] + level > -1
|
|
476
|
+
) {
|
|
397
477
|
point.path = [point.path[0] + level, ...point.path.slice(1)]
|
|
398
478
|
}
|
|
399
479
|
})
|
|
@@ -449,7 +529,10 @@ const shouldMerge = (op: Operation, prev: Operation | undefined): boolean => {
|
|
|
449
529
|
return false
|
|
450
530
|
}
|
|
451
531
|
|
|
452
|
-
const shouldOverwrite = (
|
|
532
|
+
const shouldOverwrite = (
|
|
533
|
+
op: Operation,
|
|
534
|
+
prev: Operation | undefined,
|
|
535
|
+
): boolean => {
|
|
453
536
|
if (prev && op.type === 'set_selection' && prev.type === 'set_selection') {
|
|
454
537
|
return true
|
|
455
538
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {Editor, Range, Text, Transforms} from 'slate'
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
type PortableTextMemberSchemaTypes,
|
|
4
|
+
type PortableTextSlateEditor,
|
|
5
|
+
} from '../../types/editor'
|
|
4
6
|
import {debugWithName} from '../../utils/debug'
|
|
5
7
|
import {toSlateValue} from '../../utils/values'
|
|
6
8
|
import {type PortableTextEditor} from '../PortableTextEditor'
|
|
@@ -16,8 +18,14 @@ interface Options {
|
|
|
16
18
|
* This plugin makes various util commands available in the editor
|
|
17
19
|
*
|
|
18
20
|
*/
|
|
19
|
-
export function createWithUtils({
|
|
20
|
-
|
|
21
|
+
export function createWithUtils({
|
|
22
|
+
schemaTypes,
|
|
23
|
+
keyGenerator,
|
|
24
|
+
portableTextEditor,
|
|
25
|
+
}: Options) {
|
|
26
|
+
return function withUtils(
|
|
27
|
+
editor: PortableTextSlateEditor,
|
|
28
|
+
): PortableTextSlateEditor {
|
|
21
29
|
// Expands the the selection to wrap around the word the focus is at
|
|
22
30
|
editor.pteExpandToWord = () => {
|
|
23
31
|
const {selection} = editor
|
|
@@ -37,12 +45,24 @@ export function createWithUtils({schemaTypes, keyGenerator, portableTextEditor}:
|
|
|
37
45
|
.reverse()
|
|
38
46
|
.findIndex((str) => isEmpty(str))
|
|
39
47
|
const newStartOffset =
|
|
40
|
-
whiteSpaceBeforeIndex > -1
|
|
41
|
-
|
|
48
|
+
whiteSpaceBeforeIndex > -1
|
|
49
|
+
? charsBefore.length - whiteSpaceBeforeIndex
|
|
50
|
+
: 0
|
|
51
|
+
const whiteSpaceAfterIndex = charsAfter
|
|
52
|
+
.split('')
|
|
53
|
+
.findIndex((obj) => isEmpty(obj))
|
|
42
54
|
const newEndOffset =
|
|
43
55
|
charsBefore.length +
|
|
44
|
-
(whiteSpaceAfterIndex > -1
|
|
45
|
-
|
|
56
|
+
(whiteSpaceAfterIndex > -1
|
|
57
|
+
? whiteSpaceAfterIndex
|
|
58
|
+
: charsAfter.length + 1)
|
|
59
|
+
if (
|
|
60
|
+
!(
|
|
61
|
+
newStartOffset === newEndOffset ||
|
|
62
|
+
isNaN(newStartOffset) ||
|
|
63
|
+
isNaN(newEndOffset)
|
|
64
|
+
)
|
|
65
|
+
) {
|
|
46
66
|
debug('pteExpandToWord: Expanding to focused word')
|
|
47
67
|
Transforms.setSelection(editor, {
|
|
48
68
|
anchor: {...selection.anchor, offset: newStartOffset},
|
|
@@ -54,7 +74,7 @@ export function createWithUtils({schemaTypes, keyGenerator, portableTextEditor}:
|
|
|
54
74
|
}
|
|
55
75
|
}
|
|
56
76
|
|
|
57
|
-
editor.
|
|
77
|
+
editor.pteCreateTextBlock = (options: {decorators: Array<string>}) => {
|
|
58
78
|
const block = toSlateValue(
|
|
59
79
|
[
|
|
60
80
|
{
|
|
@@ -67,7 +87,9 @@ export function createWithUtils({schemaTypes, keyGenerator, portableTextEditor}:
|
|
|
67
87
|
_type: 'span',
|
|
68
88
|
_key: keyGenerator(),
|
|
69
89
|
text: '',
|
|
70
|
-
marks:
|
|
90
|
+
marks: options.decorators.filter((decorator) =>
|
|
91
|
+
schemaTypes.decorators.find(({value}) => value === decorator),
|
|
92
|
+
),
|
|
71
93
|
},
|
|
72
94
|
],
|
|
73
95
|
},
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {noop} from 'lodash'
|
|
2
2
|
import {type BaseOperation, type Editor, type Node, type NodeEntry} from 'slate'
|
|
3
|
-
|
|
4
3
|
import {type PortableTextSlateEditor} from '../../types/editor'
|
|
5
4
|
import {type createEditorOptions} from '../../types/options'
|
|
6
5
|
import {createOperationToPatches} from '../../utils/operationToPatches'
|
|
@@ -38,14 +37,18 @@ export interface OriginalEditorFunctions {
|
|
|
38
37
|
normalizeNode: (entry: NodeEntry<Node>) => void
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
const originalFnMap = new WeakMap<
|
|
40
|
+
const originalFnMap = new WeakMap<
|
|
41
|
+
PortableTextSlateEditor,
|
|
42
|
+
OriginalEditorFunctions
|
|
43
|
+
>()
|
|
42
44
|
|
|
43
45
|
export const withPlugins = <T extends Editor>(
|
|
44
46
|
editor: T,
|
|
45
47
|
options: createEditorOptions,
|
|
46
48
|
): {editor: PortableTextSlateEditor; subscribe: () => () => void} => {
|
|
47
49
|
const e = editor as T & PortableTextSlateEditor
|
|
48
|
-
const {keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks} =
|
|
50
|
+
const {keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks} =
|
|
51
|
+
options
|
|
49
52
|
const {schemaTypes, change$} = portableTextEditor
|
|
50
53
|
e.subscriptions = []
|
|
51
54
|
if (e.destroy) {
|
|
@@ -62,7 +65,11 @@ export const withPlugins = <T extends Editor>(
|
|
|
62
65
|
const operationToPatches = createOperationToPatches(schemaTypes)
|
|
63
66
|
const withObjectKeys = createWithObjectKeys(schemaTypes, keyGenerator)
|
|
64
67
|
const withSchemaTypes = createWithSchemaTypes({schemaTypes, keyGenerator})
|
|
65
|
-
const withEditableAPI = createWithEditableAPI(
|
|
68
|
+
const withEditableAPI = createWithEditableAPI(
|
|
69
|
+
portableTextEditor,
|
|
70
|
+
schemaTypes,
|
|
71
|
+
keyGenerator,
|
|
72
|
+
)
|
|
66
73
|
const withPatches = createWithPatches({
|
|
67
74
|
change$,
|
|
68
75
|
keyGenerator,
|
|
@@ -83,14 +90,22 @@ export const withPlugins = <T extends Editor>(
|
|
|
83
90
|
change$,
|
|
84
91
|
keyGenerator,
|
|
85
92
|
)
|
|
86
|
-
const withPortableTextBlockStyle =
|
|
93
|
+
const withPortableTextBlockStyle =
|
|
94
|
+
createWithPortableTextBlockStyle(schemaTypes)
|
|
87
95
|
|
|
88
96
|
const withPlaceholderBlock = createWithPlaceholderBlock()
|
|
89
97
|
|
|
90
|
-
const withInsertBreak = createWithInsertBreak(schemaTypes)
|
|
98
|
+
const withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator)
|
|
91
99
|
|
|
92
|
-
const withUtils = createWithUtils({
|
|
93
|
-
|
|
100
|
+
const withUtils = createWithUtils({
|
|
101
|
+
keyGenerator,
|
|
102
|
+
schemaTypes,
|
|
103
|
+
portableTextEditor,
|
|
104
|
+
})
|
|
105
|
+
const withPortableTextSelections = createWithPortableTextSelections(
|
|
106
|
+
change$,
|
|
107
|
+
schemaTypes,
|
|
108
|
+
)
|
|
94
109
|
|
|
95
110
|
e.destroy = () => {
|
|
96
111
|
const originalFunctions = originalFnMap.get(e)
|
|
@@ -111,7 +126,9 @@ export const withPlugins = <T extends Editor>(
|
|
|
111
126
|
withUtils(
|
|
112
127
|
withPlaceholderBlock(
|
|
113
128
|
withPortableTextLists(
|
|
114
|
-
withPortableTextSelections(
|
|
129
|
+
withPortableTextSelections(
|
|
130
|
+
withEditableAPI(withInsertBreak(e)),
|
|
131
|
+
),
|
|
115
132
|
),
|
|
116
133
|
),
|
|
117
134
|
),
|
|
@@ -134,7 +151,11 @@ export const withPlugins = <T extends Editor>(
|
|
|
134
151
|
withUtils(
|
|
135
152
|
withMaxBlocks(
|
|
136
153
|
withUndoRedo(
|
|
137
|
-
withPatches(
|
|
154
|
+
withPatches(
|
|
155
|
+
withPortableTextSelections(
|
|
156
|
+
withEditableAPI(withInsertBreak(e)),
|
|
157
|
+
),
|
|
158
|
+
),
|
|
138
159
|
),
|
|
139
160
|
),
|
|
140
161
|
),
|
package/src/types/editor.ts
CHANGED
|
@@ -25,10 +25,13 @@ import {
|
|
|
25
25
|
type RefObject,
|
|
26
26
|
} from 'react'
|
|
27
27
|
import {type Observable, type Subject} from 'rxjs'
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
type Descendant,
|
|
30
|
+
type Node as SlateNode,
|
|
31
|
+
type Operation as SlateOperation,
|
|
32
|
+
} from 'slate'
|
|
29
33
|
import {type ReactEditor} from 'slate-react'
|
|
30
34
|
import {type DOMNode} from 'slate-react/dist/utils/dom'
|
|
31
|
-
|
|
32
35
|
import {type PortableTextEditableProps} from '../editor/Editable'
|
|
33
36
|
import {type PortableTextEditor} from '../editor/PortableTextEditor'
|
|
34
37
|
|
|
@@ -44,11 +47,20 @@ export interface EditableAPI {
|
|
|
44
47
|
addAnnotation: (
|
|
45
48
|
type: ObjectSchemaType,
|
|
46
49
|
value?: {[prop: string]: unknown},
|
|
47
|
-
) =>
|
|
50
|
+
) =>
|
|
51
|
+
| {markDefPath: Path; markDefPaths: Array<Path>; spanPath: Path}
|
|
52
|
+
| undefined
|
|
48
53
|
blur: () => void
|
|
49
|
-
delete: (
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
delete: (
|
|
55
|
+
selection: EditorSelection,
|
|
56
|
+
options?: EditableAPIDeleteOptions,
|
|
57
|
+
) => void
|
|
58
|
+
findByPath: (
|
|
59
|
+
path: Path,
|
|
60
|
+
) => [PortableTextBlock | PortableTextChild | undefined, Path | undefined]
|
|
61
|
+
findDOMNode: (
|
|
62
|
+
element: PortableTextBlock | PortableTextChild,
|
|
63
|
+
) => DOMNode | undefined
|
|
52
64
|
focus: () => void
|
|
53
65
|
focusBlock: () => PortableTextBlock | undefined
|
|
54
66
|
focusChild: () => PortableTextChild | undefined
|
|
@@ -57,13 +69,22 @@ export interface EditableAPI {
|
|
|
57
69
|
getValue: () => PortableTextBlock[] | undefined
|
|
58
70
|
hasBlockStyle: (style: string) => boolean
|
|
59
71
|
hasListStyle: (listStyle: string) => boolean
|
|
60
|
-
insertBlock: (
|
|
61
|
-
|
|
72
|
+
insertBlock: (
|
|
73
|
+
type: BlockSchemaType | ObjectSchemaType,
|
|
74
|
+
value?: {[prop: string]: unknown},
|
|
75
|
+
) => Path
|
|
76
|
+
insertChild: (
|
|
77
|
+
type: SpanSchemaType | ObjectSchemaType,
|
|
78
|
+
value?: {[prop: string]: unknown},
|
|
79
|
+
) => Path
|
|
62
80
|
insertBreak: () => void
|
|
63
81
|
isCollapsedSelection: () => boolean
|
|
64
82
|
isExpandedSelection: () => boolean
|
|
65
83
|
isMarkActive: (mark: string) => boolean
|
|
66
|
-
isSelectionsOverlapping: (
|
|
84
|
+
isSelectionsOverlapping: (
|
|
85
|
+
selectionA: EditorSelection,
|
|
86
|
+
selectionB: EditorSelection,
|
|
87
|
+
) => boolean
|
|
67
88
|
isVoid: (element: PortableTextBlock | PortableTextChild) => boolean
|
|
68
89
|
marks: () => string[]
|
|
69
90
|
redo: () => void
|
|
@@ -199,9 +220,9 @@ export interface PortableTextSlateEditor extends ReactEditor {
|
|
|
199
220
|
pteWithHotKeys: (event: KeyboardEvent<HTMLDivElement>) => void
|
|
200
221
|
|
|
201
222
|
/**
|
|
202
|
-
* Helper function that creates
|
|
223
|
+
* Helper function that creates a text block
|
|
203
224
|
*/
|
|
204
|
-
|
|
225
|
+
pteCreateTextBlock: (options: {decorators: Array<string>}) => Descendant
|
|
205
226
|
|
|
206
227
|
/**
|
|
207
228
|
* Undo
|
|
@@ -498,10 +519,14 @@ export type RenderBlockFunction = (props: BlockRenderProps) => JSX.Element
|
|
|
498
519
|
export type RenderChildFunction = (props: BlockChildRenderProps) => JSX.Element
|
|
499
520
|
|
|
500
521
|
/** @beta */
|
|
501
|
-
export type RenderEditableFunction = (
|
|
522
|
+
export type RenderEditableFunction = (
|
|
523
|
+
props: PortableTextEditableProps,
|
|
524
|
+
) => JSX.Element
|
|
502
525
|
|
|
503
526
|
/** @beta */
|
|
504
|
-
export type RenderAnnotationFunction = (
|
|
527
|
+
export type RenderAnnotationFunction = (
|
|
528
|
+
props: BlockAnnotationRenderProps,
|
|
529
|
+
) => JSX.Element
|
|
505
530
|
|
|
506
531
|
/** @beta */
|
|
507
532
|
export type RenderPlaceholderFunction = () => React.ReactNode
|
|
@@ -522,10 +547,14 @@ export interface BlockStyleRenderProps {
|
|
|
522
547
|
}
|
|
523
548
|
|
|
524
549
|
/** @beta */
|
|
525
|
-
export type RenderListItemFunction = (
|
|
550
|
+
export type RenderListItemFunction = (
|
|
551
|
+
props: BlockListItemRenderProps,
|
|
552
|
+
) => JSX.Element
|
|
526
553
|
|
|
527
554
|
/** @beta */
|
|
528
|
-
export type RenderDecoratorFunction = (
|
|
555
|
+
export type RenderDecoratorFunction = (
|
|
556
|
+
props: BlockDecoratorRenderProps,
|
|
557
|
+
) => JSX.Element
|
|
529
558
|
|
|
530
559
|
/** @beta */
|
|
531
560
|
export type ScrollSelectionIntoViewFunction = (
|
package/src/types/options.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {type BaseSyntheticEvent} from 'react'
|
|
2
|
-
|
|
3
2
|
import {type PortableTextEditor} from '../editor/PortableTextEditor'
|
|
4
3
|
import {type PatchObservable} from './editor'
|
|
5
4
|
|
|
@@ -19,5 +18,8 @@ export type createEditorOptions = {
|
|
|
19
18
|
*/
|
|
20
19
|
export type HotkeyOptions = {
|
|
21
20
|
marks?: Record<string, string>
|
|
22
|
-
custom?: Record<
|
|
21
|
+
custom?: Record<
|
|
22
|
+
string,
|
|
23
|
+
(event: BaseSyntheticEvent, editor: PortableTextEditor) => void
|
|
24
|
+
>
|
|
23
25
|
}
|
package/src/types/slate.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {type PortableTextSpan, type PortableTextTextBlock} from '@sanity/types'
|
|
2
2
|
import {type BaseEditor, type Descendant} from 'slate'
|
|
3
3
|
import {type ReactEditor} from 'slate-react'
|
|
4
|
-
|
|
5
4
|
import {type PortableTextSlateEditor} from '..'
|
|
6
5
|
|
|
7
6
|
export interface VoidElement {
|
|
@@ -12,7 +11,8 @@ export interface VoidElement {
|
|
|
12
11
|
value: Record<string, unknown>
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
export interface SlateTextBlock
|
|
14
|
+
export interface SlateTextBlock
|
|
15
|
+
extends Omit<PortableTextTextBlock, 'children'> {
|
|
16
16
|
children: Descendant[]
|
|
17
17
|
}
|
|
18
18
|
|