@portabletext/editor 1.7.1 → 1.9.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 +97 -23
- package/lib/index.d.ts +97 -23
- package/lib/index.esm.js +244 -73
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +244 -73
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +244 -73
- package/lib/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/editor/Editable.tsx +46 -31
- package/src/editor/behavior/behavior.action.insert-span.ts +48 -0
- package/src/editor/behavior/behavior.actions.ts +29 -1
- package/src/editor/behavior/behavior.links.ts +91 -0
- package/src/editor/behavior/behavior.markdown.ts +78 -11
- package/src/editor/behavior/behavior.types.ts +18 -0
- package/src/editor/plugins/createWithEditableAPI.ts +91 -71
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +6 -2
- package/src/editor/plugins/with-plugins.ts +7 -2
- package/src/index.ts +5 -1
- package/src/types/options.ts +0 -9
- package/src/utils/__tests__/operationToPatches.test.ts +1 -1
- package/src/utils/__tests__/patchToOperations.test.ts +1 -1
|
@@ -206,77 +206,18 @@ export function createEditableAPI(
|
|
|
206
206
|
type: TSchemaType,
|
|
207
207
|
value?: {[prop: string]: any},
|
|
208
208
|
): Path => {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const lastBlock = Array.from(
|
|
222
|
-
Editor.nodes(editor, {
|
|
223
|
-
match: (n) => !Editor.isEditor(n),
|
|
224
|
-
at: [],
|
|
225
|
-
reverse: true,
|
|
226
|
-
}),
|
|
227
|
-
)[0]
|
|
228
|
-
|
|
229
|
-
// If there is no selection, let's just insert the new block at the
|
|
230
|
-
// end of the document
|
|
231
|
-
Editor.insertNode(editor, block)
|
|
232
|
-
|
|
233
|
-
if (lastBlock && isEqualToEmptyEditor([lastBlock[0]], types)) {
|
|
234
|
-
// And if the last block was an empty text block, let's remove
|
|
235
|
-
// that too
|
|
236
|
-
Transforms.removeNodes(editor, {at: lastBlock[1]})
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
editor.onChange()
|
|
240
|
-
|
|
241
|
-
return (
|
|
242
|
-
toPortableTextRange(
|
|
243
|
-
fromSlateValue(
|
|
244
|
-
editor.children,
|
|
245
|
-
types.block.name,
|
|
246
|
-
KEY_TO_VALUE_ELEMENT.get(editor),
|
|
247
|
-
),
|
|
248
|
-
editor.selection,
|
|
249
|
-
types,
|
|
250
|
-
)?.focus.path ?? []
|
|
251
|
-
)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const focusBlock = Array.from(
|
|
255
|
-
Editor.nodes(editor, {
|
|
256
|
-
at: editor.selection.focus.path.slice(0, 1),
|
|
257
|
-
match: (n) => n._type === types.block.name,
|
|
258
|
-
}),
|
|
259
|
-
)[0]
|
|
260
|
-
|
|
261
|
-
Editor.insertNode(editor, block)
|
|
262
|
-
|
|
263
|
-
if (focusBlock && isEqualToEmptyEditor([focusBlock[0]], types)) {
|
|
264
|
-
Transforms.removeNodes(editor, {at: focusBlock[1]})
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
editor.onChange()
|
|
268
|
-
|
|
269
|
-
return (
|
|
270
|
-
toPortableTextRange(
|
|
271
|
-
fromSlateValue(
|
|
272
|
-
editor.children,
|
|
273
|
-
types.block.name,
|
|
274
|
-
KEY_TO_VALUE_ELEMENT.get(editor),
|
|
275
|
-
),
|
|
276
|
-
editor.selection,
|
|
277
|
-
types,
|
|
278
|
-
)?.focus.path || []
|
|
279
|
-
)
|
|
209
|
+
return insertBlockObjectActionImplementation({
|
|
210
|
+
context: {
|
|
211
|
+
keyGenerator: editorActor.getSnapshot().context.keyGenerator,
|
|
212
|
+
schema: types,
|
|
213
|
+
},
|
|
214
|
+
action: {
|
|
215
|
+
type: 'insert block object',
|
|
216
|
+
name: type.name,
|
|
217
|
+
value,
|
|
218
|
+
editor,
|
|
219
|
+
},
|
|
220
|
+
})
|
|
280
221
|
},
|
|
281
222
|
hasBlockStyle: (style: string): boolean => {
|
|
282
223
|
try {
|
|
@@ -546,6 +487,85 @@ export function createEditableAPI(
|
|
|
546
487
|
return editableApi
|
|
547
488
|
}
|
|
548
489
|
|
|
490
|
+
export const insertBlockObjectActionImplementation: BehaviourActionImplementation<
|
|
491
|
+
'insert block object',
|
|
492
|
+
Path
|
|
493
|
+
> = ({context, action}) => {
|
|
494
|
+
const editor = action.editor
|
|
495
|
+
const types = context.schema
|
|
496
|
+
const block = toSlateValue(
|
|
497
|
+
[
|
|
498
|
+
{
|
|
499
|
+
_key: context.keyGenerator(),
|
|
500
|
+
_type: action.name,
|
|
501
|
+
...(action.value ? action.value : {}),
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
{schemaTypes: context.schema},
|
|
505
|
+
)[0] as unknown as Node
|
|
506
|
+
|
|
507
|
+
if (!editor.selection) {
|
|
508
|
+
const lastBlock = Array.from(
|
|
509
|
+
Editor.nodes(editor, {
|
|
510
|
+
match: (n) => !Editor.isEditor(n),
|
|
511
|
+
at: [],
|
|
512
|
+
reverse: true,
|
|
513
|
+
}),
|
|
514
|
+
)[0]
|
|
515
|
+
|
|
516
|
+
// If there is no selection, let's just insert the new block at the
|
|
517
|
+
// end of the document
|
|
518
|
+
Editor.insertNode(editor, block)
|
|
519
|
+
|
|
520
|
+
if (lastBlock && isEqualToEmptyEditor([lastBlock[0]], types)) {
|
|
521
|
+
// And if the last block was an empty text block, let's remove
|
|
522
|
+
// that too
|
|
523
|
+
Transforms.removeNodes(editor, {at: lastBlock[1]})
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
editor.onChange()
|
|
527
|
+
|
|
528
|
+
return (
|
|
529
|
+
toPortableTextRange(
|
|
530
|
+
fromSlateValue(
|
|
531
|
+
editor.children,
|
|
532
|
+
types.block.name,
|
|
533
|
+
KEY_TO_VALUE_ELEMENT.get(editor),
|
|
534
|
+
),
|
|
535
|
+
editor.selection,
|
|
536
|
+
types,
|
|
537
|
+
)?.focus.path ?? []
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const focusBlock = Array.from(
|
|
542
|
+
Editor.nodes(editor, {
|
|
543
|
+
at: editor.selection.focus.path.slice(0, 1),
|
|
544
|
+
match: (n) => n._type === types.block.name,
|
|
545
|
+
}),
|
|
546
|
+
)[0]
|
|
547
|
+
|
|
548
|
+
Editor.insertNode(editor, block)
|
|
549
|
+
|
|
550
|
+
if (focusBlock && isEqualToEmptyEditor([focusBlock[0]], types)) {
|
|
551
|
+
Transforms.removeNodes(editor, {at: focusBlock[1]})
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
editor.onChange()
|
|
555
|
+
|
|
556
|
+
return (
|
|
557
|
+
toPortableTextRange(
|
|
558
|
+
fromSlateValue(
|
|
559
|
+
editor.children,
|
|
560
|
+
types.block.name,
|
|
561
|
+
KEY_TO_VALUE_ELEMENT.get(editor),
|
|
562
|
+
),
|
|
563
|
+
editor.selection,
|
|
564
|
+
types,
|
|
565
|
+
)?.focus.path || []
|
|
566
|
+
)
|
|
567
|
+
}
|
|
568
|
+
|
|
549
569
|
function isAnnotationActive({
|
|
550
570
|
editor,
|
|
551
571
|
annotation,
|
|
@@ -837,12 +837,16 @@ export function isDecoratorActive({
|
|
|
837
837
|
return false
|
|
838
838
|
}
|
|
839
839
|
|
|
840
|
-
const
|
|
840
|
+
const selectedTextNodes = Array.from(
|
|
841
841
|
Editor.nodes(editor, {match: Text.isText, at: editor.selection}),
|
|
842
842
|
)
|
|
843
843
|
|
|
844
|
+
if (selectedTextNodes.length === 0) {
|
|
845
|
+
return false
|
|
846
|
+
}
|
|
847
|
+
|
|
844
848
|
if (Range.isExpanded(editor.selection)) {
|
|
845
|
-
return
|
|
849
|
+
return selectedTextNodes.every((n) => {
|
|
846
850
|
const [node] = n
|
|
847
851
|
|
|
848
852
|
return node.marks?.includes(decorator)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {BaseOperation, Editor, Node, NodeEntry} from 'slate'
|
|
2
2
|
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
3
|
-
import type {createEditorOptions} from '../../types/options'
|
|
4
3
|
import {createOperationToPatches} from '../../utils/operationToPatches'
|
|
4
|
+
import type {EditorActor} from '../editor-machine'
|
|
5
5
|
import {createWithEventListeners} from './create-with-event-listeners'
|
|
6
6
|
import {createWithMaxBlocks} from './createWithMaxBlocks'
|
|
7
7
|
import {createWithObjectKeys} from './createWithObjectKeys'
|
|
@@ -26,9 +26,14 @@ const originalFnMap = new WeakMap<
|
|
|
26
26
|
OriginalEditorFunctions
|
|
27
27
|
>()
|
|
28
28
|
|
|
29
|
+
type PluginsOptions = {
|
|
30
|
+
editorActor: EditorActor
|
|
31
|
+
subscriptions: Array<() => () => void>
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
export const withPlugins = <T extends Editor>(
|
|
30
35
|
editor: T,
|
|
31
|
-
options:
|
|
36
|
+
options: PluginsOptions,
|
|
32
37
|
): PortableTextSlateEditor => {
|
|
33
38
|
const e = editor as T & PortableTextSlateEditor
|
|
34
39
|
const {editorActor} = options
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,10 @@ export {
|
|
|
5
5
|
createMarkdownBehaviors,
|
|
6
6
|
type MarkdownBehaviorsConfig,
|
|
7
7
|
} from './editor/behavior/behavior.markdown'
|
|
8
|
+
export {
|
|
9
|
+
createLinkBehaviors,
|
|
10
|
+
type LinkBehaviorsConfig,
|
|
11
|
+
} from './editor/behavior/behavior.links'
|
|
8
12
|
export {
|
|
9
13
|
defineBehavior,
|
|
10
14
|
type Behavior,
|
|
@@ -45,4 +49,4 @@ export {
|
|
|
45
49
|
type EditorEvent,
|
|
46
50
|
} from './editor/use-editor'
|
|
47
51
|
export * from './types/editor'
|
|
48
|
-
export
|
|
52
|
+
export type {HotkeyOptions} from './types/options'
|
package/src/types/options.ts
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import type {BaseSyntheticEvent} from 'react'
|
|
2
|
-
import type {EditorActor} from '../editor/editor-machine'
|
|
3
2
|
import type {PortableTextEditor} from '../editor/PortableTextEditor'
|
|
4
3
|
|
|
5
|
-
/**
|
|
6
|
-
* @internal
|
|
7
|
-
*/
|
|
8
|
-
export type createEditorOptions = {
|
|
9
|
-
editorActor: EditorActor
|
|
10
|
-
subscriptions: Array<() => () => void>
|
|
11
|
-
}
|
|
12
|
-
|
|
13
4
|
/**
|
|
14
5
|
* @beta
|
|
15
6
|
*/
|
|
@@ -2,9 +2,9 @@ import type {PortableTextTextBlock} from '@sanity/types'
|
|
|
2
2
|
import {createEditor, type Descendant} from 'slate'
|
|
3
3
|
import {beforeEach, describe, expect, it} from 'vitest'
|
|
4
4
|
import {createActor} from 'xstate'
|
|
5
|
-
import {editorMachine} from '../..'
|
|
6
5
|
import {schemaType} from '../../editor/__tests__/PortableTextEditorTester'
|
|
7
6
|
import {coreBehaviors} from '../../editor/behavior/behavior.core'
|
|
7
|
+
import {editorMachine} from '../../editor/editor-machine'
|
|
8
8
|
import {defaultKeyGenerator} from '../../editor/key-generator'
|
|
9
9
|
import {withPlugins} from '../../editor/plugins/with-plugins'
|
|
10
10
|
import {getPortableTextMemberSchemaTypes} from '../getPortableTextMemberSchemaTypes'
|
|
@@ -2,9 +2,9 @@ import type {Patch} from '@portabletext/patches'
|
|
|
2
2
|
import {createEditor, type Descendant} from 'slate'
|
|
3
3
|
import {beforeEach, describe, expect, it} from 'vitest'
|
|
4
4
|
import {createActor} from 'xstate'
|
|
5
|
-
import {editorMachine} from '../..'
|
|
6
5
|
import {schemaType} from '../../editor/__tests__/PortableTextEditorTester'
|
|
7
6
|
import {coreBehaviors} from '../../editor/behavior/behavior.core'
|
|
7
|
+
import {editorMachine} from '../../editor/editor-machine'
|
|
8
8
|
import {defaultKeyGenerator} from '../../editor/key-generator'
|
|
9
9
|
import {withPlugins} from '../../editor/plugins/with-plugins'
|
|
10
10
|
import {createApplyPatch} from '../applyPatch'
|