@portabletext/editor 1.0.19 → 1.1.1

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 (76) hide show
  1. package/lib/index.d.mts +142 -67
  2. package/lib/index.d.ts +142 -67
  3. package/lib/index.esm.js +1130 -371
  4. package/lib/index.esm.js.map +1 -1
  5. package/lib/index.js +1130 -371
  6. package/lib/index.js.map +1 -1
  7. package/lib/index.mjs +1130 -371
  8. package/lib/index.mjs.map +1 -1
  9. package/package.json +4 -18
  10. package/src/editor/Editable.tsx +128 -55
  11. package/src/editor/PortableTextEditor.tsx +66 -32
  12. package/src/editor/__tests__/PortableTextEditor.test.tsx +44 -18
  13. package/src/editor/__tests__/PortableTextEditorTester.tsx +50 -38
  14. package/src/editor/__tests__/RangeDecorations.test.tsx +4 -6
  15. package/src/editor/__tests__/handleClick.test.tsx +28 -9
  16. package/src/editor/__tests__/insert-block.test.tsx +24 -8
  17. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +31 -63
  18. package/src/editor/__tests__/utils.ts +10 -4
  19. package/src/editor/components/DraggableBlock.tsx +36 -13
  20. package/src/editor/components/Element.tsx +73 -33
  21. package/src/editor/components/Leaf.tsx +114 -76
  22. package/src/editor/components/SlateContainer.tsx +14 -7
  23. package/src/editor/components/Synchronizer.tsx +8 -5
  24. package/src/editor/hooks/usePortableTextEditor.ts +3 -3
  25. package/src/editor/hooks/usePortableTextEditorSelection.tsx +10 -4
  26. package/src/editor/hooks/useSyncValue.test.tsx +9 -4
  27. package/src/editor/hooks/useSyncValue.ts +198 -133
  28. package/src/editor/nodes/DefaultAnnotation.tsx +6 -4
  29. package/src/editor/nodes/DefaultObject.tsx +1 -1
  30. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +23 -8
  31. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +26 -9
  32. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +15 -5
  33. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +60 -19
  34. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +5 -3
  35. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +4 -2
  36. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +61 -19
  37. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +6 -3
  38. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +30 -13
  39. package/src/editor/plugins/createWithEditableAPI.ts +361 -131
  40. package/src/editor/plugins/createWithHotKeys.ts +46 -130
  41. package/src/editor/plugins/createWithInsertBreak.ts +167 -28
  42. package/src/editor/plugins/createWithInsertData.ts +66 -30
  43. package/src/editor/plugins/createWithMaxBlocks.ts +6 -3
  44. package/src/editor/plugins/createWithObjectKeys.ts +7 -3
  45. package/src/editor/plugins/createWithPatches.ts +66 -24
  46. package/src/editor/plugins/createWithPlaceholderBlock.ts +9 -5
  47. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +17 -7
  48. package/src/editor/plugins/createWithPortableTextLists.ts +21 -9
  49. package/src/editor/plugins/createWithPortableTextMarkModel.ts +217 -52
  50. package/src/editor/plugins/createWithPortableTextSelections.ts +11 -9
  51. package/src/editor/plugins/createWithSchemaTypes.ts +26 -10
  52. package/src/editor/plugins/createWithUndoRedo.ts +106 -27
  53. package/src/editor/plugins/createWithUtils.ts +33 -11
  54. package/src/editor/plugins/index.ts +34 -13
  55. package/src/types/editor.ts +73 -44
  56. package/src/types/options.ts +7 -5
  57. package/src/types/slate.ts +6 -6
  58. package/src/utils/__tests__/dmpToOperations.test.ts +41 -16
  59. package/src/utils/__tests__/operationToPatches.test.ts +4 -3
  60. package/src/utils/__tests__/patchToOperations.test.ts +16 -5
  61. package/src/utils/__tests__/ranges.test.ts +9 -4
  62. package/src/utils/__tests__/valueNormalization.test.tsx +12 -4
  63. package/src/utils/__tests__/values.test.ts +0 -1
  64. package/src/utils/applyPatch.ts +78 -29
  65. package/src/utils/getPortableTextMemberSchemaTypes.ts +38 -23
  66. package/src/utils/operationToPatches.ts +123 -44
  67. package/src/utils/paths.ts +26 -9
  68. package/src/utils/ranges.ts +16 -10
  69. package/src/utils/selection.ts +21 -9
  70. package/src/utils/ucs2Indices.ts +2 -2
  71. package/src/utils/validateValue.ts +118 -45
  72. package/src/utils/values.ts +38 -17
  73. package/src/utils/weakMaps.ts +20 -10
  74. package/src/utils/withChanges.ts +5 -3
  75. package/src/utils/withUndoRedo.ts +1 -1
  76. package/src/utils/withoutPatching.ts +1 -1
@@ -1,4 +1,4 @@
1
- import {type PortableTextSlateEditor} from '../../types/editor'
1
+ import type {PortableTextSlateEditor} from '../../types/editor'
2
2
  import {isChangingRemotely} from '../../utils/withChanges'
3
3
  import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
4
4
 
@@ -7,7 +7,9 @@ import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
7
7
  *
8
8
  */
9
9
  export function createWithMaxBlocks(maxBlocks: number) {
10
- return function withMaxBlocks(editor: PortableTextSlateEditor): PortableTextSlateEditor {
10
+ return function withMaxBlocks(
11
+ editor: PortableTextSlateEditor,
12
+ ): PortableTextSlateEditor {
11
13
  const {apply} = editor
12
14
  editor.apply = (operation) => {
13
15
  /**
@@ -31,7 +33,8 @@ export function createWithMaxBlocks(maxBlocks: number) {
31
33
  const rows = maxBlocks
32
34
  if (rows > 0 && editor.children.length >= rows) {
33
35
  if (
34
- (operation.type === 'insert_node' || operation.type === 'split_node') &&
36
+ (operation.type === 'insert_node' ||
37
+ operation.type === 'split_node') &&
35
38
  operation.path.length === 1
36
39
  ) {
37
40
  return
@@ -1,6 +1,8 @@
1
1
  import {Editor, Element, Node, Transforms} from 'slate'
2
-
3
- import {type PortableTextMemberSchemaTypes, type PortableTextSlateEditor} from '../../types/editor'
2
+ import type {
3
+ PortableTextMemberSchemaTypes,
4
+ PortableTextSlateEditor,
5
+ } from '../../types/editor'
4
6
  import {isChangingRemotely} from '../../utils/withChanges'
5
7
  import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
6
8
 
@@ -12,7 +14,9 @@ export function createWithObjectKeys(
12
14
  schemaTypes: PortableTextMemberSchemaTypes,
13
15
  keyGenerator: () => string,
14
16
  ) {
15
- return function withKeys(editor: PortableTextSlateEditor): PortableTextSlateEditor {
17
+ return function withKeys(
18
+ editor: PortableTextSlateEditor,
19
+ ): PortableTextSlateEditor {
16
20
  const {apply, normalizeNode} = editor
17
21
 
18
22
  // The default behavior is to always generate a new key here.
@@ -1,9 +1,8 @@
1
- /* eslint-disable max-nested-callbacks */
2
- import {insert, type Patch, setIfMissing, unset} from '@portabletext/patches'
3
- import {type Subject} from 'rxjs'
1
+ import {insert, setIfMissing, unset, type Patch} from '@portabletext/patches'
2
+ import type {Subject} from 'rxjs'
4
3
  import {
5
- type Descendant,
6
4
  Editor,
5
+ type Descendant,
7
6
  type InsertNodeOperation,
8
7
  type InsertTextOperation,
9
8
  type MergeNodeOperation,
@@ -14,19 +13,25 @@ import {
14
13
  type SetNodeOperation,
15
14
  type SplitNodeOperation,
16
15
  } from 'slate'
17
-
18
- import {
19
- type EditorChange,
20
- type PatchObservable,
21
- type PortableTextMemberSchemaTypes,
22
- type PortableTextSlateEditor,
16
+ import type {
17
+ EditorChange,
18
+ PatchObservable,
19
+ PortableTextMemberSchemaTypes,
20
+ PortableTextSlateEditor,
23
21
  } from '../../types/editor'
24
22
  import {createApplyPatch} from '../../utils/applyPatch'
25
23
  import {debugWithName} from '../../utils/debug'
26
24
  import {fromSlateValue, isEqualToEmptyEditor} from '../../utils/values'
27
- import {IS_PROCESSING_REMOTE_CHANGES, KEY_TO_VALUE_ELEMENT} from '../../utils/weakMaps'
25
+ import {
26
+ IS_PROCESSING_REMOTE_CHANGES,
27
+ KEY_TO_VALUE_ELEMENT,
28
+ } from '../../utils/weakMaps'
28
29
  import {withRemoteChanges} from '../../utils/withChanges'
29
- import {isPatching, PATCHING, withoutPatching} from '../../utils/withoutPatching'
30
+ import {
31
+ isPatching,
32
+ PATCHING,
33
+ withoutPatching,
34
+ } from '../../utils/withoutPatching'
30
35
  import {withoutSaving} from './createWithUndoRedo'
31
36
 
32
37
  const debug = debugWithName('plugin:withPatches')
@@ -117,7 +122,8 @@ export function createWithPatches({
117
122
  withoutPatching(editor, () => {
118
123
  withoutSaving(editor, () => {
119
124
  patches.forEach((patch) => {
120
- if (debug.enabled) debug(`Handling remote patch ${JSON.stringify(patch)}`)
125
+ if (debug.enabled)
126
+ debug(`Handling remote patch ${JSON.stringify(patch)}`)
121
127
  changed = applyPatch(editor, patch)
122
128
  })
123
129
  })
@@ -169,12 +175,19 @@ export function createWithPatches({
169
175
 
170
176
  if (!isPatching(editor)) {
171
177
  if (debugVerbose && debug.enabled)
172
- debug(`Editor is not producing patch for operation ${operation.type}`, operation)
178
+ debug(
179
+ `Editor is not producing patch for operation ${operation.type}`,
180
+ operation,
181
+ )
173
182
  return editor
174
183
  }
175
184
 
176
185
  // If the editor was empty and now isn't, insert the placeholder into it.
177
- if (editorWasEmpty && !editorIsEmpty && operation.type !== 'set_selection') {
186
+ if (
187
+ editorWasEmpty &&
188
+ !editorIsEmpty &&
189
+ operation.type !== 'set_selection'
190
+ ) {
178
191
  patches.push(insert(previousChildren, 'before', [0]))
179
192
  }
180
193
 
@@ -182,31 +195,51 @@ export function createWithPatches({
182
195
  case 'insert_text':
183
196
  patches = [
184
197
  ...patches,
185
- ...patchFunctions.insertTextPatch(editor, operation, previousChildren),
198
+ ...patchFunctions.insertTextPatch(
199
+ editor,
200
+ operation,
201
+ previousChildren,
202
+ ),
186
203
  ]
187
204
  break
188
205
  case 'remove_text':
189
206
  patches = [
190
207
  ...patches,
191
- ...patchFunctions.removeTextPatch(editor, operation, previousChildren),
208
+ ...patchFunctions.removeTextPatch(
209
+ editor,
210
+ operation,
211
+ previousChildren,
212
+ ),
192
213
  ]
193
214
  break
194
215
  case 'remove_node':
195
216
  patches = [
196
217
  ...patches,
197
- ...patchFunctions.removeNodePatch(editor, operation, previousChildren),
218
+ ...patchFunctions.removeNodePatch(
219
+ editor,
220
+ operation,
221
+ previousChildren,
222
+ ),
198
223
  ]
199
224
  break
200
225
  case 'split_node':
201
226
  patches = [
202
227
  ...patches,
203
- ...patchFunctions.splitNodePatch(editor, operation, previousChildren),
228
+ ...patchFunctions.splitNodePatch(
229
+ editor,
230
+ operation,
231
+ previousChildren,
232
+ ),
204
233
  ]
205
234
  break
206
235
  case 'insert_node':
207
236
  patches = [
208
237
  ...patches,
209
- ...patchFunctions.insertNodePatch(editor, operation, previousChildren),
238
+ ...patchFunctions.insertNodePatch(
239
+ editor,
240
+ operation,
241
+ previousChildren,
242
+ ),
210
243
  ]
211
244
  break
212
245
  case 'set_node':
@@ -218,16 +251,23 @@ export function createWithPatches({
218
251
  case 'merge_node':
219
252
  patches = [
220
253
  ...patches,
221
- ...patchFunctions.mergeNodePatch(editor, operation, previousChildren),
254
+ ...patchFunctions.mergeNodePatch(
255
+ editor,
256
+ operation,
257
+ previousChildren,
258
+ ),
222
259
  ]
223
260
  break
224
261
  case 'move_node':
225
262
  patches = [
226
263
  ...patches,
227
- ...patchFunctions.moveNodePatch(editor, operation, previousChildren),
264
+ ...patchFunctions.moveNodePatch(
265
+ editor,
266
+ operation,
267
+ previousChildren,
268
+ ),
228
269
  ]
229
270
  break
230
- case 'set_selection':
231
271
  default:
232
272
  // Do nothing
233
273
  }
@@ -236,7 +276,9 @@ export function createWithPatches({
236
276
  if (
237
277
  !editorWasEmpty &&
238
278
  editorIsEmpty &&
239
- ['merge_node', 'set_node', 'remove_text', 'remove_node'].includes(operation.type)
279
+ ['merge_node', 'set_node', 'remove_text', 'remove_node'].includes(
280
+ operation.type,
281
+ )
240
282
  ) {
241
283
  patches = [...patches, unset([])]
242
284
  change$.next({
@@ -1,7 +1,6 @@
1
1
  import {Editor, Path} from 'slate'
2
-
3
- import {type PortableTextSlateEditor} from '../../types/editor'
4
- import {type SlateTextBlock, type VoidElement} from '../../types/slate'
2
+ import type {PortableTextSlateEditor} from '../../types/editor'
3
+ import type {SlateTextBlock, VoidElement} from '../../types/slate'
5
4
  import {debugWithName} from '../../utils/debug'
6
5
  import {isChangingRemotely} from '../../utils/withChanges'
7
6
  import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
@@ -15,7 +14,9 @@ const debug = debugWithName('plugin:withPlaceholderBlock')
15
14
  export function createWithPlaceholderBlock(): (
16
15
  editor: PortableTextSlateEditor,
17
16
  ) => PortableTextSlateEditor {
18
- return function withPlaceholderBlock(editor: PortableTextSlateEditor): PortableTextSlateEditor {
17
+ return function withPlaceholderBlock(
18
+ editor: PortableTextSlateEditor,
19
+ ): PortableTextSlateEditor {
19
20
  const {apply} = editor
20
21
 
21
22
  editor.apply = (op) => {
@@ -45,7 +46,10 @@ export function createWithPlaceholderBlock(): (
45
46
  // Is removing the first block which is a void (not a text block), add a new empty text block in it, if there is no other element in the next path
46
47
  if (!editor.children[nextPath[0]]) {
47
48
  debug('Adding placeholder block')
48
- Editor.insertNode(editor, editor.pteCreateEmptyBlock())
49
+ Editor.insertNode(
50
+ editor,
51
+ editor.pteCreateTextBlock({decorators: []}),
52
+ )
49
53
  }
50
54
  }
51
55
  }
@@ -1,6 +1,8 @@
1
- import {Editor, type Node, Path, Text as SlateText, Transforms} from 'slate'
2
-
3
- import {type PortableTextMemberSchemaTypes, type PortableTextSlateEditor} from '../../types/editor'
1
+ import {Editor, Path, Text as SlateText, Transforms, type Node} from 'slate'
2
+ import type {
3
+ PortableTextMemberSchemaTypes,
4
+ PortableTextSlateEditor,
5
+ } from '../../types/editor'
4
6
  import {debugWithName} from '../../utils/debug'
5
7
 
6
8
  const debug = debugWithName('plugin:withPortableTextBlockStyle')
@@ -30,7 +32,11 @@ export function createWithPortableTextBlockStyle(
30
32
  const [child] = Editor.node(editor, [op.path[0] + 1, 0])
31
33
  if (SlateText.isText(child) && child.text === '') {
32
34
  debug(`Normalizing split node to ${defaultStyle} style`, op)
33
- Transforms.setNodes(editor, {style: defaultStyle}, {at: [op.path[0] + 1], voids: false})
35
+ Transforms.setNodes(
36
+ editor,
37
+ {style: defaultStyle},
38
+ {at: [op.path[0] + 1], voids: false},
39
+ )
34
40
  break
35
41
  }
36
42
  }
@@ -65,9 +71,13 @@ export function createWithPortableTextBlockStyle(
65
71
  selectedBlocks.forEach(([node, path]) => {
66
72
  if (editor.isTextBlock(node) && node.style === blockStyle) {
67
73
  debug(`Unsetting block style '${blockStyle}'`)
68
- Transforms.setNodes(editor, {...node, style: defaultStyle} as Partial<Node>, {
69
- at: path,
70
- })
74
+ Transforms.setNodes(
75
+ editor,
76
+ {...node, style: defaultStyle} as Partial<Node>,
77
+ {
78
+ at: path,
79
+ },
80
+ )
71
81
  } else {
72
82
  if (blockStyle) {
73
83
  debug(`Setting style '${blockStyle}'`)
@@ -1,13 +1,19 @@
1
- import {Editor, Element, type Node, Text, Transforms} from 'slate'
2
-
3
- import {type PortableTextMemberSchemaTypes, type PortableTextSlateEditor} from '../../types/editor'
1
+ import {Editor, Element, Text, Transforms, type Node} from 'slate'
2
+ import type {
3
+ PortableTextMemberSchemaTypes,
4
+ PortableTextSlateEditor,
5
+ } from '../../types/editor'
4
6
  import {debugWithName} from '../../utils/debug'
5
7
 
6
8
  const debug = debugWithName('plugin:withPortableTextLists')
7
9
  const MAX_LIST_LEVEL = 10
8
10
 
9
- export function createWithPortableTextLists(types: PortableTextMemberSchemaTypes) {
10
- return function withPortableTextLists(editor: PortableTextSlateEditor): PortableTextSlateEditor {
11
+ export function createWithPortableTextLists(
12
+ types: PortableTextMemberSchemaTypes,
13
+ ) {
14
+ return function withPortableTextLists(
15
+ editor: PortableTextSlateEditor,
16
+ ): PortableTextSlateEditor {
11
17
  editor.pteToggleListItem = (listItemStyle: string) => {
12
18
  const isActive = editor.pteHasListStyle(listItemStyle)
13
19
  if (isActive) {
@@ -26,12 +32,12 @@ export function createWithPortableTextLists(types: PortableTextMemberSchemaTypes
26
32
  const selectedBlocks = [
27
33
  ...Editor.nodes(editor, {
28
34
  at: editor.selection,
29
- match: (node) => Element.isElement(node) && node._type === types.block.name,
35
+ match: (node) =>
36
+ Element.isElement(node) && node._type === types.block.name,
30
37
  }),
31
38
  ]
32
39
  selectedBlocks.forEach(([node, path]) => {
33
40
  if (editor.isListBlock(node)) {
34
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
35
41
  const {listItem, level, ...rest} = node
36
42
  const newNode = {
37
43
  ...rest,
@@ -121,10 +127,16 @@ export function createWithPortableTextLists(types: PortableTextMemberSchemaTypes
121
127
  let level = node.level || 1
122
128
  if (reverse) {
123
129
  level--
124
- debug('Decrementing list level', Math.min(MAX_LIST_LEVEL, Math.max(1, level)))
130
+ debug(
131
+ 'Decrementing list level',
132
+ Math.min(MAX_LIST_LEVEL, Math.max(1, level)),
133
+ )
125
134
  } else {
126
135
  level++
127
- debug('Incrementing list level', Math.min(MAX_LIST_LEVEL, Math.max(1, level)))
136
+ debug(
137
+ 'Incrementing list level',
138
+ Math.min(MAX_LIST_LEVEL, Math.max(1, level)),
139
+ )
128
140
  }
129
141
  Transforms.setNodes(
130
142
  editor,