@portabletext/editor 1.48.15 → 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 +32 -17
- 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 +32 -17
- 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/index.cjs +346 -273
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +353 -280
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/behaviors/behavior.core.block-element.ts +108 -0
- 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/internal-utils/parse-blocks.ts +2 -2
- package/src/internal-utils/slate-utils.ts +1 -1
- package/src/editor/components/DefaultObject.tsx +0 -21
- package/src/editor/components/Element.tsx +0 -461
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type {PortableTextTextBlock} 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 {
|
|
8
|
+
RenderBlockFunction,
|
|
9
|
+
RenderListItemFunction,
|
|
10
|
+
RenderStyleFunction,
|
|
11
|
+
} from '../../types/editor'
|
|
12
|
+
import {EditorActorContext} from '../editor-actor-context'
|
|
13
|
+
import {DropIndicator} from './drop-indicator'
|
|
14
|
+
import {useCoreBlockElementBehaviors} from './use-core-block-element-behaviors'
|
|
15
|
+
|
|
16
|
+
export function RenderTextBlock(props: {
|
|
17
|
+
attributes: RenderElementProps['attributes']
|
|
18
|
+
children: ReactElement
|
|
19
|
+
element: SlateElement
|
|
20
|
+
readOnly: boolean
|
|
21
|
+
renderBlock?: RenderBlockFunction
|
|
22
|
+
renderListItem?: RenderListItemFunction
|
|
23
|
+
renderStyle?: RenderStyleFunction
|
|
24
|
+
spellCheck?: boolean
|
|
25
|
+
textBlock: PortableTextTextBlock
|
|
26
|
+
}) {
|
|
27
|
+
const [dragPositionBlock, setDragPositionBlock] =
|
|
28
|
+
useState<EventPositionBlock>()
|
|
29
|
+
const blockRef = useRef<HTMLDivElement>(null)
|
|
30
|
+
|
|
31
|
+
const slateEditor = useSlateStatic()
|
|
32
|
+
const selected = useSelected()
|
|
33
|
+
|
|
34
|
+
const editorActor = useContext(EditorActorContext)
|
|
35
|
+
|
|
36
|
+
useCoreBlockElementBehaviors({
|
|
37
|
+
key: props.element._key,
|
|
38
|
+
onSetDragPositionBlock: setDragPositionBlock,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const legacySchema = useSelector(editorActor, (s) =>
|
|
42
|
+
s.context.getLegacySchema(),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
const focused =
|
|
46
|
+
selected &&
|
|
47
|
+
slateEditor.selection !== null &&
|
|
48
|
+
Range.isCollapsed(slateEditor.selection)
|
|
49
|
+
|
|
50
|
+
let children = props.children
|
|
51
|
+
|
|
52
|
+
const legacyBlockSchemaType = legacySchema.block
|
|
53
|
+
|
|
54
|
+
if (props.renderStyle && props.textBlock.style) {
|
|
55
|
+
const legacyStyleSchemaType =
|
|
56
|
+
props.textBlock.style !== undefined
|
|
57
|
+
? legacySchema.styles.find(
|
|
58
|
+
(style) => style.value === props.textBlock.style,
|
|
59
|
+
)
|
|
60
|
+
: undefined
|
|
61
|
+
|
|
62
|
+
if (legacyStyleSchemaType) {
|
|
63
|
+
children = props.renderStyle({
|
|
64
|
+
block: props.textBlock,
|
|
65
|
+
children,
|
|
66
|
+
editorElementRef: blockRef,
|
|
67
|
+
focused,
|
|
68
|
+
path: [{_key: props.textBlock._key}],
|
|
69
|
+
schemaType: legacyStyleSchemaType,
|
|
70
|
+
selected,
|
|
71
|
+
value: props.textBlock.style,
|
|
72
|
+
})
|
|
73
|
+
} else {
|
|
74
|
+
console.error(
|
|
75
|
+
`Unable to find Schema type for text block style ${props.textBlock.style}`,
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (props.renderListItem && props.textBlock.listItem) {
|
|
81
|
+
const legacyListItemSchemaType = legacySchema.lists.find(
|
|
82
|
+
(list) => list.value === props.textBlock.listItem,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if (legacyListItemSchemaType) {
|
|
86
|
+
children = props.renderListItem({
|
|
87
|
+
block: props.textBlock,
|
|
88
|
+
children,
|
|
89
|
+
editorElementRef: blockRef,
|
|
90
|
+
focused,
|
|
91
|
+
level: props.textBlock.level ?? 1,
|
|
92
|
+
path: [{_key: props.textBlock._key}],
|
|
93
|
+
selected,
|
|
94
|
+
value: props.textBlock.listItem,
|
|
95
|
+
schemaType: legacyListItemSchemaType,
|
|
96
|
+
})
|
|
97
|
+
} else {
|
|
98
|
+
console.error(
|
|
99
|
+
`Unable to find Schema type for text block list item ${props.textBlock.listItem}`,
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<div
|
|
106
|
+
key={props.element._key}
|
|
107
|
+
{...props.attributes}
|
|
108
|
+
className={[
|
|
109
|
+
'pt-block',
|
|
110
|
+
'pt-text-block',
|
|
111
|
+
...(props.textBlock.style
|
|
112
|
+
? [`pt-text-block-style-${props.textBlock.style}`]
|
|
113
|
+
: []),
|
|
114
|
+
...(props.textBlock.listItem
|
|
115
|
+
? [
|
|
116
|
+
'pt-list-item',
|
|
117
|
+
`pt-list-item-${props.textBlock.listItem}`,
|
|
118
|
+
`pt-list-item-level-${props.textBlock.level ?? 1}`,
|
|
119
|
+
]
|
|
120
|
+
: []),
|
|
121
|
+
].join(' ')}
|
|
122
|
+
spellCheck={props.spellCheck}
|
|
123
|
+
data-block-key={props.textBlock._key}
|
|
124
|
+
data-block-name={props.textBlock._type}
|
|
125
|
+
data-block-type="text"
|
|
126
|
+
>
|
|
127
|
+
{dragPositionBlock === 'start' ? <DropIndicator /> : null}
|
|
128
|
+
<div ref={blockRef}>
|
|
129
|
+
{props.renderBlock
|
|
130
|
+
? props.renderBlock({
|
|
131
|
+
children,
|
|
132
|
+
editorElementRef: blockRef,
|
|
133
|
+
focused,
|
|
134
|
+
level: props.textBlock.level,
|
|
135
|
+
listItem: props.textBlock.listItem,
|
|
136
|
+
path: [{_key: props.textBlock._key}],
|
|
137
|
+
selected,
|
|
138
|
+
schemaType: legacyBlockSchemaType,
|
|
139
|
+
style: props.textBlock.style,
|
|
140
|
+
type: legacyBlockSchemaType,
|
|
141
|
+
value: props.textBlock,
|
|
142
|
+
})
|
|
143
|
+
: props.children}
|
|
144
|
+
</div>
|
|
145
|
+
{dragPositionBlock === 'end' ? <DropIndicator /> : null}
|
|
146
|
+
</div>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {useContext, useEffect} from 'react'
|
|
2
|
+
import {createCoreBlockElementBehaviorsConfig} from '../../behaviors/behavior.core.block-element'
|
|
3
|
+
import type {EventPositionBlock} from '../../internal-utils/event-position'
|
|
4
|
+
import {EditorActorContext} from '../editor-actor-context'
|
|
5
|
+
|
|
6
|
+
export function useCoreBlockElementBehaviors({
|
|
7
|
+
key,
|
|
8
|
+
onSetDragPositionBlock,
|
|
9
|
+
}: {
|
|
10
|
+
key: string
|
|
11
|
+
onSetDragPositionBlock: (
|
|
12
|
+
eventPositionBlock: EventPositionBlock | undefined,
|
|
13
|
+
) => void
|
|
14
|
+
}) {
|
|
15
|
+
const editorActor = useContext(EditorActorContext)
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const behaviorConfigs = createCoreBlockElementBehaviorsConfig({
|
|
19
|
+
key,
|
|
20
|
+
onSetDragPositionBlock,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
for (const behaviorConfig of behaviorConfigs) {
|
|
24
|
+
editorActor.send({
|
|
25
|
+
type: 'add behavior',
|
|
26
|
+
behaviorConfig,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return () => {
|
|
31
|
+
for (const behaviorConfig of behaviorConfigs) {
|
|
32
|
+
editorActor.send({
|
|
33
|
+
type: 'remove behavior',
|
|
34
|
+
behaviorConfig,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}, [editorActor, key, onSetDragPositionBlock])
|
|
39
|
+
}
|
|
@@ -49,7 +49,7 @@ export function parseBlock({
|
|
|
49
49
|
)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function parseBlockObject({
|
|
52
|
+
export function parseBlockObject({
|
|
53
53
|
blockObject,
|
|
54
54
|
context,
|
|
55
55
|
options,
|
|
@@ -104,7 +104,7 @@ export function isTextBlock(
|
|
|
104
104
|
)
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
function parseTextBlock({
|
|
107
|
+
export function parseTextBlock({
|
|
108
108
|
block,
|
|
109
109
|
context,
|
|
110
110
|
options,
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type {PortableTextBlock, PortableTextChild} from '@sanity/types'
|
|
2
|
-
|
|
3
|
-
export function DefaultBlockObject(props: {
|
|
4
|
-
value: PortableTextBlock | PortableTextChild
|
|
5
|
-
}) {
|
|
6
|
-
return (
|
|
7
|
-
<div style={{userSelect: 'none'}}>
|
|
8
|
-
[{props.value._type}: {props.value._key}]
|
|
9
|
-
</div>
|
|
10
|
-
)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function DefaultInlineObject(props: {
|
|
14
|
-
value: PortableTextBlock | PortableTextChild
|
|
15
|
-
}) {
|
|
16
|
-
return (
|
|
17
|
-
<span style={{userSelect: 'none'}}>
|
|
18
|
-
[{props.value._type}: {props.value._key}]
|
|
19
|
-
</span>
|
|
20
|
-
)
|
|
21
|
-
}
|
|
@@ -1,461 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Path,
|
|
3
|
-
PortableTextChild,
|
|
4
|
-
PortableTextObject,
|
|
5
|
-
PortableTextTextBlock,
|
|
6
|
-
} from '@sanity/types'
|
|
7
|
-
import {
|
|
8
|
-
useContext,
|
|
9
|
-
useEffect,
|
|
10
|
-
useMemo,
|
|
11
|
-
useRef,
|
|
12
|
-
useState,
|
|
13
|
-
type FunctionComponent,
|
|
14
|
-
type JSX,
|
|
15
|
-
type ReactElement,
|
|
16
|
-
} from 'react'
|
|
17
|
-
import {Editor, Range, Element as SlateElement} from 'slate'
|
|
18
|
-
import {
|
|
19
|
-
ReactEditor,
|
|
20
|
-
useSelected,
|
|
21
|
-
useSlateStatic,
|
|
22
|
-
type RenderElementProps,
|
|
23
|
-
} from 'slate-react'
|
|
24
|
-
import {defineBehavior, forward} from '../../behaviors'
|
|
25
|
-
import {debugWithName} from '../../internal-utils/debug'
|
|
26
|
-
import type {EventPositionBlock} from '../../internal-utils/event-position'
|
|
27
|
-
import {fromSlateValue} from '../../internal-utils/values'
|
|
28
|
-
import {KEY_TO_VALUE_ELEMENT} from '../../internal-utils/weakMaps'
|
|
29
|
-
import {corePriority} from '../../priority/priority.core'
|
|
30
|
-
import {createEditorPriority} from '../../priority/priority.types'
|
|
31
|
-
import * as selectors from '../../selectors'
|
|
32
|
-
import type {
|
|
33
|
-
BlockRenderProps,
|
|
34
|
-
PortableTextMemberSchemaTypes,
|
|
35
|
-
RenderBlockFunction,
|
|
36
|
-
RenderChildFunction,
|
|
37
|
-
RenderListItemFunction,
|
|
38
|
-
RenderStyleFunction,
|
|
39
|
-
} from '../../types/editor'
|
|
40
|
-
import {EditorActorContext} from '../editor-actor-context'
|
|
41
|
-
import {DefaultBlockObject, DefaultInlineObject} from './DefaultObject'
|
|
42
|
-
import {DropIndicator} from './drop-indicator'
|
|
43
|
-
|
|
44
|
-
const debug = debugWithName('components:Element')
|
|
45
|
-
const debugRenders = false
|
|
46
|
-
const EMPTY_ANNOTATIONS: PortableTextObject[] = []
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @internal
|
|
50
|
-
*/
|
|
51
|
-
export interface ElementProps {
|
|
52
|
-
attributes: RenderElementProps['attributes']
|
|
53
|
-
children: ReactElement<any>
|
|
54
|
-
element: SlateElement
|
|
55
|
-
schemaTypes: PortableTextMemberSchemaTypes
|
|
56
|
-
readOnly: boolean
|
|
57
|
-
renderBlock?: RenderBlockFunction
|
|
58
|
-
renderChild?: RenderChildFunction
|
|
59
|
-
renderListItem?: RenderListItemFunction
|
|
60
|
-
renderStyle?: RenderStyleFunction
|
|
61
|
-
spellCheck?: boolean
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const inlineBlockStyle = {display: 'inline-block'}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Renders Portable Text block and inline object nodes in Slate
|
|
68
|
-
* @internal
|
|
69
|
-
*/
|
|
70
|
-
export const Element: FunctionComponent<ElementProps> = ({
|
|
71
|
-
attributes,
|
|
72
|
-
children,
|
|
73
|
-
element,
|
|
74
|
-
schemaTypes,
|
|
75
|
-
readOnly,
|
|
76
|
-
renderBlock,
|
|
77
|
-
renderChild,
|
|
78
|
-
renderListItem,
|
|
79
|
-
renderStyle,
|
|
80
|
-
spellCheck,
|
|
81
|
-
}) => {
|
|
82
|
-
const editorActor = useContext(EditorActorContext)
|
|
83
|
-
const slateEditor = useSlateStatic()
|
|
84
|
-
const selected = useSelected()
|
|
85
|
-
const blockRef = useRef<HTMLDivElement | null>(null)
|
|
86
|
-
const inlineBlockObjectRef = useRef(null)
|
|
87
|
-
const focused =
|
|
88
|
-
(selected &&
|
|
89
|
-
slateEditor.selection &&
|
|
90
|
-
Range.isCollapsed(slateEditor.selection)) ||
|
|
91
|
-
false
|
|
92
|
-
const [dragPositionBlock, setDragPositionBlock] =
|
|
93
|
-
useState<EventPositionBlock>()
|
|
94
|
-
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
const behavior = defineBehavior({
|
|
97
|
-
on: 'drag.dragover',
|
|
98
|
-
guard: ({snapshot, event}) => {
|
|
99
|
-
const dropFocusBlock = selectors.getFocusBlock({
|
|
100
|
-
...snapshot,
|
|
101
|
-
context: {
|
|
102
|
-
...snapshot.context,
|
|
103
|
-
selection: event.position.selection,
|
|
104
|
-
},
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
if (!dropFocusBlock || dropFocusBlock.node._key !== element._key) {
|
|
108
|
-
return false
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const dragOrigin = snapshot.beta.internalDrag?.origin
|
|
112
|
-
|
|
113
|
-
if (!dragOrigin) {
|
|
114
|
-
return false
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const draggedBlocks = selectors.getSelectedBlocks({
|
|
118
|
-
...snapshot,
|
|
119
|
-
context: {
|
|
120
|
-
...snapshot.context,
|
|
121
|
-
selection: dragOrigin.selection,
|
|
122
|
-
},
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
draggedBlocks.some(
|
|
127
|
-
(draggedBlock) => draggedBlock.node._key === element._key,
|
|
128
|
-
)
|
|
129
|
-
) {
|
|
130
|
-
return false
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const draggingEntireBlocks = selectors.isSelectingEntireBlocks({
|
|
134
|
-
...snapshot,
|
|
135
|
-
context: {
|
|
136
|
-
...snapshot.context,
|
|
137
|
-
selection: dragOrigin.selection,
|
|
138
|
-
},
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
return draggingEntireBlocks
|
|
142
|
-
},
|
|
143
|
-
actions: [
|
|
144
|
-
({event}) => [
|
|
145
|
-
{
|
|
146
|
-
type: 'effect',
|
|
147
|
-
effect: () => {
|
|
148
|
-
setDragPositionBlock(event.position.block)
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
],
|
|
152
|
-
],
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
const priority = createEditorPriority({
|
|
156
|
-
reference: {
|
|
157
|
-
priority: corePriority,
|
|
158
|
-
importance: 'lower',
|
|
159
|
-
},
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
const behaviorConfig = {
|
|
163
|
-
behavior,
|
|
164
|
-
priority,
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
editorActor.send({
|
|
168
|
-
type: 'add behavior',
|
|
169
|
-
behaviorConfig,
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
return () => {
|
|
173
|
-
editorActor.send({
|
|
174
|
-
type: 'remove behavior',
|
|
175
|
-
behaviorConfig,
|
|
176
|
-
})
|
|
177
|
-
}
|
|
178
|
-
}, [editorActor, element._key])
|
|
179
|
-
|
|
180
|
-
useEffect(() => {
|
|
181
|
-
const behavior = defineBehavior({
|
|
182
|
-
on: 'drag.*',
|
|
183
|
-
guard: ({event}) => {
|
|
184
|
-
return event.type !== 'drag.dragover'
|
|
185
|
-
},
|
|
186
|
-
actions: [
|
|
187
|
-
({event}) => [
|
|
188
|
-
{
|
|
189
|
-
type: 'effect',
|
|
190
|
-
effect: () => {
|
|
191
|
-
setDragPositionBlock(undefined)
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
forward(event),
|
|
195
|
-
],
|
|
196
|
-
],
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
const priority = createEditorPriority({
|
|
200
|
-
reference: {
|
|
201
|
-
priority: corePriority,
|
|
202
|
-
importance: 'lower',
|
|
203
|
-
},
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
const behaviorConfig = {
|
|
207
|
-
behavior,
|
|
208
|
-
priority,
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
editorActor.send({
|
|
212
|
-
type: 'add behavior',
|
|
213
|
-
behaviorConfig,
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
return () => {
|
|
217
|
-
editorActor.send({
|
|
218
|
-
type: 'remove behavior',
|
|
219
|
-
behaviorConfig,
|
|
220
|
-
})
|
|
221
|
-
}
|
|
222
|
-
}, [editorActor])
|
|
223
|
-
|
|
224
|
-
const value = useMemo(
|
|
225
|
-
() =>
|
|
226
|
-
fromSlateValue(
|
|
227
|
-
[element],
|
|
228
|
-
schemaTypes.block.name,
|
|
229
|
-
KEY_TO_VALUE_ELEMENT.get(slateEditor),
|
|
230
|
-
)[0],
|
|
231
|
-
[slateEditor, element, schemaTypes.block.name],
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
let renderedBlock = children
|
|
235
|
-
|
|
236
|
-
let className: string | undefined
|
|
237
|
-
|
|
238
|
-
const blockPath: Path = useMemo(() => [{_key: element._key}], [element])
|
|
239
|
-
|
|
240
|
-
if (typeof element._type !== 'string') {
|
|
241
|
-
throw new Error(`Expected element to have a _type property`)
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (typeof element._key !== 'string') {
|
|
245
|
-
throw new Error(`Expected element to have a _key property`)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Test for inline objects first
|
|
249
|
-
if (slateEditor.isInline(element)) {
|
|
250
|
-
const path = ReactEditor.findPath(slateEditor, element)
|
|
251
|
-
const [block] = Editor.node(slateEditor, path, {depth: 1})
|
|
252
|
-
const schemaType = schemaTypes.inlineObjects.find(
|
|
253
|
-
(_type) => _type.name === element._type,
|
|
254
|
-
)
|
|
255
|
-
if (!schemaType) {
|
|
256
|
-
throw new Error('Could not find type for inline block element')
|
|
257
|
-
}
|
|
258
|
-
if (SlateElement.isElement(block)) {
|
|
259
|
-
const elmPath: Path = [
|
|
260
|
-
{_key: block._key},
|
|
261
|
-
'children',
|
|
262
|
-
{_key: element._key},
|
|
263
|
-
]
|
|
264
|
-
if (debugRenders) {
|
|
265
|
-
debug(`Render ${element._key} (inline object)`)
|
|
266
|
-
}
|
|
267
|
-
return (
|
|
268
|
-
<span {...attributes}>
|
|
269
|
-
{/* Note that children must follow immediately or cut and selections will not work properly in Chrome. */}
|
|
270
|
-
{children}
|
|
271
|
-
<span
|
|
272
|
-
draggable={!readOnly}
|
|
273
|
-
className="pt-inline-object"
|
|
274
|
-
data-testid="pt-inline-object"
|
|
275
|
-
ref={inlineBlockObjectRef}
|
|
276
|
-
key={element._key}
|
|
277
|
-
style={inlineBlockStyle}
|
|
278
|
-
contentEditable={false}
|
|
279
|
-
>
|
|
280
|
-
{renderChild &&
|
|
281
|
-
renderChild({
|
|
282
|
-
annotations: EMPTY_ANNOTATIONS, // These inline objects currently doesn't support annotations. This is a limitation of the current PT spec/model.
|
|
283
|
-
children: <DefaultInlineObject value={value} />,
|
|
284
|
-
editorElementRef: inlineBlockObjectRef,
|
|
285
|
-
focused,
|
|
286
|
-
path: elmPath,
|
|
287
|
-
schemaType,
|
|
288
|
-
selected,
|
|
289
|
-
type: schemaType,
|
|
290
|
-
value: value as PortableTextChild,
|
|
291
|
-
})}
|
|
292
|
-
{!renderChild && <DefaultInlineObject value={value} />}
|
|
293
|
-
</span>
|
|
294
|
-
</span>
|
|
295
|
-
)
|
|
296
|
-
}
|
|
297
|
-
throw new Error('Block not found!')
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// If not inline, it's either a block (text) or a block object (non-text)
|
|
301
|
-
// NOTE: text blocks aren't draggable with DraggableBlock (yet?)
|
|
302
|
-
if (element._type === schemaTypes.block.name) {
|
|
303
|
-
className = `pt-block pt-text-block`
|
|
304
|
-
const isListItem = 'listItem' in element
|
|
305
|
-
if (debugRenders) {
|
|
306
|
-
debug(`Render ${element._key} (text block)`)
|
|
307
|
-
}
|
|
308
|
-
const style = ('style' in element && element.style) || 'normal'
|
|
309
|
-
className = `pt-block pt-text-block pt-text-block-style-${style}`
|
|
310
|
-
const blockStyleType = schemaTypes.styles.find(
|
|
311
|
-
(item) => item.value === style,
|
|
312
|
-
)
|
|
313
|
-
if (renderStyle && blockStyleType) {
|
|
314
|
-
renderedBlock = renderStyle({
|
|
315
|
-
block: element as PortableTextTextBlock,
|
|
316
|
-
children,
|
|
317
|
-
focused,
|
|
318
|
-
selected,
|
|
319
|
-
value: style,
|
|
320
|
-
path: blockPath,
|
|
321
|
-
schemaType: blockStyleType,
|
|
322
|
-
editorElementRef: blockRef,
|
|
323
|
-
})
|
|
324
|
-
}
|
|
325
|
-
let level: number | undefined
|
|
326
|
-
|
|
327
|
-
if (isListItem) {
|
|
328
|
-
if (typeof element.level === 'number') {
|
|
329
|
-
level = element.level
|
|
330
|
-
}
|
|
331
|
-
className += ` pt-list-item pt-list-item-${element.listItem} pt-list-item-level-${level || 1}`
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (slateEditor.isListBlock(value) && isListItem && element.listItem) {
|
|
335
|
-
const listType = schemaTypes.lists.find(
|
|
336
|
-
(item) => item.value === element.listItem,
|
|
337
|
-
)
|
|
338
|
-
if (renderListItem && listType) {
|
|
339
|
-
renderedBlock = renderListItem({
|
|
340
|
-
block: value,
|
|
341
|
-
children: renderedBlock,
|
|
342
|
-
focused,
|
|
343
|
-
selected,
|
|
344
|
-
value: element.listItem,
|
|
345
|
-
path: blockPath,
|
|
346
|
-
schemaType: listType,
|
|
347
|
-
level: value.level || 1,
|
|
348
|
-
editorElementRef: blockRef,
|
|
349
|
-
})
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
const renderProps: Omit<BlockRenderProps, 'type'> = Object.defineProperty(
|
|
354
|
-
{
|
|
355
|
-
children: renderedBlock,
|
|
356
|
-
editorElementRef: blockRef,
|
|
357
|
-
focused,
|
|
358
|
-
level,
|
|
359
|
-
listItem: isListItem ? element.listItem : undefined,
|
|
360
|
-
path: blockPath,
|
|
361
|
-
selected,
|
|
362
|
-
style,
|
|
363
|
-
schemaType: schemaTypes.block,
|
|
364
|
-
value,
|
|
365
|
-
},
|
|
366
|
-
'type',
|
|
367
|
-
{
|
|
368
|
-
enumerable: false,
|
|
369
|
-
get() {
|
|
370
|
-
console.warn(
|
|
371
|
-
"Property 'type' is deprecated, use 'schemaType' instead.",
|
|
372
|
-
)
|
|
373
|
-
return schemaTypes.block
|
|
374
|
-
},
|
|
375
|
-
},
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
const propsOrDefaultRendered = renderBlock
|
|
379
|
-
? renderBlock(renderProps as BlockRenderProps)
|
|
380
|
-
: children
|
|
381
|
-
|
|
382
|
-
return (
|
|
383
|
-
<div
|
|
384
|
-
key={element._key}
|
|
385
|
-
{...attributes}
|
|
386
|
-
className={className}
|
|
387
|
-
spellCheck={spellCheck}
|
|
388
|
-
>
|
|
389
|
-
{dragPositionBlock === 'start' ? <DropIndicator /> : null}
|
|
390
|
-
<div ref={blockRef}>{propsOrDefaultRendered}</div>
|
|
391
|
-
{dragPositionBlock === 'end' ? <DropIndicator /> : null}
|
|
392
|
-
</div>
|
|
393
|
-
)
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const schemaType = schemaTypes.blockObjects.find(
|
|
397
|
-
(_type) => _type.name === element._type,
|
|
398
|
-
)
|
|
399
|
-
|
|
400
|
-
if (!schemaType) {
|
|
401
|
-
throw new Error(
|
|
402
|
-
`Could not find schema type for block element of _type ${element._type}`,
|
|
403
|
-
)
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (debugRenders) {
|
|
407
|
-
debug(`Render ${element._key} (object block)`)
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
className = 'pt-block pt-object-block'
|
|
411
|
-
|
|
412
|
-
const block = fromSlateValue(
|
|
413
|
-
[element],
|
|
414
|
-
schemaTypes.block.name,
|
|
415
|
-
KEY_TO_VALUE_ELEMENT.get(slateEditor),
|
|
416
|
-
)[0]
|
|
417
|
-
|
|
418
|
-
let renderedBlockFromProps: JSX.Element | undefined
|
|
419
|
-
|
|
420
|
-
if (renderBlock) {
|
|
421
|
-
const _props: Omit<BlockRenderProps, 'type'> = Object.defineProperty(
|
|
422
|
-
{
|
|
423
|
-
children: <DefaultBlockObject value={value} />,
|
|
424
|
-
editorElementRef: blockRef,
|
|
425
|
-
focused,
|
|
426
|
-
path: blockPath,
|
|
427
|
-
schemaType,
|
|
428
|
-
selected,
|
|
429
|
-
value: block,
|
|
430
|
-
},
|
|
431
|
-
'type',
|
|
432
|
-
{
|
|
433
|
-
enumerable: false,
|
|
434
|
-
get() {
|
|
435
|
-
console.warn(
|
|
436
|
-
"Property 'type' is deprecated, use 'schemaType' instead.",
|
|
437
|
-
)
|
|
438
|
-
return schemaType
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
)
|
|
442
|
-
renderedBlockFromProps = renderBlock(_props as BlockRenderProps)
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
return (
|
|
446
|
-
<div key={element._key} {...attributes} className={className}>
|
|
447
|
-
{dragPositionBlock === 'start' ? <DropIndicator /> : null}
|
|
448
|
-
{children}
|
|
449
|
-
<div ref={blockRef} contentEditable={false} draggable={!readOnly}>
|
|
450
|
-
{renderedBlockFromProps ? (
|
|
451
|
-
renderedBlockFromProps
|
|
452
|
-
) : (
|
|
453
|
-
<DefaultBlockObject value={value} />
|
|
454
|
-
)}
|
|
455
|
-
</div>
|
|
456
|
-
{dragPositionBlock === 'end' ? <DropIndicator /> : null}
|
|
457
|
-
</div>
|
|
458
|
-
)
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
Element.displayName = 'Element'
|