@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.js
CHANGED
|
@@ -533,6 +533,65 @@ function createMarkdownBehaviors(config) {
|
|
|
533
533
|
};
|
|
534
534
|
return [automaticBlockquoteOnSpace, automaticBreak, automaticHeadingOnSpace, clearStyleOnBackspace, automaticListOnSpace];
|
|
535
535
|
}
|
|
536
|
+
function createLinkBehaviors(config) {
|
|
537
|
+
const pasteLinkOnSelection = {
|
|
538
|
+
on: "paste",
|
|
539
|
+
guard: ({
|
|
540
|
+
context,
|
|
541
|
+
event
|
|
542
|
+
}) => {
|
|
543
|
+
const selectionCollapsed = selectionIsCollapsed(context), text = event.clipboardData.getData("text/plain"), url = looksLikeUrl(text) ? text : void 0, annotation = url !== void 0 ? config.mapLinkAnnotation?.({
|
|
544
|
+
url,
|
|
545
|
+
schema: context.schema
|
|
546
|
+
}) : void 0;
|
|
547
|
+
return annotation && !selectionCollapsed ? {
|
|
548
|
+
annotation
|
|
549
|
+
} : !1;
|
|
550
|
+
},
|
|
551
|
+
actions: [(_, {
|
|
552
|
+
annotation
|
|
553
|
+
}) => [{
|
|
554
|
+
type: "annotation.add",
|
|
555
|
+
annotation
|
|
556
|
+
}]]
|
|
557
|
+
}, pasteLinkAtCaret = {
|
|
558
|
+
on: "paste",
|
|
559
|
+
guard: ({
|
|
560
|
+
context,
|
|
561
|
+
event
|
|
562
|
+
}) => {
|
|
563
|
+
const focusSpan = getFocusSpan(context), selectionCollapsed = selectionIsCollapsed(context);
|
|
564
|
+
if (!focusSpan || !selectionCollapsed)
|
|
565
|
+
return !1;
|
|
566
|
+
const text = event.clipboardData.getData("text/plain"), url = looksLikeUrl(text) ? text : void 0, annotation = url !== void 0 ? config.mapLinkAnnotation?.({
|
|
567
|
+
url,
|
|
568
|
+
schema: context.schema
|
|
569
|
+
}) : void 0;
|
|
570
|
+
return url && annotation && selectionCollapsed ? {
|
|
571
|
+
focusSpan,
|
|
572
|
+
annotation,
|
|
573
|
+
url
|
|
574
|
+
} : !1;
|
|
575
|
+
},
|
|
576
|
+
actions: [(_, {
|
|
577
|
+
annotation,
|
|
578
|
+
url
|
|
579
|
+
}) => [{
|
|
580
|
+
type: "insert span",
|
|
581
|
+
text: url,
|
|
582
|
+
annotations: [annotation]
|
|
583
|
+
}]]
|
|
584
|
+
};
|
|
585
|
+
return [pasteLinkOnSelection, pasteLinkAtCaret];
|
|
586
|
+
}
|
|
587
|
+
function looksLikeUrl(text) {
|
|
588
|
+
let looksLikeUrl2 = !1;
|
|
589
|
+
try {
|
|
590
|
+
new URL(text), looksLikeUrl2 = !0;
|
|
591
|
+
} catch {
|
|
592
|
+
}
|
|
593
|
+
return looksLikeUrl2;
|
|
594
|
+
}
|
|
536
595
|
function getPortableTextMemberSchemaTypes(portableTextType) {
|
|
537
596
|
if (!portableTextType)
|
|
538
597
|
throw new Error("Parameter 'portabletextType' missing (required)");
|
|
@@ -4447,11 +4506,11 @@ function isDecoratorActive({
|
|
|
4447
4506
|
}) {
|
|
4448
4507
|
if (!editor.selection)
|
|
4449
4508
|
return !1;
|
|
4450
|
-
const
|
|
4509
|
+
const selectedTextNodes = Array.from(slate.Editor.nodes(editor, {
|
|
4451
4510
|
match: slate.Text.isText,
|
|
4452
4511
|
at: editor.selection
|
|
4453
4512
|
}));
|
|
4454
|
-
return slate.Range.isExpanded(editor.selection) ?
|
|
4513
|
+
return selectedTextNodes.length === 0 ? !1 : slate.Range.isExpanded(editor.selection) ? selectedTextNodes.every((n) => {
|
|
4455
4514
|
const [node] = n;
|
|
4456
4515
|
return node.marks?.includes(decorator);
|
|
4457
4516
|
}) : ({
|
|
@@ -5279,6 +5338,35 @@ const addAnnotationActionImplementation = ({
|
|
|
5279
5338
|
type: "insert break"
|
|
5280
5339
|
}
|
|
5281
5340
|
});
|
|
5341
|
+
}, insertSpanActionImplementation = ({
|
|
5342
|
+
context,
|
|
5343
|
+
action
|
|
5344
|
+
}) => {
|
|
5345
|
+
if (!action.editor.selection) {
|
|
5346
|
+
console.error("Unable to perform action without selection", action);
|
|
5347
|
+
return;
|
|
5348
|
+
}
|
|
5349
|
+
const [focusBlock, focusBlockPath] = Array.from(slate.Editor.nodes(action.editor, {
|
|
5350
|
+
at: action.editor.selection.focus.path,
|
|
5351
|
+
match: (node) => action.editor.isTextBlock(node)
|
|
5352
|
+
}))[0] ?? [void 0, void 0];
|
|
5353
|
+
if (!focusBlock || !focusBlockPath) {
|
|
5354
|
+
console.error("Unable to perform action without focus block", action);
|
|
5355
|
+
return;
|
|
5356
|
+
}
|
|
5357
|
+
const markDefs = focusBlock.markDefs ?? [], annotations = action.annotations ? action.annotations.map((annotation) => ({
|
|
5358
|
+
_type: annotation.name,
|
|
5359
|
+
_key: context.keyGenerator(),
|
|
5360
|
+
...annotation.value
|
|
5361
|
+
})) : void 0;
|
|
5362
|
+
annotations && annotations.length > 0 && slate.Transforms.setNodes(action.editor, {
|
|
5363
|
+
markDefs: [...markDefs, ...annotations]
|
|
5364
|
+
}), slate.Transforms.insertNodes(action.editor, {
|
|
5365
|
+
_type: "span",
|
|
5366
|
+
_key: context.keyGenerator(),
|
|
5367
|
+
text: action.text,
|
|
5368
|
+
marks: [...annotations?.map((annotation) => annotation._key) ?? [], ...action.decorators ?? []]
|
|
5369
|
+
});
|
|
5282
5370
|
}, behaviorActionImplementations = {
|
|
5283
5371
|
"annotation.add": addAnnotationActionImplementation,
|
|
5284
5372
|
"annotation.remove": removeAnnotationActionImplementation,
|
|
@@ -5366,6 +5454,7 @@ const addAnnotationActionImplementation = ({
|
|
|
5366
5454
|
"insert block object": insertBlockObjectActionImplementation,
|
|
5367
5455
|
"insert break": insertBreakActionImplementation,
|
|
5368
5456
|
"insert soft break": insertSoftBreakActionImplementation,
|
|
5457
|
+
"insert span": insertSpanActionImplementation,
|
|
5369
5458
|
"insert text": ({
|
|
5370
5459
|
action
|
|
5371
5460
|
}) => {
|
|
@@ -5392,6 +5481,11 @@ const addAnnotationActionImplementation = ({
|
|
|
5392
5481
|
}) => {
|
|
5393
5482
|
action.effect();
|
|
5394
5483
|
},
|
|
5484
|
+
paste: ({
|
|
5485
|
+
action
|
|
5486
|
+
}) => {
|
|
5487
|
+
action.editor.insertData(action.clipboardData);
|
|
5488
|
+
},
|
|
5395
5489
|
select: ({
|
|
5396
5490
|
action
|
|
5397
5491
|
}) => {
|
|
@@ -5428,6 +5522,13 @@ function performAction({
|
|
|
5428
5522
|
});
|
|
5429
5523
|
break;
|
|
5430
5524
|
}
|
|
5525
|
+
case "insert span": {
|
|
5526
|
+
behaviorActionImplementations["insert span"]({
|
|
5527
|
+
context,
|
|
5528
|
+
action
|
|
5529
|
+
});
|
|
5530
|
+
break;
|
|
5531
|
+
}
|
|
5431
5532
|
case "insert text block": {
|
|
5432
5533
|
behaviorActionImplementations["insert text block"]({
|
|
5433
5534
|
context,
|
|
@@ -5559,11 +5660,18 @@ function performDefaultAction({
|
|
|
5559
5660
|
});
|
|
5560
5661
|
break;
|
|
5561
5662
|
}
|
|
5562
|
-
|
|
5663
|
+
case "insert text": {
|
|
5563
5664
|
behaviorActionImplementations["insert text"]({
|
|
5564
5665
|
context,
|
|
5565
5666
|
action
|
|
5566
5667
|
});
|
|
5668
|
+
break;
|
|
5669
|
+
}
|
|
5670
|
+
default:
|
|
5671
|
+
behaviorActionImplementations.paste({
|
|
5672
|
+
context,
|
|
5673
|
+
action
|
|
5674
|
+
});
|
|
5567
5675
|
}
|
|
5568
5676
|
}
|
|
5569
5677
|
const networkLogic = xstate.fromCallback(({
|
|
@@ -6629,19 +6737,13 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6629
6737
|
const handleCopy = react.useCallback((event) => {
|
|
6630
6738
|
onCopy && onCopy(event) !== void 0 && event.preventDefault();
|
|
6631
6739
|
}, [onCopy]), handlePaste = react.useCallback((event_0) => {
|
|
6632
|
-
|
|
6633
|
-
return;
|
|
6634
|
-
if (!onPaste) {
|
|
6635
|
-
debug("Pasting normally"), slateEditor.insertData(event_0.clipboardData);
|
|
6636
|
-
return;
|
|
6637
|
-
}
|
|
6638
|
-
const value_0 = PortableTextEditor.getValue(portableTextEditor), path = toPortableTextRange(value_0, slateEditor.selection, schemaTypes)?.focus.path || [], onPasteResult = onPaste({
|
|
6740
|
+
const value_0 = PortableTextEditor.getValue(portableTextEditor), path = toPortableTextRange(value_0, slateEditor.selection, schemaTypes)?.focus.path || [], onPasteResult = onPaste?.({
|
|
6639
6741
|
event: event_0,
|
|
6640
6742
|
value: value_0,
|
|
6641
6743
|
path,
|
|
6642
6744
|
schemaTypes
|
|
6643
6745
|
});
|
|
6644
|
-
onPasteResult
|
|
6746
|
+
onPasteResult || !slateEditor.selection ? (event_0.preventDefault(), editorActor.send({
|
|
6645
6747
|
type: "loading"
|
|
6646
6748
|
}), Promise.resolve(onPasteResult).then((result_0) => {
|
|
6647
6749
|
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, {
|
|
@@ -6651,7 +6753,14 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6651
6753
|
editorActor.send({
|
|
6652
6754
|
type: "done loading"
|
|
6653
6755
|
});
|
|
6654
|
-
}))
|
|
6756
|
+
})) : event_0.nativeEvent.clipboardData && (event_0.preventDefault(), editorActor.send({
|
|
6757
|
+
type: "behavior event",
|
|
6758
|
+
behaviorEvent: {
|
|
6759
|
+
type: "paste",
|
|
6760
|
+
clipboardData: event_0.nativeEvent.clipboardData
|
|
6761
|
+
},
|
|
6762
|
+
editor: slateEditor
|
|
6763
|
+
})), debug("No result from custom paste handler, pasting normally");
|
|
6655
6764
|
}, [editorActor, onPaste, portableTextEditor, schemaTypes, slateEditor]), handleOnFocus = react.useCallback((event_1) => {
|
|
6656
6765
|
if (onFocus && onFocus(event_1), !event_1.isDefaultPrevented()) {
|
|
6657
6766
|
const selection = PortableTextEditor.getSelection(portableTextEditor);
|
|
@@ -6666,15 +6775,11 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6666
6775
|
});
|
|
6667
6776
|
}
|
|
6668
6777
|
}, [editorActor, onFocus, portableTextEditor, slateEditor]), handleClick = react.useCallback((event_2) => {
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
decorators: []
|
|
6675
|
-
})), slateEditor.onChange());
|
|
6676
|
-
}
|
|
6677
|
-
}
|
|
6778
|
+
onClick && onClick(event_2);
|
|
6779
|
+
const focusBlockPath = slateEditor.selection ? slateEditor.selection.focus.path.slice(0, 1) : void 0, focusBlock = focusBlockPath ? slate.Node.descendant(slateEditor, focusBlockPath) : void 0, [_, lastNodePath] = slate.Node.last(slateEditor, []), lastBlockPath = lastNodePath.slice(0, 1), lastNodeFocused = focusBlockPath ? slate.Path.equals(lastBlockPath, focusBlockPath) : !1, lastBlockIsVoid = focusBlock ? !slateEditor.isTextBlock(focusBlock) : !1;
|
|
6780
|
+
slateEditor.selection && slate.Range.isCollapsed(slateEditor.selection) && lastNodeFocused && lastBlockIsVoid && (slate.Transforms.insertNodes(slateEditor, slateEditor.pteCreateTextBlock({
|
|
6781
|
+
decorators: []
|
|
6782
|
+
})), slateEditor.onChange());
|
|
6678
6783
|
}, [onClick, slateEditor]), handleOnBlur = react.useCallback((event_3) => {
|
|
6679
6784
|
onBlur && onBlur(event_3), event_3.isPropagationStopped() || editorActor.send({
|
|
6680
6785
|
type: "blur",
|
|
@@ -6722,7 +6827,7 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6722
6827
|
return scrollSelectionIntoView === null ? noop__default.default : (_editor, domRange) => {
|
|
6723
6828
|
scrollSelectionIntoView(portableTextEditor, domRange);
|
|
6724
6829
|
};
|
|
6725
|
-
}, [portableTextEditor, scrollSelectionIntoView]), decorate = react.useCallback(([,
|
|
6830
|
+
}, [portableTextEditor, scrollSelectionIntoView]), decorate = react.useCallback(([, path_0]) => {
|
|
6726
6831
|
if (isEqualToEmptyEditor(slateEditor.children, schemaTypes))
|
|
6727
6832
|
return [{
|
|
6728
6833
|
anchor: {
|
|
@@ -6735,18 +6840,18 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
|
|
|
6735
6840
|
},
|
|
6736
6841
|
placeholder: !0
|
|
6737
6842
|
}];
|
|
6738
|
-
if (
|
|
6843
|
+
if (path_0.length === 0)
|
|
6739
6844
|
return [];
|
|
6740
|
-
const result_1 = rangeDecorationState.filter((item) => slate.Range.isCollapsed(item) ?
|
|
6845
|
+
const result_1 = rangeDecorationState.filter((item) => slate.Range.isCollapsed(item) ? path_0.length !== 2 ? !1 : slate.Path.equals(item.focus.path, path_0) && slate.Path.equals(item.anchor.path, path_0) : slate.Range.intersection(item, {
|
|
6741
6846
|
anchor: {
|
|
6742
|
-
path:
|
|
6847
|
+
path: path_0,
|
|
6743
6848
|
offset: 0
|
|
6744
6849
|
},
|
|
6745
6850
|
focus: {
|
|
6746
|
-
path:
|
|
6851
|
+
path: path_0,
|
|
6747
6852
|
offset: 0
|
|
6748
6853
|
}
|
|
6749
|
-
}) || slate.Range.includes(item,
|
|
6854
|
+
}) || slate.Range.includes(item, path_0));
|
|
6750
6855
|
return result_1.length > 0 ? result_1 : [];
|
|
6751
6856
|
}, [slateEditor, schemaTypes, rangeDecorationState]);
|
|
6752
6857
|
return react.useEffect(() => {
|
|
@@ -6816,6 +6921,7 @@ exports.PortableTextEditable = PortableTextEditable;
|
|
|
6816
6921
|
exports.PortableTextEditor = PortableTextEditor;
|
|
6817
6922
|
exports.coreBehavior = coreBehavior;
|
|
6818
6923
|
exports.coreBehaviors = coreBehaviors;
|
|
6924
|
+
exports.createLinkBehaviors = createLinkBehaviors;
|
|
6819
6925
|
exports.createMarkdownBehaviors = createMarkdownBehaviors;
|
|
6820
6926
|
exports.defineBehavior = defineBehavior;
|
|
6821
6927
|
exports.defineSchema = defineSchema;
|