@webiny/lexical-editor 6.3.0 → 6.4.0-beta.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/commands/image.js +2 -1
- package/commands/image.js.map +1 -1
- package/commands/index.js +0 -2
- package/commands/list.js +4 -3
- package/commands/list.js.map +1 -1
- package/commands/quote.js +2 -1
- package/commands/quote.js.map +1 -1
- package/commands/toolbar.js +2 -1
- package/commands/toolbar.js.map +1 -1
- package/commands/typography.js +2 -1
- package/commands/typography.js.map +1 -1
- package/components/Editor/EnsureHeadingTagPlugin.js +8 -15
- package/components/Editor/EnsureHeadingTagPlugin.js.map +1 -1
- package/components/Editor/RichTextEditor.js +82 -121
- package/components/Editor/RichTextEditor.js.map +1 -1
- package/components/Editor/normalizeInputValue.js +11 -13
- package/components/Editor/normalizeInputValue.js.map +1 -1
- package/components/LexicalEditorConfig/LexicalEditorConfig.js +24 -15
- package/components/LexicalEditorConfig/LexicalEditorConfig.js.map +1 -1
- package/components/LexicalEditorConfig/components/Node.js +21 -26
- package/components/LexicalEditorConfig/components/Node.js.map +1 -1
- package/components/LexicalEditorConfig/components/Plugin.js +21 -26
- package/components/LexicalEditorConfig/components/Plugin.js.map +1 -1
- package/components/LexicalEditorConfig/components/ToolbarElement.js +21 -26
- package/components/LexicalEditorConfig/components/ToolbarElement.js.map +1 -1
- package/components/LexicalHtmlRenderer.js +35 -40
- package/components/LexicalHtmlRenderer.js.map +1 -1
- package/components/Toolbar/StaticToolbar.js +11 -16
- package/components/Toolbar/StaticToolbar.js.map +1 -1
- package/components/ToolbarActions/BoldAction.js +16 -19
- package/components/ToolbarActions/BoldAction.js.map +1 -1
- package/components/ToolbarActions/BulletListAction.js +24 -32
- package/components/ToolbarActions/BulletListAction.js.map +1 -1
- package/components/ToolbarActions/CodeHighlightAction.js +16 -19
- package/components/ToolbarActions/CodeHighlightAction.js.map +1 -1
- package/components/ToolbarActions/FontColorAction.js +32 -38
- package/components/ToolbarActions/FontColorAction.js.map +1 -1
- package/components/ToolbarActions/ImageAction.js +28 -30
- package/components/ToolbarActions/ImageAction.js.map +1 -1
- package/components/ToolbarActions/ItalicAction.js +16 -19
- package/components/ToolbarActions/ItalicAction.js.map +1 -1
- package/components/ToolbarActions/LinkAction.js +25 -30
- package/components/ToolbarActions/LinkAction.js.map +1 -1
- package/components/ToolbarActions/NumberedListAction.js +28 -37
- package/components/ToolbarActions/NumberedListAction.js.map +1 -1
- package/components/ToolbarActions/QuoteAction.js +22 -27
- package/components/ToolbarActions/QuoteAction.js.map +1 -1
- package/components/ToolbarActions/TextAlignmentAction.js +38 -50
- package/components/ToolbarActions/TextAlignmentAction.js.map +1 -1
- package/components/ToolbarActions/TypographyAction.js +69 -99
- package/components/ToolbarActions/TypographyAction.js.map +1 -1
- package/components/ToolbarActions/UnderlineAction.js +16 -19
- package/components/ToolbarActions/UnderlineAction.js.map +1 -1
- package/context/FontColorActionContext.js +3 -2
- package/context/FontColorActionContext.js.map +1 -1
- package/context/RichTextEditorContext.js +26 -29
- package/context/RichTextEditorContext.js.map +1 -1
- package/context/SharedHistoryContext.js +11 -15
- package/context/SharedHistoryContext.js.map +1 -1
- package/context/TextAlignmentActionContextProps.js +3 -2
- package/context/TextAlignmentActionContextProps.js.map +1 -1
- package/context/TypographyActionContext.js +3 -2
- package/context/TypographyActionContext.js.map +1 -1
- package/exports/admin/lexical.js +2 -20
- package/hooks/index.js +0 -2
- package/hooks/useCurrentElement.js +18 -21
- package/hooks/useCurrentElement.js.map +1 -1
- package/hooks/useCurrentSelection.js +39 -48
- package/hooks/useCurrentSelection.js.map +1 -1
- package/hooks/useFontColorPicker.js +5 -6
- package/hooks/useFontColorPicker.js.map +1 -1
- package/hooks/useIsMounted.js +7 -8
- package/hooks/useIsMounted.js.map +1 -1
- package/hooks/useRichTextEditor.js +5 -6
- package/hooks/useRichTextEditor.js.map +1 -1
- package/hooks/useTextAlignmentAction.js +5 -6
- package/hooks/useTextAlignmentAction.js.map +1 -1
- package/hooks/useTypographyAction.js +5 -6
- package/hooks/useTypographyAction.js.map +1 -1
- package/images/icons/chat-square-quote.js +19 -0
- package/images/icons/chat-square-quote.js.map +1 -0
- package/images/icons/chevron-down.js +18 -0
- package/images/icons/chevron-down.js.map +1 -0
- package/images/icons/code.js +17 -0
- package/images/icons/code.js.map +1 -0
- package/images/icons/font-color.js +17 -0
- package/images/icons/font-color.js.map +1 -0
- package/images/icons/indent.js +18 -0
- package/images/icons/indent.js.map +1 -0
- package/images/icons/insert-image.js +20 -0
- package/images/icons/insert-image.js.map +1 -0
- package/images/icons/justify.js +19 -0
- package/images/icons/justify.js.map +1 -0
- package/images/icons/link.js +19 -0
- package/images/icons/link.js.map +1 -0
- package/images/icons/list-ol.js +20 -0
- package/images/icons/list-ol.js.map +1 -0
- package/images/icons/list-ul.js +18 -0
- package/images/icons/list-ul.js.map +1 -0
- package/images/icons/outdent.js +18 -0
- package/images/icons/outdent.js.map +1 -0
- package/images/icons/pencil-fill.js +17 -0
- package/images/icons/pencil-fill.js.map +1 -0
- package/images/icons/text-center.js +18 -0
- package/images/icons/text-center.js.map +1 -0
- package/images/icons/text-left.js +18 -0
- package/images/icons/text-left.js.map +1 -0
- package/images/icons/text-paragraph.js +18 -0
- package/images/icons/text-paragraph.js.map +1 -0
- package/images/icons/text-right.js +18 -0
- package/images/icons/text-right.js.map +1 -0
- package/images/icons/type-bold.js +17 -0
- package/images/icons/type-bold.js.map +1 -0
- package/images/icons/type-h1.js +17 -0
- package/images/icons/type-h1.js.map +1 -0
- package/images/icons/type-h2.js +17 -0
- package/images/icons/type-h2.js.map +1 -0
- package/images/icons/type-h3.js +17 -0
- package/images/icons/type-h3.js.map +1 -0
- package/images/icons/type-h4.js +17 -0
- package/images/icons/type-h4.js.map +1 -0
- package/images/icons/type-h5.js +17 -0
- package/images/icons/type-h5.js.map +1 -0
- package/images/icons/type-h6.js +17 -0
- package/images/icons/type-h6.js.map +1 -0
- package/images/icons/type-italic.js +17 -0
- package/images/icons/type-italic.js.map +1 -0
- package/images/icons/type-strikethrough.js +17 -0
- package/images/icons/type-strikethrough.js.map +1 -0
- package/images/icons/type-underline.js +17 -0
- package/images/icons/type-underline.js.map +1 -0
- package/images/icons/unlink_icon.js +27 -0
- package/images/icons/unlink_icon.js.map +1 -0
- package/index.js +5 -18
- package/package.json +7 -7
- package/plugins/BlurEventPlugin/BlurEventPlugin.js +11 -14
- package/plugins/BlurEventPlugin/BlurEventPlugin.js.map +1 -1
- package/plugins/CodeHighlightPlugin/CodeHighlightPlugin.js +7 -8
- package/plugins/CodeHighlightPlugin/CodeHighlightPlugin.js.map +1 -1
- package/plugins/CodeHighlightPlugin/index.js +0 -2
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.js +16 -24
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.js.map +1 -1
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js +37 -51
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js.map +1 -1
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin.js +6 -5
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin.js.map +1 -1
- package/plugins/FloatingLinkEditorPlugin/index.js +0 -2
- package/plugins/FloatingLinkEditorPlugin/isChildOfLinkEditor.js +6 -9
- package/plugins/FloatingLinkEditorPlugin/isChildOfLinkEditor.js.map +1 -1
- package/plugins/FloatingLinkEditorPlugin/types.js +0 -3
- package/plugins/FloatingLinkEditorPlugin/useFloatingLinkEditor.js +101 -108
- package/plugins/FloatingLinkEditorPlugin/useFloatingLinkEditor.js.map +1 -1
- package/plugins/FontColorPlugin/FontColorPlugin.js +14 -19
- package/plugins/FontColorPlugin/FontColorPlugin.js.map +1 -1
- package/plugins/FontColorPlugin/applyColorToNode.js +5 -4
- package/plugins/FontColorPlugin/applyColorToNode.js.map +1 -1
- package/plugins/FontColorPlugin/applyColorToSelection.js +42 -60
- package/plugins/FontColorPlugin/applyColorToSelection.js.map +1 -1
- package/plugins/ImagesPlugin/ImagesPlugin.js +79 -121
- package/plugins/ImagesPlugin/ImagesPlugin.js.map +1 -1
- package/plugins/LinkPlugin/LinkPlugin.js +46 -52
- package/plugins/LinkPlugin/LinkPlugin.js.map +1 -1
- package/plugins/ListPLugin/ListPlugin.js +44 -52
- package/plugins/ListPLugin/ListPlugin.js.map +1 -1
- package/plugins/QuoteNodePlugin/QuoteNodePlugin.js +18 -19
- package/plugins/QuoteNodePlugin/QuoteNodePlugin.js.map +1 -1
- package/plugins/StateHandlingPlugin.js +55 -64
- package/plugins/StateHandlingPlugin.js.map +1 -1
- package/plugins/TypographyPlugin/TypographyPlugin.js +13 -20
- package/plugins/TypographyPlugin/TypographyPlugin.js.map +1 -1
- package/static/svg/chat-square-quote.123cfa24.svg +1 -0
- package/static/svg/chevron-down.d9636921.svg +1 -0
- package/static/svg/code.912b1f4d.svg +1 -0
- package/static/svg/font-color.4f0c0de5.svg +1 -0
- package/static/svg/indent.4d78e483.svg +3 -0
- package/static/svg/insert-image.354465f1.svg +4 -0
- package/static/svg/justify.dab42aec.svg +3 -0
- package/static/svg/link.b774de25.svg +1 -0
- package/static/svg/list-ol.d64946f3.svg +1 -0
- package/static/svg/list-ul.1d54da3f.svg +1 -0
- package/static/svg/outdent.5c13ff16.svg +3 -0
- package/static/svg/pencil-fill.94cb216b.svg +1 -0
- package/static/svg/text-center.a411e780.svg +1 -0
- package/static/svg/text-left.54f41f4e.svg +1 -0
- package/static/svg/text-paragraph.61674422.svg +1 -0
- package/static/svg/text-right.9288b7a2.svg +1 -0
- package/static/svg/type-bold.7e3e270b.svg +1 -0
- package/static/svg/type-h1.f292ffe1.svg +1 -0
- package/static/svg/type-h2.a9d1aa48.svg +1 -0
- package/static/svg/type-h3.4a29ff88.svg +1 -0
- package/static/svg/type-h4.7f48750c.svg +1 -0
- package/static/svg/type-h5.14b4ac56.svg +1 -0
- package/static/svg/type-h6.4e9dfe2d.svg +1 -0
- package/static/svg/type-italic.d8e45748.svg +1 -0
- package/static/svg/type-strikethrough.2694a816.svg +1 -0
- package/static/svg/type-underline.104a0ed5.svg +1 -0
- package/static/svg/unlink_icon.074ceed3.svg +1 -0
- package/types.js +0 -8
- package/ui/ContentEditable.js +6 -14
- package/ui/ContentEditable.js.map +1 -1
- package/ui/Divider.js +6 -5
- package/ui/Divider.js.map +1 -1
- package/ui/DropDown.js +146 -176
- package/ui/DropDown.js.map +1 -1
- package/ui/ImageResizer.js +173 -204
- package/ui/ImageResizer.js.map +1 -1
- package/ui/LinkPreview.js +61 -84
- package/ui/LinkPreview.js.map +1 -1
- package/ui/Placeholder.js +9 -20
- package/ui/Placeholder.js.map +1 -1
- package/ui/TextInput.js +17 -30
- package/ui/TextInput.js.map +1 -1
- package/ui/ToolbarActionDialog.js +64 -73
- package/ui/ToolbarActionDialog.js.map +1 -1
- package/utils/canUseDOM.js +2 -1
- package/utils/canUseDOM.js.map +1 -1
- package/utils/files.js +9 -8
- package/utils/files.js.map +1 -1
- package/utils/getDOMRangeRect.js +10 -20
- package/utils/getDOMRangeRect.js.map +1 -1
- package/utils/getSelectedNode.js +9 -20
- package/utils/getSelectedNode.js.map +1 -1
- package/utils/getTransparentImage.js +2 -3
- package/utils/getTransparentImage.js.map +1 -1
- package/utils/insertImage.js +9 -11
- package/utils/insertImage.js.map +1 -1
- package/utils/isAnchorLink.js +2 -3
- package/utils/isAnchorLink.js.map +1 -1
- package/utils/isChildOfFloatingToolbar.js +6 -9
- package/utils/isChildOfFloatingToolbar.js.map +1 -1
- package/utils/isHTMLElement.js +3 -9
- package/utils/isHTMLElement.js.map +1 -1
- package/utils/isValidJSON.js +9 -10
- package/utils/isValidJSON.js.map +1 -1
- package/utils/isValidLexicalData.js +17 -20
- package/utils/isValidLexicalData.js.map +1 -1
- package/utils/point.js +32 -45
- package/utils/point.js.map +1 -1
- package/utils/rect.js +92 -125
- package/utils/rect.js.map +1 -1
- package/utils/sanitizeUrl.js +8 -21
- package/utils/sanitizeUrl.js.map +1 -1
- package/utils/setFloatingElemPosition.js +23 -27
- package/utils/setFloatingElemPosition.js.map +1 -1
- package/commands/index.js.map +0 -1
- package/exports/admin/lexical.js.map +0 -1
- package/hooks/index.js.map +0 -1
- package/index.js.map +0 -1
- package/plugins/CodeHighlightPlugin/index.js.map +0 -1
- package/plugins/FloatingLinkEditorPlugin/index.js.map +0 -1
- package/plugins/FloatingLinkEditorPlugin/types.js.map +0 -1
- package/types.js.map +0 -1
|
@@ -1,66 +1,48 @@
|
|
|
1
1
|
import { TextNode } from "lexical";
|
|
2
2
|
import { applyColorToNode } from "./applyColorToNode.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (startOffset === 0 && endOffset === firstNodeTextLength) {
|
|
32
|
-
const fontColorNode = applyColorToNode(firstNode, color);
|
|
33
|
-
fontColorNode.select(startOffset, endOffset);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// The node is partially selected, so split it into two nodes and style the selected part.
|
|
38
|
-
const splitNodes = firstNode.splitText(startOffset, endOffset);
|
|
39
|
-
const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];
|
|
40
|
-
const fontColorNode = applyColorToNode(replacement, color);
|
|
41
|
-
fontColorNode.select(0, endOffset - startOffset);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Several nodes are selected.
|
|
46
|
-
textNodes.forEach(textNode => {
|
|
47
|
-
// First node is partially selected.
|
|
48
|
-
if (textNode === firstNode && startOffset > 0) {
|
|
49
|
-
const [, toColor] = textNode.splitText(startOffset);
|
|
50
|
-
applyColorToNode(toColor, color);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Last node is partially selected.
|
|
55
|
-
if (textNode === lastNode && lastNode.getTextContent().length !== endOffset) {
|
|
56
|
-
const [toColor] = textNode.splitText(endOffset);
|
|
57
|
-
applyColorToNode(toColor, color);
|
|
58
|
-
return;
|
|
3
|
+
function applyColorToSelection(selection, color) {
|
|
4
|
+
const textNodes = selection.getNodes().filter((node)=>node instanceof TextNode);
|
|
5
|
+
const selectedTextNodesLength = textNodes.length;
|
|
6
|
+
const startEndPoints = selection.getStartEndPoints();
|
|
7
|
+
if (null === startEndPoints) return;
|
|
8
|
+
const [anchor, focus] = startEndPoints;
|
|
9
|
+
const lastIndex = selectedTextNodesLength - 1;
|
|
10
|
+
const firstNode = textNodes[0];
|
|
11
|
+
const lastNode = textNodes[lastIndex];
|
|
12
|
+
const firstNodeText = firstNode.getTextContent();
|
|
13
|
+
const firstNodeTextLength = firstNodeText.length;
|
|
14
|
+
const focusOffset = focus.offset;
|
|
15
|
+
const anchorOffset = anchor.offset;
|
|
16
|
+
const isBefore = anchor.isBefore(focus);
|
|
17
|
+
const startOffset = isBefore ? anchorOffset : focusOffset;
|
|
18
|
+
const endOffset = isBefore ? focusOffset : anchorOffset;
|
|
19
|
+
if (startOffset === endOffset) return;
|
|
20
|
+
if (1 === selectedTextNodesLength) {
|
|
21
|
+
if (0 === startOffset && endOffset === firstNodeTextLength) {
|
|
22
|
+
const fontColorNode = applyColorToNode(firstNode, color);
|
|
23
|
+
fontColorNode.select(startOffset, endOffset);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const splitNodes = firstNode.splitText(startOffset, endOffset);
|
|
27
|
+
const replacement = 0 === startOffset ? splitNodes[0] : splitNodes[1];
|
|
28
|
+
const fontColorNode = applyColorToNode(replacement, color);
|
|
29
|
+
fontColorNode.select(0, endOffset - startOffset);
|
|
30
|
+
return;
|
|
59
31
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
32
|
+
textNodes.forEach((textNode)=>{
|
|
33
|
+
if (textNode === firstNode && startOffset > 0) {
|
|
34
|
+
const [, toColor] = textNode.splitText(startOffset);
|
|
35
|
+
applyColorToNode(toColor, color);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (textNode === lastNode && lastNode.getTextContent().length !== endOffset) {
|
|
39
|
+
const [toColor] = textNode.splitText(endOffset);
|
|
40
|
+
applyColorToNode(toColor, color);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
applyColorToNode(textNode, color);
|
|
44
|
+
});
|
|
64
45
|
}
|
|
46
|
+
export { applyColorToSelection };
|
|
65
47
|
|
|
66
48
|
//# sourceMappingURL=applyColorToSelection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"plugins/FontColorPlugin/applyColorToSelection.js","sources":["../../../src/plugins/FontColorPlugin/applyColorToSelection.ts"],"sourcesContent":["import type { RangeSelection } from \"lexical\";\nimport { TextNode } from \"lexical\";\nimport type { ThemeColorValue } from \"@webiny/lexical-nodes\";\nimport { applyColorToNode } from \"~/plugins/FontColorPlugin/applyColorToNode.js\";\n\nexport function applyColorToSelection(selection: RangeSelection, color: ThemeColorValue) {\n // Basic variables\n const textNodes = selection.getNodes().filter(node => node instanceof TextNode) as TextNode[];\n\n const selectedTextNodesLength = textNodes.length;\n const startEndPoints = selection.getStartEndPoints();\n\n if (startEndPoints === null) {\n return;\n }\n\n const [anchor, focus] = startEndPoints;\n\n const lastIndex = selectedTextNodesLength - 1;\n const firstNode = textNodes[0];\n const lastNode = textNodes[lastIndex];\n const firstNodeText = firstNode.getTextContent();\n const firstNodeTextLength = firstNodeText.length;\n const focusOffset = focus.offset;\n const anchorOffset = anchor.offset;\n const isBefore = anchor.isBefore(focus);\n const startOffset = isBefore ? anchorOffset : focusOffset;\n const endOffset = isBefore ? focusOffset : anchorOffset;\n\n // No actual text is selected, so do nothing.\n if (startOffset === endOffset) {\n return;\n }\n\n // Only one node is selected.\n if (selectedTextNodesLength === 1) {\n // The entire node is selected.\n if (startOffset === 0 && endOffset === firstNodeTextLength) {\n const fontColorNode = applyColorToNode(firstNode, color);\n fontColorNode.select(startOffset, endOffset);\n return;\n }\n\n // The node is partially selected, so split it into two nodes and style the selected part.\n const splitNodes = firstNode.splitText(startOffset, endOffset);\n const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];\n const fontColorNode = applyColorToNode(replacement, color);\n fontColorNode.select(0, endOffset - startOffset);\n\n return;\n }\n\n // Several nodes are selected.\n textNodes.forEach(textNode => {\n // First node is partially selected.\n if (textNode === firstNode && startOffset > 0) {\n const [, toColor] = textNode.splitText(startOffset);\n applyColorToNode(toColor, color);\n\n return;\n }\n\n // Last node is partially selected.\n if (textNode === lastNode && lastNode.getTextContent().length !== endOffset) {\n const [toColor] = textNode.splitText(endOffset);\n applyColorToNode(toColor, color);\n return;\n }\n\n // Colorize the whole node.\n applyColorToNode(textNode, color);\n });\n}\n"],"names":["applyColorToSelection","selection","color","textNodes","node","TextNode","selectedTextNodesLength","startEndPoints","anchor","focus","lastIndex","firstNode","lastNode","firstNodeText","firstNodeTextLength","focusOffset","anchorOffset","isBefore","startOffset","endOffset","fontColorNode","applyColorToNode","splitNodes","replacement","textNode","toColor"],"mappings":";;AAKO,SAASA,sBAAsBC,SAAyB,EAAEC,KAAsB;IAEnF,MAAMC,YAAYF,UAAU,QAAQ,GAAG,MAAM,CAACG,CAAAA,OAAQA,gBAAgBC;IAEtE,MAAMC,0BAA0BH,UAAU,MAAM;IAChD,MAAMI,iBAAiBN,UAAU,iBAAiB;IAElD,IAAIM,AAAmB,SAAnBA,gBACA;IAGJ,MAAM,CAACC,QAAQC,MAAM,GAAGF;IAExB,MAAMG,YAAYJ,0BAA0B;IAC5C,MAAMK,YAAYR,SAAS,CAAC,EAAE;IAC9B,MAAMS,WAAWT,SAAS,CAACO,UAAU;IACrC,MAAMG,gBAAgBF,UAAU,cAAc;IAC9C,MAAMG,sBAAsBD,cAAc,MAAM;IAChD,MAAME,cAAcN,MAAM,MAAM;IAChC,MAAMO,eAAeR,OAAO,MAAM;IAClC,MAAMS,WAAWT,OAAO,QAAQ,CAACC;IACjC,MAAMS,cAAcD,WAAWD,eAAeD;IAC9C,MAAMI,YAAYF,WAAWF,cAAcC;IAG3C,IAAIE,gBAAgBC,WAChB;IAIJ,IAAIb,AAA4B,MAA5BA,yBAA+B;QAE/B,IAAIY,AAAgB,MAAhBA,eAAqBC,cAAcL,qBAAqB;YACxD,MAAMM,gBAAgBC,iBAAiBV,WAAWT;YAClDkB,cAAc,MAAM,CAACF,aAAaC;YAClC;QACJ;QAGA,MAAMG,aAAaX,UAAU,SAAS,CAACO,aAAaC;QACpD,MAAMI,cAAcL,AAAgB,MAAhBA,cAAoBI,UAAU,CAAC,EAAE,GAAGA,UAAU,CAAC,EAAE;QACrE,MAAMF,gBAAgBC,iBAAiBE,aAAarB;QACpDkB,cAAc,MAAM,CAAC,GAAGD,YAAYD;QAEpC;IACJ;IAGAf,UAAU,OAAO,CAACqB,CAAAA;QAEd,IAAIA,aAAab,aAAaO,cAAc,GAAG;YAC3C,MAAM,GAAGO,QAAQ,GAAGD,SAAS,SAAS,CAACN;YACvCG,iBAAiBI,SAASvB;YAE1B;QACJ;QAGA,IAAIsB,aAAaZ,YAAYA,SAAS,cAAc,GAAG,MAAM,KAAKO,WAAW;YACzE,MAAM,CAACM,QAAQ,GAAGD,SAAS,SAAS,CAACL;YACrCE,iBAAiBI,SAASvB;YAC1B;QACJ;QAGAmB,iBAAiBG,UAAUtB;IAC/B;AACJ"}
|
|
@@ -1,148 +1,106 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
2
|
import { useEffect } from "react";
|
|
11
|
-
import { $createRangeSelection, $getSelection, $isNodeSelection, $setSelection,
|
|
3
|
+
import { $createRangeSelection, $getSelection, $isNodeSelection, $setSelection, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, mergeRegister } from "lexical";
|
|
12
4
|
import { $isImageNode, ImageNode } from "@webiny/lexical-nodes";
|
|
13
5
|
import { INSERT_IMAGE_COMMAND } from "../../commands/index.js";
|
|
14
6
|
import { CAN_USE_DOM } from "../../utils/canUseDOM.js";
|
|
15
7
|
import { insertImage } from "../../utils/insertImage.js";
|
|
16
8
|
import { useRichTextEditor } from "../../hooks/index.js";
|
|
17
|
-
const getDOMSelection = targetWindow
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}, COMMAND_PRIORITY_HIGH), editor.registerCommand(DRAGOVER_COMMAND, event => {
|
|
31
|
-
return onDragover(event);
|
|
32
|
-
}, COMMAND_PRIORITY_LOW), editor.registerCommand(DROP_COMMAND, event => {
|
|
33
|
-
return onDrop(event, editor);
|
|
34
|
-
}, COMMAND_PRIORITY_HIGH));
|
|
35
|
-
}, [captionsEnabled, editor]);
|
|
36
|
-
return null;
|
|
9
|
+
const getDOMSelection = (targetWindow)=>CAN_USE_DOM ? (targetWindow || window).getSelection() : null;
|
|
10
|
+
function ImagesPlugin({ captionsEnabled }) {
|
|
11
|
+
const { editor } = useRichTextEditor();
|
|
12
|
+
useEffect(()=>{
|
|
13
|
+
if (!editor.hasNodes([
|
|
14
|
+
ImageNode
|
|
15
|
+
])) throw new Error("ImagesPlugin: ImageNode not registered in the editor!");
|
|
16
|
+
return mergeRegister(editor.registerCommand(INSERT_IMAGE_COMMAND, (payload)=>insertImage(payload), COMMAND_PRIORITY_EDITOR), editor.registerCommand(DRAGSTART_COMMAND, (event)=>onDragStart(event), COMMAND_PRIORITY_HIGH), editor.registerCommand(DRAGOVER_COMMAND, (event)=>onDragover(event), COMMAND_PRIORITY_LOW), editor.registerCommand(DROP_COMMAND, (event)=>onDrop(event, editor), COMMAND_PRIORITY_HIGH));
|
|
17
|
+
}, [
|
|
18
|
+
captionsEnabled,
|
|
19
|
+
editor
|
|
20
|
+
]);
|
|
21
|
+
return null;
|
|
37
22
|
}
|
|
38
23
|
function getDragImage() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
img.src = TRANSPARENT_IMAGE;
|
|
45
|
-
return img;
|
|
24
|
+
if (!document) return;
|
|
25
|
+
const TRANSPARENT_IMAGE = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
26
|
+
const img = document.createElement("img");
|
|
27
|
+
img.src = TRANSPARENT_IMAGE;
|
|
28
|
+
return img;
|
|
46
29
|
}
|
|
47
30
|
function onDragStart(event) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
},
|
|
69
|
-
type: "image"
|
|
70
|
-
}));
|
|
71
|
-
return true;
|
|
31
|
+
const node = getImageNodeInSelection();
|
|
32
|
+
if (!node) return false;
|
|
33
|
+
const dataTransfer = event.dataTransfer;
|
|
34
|
+
const dragImage = getDragImage();
|
|
35
|
+
if (!dataTransfer || !dragImage) return false;
|
|
36
|
+
dataTransfer.setData("text/plain", "_");
|
|
37
|
+
dataTransfer.setDragImage(dragImage, 0, 0);
|
|
38
|
+
dataTransfer.setData("application/x-lexical-drag", JSON.stringify({
|
|
39
|
+
data: {
|
|
40
|
+
id: node.__id,
|
|
41
|
+
altText: node.__altText,
|
|
42
|
+
height: node.__height,
|
|
43
|
+
key: node.getKey(),
|
|
44
|
+
maxWidth: node.__maxWidth,
|
|
45
|
+
src: node.__src,
|
|
46
|
+
width: node.__width
|
|
47
|
+
},
|
|
48
|
+
type: "image"
|
|
49
|
+
}));
|
|
50
|
+
return true;
|
|
72
51
|
}
|
|
73
52
|
function onDragover(event) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (!canDropImage(event)) {
|
|
79
|
-
event.preventDefault();
|
|
80
|
-
}
|
|
81
|
-
return true;
|
|
53
|
+
const node = getImageNodeInSelection();
|
|
54
|
+
if (!node) return false;
|
|
55
|
+
if (!canDropImage(event)) event.preventDefault();
|
|
56
|
+
return true;
|
|
82
57
|
}
|
|
83
58
|
function onDrop(event, editor) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const rangeSelection = $createRangeSelection();
|
|
97
|
-
if (range !== null && range !== undefined) {
|
|
98
|
-
rangeSelection.applyDOMRange(range);
|
|
59
|
+
const node = getImageNodeInSelection();
|
|
60
|
+
if (!node) return false;
|
|
61
|
+
const data = getDragImageData(event);
|
|
62
|
+
if (!data) return false;
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
if (canDropImage(event)) {
|
|
65
|
+
const range = getDragSelection(event);
|
|
66
|
+
node.remove();
|
|
67
|
+
const rangeSelection = $createRangeSelection();
|
|
68
|
+
if (null != range) rangeSelection.applyDOMRange(range);
|
|
69
|
+
$setSelection(rangeSelection);
|
|
70
|
+
editor.dispatchCommand(INSERT_IMAGE_COMMAND, data);
|
|
99
71
|
}
|
|
100
|
-
|
|
101
|
-
editor.dispatchCommand(INSERT_IMAGE_COMMAND, data);
|
|
102
|
-
}
|
|
103
|
-
return true;
|
|
72
|
+
return true;
|
|
104
73
|
}
|
|
105
74
|
function getImageNodeInSelection() {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const node = nodes[0];
|
|
112
|
-
return $isImageNode(node) ? node : null;
|
|
75
|
+
const selection = $getSelection();
|
|
76
|
+
if (!$isNodeSelection(selection)) return null;
|
|
77
|
+
const nodes = selection.getNodes();
|
|
78
|
+
const node = nodes[0];
|
|
79
|
+
return $isImageNode(node) ? node : null;
|
|
113
80
|
}
|
|
114
81
|
function getDragImageData(event) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
type,
|
|
121
|
-
data
|
|
122
|
-
} = JSON.parse(dragData);
|
|
123
|
-
if (type !== "image") {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
return data;
|
|
82
|
+
const dragData = event.dataTransfer?.getData("application/x-lexical-drag");
|
|
83
|
+
if (!dragData) return null;
|
|
84
|
+
const { type, data } = JSON.parse(dragData);
|
|
85
|
+
if ("image" !== type) return null;
|
|
86
|
+
return data;
|
|
127
87
|
}
|
|
128
88
|
function canDropImage(event) {
|
|
129
|
-
|
|
130
|
-
|
|
89
|
+
const target = event.target;
|
|
90
|
+
return !!(target && target instanceof HTMLElement && !target.closest("code, span.editor-image") && target.parentElement && target.parentElement.closest("div.ContentEditable__root"));
|
|
131
91
|
}
|
|
132
92
|
function getDragSelection(event) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
throw Error(`Cannot get the selection when dragging`);
|
|
144
|
-
}
|
|
145
|
-
return range;
|
|
93
|
+
let range;
|
|
94
|
+
const target = event.target;
|
|
95
|
+
const targetWindow = null == target ? null : 9 === target.nodeType ? target.defaultView : target.ownerDocument.defaultView;
|
|
96
|
+
const domSelection = getDOMSelection(targetWindow);
|
|
97
|
+
if (document.caretRangeFromPoint) range = document.caretRangeFromPoint(event.clientX, event.clientY);
|
|
98
|
+
else if (event.rangeParent && null !== domSelection) {
|
|
99
|
+
domSelection.collapse(event.rangeParent, event.rangeOffset || 0);
|
|
100
|
+
range = domSelection.getRangeAt(0);
|
|
101
|
+
} else throw Error("Cannot get the selection when dragging");
|
|
102
|
+
return range;
|
|
146
103
|
}
|
|
104
|
+
export { ImagesPlugin };
|
|
147
105
|
|
|
148
106
|
//# sourceMappingURL=ImagesPlugin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","$createRangeSelection","$getSelection","$isNodeSelection","$setSelection","mergeRegister","COMMAND_PRIORITY_EDITOR","COMMAND_PRIORITY_HIGH","COMMAND_PRIORITY_LOW","DRAGOVER_COMMAND","DRAGSTART_COMMAND","DROP_COMMAND","$isImageNode","ImageNode","INSERT_IMAGE_COMMAND","CAN_USE_DOM","insertImage","useRichTextEditor","getDOMSelection","targetWindow","window","getSelection","ImagesPlugin","captionsEnabled","editor","hasNodes","Error","registerCommand","payload","event","onDragStart","onDragover","onDrop","getDragImage","document","undefined","TRANSPARENT_IMAGE","img","createElement","src","node","getImageNodeInSelection","dataTransfer","dragImage","setData","setDragImage","JSON","stringify","data","id","__id","altText","__altText","height","__height","key","getKey","maxWidth","__maxWidth","__src","width","__width","type","canDropImage","preventDefault","getDragImageData","range","getDragSelection","remove","rangeSelection","applyDOMRange","dispatchCommand","selection","nodes","getNodes","dragData","getData","parse","target","HTMLElement","closest","parentElement","nodeType","defaultView","ownerDocument","domSelection","caretRangeFromPoint","clientX","clientY","rangeParent","collapse","rangeOffset","getRangeAt"],"sources":["ImagesPlugin.tsx"],"sourcesContent":["\"use client\";\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\nimport { useEffect } from \"react\";\nimport type { LexicalEditor } from \"lexical\";\nimport {\n $createRangeSelection,\n $getSelection,\n $isNodeSelection,\n $setSelection,\n mergeRegister,\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_HIGH,\n COMMAND_PRIORITY_LOW,\n DRAGOVER_COMMAND,\n DRAGSTART_COMMAND,\n DROP_COMMAND\n} from \"lexical\";\nimport { $isImageNode, ImageNode } from \"@webiny/lexical-nodes\";\nimport type { ImagePayload } from \"~/commands/index.js\";\nimport { INSERT_IMAGE_COMMAND } from \"~/commands/index.js\";\nimport { CAN_USE_DOM } from \"~/utils/canUseDOM.js\";\nimport { insertImage } from \"~/utils/insertImage.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\n\nexport type InsertImagePayload = Readonly<ImagePayload>;\n\nconst getDOMSelection = (targetWindow: Window | null): Selection | null =>\n CAN_USE_DOM ? (targetWindow || window).getSelection() : null;\n\nexport function ImagesPlugin({\n captionsEnabled\n}: {\n captionsEnabled?: boolean;\n}): React.JSX.Element | null {\n const { editor } = useRichTextEditor();\n\n useEffect(() => {\n if (!editor.hasNodes([ImageNode])) {\n throw new Error(\"ImagesPlugin: ImageNode not registered in the editor!\");\n }\n\n return mergeRegister(\n editor.registerCommand<InsertImagePayload>(\n INSERT_IMAGE_COMMAND,\n payload => insertImage(payload),\n COMMAND_PRIORITY_EDITOR\n ),\n editor.registerCommand<DragEvent>(\n DRAGSTART_COMMAND,\n event => {\n return onDragStart(event);\n },\n COMMAND_PRIORITY_HIGH\n ),\n editor.registerCommand<DragEvent>(\n DRAGOVER_COMMAND,\n event => {\n return onDragover(event);\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand<DragEvent>(\n DROP_COMMAND,\n event => {\n return onDrop(event, editor);\n },\n COMMAND_PRIORITY_HIGH\n )\n );\n }, [captionsEnabled, editor]);\n\n return null;\n}\n\nfunction getDragImage() {\n if (!document) {\n return undefined;\n }\n\n const TRANSPARENT_IMAGE =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\";\n const img = document.createElement(\"img\");\n img.src = TRANSPARENT_IMAGE;\n return img;\n}\n\nfunction onDragStart(event: DragEvent): boolean {\n const node = getImageNodeInSelection();\n if (!node) {\n return false;\n }\n const dataTransfer = event.dataTransfer;\n const dragImage = getDragImage();\n if (!dataTransfer || !dragImage) {\n return false;\n }\n dataTransfer.setData(\"text/plain\", \"_\");\n dataTransfer.setDragImage(dragImage, 0, 0);\n dataTransfer.setData(\n \"application/x-lexical-drag\",\n JSON.stringify({\n data: {\n id: node.__id,\n altText: node.__altText,\n height: node.__height,\n key: node.getKey(),\n maxWidth: node.__maxWidth,\n src: node.__src,\n width: node.__width\n },\n type: \"image\"\n })\n );\n\n return true;\n}\n\nfunction onDragover(event: DragEvent): boolean {\n const node = getImageNodeInSelection();\n if (!node) {\n return false;\n }\n if (!canDropImage(event)) {\n event.preventDefault();\n }\n return true;\n}\n\nfunction onDrop(event: DragEvent, editor: LexicalEditor): boolean {\n const node = getImageNodeInSelection();\n if (!node) {\n return false;\n }\n const data = getDragImageData(event);\n if (!data) {\n return false;\n }\n event.preventDefault();\n if (canDropImage(event)) {\n const range = getDragSelection(event);\n node.remove();\n const rangeSelection = $createRangeSelection();\n if (range !== null && range !== undefined) {\n rangeSelection.applyDOMRange(range);\n }\n $setSelection(rangeSelection);\n editor.dispatchCommand(INSERT_IMAGE_COMMAND, data);\n }\n return true;\n}\n\nfunction getImageNodeInSelection(): ImageNode | null {\n const selection = $getSelection();\n if (!$isNodeSelection(selection)) {\n return null;\n }\n const nodes = selection.getNodes();\n const node = nodes[0];\n return $isImageNode(node) ? node : null;\n}\n\nfunction getDragImageData(event: DragEvent): null | InsertImagePayload {\n const dragData = event.dataTransfer?.getData(\"application/x-lexical-drag\");\n if (!dragData) {\n return null;\n }\n const { type, data } = JSON.parse(dragData);\n if (type !== \"image\") {\n return null;\n }\n\n return data;\n}\n\ndeclare global {\n interface DragEvent {\n rangeOffset?: number;\n rangeParent?: Node;\n }\n}\n\nfunction canDropImage(event: DragEvent): boolean {\n const target = event.target;\n return !!(\n target &&\n target instanceof HTMLElement &&\n !target.closest(\"code, span.editor-image\") &&\n target.parentElement &&\n target.parentElement.closest(\"div.ContentEditable__root\")\n );\n}\n\nfunction getDragSelection(event: DragEvent): Range | null | undefined {\n let range;\n const target = event.target as null | Element | Document;\n const targetWindow =\n target == null\n ? null\n : target.nodeType === 9\n ? (target as Document).defaultView\n : (target as Element).ownerDocument.defaultView;\n const domSelection = getDOMSelection(targetWindow);\n if (document.caretRangeFromPoint) {\n range = document.caretRangeFromPoint(event.clientX, event.clientY);\n } else if (event.rangeParent && domSelection !== null) {\n domSelection.collapse(event.rangeParent, event.rangeOffset || 0);\n range = domSelection.getRangeAt(0);\n } else {\n throw Error(`Cannot get the selection when dragging`);\n }\n\n return range;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"plugins/ImagesPlugin/ImagesPlugin.js","sources":["../../../src/plugins/ImagesPlugin/ImagesPlugin.tsx"],"sourcesContent":["\"use client\";\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\nimport { useEffect } from \"react\";\nimport type { LexicalEditor } from \"lexical\";\nimport {\n $createRangeSelection,\n $getSelection,\n $isNodeSelection,\n $setSelection,\n mergeRegister,\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_HIGH,\n COMMAND_PRIORITY_LOW,\n DRAGOVER_COMMAND,\n DRAGSTART_COMMAND,\n DROP_COMMAND\n} from \"lexical\";\nimport { $isImageNode, ImageNode } from \"@webiny/lexical-nodes\";\nimport type { ImagePayload } from \"~/commands/index.js\";\nimport { INSERT_IMAGE_COMMAND } from \"~/commands/index.js\";\nimport { CAN_USE_DOM } from \"~/utils/canUseDOM.js\";\nimport { insertImage } from \"~/utils/insertImage.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\n\nexport type InsertImagePayload = Readonly<ImagePayload>;\n\nconst getDOMSelection = (targetWindow: Window | null): Selection | null =>\n CAN_USE_DOM ? (targetWindow || window).getSelection() : null;\n\nexport function ImagesPlugin({\n captionsEnabled\n}: {\n captionsEnabled?: boolean;\n}): React.JSX.Element | null {\n const { editor } = useRichTextEditor();\n\n useEffect(() => {\n if (!editor.hasNodes([ImageNode])) {\n throw new Error(\"ImagesPlugin: ImageNode not registered in the editor!\");\n }\n\n return mergeRegister(\n editor.registerCommand<InsertImagePayload>(\n INSERT_IMAGE_COMMAND,\n payload => insertImage(payload),\n COMMAND_PRIORITY_EDITOR\n ),\n editor.registerCommand<DragEvent>(\n DRAGSTART_COMMAND,\n event => {\n return onDragStart(event);\n },\n COMMAND_PRIORITY_HIGH\n ),\n editor.registerCommand<DragEvent>(\n DRAGOVER_COMMAND,\n event => {\n return onDragover(event);\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand<DragEvent>(\n DROP_COMMAND,\n event => {\n return onDrop(event, editor);\n },\n COMMAND_PRIORITY_HIGH\n )\n );\n }, [captionsEnabled, editor]);\n\n return null;\n}\n\nfunction getDragImage() {\n if (!document) {\n return undefined;\n }\n\n const TRANSPARENT_IMAGE =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\";\n const img = document.createElement(\"img\");\n img.src = TRANSPARENT_IMAGE;\n return img;\n}\n\nfunction onDragStart(event: DragEvent): boolean {\n const node = getImageNodeInSelection();\n if (!node) {\n return false;\n }\n const dataTransfer = event.dataTransfer;\n const dragImage = getDragImage();\n if (!dataTransfer || !dragImage) {\n return false;\n }\n dataTransfer.setData(\"text/plain\", \"_\");\n dataTransfer.setDragImage(dragImage, 0, 0);\n dataTransfer.setData(\n \"application/x-lexical-drag\",\n JSON.stringify({\n data: {\n id: node.__id,\n altText: node.__altText,\n height: node.__height,\n key: node.getKey(),\n maxWidth: node.__maxWidth,\n src: node.__src,\n width: node.__width\n },\n type: \"image\"\n })\n );\n\n return true;\n}\n\nfunction onDragover(event: DragEvent): boolean {\n const node = getImageNodeInSelection();\n if (!node) {\n return false;\n }\n if (!canDropImage(event)) {\n event.preventDefault();\n }\n return true;\n}\n\nfunction onDrop(event: DragEvent, editor: LexicalEditor): boolean {\n const node = getImageNodeInSelection();\n if (!node) {\n return false;\n }\n const data = getDragImageData(event);\n if (!data) {\n return false;\n }\n event.preventDefault();\n if (canDropImage(event)) {\n const range = getDragSelection(event);\n node.remove();\n const rangeSelection = $createRangeSelection();\n if (range !== null && range !== undefined) {\n rangeSelection.applyDOMRange(range);\n }\n $setSelection(rangeSelection);\n editor.dispatchCommand(INSERT_IMAGE_COMMAND, data);\n }\n return true;\n}\n\nfunction getImageNodeInSelection(): ImageNode | null {\n const selection = $getSelection();\n if (!$isNodeSelection(selection)) {\n return null;\n }\n const nodes = selection.getNodes();\n const node = nodes[0];\n return $isImageNode(node) ? node : null;\n}\n\nfunction getDragImageData(event: DragEvent): null | InsertImagePayload {\n const dragData = event.dataTransfer?.getData(\"application/x-lexical-drag\");\n if (!dragData) {\n return null;\n }\n const { type, data } = JSON.parse(dragData);\n if (type !== \"image\") {\n return null;\n }\n\n return data;\n}\n\ndeclare global {\n interface DragEvent {\n rangeOffset?: number;\n rangeParent?: Node;\n }\n}\n\nfunction canDropImage(event: DragEvent): boolean {\n const target = event.target;\n return !!(\n target &&\n target instanceof HTMLElement &&\n !target.closest(\"code, span.editor-image\") &&\n target.parentElement &&\n target.parentElement.closest(\"div.ContentEditable__root\")\n );\n}\n\nfunction getDragSelection(event: DragEvent): Range | null | undefined {\n let range;\n const target = event.target as null | Element | Document;\n const targetWindow =\n target == null\n ? null\n : target.nodeType === 9\n ? (target as Document).defaultView\n : (target as Element).ownerDocument.defaultView;\n const domSelection = getDOMSelection(targetWindow);\n if (document.caretRangeFromPoint) {\n range = document.caretRangeFromPoint(event.clientX, event.clientY);\n } else if (event.rangeParent && domSelection !== null) {\n domSelection.collapse(event.rangeParent, event.rangeOffset || 0);\n range = domSelection.getRangeAt(0);\n } else {\n throw Error(`Cannot get the selection when dragging`);\n }\n\n return range;\n}\n"],"names":["getDOMSelection","targetWindow","CAN_USE_DOM","window","ImagesPlugin","captionsEnabled","editor","useRichTextEditor","useEffect","ImageNode","Error","mergeRegister","INSERT_IMAGE_COMMAND","payload","insertImage","COMMAND_PRIORITY_EDITOR","DRAGSTART_COMMAND","event","onDragStart","COMMAND_PRIORITY_HIGH","DRAGOVER_COMMAND","onDragover","COMMAND_PRIORITY_LOW","DROP_COMMAND","onDrop","getDragImage","document","TRANSPARENT_IMAGE","img","node","getImageNodeInSelection","dataTransfer","dragImage","JSON","canDropImage","data","getDragImageData","range","getDragSelection","rangeSelection","$createRangeSelection","$setSelection","selection","$getSelection","$isNodeSelection","nodes","$isImageNode","dragData","type","target","HTMLElement","domSelection"],"mappings":"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"}
|
|
@@ -1,58 +1,52 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
|
-
import { $getSelection, $isElementNode, $isRangeSelection,
|
|
2
|
+
import { $getSelection, $isElementNode, $isRangeSelection, COMMAND_PRIORITY_LOW, PASTE_COMMAND, mergeRegister } from "lexical";
|
|
3
3
|
import { LinkNode, TOGGLE_LINK_COMMAND, toggleLink } from "@webiny/lexical-nodes";
|
|
4
4
|
import { useRichTextEditor } from "../../hooks/index.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
return false;
|
|
51
|
-
}, COMMAND_PRIORITY_LOW));
|
|
52
|
-
}
|
|
53
|
-
return mergeRegister(...commands);
|
|
54
|
-
}, [editor, validateUrl]);
|
|
55
|
-
return null;
|
|
5
|
+
function LinkPlugin({ validateUrl }) {
|
|
6
|
+
const { editor } = useRichTextEditor();
|
|
7
|
+
useEffect(()=>{
|
|
8
|
+
if (!editor.hasNodes([
|
|
9
|
+
LinkNode
|
|
10
|
+
])) throw new Error("LinkPlugin: LinkNode not registered in the editor!");
|
|
11
|
+
const commands = [
|
|
12
|
+
editor.registerCommand(TOGGLE_LINK_COMMAND, (payload)=>{
|
|
13
|
+
if (null === payload) {
|
|
14
|
+
toggleLink(payload);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
if ("string" == typeof payload) {
|
|
18
|
+
if (void 0 === validateUrl || validateUrl(payload)) {
|
|
19
|
+
toggleLink(payload);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
{
|
|
25
|
+
const { url, ...attrs } = payload;
|
|
26
|
+
toggleLink(url, attrs);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}, COMMAND_PRIORITY_LOW)
|
|
30
|
+
];
|
|
31
|
+
if (void 0 !== validateUrl) commands.push(editor.registerCommand(PASTE_COMMAND, (event)=>{
|
|
32
|
+
const selection = $getSelection();
|
|
33
|
+
if (!$isRangeSelection(selection) || selection.isCollapsed() || !(event instanceof ClipboardEvent) || null == event.clipboardData) return false;
|
|
34
|
+
const clipboardText = event.clipboardData.getData("text");
|
|
35
|
+
if (!validateUrl(clipboardText)) return false;
|
|
36
|
+
if (!selection.getNodes().some((node)=>$isElementNode(node))) {
|
|
37
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, clipboardText);
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}, COMMAND_PRIORITY_LOW));
|
|
43
|
+
return mergeRegister(...commands);
|
|
44
|
+
}, [
|
|
45
|
+
editor,
|
|
46
|
+
validateUrl
|
|
47
|
+
]);
|
|
48
|
+
return null;
|
|
56
49
|
}
|
|
50
|
+
export { LinkPlugin };
|
|
57
51
|
|
|
58
52
|
//# sourceMappingURL=LinkPlugin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"plugins/LinkPlugin/LinkPlugin.js","sources":["../../../src/plugins/LinkPlugin/LinkPlugin.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport {\n $getSelection,\n $isElementNode,\n $isRangeSelection,\n mergeRegister,\n COMMAND_PRIORITY_LOW,\n PASTE_COMMAND\n} from \"lexical\";\nimport { LinkNode, TOGGLE_LINK_COMMAND, toggleLink } from \"@webiny/lexical-nodes\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\n\ntype Props = {\n validateUrl?: (url: string) => boolean;\n};\n\nexport function LinkPlugin({ validateUrl }: Props): null {\n const { editor } = useRichTextEditor();\n\n useEffect(() => {\n if (!editor.hasNodes([LinkNode])) {\n throw new Error(\"LinkPlugin: LinkNode not registered in the editor!\");\n }\n\n const commands = [\n editor.registerCommand(\n TOGGLE_LINK_COMMAND,\n payload => {\n if (payload === null) {\n toggleLink(payload);\n return true;\n } else if (typeof payload === \"string\") {\n if (validateUrl === undefined || validateUrl(payload)) {\n toggleLink(payload);\n return true;\n }\n return false;\n } else {\n const { url, ...attrs } = payload;\n toggleLink(url, attrs);\n return true;\n }\n },\n COMMAND_PRIORITY_LOW\n )\n ];\n\n if (validateUrl !== undefined) {\n commands.push(\n editor.registerCommand(\n PASTE_COMMAND,\n event => {\n const selection = $getSelection();\n if (\n !$isRangeSelection(selection) ||\n selection.isCollapsed() ||\n !(event instanceof ClipboardEvent) ||\n event.clipboardData == null\n ) {\n return false;\n }\n const clipboardText = event.clipboardData.getData(\"text\");\n if (!validateUrl(clipboardText)) {\n return false;\n }\n // If we select nodes that are elements then avoid applying the link.\n if (!selection.getNodes().some(node => $isElementNode(node))) {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, clipboardText);\n event.preventDefault();\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_LOW\n )\n );\n }\n\n return mergeRegister(...commands);\n }, [editor, validateUrl]);\n\n return null;\n}\n"],"names":["LinkPlugin","validateUrl","editor","useRichTextEditor","useEffect","LinkNode","Error","commands","TOGGLE_LINK_COMMAND","payload","toggleLink","undefined","url","attrs","COMMAND_PRIORITY_LOW","PASTE_COMMAND","event","selection","$getSelection","$isRangeSelection","ClipboardEvent","clipboardText","node","$isElementNode","mergeRegister"],"mappings":";;;;AAgBO,SAASA,WAAW,EAAEC,WAAW,EAAS;IAC7C,MAAM,EAAEC,MAAM,EAAE,GAAGC;IAEnBC,UAAU;QACN,IAAI,CAACF,OAAO,QAAQ,CAAC;YAACG;SAAS,GAC3B,MAAM,IAAIC,MAAM;QAGpB,MAAMC,WAAW;YACbL,OAAO,eAAe,CAClBM,qBACAC,CAAAA;gBACI,IAAIA,AAAY,SAAZA,SAAkB;oBAClBC,WAAWD;oBACX,OAAO;gBACX;gBAAO,IAAI,AAAmB,YAAnB,OAAOA,SAAsB;oBACpC,IAAIR,AAAgBU,WAAhBV,eAA6BA,YAAYQ,UAAU;wBACnDC,WAAWD;wBACX,OAAO;oBACX;oBACA,OAAO;gBACX;gBAAO;oBACH,MAAM,EAAEG,GAAG,EAAE,GAAGC,OAAO,GAAGJ;oBAC1BC,WAAWE,KAAKC;oBAChB,OAAO;gBACX;YACJ,GACAC;SAEP;QAED,IAAIb,AAAgBU,WAAhBV,aACAM,SAAS,IAAI,CACTL,OAAO,eAAe,CAClBa,eACAC,CAAAA;YACI,MAAMC,YAAYC;YAClB,IACI,CAACC,kBAAkBF,cACnBA,UAAU,WAAW,MACrB,CAAED,CAAAA,iBAAiBI,cAAa,KAChCJ,AAAuB,QAAvBA,MAAM,aAAa,EAEnB,OAAO;YAEX,MAAMK,gBAAgBL,MAAM,aAAa,CAAC,OAAO,CAAC;YAClD,IAAI,CAACf,YAAYoB,gBACb,OAAO;YAGX,IAAI,CAACJ,UAAU,QAAQ,GAAG,IAAI,CAACK,CAAAA,OAAQC,eAAeD,QAAQ;gBAC1DpB,OAAO,eAAe,CAACM,qBAAqBa;gBAC5CL,MAAM,cAAc;gBACpB,OAAO;YACX;YACA,OAAO;QACX,GACAF;QAKZ,OAAOU,iBAAiBjB;IAC5B,GAAG;QAACL;QAAQD;KAAY;IAExB,OAAO;AACX"}
|