@portabletext/editor 1.0.18 → 1.1.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.
Files changed (75) hide show
  1. package/lib/index.d.mts +140 -66
  2. package/lib/index.d.ts +140 -66
  3. package/lib/index.esm.js +1164 -410
  4. package/lib/index.esm.js.map +1 -1
  5. package/lib/index.js +1164 -410
  6. package/lib/index.js.map +1 -1
  7. package/lib/index.mjs +1164 -410
  8. package/lib/index.mjs.map +1 -1
  9. package/package.json +8 -4
  10. package/src/editor/Editable.tsx +107 -36
  11. package/src/editor/PortableTextEditor.tsx +47 -12
  12. package/src/editor/__tests__/PortableTextEditor.test.tsx +42 -15
  13. package/src/editor/__tests__/PortableTextEditorTester.tsx +50 -38
  14. package/src/editor/__tests__/RangeDecorations.test.tsx +0 -1
  15. package/src/editor/__tests__/handleClick.test.tsx +28 -9
  16. package/src/editor/__tests__/insert-block.test.tsx +22 -6
  17. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +30 -62
  18. package/src/editor/__tests__/utils.ts +10 -3
  19. package/src/editor/components/DraggableBlock.tsx +36 -13
  20. package/src/editor/components/Element.tsx +59 -17
  21. package/src/editor/components/Leaf.tsx +106 -68
  22. package/src/editor/components/SlateContainer.tsx +12 -5
  23. package/src/editor/components/Synchronizer.tsx +5 -2
  24. package/src/editor/hooks/usePortableTextEditor.ts +2 -2
  25. package/src/editor/hooks/usePortableTextEditorSelection.tsx +9 -3
  26. package/src/editor/hooks/useSyncValue.test.tsx +9 -4
  27. package/src/editor/hooks/useSyncValue.ts +199 -130
  28. package/src/editor/nodes/DefaultAnnotation.tsx +6 -3
  29. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +25 -7
  30. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +26 -9
  31. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +15 -5
  32. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +60 -19
  33. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +4 -2
  34. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +4 -2
  35. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +61 -550
  36. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +6 -3
  37. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +30 -13
  38. package/src/editor/plugins/createWithEditableAPI.ts +354 -115
  39. package/src/editor/plugins/createWithHotKeys.ts +41 -121
  40. package/src/editor/plugins/createWithInsertBreak.ts +166 -27
  41. package/src/editor/plugins/createWithInsertData.ts +60 -23
  42. package/src/editor/plugins/createWithMaxBlocks.ts +5 -2
  43. package/src/editor/plugins/createWithObjectKeys.ts +7 -3
  44. package/src/editor/plugins/createWithPatches.ts +60 -16
  45. package/src/editor/plugins/createWithPlaceholderBlock.ts +7 -3
  46. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +17 -7
  47. package/src/editor/plugins/createWithPortableTextLists.ts +21 -8
  48. package/src/editor/plugins/createWithPortableTextMarkModel.ts +301 -155
  49. package/src/editor/plugins/createWithPortableTextSelections.ts +4 -2
  50. package/src/editor/plugins/createWithSchemaTypes.ts +25 -9
  51. package/src/editor/plugins/createWithUndoRedo.ts +107 -24
  52. package/src/editor/plugins/createWithUtils.ts +32 -10
  53. package/src/editor/plugins/index.ts +31 -10
  54. package/src/types/editor.ts +44 -15
  55. package/src/types/options.ts +4 -2
  56. package/src/types/slate.ts +2 -2
  57. package/src/utils/__tests__/dmpToOperations.test.ts +38 -13
  58. package/src/utils/__tests__/operationToPatches.test.ts +3 -2
  59. package/src/utils/__tests__/patchToOperations.test.ts +15 -4
  60. package/src/utils/__tests__/ranges.test.ts +8 -3
  61. package/src/utils/__tests__/valueNormalization.test.tsx +12 -4
  62. package/src/utils/__tests__/values.test.ts +0 -1
  63. package/src/utils/applyPatch.ts +71 -20
  64. package/src/utils/getPortableTextMemberSchemaTypes.ts +30 -15
  65. package/src/utils/operationToPatches.ts +126 -43
  66. package/src/utils/paths.ts +24 -7
  67. package/src/utils/ranges.ts +12 -5
  68. package/src/utils/selection.ts +19 -7
  69. package/src/utils/validateValue.ts +118 -45
  70. package/src/utils/values.ts +31 -10
  71. package/src/utils/weakMaps.ts +18 -8
  72. package/src/utils/withChanges.ts +4 -2
  73. package/src/editor/plugins/__tests__/withHotkeys.test.tsx +0 -212
  74. package/src/editor/plugins/__tests__/withInsertBreak.test.tsx +0 -220
  75. package/src/editor/plugins/__tests__/withPlaceholderBlock.test.tsx +0 -133
@@ -1,9 +1,9 @@
1
1
  /* eslint-disable max-nested-callbacks */
2
- import {insert, type Patch, setIfMissing, unset} from '@portabletext/patches'
2
+ import {insert, setIfMissing, unset, type Patch} from '@portabletext/patches'
3
3
  import {type Subject} from 'rxjs'
4
4
  import {
5
- type Descendant,
6
5
  Editor,
6
+ type Descendant,
7
7
  type InsertNodeOperation,
8
8
  type InsertTextOperation,
9
9
  type MergeNodeOperation,
@@ -14,7 +14,6 @@ import {
14
14
  type SetNodeOperation,
15
15
  type SplitNodeOperation,
16
16
  } from 'slate'
17
-
18
17
  import {
19
18
  type EditorChange,
20
19
  type PatchObservable,
@@ -24,9 +23,16 @@ import {
24
23
  import {createApplyPatch} from '../../utils/applyPatch'
25
24
  import {debugWithName} from '../../utils/debug'
26
25
  import {fromSlateValue, isEqualToEmptyEditor} from '../../utils/values'
27
- import {IS_PROCESSING_REMOTE_CHANGES, KEY_TO_VALUE_ELEMENT} from '../../utils/weakMaps'
26
+ import {
27
+ IS_PROCESSING_REMOTE_CHANGES,
28
+ KEY_TO_VALUE_ELEMENT,
29
+ } from '../../utils/weakMaps'
28
30
  import {withRemoteChanges} from '../../utils/withChanges'
29
- import {isPatching, PATCHING, withoutPatching} from '../../utils/withoutPatching'
31
+ import {
32
+ isPatching,
33
+ PATCHING,
34
+ withoutPatching,
35
+ } from '../../utils/withoutPatching'
30
36
  import {withoutSaving} from './createWithUndoRedo'
31
37
 
32
38
  const debug = debugWithName('plugin:withPatches')
@@ -117,7 +123,8 @@ export function createWithPatches({
117
123
  withoutPatching(editor, () => {
118
124
  withoutSaving(editor, () => {
119
125
  patches.forEach((patch) => {
120
- if (debug.enabled) debug(`Handling remote patch ${JSON.stringify(patch)}`)
126
+ if (debug.enabled)
127
+ debug(`Handling remote patch ${JSON.stringify(patch)}`)
121
128
  changed = applyPatch(editor, patch)
122
129
  })
123
130
  })
@@ -169,12 +176,19 @@ export function createWithPatches({
169
176
 
170
177
  if (!isPatching(editor)) {
171
178
  if (debugVerbose && debug.enabled)
172
- debug(`Editor is not producing patch for operation ${operation.type}`, operation)
179
+ debug(
180
+ `Editor is not producing patch for operation ${operation.type}`,
181
+ operation,
182
+ )
173
183
  return editor
174
184
  }
175
185
 
176
186
  // If the editor was empty and now isn't, insert the placeholder into it.
177
- if (editorWasEmpty && !editorIsEmpty && operation.type !== 'set_selection') {
187
+ if (
188
+ editorWasEmpty &&
189
+ !editorIsEmpty &&
190
+ operation.type !== 'set_selection'
191
+ ) {
178
192
  patches.push(insert(previousChildren, 'before', [0]))
179
193
  }
180
194
 
@@ -182,31 +196,51 @@ export function createWithPatches({
182
196
  case 'insert_text':
183
197
  patches = [
184
198
  ...patches,
185
- ...patchFunctions.insertTextPatch(editor, operation, previousChildren),
199
+ ...patchFunctions.insertTextPatch(
200
+ editor,
201
+ operation,
202
+ previousChildren,
203
+ ),
186
204
  ]
187
205
  break
188
206
  case 'remove_text':
189
207
  patches = [
190
208
  ...patches,
191
- ...patchFunctions.removeTextPatch(editor, operation, previousChildren),
209
+ ...patchFunctions.removeTextPatch(
210
+ editor,
211
+ operation,
212
+ previousChildren,
213
+ ),
192
214
  ]
193
215
  break
194
216
  case 'remove_node':
195
217
  patches = [
196
218
  ...patches,
197
- ...patchFunctions.removeNodePatch(editor, operation, previousChildren),
219
+ ...patchFunctions.removeNodePatch(
220
+ editor,
221
+ operation,
222
+ previousChildren,
223
+ ),
198
224
  ]
199
225
  break
200
226
  case 'split_node':
201
227
  patches = [
202
228
  ...patches,
203
- ...patchFunctions.splitNodePatch(editor, operation, previousChildren),
229
+ ...patchFunctions.splitNodePatch(
230
+ editor,
231
+ operation,
232
+ previousChildren,
233
+ ),
204
234
  ]
205
235
  break
206
236
  case 'insert_node':
207
237
  patches = [
208
238
  ...patches,
209
- ...patchFunctions.insertNodePatch(editor, operation, previousChildren),
239
+ ...patchFunctions.insertNodePatch(
240
+ editor,
241
+ operation,
242
+ previousChildren,
243
+ ),
210
244
  ]
211
245
  break
212
246
  case 'set_node':
@@ -218,13 +252,21 @@ export function createWithPatches({
218
252
  case 'merge_node':
219
253
  patches = [
220
254
  ...patches,
221
- ...patchFunctions.mergeNodePatch(editor, operation, previousChildren),
255
+ ...patchFunctions.mergeNodePatch(
256
+ editor,
257
+ operation,
258
+ previousChildren,
259
+ ),
222
260
  ]
223
261
  break
224
262
  case 'move_node':
225
263
  patches = [
226
264
  ...patches,
227
- ...patchFunctions.moveNodePatch(editor, operation, previousChildren),
265
+ ...patchFunctions.moveNodePatch(
266
+ editor,
267
+ operation,
268
+ previousChildren,
269
+ ),
228
270
  ]
229
271
  break
230
272
  case 'set_selection':
@@ -236,7 +278,9 @@ export function createWithPatches({
236
278
  if (
237
279
  !editorWasEmpty &&
238
280
  editorIsEmpty &&
239
- ['merge_node', 'set_node', 'remove_text', 'remove_node'].includes(operation.type)
281
+ ['merge_node', 'set_node', 'remove_text', 'remove_node'].includes(
282
+ operation.type,
283
+ )
240
284
  ) {
241
285
  patches = [...patches, unset([])]
242
286
  change$.next({
@@ -1,5 +1,4 @@
1
1
  import {Editor, Path} from 'slate'
2
-
3
2
  import {type PortableTextSlateEditor} from '../../types/editor'
4
3
  import {type SlateTextBlock, type VoidElement} from '../../types/slate'
5
4
  import {debugWithName} from '../../utils/debug'
@@ -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 {
3
+ type PortableTextMemberSchemaTypes,
4
+ type 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 {
3
+ type PortableTextMemberSchemaTypes,
4
+ type 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,7 +32,8 @@ 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]) => {
@@ -121,10 +128,16 @@ export function createWithPortableTextLists(types: PortableTextMemberSchemaTypes
121
128
  let level = node.level || 1
122
129
  if (reverse) {
123
130
  level--
124
- debug('Decrementing list level', Math.min(MAX_LIST_LEVEL, Math.max(1, level)))
131
+ debug(
132
+ 'Decrementing list level',
133
+ Math.min(MAX_LIST_LEVEL, Math.max(1, level)),
134
+ )
125
135
  } else {
126
136
  level++
127
- debug('Incrementing list level', Math.min(MAX_LIST_LEVEL, Math.max(1, level)))
137
+ debug(
138
+ 'Incrementing list level',
139
+ Math.min(MAX_LIST_LEVEL, Math.max(1, level)),
140
+ )
128
141
  }
129
142
  Transforms.setNodes(
130
143
  editor,