@portabletext/editor 1.53.0 → 1.54.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/_chunks-cjs/selection-point.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +144 -6
- package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-selection-expanded.cjs +6 -140
- package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -1
- package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +1 -1
- package/lib/_chunks-es/selection-point.js.map +1 -1
- package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +148 -10
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
- package/lib/_chunks-es/selector.is-selection-expanded.js +6 -140
- package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -1
- package/lib/_chunks-es/util.is-equal-selection-points.js.map +1 -1
- package/lib/behaviors/index.cjs.map +1 -1
- package/lib/behaviors/index.d.cts +68 -9
- package/lib/behaviors/index.d.ts +68 -9
- package/lib/behaviors/index.js.map +1 -1
- package/lib/index.cjs +553 -313
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +69 -13
- package/lib/index.d.ts +69 -13
- package/lib/index.js +534 -294
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.cts +69 -9
- package/lib/plugins/index.d.ts +69 -9
- package/lib/selectors/index.cjs +10 -10
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +42 -27
- package/lib/selectors/index.d.ts +42 -27
- package/lib/selectors/index.js +4 -4
- package/lib/selectors/index.js.map +1 -1
- package/lib/utils/index.d.cts +27 -5
- package/lib/utils/index.d.ts +27 -5
- package/package.json +14 -14
- package/src/behaviors/behavior.abstract.annotation.ts +51 -0
- package/src/behaviors/behavior.abstract.delete.ts +55 -0
- package/src/behaviors/behavior.perform-event.ts +6 -15
- package/src/behaviors/behavior.types.action.ts +1 -1
- package/src/behaviors/behavior.types.event.ts +32 -8
- package/src/behaviors/behavior.types.guard.ts +1 -1
- package/src/editor/Editable.tsx +3 -0
- package/src/editor/PortableTextEditor.tsx +1 -6
- package/src/editor/create-editor.ts +5 -0
- package/src/{internal-utils/selection-elements.ts → editor/editor-dom.ts} +29 -21
- package/src/editor/editor-provider.tsx +1 -6
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +6 -46
- package/src/editor/plugins/createWithPatches.ts +1 -5
- package/src/editor.ts +2 -0
- package/src/index.ts +2 -0
- package/src/operations/behavior.operation.child.set.ts +103 -0
- package/src/operations/behavior.operation.child.unset.ts +89 -0
- package/src/operations/behavior.operations.ts +18 -0
- package/src/selectors/index.ts +13 -1
- package/src/selectors/selector.get-active-annotations.ts +2 -1
- package/src/selectors/selector.get-active-list-item.ts +1 -1
- package/src/selectors/selector.get-active-style.ts +1 -1
- package/src/selectors/selector.get-anchor-block.ts +3 -2
- package/src/selectors/selector.get-anchor-child.ts +2 -2
- package/src/selectors/selector.get-anchor-span.ts +2 -3
- package/src/selectors/selector.get-anchor-text-block.ts +3 -2
- package/src/selectors/selector.get-caret-word-selection.ts +1 -1
- package/src/selectors/selector.get-first-block.ts +14 -0
- package/src/selectors/selector.get-focus-block-object.ts +18 -0
- package/src/selectors/selector.get-focus-block.ts +23 -0
- package/src/selectors/selector.get-focus-child.ts +36 -0
- package/src/selectors/selector.get-focus-inline-object.ts +4 -8
- package/src/selectors/selector.get-focus-list-block.ts +18 -0
- package/src/selectors/selector.get-focus-span.ts +18 -0
- package/src/selectors/selector.get-focus-text-block.ts +18 -0
- package/src/selectors/selector.get-last-block.ts +16 -0
- package/src/selectors/selector.get-list-state.ts +2 -1
- package/src/selectors/selector.get-next-block.ts +38 -0
- package/src/selectors/selector.get-next-inline-object.ts +5 -8
- package/src/selectors/selector.get-previous-block.ts +35 -0
- package/src/selectors/selector.get-previous-inline-object.ts +5 -8
- package/src/selectors/selector.get-selected-blocks.ts +49 -0
- package/src/selectors/selector.get-selected-spans.test.ts +96 -0
- package/src/selectors/selector.get-selected-spans.ts +4 -3
- package/src/selectors/selector.get-selected-text-blocks.ts +4 -3
- package/src/selectors/selector.get-selection-end-block.ts +4 -1
- package/src/selectors/selector.get-selection-start-block.ts +4 -1
- package/src/selectors/selector.get-text-before.ts +1 -1
- package/src/selectors/selector.get-trimmed-selection.ts +1 -1
- package/src/selectors/selector.is-active-annotation.ts +1 -1
- package/src/selectors/selector.is-at-the-end-of-block.ts +3 -2
- package/src/selectors/selector.is-at-the-start-of-block.ts +3 -2
- package/src/selectors/selector.is-selecting-entire-blocks.ts +2 -1
- package/src/types/block-offset.ts +2 -2
- package/src/types/paths.ts +13 -0
- package/src/utils/util.block-offset.ts +2 -4
- package/src/utils/util.get-block-end-point.ts +3 -2
- package/src/utils/util.get-block-start-point.ts +3 -2
- package/src/selectors/selectors.ts +0 -299
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createContext,
|
|
3
|
-
startTransition,
|
|
4
|
-
useContext,
|
|
5
|
-
useEffect,
|
|
6
|
-
useState,
|
|
7
|
-
} from 'react'
|
|
8
|
-
import {debugWithName} from '../../internal-utils/debug'
|
|
1
|
+
import {startTransition, useContext, useEffect, useState} from 'react'
|
|
9
2
|
import type {EditorSelection} from '../../types/editor'
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A React context for sharing the editor selection.
|
|
14
|
-
*/
|
|
15
|
-
const PortableTextEditorSelectionContext =
|
|
16
|
-
createContext<EditorSelection | null>(null)
|
|
3
|
+
import {EditorActorContext} from '../editor-actor-context'
|
|
17
4
|
|
|
18
5
|
/**
|
|
19
6
|
* @deprecated Use `useEditorSelector` to get the current editor selection.
|
|
@@ -21,48 +8,21 @@ const PortableTextEditorSelectionContext =
|
|
|
21
8
|
* Get the current editor selection from the React context.
|
|
22
9
|
*/
|
|
23
10
|
export const usePortableTextEditorSelection = (): EditorSelection => {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
if (selection === undefined) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
`The \`usePortableTextEditorSelection\` hook must be used inside the <PortableTextEditor> component's context.`,
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
return selection
|
|
32
|
-
}
|
|
33
|
-
const debug = debugWithName('component:PortableTextEditor:SelectionProvider')
|
|
34
|
-
const debugVerbose = debug.enabled && false
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @internal
|
|
38
|
-
*/
|
|
39
|
-
export function PortableTextEditorSelectionProvider(
|
|
40
|
-
props: React.PropsWithChildren<{
|
|
41
|
-
editorActor: EditorActor
|
|
42
|
-
}>,
|
|
43
|
-
) {
|
|
11
|
+
const editorActor = useContext(EditorActorContext)
|
|
44
12
|
const [selection, setSelection] = useState<EditorSelection>(null)
|
|
45
13
|
|
|
46
|
-
// Subscribe to, and handle changes from the editor
|
|
47
14
|
useEffect(() => {
|
|
48
|
-
|
|
49
|
-
const subscription = props.editorActor.on('selection', (event) => {
|
|
15
|
+
const subscription = editorActor.on('selection', (event) => {
|
|
50
16
|
// Set the selection state in a transition, we don't need the state immediately.
|
|
51
17
|
startTransition(() => {
|
|
52
|
-
if (debugVerbose) debug('Setting selection')
|
|
53
18
|
setSelection(event.selection)
|
|
54
19
|
})
|
|
55
20
|
})
|
|
56
21
|
|
|
57
22
|
return () => {
|
|
58
|
-
debug('Unsubscribing to selection changes')
|
|
59
23
|
subscription.unsubscribe()
|
|
60
24
|
}
|
|
61
|
-
}, [
|
|
25
|
+
}, [editorActor])
|
|
62
26
|
|
|
63
|
-
return
|
|
64
|
-
<PortableTextEditorSelectionContext.Provider value={selection}>
|
|
65
|
-
{props.children}
|
|
66
|
-
</PortableTextEditorSelectionContext.Provider>
|
|
67
|
-
)
|
|
27
|
+
return selection
|
|
68
28
|
}
|
|
@@ -267,11 +267,7 @@ export function createWithPatches({
|
|
|
267
267
|
type: 'internal.patch',
|
|
268
268
|
patch: {...patch, origin: 'local'},
|
|
269
269
|
operationId: getCurrentOperationId(editor),
|
|
270
|
-
value:
|
|
271
|
-
editor.children,
|
|
272
|
-
editorActor.getSnapshot().context.schema.block.name,
|
|
273
|
-
KEY_TO_VALUE_ELEMENT.get(editor),
|
|
274
|
-
),
|
|
270
|
+
value: editor.value,
|
|
275
271
|
})
|
|
276
272
|
}
|
|
277
273
|
}
|
package/src/editor.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
import type {ActorRef, EventObject, Snapshot} from 'xstate'
|
|
7
7
|
import type {Behavior} from './behaviors/behavior.types.behavior'
|
|
8
8
|
import type {ExternalBehaviorEvent} from './behaviors/behavior.types.event'
|
|
9
|
+
import type {EditorDom} from './editor/editor-dom'
|
|
9
10
|
import type {ExternalEditorEvent} from './editor/editor-machine'
|
|
10
11
|
import type {SchemaDefinition} from './editor/editor-schema'
|
|
11
12
|
import type {EditorSnapshot} from './editor/editor-snapshot'
|
|
@@ -51,6 +52,7 @@ export type EditorEvent =
|
|
|
51
52
|
* @public
|
|
52
53
|
*/
|
|
53
54
|
export type Editor = {
|
|
55
|
+
dom: EditorDom
|
|
54
56
|
getSnapshot: () => EditorSnapshot
|
|
55
57
|
/**
|
|
56
58
|
* @beta
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export type {Patch} from '@portabletext/patches'
|
|
|
2
2
|
export type {
|
|
3
3
|
PortableTextBlock,
|
|
4
4
|
PortableTextChild,
|
|
5
|
+
PortableTextObject,
|
|
5
6
|
PortableTextSpan,
|
|
6
7
|
} from '@sanity/types'
|
|
7
8
|
export type {Editor, EditorConfig, EditorEvent} from './editor'
|
|
@@ -79,3 +80,4 @@ export type {
|
|
|
79
80
|
ValueChange,
|
|
80
81
|
} from './types/editor'
|
|
81
82
|
export type {HotkeyOptions} from './types/options'
|
|
83
|
+
export type {AnnotationPath, BlockPath, ChildPath} from './types/paths'
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {Editor, Element, Transforms} from 'slate'
|
|
2
|
+
import {toSlateRange} from '../internal-utils/ranges'
|
|
3
|
+
import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
4
|
+
|
|
5
|
+
export const childSetOperationImplementation: BehaviorOperationImplementation<
|
|
6
|
+
'child.set'
|
|
7
|
+
> = ({context, operation}) => {
|
|
8
|
+
const location = toSlateRange(
|
|
9
|
+
{
|
|
10
|
+
anchor: {path: operation.at, offset: 0},
|
|
11
|
+
focus: {path: operation.at, offset: 0},
|
|
12
|
+
},
|
|
13
|
+
operation.editor,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if (!location) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Unable to convert ${JSON.stringify(operation.at)} into a Slate Range`,
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const childEntry = Editor.node(operation.editor, location, {depth: 2})
|
|
23
|
+
const child = childEntry?.[0]
|
|
24
|
+
const childPath = childEntry?.[1]
|
|
25
|
+
|
|
26
|
+
if (!child || !childPath) {
|
|
27
|
+
throw new Error(`Unable to find child at ${JSON.stringify(operation.at)}`)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (operation.editor.isTextSpan(child)) {
|
|
31
|
+
const {_type, text, ...rest} = operation.props
|
|
32
|
+
|
|
33
|
+
Transforms.setNodes(
|
|
34
|
+
operation.editor,
|
|
35
|
+
{
|
|
36
|
+
...child,
|
|
37
|
+
...rest,
|
|
38
|
+
},
|
|
39
|
+
{at: childPath},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if (typeof text === 'string') {
|
|
43
|
+
if (child.text !== text) {
|
|
44
|
+
operation.editor.apply({
|
|
45
|
+
type: 'remove_text',
|
|
46
|
+
path: childPath,
|
|
47
|
+
offset: 0,
|
|
48
|
+
text: child.text,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
operation.editor.apply({
|
|
52
|
+
type: 'insert_text',
|
|
53
|
+
path: childPath,
|
|
54
|
+
offset: 0,
|
|
55
|
+
text,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (Element.isElement(child)) {
|
|
64
|
+
const definition = context.schema.inlineObjects.find(
|
|
65
|
+
(definition) => definition.name === child._type,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if (!definition) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Unable to find schema definition for Inline Object type ${child._type}`,
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const value =
|
|
75
|
+
'value' in child && typeof child.value === 'object' ? child.value : {}
|
|
76
|
+
const {_type, _key, ...rest} = operation.props
|
|
77
|
+
|
|
78
|
+
for (const prop in rest) {
|
|
79
|
+
if (!definition.fields.some((field) => field.name === prop)) {
|
|
80
|
+
delete rest[prop]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
Transforms.setNodes(
|
|
85
|
+
operation.editor,
|
|
86
|
+
{
|
|
87
|
+
...child,
|
|
88
|
+
_key: typeof _key === 'string' ? _key : child._key,
|
|
89
|
+
value: {
|
|
90
|
+
...value,
|
|
91
|
+
...rest,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{at: childPath},
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Unable to determine the type of child at ${JSON.stringify(operation.at)}`,
|
|
102
|
+
)
|
|
103
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {applyAll} from '@portabletext/patches'
|
|
2
|
+
import {Editor, Element, Transforms} from 'slate'
|
|
3
|
+
import {toSlateRange} from '../internal-utils/ranges'
|
|
4
|
+
import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
5
|
+
|
|
6
|
+
export const childUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
7
|
+
'child.unset'
|
|
8
|
+
> = ({context, operation}) => {
|
|
9
|
+
const location = toSlateRange(
|
|
10
|
+
{
|
|
11
|
+
anchor: {path: operation.at, offset: 0},
|
|
12
|
+
focus: {path: operation.at, offset: 0},
|
|
13
|
+
},
|
|
14
|
+
operation.editor,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if (!location) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Unable to convert ${JSON.stringify(operation.at)} into a Slate Range`,
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const childEntry = Editor.node(operation.editor, location, {depth: 2})
|
|
24
|
+
const child = childEntry?.[0]
|
|
25
|
+
const childPath = childEntry?.[1]
|
|
26
|
+
|
|
27
|
+
if (!child || !childPath) {
|
|
28
|
+
throw new Error(`Unable to find child at ${JSON.stringify(operation.at)}`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (operation.editor.isTextSpan(child)) {
|
|
32
|
+
if (operation.props.includes('text')) {
|
|
33
|
+
operation.editor.apply({
|
|
34
|
+
type: 'remove_text',
|
|
35
|
+
path: childPath,
|
|
36
|
+
offset: 0,
|
|
37
|
+
text: child.text,
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const newNode: Record<string, unknown> = {}
|
|
42
|
+
|
|
43
|
+
for (const prop of operation.props) {
|
|
44
|
+
if (prop === '_type') {
|
|
45
|
+
// It's not allowed to unset the _type of a span
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (prop === '_key') {
|
|
50
|
+
newNode._key = context.keyGenerator()
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
newNode[prop] = null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Transforms.setNodes(operation.editor, newNode, {at: childPath})
|
|
58
|
+
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (Element.isElement(child)) {
|
|
63
|
+
const value =
|
|
64
|
+
'value' in child && typeof child.value === 'object' ? child.value : {}
|
|
65
|
+
const patches = operation.props.map((prop) => ({
|
|
66
|
+
type: 'unset' as const,
|
|
67
|
+
path: [prop],
|
|
68
|
+
}))
|
|
69
|
+
const newValue = applyAll(value, patches)
|
|
70
|
+
|
|
71
|
+
Transforms.setNodes(
|
|
72
|
+
operation.editor,
|
|
73
|
+
{
|
|
74
|
+
...child,
|
|
75
|
+
_key: operation.props.includes('_key')
|
|
76
|
+
? context.keyGenerator()
|
|
77
|
+
: child._key,
|
|
78
|
+
value: newValue,
|
|
79
|
+
},
|
|
80
|
+
{at: childPath},
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
throw new Error(
|
|
87
|
+
`Unable to determine the type of child at ${JSON.stringify(operation.at)}`,
|
|
88
|
+
)
|
|
89
|
+
}
|
|
@@ -14,6 +14,8 @@ import {addAnnotationOperationImplementation} from './behavior.operation.annotat
|
|
|
14
14
|
import {removeAnnotationOperationImplementation} from './behavior.operation.annotation.remove'
|
|
15
15
|
import {blockSetOperationImplementation} from './behavior.operation.block.set'
|
|
16
16
|
import {blockUnsetOperationImplementation} from './behavior.operation.block.unset'
|
|
17
|
+
import {childSetOperationImplementation} from './behavior.operation.child.set'
|
|
18
|
+
import {childUnsetOperationImplementation} from './behavior.operation.child.unset'
|
|
17
19
|
import {decoratorAddOperationImplementation} from './behavior.operation.decorator.add'
|
|
18
20
|
import {deleteOperationImplementation} from './behavior.operation.delete'
|
|
19
21
|
import {insertInlineObjectOperationImplementation} from './behavior.operation.insert-inline-object'
|
|
@@ -58,6 +60,8 @@ const behaviorOperationImplementations: BehaviorOperationImplementations = {
|
|
|
58
60
|
'annotation.remove': removeAnnotationOperationImplementation,
|
|
59
61
|
'block.set': blockSetOperationImplementation,
|
|
60
62
|
'block.unset': blockUnsetOperationImplementation,
|
|
63
|
+
'child.set': childSetOperationImplementation,
|
|
64
|
+
'child.unset': childUnsetOperationImplementation,
|
|
61
65
|
'decorator.add': decoratorAddOperationImplementation,
|
|
62
66
|
'decorator.remove': removeDecoratorOperationImplementation,
|
|
63
67
|
'delete': deleteOperationImplementation,
|
|
@@ -110,6 +114,20 @@ export function performOperation({
|
|
|
110
114
|
})
|
|
111
115
|
break
|
|
112
116
|
}
|
|
117
|
+
case 'child.set': {
|
|
118
|
+
behaviorOperationImplementations['child.set']({
|
|
119
|
+
context,
|
|
120
|
+
operation: operation,
|
|
121
|
+
})
|
|
122
|
+
break
|
|
123
|
+
}
|
|
124
|
+
case 'child.unset': {
|
|
125
|
+
behaviorOperationImplementations['child.unset']({
|
|
126
|
+
context,
|
|
127
|
+
operation: operation,
|
|
128
|
+
})
|
|
129
|
+
break
|
|
130
|
+
}
|
|
113
131
|
case 'decorator.add': {
|
|
114
132
|
behaviorOperationImplementations['decorator.add']({
|
|
115
133
|
context,
|
package/src/selectors/index.ts
CHANGED
|
@@ -7,15 +7,28 @@ export {getAnchorSpan} from './selector.get-anchor-span'
|
|
|
7
7
|
export {getAnchorTextBlock} from './selector.get-anchor-text-block'
|
|
8
8
|
export {getBlockOffsets} from './selector.get-block-offsets'
|
|
9
9
|
export {getCaretWordSelection} from './selector.get-caret-word-selection'
|
|
10
|
+
export {getFirstBlock} from './selector.get-first-block'
|
|
11
|
+
export {getFocusBlock} from './selector.get-focus-block'
|
|
12
|
+
export {getFocusBlockObject} from './selector.get-focus-block-object'
|
|
13
|
+
export {getFocusChild} from './selector.get-focus-child'
|
|
10
14
|
export {getFocusInlineObject} from './selector.get-focus-inline-object'
|
|
15
|
+
export {getFocusListBlock} from './selector.get-focus-list-block'
|
|
16
|
+
export {getFocusSpan} from './selector.get-focus-span'
|
|
17
|
+
export {getFocusTextBlock} from './selector.get-focus-text-block'
|
|
18
|
+
export {getLastBlock} from './selector.get-last-block'
|
|
11
19
|
export {getListIndex} from './selector.get-list-state'
|
|
20
|
+
export {getNextBlock} from './selector.get-next-block'
|
|
12
21
|
export {getNextInlineObject} from './selector.get-next-inline-object'
|
|
22
|
+
export {getPreviousBlock} from './selector.get-previous-block'
|
|
13
23
|
export {getPreviousInlineObject} from './selector.get-previous-inline-object'
|
|
24
|
+
export {getSelectedBlocks} from './selector.get-selected-blocks'
|
|
14
25
|
export {getSelectedSlice} from './selector.get-selected-slice'
|
|
15
26
|
export {getSelectedSpans} from './selector.get-selected-spans'
|
|
16
27
|
export {getSelectedTextBlocks} from './selector.get-selected-text-blocks'
|
|
17
28
|
export {getSelection} from './selector.get-selection'
|
|
29
|
+
export {getSelectionEndBlock} from './selector.get-selection-end-block'
|
|
18
30
|
export {getSelectionEndPoint} from './selector.get-selection-end-point'
|
|
31
|
+
export {getSelectionStartBlock} from './selector.get-selection-start-block'
|
|
19
32
|
export {getSelectionStartPoint} from './selector.get-selection-start-point'
|
|
20
33
|
export {getSelectionText} from './selector.get-selection-text'
|
|
21
34
|
export {getBlockTextBefore} from './selector.get-text-before'
|
|
@@ -33,4 +46,3 @@ export {isPointBeforeSelection} from './selector.is-point-before-selection'
|
|
|
33
46
|
export {isSelectingEntireBlocks} from './selector.is-selecting-entire-blocks'
|
|
34
47
|
export {isSelectionCollapsed} from './selector.is-selection-collapsed'
|
|
35
48
|
export {isSelectionExpanded} from './selector.is-selection-expanded'
|
|
36
|
-
export * from './selectors'
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type {PortableTextObject} from '@sanity/types'
|
|
2
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
3
|
import {isTextBlock} from '../internal-utils/parse-blocks'
|
|
4
|
+
import {getFocusSpan} from './selector.get-focus-span'
|
|
5
|
+
import {getSelectedBlocks} from './selector.get-selected-blocks'
|
|
4
6
|
import {getSelectedSpans} from './selector.get-selected-spans'
|
|
5
7
|
import {isSelectionCollapsed} from './selector.is-selection-collapsed'
|
|
6
|
-
import {getFocusSpan, getSelectedBlocks} from './selectors'
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @public
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {PortableTextListBlock} from '@sanity/types'
|
|
2
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
3
|
import {isTextBlock} from '../internal-utils/parse-blocks'
|
|
4
|
-
import {getSelectedBlocks} from './
|
|
4
|
+
import {getSelectedBlocks} from './selector.get-selected-blocks'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @public
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {PortableTextTextBlock} from '@sanity/types'
|
|
2
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
3
|
import {isTextBlock} from '../internal-utils/parse-blocks'
|
|
4
|
-
import {getSelectedBlocks} from './
|
|
4
|
+
import {getSelectedBlocks} from './selector.get-selected-blocks'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @public
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {PortableTextBlock} from '@sanity/types'
|
|
2
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
3
|
import {getBlockKeyFromSelectionPoint} from '../selection/selection-point'
|
|
4
|
+
import type {BlockPath} from '../types/paths'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @public
|
|
7
8
|
*/
|
|
8
9
|
export const getAnchorBlock: EditorSelector<
|
|
9
|
-
{node: PortableTextBlock; path:
|
|
10
|
+
{node: PortableTextBlock; path: BlockPath} | undefined
|
|
10
11
|
> = (snapshot) => {
|
|
11
12
|
if (!snapshot.context.selection) {
|
|
12
13
|
return undefined
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {KeyedSegment} from '@portabletext/patches'
|
|
2
1
|
import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
|
|
3
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
4
3
|
import {getChildKeyFromSelectionPoint} from '../selection/selection-point'
|
|
4
|
+
import type {ChildPath} from '../types/paths'
|
|
5
5
|
import {getAnchorTextBlock} from './selector.get-anchor-text-block'
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -10,7 +10,7 @@ import {getAnchorTextBlock} from './selector.get-anchor-text-block'
|
|
|
10
10
|
export const getAnchorChild: EditorSelector<
|
|
11
11
|
| {
|
|
12
12
|
node: PortableTextObject | PortableTextSpan
|
|
13
|
-
path:
|
|
13
|
+
path: ChildPath
|
|
14
14
|
}
|
|
15
15
|
| undefined
|
|
16
16
|
> = (snapshot) => {
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import type {KeyedSegment} from '@portabletext/patches'
|
|
2
1
|
import {isPortableTextSpan, type PortableTextSpan} from '@sanity/types'
|
|
3
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import type {ChildPath} from '../types/paths'
|
|
4
4
|
import {getAnchorChild} from './selector.get-anchor-child'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @public
|
|
8
8
|
*/
|
|
9
9
|
export const getAnchorSpan: EditorSelector<
|
|
10
|
-
|
|
11
|
-
| undefined
|
|
10
|
+
{node: PortableTextSpan; path: ChildPath} | undefined
|
|
12
11
|
> = (snapshot) => {
|
|
13
12
|
const anchorChild = getAnchorChild(snapshot)
|
|
14
13
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {PortableTextTextBlock} from '@sanity/types'
|
|
2
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
3
|
import {isTextBlock} from '../internal-utils/parse-blocks'
|
|
4
|
+
import type {BlockPath} from '../types/paths'
|
|
4
5
|
import {getAnchorBlock} from './selector.get-anchor-block'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @public
|
|
8
9
|
*/
|
|
9
10
|
export const getAnchorTextBlock: EditorSelector<
|
|
10
|
-
{node: PortableTextTextBlock; path:
|
|
11
|
+
{node: PortableTextTextBlock; path: BlockPath} | undefined
|
|
11
12
|
> = (snapshot) => {
|
|
12
13
|
const anchorBlock = getAnchorBlock(snapshot)
|
|
13
14
|
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
getBlockStartPoint,
|
|
8
8
|
spanSelectionPointToBlockOffset,
|
|
9
9
|
} from '../utils'
|
|
10
|
+
import {getFocusTextBlock} from './selector.get-focus-text-block'
|
|
10
11
|
import {getNextInlineObject} from './selector.get-next-inline-object'
|
|
11
12
|
import {getPreviousInlineObject} from './selector.get-previous-inline-object'
|
|
12
13
|
import {getSelectionStartPoint} from './selector.get-selection-start-point'
|
|
13
14
|
import {getSelectionText} from './selector.get-selection-text'
|
|
14
15
|
import {isSelectionCollapsed} from './selector.is-selection-collapsed'
|
|
15
16
|
import {isSelectionExpanded} from './selector.is-selection-expanded'
|
|
16
|
-
import {getFocusTextBlock} from './selectors'
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @public
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type {PortableTextBlock} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import type {BlockPath} from '../types/paths'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export const getFirstBlock: EditorSelector<
|
|
9
|
+
{node: PortableTextBlock; path: BlockPath} | undefined
|
|
10
|
+
> = (snapshot) => {
|
|
11
|
+
const node = snapshot.context.value[0]
|
|
12
|
+
|
|
13
|
+
return node ? {node, path: [{_key: node._key}]} : undefined
|
|
14
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {PortableTextObject} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import {isTextBlock} from '../internal-utils/parse-blocks'
|
|
4
|
+
import type {BlockPath} from '../types/paths'
|
|
5
|
+
import {getFocusBlock} from './selector.get-focus-block'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export const getFocusBlockObject: EditorSelector<
|
|
11
|
+
{node: PortableTextObject; path: BlockPath} | undefined
|
|
12
|
+
> = (snapshot) => {
|
|
13
|
+
const focusBlock = getFocusBlock(snapshot)
|
|
14
|
+
|
|
15
|
+
return focusBlock && !isTextBlock(snapshot.context, focusBlock.node)
|
|
16
|
+
? {node: focusBlock.node, path: focusBlock.path}
|
|
17
|
+
: undefined
|
|
18
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type {PortableTextBlock} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import {getBlockKeyFromSelectionPoint} from '../selection/selection-point'
|
|
4
|
+
import type {BlockPath} from '../types/paths'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export const getFocusBlock: EditorSelector<
|
|
10
|
+
{node: PortableTextBlock; path: BlockPath} | undefined
|
|
11
|
+
> = (snapshot) => {
|
|
12
|
+
if (!snapshot.context.selection) {
|
|
13
|
+
return undefined
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const key = getBlockKeyFromSelectionPoint(snapshot.context.selection.focus)
|
|
17
|
+
|
|
18
|
+
const node = key
|
|
19
|
+
? snapshot.context.value.find((block) => block._key === key)
|
|
20
|
+
: undefined
|
|
21
|
+
|
|
22
|
+
return node && key ? {node, path: [{_key: key}]} : undefined
|
|
23
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import {getChildKeyFromSelectionPoint} from '../selection/selection-point'
|
|
4
|
+
import type {ChildPath} from '../types/paths'
|
|
5
|
+
import {getFocusTextBlock} from './selector.get-focus-text-block'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export const getFocusChild: EditorSelector<
|
|
11
|
+
| {
|
|
12
|
+
node: PortableTextObject | PortableTextSpan
|
|
13
|
+
path: ChildPath
|
|
14
|
+
}
|
|
15
|
+
| undefined
|
|
16
|
+
> = (snapshot) => {
|
|
17
|
+
if (!snapshot.context.selection) {
|
|
18
|
+
return undefined
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const focusBlock = getFocusTextBlock(snapshot)
|
|
22
|
+
|
|
23
|
+
if (!focusBlock) {
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const key = getChildKeyFromSelectionPoint(snapshot.context.selection.focus)
|
|
28
|
+
|
|
29
|
+
const node = key
|
|
30
|
+
? focusBlock.node.children.find((span) => span._key === key)
|
|
31
|
+
: undefined
|
|
32
|
+
|
|
33
|
+
return node && key
|
|
34
|
+
? {node, path: [...focusBlock.path, 'children', {_key: key}]}
|
|
35
|
+
: undefined
|
|
36
|
+
}
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isPortableTextSpan,
|
|
3
|
-
type KeyedSegment,
|
|
4
|
-
type PortableTextObject,
|
|
5
|
-
} from '@sanity/types'
|
|
1
|
+
import {isPortableTextSpan, type PortableTextObject} from '@sanity/types'
|
|
6
2
|
import type {EditorSelector} from '../editor/editor-selector'
|
|
7
|
-
import {
|
|
3
|
+
import type {ChildPath} from '../types/paths'
|
|
4
|
+
import {getFocusChild} from './selector.get-focus-child'
|
|
8
5
|
|
|
9
6
|
/**
|
|
10
7
|
* @public
|
|
11
8
|
*/
|
|
12
9
|
export const getFocusInlineObject: EditorSelector<
|
|
13
|
-
|
|
14
|
-
| undefined
|
|
10
|
+
{node: PortableTextObject; path: ChildPath} | undefined
|
|
15
11
|
> = (snapshot) => {
|
|
16
12
|
const focusChild = getFocusChild(snapshot)
|
|
17
13
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {PortableTextListBlock} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import {isListBlock} from '../internal-utils/parse-blocks'
|
|
4
|
+
import type {BlockPath} from '../types/paths'
|
|
5
|
+
import {getFocusTextBlock} from './selector.get-focus-text-block'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export const getFocusListBlock: EditorSelector<
|
|
11
|
+
{node: PortableTextListBlock; path: BlockPath} | undefined
|
|
12
|
+
> = (snapshot) => {
|
|
13
|
+
const focusTextBlock = getFocusTextBlock(snapshot)
|
|
14
|
+
|
|
15
|
+
return focusTextBlock && isListBlock(snapshot.context, focusTextBlock.node)
|
|
16
|
+
? {node: focusTextBlock.node, path: focusTextBlock.path}
|
|
17
|
+
: undefined
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {PortableTextSpan} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import {isSpan} from '../internal-utils/parse-blocks'
|
|
4
|
+
import type {ChildPath} from '../types/paths'
|
|
5
|
+
import {getFocusChild} from './selector.get-focus-child'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export const getFocusSpan: EditorSelector<
|
|
11
|
+
{node: PortableTextSpan; path: ChildPath} | undefined
|
|
12
|
+
> = (snapshot) => {
|
|
13
|
+
const focusChild = getFocusChild(snapshot)
|
|
14
|
+
|
|
15
|
+
return focusChild && isSpan(snapshot.context, focusChild.node)
|
|
16
|
+
? {node: focusChild.node, path: focusChild.path}
|
|
17
|
+
: undefined
|
|
18
|
+
}
|