@webiny/lexical-editor 6.4.11 → 6.6.0-alpha.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/components/Editor/EditorPlaceholder.d.ts +15 -0
- package/components/Editor/EditorPlaceholder.js +41 -0
- package/components/Editor/EditorPlaceholder.js.map +1 -0
- package/components/Editor/RichTextEditor.js +7 -5
- package/components/Editor/RichTextEditor.js.map +1 -1
- package/components/LexicalEditorConfig/LexicalEditorConfig.d.ts +6 -3
- package/components/Toolbar/StaticToolbar.css +95 -191
- package/components/ToolbarActions/BoldAction.js +7 -3
- package/components/ToolbarActions/BoldAction.js.map +1 -1
- package/components/ToolbarActions/BulletListAction.js +7 -3
- package/components/ToolbarActions/BulletListAction.js.map +1 -1
- package/components/ToolbarActions/CodeHighlightAction.js +7 -3
- package/components/ToolbarActions/CodeHighlightAction.js.map +1 -1
- package/components/ToolbarActions/FontSizeAction.js +2 -1
- package/components/ToolbarActions/FontSizeAction.js.map +1 -1
- package/components/ToolbarActions/ImageAction.js +3 -2
- package/components/ToolbarActions/ImageAction.js.map +1 -1
- package/components/ToolbarActions/ItalicAction.js +7 -3
- package/components/ToolbarActions/ItalicAction.js.map +1 -1
- package/components/ToolbarActions/LinkAction.js +7 -3
- package/components/ToolbarActions/LinkAction.js.map +1 -1
- package/components/ToolbarActions/NumberedListAction.js +7 -3
- package/components/ToolbarActions/NumberedListAction.js.map +1 -1
- package/components/ToolbarActions/QuoteAction.js +7 -3
- package/components/ToolbarActions/QuoteAction.js.map +1 -1
- package/components/ToolbarActions/UnderlineAction.js +7 -3
- package/components/ToolbarActions/UnderlineAction.js.map +1 -1
- package/hooks/useCurrentElement.d.ts +2 -2
- package/package.json +17 -15
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js +1 -1
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js.map +1 -1
- package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin.css +4 -3
- package/ui/DropDown.d.ts +4 -2
- package/ui/DropDown.js +13 -5
- package/ui/DropDown.js.map +1 -1
- package/ui/Placeholder.css +2 -1
- package/ui/Placeholder.js +1 -1
- package/ui/Placeholder.js.map +1 -1
- package/ui/ToolbarActionDialog.js +2 -1
- package/ui/ToolbarActionDialog.js.map +1 -1
- package/utils/rect.d.ts +2 -2
- package/images/icons/chat-square-quote.js +0 -19
- package/images/icons/chat-square-quote.js.map +0 -1
- package/images/icons/chat-square-quote.svg +0 -1
- package/images/icons/chevron-down.js +0 -18
- package/images/icons/chevron-down.js.map +0 -1
- package/images/icons/chevron-down.svg +0 -1
- package/images/icons/code.js +0 -17
- package/images/icons/code.js.map +0 -1
- package/images/icons/code.svg +0 -1
- package/images/icons/font-color.js +0 -17
- package/images/icons/font-color.js.map +0 -1
- package/images/icons/font-color.svg +0 -1
- package/images/icons/indent.js +0 -18
- package/images/icons/indent.js.map +0 -1
- package/images/icons/indent.svg +0 -3
- package/images/icons/insert-image.js +0 -20
- package/images/icons/insert-image.js.map +0 -1
- package/images/icons/insert-image.svg +0 -4
- package/images/icons/justify.js +0 -19
- package/images/icons/justify.js.map +0 -1
- package/images/icons/justify.svg +0 -3
- package/images/icons/link.js +0 -19
- package/images/icons/link.js.map +0 -1
- package/images/icons/link.svg +0 -1
- package/images/icons/list-ol.js +0 -20
- package/images/icons/list-ol.js.map +0 -1
- package/images/icons/list-ol.svg +0 -1
- package/images/icons/list-ul.js +0 -18
- package/images/icons/list-ul.js.map +0 -1
- package/images/icons/list-ul.svg +0 -1
- package/images/icons/outdent.js +0 -18
- package/images/icons/outdent.js.map +0 -1
- package/images/icons/outdent.svg +0 -3
- package/images/icons/text-center.js +0 -18
- package/images/icons/text-center.js.map +0 -1
- package/images/icons/text-center.svg +0 -1
- package/images/icons/text-left.js +0 -18
- package/images/icons/text-left.js.map +0 -1
- package/images/icons/text-left.svg +0 -1
- package/images/icons/text-right.js +0 -18
- package/images/icons/text-right.js.map +0 -1
- package/images/icons/text-right.svg +0 -1
- package/images/icons/type-bold.js +0 -17
- package/images/icons/type-bold.js.map +0 -1
- package/images/icons/type-bold.svg +0 -1
- package/images/icons/type-italic.js +0 -17
- package/images/icons/type-italic.js.map +0 -1
- package/images/icons/type-italic.svg +0 -1
- package/images/icons/type-strikethrough.js +0 -17
- package/images/icons/type-strikethrough.js.map +0 -1
- package/images/icons/type-strikethrough.svg +0 -1
- package/images/icons/type-underline.js +0 -17
- package/images/icons/type-underline.js.map +0 -1
- package/images/icons/type-underline.svg +0 -1
- package/static/svg/chat-square-quote.123cfa24.svg +0 -1
- package/static/svg/chevron-down.d9636921.svg +0 -1
- package/static/svg/code.912b1f4d.svg +0 -1
- package/static/svg/font-color.4f0c0de5.svg +0 -1
- package/static/svg/indent.4d78e483.svg +0 -3
- package/static/svg/insert-image.354465f1.svg +0 -4
- package/static/svg/justify.dab42aec.svg +0 -3
- package/static/svg/link.b774de25.svg +0 -1
- package/static/svg/list-ol.d64946f3.svg +0 -1
- package/static/svg/list-ul.1d54da3f.svg +0 -1
- package/static/svg/outdent.5c13ff16.svg +0 -3
- package/static/svg/text-center.a411e780.svg +0 -1
- package/static/svg/text-left.54f41f4e.svg +0 -1
- package/static/svg/text-right.9288b7a2.svg +0 -1
- package/static/svg/type-bold.7e3e270b.svg +0 -1
- package/static/svg/type-italic.d8e45748.svg +0 -1
- package/static/svg/type-strikethrough.2694a816.svg +0 -1
- package/static/svg/type-underline.104a0ed5.svg +0 -1
|
@@ -2,6 +2,8 @@ import react from "react";
|
|
|
2
2
|
import { FORMAT_TEXT_COMMAND } from "lexical";
|
|
3
3
|
import { useCurrentSelection } from "../../hooks/useCurrentSelection.js";
|
|
4
4
|
import { useRichTextEditor } from "../../hooks/index.js";
|
|
5
|
+
import { ReactComponent } from "@webiny/icons/format_bold.svg";
|
|
6
|
+
import clsx from "clsx";
|
|
5
7
|
const BoldAction = ()=>{
|
|
6
8
|
const { editor } = useRichTextEditor();
|
|
7
9
|
const { rangeSelection } = useCurrentSelection();
|
|
@@ -11,10 +13,12 @@ const BoldAction = ()=>{
|
|
|
11
13
|
};
|
|
12
14
|
return /*#__PURE__*/ react.createElement("button", {
|
|
13
15
|
onClick: handleClick,
|
|
14
|
-
className: "popup-item
|
|
16
|
+
className: clsx("popup-item", "spaced", {
|
|
17
|
+
active: isBoldSelected
|
|
18
|
+
}),
|
|
15
19
|
"aria-label": "Format text as bold"
|
|
16
|
-
}, /*#__PURE__*/ react.createElement(
|
|
17
|
-
className: "format
|
|
20
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
21
|
+
className: "format"
|
|
18
22
|
}));
|
|
19
23
|
};
|
|
20
24
|
export { BoldAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/BoldAction.js","sources":["../../../src/components/ToolbarActions/BoldAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\n\nexport const BoldAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isBoldSelected = rangeSelection ? rangeSelection.hasFormat(\"bold\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"bold\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/BoldAction.js","sources":["../../../src/components/ToolbarActions/BoldAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { ReactComponent as BoldIcon } from \"@webiny/icons/format_bold.svg\";\nimport cn from \"clsx\";\n\nexport const BoldAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isBoldSelected = rangeSelection ? rangeSelection.hasFormat(\"bold\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"bold\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={cn(\"popup-item\", \"spaced\", { active: isBoldSelected })}\n aria-label=\"Format text as bold\"\n >\n <BoldIcon className=\"format\" />\n </button>\n );\n};\n"],"names":["BoldAction","editor","useRichTextEditor","rangeSelection","useCurrentSelection","isBoldSelected","handleClick","FORMAT_TEXT_COMMAND","cn","BoldIcon"],"mappings":";;;;;;AAOO,MAAMA,aAAa;IACtB,MAAM,EAAEC,MAAM,EAAE,GAAGC;IACnB,MAAM,EAAEC,cAAc,EAAE,GAAGC;IAC3B,MAAMC,iBAAiBF,iBAAiBA,eAAe,SAAS,CAAC,UAAU;IAE3E,MAAMG,cAAc;QAChBL,OAAO,eAAe,CAACM,qBAAqB;IAChD;IAEA,OAAO,WAAP,GACI,oBAAC;QACG,SAASD;QACT,WAAWE,KAAG,cAAc,UAAU;YAAE,QAAQH;QAAe;QAC/D,cAAW;qBAEX,oBAACI,gBAAQA;QAAC,WAAU;;AAGhC"}
|
|
@@ -3,6 +3,8 @@ import { INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND } from "../../comman
|
|
|
3
3
|
import { useRichTextEditor } from "../../hooks/useRichTextEditor.js";
|
|
4
4
|
import { $isListNode } from "@webiny/lexical-nodes";
|
|
5
5
|
import { useCurrentElement } from "../../hooks/useCurrentElement.js";
|
|
6
|
+
import { ReactComponent } from "@webiny/icons/format_list_bulleted.svg";
|
|
7
|
+
import clsx from "clsx";
|
|
6
8
|
const BulletListAction = ()=>{
|
|
7
9
|
const { editor } = useRichTextEditor();
|
|
8
10
|
const { element } = useCurrentElement();
|
|
@@ -20,10 +22,12 @@ const BulletListAction = ()=>{
|
|
|
20
22
|
};
|
|
21
23
|
return /*#__PURE__*/ react.createElement("button", {
|
|
22
24
|
onClick: ()=>formatBulletList(),
|
|
23
|
-
className: "popup-item
|
|
25
|
+
className: clsx("popup-item", "spaced", {
|
|
26
|
+
active: isBullet
|
|
27
|
+
}),
|
|
24
28
|
"aria-label": "Format text as bullet list"
|
|
25
|
-
}, /*#__PURE__*/ react.createElement(
|
|
26
|
-
className: "icon
|
|
29
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
30
|
+
className: "icon"
|
|
27
31
|
}));
|
|
28
32
|
};
|
|
29
33
|
export { BulletListAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/BulletListAction.js","sources":["../../../src/components/ToolbarActions/BulletListAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND } from \"~/commands/index.js\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport type { ListNode } from \"@webiny/lexical-nodes\";\nimport { $isListNode } from \"@webiny/lexical-nodes\";\nimport { useCurrentElement } from \"~/hooks/useCurrentElement.js\";\n\nexport const BulletListAction = () => {\n const { editor } = useRichTextEditor();\n const { element } = useCurrentElement();\n const { theme } = useRichTextEditor();\n const isList = $isListNode(element);\n\n const isBullet = isList && (element as ListNode).getListType() === \"bullet\";\n\n const formatBulletList = () => {\n if (!isBullet) {\n const styleId = theme.getTypographyByTag(\"ul\")?.id;\n\n // will update the active state in the useEffect\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, { themeStyleId: styleId });\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n }\n };\n\n return (\n <button\n onClick={() => formatBulletList()}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/BulletListAction.js","sources":["../../../src/components/ToolbarActions/BulletListAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND } from \"~/commands/index.js\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport type { ListNode } from \"@webiny/lexical-nodes\";\nimport { $isListNode } from \"@webiny/lexical-nodes\";\nimport { useCurrentElement } from \"~/hooks/useCurrentElement.js\";\nimport { ReactComponent as BulletListIcon } from \"@webiny/icons/format_list_bulleted.svg\";\nimport cn from \"clsx\";\n\nexport const BulletListAction = () => {\n const { editor } = useRichTextEditor();\n const { element } = useCurrentElement();\n const { theme } = useRichTextEditor();\n const isList = $isListNode(element);\n\n const isBullet = isList && (element as ListNode).getListType() === \"bullet\";\n\n const formatBulletList = () => {\n if (!isBullet) {\n const styleId = theme.getTypographyByTag(\"ul\")?.id;\n\n // will update the active state in the useEffect\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, { themeStyleId: styleId });\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n }\n };\n\n return (\n <button\n onClick={() => formatBulletList()}\n className={cn(\"popup-item\", \"spaced\", { active: isBullet })}\n aria-label=\"Format text as bullet list\"\n >\n <BulletListIcon className=\"icon\" />\n </button>\n );\n};\n"],"names":["BulletListAction","editor","useRichTextEditor","element","useCurrentElement","theme","isList","$isListNode","isBullet","formatBulletList","REMOVE_LIST_COMMAND","undefined","styleId","INSERT_UNORDERED_LIST_COMMAND","cn","BulletListIcon"],"mappings":";;;;;;;AASO,MAAMA,mBAAmB;IAC5B,MAAM,EAAEC,MAAM,EAAE,GAAGC;IACnB,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAM,EAAEC,KAAK,EAAE,GAAGH;IAClB,MAAMI,SAASC,YAAYJ;IAE3B,MAAMK,WAAWF,UAAWH,AAAuC,aAAvCA,QAAqB,WAAW;IAE5D,MAAMM,mBAAmB;QACrB,IAAKD,UAMDP,OAAO,eAAe,CAACS,qBAAqBC;aANjC;YACX,MAAMC,UAAUP,MAAM,kBAAkB,CAAC,OAAO;YAGhDJ,OAAO,eAAe,CAACY,+BAA+B;gBAAE,cAAcD;YAAQ;QAClF;IAGJ;IAEA,OAAO,WAAP,GACI,oBAAC;QACG,SAAS,IAAMH;QACf,WAAWK,KAAG,cAAc,UAAU;YAAE,QAAQN;QAAS;QACzD,cAAW;qBAEX,oBAACO,gBAAcA;QAAC,WAAU;;AAGtC"}
|
|
@@ -2,6 +2,8 @@ import react from "react";
|
|
|
2
2
|
import { FORMAT_TEXT_COMMAND } from "lexical";
|
|
3
3
|
import { useCurrentSelection } from "../../hooks/useCurrentSelection.js";
|
|
4
4
|
import { useRichTextEditor } from "../../hooks/index.js";
|
|
5
|
+
import { ReactComponent } from "@webiny/icons/code.svg";
|
|
6
|
+
import clsx from "clsx";
|
|
5
7
|
const CodeHighlightAction = ()=>{
|
|
6
8
|
const { editor } = useRichTextEditor();
|
|
7
9
|
const { rangeSelection } = useCurrentSelection();
|
|
@@ -11,10 +13,12 @@ const CodeHighlightAction = ()=>{
|
|
|
11
13
|
};
|
|
12
14
|
return /*#__PURE__*/ react.createElement("button", {
|
|
13
15
|
onClick: handleClick,
|
|
14
|
-
className: "popup-item
|
|
16
|
+
className: clsx("popup-item", "spaced", {
|
|
17
|
+
active: isCodeSelected
|
|
18
|
+
}),
|
|
15
19
|
"aria-label": "Text code highlight"
|
|
16
|
-
}, /*#__PURE__*/ react.createElement(
|
|
17
|
-
className: "format
|
|
20
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
21
|
+
className: "format"
|
|
18
22
|
}));
|
|
19
23
|
};
|
|
20
24
|
export { CodeHighlightAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/CodeHighlightAction.js","sources":["../../../src/components/ToolbarActions/CodeHighlightAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\n\nexport const CodeHighlightAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isCodeSelected = rangeSelection ? rangeSelection.hasFormat(\"code\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"code\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/CodeHighlightAction.js","sources":["../../../src/components/ToolbarActions/CodeHighlightAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { ReactComponent as CodeIcon } from \"@webiny/icons/code.svg\";\nimport cn from \"clsx\";\n\nexport const CodeHighlightAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isCodeSelected = rangeSelection ? rangeSelection.hasFormat(\"code\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"code\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={cn(\"popup-item\", \"spaced\", { active: isCodeSelected })}\n aria-label=\"Text code highlight\"\n >\n <CodeIcon className=\"format\" />\n </button>\n );\n};\n"],"names":["CodeHighlightAction","editor","useRichTextEditor","rangeSelection","useCurrentSelection","isCodeSelected","handleClick","FORMAT_TEXT_COMMAND","cn","CodeIcon"],"mappings":";;;;;;AAOO,MAAMA,sBAAsB;IAC/B,MAAM,EAAEC,MAAM,EAAE,GAAGC;IACnB,MAAM,EAAEC,cAAc,EAAE,GAAGC;IAC3B,MAAMC,iBAAiBF,iBAAiBA,eAAe,SAAS,CAAC,UAAU;IAE3E,MAAMG,cAAc;QAChBL,OAAO,eAAe,CAACM,qBAAqB;IAChD;IAEA,OAAO,WAAP,GACI,oBAAC;QACG,SAASD;QACT,WAAWE,KAAG,cAAc,UAAU;YAAE,QAAQH;QAAe;QAC/D,cAAW;qBAEX,oBAACI,gBAAQA;QAAC,WAAU;;AAGhC"}
|
|
@@ -52,7 +52,8 @@ const FontSizeDropdown = ({ sizes })=>{
|
|
|
52
52
|
disabled: false,
|
|
53
53
|
showScroll: true
|
|
54
54
|
}, fontSizeOptions.map((option)=>/*#__PURE__*/ react.createElement(DropDownItem, {
|
|
55
|
-
className:
|
|
55
|
+
className: "item typography-item",
|
|
56
|
+
selected: selectedFontSize === option.value,
|
|
56
57
|
onClick: ()=>onFontSizeSelect(option.value),
|
|
57
58
|
key: option.value
|
|
58
59
|
}, /*#__PURE__*/ react.createElement("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/FontSizeAction.js","sources":["../../../src/components/ToolbarActions/FontSizeAction.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { $getSelection, $isRangeSelection } from \"lexical\";\nimport { $patchStyleText } from \"@lexical/selection\";\nimport { $getSelectionStyleValueForProperty } from \"@lexical/selection\";\nimport { useDeriveValueFromSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { DropDown } from \"~/ui/DropDown.js\";\nimport { DropDownItem } from \"~/ui/DropDown.js\";\n\ninterface FontSizeDropdownProps {\n sizes: string[];\n}\n\nconst FontSizeDropdown = ({ sizes }: FontSizeDropdownProps) => {\n const { editor } = useRichTextEditor();\n\n const fontSizeOptions = useMemo(() => {\n return [\n {\n value: \"inherit\",\n label: \"Auto\"\n },\n ...sizes.map(size => {\n return {\n value: size,\n label: `${size}`\n };\n })\n ];\n }, [sizes]);\n\n const selectedFontSize = useDeriveValueFromSelection(({ rangeSelection }) => {\n if (!rangeSelection) {\n return \"inherit\";\n }\n return $getSelectionStyleValueForProperty(rangeSelection, \"font-size\", \"inherit\");\n });\n\n const onFontSizeSelect = useCallback(\n (size: string) => {\n editor.update(() => {\n if (editor.isEditable()) {\n const selection = $getSelection();\n if (selection === null) {\n return;\n }\n\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n const anchor = selection.anchor.getNode();\n const topElement = anchor.getTopLevelElementOrThrow();\n topElement.select(0, topElement.getChildrenSize());\n const expanded = $getSelection();\n if (expanded !== null) {\n $patchStyleText(expanded, { \"font-size\": size });\n }\n } else {\n $patchStyleText(selection, { \"font-size\": size });\n }\n }\n });\n },\n [editor]\n );\n\n const selectedOption = fontSizeOptions.find(option => option.value === selectedFontSize);\n\n return (\n <DropDown\n buttonClassName=\"toolbar-item typography-dropdown\"\n buttonAriaLabel={\"Typography formatting options\"}\n buttonLabel={selectedOption?.label || \"Auto\"}\n stopCloseOnClickSelf={true}\n disabled={false}\n showScroll={true}\n >\n {fontSizeOptions.map(option => (\n <DropDownItem\n className
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/FontSizeAction.js","sources":["../../../src/components/ToolbarActions/FontSizeAction.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { $getSelection, $isRangeSelection } from \"lexical\";\nimport { $patchStyleText } from \"@lexical/selection\";\nimport { $getSelectionStyleValueForProperty } from \"@lexical/selection\";\nimport { useDeriveValueFromSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { DropDown } from \"~/ui/DropDown.js\";\nimport { DropDownItem } from \"~/ui/DropDown.js\";\n\ninterface FontSizeDropdownProps {\n sizes: string[];\n}\n\nconst FontSizeDropdown = ({ sizes }: FontSizeDropdownProps) => {\n const { editor } = useRichTextEditor();\n\n const fontSizeOptions = useMemo(() => {\n return [\n {\n value: \"inherit\",\n label: \"Auto\"\n },\n ...sizes.map(size => {\n return {\n value: size,\n label: `${size}`\n };\n })\n ];\n }, [sizes]);\n\n const selectedFontSize = useDeriveValueFromSelection(({ rangeSelection }) => {\n if (!rangeSelection) {\n return \"inherit\";\n }\n return $getSelectionStyleValueForProperty(rangeSelection, \"font-size\", \"inherit\");\n });\n\n const onFontSizeSelect = useCallback(\n (size: string) => {\n editor.update(() => {\n if (editor.isEditable()) {\n const selection = $getSelection();\n if (selection === null) {\n return;\n }\n\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n const anchor = selection.anchor.getNode();\n const topElement = anchor.getTopLevelElementOrThrow();\n topElement.select(0, topElement.getChildrenSize());\n const expanded = $getSelection();\n if (expanded !== null) {\n $patchStyleText(expanded, { \"font-size\": size });\n }\n } else {\n $patchStyleText(selection, { \"font-size\": size });\n }\n }\n });\n },\n [editor]\n );\n\n const selectedOption = fontSizeOptions.find(option => option.value === selectedFontSize);\n\n return (\n <DropDown\n buttonClassName=\"toolbar-item typography-dropdown\"\n buttonAriaLabel={\"Typography formatting options\"}\n buttonLabel={selectedOption?.label || \"Auto\"}\n stopCloseOnClickSelf={true}\n disabled={false}\n showScroll={true}\n >\n {fontSizeOptions.map(option => (\n <DropDownItem\n className=\"item typography-item\"\n selected={selectedFontSize === option.value}\n onClick={() => onFontSizeSelect(option.value)}\n key={option.value}\n >\n <span className=\"text\">{option.label}</span>\n </DropDownItem>\n ))}\n </DropDown>\n );\n};\n\nexport const FontSizeAction = () => {\n const { theme } = useRichTextEditor();\n\n if (!theme.fontSizes || theme.fontSizes.length === 0) {\n return null;\n }\n\n return <FontSizeDropdown sizes={theme.fontSizes} />;\n};\n"],"names":["FontSizeDropdown","sizes","editor","useRichTextEditor","fontSizeOptions","useMemo","size","selectedFontSize","useDeriveValueFromSelection","rangeSelection","$getSelectionStyleValueForProperty","onFontSizeSelect","useCallback","selection","$getSelection","$isRangeSelection","anchor","topElement","expanded","$patchStyleText","selectedOption","option","DropDown","DropDownItem","FontSizeAction","theme"],"mappings":";;;;;;AAaA,MAAMA,mBAAmB,CAAC,EAAEC,KAAK,EAAyB;IACtD,MAAM,EAAEC,MAAM,EAAE,GAAGC;IAEnB,MAAMC,kBAAkBC,QAAQ,IACrB;YACH;gBACI,OAAO;gBACP,OAAO;YACX;eACGJ,MAAM,GAAG,CAACK,CAAAA,OACF;oBACH,OAAOA;oBACP,OAAO,GAAGA,MAAM;gBACpB;SAEP,EACF;QAACL;KAAM;IAEV,MAAMM,mBAAmBC,4BAA4B,CAAC,EAAEC,cAAc,EAAE;QACpE,IAAI,CAACA,gBACD,OAAO;QAEX,OAAOC,mCAAmCD,gBAAgB,aAAa;IAC3E;IAEA,MAAME,mBAAmBC,YACrB,CAACN;QACGJ,OAAO,MAAM,CAAC;YACV,IAAIA,OAAO,UAAU,IAAI;gBACrB,MAAMW,YAAYC;gBAClB,IAAID,AAAc,SAAdA,WACA;gBAGJ,IAAIE,kBAAkBF,cAAcA,UAAU,WAAW,IAAI;oBACzD,MAAMG,SAASH,UAAU,MAAM,CAAC,OAAO;oBACvC,MAAMI,aAAaD,OAAO,yBAAyB;oBACnDC,WAAW,MAAM,CAAC,GAAGA,WAAW,eAAe;oBAC/C,MAAMC,WAAWJ;oBACjB,IAAII,AAAa,SAAbA,UACAC,gBAAgBD,UAAU;wBAAE,aAAaZ;oBAAK;gBAEtD,OACIa,gBAAgBN,WAAW;oBAAE,aAAaP;gBAAK;YAEvD;QACJ;IACJ,GACA;QAACJ;KAAO;IAGZ,MAAMkB,iBAAiBhB,gBAAgB,IAAI,CAACiB,CAAAA,SAAUA,OAAO,KAAK,KAAKd;IAEvE,OAAO,WAAP,GACI,oBAACe,UAAQA;QACL,iBAAgB;QAChB,iBAAiB;QACjB,aAAaF,gBAAgB,SAAS;QACtC,sBAAsB;QACtB,UAAU;QACV,YAAY;OAEXhB,gBAAgB,GAAG,CAACiB,CAAAA,SAAAA,WAAAA,GACjB,oBAACE,cAAYA;YACT,WAAU;YACV,UAAUhB,qBAAqBc,OAAO,KAAK;YAC3C,SAAS,IAAMV,iBAAiBU,OAAO,KAAK;YAC5C,KAAKA,OAAO,KAAK;yBAEjB,oBAAC;YAAK,WAAU;WAAQA,OAAO,KAAK;AAKxD;AAEO,MAAMG,iBAAiB;IAC1B,MAAM,EAAEC,KAAK,EAAE,GAAGtB;IAElB,IAAI,CAACsB,MAAM,SAAS,IAAIA,AAA2B,MAA3BA,MAAM,SAAS,CAAC,MAAM,EAC1C,OAAO;IAGX,OAAO,WAAP,GAAO,oBAACzB,kBAAgBA;QAAC,OAAOyB,MAAM,SAAS;;AACnD"}
|
|
@@ -2,6 +2,7 @@ import react, { useEffect, useState } from "react";
|
|
|
2
2
|
import { useRichTextEditor } from "../../hooks/useRichTextEditor.js";
|
|
3
3
|
import { fileToImagePayload } from "../../utils/files.js";
|
|
4
4
|
import { INSERT_IMAGE_COMMAND } from "../../commands/index.js";
|
|
5
|
+
import { ReactComponent } from "@webiny/icons/image.svg";
|
|
5
6
|
const ImageAction = ()=>{
|
|
6
7
|
const { editor, toolbarActionPlugins } = useRichTextEditor();
|
|
7
8
|
const [imageActionPlugin, setImageActionPlugin] = useState();
|
|
@@ -26,8 +27,8 @@ const ImageAction = ()=>{
|
|
|
26
27
|
onClick: ()=>handleClick(),
|
|
27
28
|
className: "popup-item",
|
|
28
29
|
"aria-label": "Insert image"
|
|
29
|
-
}, /*#__PURE__*/ react.createElement(
|
|
30
|
-
className: "icon
|
|
30
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
31
|
+
className: "icon"
|
|
31
32
|
}));
|
|
32
33
|
};
|
|
33
34
|
export { ImageAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/ImageAction.js","sources":["../../../src/components/ToolbarActions/ImageAction.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport type { LexicalCommand } from \"lexical\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport type { FileManagerFileItem } from \"~/utils/files.js\";\nimport { fileToImagePayload } from \"~/utils/files.js\";\nimport type { ImagePayload } from \"~/commands/index.js\";\nimport { INSERT_IMAGE_COMMAND } from \"~/commands/index.js\";\nimport type { ToolbarActionPlugin } from \"~/types.js\";\n\nexport const ImageAction = () => {\n const { editor, toolbarActionPlugins } = useRichTextEditor();\n const [imageActionPlugin, setImageActionPlugin] = useState<ToolbarActionPlugin | undefined>();\n\n useEffect(() => {\n if (!!toolbarActionPlugins?.length) {\n const actionPlugin = toolbarActionPlugins.find(\n action => action.targetAction === \"image-action\"\n );\n setImageActionPlugin(actionPlugin);\n }\n }, [toolbarActionPlugins]);\n\n const handleClick = () => {\n if (typeof imageActionPlugin?.plugin === \"function\") {\n const cb = (data: FileManagerFileItem) => {\n const imagePayload = fileToImagePayload(data);\n if (imagePayload) {\n editor.dispatchCommand<LexicalCommand<ImagePayload>>(\n INSERT_IMAGE_COMMAND,\n imagePayload\n );\n }\n };\n imageActionPlugin.plugin(cb);\n }\n };\n\n return (\n <button onClick={() => handleClick()} className={\"popup-item\"} aria-label=\"Insert image\">\n <
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/ImageAction.js","sources":["../../../src/components/ToolbarActions/ImageAction.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport type { LexicalCommand } from \"lexical\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport type { FileManagerFileItem } from \"~/utils/files.js\";\nimport { fileToImagePayload } from \"~/utils/files.js\";\nimport type { ImagePayload } from \"~/commands/index.js\";\nimport { INSERT_IMAGE_COMMAND } from \"~/commands/index.js\";\nimport type { ToolbarActionPlugin } from \"~/types.js\";\nimport { ReactComponent as ImageIcon } from \"@webiny/icons/image.svg\";\n\nexport const ImageAction = () => {\n const { editor, toolbarActionPlugins } = useRichTextEditor();\n const [imageActionPlugin, setImageActionPlugin] = useState<ToolbarActionPlugin | undefined>();\n\n useEffect(() => {\n if (!!toolbarActionPlugins?.length) {\n const actionPlugin = toolbarActionPlugins.find(\n action => action.targetAction === \"image-action\"\n );\n setImageActionPlugin(actionPlugin);\n }\n }, [toolbarActionPlugins]);\n\n const handleClick = () => {\n if (typeof imageActionPlugin?.plugin === \"function\") {\n const cb = (data: FileManagerFileItem) => {\n const imagePayload = fileToImagePayload(data);\n if (imagePayload) {\n editor.dispatchCommand<LexicalCommand<ImagePayload>>(\n INSERT_IMAGE_COMMAND,\n imagePayload\n );\n }\n };\n imageActionPlugin.plugin(cb);\n }\n };\n\n return (\n <button onClick={() => handleClick()} className={\"popup-item\"} aria-label=\"Insert image\">\n <ImageIcon className=\"icon\" />\n </button>\n );\n};\n"],"names":["ImageAction","editor","toolbarActionPlugins","useRichTextEditor","imageActionPlugin","setImageActionPlugin","useState","useEffect","actionPlugin","action","handleClick","cb","data","imagePayload","fileToImagePayload","INSERT_IMAGE_COMMAND","ImageIcon"],"mappings":";;;;;AAUO,MAAMA,cAAc;IACvB,MAAM,EAAEC,MAAM,EAAEC,oBAAoB,EAAE,GAAGC;IACzC,MAAM,CAACC,mBAAmBC,qBAAqB,GAAGC;IAElDC,UAAU;QACN,IAAI,CAAC,CAACL,sBAAsB,QAAQ;YAChC,MAAMM,eAAeN,qBAAqB,IAAI,CAC1CO,CAAAA,SAAUA,AAAwB,mBAAxBA,OAAO,YAAY;YAEjCJ,qBAAqBG;QACzB;IACJ,GAAG;QAACN;KAAqB;IAEzB,MAAMQ,cAAc;QAChB,IAAI,AAAqC,cAArC,OAAON,mBAAmB,QAAuB;YACjD,MAAMO,KAAK,CAACC;gBACR,MAAMC,eAAeC,mBAAmBF;gBACxC,IAAIC,cACAZ,OAAO,eAAe,CAClBc,sBACAF;YAGZ;YACAT,kBAAkB,MAAM,CAACO;QAC7B;IACJ;IAEA,OAAO,WAAP,GACI,oBAAC;QAAO,SAAS,IAAMD;QAAe,WAAW;QAAc,cAAW;qBACtE,oBAACM,gBAASA;QAAC,WAAU;;AAGjC"}
|
|
@@ -2,6 +2,8 @@ import react from "react";
|
|
|
2
2
|
import { FORMAT_TEXT_COMMAND } from "lexical";
|
|
3
3
|
import { useCurrentSelection } from "../../hooks/useCurrentSelection.js";
|
|
4
4
|
import { useRichTextEditor } from "../../hooks/index.js";
|
|
5
|
+
import { ReactComponent } from "@webiny/icons/format_italic.svg";
|
|
6
|
+
import clsx from "clsx";
|
|
5
7
|
const ItalicAction = ()=>{
|
|
6
8
|
const { editor } = useRichTextEditor();
|
|
7
9
|
const { rangeSelection } = useCurrentSelection();
|
|
@@ -11,10 +13,12 @@ const ItalicAction = ()=>{
|
|
|
11
13
|
};
|
|
12
14
|
return /*#__PURE__*/ react.createElement("button", {
|
|
13
15
|
onClick: handleClick,
|
|
14
|
-
className: "popup-item
|
|
16
|
+
className: clsx("popup-item", "spaced", {
|
|
17
|
+
active: isItalicSelected
|
|
18
|
+
}),
|
|
15
19
|
"aria-label": "Format text as italic"
|
|
16
|
-
}, /*#__PURE__*/ react.createElement(
|
|
17
|
-
className: "format
|
|
20
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
21
|
+
className: "format"
|
|
18
22
|
}));
|
|
19
23
|
};
|
|
20
24
|
export { ItalicAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/ItalicAction.js","sources":["../../../src/components/ToolbarActions/ItalicAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\n\nexport const ItalicAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isItalicSelected = rangeSelection ? rangeSelection.hasFormat(\"italic\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"italic\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/ItalicAction.js","sources":["../../../src/components/ToolbarActions/ItalicAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { ReactComponent as ItalicIcon } from \"@webiny/icons/format_italic.svg\";\nimport cn from \"clsx\";\n\nexport const ItalicAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isItalicSelected = rangeSelection ? rangeSelection.hasFormat(\"italic\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"italic\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={cn(\"popup-item\", \"spaced\", { active: isItalicSelected })}\n aria-label=\"Format text as italic\"\n >\n <ItalicIcon className=\"format\" />\n </button>\n );\n};\n"],"names":["ItalicAction","editor","useRichTextEditor","rangeSelection","useCurrentSelection","isItalicSelected","handleClick","FORMAT_TEXT_COMMAND","cn","ItalicIcon"],"mappings":";;;;;;AAOO,MAAMA,eAAe;IACxB,MAAM,EAAEC,MAAM,EAAE,GAAGC;IACnB,MAAM,EAAEC,cAAc,EAAE,GAAGC;IAC3B,MAAMC,mBAAmBF,iBAAiBA,eAAe,SAAS,CAAC,YAAY;IAE/E,MAAMG,cAAc;QAChBL,OAAO,eAAe,CAACM,qBAAqB;IAChD;IAEA,OAAO,WAAP,GACI,oBAAC;QACG,SAASD;QACT,WAAWE,KAAG,cAAc,UAAU;YAAE,QAAQH;QAAiB;QACjE,cAAW;qBAEX,oBAACI,gBAAUA;QAAC,WAAU;;AAGlC"}
|
|
@@ -3,6 +3,8 @@ import { $isLinkNode, TOGGLE_LINK_COMMAND } from "@webiny/lexical-nodes";
|
|
|
3
3
|
import { getNodeFromSelection } from "../../hooks/useCurrentElement.js";
|
|
4
4
|
import { useDeriveValueFromSelection } from "../../hooks/useCurrentSelection.js";
|
|
5
5
|
import { useRichTextEditor } from "../../hooks/index.js";
|
|
6
|
+
import { ReactComponent } from "@webiny/icons/link.svg";
|
|
7
|
+
import clsx from "clsx";
|
|
6
8
|
const LinkAction = ()=>{
|
|
7
9
|
const { editor } = useRichTextEditor();
|
|
8
10
|
const isLink = useDeriveValueFromSelection(({ rangeSelection })=>{
|
|
@@ -21,10 +23,12 @@ const LinkAction = ()=>{
|
|
|
21
23
|
]);
|
|
22
24
|
return /*#__PURE__*/ react.createElement("button", {
|
|
23
25
|
onClick: insertLink,
|
|
24
|
-
className: "popup-item
|
|
26
|
+
className: clsx("popup-item", "spaced", {
|
|
27
|
+
active: isLink
|
|
28
|
+
}),
|
|
25
29
|
"aria-label": "Insert link"
|
|
26
|
-
}, /*#__PURE__*/ react.createElement(
|
|
27
|
-
className: "format
|
|
30
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
31
|
+
className: "format"
|
|
28
32
|
}));
|
|
29
33
|
};
|
|
30
34
|
export { LinkAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/LinkAction.js","sources":["../../../src/components/ToolbarActions/LinkAction.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { $isLinkNode, TOGGLE_LINK_COMMAND } from \"@webiny/lexical-nodes\";\nimport { getNodeFromSelection } from \"~/hooks/useCurrentElement.js\";\nimport { useDeriveValueFromSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\n\nexport const LinkAction = () => {\n const { editor } = useRichTextEditor();\n const isLink = useDeriveValueFromSelection(({ rangeSelection }) => {\n if (!rangeSelection) {\n return false;\n }\n const node = getNodeFromSelection(rangeSelection);\n return node ? $isLinkNode(node) || $isLinkNode(node.getParent()) : false;\n });\n\n const insertLink = useCallback(() => {\n if (!isLink) {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, { url: \"https://\" });\n } else {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);\n }\n }, [editor, isLink]);\n\n return (\n <button\n onClick={insertLink}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/LinkAction.js","sources":["../../../src/components/ToolbarActions/LinkAction.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { $isLinkNode, TOGGLE_LINK_COMMAND } from \"@webiny/lexical-nodes\";\nimport { getNodeFromSelection } from \"~/hooks/useCurrentElement.js\";\nimport { useDeriveValueFromSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { ReactComponent as LinkIcon } from \"@webiny/icons/link.svg\";\nimport cn from \"clsx\";\n\nexport const LinkAction = () => {\n const { editor } = useRichTextEditor();\n const isLink = useDeriveValueFromSelection(({ rangeSelection }) => {\n if (!rangeSelection) {\n return false;\n }\n const node = getNodeFromSelection(rangeSelection);\n return node ? $isLinkNode(node) || $isLinkNode(node.getParent()) : false;\n });\n\n const insertLink = useCallback(() => {\n if (!isLink) {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, { url: \"https://\" });\n } else {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);\n }\n }, [editor, isLink]);\n\n return (\n <button\n onClick={insertLink}\n className={cn(\"popup-item\", \"spaced\", { active: isLink })}\n aria-label=\"Insert link\"\n >\n <LinkIcon className=\"format\" />\n </button>\n );\n};\n"],"names":["LinkAction","editor","useRichTextEditor","isLink","useDeriveValueFromSelection","rangeSelection","node","getNodeFromSelection","$isLinkNode","insertLink","useCallback","TOGGLE_LINK_COMMAND","cn","LinkIcon"],"mappings":";;;;;;;AAQO,MAAMA,aAAa;IACtB,MAAM,EAAEC,MAAM,EAAE,GAAGC;IACnB,MAAMC,SAASC,4BAA4B,CAAC,EAAEC,cAAc,EAAE;QAC1D,IAAI,CAACA,gBACD,OAAO;QAEX,MAAMC,OAAOC,qBAAqBF;QAClC,OAAOC,OAAOE,YAAYF,SAASE,YAAYF,KAAK,SAAS,MAAM;IACvE;IAEA,MAAMG,aAAaC,YAAY;QAC3B,IAAKP,QAGDF,OAAO,eAAe,CAACU,qBAAqB;aAF5CV,OAAO,eAAe,CAACU,qBAAqB;YAAE,KAAK;QAAW;IAItE,GAAG;QAACV;QAAQE;KAAO;IAEnB,OAAO,WAAP,GACI,oBAAC;QACG,SAASM;QACT,WAAWG,KAAG,cAAc,UAAU;YAAE,QAAQT;QAAO;QACvD,cAAW;qBAEX,oBAACU,gBAAQA;QAAC,WAAU;;AAGhC"}
|
|
@@ -3,6 +3,8 @@ import { $isListNode } from "@webiny/lexical-nodes";
|
|
|
3
3
|
import { INSERT_ORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND } from "../../commands/index.js";
|
|
4
4
|
import { useRichTextEditor } from "../../hooks/useRichTextEditor.js";
|
|
5
5
|
import { useCurrentElement } from "../../hooks/useCurrentElement.js";
|
|
6
|
+
import { ReactComponent } from "@webiny/icons/format_list_numbered.svg";
|
|
7
|
+
import clsx from "clsx";
|
|
6
8
|
const NumberedListAction = ()=>{
|
|
7
9
|
const { element } = useCurrentElement();
|
|
8
10
|
const { editor, theme } = useRichTextEditor();
|
|
@@ -24,10 +26,12 @@ const NumberedListAction = ()=>{
|
|
|
24
26
|
};
|
|
25
27
|
return /*#__PURE__*/ react.createElement("button", {
|
|
26
28
|
onClick: ()=>formatNumberedList(),
|
|
27
|
-
className: "popup-item
|
|
29
|
+
className: clsx("popup-item", "spaced", {
|
|
30
|
+
active: isNumbered
|
|
31
|
+
}),
|
|
28
32
|
"aria-label": "Format text as numbered list"
|
|
29
|
-
}, /*#__PURE__*/ react.createElement(
|
|
30
|
-
className: "icon
|
|
33
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
34
|
+
className: "icon"
|
|
31
35
|
}));
|
|
32
36
|
};
|
|
33
37
|
export { NumberedListAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/NumberedListAction.js","sources":["../../../src/components/ToolbarActions/NumberedListAction.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ListNode } from \"@webiny/lexical-nodes\";\nimport { $isListNode } from \"@webiny/lexical-nodes\";\nimport { INSERT_ORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND } from \"~/commands/index.js\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport { useCurrentElement } from \"~/hooks/useCurrentElement.js\";\n\nexport const NumberedListAction = () => {\n const { element } = useCurrentElement();\n const { editor, theme } = useRichTextEditor();\n const isList = $isListNode(element);\n const isNumbered = isList && (element as ListNode).getListType() === \"number\";\n\n const getStyleId = (): string | undefined => {\n // check default style for numbered list\n const id = theme.getTypographyByTag(\"ol\")?.id;\n if (id) {\n return id;\n }\n // fallback to ul list styles\n return theme.getTypographyByTag(\"ul\")?.id;\n };\n\n const formatNumberedList = () => {\n if (!isNumbered) {\n const styleId = getStyleId();\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, { themeStyleId: styleId });\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n }\n };\n\n return (\n <button\n onClick={() => formatNumberedList()}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/NumberedListAction.js","sources":["../../../src/components/ToolbarActions/NumberedListAction.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ListNode } from \"@webiny/lexical-nodes\";\nimport { $isListNode } from \"@webiny/lexical-nodes\";\nimport { INSERT_ORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND } from \"~/commands/index.js\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport { useCurrentElement } from \"~/hooks/useCurrentElement.js\";\nimport { ReactComponent as NumberedListIcon } from \"@webiny/icons/format_list_numbered.svg\";\nimport cn from \"clsx\";\n\nexport const NumberedListAction = () => {\n const { element } = useCurrentElement();\n const { editor, theme } = useRichTextEditor();\n const isList = $isListNode(element);\n const isNumbered = isList && (element as ListNode).getListType() === \"number\";\n\n const getStyleId = (): string | undefined => {\n // check default style for numbered list\n const id = theme.getTypographyByTag(\"ol\")?.id;\n if (id) {\n return id;\n }\n // fallback to ul list styles\n return theme.getTypographyByTag(\"ul\")?.id;\n };\n\n const formatNumberedList = () => {\n if (!isNumbered) {\n const styleId = getStyleId();\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, { themeStyleId: styleId });\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n }\n };\n\n return (\n <button\n onClick={() => formatNumberedList()}\n className={cn(\"popup-item\", \"spaced\", { active: isNumbered })}\n aria-label=\"Format text as numbered list\"\n >\n <NumberedListIcon className=\"icon\" />\n </button>\n );\n};\n"],"names":["NumberedListAction","element","useCurrentElement","editor","theme","useRichTextEditor","isList","$isListNode","isNumbered","getStyleId","id","formatNumberedList","REMOVE_LIST_COMMAND","undefined","styleId","INSERT_ORDERED_LIST_COMMAND","cn","NumberedListIcon"],"mappings":";;;;;;;AASO,MAAMA,qBAAqB;IAC9B,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAE,GAAGC;IAC1B,MAAMC,SAASC,YAAYN;IAC3B,MAAMO,aAAaF,UAAWL,AAAuC,aAAvCA,QAAqB,WAAW;IAE9D,MAAMQ,aAAa;QAEf,MAAMC,KAAKN,MAAM,kBAAkB,CAAC,OAAO;QAC3C,IAAIM,IACA,OAAOA;QAGX,OAAON,MAAM,kBAAkB,CAAC,OAAO;IAC3C;IAEA,MAAMO,qBAAqB;QACvB,IAAKH,YAIDL,OAAO,eAAe,CAACS,qBAAqBC;aAJ/B;YACb,MAAMC,UAAUL;YAChBN,OAAO,eAAe,CAACY,6BAA6B;gBAAE,cAAcD;YAAQ;QAChF;IAGJ;IAEA,OAAO,WAAP,GACI,oBAAC;QACG,SAAS,IAAMH;QACf,WAAWK,KAAG,cAAc,UAAU;YAAE,QAAQR;QAAW;QAC3D,cAAW;qBAEX,oBAACS,gBAAgBA;QAAC,WAAU;;AAGxC"}
|
|
@@ -2,6 +2,8 @@ import react from "react";
|
|
|
2
2
|
import { $isQuoteNode, formatToParagraph, formatToQuote } from "@webiny/lexical-nodes";
|
|
3
3
|
import { useRichTextEditor } from "../../hooks/useRichTextEditor.js";
|
|
4
4
|
import { useCurrentElement } from "../../hooks/useCurrentElement.js";
|
|
5
|
+
import { ReactComponent } from "@webiny/icons/format_quote.svg";
|
|
6
|
+
import clsx from "clsx";
|
|
5
7
|
const QUOTE_TAG = "quote";
|
|
6
8
|
const QuoteAction = ()=>{
|
|
7
9
|
const { editor, theme } = useRichTextEditor();
|
|
@@ -17,10 +19,12 @@ const QuoteAction = ()=>{
|
|
|
17
19
|
};
|
|
18
20
|
return /*#__PURE__*/ react.createElement("button", {
|
|
19
21
|
onClick: formatText,
|
|
20
|
-
className: "popup-item
|
|
22
|
+
className: clsx("popup-item", {
|
|
23
|
+
active: isQuote
|
|
24
|
+
}),
|
|
21
25
|
"aria-label": "Format text as quote"
|
|
22
|
-
}, /*#__PURE__*/ react.createElement(
|
|
23
|
-
className: "icon
|
|
26
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
27
|
+
className: "icon"
|
|
24
28
|
}));
|
|
25
29
|
};
|
|
26
30
|
export { QuoteAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/QuoteAction.js","sources":["../../../src/components/ToolbarActions/QuoteAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { $isQuoteNode, formatToQuote, formatToParagraph } from \"@webiny/lexical-nodes\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport { useCurrentElement } from \"~/hooks/useCurrentElement.js\";\n\nconst QUOTE_TAG = \"quote\";\n\nexport const QuoteAction = () => {\n const { editor, theme } = useRichTextEditor();\n const { element } = useCurrentElement();\n const isQuote = $isQuoteNode(element);\n\n const formatText = () => {\n if (!isQuote) {\n // Try to set default quote style, when the action button is clicked for first time\n const hasQuoteStyles = theme.getTypographyByTag(QUOTE_TAG);\n formatToQuote(editor, hasQuoteStyles ? QUOTE_TAG : undefined);\n return;\n }\n formatToParagraph(editor);\n };\n\n return (\n <button\n onClick={formatText}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/QuoteAction.js","sources":["../../../src/components/ToolbarActions/QuoteAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { $isQuoteNode, formatToQuote, formatToParagraph } from \"@webiny/lexical-nodes\";\nimport { useRichTextEditor } from \"~/hooks/useRichTextEditor.js\";\nimport { useCurrentElement } from \"~/hooks/useCurrentElement.js\";\nimport { ReactComponent as QuoteIcon } from \"@webiny/icons/format_quote.svg\";\nimport cn from \"clsx\";\n\nconst QUOTE_TAG = \"quote\";\n\nexport const QuoteAction = () => {\n const { editor, theme } = useRichTextEditor();\n const { element } = useCurrentElement();\n const isQuote = $isQuoteNode(element);\n\n const formatText = () => {\n if (!isQuote) {\n // Try to set default quote style, when the action button is clicked for first time\n const hasQuoteStyles = theme.getTypographyByTag(QUOTE_TAG);\n formatToQuote(editor, hasQuoteStyles ? QUOTE_TAG : undefined);\n return;\n }\n formatToParagraph(editor);\n };\n\n return (\n <button\n onClick={formatText}\n className={cn(\"popup-item\", { active: isQuote })}\n aria-label=\"Format text as quote\"\n >\n <QuoteIcon className=\"icon\" />\n </button>\n );\n};\n"],"names":["QUOTE_TAG","QuoteAction","editor","theme","useRichTextEditor","element","useCurrentElement","isQuote","$isQuoteNode","formatText","hasQuoteStyles","formatToQuote","undefined","formatToParagraph","cn","QuoteIcon"],"mappings":";;;;;;AAOA,MAAMA,YAAY;AAEX,MAAMC,cAAc;IACvB,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAE,GAAGC;IAC1B,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAMC,UAAUC,aAAaH;IAE7B,MAAMI,aAAa;QACf,IAAI,CAACF,SAAS;YAEV,MAAMG,iBAAiBP,MAAM,kBAAkB,CAACH;YAChDW,cAAcT,QAAQQ,iBAAiBV,YAAYY;YACnD;QACJ;QACAC,kBAAkBX;IACtB;IAEA,OAAO,WAAP,GACI,oBAAC;QACG,SAASO;QACT,WAAWK,KAAG,cAAc;YAAE,QAAQP;QAAQ;QAC9C,cAAW;qBAEX,oBAACQ,gBAASA;QAAC,WAAU;;AAGjC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import react from "react";
|
|
2
2
|
import { FORMAT_TEXT_COMMAND } from "lexical";
|
|
3
3
|
import { useCurrentSelection, useRichTextEditor } from "../../hooks/index.js";
|
|
4
|
+
import { ReactComponent } from "@webiny/icons/format_underlined.svg";
|
|
5
|
+
import clsx from "clsx";
|
|
4
6
|
const UnderlineAction = ()=>{
|
|
5
7
|
const { editor } = useRichTextEditor();
|
|
6
8
|
const { rangeSelection } = useCurrentSelection();
|
|
@@ -10,10 +12,12 @@ const UnderlineAction = ()=>{
|
|
|
10
12
|
};
|
|
11
13
|
return /*#__PURE__*/ react.createElement("button", {
|
|
12
14
|
onClick: handleClick,
|
|
13
|
-
className: "popup-item
|
|
15
|
+
className: clsx("popup-item", "spaced", {
|
|
16
|
+
active: isUnderlineSelected
|
|
17
|
+
}),
|
|
14
18
|
"aria-label": "Underline text"
|
|
15
|
-
}, /*#__PURE__*/ react.createElement(
|
|
16
|
-
className: "format
|
|
19
|
+
}, /*#__PURE__*/ react.createElement(ReactComponent, {
|
|
20
|
+
className: "format"
|
|
17
21
|
}));
|
|
18
22
|
};
|
|
19
23
|
export { UnderlineAction };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components/ToolbarActions/UnderlineAction.js","sources":["../../../src/components/ToolbarActions/UnderlineAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection, useRichTextEditor } from \"~/hooks/index.js\";\n\nexport const UnderlineAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isUnderlineSelected = rangeSelection ? rangeSelection.hasFormat(\"underline\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"underline\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={\"popup-item
|
|
1
|
+
{"version":3,"file":"components/ToolbarActions/UnderlineAction.js","sources":["../../../src/components/ToolbarActions/UnderlineAction.tsx"],"sourcesContent":["import React from \"react\";\nimport { FORMAT_TEXT_COMMAND } from \"lexical\";\nimport { useCurrentSelection, useRichTextEditor } from \"~/hooks/index.js\";\nimport { ReactComponent as UnderlineIcon } from \"@webiny/icons/format_underlined.svg\";\nimport cn from \"clsx\";\n\nexport const UnderlineAction = () => {\n const { editor } = useRichTextEditor();\n const { rangeSelection } = useCurrentSelection();\n const isUnderlineSelected = rangeSelection ? rangeSelection.hasFormat(\"underline\") : false;\n\n const handleClick = () => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"underline\");\n };\n\n return (\n <button\n onClick={handleClick}\n className={cn(\"popup-item\", \"spaced\", { active: isUnderlineSelected })}\n aria-label=\"Underline text\"\n >\n <UnderlineIcon className=\"format\" />\n </button>\n );\n};\n"],"names":["UnderlineAction","editor","useRichTextEditor","rangeSelection","useCurrentSelection","isUnderlineSelected","handleClick","FORMAT_TEXT_COMMAND","cn","UnderlineIcon"],"mappings":";;;;;AAMO,MAAMA,kBAAkB;IAC3B,MAAM,EAAEC,MAAM,EAAE,GAAGC;IACnB,MAAM,EAAEC,cAAc,EAAE,GAAGC;IAC3B,MAAMC,sBAAsBF,iBAAiBA,eAAe,SAAS,CAAC,eAAe;IAErF,MAAMG,cAAc;QAChBL,OAAO,eAAe,CAACM,qBAAqB;IAChD;IAEA,OAAO,WAAP,GACI,oBAAC;QACG,SAASD;QACT,WAAWE,KAAG,cAAc,UAAU;YAAE,QAAQH;QAAoB;QACpE,cAAW;qBAEX,oBAACI,gBAAaA;QAAC,WAAU;;AAGrC"}
|
|
@@ -2,6 +2,6 @@ import type { RangeSelection } from "lexical";
|
|
|
2
2
|
export declare function useCurrentElement(): {
|
|
3
3
|
element: null;
|
|
4
4
|
} | {
|
|
5
|
-
element: import("lexical").
|
|
5
|
+
element: import("lexical").LexicalNode;
|
|
6
6
|
};
|
|
7
|
-
export declare function getNodeFromSelection(selection: RangeSelection): import("lexical").
|
|
7
|
+
export declare function getNodeFromSelection(selection: RangeSelection): import("lexical").LexicalNode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/lexical-editor",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.6.0-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -12,25 +12,27 @@
|
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@lexical/code": "0.
|
|
16
|
-
"@lexical/history": "0.
|
|
17
|
-
"@lexical/react": "0.
|
|
18
|
-
"@lexical/rich-text": "0.
|
|
19
|
-
"@lexical/selection": "0.
|
|
20
|
-
"@lexical/text": "0.
|
|
21
|
-
"@lexical/utils": "0.
|
|
22
|
-
"@webiny/
|
|
23
|
-
"@webiny/lexical-
|
|
24
|
-
"@webiny/
|
|
25
|
-
"@webiny/react-
|
|
26
|
-
"
|
|
15
|
+
"@lexical/code": "0.49.0",
|
|
16
|
+
"@lexical/history": "0.49.0",
|
|
17
|
+
"@lexical/react": "0.49.0",
|
|
18
|
+
"@lexical/rich-text": "0.49.0",
|
|
19
|
+
"@lexical/selection": "0.49.0",
|
|
20
|
+
"@lexical/text": "0.49.0",
|
|
21
|
+
"@lexical/utils": "0.49.0",
|
|
22
|
+
"@webiny/icons": "6.6.0-alpha.1",
|
|
23
|
+
"@webiny/lexical-nodes": "6.6.0-alpha.1",
|
|
24
|
+
"@webiny/lexical-theme": "6.6.0-alpha.1",
|
|
25
|
+
"@webiny/react-composition": "6.6.0-alpha.1",
|
|
26
|
+
"@webiny/react-properties": "6.6.0-alpha.1",
|
|
27
|
+
"clsx": "2.1.1",
|
|
28
|
+
"lexical": "0.49.0",
|
|
27
29
|
"lodash": "4.18.1",
|
|
28
|
-
"radix-ui": "1.6.
|
|
30
|
+
"radix-ui": "1.6.7",
|
|
29
31
|
"react": "18.3.1",
|
|
30
32
|
"react-dom": "18.3.1"
|
|
31
33
|
},
|
|
32
34
|
"devDependencies": {
|
|
33
|
-
"@webiny/build-tools": "6.
|
|
35
|
+
"@webiny/build-tools": "6.6.0-alpha.1"
|
|
34
36
|
},
|
|
35
37
|
"publishConfig": {
|
|
36
38
|
"access": "public"
|
|
@@ -30,7 +30,7 @@ const FloatingLinkEditorController = (props)=>{
|
|
|
30
30
|
if (!isChildOfLinkEditor(payload.relatedTarget)) setIsLink(false);
|
|
31
31
|
return false;
|
|
32
32
|
}, COMMAND_PRIORITY_LOW), editor.registerCommand(TOGGLE_LINK_COMMAND, (payload)=>{
|
|
33
|
-
setIsLink(!!payload);
|
|
33
|
+
setIsLink(!!payload && $isRangeSelection($getSelection()));
|
|
34
34
|
return false;
|
|
35
35
|
}, COMMAND_PRIORITY_CRITICAL)), [
|
|
36
36
|
editor,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js","sources":["../../../src/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.tsx"],"sourcesContent":["import React, { useCallback, useState, useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { getSelectedNode } from \"~/utils/getSelectedNode.js\";\nimport { $isAutoLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from \"@webiny/lexical-nodes\";\nimport { isChildOfLinkEditor } from \"~/plugins/FloatingLinkEditorPlugin/isChildOfLinkEditor.js\";\nimport debounce from \"lodash/debounce.js\";\nimport {\n $getSelection,\n $isRangeSelection,\n BLUR_COMMAND,\n COMMAND_PRIORITY_CRITICAL,\n COMMAND_PRIORITY_LOW,\n SELECTION_CHANGE_COMMAND,\n mergeRegister,\n $findMatchingParent\n} from \"lexical\";\nimport { FloatingLinkEditor } from \"./FloatingLinkEditor.js\";\nimport { LinkFormProps } from \"./types.js\";\n\ninterface FloatingLinkEditorProps {\n LinkForm: React.FunctionComponent<LinkFormProps>;\n}\n\nexport const FloatingLinkEditorController = (props: FloatingLinkEditorProps) => {\n const { editor, getOverlaysElement } = useRichTextEditor();\n const [isLink, setIsLink] = useState(false);\n\n const debounceSetIsLink = useCallback(debounce(setIsLink, 50), []);\n\n const updateToolbar = useCallback(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return;\n }\n\n const node = getSelectedNode(selection);\n const linkParent = $findMatchingParent(node, $isLinkNode);\n const autoLinkParent = $findMatchingParent(node, $isAutoLinkNode);\n const isLinkOrChildOfLink = Boolean($isLinkNode(node) || linkParent);\n\n if (!isLinkOrChildOfLink) {\n // When hiding the toolbar, we want to hide immediately.\n setIsLink(false);\n }\n\n if (selection.dirty) {\n // We don't want this menu to open for auto links.\n if (linkParent != null && autoLinkParent == null) {\n // When showing the toolbar, we want to debounce it, because sometimes selection gets updated\n // multiple times, and the `selection.dirty` flag goes from true to false multiple times,\n // eventually settling on `false`, which we want to set once it has settled.\n debounceSetIsLink(true);\n }\n }\n }, []);\n\n useEffect(() => {\n return mergeRegister(\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n updateToolbar();\n return false;\n },\n COMMAND_PRIORITY_CRITICAL\n ),\n editor.registerCommand(\n BLUR_COMMAND,\n payload => {\n if (!isChildOfLinkEditor(payload.relatedTarget as HTMLElement)) {\n setIsLink(false);\n }\n\n return false;\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n TOGGLE_LINK_COMMAND,\n payload => {\n setIsLink(!!payload);\n return false;\n },\n COMMAND_PRIORITY_CRITICAL\n )\n );\n }, [editor, updateToolbar]);\n\n return createPortal(\n <FloatingLinkEditor isVisible={isLink} editor={editor} LinkForm={props.LinkForm} />,\n getOverlaysElement()\n );\n};\n"],"names":["FloatingLinkEditorController","props","editor","getOverlaysElement","useRichTextEditor","isLink","setIsLink","useState","debounceSetIsLink","useCallback","debounce","updateToolbar","selection","$getSelection","$isRangeSelection","node","getSelectedNode","linkParent","$findMatchingParent","$isLinkNode","autoLinkParent","$isAutoLinkNode","isLinkOrChildOfLink","Boolean","useEffect","mergeRegister","SELECTION_CHANGE_COMMAND","COMMAND_PRIORITY_CRITICAL","BLUR_COMMAND","payload","isChildOfLinkEditor","COMMAND_PRIORITY_LOW","TOGGLE_LINK_COMMAND","createPortal","FloatingLinkEditor"],"mappings":";;;;;;;;;AAwBO,MAAMA,+BAA+B,CAACC;IACzC,MAAM,EAAEC,MAAM,EAAEC,kBAAkB,EAAE,GAAGC;IACvC,MAAM,CAACC,QAAQC,UAAU,GAAGC,SAAS;IAErC,MAAMC,oBAAoBC,YAAYC,SAASJ,WAAW,KAAK,EAAE;IAEjE,MAAMK,gBAAgBF,YAAY;QAC9B,MAAMG,YAAYC;QAClB,IAAI,CAACC,kBAAkBF,YACnB;QAGJ,MAAMG,OAAOC,gBAAgBJ;QAC7B,MAAMK,aAAaC,oBAAoBH,MAAMI;QAC7C,MAAMC,iBAAiBF,oBAAoBH,MAAMM;QACjD,MAAMC,sBAAsBC,QAAQJ,YAAYJ,SAASE;QAEzD,IAAI,CAACK,qBAEDhB,UAAU;QAGd,IAAIM,UAAU,KAAK,EAEf;YAAA,IAAIK,AAAc,QAAdA,cAAsBG,AAAkB,QAAlBA,gBAItBZ,kBAAkB;QACtB;IAER,GAAG,EAAE;IAELgB,UAAU,IACCC,cACHvB,OAAO,eAAe,CAClBwB,0BACA;YACIf;YACA,OAAO;QACX,GACAgB,4BAEJzB,OAAO,eAAe,CAClB0B,cACAC,CAAAA;YACI,IAAI,CAACC,oBAAoBD,QAAQ,aAAa,GAC1CvB,UAAU;YAGd,OAAO;QACX,GACAyB,uBAEJ7B,OAAO,eAAe,CAClB8B,qBACAH,CAAAA;
|
|
1
|
+
{"version":3,"file":"plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js","sources":["../../../src/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.tsx"],"sourcesContent":["import React, { useCallback, useState, useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { getSelectedNode } from \"~/utils/getSelectedNode.js\";\nimport { $isAutoLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from \"@webiny/lexical-nodes\";\nimport { isChildOfLinkEditor } from \"~/plugins/FloatingLinkEditorPlugin/isChildOfLinkEditor.js\";\nimport debounce from \"lodash/debounce.js\";\nimport {\n $getSelection,\n $isRangeSelection,\n BLUR_COMMAND,\n COMMAND_PRIORITY_CRITICAL,\n COMMAND_PRIORITY_LOW,\n SELECTION_CHANGE_COMMAND,\n mergeRegister,\n $findMatchingParent\n} from \"lexical\";\nimport { FloatingLinkEditor } from \"./FloatingLinkEditor.js\";\nimport { LinkFormProps } from \"./types.js\";\n\ninterface FloatingLinkEditorProps {\n LinkForm: React.FunctionComponent<LinkFormProps>;\n}\n\nexport const FloatingLinkEditorController = (props: FloatingLinkEditorProps) => {\n const { editor, getOverlaysElement } = useRichTextEditor();\n const [isLink, setIsLink] = useState(false);\n\n const debounceSetIsLink = useCallback(debounce(setIsLink, 50), []);\n\n const updateToolbar = useCallback(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return;\n }\n\n const node = getSelectedNode(selection);\n const linkParent = $findMatchingParent(node, $isLinkNode);\n const autoLinkParent = $findMatchingParent(node, $isAutoLinkNode);\n const isLinkOrChildOfLink = Boolean($isLinkNode(node) || linkParent);\n\n if (!isLinkOrChildOfLink) {\n // When hiding the toolbar, we want to hide immediately.\n setIsLink(false);\n }\n\n if (selection.dirty) {\n // We don't want this menu to open for auto links.\n if (linkParent != null && autoLinkParent == null) {\n // When showing the toolbar, we want to debounce it, because sometimes selection gets updated\n // multiple times, and the `selection.dirty` flag goes from true to false multiple times,\n // eventually settling on `false`, which we want to set once it has settled.\n debounceSetIsLink(true);\n }\n }\n }, []);\n\n useEffect(() => {\n return mergeRegister(\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n updateToolbar();\n return false;\n },\n COMMAND_PRIORITY_CRITICAL\n ),\n editor.registerCommand(\n BLUR_COMMAND,\n payload => {\n if (!isChildOfLinkEditor(payload.relatedTarget as HTMLElement)) {\n setIsLink(false);\n }\n\n return false;\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n TOGGLE_LINK_COMMAND,\n payload => {\n // Only open the editor when there's a real range selection inside the\n // editor. Otherwise (e.g. the link button clicked with no cursor in the\n // editor) there's nothing to anchor to and the dialog jumps to (0, 0).\n setIsLink(!!payload && $isRangeSelection($getSelection()));\n return false;\n },\n COMMAND_PRIORITY_CRITICAL\n )\n );\n }, [editor, updateToolbar]);\n\n return createPortal(\n <FloatingLinkEditor isVisible={isLink} editor={editor} LinkForm={props.LinkForm} />,\n getOverlaysElement()\n );\n};\n"],"names":["FloatingLinkEditorController","props","editor","getOverlaysElement","useRichTextEditor","isLink","setIsLink","useState","debounceSetIsLink","useCallback","debounce","updateToolbar","selection","$getSelection","$isRangeSelection","node","getSelectedNode","linkParent","$findMatchingParent","$isLinkNode","autoLinkParent","$isAutoLinkNode","isLinkOrChildOfLink","Boolean","useEffect","mergeRegister","SELECTION_CHANGE_COMMAND","COMMAND_PRIORITY_CRITICAL","BLUR_COMMAND","payload","isChildOfLinkEditor","COMMAND_PRIORITY_LOW","TOGGLE_LINK_COMMAND","createPortal","FloatingLinkEditor"],"mappings":";;;;;;;;;AAwBO,MAAMA,+BAA+B,CAACC;IACzC,MAAM,EAAEC,MAAM,EAAEC,kBAAkB,EAAE,GAAGC;IACvC,MAAM,CAACC,QAAQC,UAAU,GAAGC,SAAS;IAErC,MAAMC,oBAAoBC,YAAYC,SAASJ,WAAW,KAAK,EAAE;IAEjE,MAAMK,gBAAgBF,YAAY;QAC9B,MAAMG,YAAYC;QAClB,IAAI,CAACC,kBAAkBF,YACnB;QAGJ,MAAMG,OAAOC,gBAAgBJ;QAC7B,MAAMK,aAAaC,oBAAoBH,MAAMI;QAC7C,MAAMC,iBAAiBF,oBAAoBH,MAAMM;QACjD,MAAMC,sBAAsBC,QAAQJ,YAAYJ,SAASE;QAEzD,IAAI,CAACK,qBAEDhB,UAAU;QAGd,IAAIM,UAAU,KAAK,EAEf;YAAA,IAAIK,AAAc,QAAdA,cAAsBG,AAAkB,QAAlBA,gBAItBZ,kBAAkB;QACtB;IAER,GAAG,EAAE;IAELgB,UAAU,IACCC,cACHvB,OAAO,eAAe,CAClBwB,0BACA;YACIf;YACA,OAAO;QACX,GACAgB,4BAEJzB,OAAO,eAAe,CAClB0B,cACAC,CAAAA;YACI,IAAI,CAACC,oBAAoBD,QAAQ,aAAa,GAC1CvB,UAAU;YAGd,OAAO;QACX,GACAyB,uBAEJ7B,OAAO,eAAe,CAClB8B,qBACAH,CAAAA;YAIIvB,UAAU,CAAC,CAACuB,WAAWf,kBAAkBD;YACzC,OAAO;QACX,GACAc,6BAGT;QAACzB;QAAQS;KAAc;IAE1B,OAAO,WAAP,GAAOsB,aAAa,WAADA,GACf,oBAACC,oBAAkBA;QAAC,WAAW7B;QAAQ,QAAQH;QAAQ,UAAUD,MAAM,QAAQ;QAC/EE;AAER"}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
max-width: 400px;
|
|
5
5
|
width: 100%;
|
|
6
6
|
opacity: 0;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
border
|
|
7
|
+
/* Border-defined like admin-ui menus (no shadow), rounded-md. */
|
|
8
|
+
background-color: var(--color-neutral-base);
|
|
9
|
+
border: 1px solid var(--border-color-neutral-muted);
|
|
10
|
+
border-radius: var(--radius-md);
|
|
10
11
|
pointer-events: all;
|
|
11
12
|
}
|
|
12
13
|
.link-editor .button {
|
package/ui/DropDown.d.ts
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
export declare function DropDownItem({ children, className, onClick, title }: {
|
|
3
|
+
export declare function DropDownItem({ children, className, onClick, title, selected }: {
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
className: string;
|
|
6
6
|
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
7
7
|
title?: string;
|
|
8
|
+
selected?: boolean;
|
|
8
9
|
}): React.JSX.Element;
|
|
9
10
|
interface DropDownProps {
|
|
10
11
|
disabled?: boolean;
|
|
11
12
|
buttonAriaLabel?: string;
|
|
12
13
|
buttonClassName: string;
|
|
13
14
|
buttonIconClassName?: string;
|
|
15
|
+
buttonIcon?: ReactNode;
|
|
14
16
|
buttonLabel?: string;
|
|
15
17
|
children: ReactNode;
|
|
16
18
|
stopCloseOnClickSelf?: boolean;
|
|
17
19
|
showScroll?: boolean;
|
|
18
20
|
}
|
|
19
|
-
export declare function DropDown({ disabled, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, children, showScroll }: DropDownProps): React.JSX.Element;
|
|
21
|
+
export declare function DropDown({ disabled, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, buttonIcon, children, showScroll }: DropDownProps): React.JSX.Element;
|
|
20
22
|
export {};
|
package/ui/DropDown.js
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { DropdownMenu } from "radix-ui";
|
|
2
|
+
import { ReactComponent } from "@webiny/icons/expand_more.svg";
|
|
3
|
+
import { ReactComponent as check_svg_ReactComponent } from "@webiny/icons/check.svg";
|
|
2
4
|
import * as __rspack_external_react from "react";
|
|
3
|
-
function DropDownItem({ children, className, onClick, title }) {
|
|
5
|
+
function DropDownItem({ children, className, onClick, title, selected }) {
|
|
6
|
+
const hasCheckSlot = void 0 !== selected;
|
|
4
7
|
return /*#__PURE__*/ __rspack_external_react.createElement("button", {
|
|
5
8
|
className: className,
|
|
6
9
|
onClick: onClick,
|
|
7
10
|
title: title,
|
|
8
11
|
type: "button"
|
|
9
|
-
},
|
|
12
|
+
}, hasCheckSlot ? selected ? /*#__PURE__*/ __rspack_external_react.createElement(check_svg_ReactComponent, {
|
|
13
|
+
className: "item-check"
|
|
14
|
+
}) : /*#__PURE__*/ __rspack_external_react.createElement("span", {
|
|
15
|
+
className: "item-check",
|
|
16
|
+
"aria-hidden": "true"
|
|
17
|
+
}) : null, children);
|
|
10
18
|
}
|
|
11
|
-
function DropDown({ disabled = false, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, children, showScroll = true }) {
|
|
19
|
+
function DropDown({ disabled = false, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, buttonIcon, children, showScroll = true }) {
|
|
12
20
|
return /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Root, null, /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Trigger, {
|
|
13
21
|
asChild: true
|
|
14
22
|
}, /*#__PURE__*/ __rspack_external_react.createElement("button", {
|
|
@@ -18,11 +26,11 @@ function DropDown({ disabled = false, buttonLabel, buttonAriaLabel, buttonClassN
|
|
|
18
26
|
disabled: disabled,
|
|
19
27
|
"aria-label": buttonAriaLabel || buttonLabel,
|
|
20
28
|
className: buttonClassName
|
|
21
|
-
}, buttonIconClassName && /*#__PURE__*/ __rspack_external_react.createElement("span", {
|
|
29
|
+
}, buttonIcon ? buttonIcon : buttonIconClassName && /*#__PURE__*/ __rspack_external_react.createElement("span", {
|
|
22
30
|
className: buttonIconClassName
|
|
23
31
|
}), buttonLabel && /*#__PURE__*/ __rspack_external_react.createElement("span", {
|
|
24
32
|
className: "text dropdown-button-text"
|
|
25
|
-
}, buttonLabel), /*#__PURE__*/ __rspack_external_react.createElement(
|
|
33
|
+
}, buttonLabel), /*#__PURE__*/ __rspack_external_react.createElement(ReactComponent, {
|
|
26
34
|
className: "chevron-down"
|
|
27
35
|
}))), /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Portal, null, /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Content, {
|
|
28
36
|
className: `lexical-dropdown z-overlay ${showScroll ? "" : "no-scroll"}`,
|