@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -59,8 +59,6 @@
|
|
|
59
59
|
"@portabletext/toolkit": "^2.0.15",
|
|
60
60
|
"@sanity/block-tools": "^3.55.0",
|
|
61
61
|
"@sanity/diff-match-patch": "^3.1.1",
|
|
62
|
-
"@sanity/eslint-config-i18n": "^1.1.0",
|
|
63
|
-
"@sanity/eslint-config-studio": "^4.0.0",
|
|
64
62
|
"@sanity/pkg-utils": "^6.10.10",
|
|
65
63
|
"@sanity/schema": "^3.55.0",
|
|
66
64
|
"@sanity/test": "0.0.1-alpha.1",
|
|
@@ -78,20 +76,8 @@
|
|
|
78
76
|
"@types/react": "^18.3.3",
|
|
79
77
|
"@types/react-dom": "^18.3.0",
|
|
80
78
|
"@types/ws": "~8.5.12",
|
|
81
|
-
"@typescript-eslint/eslint-plugin": "^8.2.0",
|
|
82
|
-
"@typescript-eslint/parser": "^8.2.0",
|
|
83
79
|
"@vitejs/plugin-react": "^4.3.1",
|
|
84
80
|
"dotenv": "^16.4.5",
|
|
85
|
-
"eslint": "^8.57.0",
|
|
86
|
-
"eslint-config-prettier": "^9.1.0",
|
|
87
|
-
"eslint-config-sanity": "^7.1.2",
|
|
88
|
-
"eslint-import-resolver-typescript": "^3.6.1",
|
|
89
|
-
"eslint-plugin-import": "^2.29.1",
|
|
90
|
-
"eslint-plugin-prettier": "^5.2.1",
|
|
91
|
-
"eslint-plugin-react-compiler": "0.0.0-experimental-eeb1b2a-20240818",
|
|
92
|
-
"eslint-plugin-tsdoc": "^0.3.0",
|
|
93
|
-
"eslint-plugin-unicorn": "^55.0.0",
|
|
94
|
-
"eslint-plugin-unused-imports": "^4.1.3",
|
|
95
81
|
"express": "^4.19.2",
|
|
96
82
|
"express-ws": "^5.0.2",
|
|
97
83
|
"jest": "^29.7.0",
|
|
@@ -125,12 +111,12 @@
|
|
|
125
111
|
},
|
|
126
112
|
"scripts": {
|
|
127
113
|
"build": "pkg-utils build --strict --check --clean",
|
|
128
|
-
"check:lint": "
|
|
129
|
-
"check:types": "tsc
|
|
114
|
+
"check:lint": "biome lint .",
|
|
115
|
+
"check:types": "tsc",
|
|
130
116
|
"clean": "del .turbo && del lib && del node_modules",
|
|
131
117
|
"dev": "pkg-utils watch",
|
|
132
118
|
"dev:e2e-server": "cd ./e2e-tests/ && tsx serve",
|
|
133
|
-
"lint:fix": "
|
|
119
|
+
"lint:fix": "biome lint --write .",
|
|
134
120
|
"test": "jest",
|
|
135
121
|
"test:e2e": "jest --config=e2e-tests/e2e.config.ts",
|
|
136
122
|
"test:e2e:watch": "jest --config=e2e-tests/e2e.config.ts --watch",
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -1,62 +1,69 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type {PortableTextBlock} from '@sanity/types'
|
|
2
2
|
import {isEqual, noop} from 'lodash'
|
|
3
3
|
import {
|
|
4
|
+
forwardRef,
|
|
5
|
+
useCallback,
|
|
6
|
+
useEffect,
|
|
7
|
+
useImperativeHandle,
|
|
8
|
+
useMemo,
|
|
9
|
+
useRef,
|
|
10
|
+
useState,
|
|
4
11
|
type ClipboardEvent,
|
|
5
12
|
type CSSProperties,
|
|
6
13
|
type FocusEventHandler,
|
|
7
14
|
type ForwardedRef,
|
|
8
|
-
forwardRef,
|
|
9
15
|
type HTMLProps,
|
|
10
16
|
type KeyboardEvent,
|
|
11
17
|
type MutableRefObject,
|
|
12
18
|
type TextareaHTMLAttributes,
|
|
13
|
-
useCallback,
|
|
14
|
-
useEffect,
|
|
15
|
-
useImperativeHandle,
|
|
16
|
-
useMemo,
|
|
17
|
-
useRef,
|
|
18
|
-
useState,
|
|
19
19
|
} from 'react'
|
|
20
20
|
import {
|
|
21
|
-
type BaseRange,
|
|
22
21
|
Editor,
|
|
23
22
|
Node,
|
|
24
|
-
type NodeEntry,
|
|
25
|
-
type Operation,
|
|
26
23
|
Path,
|
|
27
24
|
Range as SlateRange,
|
|
28
|
-
type Text,
|
|
29
25
|
Transforms,
|
|
26
|
+
type BaseRange,
|
|
27
|
+
type NodeEntry,
|
|
28
|
+
type Operation,
|
|
29
|
+
type Text,
|
|
30
30
|
} from 'slate'
|
|
31
31
|
import {
|
|
32
|
-
Editable as SlateEditable,
|
|
33
32
|
ReactEditor,
|
|
33
|
+
Editable as SlateEditable,
|
|
34
|
+
useSlate,
|
|
34
35
|
type RenderElementProps,
|
|
35
36
|
type RenderLeafProps,
|
|
36
|
-
useSlate,
|
|
37
37
|
} from 'slate-react'
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
type ScrollSelectionIntoViewFunction,
|
|
38
|
+
import type {
|
|
39
|
+
EditorChange,
|
|
40
|
+
EditorSelection,
|
|
41
|
+
OnCopyFn,
|
|
42
|
+
OnPasteFn,
|
|
43
|
+
RangeDecoration,
|
|
44
|
+
RenderAnnotationFunction,
|
|
45
|
+
RenderBlockFunction,
|
|
46
|
+
RenderChildFunction,
|
|
47
|
+
RenderDecoratorFunction,
|
|
48
|
+
RenderListItemFunction,
|
|
49
|
+
RenderPlaceholderFunction,
|
|
50
|
+
RenderStyleFunction,
|
|
51
|
+
ScrollSelectionIntoViewFunction,
|
|
53
52
|
} from '../types/editor'
|
|
54
|
-
import
|
|
55
|
-
import
|
|
53
|
+
import type {HotkeyOptions} from '../types/options'
|
|
54
|
+
import type {SlateTextBlock, VoidElement} from '../types/slate'
|
|
56
55
|
import {debugWithName} from '../utils/debug'
|
|
57
|
-
import {
|
|
56
|
+
import {
|
|
57
|
+
moveRangeByOperation,
|
|
58
|
+
toPortableTextRange,
|
|
59
|
+
toSlateRange,
|
|
60
|
+
} from '../utils/ranges'
|
|
58
61
|
import {normalizeSelection} from '../utils/selection'
|
|
59
|
-
import {
|
|
62
|
+
import {
|
|
63
|
+
fromSlateValue,
|
|
64
|
+
isEqualToEmptyEditor,
|
|
65
|
+
toSlateValue,
|
|
66
|
+
} from '../utils/values'
|
|
60
67
|
import {Element} from './components/Element'
|
|
61
68
|
import {Leaf} from './components/Leaf'
|
|
62
69
|
import {usePortableTextEditor} from './hooks/usePortableTextEditor'
|
|
@@ -138,12 +145,19 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
138
145
|
const readOnly = usePortableTextEditorReadOnlyStatus()
|
|
139
146
|
const keyGenerator = usePortableTextEditorKeyGenerator()
|
|
140
147
|
const ref = useRef<HTMLDivElement | null>(null)
|
|
141
|
-
const [editableElement, setEditableElement] = useState<HTMLDivElement | null>(
|
|
148
|
+
const [editableElement, setEditableElement] = useState<HTMLDivElement | null>(
|
|
149
|
+
null,
|
|
150
|
+
)
|
|
142
151
|
const [hasInvalidValue, setHasInvalidValue] = useState(false)
|
|
143
|
-
const [rangeDecorationState, setRangeDecorationsState] = useState<
|
|
152
|
+
const [rangeDecorationState, setRangeDecorationsState] = useState<
|
|
153
|
+
BaseRangeWithDecoration[]
|
|
154
|
+
>([])
|
|
144
155
|
|
|
145
156
|
// Forward ref to parent component
|
|
146
|
-
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(
|
|
157
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(
|
|
158
|
+
forwardedRef,
|
|
159
|
+
() => ref.current,
|
|
160
|
+
)
|
|
147
161
|
|
|
148
162
|
const rangeDecorationsRef = useRef(rangeDecorations)
|
|
149
163
|
|
|
@@ -187,7 +201,15 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
187
201
|
spellCheck={spellCheck}
|
|
188
202
|
/>
|
|
189
203
|
),
|
|
190
|
-
[
|
|
204
|
+
[
|
|
205
|
+
schemaTypes,
|
|
206
|
+
spellCheck,
|
|
207
|
+
readOnly,
|
|
208
|
+
renderBlock,
|
|
209
|
+
renderChild,
|
|
210
|
+
renderListItem,
|
|
211
|
+
renderStyle,
|
|
212
|
+
],
|
|
191
213
|
)
|
|
192
214
|
|
|
193
215
|
const renderLeaf = useCallback(
|
|
@@ -207,7 +229,11 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
207
229
|
readOnly={readOnly}
|
|
208
230
|
/>
|
|
209
231
|
)
|
|
210
|
-
if (
|
|
232
|
+
if (
|
|
233
|
+
renderPlaceholder &&
|
|
234
|
+
lProps.leaf.placeholder &&
|
|
235
|
+
lProps.text.text === ''
|
|
236
|
+
) {
|
|
211
237
|
return (
|
|
212
238
|
<>
|
|
213
239
|
<span style={PLACEHOLDER_STYLE} contentEditable={false}>
|
|
@@ -225,7 +251,14 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
225
251
|
}
|
|
226
252
|
return lProps.children
|
|
227
253
|
},
|
|
228
|
-
[
|
|
254
|
+
[
|
|
255
|
+
readOnly,
|
|
256
|
+
renderAnnotation,
|
|
257
|
+
renderChild,
|
|
258
|
+
renderDecorator,
|
|
259
|
+
renderPlaceholder,
|
|
260
|
+
schemaTypes,
|
|
261
|
+
],
|
|
229
262
|
)
|
|
230
263
|
|
|
231
264
|
const restoreSelectionFromProps = useCallback(() => {
|
|
@@ -236,7 +269,9 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
236
269
|
fromSlateValue(slateEditor.children, blockTypeName),
|
|
237
270
|
)
|
|
238
271
|
if (normalizedSelection !== null) {
|
|
239
|
-
debug(
|
|
272
|
+
debug(
|
|
273
|
+
`Normalized selection from props ${JSON.stringify(normalizedSelection)}`,
|
|
274
|
+
)
|
|
240
275
|
const slateRange = toSlateRange(normalizedSelection, slateEditor)
|
|
241
276
|
if (slateRange) {
|
|
242
277
|
Transforms.select(slateEditor, slateRange)
|
|
@@ -256,7 +291,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
256
291
|
if (rangeDecorations && rangeDecorations.length > 0) {
|
|
257
292
|
const newSlateRanges: BaseRangeWithDecoration[] = []
|
|
258
293
|
rangeDecorations.forEach((rangeDecorationItem) => {
|
|
259
|
-
const slateRange = toSlateRange(
|
|
294
|
+
const slateRange = toSlateRange(
|
|
295
|
+
rangeDecorationItem.selection,
|
|
296
|
+
slateEditor,
|
|
297
|
+
)
|
|
260
298
|
if (!SlateRange.isRange(slateRange)) {
|
|
261
299
|
if (rangeDecorationItem.onMoved) {
|
|
262
300
|
rangeDecorationItem.onMoved({
|
|
@@ -270,9 +308,16 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
270
308
|
let newRange: BaseRange | null | undefined
|
|
271
309
|
if (operation) {
|
|
272
310
|
newRange = moveRangeByOperation(slateRange, operation)
|
|
273
|
-
if (
|
|
311
|
+
if (
|
|
312
|
+
(newRange && newRange !== slateRange) ||
|
|
313
|
+
(newRange === null && slateRange)
|
|
314
|
+
) {
|
|
274
315
|
const value = PortableTextEditor.getValue(portableTextEditor)
|
|
275
|
-
const newRangeSelection = toPortableTextRange(
|
|
316
|
+
const newRangeSelection = toPortableTextRange(
|
|
317
|
+
value,
|
|
318
|
+
newRange,
|
|
319
|
+
schemaTypes,
|
|
320
|
+
)
|
|
276
321
|
if (rangeDecorationItem.onMoved) {
|
|
277
322
|
rangeDecorationItem.onMoved({
|
|
278
323
|
newSelection: newRangeSelection,
|
|
@@ -285,7 +330,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
285
330
|
// If the newRange is null, it means that the range is not valid anymore and should be removed
|
|
286
331
|
// If it's undefined, it means that the slateRange is still valid and should be kept
|
|
287
332
|
if (newRange !== null) {
|
|
288
|
-
newSlateRanges.push({
|
|
333
|
+
newSlateRanges.push({
|
|
334
|
+
...(newRange || slateRange),
|
|
335
|
+
rangeDecoration: rangeDecorationItem,
|
|
336
|
+
})
|
|
289
337
|
}
|
|
290
338
|
})
|
|
291
339
|
if (newSlateRanges.length > 0) {
|
|
@@ -293,7 +341,9 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
293
341
|
return
|
|
294
342
|
}
|
|
295
343
|
}
|
|
296
|
-
|
|
344
|
+
if (rangeDecorationState.length > 0) {
|
|
345
|
+
setRangeDecorationsState([])
|
|
346
|
+
}
|
|
297
347
|
},
|
|
298
348
|
[portableTextEditor, rangeDecorations, schemaTypes, slateEditor],
|
|
299
349
|
)
|
|
@@ -388,7 +438,11 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
388
438
|
}
|
|
389
439
|
|
|
390
440
|
const value = PortableTextEditor.getValue(portableTextEditor)
|
|
391
|
-
const ptRange = toPortableTextRange(
|
|
441
|
+
const ptRange = toPortableTextRange(
|
|
442
|
+
value,
|
|
443
|
+
slateEditor.selection,
|
|
444
|
+
schemaTypes,
|
|
445
|
+
)
|
|
392
446
|
const path = ptRange?.focus.path || []
|
|
393
447
|
const onPasteResult = onPaste({event, value, path, schemaTypes})
|
|
394
448
|
|
|
@@ -406,14 +460,19 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
406
460
|
slateEditor.insertData(event.clipboardData)
|
|
407
461
|
} else if (result.insert) {
|
|
408
462
|
slateEditor.insertFragment(
|
|
409
|
-
toSlateValue(result.insert as PortableTextBlock[], {
|
|
463
|
+
toSlateValue(result.insert as PortableTextBlock[], {
|
|
464
|
+
schemaTypes,
|
|
465
|
+
}),
|
|
410
466
|
)
|
|
411
467
|
} else {
|
|
412
|
-
console.warn(
|
|
468
|
+
console.warn(
|
|
469
|
+
'Your onPaste function returned something unexpected:',
|
|
470
|
+
result,
|
|
471
|
+
)
|
|
413
472
|
}
|
|
414
473
|
})
|
|
415
474
|
.catch((error) => {
|
|
416
|
-
console.error(error)
|
|
475
|
+
console.error(error)
|
|
417
476
|
return error
|
|
418
477
|
})
|
|
419
478
|
.finally(() => {
|
|
@@ -465,7 +524,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
465
524
|
| SlateTextBlock
|
|
466
525
|
| VoidElement
|
|
467
526
|
if (lastBlock && Editor.isVoid(slateEditor, node)) {
|
|
468
|
-
Transforms.insertNodes(
|
|
527
|
+
Transforms.insertNodes(
|
|
528
|
+
slateEditor,
|
|
529
|
+
slateEditor.pteCreateTextBlock({decorators: []}),
|
|
530
|
+
)
|
|
469
531
|
slateEditor.onChange()
|
|
470
532
|
}
|
|
471
533
|
}
|
|
@@ -528,7 +590,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
528
590
|
}
|
|
529
591
|
const existingDOMRange = domSelection.getRangeAt(0)
|
|
530
592
|
try {
|
|
531
|
-
const newDOMRange = ReactEditor.toDOMRange(
|
|
593
|
+
const newDOMRange = ReactEditor.toDOMRange(
|
|
594
|
+
slateEditor,
|
|
595
|
+
slateEditor.selection,
|
|
596
|
+
)
|
|
532
597
|
if (
|
|
533
598
|
newDOMRange.startOffset !== existingDOMRange.startOffset ||
|
|
534
599
|
newDOMRange.endOffset !== existingDOMRange.endOffset
|
|
@@ -625,12 +690,17 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
625
690
|
if (path.length !== 2) {
|
|
626
691
|
return false
|
|
627
692
|
}
|
|
628
|
-
return
|
|
693
|
+
return (
|
|
694
|
+
Path.equals(item.focus.path, path) &&
|
|
695
|
+
Path.equals(item.anchor.path, path)
|
|
696
|
+
)
|
|
629
697
|
}
|
|
630
698
|
// Include decorations that either include or intersects with this path
|
|
631
699
|
return (
|
|
632
|
-
SlateRange.intersection(item, {
|
|
633
|
-
|
|
700
|
+
SlateRange.intersection(item, {
|
|
701
|
+
anchor: {path, offset: 0},
|
|
702
|
+
focus: {path, offset: 0},
|
|
703
|
+
}) || SlateRange.includes(item, path)
|
|
634
704
|
)
|
|
635
705
|
})
|
|
636
706
|
if (result.length > 0) {
|
|
@@ -645,7 +715,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
645
715
|
// Also set the editable element in a state so that the MutationObserver
|
|
646
716
|
// is setup when this element is ready.
|
|
647
717
|
useEffect(() => {
|
|
648
|
-
ref.current = ReactEditor.toDOMNode(
|
|
718
|
+
ref.current = ReactEditor.toDOMNode(
|
|
719
|
+
slateEditor,
|
|
720
|
+
slateEditor,
|
|
721
|
+
) as HTMLDivElement | null
|
|
649
722
|
setEditableElement(ref.current)
|
|
650
723
|
}, [slateEditor, ref])
|
|
651
724
|
|
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import type {
|
|
2
|
+
ArrayDefinition,
|
|
3
|
+
ArraySchemaType,
|
|
4
|
+
BlockSchemaType,
|
|
5
|
+
ObjectSchemaType,
|
|
6
|
+
Path,
|
|
7
|
+
PortableTextBlock,
|
|
8
|
+
PortableTextChild,
|
|
9
|
+
PortableTextObject,
|
|
10
|
+
SpanSchemaType,
|
|
11
11
|
} from '@sanity/types'
|
|
12
12
|
import {Component, type MutableRefObject, type PropsWithChildren} from 'react'
|
|
13
13
|
import {Subject} from 'rxjs'
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type PortableTextMemberSchemaTypes,
|
|
14
|
+
import type {
|
|
15
|
+
EditableAPI,
|
|
16
|
+
EditableAPIDeleteOptions,
|
|
17
|
+
EditorChange,
|
|
18
|
+
EditorChanges,
|
|
19
|
+
EditorSelection,
|
|
20
|
+
PatchObservable,
|
|
21
|
+
PortableTextMemberSchemaTypes,
|
|
23
22
|
} from '../types/editor'
|
|
24
23
|
import {debugWithName} from '../utils/debug'
|
|
25
24
|
import {getPortableTextMemberSchemaTypes} from '../utils/getPortableTextMemberSchemaTypes'
|
|
@@ -114,7 +113,9 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
if (props.incomingPatches$) {
|
|
117
|
-
console.warn(
|
|
116
|
+
console.warn(
|
|
117
|
+
`The prop 'incomingPatches$' is deprecated and renamed to 'patches$'`,
|
|
118
|
+
)
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
this.change$.next({type: 'loading', isLoading: true})
|
|
@@ -160,7 +161,7 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
160
161
|
const maxBlocks =
|
|
161
162
|
typeof this.props.maxBlocks === 'undefined'
|
|
162
163
|
? undefined
|
|
163
|
-
: parseInt(this.props.maxBlocks.toString(), 10) || undefined
|
|
164
|
+
: Number.parseInt(this.props.maxBlocks.toString(), 10) || undefined
|
|
164
165
|
|
|
165
166
|
const readOnly = Boolean(this.props.readOnly)
|
|
166
167
|
const keyGenerator = this.props.keyGenerator || defaultKeyGenerator
|
|
@@ -192,20 +193,39 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
// Static API methods
|
|
195
|
-
static activeAnnotations = (
|
|
196
|
+
static activeAnnotations = (
|
|
197
|
+
editor: PortableTextEditor,
|
|
198
|
+
): PortableTextObject[] => {
|
|
196
199
|
return editor && editor.editable ? editor.editable.activeAnnotations() : []
|
|
197
200
|
}
|
|
198
201
|
static isAnnotationActive = (
|
|
199
202
|
editor: PortableTextEditor,
|
|
200
203
|
annotationType: PortableTextObject['_type'],
|
|
201
204
|
): boolean => {
|
|
202
|
-
return editor && editor.editable
|
|
205
|
+
return editor && editor.editable
|
|
206
|
+
? editor.editable.isAnnotationActive(annotationType)
|
|
207
|
+
: false
|
|
203
208
|
}
|
|
204
209
|
static addAnnotation = (
|
|
205
210
|
editor: PortableTextEditor,
|
|
206
211
|
type: ObjectSchemaType,
|
|
207
212
|
value?: {[prop: string]: unknown},
|
|
208
|
-
):
|
|
213
|
+
):
|
|
214
|
+
| {
|
|
215
|
+
/**
|
|
216
|
+
* @deprecated An annotation may be applied to multiple blocks, resulting
|
|
217
|
+
* in multiple `markDef`'s being created. Use `markDefPaths` instead.
|
|
218
|
+
*/
|
|
219
|
+
markDefPath: Path
|
|
220
|
+
markDefPaths: Array<Path>
|
|
221
|
+
/**
|
|
222
|
+
* @deprecated Does not return anything meaningful since an annotation
|
|
223
|
+
* can span multiple blocks and spans. If references the span closest
|
|
224
|
+
* to the focus point of the selection.
|
|
225
|
+
*/
|
|
226
|
+
spanPath: Path
|
|
227
|
+
}
|
|
228
|
+
| undefined => editor.editable?.addAnnotation(type, value)
|
|
209
229
|
static blur = (editor: PortableTextEditor): void => {
|
|
210
230
|
debug('Host blurred')
|
|
211
231
|
editor.editable?.blur()
|
|
@@ -219,7 +239,6 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
219
239
|
editor: PortableTextEditor,
|
|
220
240
|
element: PortableTextBlock | PortableTextChild,
|
|
221
241
|
) => {
|
|
222
|
-
// eslint-disable-next-line react/no-find-dom-node
|
|
223
242
|
return editor.editable?.findDOMNode(element)
|
|
224
243
|
}
|
|
225
244
|
static findByPath = (editor: PortableTextEditor, path: Path) => {
|
|
@@ -232,7 +251,9 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
232
251
|
static focusBlock = (editor: PortableTextEditor) => {
|
|
233
252
|
return editor.editable?.focusBlock()
|
|
234
253
|
}
|
|
235
|
-
static focusChild = (
|
|
254
|
+
static focusChild = (
|
|
255
|
+
editor: PortableTextEditor,
|
|
256
|
+
): PortableTextChild | undefined => {
|
|
236
257
|
return editor.editable?.focusChild()
|
|
237
258
|
}
|
|
238
259
|
static getSelection = (editor: PortableTextEditor) => {
|
|
@@ -271,7 +292,10 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
271
292
|
static insertBreak = (editor: PortableTextEditor): void => {
|
|
272
293
|
return editor.editable?.insertBreak()
|
|
273
294
|
}
|
|
274
|
-
static isVoid = (
|
|
295
|
+
static isVoid = (
|
|
296
|
+
editor: PortableTextEditor,
|
|
297
|
+
element: PortableTextBlock | PortableTextChild,
|
|
298
|
+
) => {
|
|
275
299
|
return editor.editable?.isVoid(element)
|
|
276
300
|
}
|
|
277
301
|
static isObjectPath = (editor: PortableTextEditor, path: Path): boolean => {
|
|
@@ -283,13 +307,21 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
283
307
|
static marks = (editor: PortableTextEditor) => {
|
|
284
308
|
return editor.editable?.marks()
|
|
285
309
|
}
|
|
286
|
-
static select = (
|
|
310
|
+
static select = (
|
|
311
|
+
editor: PortableTextEditor,
|
|
312
|
+
selection: EditorSelection | null,
|
|
313
|
+
) => {
|
|
287
314
|
debug(`Host setting selection`, selection)
|
|
288
315
|
editor.editable?.select(selection)
|
|
289
316
|
}
|
|
290
|
-
static removeAnnotation = (
|
|
291
|
-
editor
|
|
292
|
-
|
|
317
|
+
static removeAnnotation = (
|
|
318
|
+
editor: PortableTextEditor,
|
|
319
|
+
type: ObjectSchemaType,
|
|
320
|
+
) => editor.editable?.removeAnnotation(type)
|
|
321
|
+
static toggleBlockStyle = (
|
|
322
|
+
editor: PortableTextEditor,
|
|
323
|
+
blockStyle: string,
|
|
324
|
+
) => {
|
|
293
325
|
debug(`Host is toggling block style`)
|
|
294
326
|
return editor.editable?.toggleBlockStyle(blockStyle)
|
|
295
327
|
}
|
|
@@ -300,7 +332,9 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
300
332
|
debug(`Host toggling mark`, mark)
|
|
301
333
|
editor.editable?.toggleMark(mark)
|
|
302
334
|
}
|
|
303
|
-
static getFragment = (
|
|
335
|
+
static getFragment = (
|
|
336
|
+
editor: PortableTextEditor,
|
|
337
|
+
): PortableTextBlock[] | undefined => {
|
|
304
338
|
debug(`Host getting fragment`)
|
|
305
339
|
return editor.editable?.getFragment()
|
|
306
340
|
}
|