@portabletext/editor 1.38.0 → 1.39.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 (47) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +24 -16
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +2 -2
  4. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
  5. package/lib/_chunks-cjs/editor-provider.cjs +19 -24
  6. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
  7. package/lib/_chunks-es/behavior.core.js +24 -16
  8. package/lib/_chunks-es/behavior.core.js.map +1 -1
  9. package/lib/_chunks-es/behavior.markdown.js +2 -2
  10. package/lib/_chunks-es/behavior.markdown.js.map +1 -1
  11. package/lib/_chunks-es/editor-provider.js +20 -25
  12. package/lib/_chunks-es/editor-provider.js.map +1 -1
  13. package/lib/behaviors/index.cjs +12 -12
  14. package/lib/behaviors/index.cjs.map +1 -1
  15. package/lib/behaviors/index.d.cts +1505 -2318
  16. package/lib/behaviors/index.d.ts +1505 -2318
  17. package/lib/behaviors/index.js +12 -12
  18. package/lib/behaviors/index.js.map +1 -1
  19. package/lib/index.cjs +43 -25
  20. package/lib/index.cjs.map +1 -1
  21. package/lib/index.d.cts +1084 -2011
  22. package/lib/index.d.ts +1084 -2011
  23. package/lib/index.js +43 -25
  24. package/lib/index.js.map +1 -1
  25. package/lib/plugins/index.d.cts +1084 -2011
  26. package/lib/plugins/index.d.ts +1084 -2011
  27. package/lib/selectors/index.d.cts +1084 -2011
  28. package/lib/selectors/index.d.ts +1084 -2011
  29. package/lib/utils/index.d.cts +1084 -2011
  30. package/lib/utils/index.d.ts +1084 -2011
  31. package/package.json +1 -1
  32. package/src/behavior-actions/behavior.action.serialization.success.ts +4 -1
  33. package/src/behaviors/behavior.code-editor.ts +4 -4
  34. package/src/behaviors/behavior.core.block-objects.ts +4 -4
  35. package/src/behaviors/behavior.core.decorators.ts +8 -8
  36. package/src/behaviors/behavior.core.lists.ts +4 -4
  37. package/src/behaviors/behavior.default.raise-soft-break.ts +3 -3
  38. package/src/behaviors/behavior.default.ts +10 -16
  39. package/src/behaviors/behavior.emoji-picker.ts +6 -6
  40. package/src/behaviors/behavior.links.ts +4 -4
  41. package/src/behaviors/behavior.markdown.ts +2 -2
  42. package/src/behaviors/behavior.types.ts +124 -77
  43. package/src/converters/converter.text-html.serialize.test.ts +4 -4
  44. package/src/converters/converter.text-plain.test.ts +6 -6
  45. package/src/converters/converter.types.ts +3 -3
  46. package/src/editor/Editable.tsx +41 -21
  47. package/src/editor/editor-machine.ts +26 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.38.0",
3
+ "version": "1.39.0",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -7,8 +7,11 @@ export const serializationSuccessActionImplementation: BehaviorActionImplementat
7
7
  dataTransferSetActionImplementation({
8
8
  context,
9
9
  action: {
10
- ...action,
11
10
  type: 'data transfer.set',
11
+ data: action.data,
12
+ dataTransfer: action.originEvent.originEvent.dataTransfer,
13
+ mimeType: action.mimeType,
14
+ editor: action.editor,
12
15
  },
13
16
  })
14
17
  }
@@ -16,11 +16,11 @@ export type CodeEditorBehaviorsConfig = {
16
16
  export function createCodeEditorBehaviors(config: CodeEditorBehaviorsConfig) {
17
17
  return [
18
18
  defineBehavior({
19
- on: 'key.down',
19
+ on: 'keyboard.keydown',
20
20
  guard: ({snapshot, event}) => {
21
21
  const isMoveUpShortcut = isHotkey(
22
22
  config.moveBlockUpShortcut,
23
- event.keyboardEvent,
23
+ event.originEvent,
24
24
  )
25
25
  const firstBlock = selectors.getFirstBlock(snapshot)
26
26
  const selectedBlocks = selectors.getSelectedBlocks(snapshot)
@@ -42,11 +42,11 @@ export function createCodeEditorBehaviors(config: CodeEditorBehaviorsConfig) {
42
42
  ],
43
43
  }),
44
44
  defineBehavior({
45
- on: 'key.down',
45
+ on: 'keyboard.keydown',
46
46
  guard: ({snapshot, event}) => {
47
47
  const isMoveDownShortcut = isHotkey(
48
48
  config.moveBlockDownShortcut,
49
- event.keyboardEvent,
49
+ event.originEvent,
50
50
  )
51
51
  const lastBlock = selectors.getLastBlock(snapshot)
52
52
  const selectedBlocks = selectors.getSelectedBlocks(snapshot)
@@ -5,9 +5,9 @@ import {isEmptyTextBlock} from '../utils/util.is-empty-text-block'
5
5
  import {defineBehavior, raise} from './behavior.types'
6
6
 
7
7
  const arrowDownOnLonelyBlockObject = defineBehavior({
8
- on: 'key.down',
8
+ on: 'keyboard.keydown',
9
9
  guard: ({snapshot, event}) => {
10
- const isArrowDown = isHotkey('ArrowDown', event.keyboardEvent)
10
+ const isArrowDown = isHotkey('ArrowDown', event.originEvent)
11
11
  const focusBlockObject = selectors.getFocusBlockObject(snapshot)
12
12
  const nextBlock = selectors.getNextBlock(snapshot)
13
13
 
@@ -17,9 +17,9 @@ const arrowDownOnLonelyBlockObject = defineBehavior({
17
17
  })
18
18
 
19
19
  const arrowUpOnLonelyBlockObject = defineBehavior({
20
- on: 'key.down',
20
+ on: 'keyboard.keydown',
21
21
  guard: ({snapshot, event}) => {
22
- const isArrowUp = isHotkey('ArrowUp', event.keyboardEvent)
22
+ const isArrowUp = isHotkey('ArrowUp', event.originEvent)
23
23
  const focusBlockObject = selectors.getFocusBlockObject(snapshot)
24
24
  const previousBlock = selectors.getPreviousBlock(snapshot)
25
25
 
@@ -3,27 +3,27 @@ import {defineBehavior, raise} from './behavior.types'
3
3
 
4
4
  export const coreDecoratorBehaviors = {
5
5
  strongShortcut: defineBehavior({
6
- on: 'key.down',
6
+ on: 'keyboard.keydown',
7
7
  guard: ({snapshot, event}) =>
8
- isHotkey('mod+b', event.keyboardEvent) &&
8
+ isHotkey('mod+b', event.originEvent) &&
9
9
  snapshot.context.schema.decorators.some(
10
10
  (decorator) => decorator.value === 'strong',
11
11
  ),
12
12
  actions: [() => [raise({type: 'decorator.toggle', decorator: 'strong'})]],
13
13
  }),
14
14
  emShortcut: defineBehavior({
15
- on: 'key.down',
15
+ on: 'keyboard.keydown',
16
16
  guard: ({snapshot, event}) =>
17
- isHotkey('mod+i', event.keyboardEvent) &&
17
+ isHotkey('mod+i', event.originEvent) &&
18
18
  snapshot.context.schema.decorators.some(
19
19
  (decorator) => decorator.value === 'em',
20
20
  ),
21
21
  actions: [() => [raise({type: 'decorator.toggle', decorator: 'em'})]],
22
22
  }),
23
23
  underlineShortcut: defineBehavior({
24
- on: 'key.down',
24
+ on: 'keyboard.keydown',
25
25
  guard: ({snapshot, event}) =>
26
- isHotkey('mod+u', event.keyboardEvent) &&
26
+ isHotkey('mod+u', event.originEvent) &&
27
27
  snapshot.context.schema.decorators.some(
28
28
  (decorator) => decorator.value === 'underline',
29
29
  ),
@@ -32,9 +32,9 @@ export const coreDecoratorBehaviors = {
32
32
  ],
33
33
  }),
34
34
  codeShortcut: defineBehavior({
35
- on: 'key.down',
35
+ on: 'keyboard.keydown',
36
36
  guard: ({snapshot, event}) =>
37
- isHotkey("mod+'", event.keyboardEvent) &&
37
+ isHotkey("mod+'", event.originEvent) &&
38
38
  snapshot.context.schema.decorators.some(
39
39
  (decorator) => decorator.value === 'code',
40
40
  ),
@@ -102,9 +102,9 @@ const clearListOnEnter = defineBehavior({
102
102
  })
103
103
 
104
104
  const indentListOnTab = defineBehavior({
105
- on: 'key.down',
105
+ on: 'keyboard.keydown',
106
106
  guard: ({snapshot, event}) => {
107
- const isTab = isHotkey('Tab', event.keyboardEvent)
107
+ const isTab = isHotkey('Tab', event.originEvent)
108
108
 
109
109
  if (!isTab) {
110
110
  return false
@@ -147,9 +147,9 @@ const indentListOnTab = defineBehavior({
147
147
  })
148
148
 
149
149
  const unindentListOnShiftTab = defineBehavior({
150
- on: 'key.down',
150
+ on: 'keyboard.keydown',
151
151
  guard: ({snapshot, event}) => {
152
- const isShiftTab = isHotkey('Shift+Tab', event.keyboardEvent)
152
+ const isShiftTab = isHotkey('Shift+Tab', event.originEvent)
153
153
 
154
154
  if (!isShiftTab) {
155
155
  return false
@@ -4,10 +4,10 @@ import {defineBehavior, raise} from './behavior.types'
4
4
  /**
5
5
  * On WebKit, Shift+Enter results in an `insertParagraph` input event rather
6
6
  * than an `insertLineBreak` input event. This Behavior makes sure we catch
7
- * that `key.down` event beforehand and raise an `insert.soft break` manually.
7
+ * that `keyboard.keydown` event beforehand and raise an `insert.soft break` manually.
8
8
  */
9
9
  export const raiseInsertSoftBreak = defineBehavior({
10
- on: 'key.down',
11
- guard: ({event}) => keyIs.lineBreak(event.keyboardEvent),
10
+ on: 'keyboard.keydown',
11
+ guard: ({event}) => keyIs.lineBreak(event.originEvent),
12
12
  actions: [() => [raise({type: 'insert.soft break'})]],
13
13
  })
@@ -89,7 +89,9 @@ const raiseDeserializationSuccessOrFailure = defineBehavior({
89
89
  guard: ({snapshot, event}) => {
90
90
  const deserializeEvents = snapshot.context.converters.flatMap(
91
91
  (converter) => {
92
- const data = event.dataTransfer.getData(converter.mimeType)
92
+ const data = event.originEvent.originEvent.dataTransfer.getData(
93
+ converter.mimeType,
94
+ )
93
95
 
94
96
  if (!data) {
95
97
  return []
@@ -128,7 +130,6 @@ const raiseDeserializationSuccessOrFailure = defineBehavior({
128
130
  ({event}, deserializeEvent) => [
129
131
  raise({
130
132
  ...deserializeEvent,
131
- dataTransfer: event.dataTransfer,
132
133
  originEvent: event.originEvent,
133
134
  }),
134
135
  ],
@@ -164,7 +165,6 @@ const raiseSerializationSuccessOrFailure = defineBehavior({
164
165
  return raise({
165
166
  ...serializeEvent,
166
167
  originEvent: event.originEvent,
167
- dataTransfer: event.dataTransfer,
168
168
  })
169
169
  }),
170
170
  ],
@@ -172,7 +172,7 @@ const raiseSerializationSuccessOrFailure = defineBehavior({
172
172
 
173
173
  export const defaultBehaviors = [
174
174
  defineBehavior({
175
- on: 'copy',
175
+ on: 'clipboard.copy',
176
176
  guard: ({snapshot}) => {
177
177
  const focusSpan = selectors.getFocusSpan(snapshot)
178
178
  const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
@@ -182,19 +182,18 @@ export const defaultBehaviors = [
182
182
  actions: [() => [{type: 'noop'}]],
183
183
  }),
184
184
  defineBehavior({
185
- on: 'copy',
185
+ on: 'clipboard.copy',
186
186
  actions: [
187
187
  ({event}) => [
188
188
  raise({
189
189
  type: 'serialize',
190
- dataTransfer: event.data,
191
190
  originEvent: event,
192
191
  }),
193
192
  ],
194
193
  ],
195
194
  }),
196
195
  defineBehavior({
197
- on: 'cut',
196
+ on: 'clipboard.cut',
198
197
  guard: ({snapshot}) => {
199
198
  const focusSpan = selectors.getFocusSpan(snapshot)
200
199
  const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
@@ -204,7 +203,7 @@ export const defaultBehaviors = [
204
203
  actions: [() => [{type: 'noop'}]],
205
204
  }),
206
205
  defineBehavior({
207
- on: 'cut',
206
+ on: 'clipboard.cut',
208
207
  guard: ({snapshot}) => {
209
208
  return snapshot.context.selection
210
209
  ? {
@@ -216,7 +215,6 @@ export const defaultBehaviors = [
216
215
  ({event}, {selection}) => [
217
216
  raise({
218
217
  type: 'serialize',
219
- dataTransfer: event.dataTransfer,
220
218
  originEvent: event,
221
219
  }),
222
220
  raise({
@@ -232,7 +230,6 @@ export const defaultBehaviors = [
232
230
  ({event}) => [
233
231
  raise({
234
232
  type: 'serialize',
235
- dataTransfer: event.dataTransfer,
236
233
  originEvent: event,
237
234
  }),
238
235
  ],
@@ -245,7 +242,7 @@ export const defaultBehaviors = [
245
242
  raise({
246
243
  type: 'data transfer.set',
247
244
  data: event.data,
248
- dataTransfer: event.dataTransfer,
245
+ dataTransfer: event.originEvent.originEvent.dataTransfer,
249
246
  mimeType: event.mimeType,
250
247
  }),
251
248
  ],
@@ -275,7 +272,6 @@ export const defaultBehaviors = [
275
272
  ({event}) => [
276
273
  raise({
277
274
  type: 'deserialize',
278
- dataTransfer: event.dataTransfer,
279
275
  originEvent: event,
280
276
  }),
281
277
  ],
@@ -367,7 +363,7 @@ export const defaultBehaviors = [
367
363
  ],
368
364
  }),
369
365
  defineBehavior({
370
- on: 'paste',
366
+ on: 'clipboard.paste',
371
367
  guard: ({snapshot}) => {
372
368
  return snapshot.context.selection &&
373
369
  selectors.isSelectionExpanded(snapshot)
@@ -382,19 +378,17 @@ export const defaultBehaviors = [
382
378
  }),
383
379
  raise({
384
380
  type: 'deserialize',
385
- dataTransfer: event.data,
386
381
  originEvent: event,
387
382
  }),
388
383
  ],
389
384
  ],
390
385
  }),
391
386
  defineBehavior({
392
- on: 'paste',
387
+ on: 'clipboard.paste',
393
388
  actions: [
394
389
  ({event}) => [
395
390
  raise({
396
391
  type: 'deserialize',
397
- dataTransfer: event.data,
398
392
  originEvent: event,
399
393
  }),
400
394
  ],
@@ -148,7 +148,7 @@ export function createEmojiPickerBehaviors<TEmojiMatch>(
148
148
  ],
149
149
  }),
150
150
  defineBehavior({
151
- on: 'key.down',
151
+ on: 'keyboard.keydown',
152
152
  guard: ({snapshot, event}) => {
153
153
  const matches = emojiPickerActor.getSnapshot().context.matches
154
154
 
@@ -156,14 +156,14 @@ export function createEmojiPickerBehaviors<TEmojiMatch>(
156
156
  return false
157
157
  }
158
158
 
159
- const isEscape = isHotkey('Escape', event.keyboardEvent)
159
+ const isEscape = isHotkey('Escape', event.originEvent)
160
160
 
161
161
  if (isEscape) {
162
162
  return {action: 'reset' as const}
163
163
  }
164
164
 
165
- const isEnter = isHotkey('Enter', event.keyboardEvent)
166
- const isTab = isHotkey('Tab', event.keyboardEvent)
165
+ const isEnter = isHotkey('Enter', event.originEvent)
166
+ const isTab = isHotkey('Tab', event.originEvent)
167
167
 
168
168
  if (isEnter || isTab) {
169
169
  const selectedIndex =
@@ -200,8 +200,8 @@ export function createEmojiPickerBehaviors<TEmojiMatch>(
200
200
  return false
201
201
  }
202
202
 
203
- const isArrowDown = isHotkey('ArrowDown', event.keyboardEvent)
204
- const isArrowUp = isHotkey('ArrowUp', event.keyboardEvent)
203
+ const isArrowDown = isHotkey('ArrowDown', event.originEvent)
204
+ const isArrowUp = isHotkey('ArrowUp', event.originEvent)
205
205
 
206
206
  if (isArrowDown && matches.length > 0) {
207
207
  return {action: 'navigate down' as const}
@@ -18,10 +18,10 @@ export type LinkBehaviorsConfig = {
18
18
  */
19
19
  export function createLinkBehaviors(config: LinkBehaviorsConfig) {
20
20
  const pasteLinkOnSelection = defineBehavior({
21
- on: 'paste',
21
+ on: 'clipboard.paste',
22
22
  guard: ({snapshot, event}) => {
23
23
  const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
24
- const text = event.data.getData('text/plain')
24
+ const text = event.originEvent.dataTransfer.getData('text/plain')
25
25
  const url = looksLikeUrl(text) ? text : undefined
26
26
  const annotation =
27
27
  url !== undefined
@@ -44,7 +44,7 @@ export function createLinkBehaviors(config: LinkBehaviorsConfig) {
44
44
  ],
45
45
  })
46
46
  const pasteLinkAtCaret = defineBehavior({
47
- on: 'paste',
47
+ on: 'clipboard.paste',
48
48
  guard: ({snapshot, event}) => {
49
49
  const focusSpan = selectors.getFocusSpan(snapshot)
50
50
  const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
@@ -53,7 +53,7 @@ export function createLinkBehaviors(config: LinkBehaviorsConfig) {
53
53
  return false
54
54
  }
55
55
 
56
- const text = event.data.getData('text/plain')
56
+ const text = event.originEvent.dataTransfer.getData('text/plain')
57
57
  const url = looksLikeUrl(text) ? text : undefined
58
58
  const annotation =
59
59
  url !== undefined
@@ -216,9 +216,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
216
216
  ],
217
217
  })
218
218
  const automaticHrOnPaste = defineBehavior({
219
- on: 'paste',
219
+ on: 'clipboard.paste',
220
220
  guard: ({snapshot, event}) => {
221
- const text = event.data.getData('text/plain')
221
+ const text = event.originEvent.dataTransfer.getData('text/plain')
222
222
  const hrRegExp = /^(---)$|(___)$|(\*\*\*)$/gm
223
223
  const hrCharacters = text.match(hrRegExp)?.[0]
224
224
  const hrObject = config.horizontalRuleObject?.(snapshot.context)
@@ -206,75 +206,110 @@ export type SyntheticBehaviorEvent =
206
206
  'type',
207
207
  'deserialization.failure' | 'deserialization.success'
208
208
  > & {
209
- dataTransfer: DataTransfer
210
- originEvent: Omit<
211
- PickFromUnion<NativeBehaviorEvent, 'type', 'drag.drop' | 'paste'>,
212
- 'dataTransfer'
209
+ originEvent: PickFromUnion<
210
+ NativeBehaviorEvent,
211
+ 'type',
212
+ 'drag.drop' | 'clipboard.paste'
213
213
  >
214
214
  })
215
215
  | {
216
216
  type: 'serialization.success'
217
217
  mimeType: MIMEType
218
218
  data: string
219
- dataTransfer: DataTransfer
220
- originEvent: Omit<
221
- PickFromUnion<
222
- NativeBehaviorEvent,
223
- 'type',
224
- 'copy' | 'cut' | 'drag.dragstart'
225
- >,
226
- 'dataTransfer'
219
+ originEvent: PickFromUnion<
220
+ NativeBehaviorEvent,
221
+ 'type',
222
+ 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart'
227
223
  >
228
224
  }
229
225
  | {
230
226
  type: 'serialization.failure'
231
227
  mimeType: MIMEType
232
228
  reason: string
233
- dataTransfer: DataTransfer
234
- originEvent: Omit<
235
- PickFromUnion<
236
- NativeBehaviorEvent,
237
- 'type',
238
- 'copy' | 'cut' | 'drag.dragstart'
239
- >,
240
- 'dataTransfer'
229
+ originEvent: PickFromUnion<
230
+ NativeBehaviorEvent,
231
+ 'type',
232
+ 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart'
241
233
  >
242
234
  }
243
235
 
244
236
  export type InsertPlacement = 'auto' | 'after' | 'before'
245
237
 
238
+ type ClipboardBehaviorEvent =
239
+ | {
240
+ type: 'clipboard.copy'
241
+ originEvent: {
242
+ dataTransfer: DataTransfer
243
+ }
244
+ position: EventPosition
245
+ }
246
+ | {
247
+ type: 'clipboard.cut'
248
+ originEvent: {
249
+ dataTransfer: DataTransfer
250
+ }
251
+ position: EventPosition
252
+ }
253
+ | {
254
+ type: 'clipboard.paste'
255
+ originEvent: {
256
+ dataTransfer: DataTransfer
257
+ }
258
+ position: EventPosition
259
+ }
260
+
261
+ export function isClipboardBehaviorEvent(
262
+ event: BehaviorEvent,
263
+ ): event is ClipboardBehaviorEvent {
264
+ return event.type.startsWith('clipboard.')
265
+ }
266
+
246
267
  type DragBehaviorEvent =
247
268
  | {
248
269
  type: 'drag.dragstart'
249
- dataTransfer: DataTransfer
270
+ originEvent: {
271
+ dataTransfer: DataTransfer
272
+ }
250
273
  position: EventPosition
251
274
  }
252
275
  | {
253
276
  type: 'drag.drag'
254
- dataTransfer: DataTransfer
277
+ originEvent: {
278
+ dataTransfer: DataTransfer
279
+ }
255
280
  }
256
281
  | {
257
282
  type: 'drag.dragend'
258
- dataTransfer: DataTransfer
283
+ originEvent: {
284
+ dataTransfer: DataTransfer
285
+ }
259
286
  }
260
287
  | {
261
288
  type: 'drag.dragenter'
262
- dataTransfer: DataTransfer
289
+ originEvent: {
290
+ dataTransfer: DataTransfer
291
+ }
263
292
  position: EventPosition
264
293
  }
265
294
  | {
266
295
  type: 'drag.dragover'
267
- dataTransfer: DataTransfer
296
+ originEvent: {
297
+ dataTransfer: DataTransfer
298
+ }
268
299
  position: EventPosition
269
300
  }
270
301
  | {
271
302
  type: 'drag.drop'
272
- dataTransfer: DataTransfer
303
+ originEvent: {
304
+ dataTransfer: DataTransfer
305
+ }
273
306
  position: EventPosition
274
307
  }
275
308
  | {
276
309
  type: 'drag.dragleave'
277
- dataTransfer: DataTransfer
310
+ originEvent: {
311
+ dataTransfer: DataTransfer
312
+ }
278
313
  }
279
314
 
280
315
  export function isDragBehaviorEvent(
@@ -283,25 +318,43 @@ export function isDragBehaviorEvent(
283
318
  return event.type.startsWith('drag.')
284
319
  }
285
320
 
321
+ export type KeyboardBehaviorEvent =
322
+ | {
323
+ type: 'keyboard.keydown'
324
+ originEvent: Pick<
325
+ KeyboardEvent,
326
+ 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
327
+ >
328
+ }
329
+ | {
330
+ type: 'keyboard.keyup'
331
+ originEvent: Pick<
332
+ KeyboardEvent,
333
+ 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
334
+ >
335
+ }
336
+
337
+ export function isKeyboardBehaviorEvent(
338
+ event: BehaviorEvent,
339
+ ): event is KeyboardBehaviorEvent {
340
+ return event.type.startsWith('keyboard.')
341
+ }
342
+
286
343
  export type DataBehaviorEvent =
287
344
  | {
288
345
  type: 'deserialize'
289
- dataTransfer: DataTransfer
290
- originEvent: Omit<
291
- PickFromUnion<NativeBehaviorEvent, 'type', 'drag.drop' | 'paste'>,
292
- 'dataTransfer'
346
+ originEvent: PickFromUnion<
347
+ NativeBehaviorEvent,
348
+ 'type',
349
+ 'drag.drop' | 'clipboard.paste'
293
350
  >
294
351
  }
295
352
  | {
296
353
  type: 'serialize'
297
- dataTransfer: DataTransfer
298
- originEvent: Omit<
299
- PickFromUnion<
300
- NativeBehaviorEvent,
301
- 'type',
302
- 'copy' | 'cut' | 'drag.dragstart'
303
- >,
304
- 'dataTransfer'
354
+ originEvent: PickFromUnion<
355
+ NativeBehaviorEvent,
356
+ 'type',
357
+ 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart'
305
358
  >
306
359
  }
307
360
 
@@ -320,36 +373,9 @@ export function isMouseBehaviorEvent(
320
373
  * @beta
321
374
  */
322
375
  export type NativeBehaviorEvent =
323
- | {
324
- type: 'copy'
325
- data: DataTransfer
326
- position: EventPosition
327
- }
328
- | {
329
- type: 'cut'
330
- dataTransfer: DataTransfer
331
- position: EventPosition
332
- }
333
- | {
334
- type: 'key.down'
335
- keyboardEvent: Pick<
336
- KeyboardEvent,
337
- 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
338
- >
339
- }
340
- | {
341
- type: 'key.up'
342
- keyboardEvent: Pick<
343
- KeyboardEvent,
344
- 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
345
- >
346
- }
376
+ | ClipboardBehaviorEvent
377
+ | KeyboardBehaviorEvent
347
378
  | MouseBehaviorEvent
348
- | {
349
- type: 'paste'
350
- data: DataTransfer
351
- position: EventPosition
352
- }
353
379
  | DragBehaviorEvent
354
380
 
355
381
  /**
@@ -412,7 +438,10 @@ export type BehaviorEvent =
412
438
  | NativeBehaviorEvent
413
439
  | CustomBehaviorEvent
414
440
  | {type: '*'}
441
+ | {type: 'clipboard.*'}
415
442
  | {type: 'drag.*'}
443
+ | {type: 'keyboard.*'}
444
+ | {type: 'mouse.*'}
416
445
 
417
446
  /**
418
447
  * @beta
@@ -422,9 +451,15 @@ export type Behavior<
422
451
  TGuardResponse = true,
423
452
  TBehaviorEvent extends BehaviorEvent = TBehaviorEventType extends '*'
424
453
  ? BehaviorEvent
425
- : TBehaviorEventType extends 'drag.*'
426
- ? DragBehaviorEvent
427
- : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
454
+ : TBehaviorEventType extends 'clipboard.*'
455
+ ? ClipboardBehaviorEvent
456
+ : TBehaviorEventType extends 'drag.*'
457
+ ? DragBehaviorEvent
458
+ : TBehaviorEventType extends 'keyboard.*'
459
+ ? KeyboardBehaviorEvent
460
+ : TBehaviorEventType extends 'mouse.*'
461
+ ? MouseBehaviorEvent
462
+ : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
428
463
  > = {
429
464
  /**
430
465
  * The internal editor event that triggers this behavior.
@@ -502,9 +537,15 @@ export function defineBehavior<
502
537
  ? CustomBehaviorEvent<TPayload, TType>
503
538
  : TBehaviorEventType extends '*'
504
539
  ? OmitFromUnion<BehaviorEvent, 'type', '*'>
505
- : TBehaviorEventType extends `drag.*`
506
- ? DragBehaviorEvent
507
- : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>
540
+ : TBehaviorEventType extends `clipboard.*`
541
+ ? ClipboardBehaviorEvent
542
+ : TBehaviorEventType extends `drag.*`
543
+ ? DragBehaviorEvent
544
+ : TBehaviorEventType extends 'keyboard.*'
545
+ ? KeyboardBehaviorEvent
546
+ : TBehaviorEventType extends 'mouse.*'
547
+ ? MouseBehaviorEvent
548
+ : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>
508
549
  >,
509
550
  ): Behavior
510
551
  export function defineBehavior<
@@ -516,9 +557,15 @@ export function defineBehavior<
516
557
  ? CustomBehaviorEvent<TPayload, TType>
517
558
  : TBehaviorEventType extends '*'
518
559
  ? OmitFromUnion<BehaviorEvent, 'type', '*'>
519
- : TBehaviorEventType extends `drag.*`
520
- ? DragBehaviorEvent
521
- : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
560
+ : TBehaviorEventType extends `clipboard.*`
561
+ ? ClipboardBehaviorEvent
562
+ : TBehaviorEventType extends `drag.*`
563
+ ? DragBehaviorEvent
564
+ : TBehaviorEventType extends 'keyboard.*'
565
+ ? KeyboardBehaviorEvent
566
+ : TBehaviorEventType extends 'mouse.*'
567
+ ? MouseBehaviorEvent
568
+ : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
522
569
  >(
523
570
  behavior: Behavior<TBehaviorEventType, TGuardResponse, TBehaviorEvent>,
524
571
  ): Behavior {