@portabletext/editor 1.49.1 → 1.49.3

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 (95) hide show
  1. package/lib/_chunks-cjs/selector.get-text-before.cjs +2 -2
  2. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  3. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +40 -230
  4. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  5. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs +201 -0
  6. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -0
  7. package/lib/_chunks-cjs/use-editor.cjs +28 -0
  8. package/lib/_chunks-cjs/use-editor.cjs.map +1 -0
  9. package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs +79 -0
  10. package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs.map +1 -0
  11. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs +34 -0
  12. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +1 -0
  13. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +2 -1
  14. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  15. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +6 -78
  16. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
  17. package/lib/_chunks-cjs/util.slice-blocks.cjs +26 -39
  18. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  19. package/lib/_chunks-es/selector.get-text-before.js +1 -1
  20. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +13 -201
  21. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  22. package/lib/_chunks-es/selector.is-selection-expanded.js +203 -0
  23. package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -0
  24. package/lib/_chunks-es/use-editor.js +25 -0
  25. package/lib/_chunks-es/use-editor.js.map +1 -0
  26. package/lib/_chunks-es/util.child-selection-point-to-block-offset.js +80 -0
  27. package/lib/_chunks-es/util.child-selection-point-to-block-offset.js.map +1 -0
  28. package/lib/_chunks-es/util.is-equal-selection-points.js +35 -0
  29. package/lib/_chunks-es/util.is-equal-selection-points.js.map +1 -0
  30. package/lib/_chunks-es/util.merge-text-blocks.js +2 -1
  31. package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
  32. package/lib/_chunks-es/util.selection-point-to-block-offset.js +6 -77
  33. package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -1
  34. package/lib/_chunks-es/util.slice-blocks.js +26 -39
  35. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  36. package/lib/index.cjs +9004 -292
  37. package/lib/index.cjs.map +1 -1
  38. package/lib/index.d.cts +2 -2
  39. package/lib/index.d.ts +2 -2
  40. package/lib/index.js +8947 -220
  41. package/lib/index.js.map +1 -1
  42. package/lib/plugins/index.cjs +23 -23
  43. package/lib/plugins/index.cjs.map +1 -1
  44. package/lib/plugins/index.js +3 -3
  45. package/lib/plugins/index.js.map +1 -1
  46. package/lib/selectors/index.cjs +22 -22
  47. package/lib/selectors/index.cjs.map +1 -1
  48. package/lib/selectors/index.js +4 -3
  49. package/lib/selectors/index.js.map +1 -1
  50. package/lib/utils/index.cjs +10 -10
  51. package/lib/utils/index.cjs.map +1 -1
  52. package/lib/utils/index.js +6 -4
  53. package/lib/utils/index.js.map +1 -1
  54. package/package.json +14 -14
  55. package/src/behaviors/behavior.abstract.split.ts +2 -2
  56. package/src/converters/converter.portable-text.ts +1 -0
  57. package/src/converters/converter.text-html.ts +1 -0
  58. package/src/converters/converter.text-plain.ts +1 -0
  59. package/src/editor/Editable.tsx +1 -0
  60. package/src/editor/components/render-element.tsx +3 -3
  61. package/src/editor/create-editor.ts +2 -58
  62. package/src/editor/editor-context.tsx +1 -1
  63. package/src/editor/editor-provider.tsx +4 -31
  64. package/src/editor/editor-selector.ts +2 -1
  65. package/src/editor/use-editor.ts +27 -0
  66. package/src/editor-event-listener.tsx +1 -1
  67. package/src/editor.ts +57 -0
  68. package/src/index.ts +9 -9
  69. package/src/internal-utils/parse-blocks.test.ts +20 -20
  70. package/src/internal-utils/parse-blocks.ts +57 -20
  71. package/src/internal-utils/text-selection.test.ts +11 -0
  72. package/src/operations/behavior.operation.annotation.add.ts +1 -1
  73. package/src/operations/behavior.operation.block.set.ts +1 -1
  74. package/src/operations/behavior.operation.block.unset.ts +2 -2
  75. package/src/operations/behavior.operation.insert-inline-object.ts +1 -1
  76. package/src/operations/behavior.operation.insert.block.ts +1 -1
  77. package/src/plugins/plugin.behavior.tsx +1 -1
  78. package/src/plugins/plugin.decorator-shortcut.ts +2 -2
  79. package/src/plugins/plugin.editor-ref.tsx +2 -2
  80. package/src/plugins/plugin.event-listener.tsx +1 -1
  81. package/src/plugins/plugin.markdown.tsx +1 -1
  82. package/src/selectors/selector.get-trimmed-selection.test.ts +1 -0
  83. package/src/utils/util.merge-text-blocks.ts +1 -1
  84. package/lib/_chunks-cjs/editor-provider.cjs +0 -8745
  85. package/lib/_chunks-cjs/editor-provider.cjs.map +0 -1
  86. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs +0 -11
  87. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs.map +0 -1
  88. package/lib/_chunks-cjs/util.is-selection-collapsed.cjs +0 -6
  89. package/lib/_chunks-cjs/util.is-selection-collapsed.cjs.map +0 -1
  90. package/lib/_chunks-es/editor-provider.js +0 -8771
  91. package/lib/_chunks-es/editor-provider.js.map +0 -1
  92. package/lib/_chunks-es/selector.get-focus-inline-object.js +0 -13
  93. package/lib/_chunks-es/selector.get-focus-inline-object.js.map +0 -1
  94. package/lib/_chunks-es/util.is-selection-collapsed.js +0 -7
  95. package/lib/_chunks-es/util.is-selection-collapsed.js.map +0 -1
@@ -19,6 +19,7 @@ export function parseBlocks({
19
19
  blocks: unknown
20
20
  options: {
21
21
  refreshKeys: boolean
22
+ validateFields: boolean
22
23
  }
23
24
  }): Array<PortableTextBlock> {
24
25
  if (!Array.isArray(blocks)) {
@@ -41,6 +42,7 @@ export function parseBlock({
41
42
  block: unknown
42
43
  options: {
43
44
  refreshKeys: boolean
45
+ validateFields: boolean
44
46
  }
45
47
  }): PortableTextBlock | undefined {
46
48
  return (
@@ -56,7 +58,7 @@ export function parseBlockObject({
56
58
  }: {
57
59
  blockObject: unknown
58
60
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
59
- options: {refreshKeys: boolean}
61
+ options: {refreshKeys: boolean; validateFields: boolean}
60
62
  }): PortableTextObject | undefined {
61
63
  if (!isTypedObject(blockObject)) {
62
64
  return undefined
@@ -99,7 +101,7 @@ export function isTextBlock(
99
101
  parseTextBlock({
100
102
  block,
101
103
  context: {schema: context.schema, keyGenerator: () => ''},
102
- options: {refreshKeys: false},
104
+ options: {refreshKeys: false, validateFields: false},
103
105
  }) !== undefined
104
106
  )
105
107
  }
@@ -111,12 +113,28 @@ export function parseTextBlock({
111
113
  }: {
112
114
  block: unknown
113
115
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
114
- options: {refreshKeys: boolean}
116
+ options: {refreshKeys: boolean; validateFields: boolean}
115
117
  }): PortableTextTextBlock | undefined {
116
118
  if (!isTypedObject(block)) {
117
119
  return undefined
118
120
  }
119
121
 
122
+ const customFields: Record<string, unknown> = {}
123
+
124
+ for (const key of Object.keys(block)) {
125
+ if (
126
+ key !== '_type' &&
127
+ key !== '_key' &&
128
+ key !== 'children' &&
129
+ key !== 'markDefs' &&
130
+ key !== 'style' &&
131
+ key !== 'listItem' &&
132
+ key !== 'level'
133
+ ) {
134
+ customFields[key] = block[key]
135
+ }
136
+ }
137
+
120
138
  if (block._type !== context.schema.block.name) {
121
139
  return undefined
122
140
  }
@@ -195,6 +213,7 @@ export function parseTextBlock({
195
213
  },
196
214
  ],
197
215
  markDefs,
216
+ ...(options.validateFields ? {} : customFields),
198
217
  }
199
218
 
200
219
  if (
@@ -235,7 +254,7 @@ export function isSpan(
235
254
  span: child,
236
255
  markDefKeyMap: new Map(),
237
256
  context: {schema: context.schema, keyGenerator: () => ''},
238
- options: {refreshKeys: false},
257
+ options: {refreshKeys: false, validateFields: false},
239
258
  }) !== undefined
240
259
  )
241
260
  }
@@ -249,12 +268,25 @@ export function parseSpan({
249
268
  span: unknown
250
269
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
251
270
  markDefKeyMap: Map<string, string>
252
- options: {refreshKeys: boolean}
271
+ options: {refreshKeys: boolean; validateFields: boolean}
253
272
  }): PortableTextSpan | undefined {
254
273
  if (!isTypedObject(span)) {
255
274
  return undefined
256
275
  }
257
276
 
277
+ const customFields: Record<string, unknown> = {}
278
+
279
+ for (const key of Object.keys(span)) {
280
+ if (
281
+ key !== '_type' &&
282
+ key !== '_key' &&
283
+ key !== 'text' &&
284
+ key !== 'marks'
285
+ ) {
286
+ customFields[key] = span[key]
287
+ }
288
+ }
289
+
258
290
  // In reality, the span schema name is always 'span', but we only the check here anyway
259
291
  if (span._type !== context.schema.span.name || span._type !== 'span') {
260
292
  return undefined
@@ -292,6 +324,7 @@ export function parseSpan({
292
324
  : context.keyGenerator(),
293
325
  text: typeof span.text === 'string' ? span.text : '',
294
326
  marks,
327
+ ...(options.validateFields ? {} : customFields),
295
328
  }
296
329
  }
297
330
 
@@ -302,7 +335,7 @@ export function parseInlineObject({
302
335
  }: {
303
336
  inlineObject: unknown
304
337
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
305
- options: {refreshKeys: boolean}
338
+ options: {refreshKeys: boolean; validateFields: boolean}
306
339
  }): PortableTextObject | undefined {
307
340
  if (!isTypedObject(inlineObject)) {
308
341
  return undefined
@@ -333,7 +366,7 @@ export function parseAnnotation({
333
366
  }: {
334
367
  annotation: TypedObject
335
368
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
336
- options: {refreshKeys: boolean}
369
+ options: {refreshKeys: boolean; validateFields: boolean}
337
370
  }): PortableTextObject | undefined {
338
371
  if (!isTypedObject(annotation)) {
339
372
  return undefined
@@ -366,22 +399,26 @@ function parseObject({
366
399
  context: Pick<EditorContext, 'keyGenerator'> & {
367
400
  schemaType: EditorSchema['blockObjects'][0]
368
401
  }
369
- options: {refreshKeys: boolean}
402
+ options: {refreshKeys: boolean; validateFields: boolean}
370
403
  }): PortableTextObject {
404
+ const {_type, _key, ...customFields} = object
405
+
371
406
  // Validates all props on the object and only takes those that match
372
407
  // the name of a field
373
- const values = context.schemaType.fields.reduce<Record<string, unknown>>(
374
- (fieldValues, field) => {
375
- const fieldValue = object[field.name]
376
-
377
- if (fieldValue !== undefined) {
378
- fieldValues[field.name] = fieldValue
379
- }
380
-
381
- return fieldValues
382
- },
383
- {},
384
- )
408
+ const values = options.validateFields
409
+ ? context.schemaType.fields.reduce<Record<string, unknown>>(
410
+ (fieldValues, field) => {
411
+ const fieldValue = object[field.name]
412
+
413
+ if (fieldValue !== undefined) {
414
+ fieldValues[field.name] = fieldValue
415
+ }
416
+
417
+ return fieldValues
418
+ },
419
+ {},
420
+ )
421
+ : customFields
385
422
 
386
423
  return {
387
424
  _type: context.schemaType.name,
@@ -6,6 +6,17 @@ import {
6
6
  } from './text-selection'
7
7
 
8
8
  test(getTextSelection.name, () => {
9
+ const simpleBlock = {
10
+ _key: 'b1',
11
+ _type: 'block',
12
+ children: [{_key: 's1', _type: 'span', text: 'foo'}],
13
+ }
14
+
15
+ expect(getTextSelection([simpleBlock], 'foo')).toEqual({
16
+ anchor: {path: [{_key: 'b1'}, 'children', {_key: 's1'}], offset: 0},
17
+ focus: {path: [{_key: 'b1'}, 'children', {_key: 's1'}], offset: 3},
18
+ })
19
+
9
20
  const joinedBlock = {
10
21
  _key: 'b1',
11
22
  _type: 'block',
@@ -31,7 +31,7 @@ export const addAnnotationOperationImplementation: BehaviorOperationImplementati
31
31
  ...operation.annotation.value,
32
32
  },
33
33
  context,
34
- options: {refreshKeys: false},
34
+ options: {refreshKeys: false, validateFields: true},
35
35
  })
36
36
 
37
37
  if (!parsedAnnotation) {
@@ -47,7 +47,7 @@ export const blockSetOperationImplementation: BehaviorOperationImplementation<
47
47
  ...parsedBlock,
48
48
  ...filteredProps,
49
49
  },
50
- options: {refreshKeys: false},
50
+ options: {refreshKeys: false, validateFields: true},
51
51
  })
52
52
 
53
53
  if (!updatedBlock) {
@@ -46,7 +46,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
46
46
  const updatedTextBlock = parseBlock({
47
47
  context,
48
48
  block: omit(parsedBlock, propsToRemove),
49
- options: {refreshKeys: false},
49
+ options: {refreshKeys: false, validateFields: true},
50
50
  })
51
51
 
52
52
  if (!updatedTextBlock) {
@@ -76,7 +76,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
76
76
  parsedBlock,
77
77
  operation.props.filter((prop) => prop !== '_type'),
78
78
  ),
79
- options: {refreshKeys: false},
79
+ options: {refreshKeys: false, validateFields: true},
80
80
  })
81
81
 
82
82
  if (!updatedBlockObject) {
@@ -12,7 +12,7 @@ export const insertInlineObjectOperationImplementation: BehaviorOperationImpleme
12
12
  _type: operation.inlineObject.name,
13
13
  ...(operation.inlineObject.value ?? {}),
14
14
  },
15
- options: {refreshKeys: false},
15
+ options: {refreshKeys: false, validateFields: true},
16
16
  })
17
17
 
18
18
  if (!parsedInlineObject) {
@@ -19,7 +19,7 @@ export const insertBlockOperationImplementation: BehaviorOperationImplementation
19
19
  const parsedBlock = parseBlock({
20
20
  block: operation.block,
21
21
  context,
22
- options: {refreshKeys: false},
22
+ options: {refreshKeys: false, validateFields: true},
23
23
  })
24
24
 
25
25
  if (!parsedBlock) {
@@ -1,6 +1,6 @@
1
1
  import {useEffect} from 'react'
2
2
  import type {Behavior} from '../behaviors'
3
- import {useEditor} from '../editor/editor-provider'
3
+ import {useEditor} from '../editor/use-editor'
4
4
 
5
5
  /**
6
6
  * @beta
@@ -10,9 +10,9 @@ import {
10
10
  import {createDecoratorPairBehavior} from '../behaviors/behavior.decorator-pair'
11
11
  import {effect, execute, forward} from '../behaviors/behavior.types.action'
12
12
  import {defineBehavior} from '../behaviors/behavior.types.behavior'
13
- import type {Editor} from '../editor/create-editor'
14
- import {useEditor} from '../editor/editor-provider'
13
+ import type {Editor} from '../editor'
15
14
  import type {EditorSchema} from '../editor/editor-schema'
15
+ import {useEditor} from '../editor/use-editor'
16
16
  import type {BlockOffset} from '../types/block-offset'
17
17
  import * as utils from '../utils'
18
18
 
@@ -1,6 +1,6 @@
1
1
  import React from 'react'
2
- import type {Editor} from '../editor/create-editor'
3
- import {useEditor} from '../editor/editor-provider'
2
+ import type {Editor} from '../editor'
3
+ import {useEditor} from '../editor/use-editor'
4
4
 
5
5
  /**
6
6
  * @beta
@@ -1,7 +1,7 @@
1
1
  import {useEffect} from 'react'
2
2
  import {useEffectEvent} from 'use-effect-event'
3
3
  import type {EditorEmittedEvent} from '../editor/editor-machine'
4
- import {useEditor} from '../editor/editor-provider'
4
+ import {useEditor} from '../editor/use-editor'
5
5
 
6
6
  /**
7
7
  * @public
@@ -3,8 +3,8 @@ import {
3
3
  createMarkdownBehaviors,
4
4
  type MarkdownBehaviorsConfig,
5
5
  } from '../behaviors/behavior.markdown'
6
- import {useEditor} from '../editor/editor-provider'
7
6
  import type {EditorSchema} from '../editor/editor-schema'
7
+ import {useEditor} from '../editor/use-editor'
8
8
  import {DecoratorShortcutPlugin} from './plugin.decorator-shortcut'
9
9
 
10
10
  /**
@@ -34,6 +34,7 @@ function snapshot(
34
34
  block,
35
35
  options: {
36
36
  refreshKeys: false,
37
+ validateFields: false,
37
38
  },
38
39
  })
39
40
 
@@ -18,7 +18,7 @@ export function mergeTextBlocks({
18
18
  const parsedIncomingBlock = parseBlock({
19
19
  context,
20
20
  block: incomingBlock,
21
- options: {refreshKeys: true},
21
+ options: {refreshKeys: true, validateFields: true},
22
22
  })
23
23
 
24
24
  if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {