@portabletext/editor 1.12.3 → 1.14.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/README.md +1 -1
  2. package/lib/_chunks-cjs/selector.get-text-before.cjs +320 -0
  3. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -0
  4. package/lib/_chunks-es/selector.get-text-before.js +321 -0
  5. package/lib/_chunks-es/selector.get-text-before.js.map +1 -0
  6. package/lib/{index.esm.js → index.cjs} +1954 -1513
  7. package/lib/index.cjs.map +1 -0
  8. package/lib/{index.d.mts → index.d.cts} +4249 -304
  9. package/lib/index.d.ts +4249 -304
  10. package/lib/index.js +1974 -1488
  11. package/lib/index.js.map +1 -1
  12. package/lib/selectors/index.cjs +35 -0
  13. package/lib/selectors/index.cjs.map +1 -0
  14. package/lib/selectors/index.d.cts +243 -0
  15. package/lib/selectors/index.d.ts +243 -0
  16. package/lib/selectors/index.js +36 -0
  17. package/lib/selectors/index.js.map +1 -0
  18. package/package.json +25 -17
  19. package/src/editor/Editable.tsx +61 -6
  20. package/src/editor/PortableTextEditor.tsx +19 -4
  21. package/src/editor/__tests__/handleClick.test.tsx +4 -4
  22. package/src/editor/behavior/behavior.action.insert-block-object.ts +1 -1
  23. package/src/editor/behavior/behavior.action.insert-break.ts +24 -27
  24. package/src/editor/behavior/behavior.action.insert-inline-object.ts +58 -0
  25. package/src/editor/behavior/behavior.action.insert-span.ts +1 -1
  26. package/src/editor/behavior/behavior.action.list-item.ts +100 -0
  27. package/src/editor/behavior/behavior.action.style.ts +108 -0
  28. package/src/editor/behavior/behavior.action.text-block.set.ts +25 -0
  29. package/src/editor/behavior/behavior.action.text-block.unset.ts +17 -0
  30. package/src/editor/behavior/behavior.actions.ts +266 -75
  31. package/src/editor/behavior/behavior.code-editor.ts +76 -0
  32. package/src/editor/behavior/behavior.core.block-objects.ts +52 -19
  33. package/src/editor/behavior/behavior.core.decorators.ts +9 -6
  34. package/src/editor/behavior/behavior.core.lists.ts +139 -17
  35. package/src/editor/behavior/behavior.core.ts +7 -2
  36. package/src/editor/behavior/behavior.guards.ts +28 -0
  37. package/src/editor/behavior/behavior.links.ts +9 -9
  38. package/src/editor/behavior/behavior.markdown.ts +69 -80
  39. package/src/editor/behavior/behavior.types.ts +121 -60
  40. package/src/editor/{use-editor.ts → create-editor.ts} +13 -8
  41. package/src/editor/editor-event-listener.tsx +2 -2
  42. package/src/editor/editor-machine.ts +57 -15
  43. package/src/editor/editor-provider.tsx +5 -5
  44. package/src/editor/editor-selector.ts +49 -0
  45. package/src/editor/editor-snapshot.ts +22 -0
  46. package/src/editor/get-value.ts +11 -0
  47. package/src/editor/plugins/create-with-event-listeners.ts +93 -5
  48. package/src/editor/plugins/createWithEditableAPI.ts +69 -20
  49. package/src/editor/plugins/createWithHotKeys.ts +0 -101
  50. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +1 -55
  51. package/src/editor/plugins/with-plugins.ts +4 -8
  52. package/src/editor/{behavior/behavior.utils.block-offset.test.ts → utils/utils.block-offset.test.ts} +1 -1
  53. package/src/editor/{behavior/behavior.utils.block-offset.ts → utils/utils.block-offset.ts} +1 -8
  54. package/src/editor/{behavior/behavior.utils.reverse-selection.ts → utils/utils.reverse-selection.ts} +3 -5
  55. package/src/editor/utils/utils.ts +21 -0
  56. package/src/index.ts +13 -9
  57. package/src/selectors/index.ts +15 -0
  58. package/src/selectors/selector.get-active-list-item.ts +37 -0
  59. package/src/{editor/behavior/behavior.utils.get-selection-text.ts → selectors/selector.get-selection-text.ts} +10 -15
  60. package/src/selectors/selector.get-text-before.ts +41 -0
  61. package/src/selectors/selectors.ts +329 -0
  62. package/src/types/editor.ts +0 -60
  63. package/src/utils/is-hotkey.test.ts +99 -46
  64. package/src/utils/is-hotkey.ts +1 -1
  65. package/src/utils/operationToPatches.ts +5 -0
  66. package/src/utils/paths.ts +4 -11
  67. package/src/utils/ranges.ts +3 -3
  68. package/lib/index.esm.js.map +0 -1
  69. package/lib/index.mjs +0 -7372
  70. package/lib/index.mjs.map +0 -1
  71. package/src/editor/behavior/behavior.utils.ts +0 -218
  72. package/src/editor/behavior/behavior.utilts.get-text-before.ts +0 -31
  73. package/src/editor/plugins/createWithPortableTextLists.ts +0 -172
  74. /package/src/editor/{behavior/behavior.utils.get-start-point.ts → utils/utils.get-start-point.ts} +0 -0
  75. /package/src/editor/{behavior/behavior.utils.is-keyed-segment.ts → utils/utils.is-keyed-segment.ts} +0 -0
@@ -1,15 +1,15 @@
1
1
  import {isPortableTextTextBlock} from '@sanity/types'
2
- import type {PortableTextMemberSchemaTypes} from '../../types/editor'
3
- import {defineBehavior} from './behavior.types'
2
+ import {getBlockTextBefore} from '../../selectors/selector.get-text-before'
4
3
  import {
5
4
  getFocusBlock,
6
5
  getFocusSpan,
7
6
  getFocusTextBlock,
8
- getTextBlockText,
9
7
  selectionIsCollapsed,
10
- } from './behavior.utils'
11
- import {spanSelectionPointToBlockOffset} from './behavior.utils.block-offset'
12
- import {getBlockTextBefore} from './behavior.utilts.get-text-before'
8
+ } from '../../selectors/selectors'
9
+ import type {PortableTextMemberSchemaTypes} from '../../types/editor'
10
+ import {getTextBlockText} from '../utils/utils'
11
+ import {spanSelectionPointToBlockOffset} from '../utils/utils.block-offset'
12
+ import {defineBehavior} from './behavior.types'
13
13
 
14
14
  /**
15
15
  * @alpha
@@ -41,7 +41,7 @@ export type MarkdownBehaviorsConfig = {
41
41
  */
42
42
  export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
43
43
  const automaticBlockquoteOnSpace = defineBehavior({
44
- on: 'insert text',
44
+ on: 'insert.text',
45
45
  guard: ({context, event}) => {
46
46
  const isSpace = event.text === ' '
47
47
 
@@ -49,9 +49,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
49
49
  return false
50
50
  }
51
51
 
52
- const selectionCollapsed = selectionIsCollapsed(context)
53
- const focusTextBlock = getFocusTextBlock(context)
54
- const focusSpan = getFocusSpan(context)
52
+ const selectionCollapsed = selectionIsCollapsed({context})
53
+ const focusTextBlock = getFocusTextBlock({context})
54
+ const focusSpan = getFocusSpan({context})
55
55
 
56
56
  if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
57
57
  return false
@@ -76,7 +76,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
76
76
  const blockText = getTextBlockText(focusTextBlock.node)
77
77
  const caretAtTheEndOfQuote = blockOffset.offset === 1
78
78
  const looksLikeMarkdownQuote = /^>/.test(blockText)
79
- const blockquoteStyle = config.blockquoteStyle?.({schema: context.schema})
79
+ const blockquoteStyle = config.blockquoteStyle?.(context)
80
80
 
81
81
  if (
82
82
  caretAtTheEndOfQuote &&
@@ -91,23 +91,23 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
91
91
  actions: [
92
92
  () => [
93
93
  {
94
- type: 'insert text',
94
+ type: 'insert.text',
95
95
  text: ' ',
96
96
  },
97
97
  ],
98
- (_, {focusTextBlock, style}) => [
98
+ ({focusTextBlock, style}) => [
99
99
  {
100
- type: 'unset block',
100
+ type: 'text block.unset',
101
101
  props: ['listItem', 'level'],
102
- paths: [focusTextBlock.path],
102
+ at: focusTextBlock.path,
103
103
  },
104
104
  {
105
- type: 'set block',
105
+ type: 'text block.set',
106
106
  style,
107
- paths: [focusTextBlock.path],
107
+ at: focusTextBlock.path,
108
108
  },
109
109
  {
110
- type: 'delete text',
110
+ type: 'delete.text',
111
111
  anchor: {
112
112
  path: focusTextBlock.path,
113
113
  offset: 0,
@@ -121,7 +121,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
121
121
  ],
122
122
  })
123
123
  const automaticHr = defineBehavior({
124
- on: 'insert text',
124
+ on: 'insert.text',
125
125
  guard: ({context, event}) => {
126
126
  const hrCharacter =
127
127
  event.text === '-'
@@ -136,20 +136,15 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
136
136
  return false
137
137
  }
138
138
 
139
- const hrObject = config.horizontalRuleObject?.({
140
- schema: context.schema,
141
- })
142
- const focusBlock = getFocusTextBlock(context)
143
- const selectionCollapsed = selectionIsCollapsed(context)
139
+ const hrObject = config.horizontalRuleObject?.(context)
140
+ const focusBlock = getFocusTextBlock({context})
141
+ const selectionCollapsed = selectionIsCollapsed({context})
144
142
 
145
143
  if (!hrObject || !focusBlock || !selectionCollapsed) {
146
144
  return false
147
145
  }
148
146
 
149
- const textBefore = getBlockTextBefore({
150
- value: context.value,
151
- point: context.selection.focus,
152
- })
147
+ const textBefore = getBlockTextBefore({context})
153
148
  const hrBlockOffsets = {
154
149
  anchor: {
155
150
  path: focusBlock.path,
@@ -168,20 +163,20 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
168
163
  return false
169
164
  },
170
165
  actions: [
171
- (_, {hrCharacter}) => [
166
+ ({hrCharacter}) => [
172
167
  {
173
- type: 'insert text',
168
+ type: 'insert.text',
174
169
  text: hrCharacter,
175
170
  },
176
171
  ],
177
- (_, {hrObject, hrBlockOffsets}) => [
172
+ ({hrObject, hrBlockOffsets}) => [
178
173
  {
179
- type: 'insert block object',
174
+ type: 'insert.block object',
180
175
  placement: 'before',
181
176
  blockObject: hrObject,
182
177
  },
183
178
  {
184
- type: 'delete text',
179
+ type: 'delete.text',
185
180
  ...hrBlockOffsets,
186
181
  },
187
182
  ],
@@ -190,13 +185,11 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
190
185
  const automaticHrOnPaste = defineBehavior({
191
186
  on: 'paste',
192
187
  guard: ({context, event}) => {
193
- const text = event.clipboardData.getData('text/plain')
188
+ const text = event.data.getData('text/plain')
194
189
  const hrRegExp = /^(---)$|(___)$|(\*\*\*)$/gm
195
190
  const hrCharacters = text.match(hrRegExp)?.[0]
196
- const hrObject = config.horizontalRuleObject?.({
197
- schema: context.schema,
198
- })
199
- const focusBlock = getFocusBlock(context)
191
+ const hrObject = config.horizontalRuleObject?.(context)
192
+ const focusBlock = getFocusBlock({context})
200
193
 
201
194
  if (!hrCharacters || !hrObject || !focusBlock) {
202
195
  return false
@@ -205,30 +198,30 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
205
198
  return {hrCharacters, hrObject, focusBlock}
206
199
  },
207
200
  actions: [
208
- (_, {hrCharacters}) => [
201
+ ({hrCharacters}) => [
209
202
  {
210
- type: 'insert text',
203
+ type: 'insert.text',
211
204
  text: hrCharacters,
212
205
  },
213
206
  ],
214
- (_, {hrObject, focusBlock}) =>
207
+ ({hrObject, focusBlock}) =>
215
208
  isPortableTextTextBlock(focusBlock.node)
216
209
  ? [
217
210
  {
218
- type: 'insert text block',
211
+ type: 'insert.text block',
219
212
  textBlock: {children: focusBlock.node.children},
220
213
  placement: 'after',
221
214
  },
222
215
  {
223
- type: 'insert block object',
216
+ type: 'insert.block object',
224
217
  blockObject: hrObject,
225
218
  placement: 'after',
226
219
  },
227
- {type: 'delete block', blockPath: focusBlock.path},
220
+ {type: 'delete.block', blockPath: focusBlock.path},
228
221
  ]
229
222
  : [
230
223
  {
231
- type: 'insert block object',
224
+ type: 'insert.block object',
232
225
  blockObject: hrObject,
233
226
  placement: 'after',
234
227
  },
@@ -236,7 +229,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
236
229
  ],
237
230
  })
238
231
  const automaticHeadingOnSpace = defineBehavior({
239
- on: 'insert text',
232
+ on: 'insert.text',
240
233
  guard: ({context, event}) => {
241
234
  const isSpace = event.text === ' '
242
235
 
@@ -244,9 +237,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
244
237
  return false
245
238
  }
246
239
 
247
- const selectionCollapsed = selectionIsCollapsed(context)
248
- const focusTextBlock = getFocusTextBlock(context)
249
- const focusSpan = getFocusSpan(context)
240
+ const selectionCollapsed = selectionIsCollapsed({context})
241
+ const focusTextBlock = getFocusTextBlock({context})
242
+ const focusSpan = getFocusSpan({context})
250
243
 
251
244
  if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
252
245
  return false
@@ -297,23 +290,23 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
297
290
  actions: [
298
291
  () => [
299
292
  {
300
- type: 'insert text',
293
+ type: 'insert.text',
301
294
  text: ' ',
302
295
  },
303
296
  ],
304
- (_, {focusTextBlock, style, level}) => [
297
+ ({focusTextBlock, style, level}) => [
305
298
  {
306
- type: 'unset block',
299
+ type: 'text block.unset',
307
300
  props: ['listItem', 'level'],
308
- paths: [focusTextBlock.path],
301
+ at: focusTextBlock.path,
309
302
  },
310
303
  {
311
- type: 'set block',
304
+ type: 'text block.set',
312
305
  style,
313
- paths: [focusTextBlock.path],
306
+ at: focusTextBlock.path,
314
307
  },
315
308
  {
316
- type: 'delete text',
309
+ type: 'delete.text',
317
310
  anchor: {
318
311
  path: focusTextBlock.path,
319
312
  offset: 0,
@@ -327,11 +320,11 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
327
320
  ],
328
321
  })
329
322
  const clearStyleOnBackspace = defineBehavior({
330
- on: 'delete backward',
323
+ on: 'delete.backward',
331
324
  guard: ({context}) => {
332
- const selectionCollapsed = selectionIsCollapsed(context)
333
- const focusTextBlock = getFocusTextBlock(context)
334
- const focusSpan = getFocusSpan(context)
325
+ const selectionCollapsed = selectionIsCollapsed({context})
326
+ const focusTextBlock = getFocusTextBlock({context})
327
+ const focusSpan = getFocusSpan({context})
335
328
 
336
329
  if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
337
330
  return false
@@ -341,7 +334,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
341
334
  focusTextBlock.node.children[0]._key === focusSpan.node._key &&
342
335
  context.selection.focus.offset === 0
343
336
 
344
- const defaultStyle = config.defaultStyle?.({schema: context.schema})
337
+ const defaultStyle = config.defaultStyle?.(context)
345
338
 
346
339
  if (
347
340
  atTheBeginningOfBLock &&
@@ -354,17 +347,17 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
354
347
  return false
355
348
  },
356
349
  actions: [
357
- (_, {defaultStyle, focusTextBlock}) => [
350
+ ({defaultStyle, focusTextBlock}) => [
358
351
  {
359
- type: 'set block',
352
+ type: 'text block.set',
360
353
  style: defaultStyle,
361
- paths: [focusTextBlock.path],
354
+ at: focusTextBlock.path,
362
355
  },
363
356
  ],
364
357
  ],
365
358
  })
366
359
  const automaticListOnSpace = defineBehavior({
367
- on: 'insert text',
360
+ on: 'insert.text',
368
361
  guard: ({context, event}) => {
369
362
  const isSpace = event.text === ' '
370
363
 
@@ -372,9 +365,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
372
365
  return false
373
366
  }
374
367
 
375
- const selectionCollapsed = selectionIsCollapsed(context)
376
- const focusTextBlock = getFocusTextBlock(context)
377
- const focusSpan = getFocusSpan(context)
368
+ const selectionCollapsed = selectionIsCollapsed({context})
369
+ const focusTextBlock = getFocusTextBlock({context})
370
+ const focusSpan = getFocusSpan({context})
378
371
 
379
372
  if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
380
373
  return false
@@ -397,11 +390,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
397
390
  }
398
391
 
399
392
  const blockText = getTextBlockText(focusTextBlock.node)
400
- const defaultStyle = config.defaultStyle?.({schema: context.schema})
393
+ const defaultStyle = config.defaultStyle?.(context)
401
394
  const looksLikeUnorderedList = /^(-|\*)/.test(blockText)
402
- const unorderedListStyle = config.unorderedListStyle?.({
403
- schema: context.schema,
404
- })
395
+ const unorderedListStyle = config.unorderedListStyle?.(context)
405
396
  const caretAtTheEndOfUnorderedList = blockOffset.offset === 1
406
397
 
407
398
  if (
@@ -419,9 +410,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
419
410
  }
420
411
 
421
412
  const looksLikeOrderedList = /^1\./.test(blockText)
422
- const orderedListStyle = config.orderedListStyle?.({
423
- schema: context.schema,
424
- })
413
+ const orderedListStyle = config.orderedListStyle?.(context)
425
414
  const caretAtTheEndOfOrderedList = blockOffset.offset === 2
426
415
 
427
416
  if (
@@ -443,20 +432,20 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
443
432
  actions: [
444
433
  () => [
445
434
  {
446
- type: 'insert text',
435
+ type: 'insert.text',
447
436
  text: ' ',
448
437
  },
449
438
  ],
450
- (_, {focusTextBlock, style, listItem, listItemLength}) => [
439
+ ({focusTextBlock, style, listItem, listItemLength}) => [
451
440
  {
452
- type: 'set block',
441
+ type: 'text block.set',
453
442
  listItem,
454
443
  level: 1,
455
444
  style,
456
- paths: [focusTextBlock.path],
445
+ at: focusTextBlock.path,
457
446
  },
458
447
  {
459
- type: 'delete text',
448
+ type: 'delete.text',
460
449
  anchor: {
461
450
  path: focusTextBlock.path,
462
451
  offset: 0,
@@ -1,25 +1,8 @@
1
- import type {
2
- KeyedSegment,
3
- PortableTextBlock,
4
- PortableTextTextBlock,
5
- } from '@sanity/types'
1
+ import type {KeyedSegment, PortableTextTextBlock} from '@sanity/types'
6
2
  import type {TextUnit} from 'slate'
7
3
  import type {TextInsertTextOptions} from 'slate/dist/interfaces/transforms/text'
8
- import type {
9
- EditorSelection,
10
- PortableTextMemberSchemaTypes,
11
- PortableTextSlateEditor,
12
- } from '../../types/editor'
13
- import type {BlockOffset} from './behavior.utils.block-offset'
14
-
15
- /**
16
- * @alpha
17
- */
18
- export type BehaviorContext = {
19
- schema: PortableTextMemberSchemaTypes
20
- value: Array<PortableTextBlock>
21
- selection: NonNullable<EditorSelection>
22
- }
4
+ import type {EditorSelection, PortableTextSlateEditor} from '../../types/editor'
5
+ import type {EditorContext} from '../editor-snapshot'
23
6
 
24
7
  /**
25
8
  * @alpha
@@ -45,6 +28,13 @@ export type BehaviorEvent =
45
28
  value: {[prop: string]: unknown}
46
29
  }
47
30
  }
31
+ | {
32
+ type: 'blur'
33
+ }
34
+ | {
35
+ type: 'copy'
36
+ data: DataTransfer
37
+ }
48
38
  | {
49
39
  type: 'decorator.add'
50
40
  decorator: string
@@ -58,30 +48,67 @@ export type BehaviorEvent =
58
48
  decorator: string
59
49
  }
60
50
  | {
61
- type: 'delete backward'
51
+ type: 'delete.backward'
62
52
  unit: TextUnit
63
53
  }
64
54
  | {
65
- type: 'delete forward'
55
+ type: 'delete.forward'
66
56
  unit: TextUnit
67
57
  }
68
58
  | {
69
59
  type: 'focus'
70
60
  }
71
61
  | {
72
- type: 'insert soft break'
62
+ type: 'insert.block object'
63
+ placement: 'auto' | 'after' | 'before'
64
+ blockObject: {
65
+ name: string
66
+ value?: {[prop: string]: unknown}
67
+ }
73
68
  }
74
69
  | {
75
- type: 'insert break'
70
+ type: 'insert.inline object'
71
+ inlineObject: {
72
+ name: string
73
+ value?: {[prop: string]: unknown}
74
+ }
76
75
  }
77
76
  | {
78
- type: 'insert text'
77
+ type: 'insert.soft break'
78
+ }
79
+ | {
80
+ type: 'insert.break'
81
+ }
82
+ | {
83
+ type: 'insert.text'
79
84
  text: string
80
85
  options?: TextInsertTextOptions
81
86
  }
82
87
  | {
83
88
  type: 'paste'
84
- clipboardData: NonNullable<ClipboardEvent['clipboardData']>
89
+ data: DataTransfer
90
+ }
91
+ | {
92
+ type: 'key.down'
93
+ keyboardEvent: Pick<
94
+ KeyboardEvent,
95
+ 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
96
+ >
97
+ }
98
+ | {
99
+ type: 'key.up'
100
+ keyboardEvent: Pick<
101
+ KeyboardEvent,
102
+ 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
103
+ >
104
+ }
105
+ | {
106
+ type: 'list item.toggle'
107
+ listItem: string
108
+ }
109
+ | {
110
+ type: 'style.toggle'
111
+ style: string
85
112
  }
86
113
 
87
114
  /**
@@ -94,8 +121,8 @@ export type BehaviorGuard<
94
121
  context,
95
122
  event,
96
123
  }: {
124
+ context: EditorContext
97
125
  event: TBehaviorEvent
98
- context: BehaviorContext
99
126
  }) => TGuardResponse | false
100
127
 
101
128
  /**
@@ -104,15 +131,7 @@ export type BehaviorGuard<
104
131
  export type BehaviorActionIntend =
105
132
  | BehaviorEvent
106
133
  | {
107
- type: 'insert block object'
108
- placement: 'auto' | 'after' | 'before'
109
- blockObject: {
110
- name: string
111
- value?: {[prop: string]: unknown}
112
- }
113
- }
114
- | {
115
- type: 'insert span'
134
+ type: 'insert.span'
116
135
  text: string
117
136
  annotations?: Array<{
118
137
  name: string
@@ -121,30 +140,42 @@ export type BehaviorActionIntend =
121
140
  decorators?: Array<string>
122
141
  }
123
142
  | {
124
- type: 'insert text block'
143
+ type: 'insert.text block'
125
144
  placement: 'auto' | 'after' | 'before'
126
145
  textBlock?: {
127
146
  children?: PortableTextTextBlock['children']
128
147
  }
129
148
  }
130
149
  | {
131
- type: 'set block'
132
- paths: Array<[KeyedSegment]>
133
- style?: string
134
- listItem?: string
135
- level?: number
150
+ type: 'list item.add'
151
+ listItem: string
152
+ }
153
+ | {
154
+ type: 'list item.remove'
155
+ listItem: string
156
+ }
157
+ | {
158
+ type: 'move.block'
159
+ at: [KeyedSegment]
160
+ to: [KeyedSegment]
161
+ }
162
+ | {
163
+ type: 'move.block down'
164
+ at: [KeyedSegment]
165
+ }
166
+ | {
167
+ type: 'move.block up'
168
+ at: [KeyedSegment]
136
169
  }
137
170
  | {
138
- type: 'unset block'
139
- paths: Array<[KeyedSegment]>
140
- props: Array<'style' | 'listItem' | 'level'>
171
+ type: 'noop'
141
172
  }
142
173
  | {
143
- type: 'delete block'
174
+ type: 'delete.block'
144
175
  blockPath: [KeyedSegment]
145
176
  }
146
177
  | {
147
- type: 'delete text'
178
+ type: 'delete.text'
148
179
  anchor: BlockOffset
149
180
  focus: BlockOffset
150
181
  }
@@ -156,9 +187,35 @@ export type BehaviorActionIntend =
156
187
  type: 'select'
157
188
  selection: EditorSelection
158
189
  }
190
+ | {
191
+ type: 'select previous block'
192
+ }
193
+ | {
194
+ type: 'select next block'
195
+ }
159
196
  | {
160
197
  type: 'reselect'
161
198
  }
199
+ | {
200
+ type: 'style.add'
201
+ style: string
202
+ }
203
+ | {
204
+ type: 'style.remove'
205
+ style: string
206
+ }
207
+ | {
208
+ type: 'text block.set'
209
+ at: [KeyedSegment]
210
+ level?: number
211
+ listItem?: string
212
+ style?: string
213
+ }
214
+ | {
215
+ type: 'text block.unset'
216
+ at: [KeyedSegment]
217
+ props: Array<'level' | 'listItem' | 'style'>
218
+ }
162
219
 
163
220
  /**
164
221
  * @alpha
@@ -190,25 +247,21 @@ export type Behavior<
190
247
  /**
191
248
  * Array of behavior action sets.
192
249
  */
193
- actions: Array<BehaviorActionIntendSet<TBehaviorEventType, TGuardResponse>>
250
+ actions: Array<BehaviorActionIntendSet<TGuardResponse>>
194
251
  }
195
252
 
196
253
  /**
197
254
  * @alpha
198
255
  */
199
- export type BehaviorActionIntendSet<
200
- TBehaviorEventType extends BehaviorEvent['type'] = BehaviorEvent['type'],
201
- TGuardResponse = true,
202
- > = (
203
- {
204
- context,
205
- event,
206
- }: {
207
- context: BehaviorContext
208
- event: PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>
209
- },
256
+ export type BehaviorActionIntendSet<TGuardResponse = true> = (
210
257
  guardResponse: TGuardResponse,
211
- ) => Array<BehaviorActionIntend>
258
+ ) => Array<
259
+ OmitFromUnion<
260
+ BehaviorActionIntend,
261
+ 'type',
262
+ 'copy' | 'key.down' | 'key.up' | 'paste'
263
+ >
264
+ >
212
265
 
213
266
  /**
214
267
  * @alpha
@@ -220,6 +273,14 @@ export function defineBehavior<
220
273
  return behavior as unknown as Behavior
221
274
  }
222
275
 
276
+ /**
277
+ * @alpha
278
+ */
279
+ export type BlockOffset = {
280
+ path: [KeyedSegment]
281
+ offset: number
282
+ }
283
+
223
284
  /**
224
285
  * @alpha
225
286
  */
@@ -53,7 +53,15 @@ export type EditorEvent = PickFromUnion<
53
53
  InternalEditorEvent,
54
54
  'type',
55
55
  | 'annotation.toggle'
56
+ | 'blur'
57
+ | 'decorator.add'
58
+ | 'decorator.remove'
59
+ | 'decorator.toggle'
56
60
  | 'focus'
61
+ | 'insert.block object'
62
+ | 'insert.inline object'
63
+ | 'list item.toggle'
64
+ | 'style.toggle'
57
65
  | 'patches'
58
66
  | 'toggle readOnly'
59
67
  | 'update behaviors'
@@ -66,15 +74,15 @@ export type EditorEvent = PickFromUnion<
66
74
  export type Editor = {
67
75
  send: (event: EditorEvent) => void
68
76
  on: ActorRef<Snapshot<unknown>, EventObject, EditorEmittedEvent>['on']
69
- editable: EditableAPI
70
77
  _internal: {
78
+ editable: EditableAPI
71
79
  editorActor: EditorActor
72
80
  slateEditor: SlateEditor
73
81
  }
74
82
  }
75
83
 
76
84
  /**
77
- * @alpha
85
+ * @internal
78
86
  */
79
87
  export function createEditor(config: EditorConfig): Editor {
80
88
  const editorActor = createActor(editorMachine, {
@@ -96,18 +104,15 @@ export function createEditor(config: EditorConfig): Editor {
96
104
  // @ts-ignore
97
105
  listener,
98
106
  ),
99
- editable,
100
107
  _internal: {
108
+ editable,
101
109
  editorActor,
102
110
  slateEditor,
103
111
  },
104
112
  }
105
113
  }
106
114
 
107
- /**
108
- * @alpha
109
- */
110
- export function useEditor(config: EditorConfig): Editor {
115
+ export function useCreateEditor(config: EditorConfig): Editor {
111
116
  const editorActor = useActorRef(editorMachine, {
112
117
  input: editorConfigToMachineInput(config),
113
118
  })
@@ -135,8 +140,8 @@ export function useEditor(config: EditorConfig): Editor {
135
140
  () => ({
136
141
  send,
137
142
  on,
138
- editable,
139
143
  _internal: {
144
+ editable,
140
145
  editorActor,
141
146
  slateEditor,
142
147
  },