@portabletext/editor 1.48.14 → 1.49.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/editor-provider.cjs +117 -34
- package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
- package/lib/_chunks-cjs/util.slice-blocks.cjs +2 -0
- package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
- package/lib/_chunks-es/editor-provider.js +117 -34
- package/lib/_chunks-es/editor-provider.js.map +1 -1
- package/lib/_chunks-es/util.slice-blocks.js +2 -0
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/behaviors/index.d.cts +222 -208
- package/lib/behaviors/index.d.ts +222 -208
- package/lib/index.cjs +346 -257
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +222 -216
- package/lib/index.d.ts +222 -216
- package/lib/index.js +353 -264
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.cts +222 -216
- package/lib/plugins/index.d.ts +222 -216
- package/lib/selectors/index.d.cts +222 -208
- package/lib/selectors/index.d.ts +222 -208
- package/lib/utils/index.d.cts +222 -208
- package/lib/utils/index.d.ts +222 -208
- package/package.json +1 -1
- package/src/behaviors/behavior.config.ts +7 -0
- package/src/behaviors/behavior.core.block-element.ts +108 -0
- package/src/behaviors/behavior.core.ts +6 -2
- package/src/converters/converter.portable-text.ts +4 -1
- package/src/converters/converter.text-html.ts +4 -1
- package/src/converters/converter.text-plain.ts +4 -1
- package/src/editor/Editable.tsx +2 -4
- package/src/editor/__tests__/PortableTextEditor.test.tsx +6 -0
- package/src/editor/components/Leaf.tsx +8 -1
- package/src/editor/components/render-block-object.tsx +90 -0
- package/src/editor/components/render-default-object.tsx +21 -0
- package/src/editor/components/render-element.tsx +140 -0
- package/src/editor/components/render-inline-object.tsx +93 -0
- package/src/editor/components/render-text-block.tsx +148 -0
- package/src/editor/components/use-core-block-element-behaviors.ts +39 -0
- package/src/editor/create-editor.ts +17 -5
- package/src/editor/editor-machine.ts +21 -18
- package/src/internal-utils/parse-blocks.ts +2 -2
- package/src/internal-utils/slate-utils.ts +1 -1
- package/src/priority/priority.core.ts +3 -0
- package/src/priority/priority.sort.test.ts +319 -0
- package/src/priority/priority.sort.ts +121 -0
- package/src/priority/priority.types.ts +24 -0
- package/src/editor/components/DefaultObject.tsx +0 -21
- package/src/editor/components/Element.tsx +0 -435
package/package.json
CHANGED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type {EventPositionBlock} from '../internal-utils/event-position'
|
|
2
|
+
import {corePriority} from '../priority/priority.core'
|
|
3
|
+
import {createEditorPriority} from '../priority/priority.types'
|
|
4
|
+
import * as selectors from '../selectors'
|
|
5
|
+
import {forward} from './behavior.types.action'
|
|
6
|
+
import {defineBehavior} from './behavior.types.behavior'
|
|
7
|
+
|
|
8
|
+
export function createCoreBlockElementBehaviorsConfig({
|
|
9
|
+
key,
|
|
10
|
+
onSetDragPositionBlock,
|
|
11
|
+
}: {
|
|
12
|
+
key: string
|
|
13
|
+
onSetDragPositionBlock: (
|
|
14
|
+
eventPositionBlock: EventPositionBlock | undefined,
|
|
15
|
+
) => void
|
|
16
|
+
}) {
|
|
17
|
+
return [
|
|
18
|
+
{
|
|
19
|
+
behavior: defineBehavior({
|
|
20
|
+
on: 'drag.dragover',
|
|
21
|
+
guard: ({snapshot, event}) => {
|
|
22
|
+
const dropFocusBlock = selectors.getFocusBlock({
|
|
23
|
+
...snapshot,
|
|
24
|
+
context: {
|
|
25
|
+
...snapshot.context,
|
|
26
|
+
selection: event.position.selection,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
if (!dropFocusBlock || dropFocusBlock.node._key !== key) {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const dragOrigin = snapshot.beta.internalDrag?.origin
|
|
35
|
+
|
|
36
|
+
if (!dragOrigin) {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const draggedBlocks = selectors.getSelectedBlocks({
|
|
41
|
+
...snapshot,
|
|
42
|
+
context: {
|
|
43
|
+
...snapshot.context,
|
|
44
|
+
selection: dragOrigin.selection,
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
draggedBlocks.some((draggedBlock) => draggedBlock.node._key === key)
|
|
50
|
+
) {
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const draggingEntireBlocks = selectors.isSelectingEntireBlocks({
|
|
55
|
+
...snapshot,
|
|
56
|
+
context: {
|
|
57
|
+
...snapshot.context,
|
|
58
|
+
selection: dragOrigin.selection,
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return draggingEntireBlocks
|
|
63
|
+
},
|
|
64
|
+
actions: [
|
|
65
|
+
({event}) => [
|
|
66
|
+
{
|
|
67
|
+
type: 'effect',
|
|
68
|
+
effect: () => {
|
|
69
|
+
onSetDragPositionBlock(event.position.block)
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
],
|
|
74
|
+
}),
|
|
75
|
+
priority: createEditorPriority({
|
|
76
|
+
reference: {
|
|
77
|
+
priority: corePriority,
|
|
78
|
+
importance: 'lower',
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
behavior: defineBehavior({
|
|
84
|
+
on: 'drag.*',
|
|
85
|
+
guard: ({event}) => {
|
|
86
|
+
return event.type !== 'drag.dragover'
|
|
87
|
+
},
|
|
88
|
+
actions: [
|
|
89
|
+
({event}) => [
|
|
90
|
+
{
|
|
91
|
+
type: 'effect',
|
|
92
|
+
effect: () => {
|
|
93
|
+
onSetDragPositionBlock(undefined)
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
forward(event),
|
|
97
|
+
],
|
|
98
|
+
],
|
|
99
|
+
}),
|
|
100
|
+
priority: createEditorPriority({
|
|
101
|
+
reference: {
|
|
102
|
+
priority: corePriority,
|
|
103
|
+
importance: 'lower',
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
},
|
|
107
|
+
]
|
|
108
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {corePriority} from '../priority/priority.core'
|
|
1
2
|
import {coreAnnotationBehaviors} from './behavior.core.annotations'
|
|
2
3
|
import {coreBlockObjectBehaviors} from './behavior.core.block-objects'
|
|
3
4
|
import {coreDecoratorBehaviors} from './behavior.core.decorators'
|
|
@@ -5,7 +6,7 @@ import {coreDndBehaviors} from './behavior.core.dnd'
|
|
|
5
6
|
import {coreInsertBreakBehaviors} from './behavior.core.insert-break'
|
|
6
7
|
import {coreListBehaviors} from './behavior.core.lists'
|
|
7
8
|
|
|
8
|
-
export const
|
|
9
|
+
export const coreBehaviorsConfig = [
|
|
9
10
|
coreAnnotationBehaviors.addAnnotationOnCollapsedSelection,
|
|
10
11
|
coreDecoratorBehaviors.strongShortcut,
|
|
11
12
|
coreDecoratorBehaviors.emShortcut,
|
|
@@ -28,4 +29,7 @@ export const coreBehaviors = [
|
|
|
28
29
|
coreInsertBreakBehaviors.breakingAtTheStartOfTextBlock,
|
|
29
30
|
coreInsertBreakBehaviors.breakingEntireDocument,
|
|
30
31
|
coreInsertBreakBehaviors.breakingEntireBlocks,
|
|
31
|
-
]
|
|
32
|
+
].map((behavior) => ({
|
|
33
|
+
behavior,
|
|
34
|
+
priority: corePriority,
|
|
35
|
+
}))
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -53,8 +53,8 @@ import type {
|
|
|
53
53
|
import type {HotkeyOptions} from '../types/options'
|
|
54
54
|
import {isSelectionCollapsed} from '../utils'
|
|
55
55
|
import {getSelectionEndPoint} from '../utils/util.get-selection-end-point'
|
|
56
|
-
import {Element} from './components/Element'
|
|
57
56
|
import {Leaf} from './components/Leaf'
|
|
57
|
+
import {RenderElement} from './components/render-element'
|
|
58
58
|
import {EditorActorContext} from './editor-actor-context'
|
|
59
59
|
import {getEditorSnapshot} from './editor-selector'
|
|
60
60
|
import {usePortableTextEditor} from './hooks/usePortableTextEditor'
|
|
@@ -223,19 +223,17 @@ export const PortableTextEditable = forwardRef<
|
|
|
223
223
|
|
|
224
224
|
const renderElement = useCallback(
|
|
225
225
|
(eProps: RenderElementProps) => (
|
|
226
|
-
<
|
|
226
|
+
<RenderElement
|
|
227
227
|
{...eProps}
|
|
228
228
|
readOnly={readOnly}
|
|
229
229
|
renderBlock={renderBlock}
|
|
230
230
|
renderChild={renderChild}
|
|
231
231
|
renderListItem={renderListItem}
|
|
232
232
|
renderStyle={renderStyle}
|
|
233
|
-
schemaTypes={portableTextEditor.schemaTypes}
|
|
234
233
|
spellCheck={spellCheck}
|
|
235
234
|
/>
|
|
236
235
|
),
|
|
237
236
|
[
|
|
238
|
-
portableTextEditor,
|
|
239
237
|
spellCheck,
|
|
240
238
|
readOnly,
|
|
241
239
|
renderBlock,
|
|
@@ -52,6 +52,9 @@ describe('initialization', () => {
|
|
|
52
52
|
>
|
|
53
53
|
<div
|
|
54
54
|
class="pt-block pt-text-block pt-text-block-style-normal"
|
|
55
|
+
data-block-key="k0"
|
|
56
|
+
data-block-name="myTestBlockType"
|
|
57
|
+
data-block-type="text"
|
|
55
58
|
data-slate-node="element"
|
|
56
59
|
>
|
|
57
60
|
<div>
|
|
@@ -65,6 +68,9 @@ describe('initialization', () => {
|
|
|
65
68
|
Jot something down here
|
|
66
69
|
</span>
|
|
67
70
|
<span
|
|
71
|
+
data-child-key="k1"
|
|
72
|
+
data-child-name="span"
|
|
73
|
+
data-child-type="span"
|
|
68
74
|
data-slate-leaf="true"
|
|
69
75
|
>
|
|
70
76
|
<span
|
|
@@ -318,7 +318,14 @@ export const Leaf = (props: LeafProps) => {
|
|
|
318
318
|
])
|
|
319
319
|
return useMemo(
|
|
320
320
|
() => (
|
|
321
|
-
<span
|
|
321
|
+
<span
|
|
322
|
+
key={leaf._key}
|
|
323
|
+
{...attributes}
|
|
324
|
+
ref={spanRef}
|
|
325
|
+
data-child-key={leaf._key}
|
|
326
|
+
data-child-name={leaf._type}
|
|
327
|
+
data-child-type="span"
|
|
328
|
+
>
|
|
322
329
|
{content}
|
|
323
330
|
</span>
|
|
324
331
|
),
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type {PortableTextObject} from '@sanity/types'
|
|
2
|
+
import {useSelector} from '@xstate/react'
|
|
3
|
+
import {useContext, useRef, useState, type ReactElement} from 'react'
|
|
4
|
+
import {Range, type Element as SlateElement} from 'slate'
|
|
5
|
+
import {useSelected, useSlateStatic, type RenderElementProps} from 'slate-react'
|
|
6
|
+
import type {EventPositionBlock} from '../../internal-utils/event-position'
|
|
7
|
+
import type {RenderBlockFunction} from '../../types/editor'
|
|
8
|
+
import {EditorActorContext} from '../editor-actor-context'
|
|
9
|
+
import {DropIndicator} from './drop-indicator'
|
|
10
|
+
import {RenderDefaultBlockObject} from './render-default-object'
|
|
11
|
+
import {useCoreBlockElementBehaviors} from './use-core-block-element-behaviors'
|
|
12
|
+
|
|
13
|
+
export function RenderBlockObject(props: {
|
|
14
|
+
attributes: RenderElementProps['attributes']
|
|
15
|
+
blockObject: PortableTextObject
|
|
16
|
+
children: ReactElement
|
|
17
|
+
element: SlateElement
|
|
18
|
+
readOnly: boolean
|
|
19
|
+
renderBlock?: RenderBlockFunction
|
|
20
|
+
}) {
|
|
21
|
+
const [dragPositionBlock, setDragPositionBlock] =
|
|
22
|
+
useState<EventPositionBlock>()
|
|
23
|
+
const blockObjectRef = useRef<HTMLDivElement>(null)
|
|
24
|
+
|
|
25
|
+
const slateEditor = useSlateStatic()
|
|
26
|
+
const selected = useSelected()
|
|
27
|
+
|
|
28
|
+
const editorActor = useContext(EditorActorContext)
|
|
29
|
+
|
|
30
|
+
useCoreBlockElementBehaviors({
|
|
31
|
+
key: props.element._key,
|
|
32
|
+
onSetDragPositionBlock: setDragPositionBlock,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const legacySchemaType = useSelector(editorActor, (s) =>
|
|
36
|
+
s.context
|
|
37
|
+
.getLegacySchema()
|
|
38
|
+
.blockObjects.find(
|
|
39
|
+
(blockObject) => blockObject.name === props.element._type,
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!legacySchemaType) {
|
|
44
|
+
console.error(
|
|
45
|
+
`Block object type ${props.element._type} not found in Schema`,
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const focused =
|
|
50
|
+
selected &&
|
|
51
|
+
slateEditor.selection !== null &&
|
|
52
|
+
Range.isCollapsed(slateEditor.selection)
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
key={props.element._key}
|
|
57
|
+
{...props.attributes}
|
|
58
|
+
className="pt-block pt-object-block"
|
|
59
|
+
data-block-key={props.element._key}
|
|
60
|
+
data-block-name={props.element._type}
|
|
61
|
+
data-block-type="object"
|
|
62
|
+
>
|
|
63
|
+
{dragPositionBlock === 'start' ? <DropIndicator /> : null}
|
|
64
|
+
{props.children}
|
|
65
|
+
<div
|
|
66
|
+
ref={blockObjectRef}
|
|
67
|
+
contentEditable={false}
|
|
68
|
+
draggable={!props.readOnly}
|
|
69
|
+
>
|
|
70
|
+
{props.renderBlock && legacySchemaType ? (
|
|
71
|
+
props.renderBlock({
|
|
72
|
+
children: (
|
|
73
|
+
<RenderDefaultBlockObject blockObject={props.blockObject} />
|
|
74
|
+
),
|
|
75
|
+
editorElementRef: blockObjectRef,
|
|
76
|
+
focused,
|
|
77
|
+
path: [{_key: props.element._key}],
|
|
78
|
+
schemaType: legacySchemaType,
|
|
79
|
+
selected,
|
|
80
|
+
type: legacySchemaType,
|
|
81
|
+
value: props.blockObject,
|
|
82
|
+
})
|
|
83
|
+
) : (
|
|
84
|
+
<RenderDefaultBlockObject blockObject={props.blockObject} />
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
{dragPositionBlock === 'end' ? <DropIndicator /> : null}
|
|
88
|
+
</div>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type {PortableTextChild, PortableTextObject} from '@sanity/types'
|
|
2
|
+
|
|
3
|
+
export function RenderDefaultBlockObject(props: {
|
|
4
|
+
blockObject: PortableTextObject
|
|
5
|
+
}) {
|
|
6
|
+
return (
|
|
7
|
+
<div style={{userSelect: 'none'}}>
|
|
8
|
+
[{props.blockObject._type}: {props.blockObject._key}]
|
|
9
|
+
</div>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function RenderDefaultInlineObject(props: {
|
|
14
|
+
inlineObject: PortableTextObject | PortableTextChild
|
|
15
|
+
}) {
|
|
16
|
+
return (
|
|
17
|
+
<span style={{userSelect: 'none'}}>
|
|
18
|
+
[{props.inlineObject._type}: {props.inlineObject._key}]
|
|
19
|
+
</span>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {useSelector} from '@xstate/react'
|
|
2
|
+
import {useContext, type ReactElement} from 'react'
|
|
3
|
+
import type {Element as SlateElement} from 'slate'
|
|
4
|
+
import type {RenderElementProps} from 'slate-react'
|
|
5
|
+
import {
|
|
6
|
+
parseBlockObject,
|
|
7
|
+
parseInlineObject,
|
|
8
|
+
parseTextBlock,
|
|
9
|
+
} from '../../internal-utils/parse-blocks'
|
|
10
|
+
import type {
|
|
11
|
+
RenderBlockFunction,
|
|
12
|
+
RenderChildFunction,
|
|
13
|
+
RenderListItemFunction,
|
|
14
|
+
RenderStyleFunction,
|
|
15
|
+
} from '../../types/editor'
|
|
16
|
+
import {EditorActorContext} from '../editor-actor-context'
|
|
17
|
+
import {RenderBlockObject} from './render-block-object'
|
|
18
|
+
import {RenderInlineObject} from './render-inline-object'
|
|
19
|
+
import {RenderTextBlock} from './render-text-block'
|
|
20
|
+
|
|
21
|
+
export function RenderElement(props: {
|
|
22
|
+
attributes: RenderElementProps['attributes']
|
|
23
|
+
children: ReactElement
|
|
24
|
+
element: SlateElement
|
|
25
|
+
readOnly: boolean
|
|
26
|
+
renderBlock?: RenderBlockFunction
|
|
27
|
+
renderChild?: RenderChildFunction
|
|
28
|
+
renderListItem?: RenderListItemFunction
|
|
29
|
+
renderStyle?: RenderStyleFunction
|
|
30
|
+
spellCheck?: boolean
|
|
31
|
+
}) {
|
|
32
|
+
const editorActor = useContext(EditorActorContext)
|
|
33
|
+
const schema = useSelector(editorActor, (s) => s.context.schema)
|
|
34
|
+
const isInline =
|
|
35
|
+
'__inline' in props.element && props.element.__inline === true
|
|
36
|
+
|
|
37
|
+
if (isInline) {
|
|
38
|
+
const inlineObject = parseInlineObject({
|
|
39
|
+
context: {
|
|
40
|
+
keyGenerator: () => '',
|
|
41
|
+
schema,
|
|
42
|
+
},
|
|
43
|
+
options: {refreshKeys: false},
|
|
44
|
+
inlineObject: {
|
|
45
|
+
_key: props.element._key,
|
|
46
|
+
_type: props.element._type,
|
|
47
|
+
...('value' in props.element && typeof props.element.value === 'object'
|
|
48
|
+
? props.element.value
|
|
49
|
+
: {}),
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
if (!inlineObject) {
|
|
54
|
+
console.error(
|
|
55
|
+
`Unable to find Inline Object "${props.element._type}" in Schema`,
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<RenderInlineObject
|
|
61
|
+
attributes={props.attributes}
|
|
62
|
+
element={props.element}
|
|
63
|
+
inlineObject={
|
|
64
|
+
inlineObject ?? {
|
|
65
|
+
_key: props.element._key,
|
|
66
|
+
_type: props.element._type,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
readOnly={props.readOnly}
|
|
70
|
+
renderChild={props.renderChild}
|
|
71
|
+
>
|
|
72
|
+
{props.children}
|
|
73
|
+
</RenderInlineObject>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const textBlock = parseTextBlock({
|
|
78
|
+
context: {
|
|
79
|
+
keyGenerator: () => '',
|
|
80
|
+
schema,
|
|
81
|
+
},
|
|
82
|
+
options: {refreshKeys: false},
|
|
83
|
+
block: props.element,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
if (textBlock) {
|
|
87
|
+
return (
|
|
88
|
+
<RenderTextBlock
|
|
89
|
+
attributes={props.attributes}
|
|
90
|
+
element={props.element}
|
|
91
|
+
readOnly={props.readOnly}
|
|
92
|
+
renderBlock={props.renderBlock}
|
|
93
|
+
renderListItem={props.renderListItem}
|
|
94
|
+
renderStyle={props.renderStyle}
|
|
95
|
+
spellCheck={props.spellCheck}
|
|
96
|
+
textBlock={textBlock}
|
|
97
|
+
>
|
|
98
|
+
{props.children}
|
|
99
|
+
</RenderTextBlock>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const blockObject = parseBlockObject({
|
|
104
|
+
context: {
|
|
105
|
+
keyGenerator: () => '',
|
|
106
|
+
schema,
|
|
107
|
+
},
|
|
108
|
+
options: {refreshKeys: false},
|
|
109
|
+
blockObject: {
|
|
110
|
+
_key: props.element._key,
|
|
111
|
+
_type: props.element._type,
|
|
112
|
+
...('value' in props.element && typeof props.element.value === 'object'
|
|
113
|
+
? props.element.value
|
|
114
|
+
: {}),
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
if (!blockObject) {
|
|
119
|
+
console.error(
|
|
120
|
+
`Unable to find Block Object "${props.element._type}" in Schema`,
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<RenderBlockObject
|
|
126
|
+
attributes={props.attributes}
|
|
127
|
+
blockObject={
|
|
128
|
+
blockObject ?? {
|
|
129
|
+
_key: props.element._key,
|
|
130
|
+
_type: props.element._type,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
element={props.element}
|
|
134
|
+
readOnly={props.readOnly}
|
|
135
|
+
renderBlock={props.renderBlock}
|
|
136
|
+
>
|
|
137
|
+
{props.children}
|
|
138
|
+
</RenderBlockObject>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type {PortableTextObject} from '@sanity/types'
|
|
2
|
+
import {useSelector} from '@xstate/react'
|
|
3
|
+
import {useContext, useRef, type ReactElement} from 'react'
|
|
4
|
+
import {Range, type Element as SlateElement} from 'slate'
|
|
5
|
+
import {DOMEditor} from 'slate-dom'
|
|
6
|
+
import {useSelected, useSlateStatic, type RenderElementProps} from 'slate-react'
|
|
7
|
+
import {getPointBlock} from '../../internal-utils/slate-utils'
|
|
8
|
+
import type {RenderChildFunction} from '../../types/editor'
|
|
9
|
+
import {EditorActorContext} from '../editor-actor-context'
|
|
10
|
+
import {RenderDefaultInlineObject} from './render-default-object'
|
|
11
|
+
|
|
12
|
+
export function RenderInlineObject(props: {
|
|
13
|
+
attributes: RenderElementProps['attributes']
|
|
14
|
+
children: ReactElement
|
|
15
|
+
element: SlateElement
|
|
16
|
+
inlineObject: PortableTextObject
|
|
17
|
+
readOnly: boolean
|
|
18
|
+
renderChild?: RenderChildFunction
|
|
19
|
+
}) {
|
|
20
|
+
const inlineObjectRef = useRef<HTMLElement>(null)
|
|
21
|
+
|
|
22
|
+
const slateEditor = useSlateStatic()
|
|
23
|
+
const selected = useSelected()
|
|
24
|
+
|
|
25
|
+
const editorActor = useContext(EditorActorContext)
|
|
26
|
+
const legacySchemaType = useSelector(editorActor, (s) =>
|
|
27
|
+
s.context
|
|
28
|
+
.getLegacySchema()
|
|
29
|
+
.inlineObjects.find(
|
|
30
|
+
(inlineObject) => inlineObject.name === props.element._type,
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if (!legacySchemaType) {
|
|
35
|
+
console.error(
|
|
36
|
+
`Inline object type ${props.element._type} not found in Schema`,
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const focused =
|
|
41
|
+
selected &&
|
|
42
|
+
slateEditor.selection !== null &&
|
|
43
|
+
Range.isCollapsed(slateEditor.selection)
|
|
44
|
+
const path = DOMEditor.findPath(slateEditor, props.element)
|
|
45
|
+
const [block] = getPointBlock({
|
|
46
|
+
editor: slateEditor,
|
|
47
|
+
point: {
|
|
48
|
+
path,
|
|
49
|
+
offset: 0,
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
if (!block) {
|
|
54
|
+
console.error(
|
|
55
|
+
`Unable to find parent block of inline object ${props.element._key}`,
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<span {...props.attributes}>
|
|
61
|
+
{props.children}
|
|
62
|
+
<span
|
|
63
|
+
draggable={!props.readOnly}
|
|
64
|
+
className="pt-inline-object"
|
|
65
|
+
data-testid="pt-inline-object"
|
|
66
|
+
ref={inlineObjectRef}
|
|
67
|
+
key={props.element._key}
|
|
68
|
+
style={{display: 'inline-block'}}
|
|
69
|
+
data-child-key={props.inlineObject._key}
|
|
70
|
+
data-child-name={props.inlineObject._type}
|
|
71
|
+
data-child-type="object"
|
|
72
|
+
>
|
|
73
|
+
{props.renderChild && block && legacySchemaType ? (
|
|
74
|
+
props.renderChild({
|
|
75
|
+
annotations: [],
|
|
76
|
+
children: (
|
|
77
|
+
<RenderDefaultInlineObject inlineObject={props.inlineObject} />
|
|
78
|
+
),
|
|
79
|
+
editorElementRef: inlineObjectRef,
|
|
80
|
+
selected,
|
|
81
|
+
focused,
|
|
82
|
+
path: [{_key: block._key}, 'children', {_key: props.element._key}],
|
|
83
|
+
schemaType: legacySchemaType,
|
|
84
|
+
value: props.inlineObject,
|
|
85
|
+
type: legacySchemaType,
|
|
86
|
+
})
|
|
87
|
+
) : (
|
|
88
|
+
<RenderDefaultInlineObject inlineObject={props.inlineObject} />
|
|
89
|
+
)}
|
|
90
|
+
</span>
|
|
91
|
+
</span>
|
|
92
|
+
)
|
|
93
|
+
}
|