@portabletext/editor 1.36.6 → 1.38.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 (119) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +84 -49
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +1 -1
  4. package/lib/_chunks-cjs/editor-provider.cjs +919 -526
  5. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
  6. package/lib/_chunks-cjs/{util.block-offsets-to-selection.cjs → parse-blocks.cjs} +36 -21
  7. package/lib/_chunks-cjs/parse-blocks.cjs.map +1 -0
  8. package/lib/_chunks-cjs/selector.get-text-before.cjs +2 -2
  9. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  10. package/lib/_chunks-cjs/{selector.is-active-style.cjs → selector.is-overlapping-selection.cjs} +144 -3
  11. package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs.map +1 -0
  12. package/lib/_chunks-cjs/util.slice-blocks.cjs +12 -0
  13. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  14. package/lib/_chunks-es/behavior.core.js +84 -49
  15. package/lib/_chunks-es/behavior.core.js.map +1 -1
  16. package/lib/_chunks-es/behavior.markdown.js +1 -1
  17. package/lib/_chunks-es/editor-provider.js +911 -517
  18. package/lib/_chunks-es/editor-provider.js.map +1 -1
  19. package/lib/_chunks-es/{util.block-offsets-to-selection.js → parse-blocks.js} +37 -22
  20. package/lib/_chunks-es/parse-blocks.js.map +1 -0
  21. package/lib/_chunks-es/selector.get-text-before.js +1 -2
  22. package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
  23. package/lib/_chunks-es/{selector.is-active-style.js → selector.is-overlapping-selection.js} +146 -5
  24. package/lib/_chunks-es/selector.is-overlapping-selection.js.map +1 -0
  25. package/lib/_chunks-es/util.slice-blocks.js +12 -0
  26. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  27. package/lib/behaviors/index.d.cts +10535 -4689
  28. package/lib/behaviors/index.d.ts +10535 -4689
  29. package/lib/index.cjs +582 -209
  30. package/lib/index.cjs.map +1 -1
  31. package/lib/index.d.cts +5297 -1178
  32. package/lib/index.d.ts +5297 -1178
  33. package/lib/index.js +591 -213
  34. package/lib/index.js.map +1 -1
  35. package/lib/plugins/index.cjs +2 -2
  36. package/lib/plugins/index.cjs.map +1 -1
  37. package/lib/plugins/index.d.cts +5297 -1178
  38. package/lib/plugins/index.d.ts +5297 -1178
  39. package/lib/plugins/index.js +2 -2
  40. package/lib/selectors/index.cjs +21 -103
  41. package/lib/selectors/index.cjs.map +1 -1
  42. package/lib/selectors/index.d.cts +5313 -1178
  43. package/lib/selectors/index.d.ts +5313 -1178
  44. package/lib/selectors/index.js +13 -96
  45. package/lib/selectors/index.js.map +1 -1
  46. package/lib/utils/index.cjs +4 -4
  47. package/lib/utils/index.cjs.map +1 -1
  48. package/lib/utils/index.d.cts +5297 -1178
  49. package/lib/utils/index.d.ts +5297 -1178
  50. package/lib/utils/index.js +3 -4
  51. package/lib/utils/index.js.map +1 -1
  52. package/package.json +15 -14
  53. package/src/behavior-actions/behavior.action.blur.ts +8 -0
  54. package/src/behavior-actions/behavior.action.decorator.add.ts +2 -1
  55. package/src/behavior-actions/behavior.action.delete.backward.ts +7 -0
  56. package/src/behavior-actions/behavior.action.delete.block.ts +24 -0
  57. package/src/behavior-actions/behavior.action.delete.forward.ts +7 -0
  58. package/src/behavior-actions/behavior.action.delete.text.ts +2 -1
  59. package/src/behavior-actions/behavior.action.delete.ts +1 -3
  60. package/src/behavior-actions/behavior.action.deserialization.failure.ts +9 -0
  61. package/src/behavior-actions/behavior.action.deserialization.success.ts +16 -0
  62. package/src/behavior-actions/behavior.action.effect.ts +7 -0
  63. package/src/behavior-actions/behavior.action.focus.ts +8 -0
  64. package/src/behavior-actions/behavior.action.insert-blocks.ts +118 -74
  65. package/src/behavior-actions/behavior.action.insert-break.ts +1 -0
  66. package/src/behavior-actions/{behavior.action.insert-block-object.ts → behavior.action.insert.block-object.ts} +9 -14
  67. package/src/behavior-actions/behavior.action.insert.block.ts +247 -2
  68. package/src/behavior-actions/behavior.action.insert.text-block.ts +33 -0
  69. package/src/behavior-actions/behavior.action.insert.text.ts +7 -0
  70. package/src/behavior-actions/behavior.action.move.block-down.ts +48 -0
  71. package/src/behavior-actions/behavior.action.move.block-up.ts +53 -0
  72. package/src/behavior-actions/behavior.action.move.block.ts +16 -0
  73. package/src/behavior-actions/behavior.action.noop.ts +5 -0
  74. package/src/behavior-actions/behavior.action.select.next-block.ts +44 -0
  75. package/src/behavior-actions/behavior.action.select.previous-block.ts +48 -0
  76. package/src/behavior-actions/behavior.action.select.ts +15 -0
  77. package/src/behavior-actions/behavior.action.serialization.failure.ts +9 -0
  78. package/src/behavior-actions/behavior.action.serialization.success.ts +14 -0
  79. package/src/behavior-actions/behavior.actions.ts +54 -212
  80. package/src/behaviors/behavior.core.block-objects.ts +35 -6
  81. package/src/behaviors/behavior.core.insert-break.ts +1 -0
  82. package/src/behaviors/behavior.core.ts +2 -0
  83. package/src/behaviors/behavior.default.ts +241 -33
  84. package/src/behaviors/behavior.types.ts +138 -20
  85. package/src/converters/converter.portable-text.ts +5 -2
  86. package/src/converters/converter.text-html.serialize.test.ts +4 -4
  87. package/src/converters/converter.text-html.ts +5 -2
  88. package/src/converters/converter.text-plain.test.ts +6 -6
  89. package/src/converters/converter.text-plain.ts +5 -2
  90. package/src/converters/converter.types.ts +3 -3
  91. package/src/editor/Editable.tsx +403 -48
  92. package/src/editor/components/Element.tsx +133 -18
  93. package/src/editor/components/use-draggable.ts +34 -102
  94. package/src/editor/editor-machine.ts +66 -10
  95. package/src/editor/editor-selector.ts +2 -0
  96. package/src/editor/editor-snapshot.ts +17 -0
  97. package/src/editor/plugins/create-with-event-listeners.ts +6 -40
  98. package/src/internal-utils/create-test-snapshot.ts +2 -0
  99. package/src/internal-utils/event-position.ts +210 -0
  100. package/src/internal-utils/slate-utils.ts +56 -0
  101. package/src/internal-utils/weakMaps.ts +1 -15
  102. package/src/selectors/index.ts +2 -0
  103. package/src/selectors/selector.get-focus-inline-object.ts +21 -0
  104. package/src/selectors/selector.is-overlapping-selection.test.ts +171 -0
  105. package/src/selectors/selector.is-overlapping-selection.ts +108 -4
  106. package/src/selectors/selector.is-point-after-selection.ts +3 -1
  107. package/src/selectors/selector.is-point-before-selection.ts +3 -1
  108. package/src/selectors/selector.is-selecting-entire-blocks.ts +34 -0
  109. package/lib/_chunks-cjs/selector.is-active-style.cjs.map +0 -1
  110. package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +0 -1
  111. package/lib/_chunks-cjs/util.reverse-selection.cjs +0 -14
  112. package/lib/_chunks-cjs/util.reverse-selection.cjs.map +0 -1
  113. package/lib/_chunks-es/selector.is-active-style.js.map +0 -1
  114. package/lib/_chunks-es/util.block-offsets-to-selection.js.map +0 -1
  115. package/lib/_chunks-es/util.reverse-selection.js +0 -15
  116. package/lib/_chunks-es/util.reverse-selection.js.map +0 -1
  117. package/src/behavior-actions/behavior.action-utils.insert-block.ts +0 -61
  118. package/src/editor/__tests__/handleClick.test.tsx +0 -277
  119. package/src/editor/components/use-droppable.ts +0 -135
@@ -1,6 +1,14 @@
1
+ import {Editor, Path, Point, Range, Transforms, type Descendant} from 'slate'
2
+ import {DOMEditor} from 'slate-dom'
3
+ import type {EditorSchema} from '../editor/define-schema'
1
4
  import {parseBlock} from '../internal-utils/parse-blocks'
2
- import {toSlateValue} from '../internal-utils/values'
3
- import {insertBlock} from './behavior.action-utils.insert-block'
5
+ import {
6
+ getFocusBlock,
7
+ getFocusChild,
8
+ getLastBlock,
9
+ } from '../internal-utils/slate-utils'
10
+ import {isEqualToEmptyEditor, toSlateValue} from '../internal-utils/values'
11
+ import type {PortableTextSlateEditor} from '../types/editor'
4
12
  import type {BehaviorActionImplementation} from './behavior.actions'
5
13
 
6
14
  export const insertBlockActionImplementation: BehaviorActionImplementation<
@@ -27,7 +35,244 @@ export const insertBlockActionImplementation: BehaviorActionImplementation<
27
35
  insertBlock({
28
36
  block: fragment,
29
37
  placement: action.placement,
38
+ select: action.select ?? 'start',
30
39
  editor: action.editor,
31
40
  schema: context.schema,
32
41
  })
33
42
  }
43
+
44
+ export function insertBlock({
45
+ block,
46
+ placement,
47
+ select,
48
+ editor,
49
+ schema,
50
+ }: {
51
+ block: Descendant
52
+ placement: 'auto' | 'after' | 'before'
53
+ select: 'start' | 'end' | 'none'
54
+ editor: PortableTextSlateEditor
55
+ schema: EditorSchema
56
+ }) {
57
+ const [focusBlock, focusBlockPath] = getFocusBlock({editor})
58
+
59
+ if (!editor.selection || !focusBlock || !focusBlockPath) {
60
+ if (select !== 'none') {
61
+ DOMEditor.focus(editor)
62
+ }
63
+
64
+ const [lastBlock, lastBlockPath] = getLastBlock({editor})
65
+
66
+ if (placement === 'before') {
67
+ Transforms.insertNodes(editor, [block], {at: [0]})
68
+
69
+ if (select === 'start') {
70
+ Transforms.select(editor, Editor.start(editor, [0]))
71
+ } else if (select === 'end') {
72
+ Transforms.select(editor, Editor.end(editor, [0]))
73
+ }
74
+ } else if (placement === 'after') {
75
+ const nextPath = lastBlockPath ? [lastBlockPath[0] + 1] : [0]
76
+ Transforms.insertNodes(editor, [block], {at: nextPath, select: false})
77
+
78
+ if (select === 'start') {
79
+ Transforms.select(editor, Editor.start(editor, nextPath))
80
+ } else if (select === 'end') {
81
+ Transforms.select(editor, Editor.end(editor, nextPath))
82
+ }
83
+ } else {
84
+ // placement === 'auto'
85
+
86
+ if (lastBlock && isEqualToEmptyEditor([lastBlock], schema)) {
87
+ // And if the last block was an empty text block, let's remove
88
+ // that too
89
+ Transforms.removeNodes(editor, {at: lastBlockPath})
90
+
91
+ Transforms.insertNodes(editor, [block], {
92
+ at: lastBlockPath,
93
+ select: false,
94
+ })
95
+
96
+ Transforms.deselect(editor)
97
+
98
+ if (select === 'start') {
99
+ Transforms.select(editor, Editor.start(editor, lastBlockPath))
100
+ } else if (select === 'end') {
101
+ Transforms.select(editor, Editor.end(editor, lastBlockPath))
102
+ }
103
+
104
+ return
105
+ }
106
+
107
+ if (
108
+ editor.isTextBlock(block) &&
109
+ lastBlock &&
110
+ editor.isTextBlock(lastBlock)
111
+ ) {
112
+ const selectionBefore = Editor.end(editor, lastBlockPath)
113
+
114
+ Transforms.insertFragment(editor, [block], {
115
+ at: Editor.end(editor, lastBlockPath),
116
+ })
117
+
118
+ if (select === 'start') {
119
+ Transforms.select(editor, selectionBefore)
120
+ } else if (select === 'none') {
121
+ Transforms.deselect(editor)
122
+ }
123
+
124
+ return
125
+ }
126
+
127
+ const nextPath = lastBlockPath ? [lastBlockPath[0] + 1] : [0]
128
+
129
+ Transforms.insertNodes(editor, [block], {at: nextPath, select: false})
130
+
131
+ if (select === 'start') {
132
+ Transforms.select(editor, Editor.start(editor, nextPath))
133
+ } else if (select === 'end') {
134
+ Transforms.select(editor, Editor.end(editor, nextPath))
135
+ }
136
+ }
137
+ } else {
138
+ if (placement === 'before') {
139
+ const currentSelection = editor.selection
140
+
141
+ Transforms.insertNodes(editor, [block], {
142
+ at: focusBlockPath,
143
+ select: false,
144
+ })
145
+
146
+ const adjustedSelection = Range.transform(currentSelection, {
147
+ type: 'move_node',
148
+ path: focusBlockPath,
149
+ newPath: [focusBlockPath[0] + 1],
150
+ })
151
+
152
+ if (adjustedSelection) {
153
+ Transforms.select(editor, adjustedSelection)
154
+ } else {
155
+ Transforms.select(editor, currentSelection)
156
+ }
157
+
158
+ if (select === 'start') {
159
+ Transforms.select(editor, Editor.start(editor, focusBlockPath))
160
+ } else if (select === 'end') {
161
+ Transforms.select(editor, Editor.end(editor, focusBlockPath))
162
+ }
163
+ } else if (placement === 'after') {
164
+ const nextPath = [focusBlockPath[0] + 1]
165
+
166
+ const currentSelection = editor.selection
167
+ Transforms.insertNodes(editor, [block], {at: nextPath, select: false})
168
+ Transforms.select(editor, currentSelection)
169
+
170
+ if (select === 'start') {
171
+ Transforms.select(editor, Editor.start(editor, nextPath))
172
+ } else if (select === 'end') {
173
+ Transforms.select(editor, Editor.end(editor, nextPath))
174
+ }
175
+ } else {
176
+ // placement === 'auto'
177
+
178
+ const currentSelection = editor.selection
179
+ const focusBlockStartPoint = Editor.start(editor, focusBlockPath)
180
+
181
+ if (editor.isTextBlock(focusBlock) && editor.isTextBlock(block)) {
182
+ if (select === 'end') {
183
+ Transforms.insertFragment(editor, [block], {
184
+ voids: true,
185
+ })
186
+
187
+ return
188
+ }
189
+
190
+ Transforms.insertFragment(editor, [block], {
191
+ at: currentSelection,
192
+ voids: true,
193
+ })
194
+
195
+ if (select === 'start') {
196
+ if (Point.equals(currentSelection.anchor, focusBlockStartPoint)) {
197
+ Transforms.select(editor, Editor.start(editor, focusBlockPath))
198
+ } else {
199
+ Transforms.select(editor, currentSelection)
200
+ }
201
+ } else {
202
+ if (!Point.equals(currentSelection.anchor, focusBlockStartPoint)) {
203
+ Transforms.select(editor, currentSelection)
204
+ }
205
+ }
206
+ } else {
207
+ if (!editor.isTextBlock(focusBlock)) {
208
+ Transforms.insertNodes(editor, [block], {select: false})
209
+
210
+ const nextPath = [focusBlockPath[0] + 1]
211
+
212
+ if (select === 'start') {
213
+ Transforms.select(editor, Editor.start(editor, nextPath))
214
+ } else if (select === 'end') {
215
+ Transforms.select(editor, Editor.end(editor, nextPath))
216
+ }
217
+ } else {
218
+ const focusBlockStartPoint = Editor.start(editor, focusBlockPath)
219
+ const focusBlockEndPoint = Editor.end(editor, focusBlockPath)
220
+
221
+ if (Point.equals(currentSelection.anchor, focusBlockStartPoint)) {
222
+ Transforms.insertNodes(editor, [block], {
223
+ at: focusBlockPath,
224
+ select: false,
225
+ })
226
+
227
+ if (select === 'start' || select === 'end') {
228
+ Transforms.select(editor, Editor.start(editor, focusBlockPath))
229
+ }
230
+
231
+ if (isEqualToEmptyEditor([focusBlock], schema)) {
232
+ Transforms.removeNodes(editor, {at: Path.next(focusBlockPath)})
233
+ }
234
+ } else if (Point.equals(currentSelection.focus, focusBlockEndPoint)) {
235
+ const nextPath = [focusBlockPath[0] + 1]
236
+
237
+ Transforms.insertNodes(editor, [block], {
238
+ at: nextPath,
239
+ select: false,
240
+ })
241
+
242
+ if (select === 'start' || select === 'end') {
243
+ Transforms.select(editor, Editor.start(editor, nextPath))
244
+ }
245
+ } else {
246
+ const currentSelection = editor.selection
247
+ const [focusChild] = getFocusChild({editor})
248
+
249
+ if (focusChild && editor.isTextSpan(focusChild)) {
250
+ Transforms.insertFragment(editor, [block], {
251
+ at: currentSelection,
252
+ })
253
+
254
+ if (select === 'start' || select === 'end') {
255
+ Transforms.select(editor, [focusBlockPath[0] + 1])
256
+ } else {
257
+ Transforms.select(editor, currentSelection)
258
+ }
259
+ } else {
260
+ const nextPath = [focusBlockPath[0] + 1]
261
+ Transforms.insertNodes(editor, [block], {
262
+ at: nextPath,
263
+ select: false,
264
+ })
265
+ Transforms.select(editor, currentSelection)
266
+
267
+ if (select === 'start') {
268
+ Transforms.select(editor, Editor.start(editor, nextPath))
269
+ } else if (select === 'end') {
270
+ Transforms.select(editor, Editor.end(editor, nextPath))
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+ }
@@ -0,0 +1,33 @@
1
+ import {insertBlockActionImplementation} from './behavior.action.insert.block'
2
+ import type {BehaviorActionImplementation} from './behavior.actions'
3
+
4
+ export const insertTextBlockActionImplementation: BehaviorActionImplementation<
5
+ 'insert.text block'
6
+ > = ({context, action}) => {
7
+ insertBlockActionImplementation({
8
+ context,
9
+ action: {
10
+ type: 'insert.block',
11
+ block: {
12
+ _key: context.keyGenerator(),
13
+ _type: context.schema.block.name,
14
+ children: action.textBlock?.children?.map((child) => ({
15
+ ...child,
16
+ _key: context.keyGenerator(),
17
+ })) ?? [
18
+ {
19
+ _type: context.schema.span.name,
20
+ _key: context.keyGenerator(),
21
+ text: '',
22
+ marks: [],
23
+ },
24
+ ],
25
+ markDefs: [],
26
+ style: context.schema.styles[0].value ?? 'normal',
27
+ },
28
+ editor: action.editor,
29
+ placement: action.placement,
30
+ select: 'start',
31
+ },
32
+ })
33
+ }
@@ -0,0 +1,7 @@
1
+ import type {BehaviorActionImplementation} from './behavior.actions'
2
+
3
+ export const insertTextActionImplementation: BehaviorActionImplementation<
4
+ 'insert.text'
5
+ > = ({action}) => {
6
+ action.editor.insertText(action.text)
7
+ }
@@ -0,0 +1,48 @@
1
+ import {Path} from 'slate'
2
+ import {toSlatePath} from '../internal-utils/paths'
3
+ import {toPortableTextRange} from '../internal-utils/ranges'
4
+ import {isKeyedSegment} from '../utils'
5
+ import {moveBlockActionImplementation} from './behavior.action.move.block'
6
+ import type {BehaviorActionImplementation} from './behavior.actions'
7
+
8
+ export const moveBlockDownActionImplementation: BehaviorActionImplementation<
9
+ 'move.block down'
10
+ > = ({context, action}) => {
11
+ const at = [toSlatePath(action.at, action.editor)[0]]
12
+ const to = [Path.next(at)[0]]
13
+ const selection = toPortableTextRange(
14
+ action.editor.children,
15
+ {
16
+ anchor: {
17
+ path: to,
18
+ offset: 0,
19
+ },
20
+ focus: {
21
+ path: to,
22
+ offset: 0,
23
+ },
24
+ },
25
+ context.schema,
26
+ )
27
+
28
+ const destinationBlockKey = selection
29
+ ? isKeyedSegment(selection.focus.path[0])
30
+ ? selection.focus.path[0]._key
31
+ : undefined
32
+ : undefined
33
+
34
+ if (destinationBlockKey === undefined) {
35
+ console.error('Could not find destination block key')
36
+ return
37
+ }
38
+
39
+ moveBlockActionImplementation({
40
+ context,
41
+ action: {
42
+ type: 'move.block',
43
+ at: action.at,
44
+ to: [{_key: destinationBlockKey}],
45
+ editor: action.editor,
46
+ },
47
+ })
48
+ }
@@ -0,0 +1,53 @@
1
+ import {Path} from 'slate'
2
+ import {toSlatePath} from '../internal-utils/paths'
3
+ import {toPortableTextRange} from '../internal-utils/ranges'
4
+ import {isKeyedSegment} from '../utils'
5
+ import {moveBlockActionImplementation} from './behavior.action.move.block'
6
+ import type {BehaviorActionImplementation} from './behavior.actions'
7
+
8
+ export const moveBlockUpActionImplementation: BehaviorActionImplementation<
9
+ 'move.block up'
10
+ > = ({context, action}) => {
11
+ const at = [toSlatePath(action.at, action.editor)[0]]
12
+
13
+ if (!Path.hasPrevious(at)) {
14
+ return
15
+ }
16
+
17
+ const to = [Path.previous(at)[0]]
18
+ const selection = toPortableTextRange(
19
+ action.editor.children,
20
+ {
21
+ anchor: {
22
+ path: to,
23
+ offset: 0,
24
+ },
25
+ focus: {
26
+ path: to,
27
+ offset: 0,
28
+ },
29
+ },
30
+ context.schema,
31
+ )
32
+
33
+ const destinationBlockKey = selection
34
+ ? isKeyedSegment(selection.focus.path[0])
35
+ ? selection.focus.path[0]._key
36
+ : undefined
37
+ : undefined
38
+
39
+ if (destinationBlockKey === undefined) {
40
+ console.error('Could not find destination block key')
41
+ return
42
+ }
43
+
44
+ moveBlockActionImplementation({
45
+ context,
46
+ action: {
47
+ type: 'move.block',
48
+ at: action.at,
49
+ to: [{_key: destinationBlockKey}],
50
+ editor: action.editor,
51
+ },
52
+ })
53
+ }
@@ -0,0 +1,16 @@
1
+ import {Transforms} from 'slate'
2
+ import {toSlatePath} from '../internal-utils/paths'
3
+ import type {BehaviorActionImplementation} from './behavior.actions'
4
+
5
+ export const moveBlockActionImplementation: BehaviorActionImplementation<
6
+ 'move.block'
7
+ > = ({action}) => {
8
+ const at = [toSlatePath(action.at, action.editor)[0]]
9
+ const to = [toSlatePath(action.to, action.editor)[0]]
10
+
11
+ Transforms.moveNodes(action.editor, {
12
+ at,
13
+ to,
14
+ mode: 'highest',
15
+ })
16
+ }
@@ -0,0 +1,5 @@
1
+ import type {BehaviorActionImplementation} from './behavior.actions'
2
+
3
+ export const noopActionImplementation: BehaviorActionImplementation<
4
+ 'noop'
5
+ > = () => {}
@@ -0,0 +1,44 @@
1
+ import {Editor} from 'slate'
2
+ import {toPortableTextRange} from '../internal-utils/ranges'
3
+ import {selectActionImplementation} from './behavior.action.select'
4
+ import type {BehaviorActionImplementation} from './behavior.actions'
5
+
6
+ export const selectNextBlockActionImplementation: BehaviorActionImplementation<
7
+ 'select.next block'
8
+ > = ({context, action}) => {
9
+ if (!action.editor.selection) {
10
+ console.error('Unable to select previous block without a selection')
11
+ return
12
+ }
13
+
14
+ const blockPath = action.editor.selection.focus.path.slice(0, 1)
15
+ const nextBlockPath = [blockPath[0] + 1]
16
+
17
+ const position =
18
+ action.select === 'end'
19
+ ? Editor.end(action.editor, nextBlockPath)
20
+ : Editor.start(action.editor, nextBlockPath)
21
+
22
+ const newSelection = toPortableTextRange(
23
+ action.editor.children,
24
+ {
25
+ anchor: position,
26
+ focus: position,
27
+ },
28
+ context.schema,
29
+ )
30
+
31
+ if (!newSelection) {
32
+ console.error('Could not find selection for next block')
33
+ return
34
+ }
35
+
36
+ selectActionImplementation({
37
+ context,
38
+ action: {
39
+ type: 'select',
40
+ selection: newSelection,
41
+ editor: action.editor,
42
+ },
43
+ })
44
+ }
@@ -0,0 +1,48 @@
1
+ import {Editor, Path} from 'slate'
2
+ import {toPortableTextRange} from '../internal-utils/ranges'
3
+ import {selectActionImplementation} from './behavior.action.select'
4
+ import type {BehaviorActionImplementation} from './behavior.actions'
5
+
6
+ export const selectPreviousBlockActionImplementation: BehaviorActionImplementation<
7
+ 'select.previous block'
8
+ > = ({context, action}) => {
9
+ if (!action.editor.selection) {
10
+ console.error('Unable to select previous block without a selection')
11
+ return
12
+ }
13
+
14
+ const blockPath = action.editor.selection.focus.path.slice(0, 1)
15
+
16
+ if (!Path.hasPrevious(blockPath)) {
17
+ console.error("There's no previous block to select")
18
+ return
19
+ }
20
+
21
+ const position =
22
+ action.select === 'end'
23
+ ? Editor.end(action.editor, Path.previous(blockPath))
24
+ : Editor.start(action.editor, Path.previous(blockPath))
25
+
26
+ const newSelection = toPortableTextRange(
27
+ action.editor.children,
28
+ {
29
+ anchor: position,
30
+ focus: position,
31
+ },
32
+ context.schema,
33
+ )
34
+
35
+ if (!newSelection) {
36
+ console.error('Could not find selection for previous block')
37
+ return
38
+ }
39
+
40
+ selectActionImplementation({
41
+ context,
42
+ action: {
43
+ type: 'select',
44
+ selection: newSelection,
45
+ editor: action.editor,
46
+ },
47
+ })
48
+ }
@@ -0,0 +1,15 @@
1
+ import {Transforms} from 'slate'
2
+ import {toSlateRange} from '../internal-utils/ranges'
3
+ import type {BehaviorActionImplementation} from './behavior.actions'
4
+
5
+ export const selectActionImplementation: BehaviorActionImplementation<
6
+ 'select'
7
+ > = ({action}) => {
8
+ const newSelection = toSlateRange(action.selection, action.editor)
9
+
10
+ if (newSelection) {
11
+ Transforms.select(action.editor, newSelection)
12
+ } else {
13
+ Transforms.deselect(action.editor)
14
+ }
15
+ }
@@ -0,0 +1,9 @@
1
+ import type {BehaviorActionImplementation} from './behavior.actions'
2
+
3
+ export const serializationFailureActionImplementation: BehaviorActionImplementation<
4
+ 'serialization.failure'
5
+ > = ({action}) => {
6
+ console.warn(
7
+ `Serialization of ${action.mimeType} failed with reason "${action.reason}"`,
8
+ )
9
+ }
@@ -0,0 +1,14 @@
1
+ import {dataTransferSetActionImplementation} from './behavior.action.data-transfer-set'
2
+ import type {BehaviorActionImplementation} from './behavior.actions'
3
+
4
+ export const serializationSuccessActionImplementation: BehaviorActionImplementation<
5
+ 'serialization.success'
6
+ > = ({context, action}) => {
7
+ dataTransferSetActionImplementation({
8
+ context,
9
+ action: {
10
+ ...action,
11
+ type: 'data transfer.set',
12
+ },
13
+ })
14
+ }