@portabletext/editor 1.24.0 → 1.26.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 (89) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +283 -64
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/selector.get-text-before.cjs +8 -8
  4. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  5. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +412 -0
  6. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -0
  7. package/lib/_chunks-cjs/util.is-empty-text-block.cjs +2 -2
  8. package/lib/_chunks-cjs/util.is-empty-text-block.cjs.map +1 -1
  9. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs +46 -0
  10. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +1 -0
  11. package/lib/_chunks-cjs/util.reverse-selection.cjs +0 -16
  12. package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
  13. package/lib/_chunks-es/behavior.core.js +259 -40
  14. package/lib/_chunks-es/behavior.core.js.map +1 -1
  15. package/lib/_chunks-es/selector.get-text-before.js +2 -2
  16. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +414 -0
  17. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -0
  18. package/lib/_chunks-es/util.is-empty-text-block.js +1 -1
  19. package/lib/_chunks-es/util.is-equal-selection-points.js +47 -0
  20. package/lib/_chunks-es/util.is-equal-selection-points.js.map +1 -0
  21. package/lib/_chunks-es/util.reverse-selection.js +0 -16
  22. package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
  23. package/lib/behaviors/index.cjs +27 -27
  24. package/lib/behaviors/index.cjs.map +1 -1
  25. package/lib/behaviors/index.d.cts +2208 -171
  26. package/lib/behaviors/index.d.ts +2208 -171
  27. package/lib/behaviors/index.js +1 -1
  28. package/lib/index.cjs +306 -298
  29. package/lib/index.cjs.map +1 -1
  30. package/lib/index.d.cts +10499 -521
  31. package/lib/index.d.ts +10499 -521
  32. package/lib/index.js +302 -294
  33. package/lib/index.js.map +1 -1
  34. package/lib/selectors/index.cjs +26 -171
  35. package/lib/selectors/index.cjs.map +1 -1
  36. package/lib/selectors/index.d.cts +16 -0
  37. package/lib/selectors/index.d.ts +16 -0
  38. package/lib/selectors/index.js +5 -151
  39. package/lib/selectors/index.js.map +1 -1
  40. package/lib/utils/index.cjs +5 -3
  41. package/lib/utils/index.cjs.map +1 -1
  42. package/lib/utils/index.d.cts +19 -0
  43. package/lib/utils/index.d.ts +19 -0
  44. package/lib/utils/index.js +4 -2
  45. package/package.json +6 -6
  46. package/src/behavior-actions/behavior.action-utils.insert-block.ts +3 -3
  47. package/src/behavior-actions/behavior.action.block.set.ts +23 -0
  48. package/src/behavior-actions/behavior.action.block.unset.ts +21 -0
  49. package/src/behavior-actions/behavior.action.insert-break.ts +2 -69
  50. package/src/behavior-actions/behavior.action.insert.block.ts +29 -0
  51. package/src/behavior-actions/behavior.actions.ts +116 -96
  52. package/src/behaviors/behavior.core.annotations.ts +29 -0
  53. package/src/behaviors/behavior.core.block-objects.ts +13 -13
  54. package/src/behaviors/behavior.core.decorators.ts +19 -0
  55. package/src/behaviors/behavior.core.insert-break.ts +122 -0
  56. package/src/behaviors/behavior.core.lists.ts +57 -23
  57. package/src/behaviors/behavior.core.style.ts +19 -0
  58. package/src/behaviors/behavior.core.ts +18 -2
  59. package/src/behaviors/behavior.types.ts +103 -88
  60. package/src/converters/converter.json.ts +4 -4
  61. package/src/converters/converter.portable-text.deserialize.test.ts +1 -1
  62. package/src/converters/converter.portable-text.ts +4 -4
  63. package/src/converters/converter.text-html.deserialize.test.ts +1 -1
  64. package/src/converters/converter.text-html.serialize.test.ts +1 -1
  65. package/src/converters/converter.text-html.ts +4 -4
  66. package/src/converters/converter.text-plain.test.ts +1 -1
  67. package/src/converters/converter.text-plain.ts +3 -3
  68. package/src/converters/{converter.ts → converter.types.ts} +6 -0
  69. package/src/editor/create-editor.ts +50 -7
  70. package/src/editor/editor-machine.ts +46 -3
  71. package/src/editor/editor-snapshot.ts +1 -1
  72. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +2 -2
  73. package/src/editor/plugins/create-with-event-listeners.ts +41 -106
  74. package/src/selectors/index.ts +2 -0
  75. package/src/selectors/selector.is-at-the-end-of-block.ts +22 -0
  76. package/src/selectors/selector.is-at-the-start-of-block.ts +25 -0
  77. package/src/selectors/selector.is-selection-collapsed.ts +6 -2
  78. package/src/utils/index.ts +2 -0
  79. package/src/utils/util.get-block-end-point.ts +34 -0
  80. package/src/utils/util.is-equal-selection-points.ts +13 -0
  81. package/lib/_chunks-cjs/selector.is-selection-collapsed.cjs +0 -231
  82. package/lib/_chunks-cjs/selector.is-selection-collapsed.cjs.map +0 -1
  83. package/lib/_chunks-cjs/util.is-keyed-segment.cjs +0 -6
  84. package/lib/_chunks-cjs/util.is-keyed-segment.cjs.map +0 -1
  85. package/lib/_chunks-es/selector.is-selection-collapsed.js +0 -232
  86. package/lib/_chunks-es/selector.is-selection-collapsed.js.map +0 -1
  87. package/lib/_chunks-es/util.is-keyed-segment.js +0 -7
  88. package/lib/_chunks-es/util.is-keyed-segment.js.map +0 -1
  89. /package/src/converters/{converters.ts → converters.core.ts} +0 -0
@@ -28,6 +28,8 @@ import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
28
28
  import type {PickFromUnion} from '../type-utils'
29
29
  import {blockOffsetToSpanSelectionPoint} from '../utils/util.block-offset'
30
30
  import {insertBlock} from './behavior.action-utils.insert-block'
31
+ import {blockSetBehaviorActionImplementation} from './behavior.action.block.set'
32
+ import {blockUnsetBehaviorActionImplementation} from './behavior.action.block.unset'
31
33
  import {dataTransferSetActionImplementation} from './behavior.action.data-transfer-set'
32
34
  import {insertBlockObjectActionImplementation} from './behavior.action.insert-block-object'
33
35
  import {insertBlocksActionImplementation} from './behavior.action.insert-blocks'
@@ -37,6 +39,7 @@ import {
37
39
  } from './behavior.action.insert-break'
38
40
  import {insertInlineObjectActionImplementation} from './behavior.action.insert-inline-object'
39
41
  import {insertSpanActionImplementation} from './behavior.action.insert-span'
42
+ import {insertBlockActionImplementation} from './behavior.action.insert.block'
40
43
  import {
41
44
  addListItemActionImplementation,
42
45
  removeListItemActionImplementation,
@@ -74,6 +77,8 @@ const behaviorActionImplementations: BehaviorActionImplementations = {
74
77
  'annotation.add': addAnnotationActionImplementation,
75
78
  'annotation.remove': removeAnnotationActionImplementation,
76
79
  'annotation.toggle': toggleAnnotationActionImplementation,
80
+ 'block.set': blockSetBehaviorActionImplementation,
81
+ 'block.unset': blockUnsetBehaviorActionImplementation,
77
82
  'blur': ({action}) => {
78
83
  ReactEditor.blur(action.editor)
79
84
  },
@@ -161,6 +166,7 @@ const behaviorActionImplementations: BehaviorActionImplementations = {
161
166
  },
162
167
  })
163
168
  },
169
+ 'insert.block': insertBlockActionImplementation,
164
170
  'insert.blocks': insertBlocksActionImplementation,
165
171
  'insert.block object': insertBlockObjectActionImplementation,
166
172
  'insert.break': insertBreakActionImplementation,
@@ -308,309 +314,323 @@ export function performAction({
308
314
  action: BehaviorAction
309
315
  }) {
310
316
  switch (action.type) {
311
- case 'annotation.toggle': {
312
- behaviorActionImplementations['annotation.toggle']({
317
+ case 'noop': {
318
+ behaviorActionImplementations.noop({
313
319
  context,
314
320
  action,
315
321
  })
316
322
  break
317
323
  }
318
- case 'decorator.add': {
319
- behaviorActionImplementations['decorator.add']({
324
+ case 'effect': {
325
+ behaviorActionImplementations.effect({
320
326
  context,
321
327
  action,
322
328
  })
323
329
  break
324
330
  }
325
- case 'decorator.remove': {
326
- behaviorActionImplementations['decorator.remove']({
331
+ default: {
332
+ performDefaultAction({context, action})
333
+ }
334
+ }
335
+ }
336
+
337
+ function performDefaultAction({
338
+ context,
339
+ action,
340
+ }: {
341
+ context: BehaviorActionImplementationContext
342
+ action: PickFromUnion<BehaviorAction, 'type', SyntheticBehaviorEvent['type']>
343
+ }) {
344
+ switch (action.type) {
345
+ case 'annotation.add': {
346
+ behaviorActionImplementations['annotation.add']({
327
347
  context,
328
348
  action,
329
349
  })
330
350
  break
331
351
  }
332
- case 'delete.block': {
333
- behaviorActionImplementations['delete.block']({
352
+ case 'annotation.remove': {
353
+ behaviorActionImplementations['annotation.remove']({
334
354
  context,
335
355
  action,
336
356
  })
337
357
  break
338
358
  }
339
- case 'delete.text': {
340
- behaviorActionImplementations['delete.text']({
359
+ case 'annotation.toggle': {
360
+ behaviorActionImplementations['annotation.toggle']({
341
361
  context,
342
362
  action,
343
363
  })
344
364
  break
345
365
  }
346
- case 'insert.span': {
347
- behaviorActionImplementations['insert.span']({
366
+ case 'block.set': {
367
+ behaviorActionImplementations['block.set']({
348
368
  context,
349
369
  action,
350
370
  })
351
371
  break
352
372
  }
353
- case 'insert.text block': {
354
- behaviorActionImplementations['insert.text block']({
373
+ case 'block.unset': {
374
+ behaviorActionImplementations['block.unset']({
355
375
  context,
356
376
  action,
357
377
  })
358
378
  break
359
379
  }
360
- case 'list item.add': {
361
- behaviorActionImplementations['list item.add']({
380
+ case 'blur': {
381
+ behaviorActionImplementations.blur({
362
382
  context,
363
383
  action,
364
384
  })
365
385
  break
366
386
  }
367
- case 'list item.remove': {
368
- behaviorActionImplementations['list item.remove']({
387
+ case 'data transfer.set': {
388
+ behaviorActionImplementations['data transfer.set']({
369
389
  context,
370
390
  action,
371
391
  })
372
392
  break
373
393
  }
374
- case 'move.block': {
375
- behaviorActionImplementations['move.block']({
394
+ case 'decorator.add': {
395
+ behaviorActionImplementations['decorator.add']({
376
396
  context,
377
397
  action,
378
398
  })
379
399
  break
380
400
  }
381
- case 'move.block down': {
382
- behaviorActionImplementations['move.block down']({
401
+ case 'decorator.remove': {
402
+ behaviorActionImplementations['decorator.remove']({
383
403
  context,
384
404
  action,
385
405
  })
386
406
  break
387
407
  }
388
- case 'move.block up': {
389
- behaviorActionImplementations['move.block up']({
408
+ case 'decorator.toggle': {
409
+ behaviorActionImplementations['decorator.toggle']({
390
410
  context,
391
411
  action,
392
412
  })
393
413
  break
394
414
  }
395
- case 'noop': {
396
- behaviorActionImplementations.noop({
415
+ case 'delete.backward': {
416
+ behaviorActionImplementations['delete.backward']({
397
417
  context,
398
418
  action,
399
419
  })
400
420
  break
401
421
  }
402
- case 'effect': {
403
- behaviorActionImplementations.effect({
422
+ case 'delete.block': {
423
+ behaviorActionImplementations['delete.block']({
404
424
  context,
405
425
  action,
406
426
  })
407
427
  break
408
428
  }
409
- case 'select': {
410
- behaviorActionImplementations.select({
429
+ case 'delete.forward': {
430
+ behaviorActionImplementations['delete.forward']({
411
431
  context,
412
432
  action,
413
433
  })
414
434
  break
415
435
  }
416
- case 'select.previous block': {
417
- behaviorActionImplementations['select.previous block']({
436
+ case 'delete.text': {
437
+ behaviorActionImplementations['delete.text']({
418
438
  context,
419
439
  action,
420
440
  })
421
441
  break
422
442
  }
423
- case 'select.next block': {
424
- behaviorActionImplementations['select.next block']({
443
+ case 'deserialization.failure': {
444
+ behaviorActionImplementations['deserialization.failure']({
425
445
  context,
426
446
  action,
427
447
  })
428
448
  break
429
449
  }
430
- case 'style.add': {
431
- behaviorActionImplementations['style.add']({
450
+ case 'deserialization.success': {
451
+ behaviorActionImplementations['deserialization.success']({
432
452
  context,
433
453
  action,
434
454
  })
435
455
  break
436
456
  }
437
- case 'style.remove': {
438
- behaviorActionImplementations['style.remove']({
457
+ case 'focus': {
458
+ behaviorActionImplementations.focus({
439
459
  context,
440
460
  action,
441
461
  })
442
462
  break
443
463
  }
444
- case 'text block.set': {
445
- behaviorActionImplementations['text block.set']({
464
+ case 'insert.block': {
465
+ behaviorActionImplementations['insert.block']({
446
466
  context,
447
467
  action,
448
468
  })
449
469
  break
450
470
  }
451
- case 'text block.unset': {
452
- behaviorActionImplementations['text block.unset']({
471
+ case 'insert.blocks': {
472
+ behaviorActionImplementations['insert.blocks']({
453
473
  context,
454
474
  action,
455
475
  })
456
476
  break
457
477
  }
458
- default: {
459
- performDefaultAction({context, action})
478
+ case 'insert.block object': {
479
+ behaviorActionImplementations['insert.block object']({
480
+ context,
481
+ action,
482
+ })
483
+ break
460
484
  }
461
- }
462
- }
463
-
464
- function performDefaultAction({
465
- context,
466
- action,
467
- }: {
468
- context: BehaviorActionImplementationContext
469
- action: PickFromUnion<BehaviorAction, 'type', SyntheticBehaviorEvent['type']>
470
- }) {
471
- switch (action.type) {
472
- case 'annotation.add': {
473
- behaviorActionImplementations['annotation.add']({
485
+ case 'insert.inline object': {
486
+ behaviorActionImplementations['insert.inline object']({
474
487
  context,
475
488
  action,
476
489
  })
477
490
  break
478
491
  }
479
- case 'annotation.remove': {
480
- behaviorActionImplementations['annotation.remove']({
492
+ case 'insert.break': {
493
+ behaviorActionImplementations['insert.break']({
481
494
  context,
482
495
  action,
483
496
  })
484
497
  break
485
498
  }
486
- case 'blur': {
487
- behaviorActionImplementations.blur({
499
+ case 'insert.soft break': {
500
+ behaviorActionImplementations['insert.soft break']({
488
501
  context,
489
502
  action,
490
503
  })
491
504
  break
492
505
  }
493
- case 'data transfer.set': {
494
- behaviorActionImplementations['data transfer.set']({
506
+ case 'insert.span': {
507
+ behaviorActionImplementations['insert.span']({
495
508
  context,
496
509
  action,
497
510
  })
498
511
  break
499
512
  }
500
- case 'decorator.toggle': {
501
- behaviorActionImplementations['decorator.toggle']({
513
+ case 'insert.text': {
514
+ behaviorActionImplementations['insert.text']({
502
515
  context,
503
516
  action,
504
517
  })
505
518
  break
506
519
  }
507
- case 'delete.backward': {
508
- behaviorActionImplementations['delete.backward']({
520
+ case 'insert.text block': {
521
+ behaviorActionImplementations['insert.text block']({
509
522
  context,
510
523
  action,
511
524
  })
512
525
  break
513
526
  }
514
- case 'delete.forward': {
515
- behaviorActionImplementations['delete.forward']({
527
+ case 'list item.add': {
528
+ behaviorActionImplementations['list item.add']({
516
529
  context,
517
530
  action,
518
531
  })
519
532
  break
520
533
  }
521
- case 'deserialization.failure': {
522
- behaviorActionImplementations['deserialization.failure']({
534
+ case 'list item.remove': {
535
+ behaviorActionImplementations['list item.remove']({
523
536
  context,
524
537
  action,
525
538
  })
526
539
  break
527
540
  }
528
- case 'deserialization.success': {
529
- behaviorActionImplementations['deserialization.success']({
541
+ case 'list item.toggle': {
542
+ behaviorActionImplementations['list item.toggle']({
530
543
  context,
531
544
  action,
532
545
  })
533
546
  break
534
547
  }
535
- case 'focus': {
536
- behaviorActionImplementations.focus({
548
+ case 'move.block': {
549
+ behaviorActionImplementations['move.block']({
537
550
  context,
538
551
  action,
539
552
  })
540
553
  break
541
554
  }
542
- case 'insert.blocks': {
543
- behaviorActionImplementations['insert.blocks']({
555
+ case 'move.block down': {
556
+ behaviorActionImplementations['move.block down']({
544
557
  context,
545
558
  action,
546
559
  })
547
560
  break
548
561
  }
549
- case 'insert.block object': {
550
- behaviorActionImplementations['insert.block object']({
562
+ case 'move.block up': {
563
+ behaviorActionImplementations['move.block up']({
551
564
  context,
552
565
  action,
553
566
  })
554
567
  break
555
568
  }
556
- case 'insert.inline object': {
557
- behaviorActionImplementations['insert.inline object']({
569
+ case 'select': {
570
+ behaviorActionImplementations.select({
558
571
  context,
559
572
  action,
560
573
  })
561
574
  break
562
575
  }
563
- case 'insert.break': {
564
- behaviorActionImplementations['insert.break']({
576
+ case 'select.previous block': {
577
+ behaviorActionImplementations['select.previous block']({
565
578
  context,
566
579
  action,
567
580
  })
568
581
  break
569
582
  }
570
- case 'insert.soft break': {
571
- behaviorActionImplementations['insert.soft break']({
583
+ case 'select.next block': {
584
+ behaviorActionImplementations['select.next block']({
572
585
  context,
573
586
  action,
574
587
  })
575
588
  break
576
589
  }
577
- case 'insert.text': {
578
- behaviorActionImplementations['insert.text']({
590
+ case 'serialization.failure': {
591
+ behaviorActionImplementations['serialization.failure']({
579
592
  context,
580
593
  action,
581
594
  })
582
595
  break
583
596
  }
584
- case 'list item.toggle': {
585
- behaviorActionImplementations['list item.toggle']({
597
+ case 'serialization.success': {
598
+ behaviorActionImplementations['serialization.success']({
586
599
  context,
587
600
  action,
588
601
  })
589
602
  break
590
603
  }
591
- case 'select': {
592
- behaviorActionImplementations.select({
604
+ case 'style.add': {
605
+ behaviorActionImplementations['style.add']({
593
606
  context,
594
607
  action,
595
608
  })
596
609
  break
597
610
  }
598
- case 'serialization.failure': {
599
- behaviorActionImplementations['serialization.failure']({
611
+ case 'style.remove': {
612
+ behaviorActionImplementations['style.remove']({
600
613
  context,
601
614
  action,
602
615
  })
603
616
  break
604
617
  }
605
- case 'serialization.success': {
606
- behaviorActionImplementations['serialization.success']({
618
+ case 'style.toggle': {
619
+ behaviorActionImplementations['style.toggle']({
620
+ context,
621
+ action,
622
+ })
623
+ break
624
+ }
625
+ case 'text block.set': {
626
+ behaviorActionImplementations['text block.set']({
607
627
  context,
608
628
  action,
609
629
  })
610
630
  break
611
631
  }
612
632
  default: {
613
- behaviorActionImplementations['style.toggle']({
633
+ behaviorActionImplementations['text block.unset']({
614
634
  context,
615
635
  action,
616
636
  })
@@ -0,0 +1,29 @@
1
+ import * as selectors from '../selectors'
2
+ import {defineBehavior, raise} from './behavior.types'
3
+
4
+ const toggleAnnotationOff = defineBehavior({
5
+ on: 'annotation.toggle',
6
+ guard: ({context, event}) =>
7
+ selectors.isActiveAnnotation(event.annotation.name)({context}),
8
+ actions: [
9
+ ({event}) => [
10
+ raise({type: 'annotation.remove', annotation: event.annotation}),
11
+ ],
12
+ ],
13
+ })
14
+
15
+ const toggleAnnotationOn = defineBehavior({
16
+ on: 'annotation.toggle',
17
+ guard: ({context, event}) =>
18
+ !selectors.isActiveAnnotation(event.annotation.name)({context}),
19
+ actions: [
20
+ ({event}) => [
21
+ raise({type: 'annotation.add', annotation: event.annotation}),
22
+ ],
23
+ ],
24
+ })
25
+
26
+ export const coreAnnotationBehaviors = {
27
+ toggleAnnotationOff,
28
+ toggleAnnotationOn,
29
+ }
@@ -2,7 +2,7 @@ import {isPortableTextTextBlock} from '@sanity/types'
2
2
  import {isHotkey} from '../internal-utils/is-hotkey'
3
3
  import * as selectors from '../selectors'
4
4
  import {isEmptyTextBlock} from '../utils/util.is-empty-text-block'
5
- import {defineBehavior} from './behavior.types'
5
+ import {defineBehavior, raise} from './behavior.types'
6
6
 
7
7
  const arrowDownOnLonelyBlockObject = defineBehavior({
8
8
  on: 'key.down',
@@ -13,7 +13,7 @@ const arrowDownOnLonelyBlockObject = defineBehavior({
13
13
 
14
14
  return isArrowDown && focusBlockObject && !nextBlock
15
15
  },
16
- actions: [() => [{type: 'insert.text block', placement: 'after'}]],
16
+ actions: [() => [raise({type: 'insert.text block', placement: 'after'})]],
17
17
  })
18
18
 
19
19
  const arrowUpOnLonelyBlockObject = defineBehavior({
@@ -27,8 +27,8 @@ const arrowUpOnLonelyBlockObject = defineBehavior({
27
27
  },
28
28
  actions: [
29
29
  () => [
30
- {type: 'insert.text block', placement: 'before'},
31
- {type: 'select.previous block'},
30
+ raise({type: 'insert.text block', placement: 'before'}),
31
+ raise({type: 'select.previous block'}),
32
32
  ],
33
33
  ],
34
34
  })
@@ -41,7 +41,7 @@ const breakingBlockObject = defineBehavior({
41
41
 
42
42
  return collapsedSelection && focusBlockObject !== undefined
43
43
  },
44
- actions: [() => [{type: 'insert.text block', placement: 'after'}]],
44
+ actions: [() => [raise({type: 'insert.text block', placement: 'after'})]],
45
45
  })
46
46
 
47
47
  const deletingEmptyTextBlockAfterBlockObject = defineBehavior({
@@ -66,17 +66,17 @@ const deletingEmptyTextBlockAfterBlockObject = defineBehavior({
66
66
  },
67
67
  actions: [
68
68
  (_, {focusTextBlock, previousBlock}) => [
69
- {
69
+ raise({
70
70
  type: 'delete.block',
71
71
  blockPath: focusTextBlock.path,
72
- },
73
- {
72
+ }),
73
+ raise({
74
74
  type: 'select',
75
75
  selection: {
76
76
  anchor: {path: previousBlock.path, offset: 0},
77
77
  focus: {path: previousBlock.path, offset: 0},
78
78
  },
79
- },
79
+ }),
80
80
  ],
81
81
  ],
82
82
  })
@@ -103,17 +103,17 @@ const deletingEmptyTextBlockBeforeBlockObject = defineBehavior({
103
103
  },
104
104
  actions: [
105
105
  (_, {focusTextBlock, nextBlock}) => [
106
- {
106
+ raise({
107
107
  type: 'delete.block',
108
108
  blockPath: focusTextBlock.path,
109
- },
110
- {
109
+ }),
110
+ raise({
111
111
  type: 'select',
112
112
  selection: {
113
113
  anchor: {path: nextBlock.path, offset: 0},
114
114
  focus: {path: nextBlock.path, offset: 0},
115
115
  },
116
- },
116
+ }),
117
117
  ],
118
118
  ],
119
119
  })
@@ -1,7 +1,26 @@
1
1
  import {isHotkey} from '../internal-utils/is-hotkey'
2
+ import * as selectors from '../selectors'
2
3
  import {defineBehavior, raise} from './behavior.types'
3
4
 
4
5
  export const coreDecoratorBehaviors = {
6
+ toggleDecoratorOff: defineBehavior({
7
+ on: 'decorator.toggle',
8
+ guard: ({context, event}) =>
9
+ selectors.isActiveDecorator(event.decorator)({context}),
10
+ actions: [
11
+ ({event}) => [
12
+ raise({type: 'decorator.remove', decorator: event.decorator}),
13
+ ],
14
+ ],
15
+ }),
16
+ toggleDecoratorOn: defineBehavior({
17
+ on: 'decorator.toggle',
18
+ guard: ({context, event}) =>
19
+ !selectors.isActiveDecorator(event.decorator)({context}),
20
+ actions: [
21
+ ({event}) => [raise({type: 'decorator.add', decorator: event.decorator})],
22
+ ],
23
+ }),
5
24
  strongShortcut: defineBehavior({
6
25
  on: 'key.down',
7
26
  guard: ({context, event}) =>