@portabletext/editor 1.8.0 → 1.9.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.
- package/lib/index.d.mts +76 -11
- package/lib/index.d.ts +76 -11
- package/lib/index.esm.js +133 -27
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +133 -27
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +133 -27
- package/lib/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/editor/Editable.tsx +46 -31
- package/src/editor/behavior/behavior.action.insert-span.ts +48 -0
- package/src/editor/behavior/behavior.actions.ts +20 -1
- package/src/editor/behavior/behavior.links.ts +91 -0
- package/src/editor/behavior/behavior.types.ts +13 -0
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +6 -2
- package/src/index.ts +4 -0
package/lib/index.mjs
CHANGED
|
@@ -554,6 +554,65 @@ function createMarkdownBehaviors(config) {
|
|
|
554
554
|
};
|
|
555
555
|
return [automaticBlockquoteOnSpace, automaticBreak, automaticHeadingOnSpace, clearStyleOnBackspace, automaticListOnSpace];
|
|
556
556
|
}
|
|
557
|
+
function createLinkBehaviors(config) {
|
|
558
|
+
const pasteLinkOnSelection = {
|
|
559
|
+
on: "paste",
|
|
560
|
+
guard: ({
|
|
561
|
+
context,
|
|
562
|
+
event
|
|
563
|
+
}) => {
|
|
564
|
+
const selectionCollapsed = selectionIsCollapsed(context), text = event.clipboardData.getData("text/plain"), url = looksLikeUrl(text) ? text : void 0, annotation = url !== void 0 ? config.mapLinkAnnotation?.({
|
|
565
|
+
url,
|
|
566
|
+
schema: context.schema
|
|
567
|
+
}) : void 0;
|
|
568
|
+
return annotation && !selectionCollapsed ? {
|
|
569
|
+
annotation
|
|
570
|
+
} : !1;
|
|
571
|
+
},
|
|
572
|
+
actions: [(_, {
|
|
573
|
+
annotation
|
|
574
|
+
}) => [{
|
|
575
|
+
type: "annotation.add",
|
|
576
|
+
annotation
|
|
577
|
+
}]]
|
|
578
|
+
}, pasteLinkAtCaret = {
|
|
579
|
+
on: "paste",
|
|
580
|
+
guard: ({
|
|
581
|
+
context,
|
|
582
|
+
event
|
|
583
|
+
}) => {
|
|
584
|
+
const focusSpan = getFocusSpan(context), selectionCollapsed = selectionIsCollapsed(context);
|
|
585
|
+
if (!focusSpan || !selectionCollapsed)
|
|
586
|
+
return !1;
|
|
587
|
+
const text = event.clipboardData.getData("text/plain"), url = looksLikeUrl(text) ? text : void 0, annotation = url !== void 0 ? config.mapLinkAnnotation?.({
|
|
588
|
+
url,
|
|
589
|
+
schema: context.schema
|
|
590
|
+
}) : void 0;
|
|
591
|
+
return url && annotation && selectionCollapsed ? {
|
|
592
|
+
focusSpan,
|
|
593
|
+
annotation,
|
|
594
|
+
url
|
|
595
|
+
} : !1;
|
|
596
|
+
},
|
|
597
|
+
actions: [(_, {
|
|
598
|
+
annotation,
|
|
599
|
+
url
|
|
600
|
+
}) => [{
|
|
601
|
+
type: "insert span",
|
|
602
|
+
text: url,
|
|
603
|
+
annotations: [annotation]
|
|
604
|
+
}]]
|
|
605
|
+
};
|
|
606
|
+
return [pasteLinkOnSelection, pasteLinkAtCaret];
|
|
607
|
+
}
|
|
608
|
+
function looksLikeUrl(text) {
|
|
609
|
+
let looksLikeUrl2 = !1;
|
|
610
|
+
try {
|
|
611
|
+
new URL(text), looksLikeUrl2 = !0;
|
|
612
|
+
} catch {
|
|
613
|
+
}
|
|
614
|
+
return looksLikeUrl2;
|
|
615
|
+
}
|
|
557
616
|
function getPortableTextMemberSchemaTypes(portableTextType) {
|
|
558
617
|
if (!portableTextType)
|
|
559
618
|
throw new Error("Parameter 'portabletextType' missing (required)");
|
|
@@ -4468,11 +4527,11 @@ function isDecoratorActive({
|
|
|
4468
4527
|
}) {
|
|
4469
4528
|
if (!editor.selection)
|
|
4470
4529
|
return !1;
|
|
4471
|
-
const
|
|
4530
|
+
const selectedTextNodes = Array.from(Editor.nodes(editor, {
|
|
4472
4531
|
match: Text.isText,
|
|
4473
4532
|
at: editor.selection
|
|
4474
4533
|
}));
|
|
4475
|
-
return Range.isExpanded(editor.selection) ?
|
|
4534
|
+
return selectedTextNodes.length === 0 ? !1 : Range.isExpanded(editor.selection) ? selectedTextNodes.every((n) => {
|
|
4476
4535
|
const [node] = n;
|
|
4477
4536
|
return node.marks?.includes(decorator);
|
|
4478
4537
|
}) : ({
|
|
@@ -5300,6 +5359,35 @@ const addAnnotationActionImplementation = ({
|
|
|
5300
5359
|
type: "insert break"
|
|
5301
5360
|
}
|
|
5302
5361
|
});
|
|
5362
|
+
}, insertSpanActionImplementation = ({
|
|
5363
|
+
context,
|
|
5364
|
+
action
|
|
5365
|
+
}) => {
|
|
5366
|
+
if (!action.editor.selection) {
|
|
5367
|
+
console.error("Unable to perform action without selection", action);
|
|
5368
|
+
return;
|
|
5369
|
+
}
|
|
5370
|
+
const [focusBlock, focusBlockPath] = Array.from(Editor.nodes(action.editor, {
|
|
5371
|
+
at: action.editor.selection.focus.path,
|
|
5372
|
+
match: (node) => action.editor.isTextBlock(node)
|
|
5373
|
+
}))[0] ?? [void 0, void 0];
|
|
5374
|
+
if (!focusBlock || !focusBlockPath) {
|
|
5375
|
+
console.error("Unable to perform action without focus block", action);
|
|
5376
|
+
return;
|
|
5377
|
+
}
|
|
5378
|
+
const markDefs = focusBlock.markDefs ?? [], annotations = action.annotations ? action.annotations.map((annotation) => ({
|
|
5379
|
+
_type: annotation.name,
|
|
5380
|
+
_key: context.keyGenerator(),
|
|
5381
|
+
...annotation.value
|
|
5382
|
+
})) : void 0;
|
|
5383
|
+
annotations && annotations.length > 0 && Transforms.setNodes(action.editor, {
|
|
5384
|
+
markDefs: [...markDefs, ...annotations]
|
|
5385
|
+
}), Transforms.insertNodes(action.editor, {
|
|
5386
|
+
_type: "span",
|
|
5387
|
+
_key: context.keyGenerator(),
|
|
5388
|
+
text: action.text,
|
|
5389
|
+
marks: [...annotations?.map((annotation) => annotation._key) ?? [], ...action.decorators ?? []]
|
|
5390
|
+
});
|
|
5303
5391
|
}, behaviorActionImplementations = {
|
|
5304
5392
|
"annotation.add": addAnnotationActionImplementation,
|
|
5305
5393
|
"annotation.remove": removeAnnotationActionImplementation,
|
|
@@ -5387,6 +5475,7 @@ const addAnnotationActionImplementation = ({
|
|
|
5387
5475
|
"insert block object": insertBlockObjectActionImplementation,
|
|
5388
5476
|
"insert break": insertBreakActionImplementation,
|
|
5389
5477
|
"insert soft break": insertSoftBreakActionImplementation,
|
|
5478
|
+
"insert span": insertSpanActionImplementation,
|
|
5390
5479
|
"insert text": ({
|
|
5391
5480
|
action
|
|
5392
5481
|
}) => {
|
|
@@ -5413,6 +5502,11 @@ const addAnnotationActionImplementation = ({
|
|
|
5413
5502
|
}) => {
|
|
5414
5503
|
action.effect();
|
|
5415
5504
|
},
|
|
5505
|
+
paste: ({
|
|
5506
|
+
action
|
|
5507
|
+
}) => {
|
|
5508
|
+
action.editor.insertData(action.clipboardData);
|
|
5509
|
+
},
|
|
5416
5510
|
select: ({
|
|
5417
5511
|
action
|
|
5418
5512
|
}) => {
|
|
@@ -5449,6 +5543,13 @@ function performAction({
|
|
|
5449
5543
|
});
|
|
5450
5544
|
break;
|
|
5451
5545
|
}
|
|
5546
|
+
case "insert span": {
|
|
5547
|
+
behaviorActionImplementations["insert span"]({
|
|
5548
|
+
context,
|
|
5549
|
+
action
|
|
5550
|
+
});
|
|
5551
|
+
break;
|
|
5552
|
+
}
|
|
5452
5553
|
case "insert text block": {
|
|
5453
5554
|
behaviorActionImplementations["insert text block"]({
|
|
5454
5555
|
context,
|
|
@@ -5580,11 +5681,18 @@ function performDefaultAction({
|
|
|
5580
5681
|
});
|
|
5581
5682
|
break;
|
|
5582
5683
|
}
|
|
5583
|
-
|
|
5684
|
+
case "insert text": {
|
|
5584
5685
|
behaviorActionImplementations["insert text"]({
|
|
5585
5686
|
context,
|
|
5586
5687
|
action
|
|
5587
5688
|
});
|
|
5689
|
+
break;
|
|
5690
|
+
}
|
|
5691
|
+
default:
|
|
5692
|
+
behaviorActionImplementations.paste({
|
|
5693
|
+
context,
|
|
5694
|
+
action
|
|
5695
|
+
});
|
|
5588
5696
|
}
|
|
5589
5697
|
}
|
|
5590
5698
|
const networkLogic = fromCallback(({
|
|
@@ -6650,19 +6758,13 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6650
6758
|
const handleCopy = useCallback((event) => {
|
|
6651
6759
|
onCopy && onCopy(event) !== void 0 && event.preventDefault();
|
|
6652
6760
|
}, [onCopy]), handlePaste = useCallback((event_0) => {
|
|
6653
|
-
|
|
6654
|
-
return;
|
|
6655
|
-
if (!onPaste) {
|
|
6656
|
-
debug("Pasting normally"), slateEditor.insertData(event_0.clipboardData);
|
|
6657
|
-
return;
|
|
6658
|
-
}
|
|
6659
|
-
const value_0 = PortableTextEditor.getValue(portableTextEditor), path = toPortableTextRange(value_0, slateEditor.selection, schemaTypes)?.focus.path || [], onPasteResult = onPaste({
|
|
6761
|
+
const value_0 = PortableTextEditor.getValue(portableTextEditor), path = toPortableTextRange(value_0, slateEditor.selection, schemaTypes)?.focus.path || [], onPasteResult = onPaste?.({
|
|
6660
6762
|
event: event_0,
|
|
6661
6763
|
value: value_0,
|
|
6662
6764
|
path,
|
|
6663
6765
|
schemaTypes
|
|
6664
6766
|
});
|
|
6665
|
-
onPasteResult
|
|
6767
|
+
onPasteResult || !slateEditor.selection ? (event_0.preventDefault(), editorActor.send({
|
|
6666
6768
|
type: "loading"
|
|
6667
6769
|
}), Promise.resolve(onPasteResult).then((result_0) => {
|
|
6668
6770
|
debug("Custom paste function from client resolved", result_0), !result_0 || !result_0.insert ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event_0.clipboardData)) : result_0.insert ? slateEditor.insertFragment(toSlateValue(result_0.insert, {
|
|
@@ -6672,7 +6774,14 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6672
6774
|
editorActor.send({
|
|
6673
6775
|
type: "done loading"
|
|
6674
6776
|
});
|
|
6675
|
-
}))
|
|
6777
|
+
})) : event_0.nativeEvent.clipboardData && (event_0.preventDefault(), editorActor.send({
|
|
6778
|
+
type: "behavior event",
|
|
6779
|
+
behaviorEvent: {
|
|
6780
|
+
type: "paste",
|
|
6781
|
+
clipboardData: event_0.nativeEvent.clipboardData
|
|
6782
|
+
},
|
|
6783
|
+
editor: slateEditor
|
|
6784
|
+
})), debug("No result from custom paste handler, pasting normally");
|
|
6676
6785
|
}, [editorActor, onPaste, portableTextEditor, schemaTypes, slateEditor]), handleOnFocus = useCallback((event_1) => {
|
|
6677
6786
|
if (onFocus && onFocus(event_1), !event_1.isDefaultPrevented()) {
|
|
6678
6787
|
const selection = PortableTextEditor.getSelection(portableTextEditor);
|
|
@@ -6687,15 +6796,11 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6687
6796
|
});
|
|
6688
6797
|
}
|
|
6689
6798
|
}, [editorActor, onFocus, portableTextEditor, slateEditor]), handleClick = useCallback((event_2) => {
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
decorators: []
|
|
6696
|
-
})), slateEditor.onChange());
|
|
6697
|
-
}
|
|
6698
|
-
}
|
|
6799
|
+
onClick && onClick(event_2);
|
|
6800
|
+
const focusBlockPath = slateEditor.selection ? slateEditor.selection.focus.path.slice(0, 1) : void 0, focusBlock = focusBlockPath ? Node.descendant(slateEditor, focusBlockPath) : void 0, [_, lastNodePath] = Node.last(slateEditor, []), lastBlockPath = lastNodePath.slice(0, 1), lastNodeFocused = focusBlockPath ? Path.equals(lastBlockPath, focusBlockPath) : !1, lastBlockIsVoid = focusBlock ? !slateEditor.isTextBlock(focusBlock) : !1;
|
|
6801
|
+
slateEditor.selection && Range.isCollapsed(slateEditor.selection) && lastNodeFocused && lastBlockIsVoid && (Transforms.insertNodes(slateEditor, slateEditor.pteCreateTextBlock({
|
|
6802
|
+
decorators: []
|
|
6803
|
+
})), slateEditor.onChange());
|
|
6699
6804
|
}, [onClick, slateEditor]), handleOnBlur = useCallback((event_3) => {
|
|
6700
6805
|
onBlur && onBlur(event_3), event_3.isPropagationStopped() || editorActor.send({
|
|
6701
6806
|
type: "blur",
|
|
@@ -6743,7 +6848,7 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6743
6848
|
return scrollSelectionIntoView === null ? noop : (_editor, domRange) => {
|
|
6744
6849
|
scrollSelectionIntoView(portableTextEditor, domRange);
|
|
6745
6850
|
};
|
|
6746
|
-
}, [portableTextEditor, scrollSelectionIntoView]), decorate = useCallback(([,
|
|
6851
|
+
}, [portableTextEditor, scrollSelectionIntoView]), decorate = useCallback(([, path_0]) => {
|
|
6747
6852
|
if (isEqualToEmptyEditor(slateEditor.children, schemaTypes))
|
|
6748
6853
|
return [{
|
|
6749
6854
|
anchor: {
|
|
@@ -6756,18 +6861,18 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6756
6861
|
},
|
|
6757
6862
|
placeholder: !0
|
|
6758
6863
|
}];
|
|
6759
|
-
if (
|
|
6864
|
+
if (path_0.length === 0)
|
|
6760
6865
|
return [];
|
|
6761
|
-
const result_1 = rangeDecorationState.filter((item) => Range.isCollapsed(item) ?
|
|
6866
|
+
const result_1 = rangeDecorationState.filter((item) => Range.isCollapsed(item) ? path_0.length !== 2 ? !1 : Path.equals(item.focus.path, path_0) && Path.equals(item.anchor.path, path_0) : Range.intersection(item, {
|
|
6762
6867
|
anchor: {
|
|
6763
|
-
path:
|
|
6868
|
+
path: path_0,
|
|
6764
6869
|
offset: 0
|
|
6765
6870
|
},
|
|
6766
6871
|
focus: {
|
|
6767
|
-
path:
|
|
6872
|
+
path: path_0,
|
|
6768
6873
|
offset: 0
|
|
6769
6874
|
}
|
|
6770
|
-
}) || Range.includes(item,
|
|
6875
|
+
}) || Range.includes(item, path_0));
|
|
6771
6876
|
return result_1.length > 0 ? result_1 : [];
|
|
6772
6877
|
}, [slateEditor, schemaTypes, rangeDecorationState]);
|
|
6773
6878
|
return useEffect(() => {
|
|
@@ -6838,6 +6943,7 @@ export {
|
|
|
6838
6943
|
PortableTextEditor,
|
|
6839
6944
|
coreBehavior,
|
|
6840
6945
|
coreBehaviors,
|
|
6946
|
+
createLinkBehaviors,
|
|
6841
6947
|
createMarkdownBehaviors,
|
|
6842
6948
|
defineBehavior,
|
|
6843
6949
|
defineSchema,
|