@portabletext/editor 1.11.3 → 1.12.1

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.
package/lib/index.js CHANGED
@@ -117,7 +117,13 @@ function getNextBlock(context) {
117
117
  return nextBlock;
118
118
  }
119
119
  function isEmptyTextBlock(block) {
120
- return block.children.length === 1 && block.children[0].text === "";
120
+ if (!types.isPortableTextTextBlock(block))
121
+ return !1;
122
+ const onlyText = block.children.every(types.isPortableTextSpan), blockText = getTextBlockText(block);
123
+ return onlyText && blockText === "";
124
+ }
125
+ function getTextBlockText(block) {
126
+ return block.children.map((child) => child.text ?? "").join("");
121
127
  }
122
128
  const breakingBlockObject = {
123
129
  on: "insert break",
@@ -126,7 +132,7 @@ const breakingBlockObject = {
126
132
  }) => !!getFocusBlockObject(context),
127
133
  actions: [() => [{
128
134
  type: "insert text block",
129
- decorators: []
135
+ placement: "after"
130
136
  }]]
131
137
  }, deletingEmptyTextBlockAfterBlockObject = {
132
138
  on: "delete backward",
@@ -143,17 +149,8 @@ const breakingBlockObject = {
143
149
  focusTextBlock,
144
150
  previousBlock
145
151
  }) => [{
146
- type: "delete",
147
- selection: {
148
- anchor: {
149
- path: focusTextBlock.path,
150
- offset: 0
151
- },
152
- focus: {
153
- path: focusTextBlock.path,
154
- offset: 0
155
- }
156
- }
152
+ type: "delete block",
153
+ blockPath: focusTextBlock.path
157
154
  }, {
158
155
  type: "select",
159
156
  selection: {
@@ -182,17 +179,8 @@ const breakingBlockObject = {
182
179
  focusTextBlock,
183
180
  nextBlock
184
181
  }) => [{
185
- type: "delete",
186
- selection: {
187
- anchor: {
188
- path: focusTextBlock.path,
189
- offset: 0
190
- },
191
- focus: {
192
- path: focusTextBlock.path,
193
- offset: 0
194
- }
195
- }
182
+ type: "delete block",
183
+ blockPath: focusTextBlock.path
196
184
  }, {
197
185
  type: "select",
198
186
  selection: {
@@ -355,20 +343,138 @@ function looksLikeUrl(text) {
355
343
  }
356
344
  return looksLikeUrl2;
357
345
  }
358
- function isPortableTextSpan(node) {
359
- return node._type === "span" && "text" in node && typeof node.text == "string" && (typeof node.marks > "u" || Array.isArray(node.marks) && node.marks.every((mark) => typeof mark == "string"));
346
+ function blockOffsetToSpanSelectionPoint({
347
+ value,
348
+ blockOffset
349
+ }) {
350
+ let offsetLeft = blockOffset.offset, selectionPoint;
351
+ for (const block of value)
352
+ if (block._key === blockOffset.path[0]._key && types.isPortableTextTextBlock(block)) {
353
+ for (const child of block.children)
354
+ if (types.isPortableTextSpan(child)) {
355
+ if (offsetLeft === 0) {
356
+ selectionPoint = {
357
+ path: [...blockOffset.path, "children", {
358
+ _key: child._key
359
+ }],
360
+ offset: 0
361
+ };
362
+ break;
363
+ }
364
+ if (offsetLeft <= child.text.length) {
365
+ selectionPoint = {
366
+ path: [...blockOffset.path, "children", {
367
+ _key: child._key
368
+ }],
369
+ offset: offsetLeft
370
+ };
371
+ break;
372
+ }
373
+ offsetLeft -= child.text.length;
374
+ }
375
+ }
376
+ return selectionPoint;
360
377
  }
361
- function isPortableTextBlock(node) {
362
- return (
363
- // A block doesn't _have_ to be named 'block' - to differentiate between
364
- // allowed child types and marks, one might name them differently
365
- typeof node._type == "string" && // Toolkit-types like nested spans are @-prefixed
366
- node._type[0] !== "@" && // `markDefs` isn't _required_ per say, but if it's there, it needs to be an array
367
- (!("markDefs" in node) || !node.markDefs || Array.isArray(node.markDefs) && // Every mark definition needs to have an `_key` to be mappable in child spans
368
- node.markDefs.every((def) => typeof def._key == "string")) && // `children` is required and needs to be an array
369
- "children" in node && Array.isArray(node.children) && // All children are objects with `_type` (usually spans, but can contain other stuff)
370
- node.children.every((child) => typeof child == "object" && "_type" in child)
371
- );
378
+ function spanSelectionPointToBlockOffset({
379
+ value,
380
+ selectionPoint
381
+ }) {
382
+ let offset = 0;
383
+ for (const block of value)
384
+ if (block._key === selectionPoint.path[0]._key && types.isPortableTextTextBlock(block)) {
385
+ for (const child of block.children)
386
+ if (types.isPortableTextSpan(child)) {
387
+ if (child._key === selectionPoint.path[2]._key)
388
+ return {
389
+ path: [{
390
+ _key: block._key
391
+ }],
392
+ offset: offset + selectionPoint.offset
393
+ };
394
+ offset += child.text.length;
395
+ }
396
+ }
397
+ }
398
+ function isKeyedSegment$1(segment) {
399
+ return typeof segment == "object" && segment !== null && "_key" in segment;
400
+ }
401
+ function reverseSelection(selection) {
402
+ return selection && (selection.backward ? {
403
+ anchor: selection.focus,
404
+ focus: selection.anchor,
405
+ backward: !1
406
+ } : {
407
+ anchor: selection.focus,
408
+ focus: selection.anchor,
409
+ backward: !0
410
+ });
411
+ }
412
+ function getSelectionText({
413
+ value,
414
+ selection
415
+ }) {
416
+ let text = "";
417
+ if (!value || !selection)
418
+ return text;
419
+ const forwardSelection = selection.backward ? reverseSelection(selection) : selection;
420
+ if (!forwardSelection)
421
+ return text;
422
+ for (const block of value)
423
+ if (!(isKeyedSegment$1(forwardSelection.anchor.path[0]) && block._key !== forwardSelection.anchor.path[0]._key) && types.isPortableTextTextBlock(block)) {
424
+ for (const child of block.children)
425
+ if (types.isPortableTextSpan(child)) {
426
+ if (isKeyedSegment$1(forwardSelection.anchor.path[2]) && child._key === forwardSelection.anchor.path[2]._key && isKeyedSegment$1(forwardSelection.focus.path[2]) && child._key === forwardSelection.focus.path[2]._key) {
427
+ text = text + child.text.slice(forwardSelection.anchor.offset, forwardSelection.focus.offset);
428
+ break;
429
+ }
430
+ if (isKeyedSegment$1(forwardSelection.anchor.path[2]) && child._key === forwardSelection.anchor.path[2]._key) {
431
+ text = text + child.text.slice(forwardSelection.anchor.offset);
432
+ continue;
433
+ }
434
+ if (isKeyedSegment$1(forwardSelection.focus.path[2]) && child._key === forwardSelection.focus.path[2]._key) {
435
+ text = text + child.text.slice(0, forwardSelection.focus.offset);
436
+ break;
437
+ }
438
+ }
439
+ if (isKeyedSegment$1(forwardSelection.focus.path[0]) && block._key === forwardSelection.focus.path[0]._key)
440
+ break;
441
+ }
442
+ return text;
443
+ }
444
+ function getStartPoint({
445
+ node,
446
+ path
447
+ }) {
448
+ return types.isPortableTextTextBlock(node) ? {
449
+ path: [...path, "children", {
450
+ _key: node.children[0]._key
451
+ }],
452
+ offset: 0
453
+ } : {
454
+ path,
455
+ offset: 0
456
+ };
457
+ }
458
+ function getBlockTextBefore({
459
+ value,
460
+ point
461
+ }) {
462
+ const key = isKeyedSegment$1(point.path[0]) ? point.path[0]._key : void 0, block = key ? value.find((block2) => block2._key === key) : void 0;
463
+ if (!block)
464
+ return "";
465
+ const startPoint = getStartPoint({
466
+ node: block,
467
+ path: [{
468
+ _key: block._key
469
+ }]
470
+ });
471
+ return getSelectionText({
472
+ value,
473
+ selection: {
474
+ anchor: startPoint,
475
+ focus: point
476
+ }
477
+ });
372
478
  }
373
479
  function createMarkdownBehaviors(config) {
374
480
  const automaticBlockquoteOnSpace = {
@@ -382,12 +488,24 @@ function createMarkdownBehaviors(config) {
382
488
  const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
383
489
  if (!selectionCollapsed || !focusTextBlock || !focusSpan)
384
490
  return !1;
385
- const caretAtTheEndOfQuote = context.selection.focus.offset === 1, looksLikeMarkdownQuote = /^>/.test(focusSpan.node.text), blockquoteStyle = config.blockquoteStyle?.({
491
+ const blockOffset = spanSelectionPointToBlockOffset({
492
+ value: context.value,
493
+ selectionPoint: {
494
+ path: [{
495
+ _key: focusTextBlock.node._key
496
+ }, "children", {
497
+ _key: focusSpan.node._key
498
+ }],
499
+ offset: context.selection.focus.offset
500
+ }
501
+ });
502
+ if (!blockOffset)
503
+ return !1;
504
+ const blockText = getTextBlockText(focusTextBlock.node), caretAtTheEndOfQuote = blockOffset.offset === 1, looksLikeMarkdownQuote = /^>/.test(blockText), blockquoteStyle = config.blockquoteStyle?.({
386
505
  schema: context.schema
387
506
  });
388
507
  return caretAtTheEndOfQuote && looksLikeMarkdownQuote && blockquoteStyle !== void 0 ? {
389
508
  focusTextBlock,
390
- focusSpan,
391
509
  style: blockquoteStyle
392
510
  } : !1;
393
511
  },
@@ -396,7 +514,6 @@ function createMarkdownBehaviors(config) {
396
514
  text: " "
397
515
  }], (_, {
398
516
  focusTextBlock,
399
- focusSpan,
400
517
  style
401
518
  }) => [{
402
519
  type: "unset block",
@@ -407,19 +524,17 @@ function createMarkdownBehaviors(config) {
407
524
  style,
408
525
  paths: [focusTextBlock.path]
409
526
  }, {
410
- type: "delete",
411
- selection: {
412
- anchor: {
413
- path: focusSpan.path,
414
- offset: 0
415
- },
416
- focus: {
417
- path: focusSpan.path,
418
- offset: 2
419
- }
527
+ type: "delete text",
528
+ anchor: {
529
+ path: focusTextBlock.path,
530
+ offset: 0
531
+ },
532
+ focus: {
533
+ path: focusTextBlock.path,
534
+ offset: 2
420
535
  }
421
536
  }]]
422
- }, automaticBreak = {
537
+ }, automaticHr = {
423
538
  on: "insert text",
424
539
  guard: ({
425
540
  context,
@@ -428,16 +543,29 @@ function createMarkdownBehaviors(config) {
428
543
  const hrCharacter = event.text === "-" ? "-" : event.text === "*" ? "*" : event.text === "_" ? "_" : void 0;
429
544
  if (hrCharacter === void 0)
430
545
  return !1;
431
- const breakObject = config.horizontalRuleObject?.({
546
+ const hrObject = config.horizontalRuleObject?.({
432
547
  schema: context.schema
433
548
  }), focusBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context);
434
- if (!breakObject || !focusBlock || !selectionCollapsed)
549
+ if (!hrObject || !focusBlock || !selectionCollapsed)
435
550
  return !1;
436
- const onlyText = focusBlock.node.children.every(isPortableTextSpan), blockText = focusBlock.node.children.map((child) => child.text ?? "").join("");
437
- return onlyText && blockText === `${hrCharacter}${hrCharacter}` ? {
438
- breakObject,
551
+ const textBefore = getBlockTextBefore({
552
+ value: context.value,
553
+ point: context.selection.focus
554
+ }), hrBlockOffsets = {
555
+ anchor: {
556
+ path: focusBlock.path,
557
+ offset: 0
558
+ },
559
+ focus: {
560
+ path: focusBlock.path,
561
+ offset: 3
562
+ }
563
+ };
564
+ return textBefore === `${hrCharacter}${hrCharacter}` ? {
565
+ hrObject,
439
566
  focusBlock,
440
- hrCharacter
567
+ hrCharacter,
568
+ hrBlockOffsets
441
569
  } : !1;
442
570
  },
443
571
  actions: [(_, {
@@ -446,26 +574,56 @@ function createMarkdownBehaviors(config) {
446
574
  type: "insert text",
447
575
  text: hrCharacter
448
576
  }], (_, {
449
- breakObject,
450
- focusBlock
577
+ hrObject,
578
+ hrBlockOffsets
451
579
  }) => [{
452
580
  type: "insert block object",
453
- ...breakObject
454
- }, {
455
- type: "delete",
456
- selection: {
457
- anchor: {
458
- path: focusBlock.path,
459
- offset: 0
460
- },
461
- focus: {
462
- path: focusBlock.path,
463
- offset: 0
464
- }
465
- }
581
+ placement: "before",
582
+ blockObject: hrObject
466
583
  }, {
584
+ type: "delete text",
585
+ ...hrBlockOffsets
586
+ }]]
587
+ }, automaticHrOnPaste = {
588
+ on: "paste",
589
+ guard: ({
590
+ context,
591
+ event
592
+ }) => {
593
+ const text = event.clipboardData.getData("text/plain"), hrRegExp = /^(---)$|(___)$|(\*\*\*)$/gm, hrCharacters = text.match(hrRegExp)?.[0], hrObject = config.horizontalRuleObject?.({
594
+ schema: context.schema
595
+ }), focusBlock = getFocusBlock(context);
596
+ return !hrCharacters || !hrObject || !focusBlock ? !1 : {
597
+ hrCharacters,
598
+ hrObject,
599
+ focusBlock
600
+ };
601
+ },
602
+ actions: [(_, {
603
+ hrCharacters
604
+ }) => [{
605
+ type: "insert text",
606
+ text: hrCharacters
607
+ }], (_, {
608
+ hrObject,
609
+ focusBlock
610
+ }) => types.isPortableTextTextBlock(focusBlock.node) ? [{
467
611
  type: "insert text block",
468
- decorators: []
612
+ textBlock: {
613
+ children: focusBlock.node.children
614
+ },
615
+ placement: "after"
616
+ }, {
617
+ type: "insert block object",
618
+ blockObject: hrObject,
619
+ placement: "after"
620
+ }, {
621
+ type: "delete block",
622
+ blockPath: focusBlock.path
623
+ }] : [{
624
+ type: "insert block object",
625
+ blockObject: hrObject,
626
+ placement: "after"
469
627
  }]]
470
628
  }, automaticHeadingOnSpace = {
471
629
  on: "insert text",
@@ -478,8 +636,21 @@ function createMarkdownBehaviors(config) {
478
636
  const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
479
637
  if (!selectionCollapsed || !focusTextBlock || !focusSpan)
480
638
  return !1;
481
- const markdownHeadingSearch = /^#+/.exec(focusSpan.node.text), level = markdownHeadingSearch ? markdownHeadingSearch[0].length : void 0;
482
- if (context.selection.focus.offset !== level)
639
+ const blockOffset = spanSelectionPointToBlockOffset({
640
+ value: context.value,
641
+ selectionPoint: {
642
+ path: [{
643
+ _key: focusTextBlock.node._key
644
+ }, "children", {
645
+ _key: focusSpan.node._key
646
+ }],
647
+ offset: context.selection.focus.offset
648
+ }
649
+ });
650
+ if (!blockOffset)
651
+ return !1;
652
+ const blockText = getTextBlockText(focusTextBlock.node), markdownHeadingSearch = /^#+/.exec(blockText), level = markdownHeadingSearch ? markdownHeadingSearch[0].length : void 0;
653
+ if (blockOffset.offset !== level)
483
654
  return !1;
484
655
  const style = level !== void 0 ? config.headingStyle?.({
485
656
  schema: context.schema,
@@ -487,7 +658,6 @@ function createMarkdownBehaviors(config) {
487
658
  }) : void 0;
488
659
  return level !== void 0 && style !== void 0 ? {
489
660
  focusTextBlock,
490
- focusSpan,
491
661
  style,
492
662
  level
493
663
  } : !1;
@@ -497,7 +667,6 @@ function createMarkdownBehaviors(config) {
497
667
  text: " "
498
668
  }], (_, {
499
669
  focusTextBlock,
500
- focusSpan,
501
670
  style,
502
671
  level
503
672
  }) => [{
@@ -509,16 +678,14 @@ function createMarkdownBehaviors(config) {
509
678
  style,
510
679
  paths: [focusTextBlock.path]
511
680
  }, {
512
- type: "delete",
513
- selection: {
514
- anchor: {
515
- path: focusSpan.path,
516
- offset: 0
517
- },
518
- focus: {
519
- path: focusSpan.path,
520
- offset: level + 1
521
- }
681
+ type: "delete text",
682
+ anchor: {
683
+ path: focusTextBlock.path,
684
+ offset: 0
685
+ },
686
+ focus: {
687
+ path: focusTextBlock.path,
688
+ offset: level + 1
522
689
  }
523
690
  }]]
524
691
  }, clearStyleOnBackspace = {
@@ -556,15 +723,27 @@ function createMarkdownBehaviors(config) {
556
723
  const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
557
724
  if (!selectionCollapsed || !focusTextBlock || !focusSpan)
558
725
  return !1;
559
- const defaultStyle = config.defaultStyle?.({
726
+ const blockOffset = spanSelectionPointToBlockOffset({
727
+ value: context.value,
728
+ selectionPoint: {
729
+ path: [{
730
+ _key: focusTextBlock.node._key
731
+ }, "children", {
732
+ _key: focusSpan.node._key
733
+ }],
734
+ offset: context.selection.focus.offset
735
+ }
736
+ });
737
+ if (!blockOffset)
738
+ return !1;
739
+ const blockText = getTextBlockText(focusTextBlock.node), defaultStyle = config.defaultStyle?.({
560
740
  schema: context.schema
561
- }), looksLikeUnorderedList = /^(-|\*)/.test(focusSpan.node.text), unorderedListStyle = config.unorderedListStyle?.({
741
+ }), looksLikeUnorderedList = /^(-|\*)/.test(blockText), unorderedListStyle = config.unorderedListStyle?.({
562
742
  schema: context.schema
563
- }), caretAtTheEndOfUnorderedList = context.selection.focus.offset === 1;
743
+ }), caretAtTheEndOfUnorderedList = blockOffset.offset === 1;
564
744
  if (defaultStyle && caretAtTheEndOfUnorderedList && looksLikeUnorderedList && unorderedListStyle !== void 0)
565
745
  return {
566
746
  focusTextBlock,
567
- focusSpan,
568
747
  listItem: unorderedListStyle,
569
748
  listItemLength: 1,
570
749
  style: defaultStyle
@@ -574,7 +753,6 @@ function createMarkdownBehaviors(config) {
574
753
  }), caretAtTheEndOfOrderedList = context.selection.focus.offset === 2;
575
754
  return defaultStyle && caretAtTheEndOfOrderedList && looksLikeOrderedList && orderedListStyle !== void 0 ? {
576
755
  focusTextBlock,
577
- focusSpan,
578
756
  listItem: orderedListStyle,
579
757
  listItemLength: 2,
580
758
  style: defaultStyle
@@ -585,7 +763,6 @@ function createMarkdownBehaviors(config) {
585
763
  text: " "
586
764
  }], (_, {
587
765
  focusTextBlock,
588
- focusSpan,
589
766
  style,
590
767
  listItem,
591
768
  listItemLength
@@ -596,20 +773,18 @@ function createMarkdownBehaviors(config) {
596
773
  style,
597
774
  paths: [focusTextBlock.path]
598
775
  }, {
599
- type: "delete",
600
- selection: {
601
- anchor: {
602
- path: focusSpan.path,
603
- offset: 0
604
- },
605
- focus: {
606
- path: focusSpan.path,
607
- offset: listItemLength + 1
608
- }
776
+ type: "delete text",
777
+ anchor: {
778
+ path: focusTextBlock.path,
779
+ offset: 0
780
+ },
781
+ focus: {
782
+ path: focusTextBlock.path,
783
+ offset: listItemLength + 1
609
784
  }
610
785
  }]]
611
786
  };
612
- return [automaticBlockquoteOnSpace, automaticBreak, automaticHeadingOnSpace, clearStyleOnBackspace, automaticListOnSpace];
787
+ return [automaticBlockquoteOnSpace, automaticHeadingOnSpace, automaticHr, automaticHrOnPaste, clearStyleOnBackspace, automaticListOnSpace];
613
788
  }
614
789
  function getPortableTextMemberSchemaTypes(portableTextType) {
615
790
  if (!portableTextType)
@@ -4007,6 +4182,21 @@ function createWithPortableTextLists(types2) {
4007
4182
  }, editor;
4008
4183
  };
4009
4184
  }
4185
+ function isPortableTextSpan(node) {
4186
+ return node._type === "span" && "text" in node && typeof node.text == "string" && (typeof node.marks > "u" || Array.isArray(node.marks) && node.marks.every((mark) => typeof mark == "string"));
4187
+ }
4188
+ function isPortableTextBlock(node) {
4189
+ return (
4190
+ // A block doesn't _have_ to be named 'block' - to differentiate between
4191
+ // allowed child types and marks, one might name them differently
4192
+ typeof node._type == "string" && // Toolkit-types like nested spans are @-prefixed
4193
+ node._type[0] !== "@" && // `markDefs` isn't _required_ per say, but if it's there, it needs to be an array
4194
+ (!("markDefs" in node) || !node.markDefs || Array.isArray(node.markDefs) && // Every mark definition needs to have an `_key` to be mappable in child spans
4195
+ node.markDefs.every((def) => typeof def._key == "string")) && // `children` is required and needs to be an array
4196
+ "children" in node && Array.isArray(node.children) && // All children are objects with `_type` (usually spans, but can contain other stuff)
4197
+ node.children.every((child) => typeof child == "object" && "_type" in child)
4198
+ );
4199
+ }
4010
4200
  function getPreviousSpan({
4011
4201
  editor,
4012
4202
  blockPath,
@@ -4707,7 +4897,66 @@ function createSlateEditor(config) {
4707
4897
  };
4708
4898
  return slateEditors.set(config.editorActor, slateEditor), slateEditor;
4709
4899
  }
4710
- const debug$5 = debugWithName("API:editable");
4900
+ function insertBlock({
4901
+ block,
4902
+ placement,
4903
+ editor,
4904
+ schema: schema2
4905
+ }) {
4906
+ if (editor.selection) {
4907
+ const [focusBlock, focusBlockPath] = Array.from(slate.Editor.nodes(editor, {
4908
+ at: editor.selection.focus.path.slice(0, 1),
4909
+ match: (n) => !slate.Editor.isEditor(n)
4910
+ }))[0] ?? [void 0, void 0];
4911
+ if (placement === "after") {
4912
+ const nextPath = [focusBlockPath[0] + 1];
4913
+ slate.Transforms.insertNodes(editor, block, {
4914
+ at: nextPath
4915
+ }), slate.Transforms.select(editor, {
4916
+ anchor: {
4917
+ path: [nextPath[0], 0],
4918
+ offset: 0
4919
+ },
4920
+ focus: {
4921
+ path: [nextPath[0], 0],
4922
+ offset: 0
4923
+ }
4924
+ });
4925
+ } else placement === "before" ? slate.Transforms.insertNodes(editor, block, {
4926
+ at: focusBlockPath
4927
+ }) : slate.Editor.insertNode(editor, block);
4928
+ focusBlock && isEqualToEmptyEditor([focusBlock], schema2) && slate.Transforms.removeNodes(editor, {
4929
+ at: focusBlockPath
4930
+ });
4931
+ } else {
4932
+ const lastBlock = Array.from(slate.Editor.nodes(editor, {
4933
+ match: (n) => !slate.Editor.isEditor(n),
4934
+ at: [],
4935
+ reverse: !0
4936
+ }))[0];
4937
+ slate.Editor.insertNode(editor, block), lastBlock && isEqualToEmptyEditor([lastBlock[0]], schema2) && slate.Transforms.removeNodes(editor, {
4938
+ at: lastBlock[1]
4939
+ });
4940
+ }
4941
+ }
4942
+ const insertBlockObjectActionImplementation = ({
4943
+ context,
4944
+ action
4945
+ }) => {
4946
+ const block = toSlateValue([{
4947
+ _key: context.keyGenerator(),
4948
+ _type: action.blockObject.name,
4949
+ ...action.blockObject.value ? action.blockObject.value : {}
4950
+ }], {
4951
+ schemaTypes: context.schema
4952
+ })[0];
4953
+ insertBlock({
4954
+ block,
4955
+ placement: action.placement,
4956
+ editor: action.editor,
4957
+ schema: context.schema
4958
+ });
4959
+ }, debug$5 = debugWithName("API:editable");
4711
4960
  function createEditableAPI(editor, editorActor) {
4712
4961
  const types2 = editorActor.getSnapshot().context.schema;
4713
4962
  return {
@@ -4796,18 +5045,21 @@ function createEditableAPI(editor, editorActor) {
4796
5045
  at: editor.selection
4797
5046
  }), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path || [];
4798
5047
  },
4799
- insertBlock: (type, value) => insertBlockObjectActionImplementation({
5048
+ insertBlock: (type, value) => (insertBlockObjectActionImplementation({
4800
5049
  context: {
4801
5050
  keyGenerator: editorActor.getSnapshot().context.keyGenerator,
4802
5051
  schema: types2
4803
5052
  },
4804
5053
  action: {
4805
5054
  type: "insert block object",
4806
- name: type.name,
4807
- value,
5055
+ blockObject: {
5056
+ name: type.name,
5057
+ value
5058
+ },
5059
+ placement: "auto",
4808
5060
  editor
4809
5061
  }
4810
- }),
5062
+ }), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path ?? []),
4811
5063
  hasBlockStyle: (style) => {
4812
5064
  try {
4813
5065
  return editor.pteHasBlockStyle(style);
@@ -4977,35 +5229,6 @@ function createEditableAPI(editor, editorActor) {
4977
5229
  }
4978
5230
  };
4979
5231
  }
4980
- const insertBlockObjectActionImplementation = ({
4981
- context,
4982
- action
4983
- }) => {
4984
- const editor = action.editor, types2 = context.schema, block = toSlateValue([{
4985
- _key: context.keyGenerator(),
4986
- _type: action.name,
4987
- ...action.value ? action.value : {}
4988
- }], {
4989
- schemaTypes: context.schema
4990
- })[0];
4991
- if (!editor.selection) {
4992
- const lastBlock = Array.from(slate.Editor.nodes(editor, {
4993
- match: (n) => !slate.Editor.isEditor(n),
4994
- at: [],
4995
- reverse: !0
4996
- }))[0];
4997
- return slate.Editor.insertNode(editor, block), lastBlock && isEqualToEmptyEditor([lastBlock[0]], types2) && slate.Transforms.removeNodes(editor, {
4998
- at: lastBlock[1]
4999
- }), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path ?? [];
5000
- }
5001
- const focusBlock = Array.from(slate.Editor.nodes(editor, {
5002
- at: editor.selection.focus.path.slice(0, 1),
5003
- match: (n) => n._type === types2.block.name
5004
- }))[0];
5005
- return slate.Editor.insertNode(editor, block), focusBlock && isEqualToEmptyEditor([focusBlock[0]], types2) && slate.Transforms.removeNodes(editor, {
5006
- at: focusBlock[1]
5007
- }), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path || [];
5008
- };
5009
5232
  function isAnnotationActive({
5010
5233
  editor,
5011
5234
  annotation
@@ -5401,18 +5624,52 @@ const addAnnotationActionImplementation = ({
5401
5624
  }) => {
5402
5625
  slate.deleteForward(action.editor, action.unit);
5403
5626
  },
5404
- delete: ({
5627
+ "delete block": ({
5628
+ action
5629
+ }) => {
5630
+ const range = toSlateRange({
5631
+ anchor: {
5632
+ path: action.blockPath,
5633
+ offset: 0
5634
+ },
5635
+ focus: {
5636
+ path: action.blockPath,
5637
+ offset: 0
5638
+ }
5639
+ }, action.editor);
5640
+ if (!range) {
5641
+ console.error("Unable to find Slate range from selection points");
5642
+ return;
5643
+ }
5644
+ slate.Transforms.removeNodes(action.editor, {
5645
+ at: range
5646
+ });
5647
+ },
5648
+ "delete text": ({
5649
+ context,
5405
5650
  action
5406
5651
  }) => {
5407
- const location = toSlateRange(action.selection, action.editor);
5408
- if (!location) {
5409
- console.error(`Could not find Slate location from selection ${action.selection}`);
5652
+ const value = fromSlateValue(action.editor.children, context.schema.block.name, KEY_TO_VALUE_ELEMENT.get(action.editor)), anchor = blockOffsetToSpanSelectionPoint({
5653
+ value,
5654
+ blockOffset: action.anchor
5655
+ }), focus = blockOffsetToSpanSelectionPoint({
5656
+ value,
5657
+ blockOffset: action.focus
5658
+ });
5659
+ if (!anchor || !focus) {
5660
+ console.error("Unable to find anchor or focus selection point");
5410
5661
  return;
5411
5662
  }
5412
- location.anchor.path.length === 1 && location.focus.path.length === 1 ? slate.Transforms.removeNodes(action.editor, {
5413
- at: location
5414
- }) : slate.Transforms.delete(action.editor, {
5415
- at: location
5663
+ const range = toSlateRange({
5664
+ anchor,
5665
+ focus
5666
+ }, action.editor);
5667
+ if (!range) {
5668
+ console.error("Unable to find Slate range from selection points");
5669
+ return;
5670
+ }
5671
+ slate.Transforms.delete(action.editor, {
5672
+ at: range
5416
5673
  });
5417
5674
  },
5418
5675
  "insert block object": insertBlockObjectActionImplementation,
@@ -5428,16 +5685,27 @@ const addAnnotationActionImplementation = ({
5428
5685
  context,
5429
5686
  action
5430
5687
  }) => {
5431
- slate.Editor.insertNode(action.editor, {
5688
+ const block = toSlateValue([{
5432
5689
  _key: context.keyGenerator(),
5433
5690
  _type: context.schema.block.name,
5434
5691
  style: context.schema.styles[0].value ?? "normal",
5435
5692
  markDefs: [],
5436
- children: [{
5693
+ children: action.textBlock?.children?.map((child) => ({
5694
+ ...child,
5695
+ _key: context.keyGenerator()
5696
+ })) ?? [{
5697
+ _type: context.schema.span.name,
5437
5698
  _key: context.keyGenerator(),
5438
- _type: "span",
5439
5699
  text: ""
5440
5700
  }]
5701
+ }], {
5702
+ schemaTypes: context.schema
5703
+ })[0];
5704
+ insertBlock({
5705
+ block,
5706
+ editor: action.editor,
5707
+ schema: context.schema,
5708
+ placement: action.placement
5441
5709
  });
5442
5710
  },
5443
5711
  effect: ({
@@ -5472,8 +5740,15 @@ function performAction({
5472
5740
  action
5473
5741
  }) {
5474
5742
  switch (action.type) {
5475
- case "delete": {
5476
- behaviorActionImplementations.delete({
5743
+ case "delete block": {
5744
+ behaviorActionImplementations["delete block"]({
5745
+ context,
5746
+ action
5747
+ });
5748
+ break;
5749
+ }
5750
+ case "delete text": {
5751
+ behaviorActionImplementations["delete text"]({
5477
5752
  context,
5478
5753
  action
5479
5754
  });