@portabletext/editor 1.49.0 → 1.49.2

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.
Files changed (41) hide show
  1. package/lib/_chunks-cjs/editor-provider.cjs +22 -11
  2. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
  3. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +2 -1
  4. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  5. package/lib/_chunks-cjs/util.slice-blocks.cjs +26 -8
  6. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  7. package/lib/_chunks-es/editor-provider.js +22 -11
  8. package/lib/_chunks-es/editor-provider.js.map +1 -1
  9. package/lib/_chunks-es/util.merge-text-blocks.js +2 -1
  10. package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
  11. package/lib/_chunks-es/util.slice-blocks.js +26 -8
  12. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  13. package/lib/index.cjs +155 -158
  14. package/lib/index.cjs.map +1 -1
  15. package/lib/index.js +160 -163
  16. package/lib/index.js.map +1 -1
  17. package/package.json +6 -6
  18. package/src/behaviors/behavior.abstract.split.ts +2 -2
  19. package/src/converters/converter.portable-text.ts +1 -0
  20. package/src/converters/converter.text-html.ts +1 -0
  21. package/src/converters/converter.text-plain.ts +1 -0
  22. package/src/editor/Editable.tsx +20 -48
  23. package/src/editor/__tests__/PortableTextEditor.test.tsx +3 -3
  24. package/src/editor/__tests__/RangeDecorations.test.tsx +2 -2
  25. package/src/editor/components/render-block-object.tsx +0 -1
  26. package/src/editor/components/render-element.tsx +3 -3
  27. package/src/editor/components/render-inline-object.tsx +9 -12
  28. package/src/editor/components/render-leaf.tsx +64 -0
  29. package/src/editor/components/render-span.tsx +260 -0
  30. package/src/editor/components/render-text-block.tsx +0 -1
  31. package/src/editor/components/render-text.tsx +18 -0
  32. package/src/internal-utils/parse-blocks.test.ts +20 -20
  33. package/src/internal-utils/parse-blocks.ts +57 -20
  34. package/src/operations/behavior.operation.annotation.add.ts +1 -1
  35. package/src/operations/behavior.operation.block.set.ts +1 -1
  36. package/src/operations/behavior.operation.block.unset.ts +2 -2
  37. package/src/operations/behavior.operation.insert-inline-object.ts +1 -1
  38. package/src/operations/behavior.operation.insert.block.ts +1 -1
  39. package/src/selectors/selector.get-trimmed-selection.test.ts +1 -0
  40. package/src/utils/util.merge-text-blocks.ts +1 -1
  41. package/src/editor/components/Leaf.tsx +0 -336
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.49.0",
3
+ "version": "1.49.2",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -79,15 +79,15 @@
79
79
  "slate-react": "0.114.2",
80
80
  "use-effect-event": "^1.0.2",
81
81
  "xstate": "^5.19.2",
82
- "@portabletext/block-tools": "1.1.23",
82
+ "@portabletext/block-tools": "1.1.24",
83
83
  "@portabletext/patches": "1.1.3"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@portabletext/toolkit": "^2.0.17",
87
87
  "@sanity/diff-match-patch": "^3.2.0",
88
88
  "@sanity/pkg-utils": "^7.2.2",
89
- "@sanity/schema": "^3.87.1",
90
- "@sanity/types": "^3.87.1",
89
+ "@sanity/schema": "^3.88.0",
90
+ "@sanity/types": "^3.88.0",
91
91
  "@testing-library/jest-dom": "^6.6.3",
92
92
  "@testing-library/react": "^16.3.0",
93
93
  "@types/debug": "^4.1.12",
@@ -114,8 +114,8 @@
114
114
  "racejar": "1.2.4"
115
115
  },
116
116
  "peerDependencies": {
117
- "@sanity/schema": "^3.87.1",
118
- "@sanity/types": "^3.87.1",
117
+ "@sanity/schema": "^3.88.0",
118
+ "@sanity/types": "^3.88.0",
119
119
  "react": "^16.9 || ^17 || ^18 || ^19",
120
120
  "rxjs": "^7.8.2"
121
121
  },
@@ -49,7 +49,7 @@ export const abstractSplitBehaviors = [
49
49
  blocks: [focusTextBlock.node],
50
50
  }).at(0),
51
51
  context: snapshot.context,
52
- options: {refreshKeys: true},
52
+ options: {refreshKeys: true, validateFields: true},
53
53
  })
54
54
 
55
55
  if (!newTextBlock || !isTextBlock(snapshot.context, newTextBlock)) {
@@ -84,7 +84,7 @@ export const abstractSplitBehaviors = [
84
84
  children: [],
85
85
  },
86
86
  context: snapshot.context,
87
- options: {refreshKeys: true},
87
+ options: {refreshKeys: true, validateFields: true},
88
88
  })
89
89
 
90
90
  if (!newTextBlock) {
@@ -62,6 +62,7 @@ export const converterPortableText = defineConverter({
62
62
  * dropped portable text as is.
63
63
  */
64
64
  refreshKeys: !snapshot.beta.hasTag?.('dragging internally'),
65
+ validateFields: false,
65
66
  },
66
67
  })
67
68
  return parsedBlock ? [parsedBlock] : []
@@ -70,6 +70,7 @@ export function createConverterTextHtml(
70
70
  block,
71
71
  options: {
72
72
  refreshKeys: false,
73
+ validateFields: true,
73
74
  },
74
75
  })
75
76
  return parsedBlock ? [parsedBlock] : []
@@ -93,6 +93,7 @@ export function createConverterTextPlain(
93
93
  block,
94
94
  options: {
95
95
  refreshKeys: false,
96
+ validateFields: true,
96
97
  },
97
98
  })
98
99
  return parsedBlock ? [parsedBlock] : []
@@ -10,7 +10,6 @@ import {
10
10
  useRef,
11
11
  useState,
12
12
  type ClipboardEvent,
13
- type CSSProperties,
14
13
  type FocusEventHandler,
15
14
  type KeyboardEvent,
16
15
  type MutableRefObject,
@@ -53,8 +52,9 @@ import type {
53
52
  import type {HotkeyOptions} from '../types/options'
54
53
  import {isSelectionCollapsed} from '../utils'
55
54
  import {getSelectionEndPoint} from '../utils/util.get-selection-end-point'
56
- import {Leaf} from './components/Leaf'
57
55
  import {RenderElement} from './components/render-element'
56
+ import {RenderLeaf} from './components/render-leaf'
57
+ import {RenderText, type RenderTextProps} from './components/render-text'
58
58
  import {EditorActorContext} from './editor-actor-context'
59
59
  import {getEditorSnapshot} from './editor-selector'
60
60
  import {usePortableTextEditor} from './hooks/usePortableTextEditor'
@@ -67,14 +67,6 @@ import {
67
67
 
68
68
  const debug = debugWithName('component:Editable')
69
69
 
70
- const PLACEHOLDER_STYLE: CSSProperties = {
71
- position: 'absolute',
72
- userSelect: 'none',
73
- pointerEvents: 'none',
74
- left: 0,
75
- right: 0,
76
- }
77
-
78
70
  /**
79
71
  * @public
80
72
  */
@@ -245,47 +237,20 @@ export const PortableTextEditable = forwardRef<
245
237
 
246
238
  const renderLeaf = useCallback(
247
239
  (
248
- lProps: RenderLeafProps & {
240
+ leafProps: RenderLeafProps & {
249
241
  leaf: Text & {placeholder?: boolean; rangeDecoration?: RangeDecoration}
250
242
  },
251
- ) => {
252
- if (lProps.leaf._type === 'span') {
253
- let rendered = (
254
- <Leaf
255
- {...lProps}
256
- editorActor={editorActor}
257
- schemaTypes={portableTextEditor.schemaTypes}
258
- renderAnnotation={renderAnnotation}
259
- renderChild={renderChild}
260
- renderDecorator={renderDecorator}
261
- readOnly={readOnly}
262
- />
263
- )
264
- if (
265
- renderPlaceholder &&
266
- lProps.leaf.placeholder &&
267
- lProps.text.text === ''
268
- ) {
269
- return (
270
- <>
271
- <span style={PLACEHOLDER_STYLE} contentEditable={false}>
272
- {renderPlaceholder()}
273
- </span>
274
- {rendered}
275
- </>
276
- )
277
- }
278
- const decoration = lProps.leaf.rangeDecoration
279
- if (decoration) {
280
- rendered = decoration.component({children: rendered})
281
- }
282
- return rendered
283
- }
284
- return lProps.children
285
- },
243
+ ) => (
244
+ <RenderLeaf
245
+ {...leafProps}
246
+ readOnly={readOnly}
247
+ renderAnnotation={renderAnnotation}
248
+ renderChild={renderChild}
249
+ renderDecorator={renderDecorator}
250
+ renderPlaceholder={renderPlaceholder}
251
+ />
252
+ ),
286
253
  [
287
- editorActor,
288
- portableTextEditor,
289
254
  readOnly,
290
255
  renderAnnotation,
291
256
  renderChild,
@@ -294,6 +259,11 @@ export const PortableTextEditable = forwardRef<
294
259
  ],
295
260
  )
296
261
 
262
+ const renderText = useCallback(
263
+ (props: RenderTextProps) => <RenderText {...props} />,
264
+ [],
265
+ )
266
+
297
267
  const restoreSelectionFromProps = useCallback(() => {
298
268
  if (propsSelection) {
299
269
  debug(`Selection from props ${JSON.stringify(propsSelection)}`)
@@ -510,6 +480,7 @@ export const PortableTextEditable = forwardRef<
510
480
  blocks: result.insert,
511
481
  options: {
512
482
  refreshKeys: true,
483
+ validateFields: true,
513
484
  },
514
485
  }),
515
486
  placement: 'auto',
@@ -1225,6 +1196,7 @@ export const PortableTextEditable = forwardRef<
1225
1196
  renderPlaceholder={undefined}
1226
1197
  renderElement={renderElement}
1227
1198
  renderLeaf={renderLeaf}
1199
+ renderText={renderText}
1228
1200
  scrollSelectionIntoView={scrollSelectionIntoViewToSlate}
1229
1201
  />
1230
1202
  )
@@ -59,6 +59,9 @@ describe('initialization', () => {
59
59
  >
60
60
  <div>
61
61
  <span
62
+ data-child-key="k1"
63
+ data-child-name="span"
64
+ data-child-type="span"
62
65
  data-slate-node="text"
63
66
  >
64
67
  <span
@@ -68,9 +71,6 @@ describe('initialization', () => {
68
71
  Jot something down here
69
72
  </span>
70
73
  <span
71
- data-child-key="k1"
72
- data-child-name="span"
73
- data-child-type="span"
74
74
  data-slate-leaf="true"
75
75
  >
76
76
  <span
@@ -125,7 +125,7 @@ describe('RangeDecorations', () => {
125
125
  )
126
126
  await waitFor(() => {
127
127
  expect([rangeDecorationIteration, 'updated-with-different']).toEqual([
128
- 3,
128
+ 2,
129
129
  'updated-with-different',
130
130
  ])
131
131
  })
@@ -152,7 +152,7 @@ describe('RangeDecorations', () => {
152
152
  )
153
153
  await waitFor(() => {
154
154
  expect([rangeDecorationIteration, 'updated-with-different']).toEqual([
155
- 4,
155
+ 3,
156
156
  'updated-with-different',
157
157
  ])
158
158
  })
@@ -53,7 +53,6 @@ export function RenderBlockObject(props: {
53
53
 
54
54
  return (
55
55
  <div
56
- key={props.element._key}
57
56
  {...props.attributes}
58
57
  className="pt-block pt-object-block"
59
58
  data-block-key={props.element._key}
@@ -40,7 +40,7 @@ export function RenderElement(props: {
40
40
  keyGenerator: () => '',
41
41
  schema,
42
42
  },
43
- options: {refreshKeys: false},
43
+ options: {refreshKeys: false, validateFields: false},
44
44
  inlineObject: {
45
45
  _key: props.element._key,
46
46
  _type: props.element._type,
@@ -79,7 +79,7 @@ export function RenderElement(props: {
79
79
  keyGenerator: () => '',
80
80
  schema,
81
81
  },
82
- options: {refreshKeys: false},
82
+ options: {refreshKeys: false, validateFields: false},
83
83
  block: props.element,
84
84
  })
85
85
 
@@ -105,7 +105,7 @@ export function RenderElement(props: {
105
105
  keyGenerator: () => '',
106
106
  schema,
107
107
  },
108
- options: {refreshKeys: false},
108
+ options: {refreshKeys: false, validateFields: false},
109
109
  blockObject: {
110
110
  _key: props.element._key,
111
111
  _type: props.element._type,
@@ -57,19 +57,16 @@ export function RenderInlineObject(props: {
57
57
  }
58
58
 
59
59
  return (
60
- <span {...props.attributes}>
60
+ <span
61
+ {...props.attributes}
62
+ draggable={!props.readOnly}
63
+ className="pt-inline-object"
64
+ data-child-key={props.inlineObject._key}
65
+ data-child-name={props.inlineObject._type}
66
+ data-child-type="object"
67
+ >
61
68
  {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
- >
69
+ <span ref={inlineObjectRef} style={{display: 'inline-block'}}>
73
70
  {props.renderChild && block && legacySchemaType ? (
74
71
  props.renderChild({
75
72
  annotations: [],
@@ -0,0 +1,64 @@
1
+ import {useSelector} from '@xstate/react'
2
+ import {useContext, type CSSProperties} from 'react'
3
+ import type {Text} from 'slate'
4
+ import type {RenderLeafProps} from 'slate-react'
5
+ import type {
6
+ RangeDecoration,
7
+ RenderAnnotationFunction,
8
+ RenderChildFunction,
9
+ RenderDecoratorFunction,
10
+ RenderPlaceholderFunction,
11
+ } from '../../types/editor'
12
+ import {EditorActorContext} from '../editor-actor-context'
13
+ import {RenderSpan} from './render-span'
14
+
15
+ const PLACEHOLDER_STYLE: CSSProperties = {
16
+ position: 'absolute',
17
+ userSelect: 'none',
18
+ pointerEvents: 'none',
19
+ left: 0,
20
+ right: 0,
21
+ }
22
+
23
+ export function RenderLeaf(
24
+ props: RenderLeafProps & {
25
+ leaf: Text & {placeholder?: boolean; rangeDecoration?: RangeDecoration}
26
+ readOnly: boolean
27
+ renderAnnotation?: RenderAnnotationFunction
28
+ renderChild?: RenderChildFunction
29
+ renderDecorator?: RenderDecoratorFunction
30
+ renderPlaceholder?: RenderPlaceholderFunction
31
+ },
32
+ ) {
33
+ const editorActor = useContext(EditorActorContext)
34
+ const schema = useSelector(editorActor, (s) => s.context.schema)
35
+
36
+ if (props.leaf._type !== schema.span.name) {
37
+ return props.children
38
+ }
39
+
40
+ let renderedSpan = <RenderSpan {...props} />
41
+
42
+ if (
43
+ props.renderPlaceholder &&
44
+ props.leaf.placeholder &&
45
+ props.text.text === ''
46
+ ) {
47
+ return (
48
+ <>
49
+ <span style={PLACEHOLDER_STYLE} contentEditable={false}>
50
+ {props.renderPlaceholder()}
51
+ </span>
52
+ {renderedSpan}
53
+ </>
54
+ )
55
+ }
56
+
57
+ const rangeDecoration = props.leaf.rangeDecoration
58
+
59
+ if (rangeDecoration) {
60
+ renderedSpan = rangeDecoration.component({children: renderedSpan})
61
+ }
62
+
63
+ return renderedSpan
64
+ }
@@ -0,0 +1,260 @@
1
+ import {useSelector} from '@xstate/react'
2
+ import {isEqual, uniq} from 'lodash'
3
+ import {
4
+ startTransition,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useRef,
10
+ useState,
11
+ type ReactElement,
12
+ } from 'react'
13
+ import {useSelected, useSlateStatic, type RenderLeafProps} from 'slate-react'
14
+ import type {
15
+ RenderAnnotationFunction,
16
+ RenderChildFunction,
17
+ RenderDecoratorFunction,
18
+ } from '../../types/editor'
19
+ import {EditorActorContext} from '../editor-actor-context'
20
+ import {usePortableTextEditor} from '../hooks/usePortableTextEditor'
21
+ import {PortableTextEditor} from '../PortableTextEditor'
22
+
23
+ export interface RenderSpanProps extends RenderLeafProps {
24
+ children: ReactElement<any>
25
+ renderAnnotation?: RenderAnnotationFunction
26
+ renderChild?: RenderChildFunction
27
+ renderDecorator?: RenderDecoratorFunction
28
+ readOnly: boolean
29
+ }
30
+
31
+ export function RenderSpan(props: RenderSpanProps) {
32
+ const slateEditor = useSlateStatic()
33
+ const editorActor = useContext(EditorActorContext)
34
+ const legacySchema = useSelector(editorActor, (s) =>
35
+ s.context.getLegacySchema(),
36
+ )
37
+ const spanRef = useRef<HTMLElement>(null)
38
+ const portableTextEditor = usePortableTextEditor()
39
+ const blockSelected = useSelected()
40
+ const [focused, setFocused] = useState(false)
41
+ const [selected, setSelected] = useState(false)
42
+
43
+ const parent = props.children.props.parent
44
+ const block = parent && slateEditor.isTextBlock(parent) ? parent : undefined
45
+
46
+ const path = useMemo(
47
+ () =>
48
+ block
49
+ ? [{_key: block._key}, 'children', {_key: props.leaf._key}]
50
+ : undefined,
51
+ [block, props.leaf._key],
52
+ )
53
+
54
+ const decoratorSchemaTypes = editorActor
55
+ .getSnapshot()
56
+ .context.schema.decorators.map((decorator) => decorator.name)
57
+
58
+ const decorators = uniq(
59
+ (props.leaf.marks ?? []).filter((mark) =>
60
+ decoratorSchemaTypes.includes(mark),
61
+ ),
62
+ )
63
+
64
+ const annotationMarkDefs = (props.leaf.marks ?? []).flatMap((mark) => {
65
+ if (decoratorSchemaTypes.includes(mark)) {
66
+ return []
67
+ }
68
+
69
+ const markDef = block?.markDefs?.find((markDef) => markDef._key === mark)
70
+
71
+ if (markDef) {
72
+ return [markDef]
73
+ }
74
+
75
+ return []
76
+ })
77
+
78
+ const shouldTrackSelectionAndFocus =
79
+ annotationMarkDefs.length > 0 && blockSelected
80
+
81
+ useEffect(() => {
82
+ if (!shouldTrackSelectionAndFocus) {
83
+ setFocused(false)
84
+ return
85
+ }
86
+
87
+ const sel = PortableTextEditor.getSelection(portableTextEditor)
88
+
89
+ if (
90
+ sel &&
91
+ isEqual(sel.focus.path, path) &&
92
+ PortableTextEditor.isCollapsedSelection(portableTextEditor)
93
+ ) {
94
+ startTransition(() => {
95
+ setFocused(true)
96
+ })
97
+ }
98
+ }, [shouldTrackSelectionAndFocus, path, portableTextEditor])
99
+
100
+ // Function to check if this leaf is currently inside the user's text selection
101
+ const setSelectedFromRange = useCallback(() => {
102
+ if (!shouldTrackSelectionAndFocus) {
103
+ return
104
+ }
105
+
106
+ const winSelection = window.getSelection()
107
+
108
+ if (!winSelection) {
109
+ setSelected(false)
110
+ return
111
+ }
112
+
113
+ if (winSelection && winSelection.rangeCount > 0) {
114
+ const range = winSelection.getRangeAt(0)
115
+
116
+ if (spanRef.current && range.intersectsNode(spanRef.current)) {
117
+ setSelected(true)
118
+ } else {
119
+ setSelected(false)
120
+ }
121
+ } else {
122
+ setSelected(false)
123
+ }
124
+ }, [shouldTrackSelectionAndFocus])
125
+
126
+ useEffect(() => {
127
+ if (!shouldTrackSelectionAndFocus) {
128
+ return undefined
129
+ }
130
+
131
+ const onBlur = editorActor.on('blurred', () => {
132
+ setFocused(false)
133
+ setSelected(false)
134
+ })
135
+
136
+ const onFocus = editorActor.on('focused', () => {
137
+ const sel = PortableTextEditor.getSelection(portableTextEditor)
138
+
139
+ if (
140
+ sel &&
141
+ isEqual(sel.focus.path, path) &&
142
+ PortableTextEditor.isCollapsedSelection(portableTextEditor)
143
+ ) {
144
+ setFocused(true)
145
+ }
146
+
147
+ setSelectedFromRange()
148
+ })
149
+
150
+ const onSelection = editorActor.on('selection', (event) => {
151
+ if (
152
+ event.selection &&
153
+ isEqual(event.selection.focus.path, path) &&
154
+ PortableTextEditor.isCollapsedSelection(portableTextEditor)
155
+ ) {
156
+ setFocused(true)
157
+ } else {
158
+ setFocused(false)
159
+ }
160
+ setSelectedFromRange()
161
+ })
162
+
163
+ return () => {
164
+ onBlur.unsubscribe()
165
+ onFocus.unsubscribe()
166
+ onSelection.unsubscribe()
167
+ }
168
+ }, [
169
+ editorActor,
170
+ path,
171
+ portableTextEditor,
172
+ setSelectedFromRange,
173
+ shouldTrackSelectionAndFocus,
174
+ ])
175
+
176
+ useEffect(() => setSelectedFromRange(), [setSelectedFromRange])
177
+
178
+ let children = props.children
179
+
180
+ /**
181
+ * Support `renderDecorator` render function for each Decorator
182
+ */
183
+ for (const mark of decorators) {
184
+ const legacyDecoratorSchemaType = legacySchema.decorators.find(
185
+ (dec) => dec.value === mark,
186
+ )
187
+
188
+ if (path && legacyDecoratorSchemaType && props.renderDecorator) {
189
+ children = props.renderDecorator({
190
+ children: children,
191
+ editorElementRef: spanRef,
192
+ focused,
193
+ path,
194
+ selected,
195
+ schemaType: legacyDecoratorSchemaType,
196
+ value: mark,
197
+ type: legacyDecoratorSchemaType,
198
+ })
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Support `renderAnnotation` render function for each Annotation
204
+ */
205
+ for (const annotationMarkDef of annotationMarkDefs) {
206
+ const legacyAnnotationSchemaType = legacySchema.annotations.find(
207
+ (t) => t.name === annotationMarkDef._type,
208
+ )
209
+ if (legacyAnnotationSchemaType) {
210
+ if (block && path && props.renderAnnotation) {
211
+ children = (
212
+ <span ref={spanRef}>
213
+ {props.renderAnnotation({
214
+ block,
215
+ children: children,
216
+ editorElementRef: spanRef,
217
+ focused,
218
+ path,
219
+ selected,
220
+ schemaType: legacyAnnotationSchemaType,
221
+ value: annotationMarkDef,
222
+ type: legacyAnnotationSchemaType,
223
+ })}
224
+ </span>
225
+ )
226
+ } else {
227
+ children = <span ref={spanRef}>{children}</span>
228
+ }
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Support `renderChild` render function for the Span itself
234
+ */
235
+ if (block && path && props.renderChild) {
236
+ const child = block.children.find(
237
+ (_child) => _child._key === props.leaf._key,
238
+ ) // Ensure object equality
239
+
240
+ if (child) {
241
+ children = props.renderChild({
242
+ annotations: annotationMarkDefs,
243
+ children: children,
244
+ editorElementRef: spanRef,
245
+ focused,
246
+ path,
247
+ schemaType: legacySchema.span,
248
+ selected,
249
+ value: child,
250
+ type: legacySchema.span,
251
+ })
252
+ }
253
+ }
254
+
255
+ return (
256
+ <span {...props.attributes} ref={spanRef}>
257
+ {children}
258
+ </span>
259
+ )
260
+ }
@@ -103,7 +103,6 @@ export function RenderTextBlock(props: {
103
103
 
104
104
  return (
105
105
  <div
106
- key={props.element._key}
107
106
  {...props.attributes}
108
107
  className={[
109
108
  'pt-block',
@@ -0,0 +1,18 @@
1
+ import type {Editable} from 'slate-react'
2
+
3
+ export type RenderTextProps = Parameters<
4
+ NonNullable<React.ComponentProps<typeof Editable>['renderText']>
5
+ >[0]
6
+
7
+ export function RenderText(props: RenderTextProps) {
8
+ return (
9
+ <span
10
+ {...props.attributes}
11
+ data-child-key={props.text._key}
12
+ data-child-name={props.text._type}
13
+ data-child-type="span"
14
+ >
15
+ {props.children}
16
+ </span>
17
+ )
18
+ }