@webiny/lexical-editor 0.0.0-unstable.06b2ede40f

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.
Files changed (308) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/commands/image.d.ts +6 -0
  4. package/commands/image.js +4 -0
  5. package/commands/image.js.map +1 -0
  6. package/commands/index.d.ts +5 -0
  7. package/commands/index.js +7 -0
  8. package/commands/index.js.map +1 -0
  9. package/commands/list.d.ts +7 -0
  10. package/commands/list.js +6 -0
  11. package/commands/list.js.map +1 -0
  12. package/commands/quote.d.ts +5 -0
  13. package/commands/quote.js +4 -0
  14. package/commands/quote.js.map +1 -0
  15. package/commands/toolbar.d.ts +1 -0
  16. package/commands/toolbar.js +4 -0
  17. package/commands/toolbar.js.map +1 -0
  18. package/commands/typography.d.ts +8 -0
  19. package/commands/typography.js +4 -0
  20. package/commands/typography.js.map +1 -0
  21. package/components/Editor/EnsureHeadingTagPlugin.d.ts +6 -0
  22. package/components/Editor/EnsureHeadingTagPlugin.js +20 -0
  23. package/components/Editor/EnsureHeadingTagPlugin.js.map +1 -0
  24. package/components/Editor/HeadingEditor.d.ts +7 -0
  25. package/components/Editor/HeadingEditor.js +22 -0
  26. package/components/Editor/HeadingEditor.js.map +1 -0
  27. package/components/Editor/ParagraphEditor.d.ts +7 -0
  28. package/components/Editor/ParagraphEditor.js +22 -0
  29. package/components/Editor/ParagraphEditor.js.map +1 -0
  30. package/components/Editor/RichTextEditor.d.ts +49 -0
  31. package/components/Editor/RichTextEditor.js +133 -0
  32. package/components/Editor/RichTextEditor.js.map +1 -0
  33. package/components/Editor/normalizeInputValue.d.ts +6 -0
  34. package/components/Editor/normalizeInputValue.js +16 -0
  35. package/components/Editor/normalizeInputValue.js.map +1 -0
  36. package/components/LexicalEditorConfig/LexicalEditorConfig.d.ts +20 -0
  37. package/components/LexicalEditorConfig/LexicalEditorConfig.js +63 -0
  38. package/components/LexicalEditorConfig/LexicalEditorConfig.js.map +1 -0
  39. package/components/LexicalEditorConfig/components/Node.d.ts +14 -0
  40. package/components/LexicalEditorConfig/components/Node.js +30 -0
  41. package/components/LexicalEditorConfig/components/Node.js.map +1 -0
  42. package/components/LexicalEditorConfig/components/Plugin.d.ts +13 -0
  43. package/components/LexicalEditorConfig/components/Plugin.js +30 -0
  44. package/components/LexicalEditorConfig/components/Plugin.js.map +1 -0
  45. package/components/LexicalEditorConfig/components/ToolbarElement.d.ts +13 -0
  46. package/components/LexicalEditorConfig/components/ToolbarElement.js +30 -0
  47. package/components/LexicalEditorConfig/components/ToolbarElement.js.map +1 -0
  48. package/components/LexicalHtmlRenderer.d.ts +14 -0
  49. package/components/LexicalHtmlRenderer.js +55 -0
  50. package/components/LexicalHtmlRenderer.js.map +1 -0
  51. package/components/Toolbar/StaticToolbar.css +260 -0
  52. package/components/Toolbar/StaticToolbar.d.ts +5 -0
  53. package/components/Toolbar/StaticToolbar.js +22 -0
  54. package/components/Toolbar/StaticToolbar.js.map +1 -0
  55. package/components/Toolbar/Toolbar.css +643 -0
  56. package/components/Toolbar/Toolbar.d.ts +6 -0
  57. package/components/Toolbar/Toolbar.js +148 -0
  58. package/components/Toolbar/Toolbar.js.map +1 -0
  59. package/components/ToolbarActions/BoldAction.d.ts +2 -0
  60. package/components/ToolbarActions/BoldAction.js +25 -0
  61. package/components/ToolbarActions/BoldAction.js.map +1 -0
  62. package/components/ToolbarActions/BulletListAction.d.ts +2 -0
  63. package/components/ToolbarActions/BulletListAction.js +40 -0
  64. package/components/ToolbarActions/BulletListAction.js.map +1 -0
  65. package/components/ToolbarActions/CodeHighlightAction.d.ts +2 -0
  66. package/components/ToolbarActions/CodeHighlightAction.js +25 -0
  67. package/components/ToolbarActions/CodeHighlightAction.js.map +1 -0
  68. package/components/ToolbarActions/FontColorAction.d.ts +29 -0
  69. package/components/ToolbarActions/FontColorAction.js +50 -0
  70. package/components/ToolbarActions/FontColorAction.js.map +1 -0
  71. package/components/ToolbarActions/FontSizeAction.d.ts +14 -0
  72. package/components/ToolbarActions/FontSizeAction.js +91 -0
  73. package/components/ToolbarActions/FontSizeAction.js.map +1 -0
  74. package/components/ToolbarActions/ImageAction.d.ts +2 -0
  75. package/components/ToolbarActions/ImageAction.js +37 -0
  76. package/components/ToolbarActions/ImageAction.js.map +1 -0
  77. package/components/ToolbarActions/ItalicAction.d.ts +2 -0
  78. package/components/ToolbarActions/ItalicAction.js +25 -0
  79. package/components/ToolbarActions/ItalicAction.js.map +1 -0
  80. package/components/ToolbarActions/LinkAction.d.ts +2 -0
  81. package/components/ToolbarActions/LinkAction.js +37 -0
  82. package/components/ToolbarActions/LinkAction.js.map +1 -0
  83. package/components/ToolbarActions/NumberedListAction.d.ts +2 -0
  84. package/components/ToolbarActions/NumberedListAction.js +48 -0
  85. package/components/ToolbarActions/NumberedListAction.js.map +1 -0
  86. package/components/ToolbarActions/QuoteAction.d.ts +2 -0
  87. package/components/ToolbarActions/QuoteAction.js +33 -0
  88. package/components/ToolbarActions/QuoteAction.js.map +1 -0
  89. package/components/ToolbarActions/TextAlignmentAction.d.ts +29 -0
  90. package/components/ToolbarActions/TextAlignmentAction.js +61 -0
  91. package/components/ToolbarActions/TextAlignmentAction.js.map +1 -0
  92. package/components/ToolbarActions/TypographyAction.d.ts +29 -0
  93. package/components/ToolbarActions/TypographyAction.js +108 -0
  94. package/components/ToolbarActions/TypographyAction.js.map +1 -0
  95. package/components/ToolbarActions/UnderlineAction.d.ts +2 -0
  96. package/components/ToolbarActions/UnderlineAction.js +24 -0
  97. package/components/ToolbarActions/UnderlineAction.js.map +1 -0
  98. package/context/FontColorActionContext.d.ts +6 -0
  99. package/context/FontColorActionContext.js +4 -0
  100. package/context/FontColorActionContext.js.map +1 -0
  101. package/context/RichTextEditorContext.d.ts +19 -0
  102. package/context/RichTextEditorContext.js +21 -0
  103. package/context/RichTextEditorContext.js.map +1 -0
  104. package/context/SharedHistoryContext.d.ts +10 -0
  105. package/context/SharedHistoryContext.js +19 -0
  106. package/context/SharedHistoryContext.js.map +1 -0
  107. package/context/TextAlignmentActionContextProps.d.ts +9 -0
  108. package/context/TextAlignmentActionContextProps.js +4 -0
  109. package/context/TextAlignmentActionContextProps.js.map +1 -0
  110. package/context/TypographyActionContext.d.ts +8 -0
  111. package/context/TypographyActionContext.js +4 -0
  112. package/context/TypographyActionContext.js.map +1 -0
  113. package/hooks/index.d.ts +8 -0
  114. package/hooks/index.js +10 -0
  115. package/hooks/index.js.map +1 -0
  116. package/hooks/useCurrentElement.d.ts +7 -0
  117. package/hooks/useCurrentElement.js +27 -0
  118. package/hooks/useCurrentElement.js.map +1 -0
  119. package/hooks/useCurrentSelection.d.ts +13 -0
  120. package/hooks/useCurrentSelection.js +57 -0
  121. package/hooks/useCurrentSelection.js.map +1 -0
  122. package/hooks/useFontColorPicker.d.ts +2 -0
  123. package/hooks/useFontColorPicker.js +11 -0
  124. package/hooks/useFontColorPicker.js.map +1 -0
  125. package/hooks/useIsMounted.d.ts +1 -0
  126. package/hooks/useIsMounted.js +12 -0
  127. package/hooks/useIsMounted.js.map +1 -0
  128. package/hooks/useList.d.ts +2 -0
  129. package/hooks/useList.js +50 -0
  130. package/hooks/useList.js.map +1 -0
  131. package/hooks/useQuote.d.ts +2 -0
  132. package/hooks/useQuote.js +17 -0
  133. package/hooks/useQuote.js.map +1 -0
  134. package/hooks/useRichTextEditor.d.ts +2 -0
  135. package/hooks/useRichTextEditor.js +11 -0
  136. package/hooks/useRichTextEditor.js.map +1 -0
  137. package/hooks/useTextAlignmentAction.d.ts +1 -0
  138. package/hooks/useTextAlignmentAction.js +11 -0
  139. package/hooks/useTextAlignmentAction.js.map +1 -0
  140. package/hooks/useTypographyAction.d.ts +1 -0
  141. package/hooks/useTypographyAction.js +11 -0
  142. package/hooks/useTypographyAction.js.map +1 -0
  143. package/images/icons/LICENSE.md +5 -0
  144. package/images/icons/chat-square-quote.svg +1 -0
  145. package/images/icons/chevron-down.svg +1 -0
  146. package/images/icons/code.svg +1 -0
  147. package/images/icons/font-color.svg +1 -0
  148. package/images/icons/indent.svg +3 -0
  149. package/images/icons/insert-image.svg +4 -0
  150. package/images/icons/justify.svg +3 -0
  151. package/images/icons/link.svg +1 -0
  152. package/images/icons/list-ol.svg +1 -0
  153. package/images/icons/list-ul.svg +1 -0
  154. package/images/icons/outdent.svg +3 -0
  155. package/images/icons/pencil-fill.svg +1 -0
  156. package/images/icons/text-center.svg +1 -0
  157. package/images/icons/text-left.svg +1 -0
  158. package/images/icons/text-paragraph.svg +1 -0
  159. package/images/icons/text-right.svg +1 -0
  160. package/images/icons/type-bold.svg +1 -0
  161. package/images/icons/type-h1.svg +1 -0
  162. package/images/icons/type-h2.svg +1 -0
  163. package/images/icons/type-h3.svg +1 -0
  164. package/images/icons/type-h4.svg +1 -0
  165. package/images/icons/type-h5.svg +1 -0
  166. package/images/icons/type-h6.svg +1 -0
  167. package/images/icons/type-italic.svg +1 -0
  168. package/images/icons/type-strikethrough.svg +1 -0
  169. package/images/icons/type-underline.svg +1 -0
  170. package/images/icons/unlink_icon.svg +1 -0
  171. package/index.d.ts +37 -0
  172. package/index.js +50 -0
  173. package/index.js.map +1 -0
  174. package/package.json +40 -0
  175. package/plugins/BlurEventPlugin/BlurEventPlugin.d.ts +7 -0
  176. package/plugins/BlurEventPlugin/BlurEventPlugin.js +20 -0
  177. package/plugins/BlurEventPlugin/BlurEventPlugin.js.map +1 -0
  178. package/plugins/CodeHighlightPlugin/CodeHighlightPlugin.d.ts +1 -0
  179. package/plugins/CodeHighlightPlugin/CodeHighlightPlugin.js +14 -0
  180. package/plugins/CodeHighlightPlugin/CodeHighlightPlugin.js.map +1 -0
  181. package/plugins/CodeHighlightPlugin/index.d.ts +1 -0
  182. package/plugins/CodeHighlightPlugin/index.js +3 -0
  183. package/plugins/CodeHighlightPlugin/index.js.map +1 -0
  184. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.d.ts +16 -0
  185. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.js +158 -0
  186. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.js.map +1 -0
  187. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.d.ts +8 -0
  188. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js +62 -0
  189. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorController.js.map +1 -0
  190. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin.css +176 -0
  191. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin.d.ts +7 -0
  192. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin.js +14 -0
  193. package/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin.js.map +1 -0
  194. package/plugins/FloatingLinkEditorPlugin/LinkEditForm.d.ts +8 -0
  195. package/plugins/FloatingLinkEditorPlugin/LinkEditForm.js +104 -0
  196. package/plugins/FloatingLinkEditorPlugin/LinkEditForm.js.map +1 -0
  197. package/plugins/FloatingLinkEditorPlugin/LinkPreviewForm.d.ts +9 -0
  198. package/plugins/FloatingLinkEditorPlugin/LinkPreviewForm.js +34 -0
  199. package/plugins/FloatingLinkEditorPlugin/LinkPreviewForm.js.map +1 -0
  200. package/plugins/FloatingLinkEditorPlugin/index.d.ts +1 -0
  201. package/plugins/FloatingLinkEditorPlugin/index.js +3 -0
  202. package/plugins/FloatingLinkEditorPlugin/index.js.map +1 -0
  203. package/plugins/FloatingLinkEditorPlugin/isChildOfLinkEditor.d.ts +1 -0
  204. package/plugins/FloatingLinkEditorPlugin/isChildOfLinkEditor.js +12 -0
  205. package/plugins/FloatingLinkEditorPlugin/isChildOfLinkEditor.js.map +1 -0
  206. package/plugins/FontColorPlugin/FontColorPlugin.d.ts +1 -0
  207. package/plugins/FontColorPlugin/FontColorPlugin.js +27 -0
  208. package/plugins/FontColorPlugin/FontColorPlugin.js.map +1 -0
  209. package/plugins/FontColorPlugin/applyColorToNode.d.ts +3 -0
  210. package/plugins/FontColorPlugin/applyColorToNode.js +8 -0
  211. package/plugins/FontColorPlugin/applyColorToNode.js.map +1 -0
  212. package/plugins/FontColorPlugin/applyColorToSelection.d.ts +3 -0
  213. package/plugins/FontColorPlugin/applyColorToSelection.js +66 -0
  214. package/plugins/FontColorPlugin/applyColorToSelection.js.map +1 -0
  215. package/plugins/ImagesPlugin/ImagesPlugin.d.ts +12 -0
  216. package/plugins/ImagesPlugin/ImagesPlugin.js +151 -0
  217. package/plugins/ImagesPlugin/ImagesPlugin.js.map +1 -0
  218. package/plugins/LinkPlugin/LinkPlugin.d.ts +5 -0
  219. package/plugins/LinkPlugin/LinkPlugin.js +59 -0
  220. package/plugins/LinkPlugin/LinkPlugin.js.map +1 -0
  221. package/plugins/ListPLugin/ListPlugin.d.ts +1 -0
  222. package/plugins/ListPLugin/ListPlugin.js +17 -0
  223. package/plugins/ListPLugin/ListPlugin.js.map +1 -0
  224. package/plugins/QuoteNodePlugin/QuoteNodePlugin.d.ts +1 -0
  225. package/plugins/QuoteNodePlugin/QuoteNodePlugin.js +18 -0
  226. package/plugins/QuoteNodePlugin/QuoteNodePlugin.js.map +1 -0
  227. package/plugins/StateHandlingPlugin.d.ts +8 -0
  228. package/plugins/StateHandlingPlugin.js +75 -0
  229. package/plugins/StateHandlingPlugin.js.map +1 -0
  230. package/plugins/TypographyPlugin/TypographyPlugin.d.ts +1 -0
  231. package/plugins/TypographyPlugin/TypographyPlugin.js +27 -0
  232. package/plugins/TypographyPlugin/TypographyPlugin.js.map +1 -0
  233. package/types.d.ts +12 -0
  234. package/types.js +9 -0
  235. package/types.js.map +1 -0
  236. package/ui/ContentEditable.css +22 -0
  237. package/ui/ContentEditable.d.ts +12 -0
  238. package/ui/ContentEditable.js +19 -0
  239. package/ui/ContentEditable.js.map +1 -0
  240. package/ui/Divider.d.ts +2 -0
  241. package/ui/Divider.js +8 -0
  242. package/ui/Divider.js.map +1 -0
  243. package/ui/DropDown.d.ts +25 -0
  244. package/ui/DropDown.js +182 -0
  245. package/ui/DropDown.js.map +1 -0
  246. package/ui/ImageResizer.d.ts +24 -0
  247. package/ui/ImageResizer.js +211 -0
  248. package/ui/ImageResizer.js.map +1 -0
  249. package/ui/Input.css +32 -0
  250. package/ui/LinkPreview.css +69 -0
  251. package/ui/LinkPreview.d.ts +12 -0
  252. package/ui/LinkPreview.js +97 -0
  253. package/ui/LinkPreview.js.map +1 -0
  254. package/ui/Placeholder.css +20 -0
  255. package/ui/Placeholder.d.ts +15 -0
  256. package/ui/Placeholder.js +24 -0
  257. package/ui/Placeholder.js.map +1 -0
  258. package/ui/TextInput.d.ts +18 -0
  259. package/ui/TextInput.js +34 -0
  260. package/ui/TextInput.js.map +1 -0
  261. package/ui/ToolbarActionDialog.d.ts +11 -0
  262. package/ui/ToolbarActionDialog.js +77 -0
  263. package/ui/ToolbarActionDialog.js.map +1 -0
  264. package/utils/canUseDOM.d.ts +1 -0
  265. package/utils/canUseDOM.js +3 -0
  266. package/utils/canUseDOM.js.map +1 -0
  267. package/utils/files.d.ts +11 -0
  268. package/utils/files.js +21 -0
  269. package/utils/files.js.map +1 -0
  270. package/utils/getDOMRangeRect.d.ts +8 -0
  271. package/utils/getDOMRangeRect.js +23 -0
  272. package/utils/getDOMRangeRect.js.map +1 -0
  273. package/utils/getSelectedNode.d.ts +2 -0
  274. package/utils/getSelectedNode.js +25 -0
  275. package/utils/getSelectedNode.js.map +1 -0
  276. package/utils/getTransparentImage.d.ts +1 -0
  277. package/utils/getTransparentImage.js +5 -0
  278. package/utils/getTransparentImage.js.map +1 -0
  279. package/utils/insertImage.d.ts +2 -0
  280. package/utils/insertImage.js +16 -0
  281. package/utils/insertImage.js.map +1 -0
  282. package/utils/isAnchorLink.d.ts +1 -0
  283. package/utils/isAnchorLink.js +5 -0
  284. package/utils/isAnchorLink.js.map +1 -0
  285. package/utils/isChildOfFloatingToolbar.d.ts +1 -0
  286. package/utils/isChildOfFloatingToolbar.js +12 -0
  287. package/utils/isChildOfFloatingToolbar.js.map +1 -0
  288. package/utils/isHTMLElement.d.ts +8 -0
  289. package/utils/isHTMLElement.js +12 -0
  290. package/utils/isHTMLElement.js.map +1 -0
  291. package/utils/isValidJSON.d.ts +1 -0
  292. package/utils/isValidJSON.js +13 -0
  293. package/utils/isValidJSON.js.map +1 -0
  294. package/utils/isValidLexicalData.d.ts +4 -0
  295. package/utils/isValidLexicalData.js +24 -0
  296. package/utils/isValidLexicalData.js.map +1 -0
  297. package/utils/point.d.ts +21 -0
  298. package/utils/point.js +49 -0
  299. package/utils/point.js.map +1 -0
  300. package/utils/rect.d.ts +45 -0
  301. package/utils/rect.js +130 -0
  302. package/utils/rect.js.map +1 -0
  303. package/utils/sanitizeUrl.d.ts +1 -0
  304. package/utils/sanitizeUrl.js +25 -0
  305. package/utils/sanitizeUrl.js.map +1 -0
  306. package/utils/setFloatingElemPosition.d.ts +1 -0
  307. package/utils/setFloatingElemPosition.js +30 -0
  308. package/utils/setFloatingElemPosition.js.map +1 -0
@@ -0,0 +1,104 @@
1
+ import React, { useState } from "react";
2
+ import { sanitizeUrl } from "../../utils/sanitizeUrl";
3
+ import { isAnchorLink } from "../../utils/isAnchorLink";
4
+ export const LinkEditForm = ({
5
+ linkData,
6
+ onSave,
7
+ onCancel
8
+ }) => {
9
+ const [linkState, setLinkState] = useState(linkData);
10
+ const onInputKeyDown = event => {
11
+ if (event.key === "Enter") {
12
+ event.preventDefault();
13
+ onSubmit();
14
+ } else if (event.key === "Escape") {
15
+ event.preventDefault();
16
+ onCancel();
17
+ }
18
+ };
19
+ const onSubmit = () => {
20
+ onSave({
21
+ ...linkState,
22
+ target: isAnchorLink(linkState.url) ? null : linkState.target,
23
+ url: sanitizeUrl(linkState.url)
24
+ });
25
+ };
26
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h5", {
27
+ className: "link-editor-popup-title"
28
+ }, "Edit Link"), /*#__PURE__*/React.createElement("div", {
29
+ className: "link-editor-section"
30
+ }, /*#__PURE__*/React.createElement("div", {
31
+ className: "header"
32
+ }, /*#__PURE__*/React.createElement("div", {
33
+ className: "header_title"
34
+ }, "URL")), /*#__PURE__*/React.createElement("div", {
35
+ className: "section-desc"
36
+ }, /*#__PURE__*/React.createElement("input", {
37
+ autoFocus: true,
38
+ placeholder: "URL: https://example.com",
39
+ className: "link-input full-with",
40
+ value: linkState.url,
41
+ onKeyDown: onInputKeyDown,
42
+ onChange: e => {
43
+ return setLinkState(state => ({
44
+ ...state,
45
+ url: e.target.value
46
+ }));
47
+ }
48
+ }))), /*#__PURE__*/React.createElement("div", {
49
+ className: "link-editor-section"
50
+ }, /*#__PURE__*/React.createElement("div", {
51
+ className: "header"
52
+ }, /*#__PURE__*/React.createElement("div", {
53
+ className: "header_title"
54
+ }, "Alt text")), /*#__PURE__*/React.createElement("div", {
55
+ className: "section-desc"
56
+ }, /*#__PURE__*/React.createElement("input", {
57
+ placeholder: "Enter alt text",
58
+ className: "link-input full-with",
59
+ type: "text",
60
+ value: linkState.alt || "",
61
+ onKeyDown: onInputKeyDown,
62
+ onChange: e => {
63
+ return setLinkState(state => ({
64
+ ...state,
65
+ alt: e.target.value
66
+ }));
67
+ }
68
+ }))), /*#__PURE__*/React.createElement("div", {
69
+ className: "link-editor-section"
70
+ }, /*#__PURE__*/React.createElement("div", {
71
+ className: "section-desc"
72
+ }, /*#__PURE__*/React.createElement("input", {
73
+ id: "link-editor-new-tab",
74
+ type: "checkbox",
75
+ checked: linkState.target === "_blank",
76
+ disabled: isAnchorLink(linkState.url),
77
+ onChange: e => {
78
+ return setLinkState(state => ({
79
+ ...state,
80
+ target: e.target.checked ? "_blank" : null
81
+ }));
82
+ }
83
+ }), /*#__PURE__*/React.createElement("label", {
84
+ htmlFor: "link-editor-new-tab"
85
+ }, "Open link in a new tab"))), /*#__PURE__*/React.createElement("div", {
86
+ className: "link-editor-section full-with edit-form-bottom-menu"
87
+ }, /*#__PURE__*/React.createElement("button", {
88
+ className: "webiny-ui-button mdc-button",
89
+ onClick: onCancel
90
+ }, /*#__PURE__*/React.createElement("div", {
91
+ className: "mdc-button__ripple"
92
+ }), /*#__PURE__*/React.createElement("span", {
93
+ className: "mdc-button__label"
94
+ }, "Cancel")), /*#__PURE__*/React.createElement("button", {
95
+ className: "webiny-ui-button webiny-ui-button--primary mdc-button mdc-button--raised",
96
+ onClick: onSubmit
97
+ }, /*#__PURE__*/React.createElement("div", {
98
+ className: "mdc-button__ripple"
99
+ }), /*#__PURE__*/React.createElement("span", {
100
+ className: "mdc-button__label"
101
+ }, "Confirm"))));
102
+ };
103
+
104
+ //# sourceMappingURL=LinkEditForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useState","sanitizeUrl","isAnchorLink","LinkEditForm","linkData","onSave","onCancel","linkState","setLinkState","onInputKeyDown","event","key","preventDefault","onSubmit","target","url","createElement","className","autoFocus","placeholder","value","onKeyDown","onChange","e","state","type","alt","id","checked","disabled","htmlFor","onClick"],"sources":["LinkEditForm.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { sanitizeUrl } from \"~/utils/sanitizeUrl\";\nimport { isAnchorLink } from \"~/utils/isAnchorLink\";\nimport type { LinkData } from \"./FloatingLinkEditor\";\n\nexport interface LinkFormProps {\n linkData: LinkData;\n onSave: (linkData: LinkData) => void;\n onCancel: () => void;\n}\n\nexport const LinkEditForm = ({ linkData, onSave, onCancel }: LinkFormProps) => {\n const [linkState, setLinkState] = useState(linkData);\n\n const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n onSubmit();\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n onCancel();\n }\n };\n\n const onSubmit = () => {\n onSave({\n ...linkState,\n target: isAnchorLink(linkState.url) ? null : linkState.target,\n url: sanitizeUrl(linkState.url)\n });\n };\n\n return (\n <div>\n <h5 className={\"link-editor-popup-title\"}>Edit Link</h5>\n\n <div className={\"link-editor-section\"}>\n <div className={\"header\"}>\n <div className={\"header_title\"}>URL</div>\n </div>\n <div className={\"section-desc\"}>\n <input\n autoFocus\n placeholder={\"URL: https://example.com\"}\n className=\"link-input full-with\"\n value={linkState.url}\n onKeyDown={onInputKeyDown}\n onChange={e => {\n return setLinkState(state => ({\n ...state,\n url: e.target.value\n }));\n }}\n />\n </div>\n </div>\n <div className={\"link-editor-section\"}>\n <div className={\"header\"}>\n <div className={\"header_title\"}>Alt text</div>\n </div>\n <div className={\"section-desc\"}>\n <input\n placeholder={\"Enter alt text\"}\n className={\"link-input full-with\"}\n type={\"text\"}\n value={linkState.alt || \"\"}\n onKeyDown={onInputKeyDown}\n onChange={e => {\n return setLinkState(state => ({\n ...state,\n alt: e.target.value\n }));\n }}\n />\n </div>\n </div>\n <div className={\"link-editor-section\"}>\n <div className={\"section-desc\"}>\n <input\n id={\"link-editor-new-tab\"}\n type={\"checkbox\"}\n checked={linkState.target === \"_blank\"}\n disabled={isAnchorLink(linkState.url)}\n onChange={e => {\n return setLinkState(state => ({\n ...state,\n target: e.target.checked ? \"_blank\" : null\n }));\n }}\n />\n <label htmlFor={\"link-editor-new-tab\"}>Open link in a new tab</label>\n </div>\n </div>\n\n <div className={\"link-editor-section full-with edit-form-bottom-menu\"}>\n <button className=\"webiny-ui-button mdc-button\" onClick={onCancel}>\n <div className=\"mdc-button__ripple\"></div>\n <span className=\"mdc-button__label\">Cancel</span>\n </button>\n <button\n className=\"webiny-ui-button webiny-ui-button--primary mdc-button mdc-button--raised\"\n onClick={onSubmit}\n >\n <div className=\"mdc-button__ripple\"></div>\n <span className=\"mdc-button__label\">Confirm</span>\n </button>\n </div>\n </div>\n );\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import type { LinkData } from "./FloatingLinkEditor";
3
+ interface LinkFormProps {
4
+ linkData: LinkData;
5
+ onEdit: () => void;
6
+ removeLink: () => void;
7
+ }
8
+ export declare const LinkPreviewForm: ({ linkData, onEdit, removeLink }: LinkFormProps) => React.JSX.Element;
9
+ export {};
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ export const LinkPreviewForm = ({
3
+ linkData,
4
+ onEdit,
5
+ removeLink
6
+ }) => {
7
+ return /*#__PURE__*/React.createElement("div", {
8
+ className: "link-preview-form"
9
+ }, /*#__PURE__*/React.createElement("h5", {
10
+ className: "link-editor-popup-title"
11
+ }, "Preview Link"), /*#__PURE__*/React.createElement("div", {
12
+ className: "link-input"
13
+ }, /*#__PURE__*/React.createElement("a", {
14
+ href: linkData.url,
15
+ target: "_blank",
16
+ rel: "noopener noreferrer"
17
+ }, linkData.url), /*#__PURE__*/React.createElement("div", {
18
+ className: "link-edit",
19
+ role: "button",
20
+ tabIndex: 0,
21
+ onMouseDown: event => event.preventDefault(),
22
+ onClick: onEdit
23
+ }), /*#__PURE__*/React.createElement("div", {
24
+ className: "link-unlink",
25
+ role: "button",
26
+ tabIndex: 0,
27
+ onMouseDown: event => event.preventDefault(),
28
+ onClick: removeLink
29
+ })), /*#__PURE__*/React.createElement("div", {
30
+ className: "link-editor-section"
31
+ }, /*#__PURE__*/React.createElement("ul", null, /*#__PURE__*/React.createElement("li", null, linkData.target === "_blank" ? /*#__PURE__*/React.createElement("span", null, "Open link in a new tab") : /*#__PURE__*/React.createElement("span", null, "Open link in the same tab")), linkData.alt && /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("span", null, "Alt text: ", /*#__PURE__*/React.createElement("span", null, linkData.alt))))));
32
+ };
33
+
34
+ //# sourceMappingURL=LinkPreviewForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","LinkPreviewForm","linkData","onEdit","removeLink","createElement","className","href","url","target","rel","role","tabIndex","onMouseDown","event","preventDefault","onClick","alt"],"sources":["LinkPreviewForm.tsx"],"sourcesContent":["import React from \"react\";\nimport type { LinkData } from \"./FloatingLinkEditor\";\n\ninterface LinkFormProps {\n linkData: LinkData;\n onEdit: () => void;\n removeLink: () => void;\n}\n\nexport const LinkPreviewForm = ({ linkData, onEdit, removeLink }: LinkFormProps) => {\n return (\n <div className={\"link-preview-form\"}>\n <h5 className={\"link-editor-popup-title\"}>Preview Link</h5>\n <div className=\"link-input\">\n <a href={linkData.url} target=\"_blank\" rel=\"noopener noreferrer\">\n {linkData.url}\n </a>\n <div\n className=\"link-edit\"\n role=\"button\"\n tabIndex={0}\n onMouseDown={event => event.preventDefault()}\n onClick={onEdit}\n />\n <div\n className=\"link-unlink\"\n role=\"button\"\n tabIndex={0}\n onMouseDown={event => event.preventDefault()}\n onClick={removeLink}\n />\n </div>\n <div className={\"link-editor-section\"}>\n <ul>\n <li>\n {linkData.target === \"_blank\" ? (\n <span>Open link in a new tab</span>\n ) : (\n <span>Open link in the same tab</span>\n )}\n </li>\n {linkData.alt && (\n <li>\n <span>\n Alt text: <span>{linkData.alt}</span>\n </span>\n </li>\n )}\n </ul>\n </div>\n </div>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AASzB,OAAO,MAAMC,eAAe,GAAGA,CAAC;EAAEC,QAAQ;EAAEC,MAAM;EAAEC;AAA0B,CAAC,KAAK;EAChF,oBACIJ,KAAA,CAAAK,aAAA;IAAKC,SAAS,EAAE;EAAoB,gBAChCN,KAAA,CAAAK,aAAA;IAAIC,SAAS,EAAE;EAA0B,GAAC,cAAgB,CAAC,eAC3DN,KAAA,CAAAK,aAAA;IAAKC,SAAS,EAAC;EAAY,gBACvBN,KAAA,CAAAK,aAAA;IAAGE,IAAI,EAAEL,QAAQ,CAACM,GAAI;IAACC,MAAM,EAAC,QAAQ;IAACC,GAAG,EAAC;EAAqB,GAC3DR,QAAQ,CAACM,GACX,CAAC,eACJR,KAAA,CAAAK,aAAA;IACIC,SAAS,EAAC,WAAW;IACrBK,IAAI,EAAC,QAAQ;IACbC,QAAQ,EAAE,CAAE;IACZC,WAAW,EAAEC,KAAK,IAAIA,KAAK,CAACC,cAAc,CAAC,CAAE;IAC7CC,OAAO,EAAEb;EAAO,CACnB,CAAC,eACFH,KAAA,CAAAK,aAAA;IACIC,SAAS,EAAC,aAAa;IACvBK,IAAI,EAAC,QAAQ;IACbC,QAAQ,EAAE,CAAE;IACZC,WAAW,EAAEC,KAAK,IAAIA,KAAK,CAACC,cAAc,CAAC,CAAE;IAC7CC,OAAO,EAAEZ;EAAW,CACvB,CACA,CAAC,eACNJ,KAAA,CAAAK,aAAA;IAAKC,SAAS,EAAE;EAAsB,gBAClCN,KAAA,CAAAK,aAAA,0BACIL,KAAA,CAAAK,aAAA,aACKH,QAAQ,CAACO,MAAM,KAAK,QAAQ,gBACzBT,KAAA,CAAAK,aAAA,eAAM,wBAA4B,CAAC,gBAEnCL,KAAA,CAAAK,aAAA,eAAM,2BAA+B,CAEzC,CAAC,EACJH,QAAQ,CAACe,GAAG,iBACTjB,KAAA,CAAAK,aAAA,0BACIL,KAAA,CAAAK,aAAA,eAAM,YACQ,eAAAL,KAAA,CAAAK,aAAA,eAAOH,QAAQ,CAACe,GAAU,CAClC,CACN,CAER,CACH,CACJ,CAAC;AAEd,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export * from "./FloatingLinkEditorPlugin";
@@ -0,0 +1,3 @@
1
+ export * from "./FloatingLinkEditorPlugin";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./FloatingLinkEditorPlugin\";\n"],"mappings":"AAAA","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare const isChildOfLinkEditor: (element: HTMLElement | null) => boolean;
@@ -0,0 +1,12 @@
1
+ export const isChildOfLinkEditor = element => {
2
+ const parent = element ? element.parentElement : null;
3
+ if (!parent) {
4
+ return false;
5
+ }
6
+ if (parent.classList.contains("link-editor")) {
7
+ return true;
8
+ }
9
+ return isChildOfLinkEditor(parent);
10
+ };
11
+
12
+ //# sourceMappingURL=isChildOfLinkEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isChildOfLinkEditor","element","parent","parentElement","classList","contains"],"sources":["isChildOfLinkEditor.ts"],"sourcesContent":["export const isChildOfLinkEditor = (element: HTMLElement | null): boolean => {\n const parent = element ? element.parentElement : null;\n\n if (!parent) {\n return false;\n }\n\n if (parent.classList.contains(\"link-editor\")) {\n return true;\n }\n\n return isChildOfLinkEditor(parent);\n};\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAIC,OAA2B,IAAc;EACzE,MAAMC,MAAM,GAAGD,OAAO,GAAGA,OAAO,CAACE,aAAa,GAAG,IAAI;EAErD,IAAI,CAACD,MAAM,EAAE;IACT,OAAO,KAAK;EAChB;EAEA,IAAIA,MAAM,CAACE,SAAS,CAACC,QAAQ,CAAC,aAAa,CAAC,EAAE;IAC1C,OAAO,IAAI;EACf;EAEA,OAAOL,mBAAmB,CAACE,MAAM,CAAC;AACtC,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare const FontColorPlugin: () => null;
@@ -0,0 +1,27 @@
1
+ import { useEffect } from "react";
2
+ import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_EDITOR } from "lexical";
3
+ import { ADD_FONT_COLOR_COMMAND } from "@webiny/lexical-nodes";
4
+ import { useRichTextEditor } from "../../hooks";
5
+ import { applyColorToSelection } from "./applyColorToSelection";
6
+ export const FontColorPlugin = () => {
7
+ const {
8
+ editor
9
+ } = useRichTextEditor();
10
+ useEffect(() => {
11
+ return editor.registerCommand(ADD_FONT_COLOR_COMMAND, payload => {
12
+ editor.update(() => {
13
+ const {
14
+ color
15
+ } = payload;
16
+ const selection = $getSelection();
17
+ if ($isRangeSelection(selection)) {
18
+ applyColorToSelection(selection, color);
19
+ }
20
+ });
21
+ return true;
22
+ }, COMMAND_PRIORITY_EDITOR);
23
+ }, [editor]);
24
+ return null;
25
+ };
26
+
27
+ //# sourceMappingURL=FontColorPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","$getSelection","$isRangeSelection","COMMAND_PRIORITY_EDITOR","ADD_FONT_COLOR_COMMAND","useRichTextEditor","applyColorToSelection","FontColorPlugin","editor","registerCommand","payload","update","color","selection"],"sources":["FontColorPlugin.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { $getSelection, $isRangeSelection, COMMAND_PRIORITY_EDITOR } from \"lexical\";\nimport type { FontColorPayload } from \"@webiny/lexical-nodes\";\nimport { ADD_FONT_COLOR_COMMAND } from \"@webiny/lexical-nodes\";\nimport { useRichTextEditor } from \"~/hooks\";\nimport { applyColorToSelection } from \"./applyColorToSelection\";\n\nexport const FontColorPlugin = () => {\n const { editor } = useRichTextEditor();\n\n useEffect(() => {\n return editor.registerCommand<FontColorPayload>(\n ADD_FONT_COLOR_COMMAND,\n payload => {\n editor.update(() => {\n const { color } = payload;\n const selection = $getSelection();\n\n if ($isRangeSelection(selection)) {\n applyColorToSelection(selection, color);\n }\n });\n return true;\n },\n COMMAND_PRIORITY_EDITOR\n );\n }, [editor]);\n\n return null;\n};\n"],"mappings":"AAAA,SAASA,SAAS,QAAQ,OAAO;AACjC,SAASC,aAAa,EAAEC,iBAAiB,EAAEC,uBAAuB,QAAQ,SAAS;AAEnF,SAASC,sBAAsB,QAAQ,uBAAuB;AAC9D,SAASC,iBAAiB;AAC1B,SAASC,qBAAqB;AAE9B,OAAO,MAAMC,eAAe,GAAGA,CAAA,KAAM;EACjC,MAAM;IAAEC;EAAO,CAAC,GAAGH,iBAAiB,CAAC,CAAC;EAEtCL,SAAS,CAAC,MAAM;IACZ,OAAOQ,MAAM,CAACC,eAAe,CACzBL,sBAAsB,EACtBM,OAAO,IAAI;MACPF,MAAM,CAACG,MAAM,CAAC,MAAM;QAChB,MAAM;UAAEC;QAAM,CAAC,GAAGF,OAAO;QACzB,MAAMG,SAAS,GAAGZ,aAAa,CAAC,CAAC;QAEjC,IAAIC,iBAAiB,CAACW,SAAS,CAAC,EAAE;UAC9BP,qBAAqB,CAACO,SAAS,EAAED,KAAK,CAAC;QAC3C;MACJ,CAAC,CAAC;MACF,OAAO,IAAI;IACf,CAAC,EACDT,uBACJ,CAAC;EACL,CAAC,EAAE,CAACK,MAAM,CAAC,CAAC;EAEZ,OAAO,IAAI;AACf,CAAC","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ import type { TextNode } from "lexical";
2
+ import type { ThemeColorValue } from "@webiny/lexical-nodes";
3
+ export declare function applyColorToNode(textNode: TextNode, color: ThemeColorValue): import("@webiny/lexical-nodes").FontColorNode;
@@ -0,0 +1,8 @@
1
+ import { $applyStylesToNode, $createFontColorNode } from "@webiny/lexical-nodes";
2
+ export function applyColorToNode(textNode, color) {
3
+ const fontColorNode = $createFontColorNode(textNode.getTextContent(), color);
4
+ $applyStylesToNode(fontColorNode, textNode);
5
+ return textNode.replace(fontColorNode);
6
+ }
7
+
8
+ //# sourceMappingURL=applyColorToNode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["$applyStylesToNode","$createFontColorNode","applyColorToNode","textNode","color","fontColorNode","getTextContent","replace"],"sources":["applyColorToNode.ts"],"sourcesContent":["import type { TextNode } from \"lexical\";\nimport type { ThemeColorValue } from \"@webiny/lexical-nodes\";\nimport { $applyStylesToNode, $createFontColorNode } from \"@webiny/lexical-nodes\";\n\nexport function applyColorToNode(textNode: TextNode, color: ThemeColorValue) {\n const fontColorNode = $createFontColorNode(textNode.getTextContent(), color);\n $applyStylesToNode(fontColorNode, textNode);\n\n return textNode.replace(fontColorNode);\n}\n"],"mappings":"AAEA,SAASA,kBAAkB,EAAEC,oBAAoB,QAAQ,uBAAuB;AAEhF,OAAO,SAASC,gBAAgBA,CAACC,QAAkB,EAAEC,KAAsB,EAAE;EACzE,MAAMC,aAAa,GAAGJ,oBAAoB,CAACE,QAAQ,CAACG,cAAc,CAAC,CAAC,EAAEF,KAAK,CAAC;EAC5EJ,kBAAkB,CAACK,aAAa,EAAEF,QAAQ,CAAC;EAE3C,OAAOA,QAAQ,CAACI,OAAO,CAACF,aAAa,CAAC;AAC1C","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ import type { RangeSelection } from "lexical";
2
+ import type { ThemeColorValue } from "@webiny/lexical-nodes";
3
+ export declare function applyColorToSelection(selection: RangeSelection, color: ThemeColorValue): void;
@@ -0,0 +1,66 @@
1
+ import { TextNode } from "lexical";
2
+ import { applyColorToNode } from "./applyColorToNode";
3
+ export function applyColorToSelection(selection, color) {
4
+ // Basic variables
5
+ const textNodes = selection.getNodes().filter(node => node instanceof TextNode);
6
+ const selectedTextNodesLength = textNodes.length;
7
+ const startEndPoints = selection.getStartEndPoints();
8
+ if (startEndPoints === null) {
9
+ return;
10
+ }
11
+ const [anchor, focus] = startEndPoints;
12
+ const lastIndex = selectedTextNodesLength - 1;
13
+ const firstNode = textNodes[0];
14
+ const lastNode = textNodes[lastIndex];
15
+ const firstNodeText = firstNode.getTextContent();
16
+ const firstNodeTextLength = firstNodeText.length;
17
+ const focusOffset = focus.offset;
18
+ const anchorOffset = anchor.offset;
19
+ const isBefore = anchor.isBefore(focus);
20
+ const startOffset = isBefore ? anchorOffset : focusOffset;
21
+ const endOffset = isBefore ? focusOffset : anchorOffset;
22
+
23
+ // No actual text is selected, so do nothing.
24
+ if (startOffset === endOffset) {
25
+ return;
26
+ }
27
+
28
+ // Only one node is selected.
29
+ if (selectedTextNodesLength === 1) {
30
+ // The entire node is selected.
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;
59
+ }
60
+
61
+ // Colorize the whole node.
62
+ applyColorToNode(textNode, color);
63
+ });
64
+ }
65
+
66
+ //# sourceMappingURL=applyColorToSelection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TextNode","applyColorToNode","applyColorToSelection","selection","color","textNodes","getNodes","filter","node","selectedTextNodesLength","length","startEndPoints","getStartEndPoints","anchor","focus","lastIndex","firstNode","lastNode","firstNodeText","getTextContent","firstNodeTextLength","focusOffset","offset","anchorOffset","isBefore","startOffset","endOffset","fontColorNode","select","splitNodes","splitText","replacement","forEach","textNode","toColor"],"sources":["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\";\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"],"mappings":"AACA,SAASA,QAAQ,QAAQ,SAAS;AAElC,SAASC,gBAAgB;AAEzB,OAAO,SAASC,qBAAqBA,CAACC,SAAyB,EAAEC,KAAsB,EAAE;EACrF;EACA,MAAMC,SAAS,GAAGF,SAAS,CAACG,QAAQ,CAAC,CAAC,CAACC,MAAM,CAACC,IAAI,IAAIA,IAAI,YAAYR,QAAQ,CAAe;EAE7F,MAAMS,uBAAuB,GAAGJ,SAAS,CAACK,MAAM;EAChD,MAAMC,cAAc,GAAGR,SAAS,CAACS,iBAAiB,CAAC,CAAC;EAEpD,IAAID,cAAc,KAAK,IAAI,EAAE;IACzB;EACJ;EAEA,MAAM,CAACE,MAAM,EAAEC,KAAK,CAAC,GAAGH,cAAc;EAEtC,MAAMI,SAAS,GAAGN,uBAAuB,GAAG,CAAC;EAC7C,MAAMO,SAAS,GAAGX,SAAS,CAAC,CAAC,CAAC;EAC9B,MAAMY,QAAQ,GAAGZ,SAAS,CAACU,SAAS,CAAC;EACrC,MAAMG,aAAa,GAAGF,SAAS,CAACG,cAAc,CAAC,CAAC;EAChD,MAAMC,mBAAmB,GAAGF,aAAa,CAACR,MAAM;EAChD,MAAMW,WAAW,GAAGP,KAAK,CAACQ,MAAM;EAChC,MAAMC,YAAY,GAAGV,MAAM,CAACS,MAAM;EAClC,MAAME,QAAQ,GAAGX,MAAM,CAACW,QAAQ,CAACV,KAAK,CAAC;EACvC,MAAMW,WAAW,GAAGD,QAAQ,GAAGD,YAAY,GAAGF,WAAW;EACzD,MAAMK,SAAS,GAAGF,QAAQ,GAAGH,WAAW,GAAGE,YAAY;;EAEvD;EACA,IAAIE,WAAW,KAAKC,SAAS,EAAE;IAC3B;EACJ;;EAEA;EACA,IAAIjB,uBAAuB,KAAK,CAAC,EAAE;IAC/B;IACA,IAAIgB,WAAW,KAAK,CAAC,IAAIC,SAAS,KAAKN,mBAAmB,EAAE;MACxD,MAAMO,aAAa,GAAG1B,gBAAgB,CAACe,SAAS,EAAEZ,KAAK,CAAC;MACxDuB,aAAa,CAACC,MAAM,CAACH,WAAW,EAAEC,SAAS,CAAC;MAC5C;IACJ;;IAEA;IACA,MAAMG,UAAU,GAAGb,SAAS,CAACc,SAAS,CAACL,WAAW,EAAEC,SAAS,CAAC;IAC9D,MAAMK,WAAW,GAAGN,WAAW,KAAK,CAAC,GAAGI,UAAU,CAAC,CAAC,CAAC,GAAGA,UAAU,CAAC,CAAC,CAAC;IACrE,MAAMF,aAAa,GAAG1B,gBAAgB,CAAC8B,WAAW,EAAE3B,KAAK,CAAC;IAC1DuB,aAAa,CAACC,MAAM,CAAC,CAAC,EAAEF,SAAS,GAAGD,WAAW,CAAC;IAEhD;EACJ;;EAEA;EACApB,SAAS,CAAC2B,OAAO,CAACC,QAAQ,IAAI;IAC1B;IACA,IAAIA,QAAQ,KAAKjB,SAAS,IAAIS,WAAW,GAAG,CAAC,EAAE;MAC3C,MAAM,GAAGS,OAAO,CAAC,GAAGD,QAAQ,CAACH,SAAS,CAACL,WAAW,CAAC;MACnDxB,gBAAgB,CAACiC,OAAO,EAAE9B,KAAK,CAAC;MAEhC;IACJ;;IAEA;IACA,IAAI6B,QAAQ,KAAKhB,QAAQ,IAAIA,QAAQ,CAACE,cAAc,CAAC,CAAC,CAACT,MAAM,KAAKgB,SAAS,EAAE;MACzE,MAAM,CAACQ,OAAO,CAAC,GAAGD,QAAQ,CAACH,SAAS,CAACJ,SAAS,CAAC;MAC/CzB,gBAAgB,CAACiC,OAAO,EAAE9B,KAAK,CAAC;MAChC;IACJ;;IAEA;IACAH,gBAAgB,CAACgC,QAAQ,EAAE7B,KAAK,CAAC;EACrC,CAAC,CAAC;AACN","ignoreList":[]}
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ import type { ImagePayload } from "../../commands";
3
+ export type InsertImagePayload = Readonly<ImagePayload>;
4
+ export declare function ImagesPlugin({ captionsEnabled }: {
5
+ captionsEnabled?: boolean;
6
+ }): JSX.Element | null;
7
+ declare global {
8
+ interface DragEvent {
9
+ rangeOffset?: number;
10
+ rangeParent?: Node;
11
+ }
12
+ }
@@ -0,0 +1,151 @@
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
+ import { useEffect } from "react";
11
+ import { mergeRegister } from "@lexical/utils";
12
+ import { $createRangeSelection, $getSelection, $isNodeSelection, $setSelection, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND } from "lexical";
13
+ import { $isImageNode, ImageNode } from "@webiny/lexical-nodes";
14
+ import { INSERT_IMAGE_COMMAND } from "../../commands";
15
+ import { CAN_USE_DOM } from "../../utils/canUseDOM";
16
+ import { insertImage } from "../../utils/insertImage";
17
+ import { useRichTextEditor } from "../../hooks";
18
+ const getDOMSelection = targetWindow => CAN_USE_DOM ? (targetWindow || window).getSelection() : null;
19
+ export function ImagesPlugin({
20
+ captionsEnabled
21
+ }) {
22
+ const {
23
+ editor
24
+ } = useRichTextEditor();
25
+ useEffect(() => {
26
+ if (!editor.hasNodes([ImageNode])) {
27
+ throw new Error("ImagesPlugin: ImageNode not registered in the editor!");
28
+ }
29
+ return mergeRegister(editor.registerCommand(INSERT_IMAGE_COMMAND, payload => insertImage(payload), COMMAND_PRIORITY_EDITOR), editor.registerCommand(DRAGSTART_COMMAND, event => {
30
+ return onDragStart(event);
31
+ }, COMMAND_PRIORITY_HIGH), editor.registerCommand(DRAGOVER_COMMAND, event => {
32
+ return onDragover(event);
33
+ }, COMMAND_PRIORITY_LOW), editor.registerCommand(DROP_COMMAND, event => {
34
+ return onDrop(event, editor);
35
+ }, COMMAND_PRIORITY_HIGH));
36
+ }, [captionsEnabled, editor]);
37
+ return null;
38
+ }
39
+ function getDragImage() {
40
+ if (!document) {
41
+ return undefined;
42
+ }
43
+ const TRANSPARENT_IMAGE = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
44
+ const img = document.createElement("img");
45
+ img.src = TRANSPARENT_IMAGE;
46
+ return img;
47
+ }
48
+ function onDragStart(event) {
49
+ const node = getImageNodeInSelection();
50
+ if (!node) {
51
+ return false;
52
+ }
53
+ const dataTransfer = event.dataTransfer;
54
+ const dragImage = getDragImage();
55
+ if (!dataTransfer || !dragImage) {
56
+ return false;
57
+ }
58
+ dataTransfer.setData("text/plain", "_");
59
+ dataTransfer.setDragImage(dragImage, 0, 0);
60
+ dataTransfer.setData("application/x-lexical-drag", JSON.stringify({
61
+ data: {
62
+ id: node.__id,
63
+ altText: node.__altText,
64
+ caption: node.__caption,
65
+ height: node.__height,
66
+ key: node.getKey(),
67
+ maxWidth: node.__maxWidth,
68
+ showCaption: node.__showCaption,
69
+ src: node.__src,
70
+ width: node.__width
71
+ },
72
+ type: "image"
73
+ }));
74
+ return true;
75
+ }
76
+ function onDragover(event) {
77
+ const node = getImageNodeInSelection();
78
+ if (!node) {
79
+ return false;
80
+ }
81
+ if (!canDropImage(event)) {
82
+ event.preventDefault();
83
+ }
84
+ return true;
85
+ }
86
+ function onDrop(event, editor) {
87
+ const node = getImageNodeInSelection();
88
+ if (!node) {
89
+ return false;
90
+ }
91
+ const data = getDragImageData(event);
92
+ if (!data) {
93
+ return false;
94
+ }
95
+ event.preventDefault();
96
+ if (canDropImage(event)) {
97
+ const range = getDragSelection(event);
98
+ node.remove();
99
+ const rangeSelection = $createRangeSelection();
100
+ if (range !== null && range !== undefined) {
101
+ rangeSelection.applyDOMRange(range);
102
+ }
103
+ $setSelection(rangeSelection);
104
+ editor.dispatchCommand(INSERT_IMAGE_COMMAND, data);
105
+ }
106
+ return true;
107
+ }
108
+ function getImageNodeInSelection() {
109
+ const selection = $getSelection();
110
+ if (!$isNodeSelection(selection)) {
111
+ return null;
112
+ }
113
+ const nodes = selection.getNodes();
114
+ const node = nodes[0];
115
+ return $isImageNode(node) ? node : null;
116
+ }
117
+ function getDragImageData(event) {
118
+ const dragData = event.dataTransfer?.getData("application/x-lexical-drag");
119
+ if (!dragData) {
120
+ return null;
121
+ }
122
+ const {
123
+ type,
124
+ data
125
+ } = JSON.parse(dragData);
126
+ if (type !== "image") {
127
+ return null;
128
+ }
129
+ return data;
130
+ }
131
+ function canDropImage(event) {
132
+ const target = event.target;
133
+ return !!(target && target instanceof HTMLElement && !target.closest("code, span.editor-image") && target.parentElement && target.parentElement.closest("div.ContentEditable__root"));
134
+ }
135
+ function getDragSelection(event) {
136
+ let range;
137
+ const target = event.target;
138
+ const targetWindow = target == null ? null : target.nodeType === 9 ? target.defaultView : target.ownerDocument.defaultView;
139
+ const domSelection = getDOMSelection(targetWindow);
140
+ if (document.caretRangeFromPoint) {
141
+ range = document.caretRangeFromPoint(event.clientX, event.clientY);
142
+ } else if (event.rangeParent && domSelection !== null) {
143
+ domSelection.collapse(event.rangeParent, event.rangeOffset || 0);
144
+ range = domSelection.getRangeAt(0);
145
+ } else {
146
+ throw Error(`Cannot get the selection when dragging`);
147
+ }
148
+ return range;
149
+ }
150
+
151
+ //# sourceMappingURL=ImagesPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","mergeRegister","$createRangeSelection","$getSelection","$isNodeSelection","$setSelection","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","caption","__caption","height","__height","key","getKey","maxWidth","__maxWidth","showCaption","__showCaption","__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 { mergeRegister } from \"@lexical/utils\";\nimport type { LexicalEditor } from \"lexical\";\nimport {\n $createRangeSelection,\n $getSelection,\n $isNodeSelection,\n $setSelection,\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\";\nimport { INSERT_IMAGE_COMMAND } from \"~/commands\";\nimport { CAN_USE_DOM } from \"~/utils/canUseDOM\";\nimport { insertImage } from \"~/utils/insertImage\";\nimport { useRichTextEditor } from \"~/hooks\";\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}): 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 caption: node.__caption,\n height: node.__height,\n key: node.getKey(),\n maxWidth: node.__maxWidth,\n showCaption: node.__showCaption,\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":[]}
@@ -0,0 +1,5 @@
1
+ type Props = {
2
+ validateUrl?: (url: string) => boolean;
3
+ };
4
+ export declare function LinkPlugin({ validateUrl }: Props): null;
5
+ export {};
@@ -0,0 +1,59 @@
1
+ import { useEffect } from "react";
2
+ import { mergeRegister } from "@lexical/utils";
3
+ import { $getSelection, $isElementNode, $isRangeSelection, COMMAND_PRIORITY_LOW, PASTE_COMMAND } from "lexical";
4
+ import { LinkNode, TOGGLE_LINK_COMMAND, toggleLink } from "@webiny/lexical-nodes";
5
+ import { useRichTextEditor } from "../../hooks";
6
+ export function LinkPlugin({
7
+ validateUrl
8
+ }) {
9
+ const {
10
+ editor
11
+ } = useRichTextEditor();
12
+ useEffect(() => {
13
+ if (!editor.hasNodes([LinkNode])) {
14
+ throw new Error("LinkPlugin: LinkNode not registered in the editor!");
15
+ }
16
+ const commands = [editor.registerCommand(TOGGLE_LINK_COMMAND, payload => {
17
+ if (payload === null) {
18
+ toggleLink(payload);
19
+ return true;
20
+ } else if (typeof payload === "string") {
21
+ if (validateUrl === undefined || validateUrl(payload)) {
22
+ toggleLink(payload);
23
+ return true;
24
+ }
25
+ return false;
26
+ } else {
27
+ const {
28
+ url,
29
+ ...attrs
30
+ } = payload;
31
+ toggleLink(url, attrs);
32
+ return true;
33
+ }
34
+ }, COMMAND_PRIORITY_LOW)];
35
+ if (validateUrl !== undefined) {
36
+ commands.push(editor.registerCommand(PASTE_COMMAND, event => {
37
+ const selection = $getSelection();
38
+ if (!$isRangeSelection(selection) || selection.isCollapsed() || !(event instanceof ClipboardEvent) || event.clipboardData == null) {
39
+ return false;
40
+ }
41
+ const clipboardText = event.clipboardData.getData("text");
42
+ if (!validateUrl(clipboardText)) {
43
+ return false;
44
+ }
45
+ // If we select nodes that are elements then avoid applying the link.
46
+ if (!selection.getNodes().some(node => $isElementNode(node))) {
47
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND, clipboardText);
48
+ event.preventDefault();
49
+ return true;
50
+ }
51
+ return false;
52
+ }, COMMAND_PRIORITY_LOW));
53
+ }
54
+ return mergeRegister(...commands);
55
+ }, [editor, validateUrl]);
56
+ return null;
57
+ }
58
+
59
+ //# sourceMappingURL=LinkPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","mergeRegister","$getSelection","$isElementNode","$isRangeSelection","COMMAND_PRIORITY_LOW","PASTE_COMMAND","LinkNode","TOGGLE_LINK_COMMAND","toggleLink","useRichTextEditor","LinkPlugin","validateUrl","editor","hasNodes","Error","commands","registerCommand","payload","undefined","url","attrs","push","event","selection","isCollapsed","ClipboardEvent","clipboardData","clipboardText","getData","getNodes","some","node","dispatchCommand","preventDefault"],"sources":["LinkPlugin.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { mergeRegister } from \"@lexical/utils\";\nimport {\n $getSelection,\n $isElementNode,\n $isRangeSelection,\n COMMAND_PRIORITY_LOW,\n PASTE_COMMAND\n} from \"lexical\";\nimport { LinkNode, TOGGLE_LINK_COMMAND, toggleLink } from \"@webiny/lexical-nodes\";\nimport { useRichTextEditor } from \"~/hooks\";\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"],"mappings":"AAAA,SAASA,SAAS,QAAQ,OAAO;AACjC,SAASC,aAAa,QAAQ,gBAAgB;AAC9C,SACIC,aAAa,EACbC,cAAc,EACdC,iBAAiB,EACjBC,oBAAoB,EACpBC,aAAa,QACV,SAAS;AAChB,SAASC,QAAQ,EAAEC,mBAAmB,EAAEC,UAAU,QAAQ,uBAAuB;AACjF,SAASC,iBAAiB;AAM1B,OAAO,SAASC,UAAUA,CAAC;EAAEC;AAAmB,CAAC,EAAQ;EACrD,MAAM;IAAEC;EAAO,CAAC,GAAGH,iBAAiB,CAAC,CAAC;EAEtCV,SAAS,CAAC,MAAM;IACZ,IAAI,CAACa,MAAM,CAACC,QAAQ,CAAC,CAACP,QAAQ,CAAC,CAAC,EAAE;MAC9B,MAAM,IAAIQ,KAAK,CAAC,oDAAoD,CAAC;IACzE;IAEA,MAAMC,QAAQ,GAAG,CACbH,MAAM,CAACI,eAAe,CAClBT,mBAAmB,EACnBU,OAAO,IAAI;MACP,IAAIA,OAAO,KAAK,IAAI,EAAE;QAClBT,UAAU,CAACS,OAAO,CAAC;QACnB,OAAO,IAAI;MACf,CAAC,MAAM,IAAI,OAAOA,OAAO,KAAK,QAAQ,EAAE;QACpC,IAAIN,WAAW,KAAKO,SAAS,IAAIP,WAAW,CAACM,OAAO,CAAC,EAAE;UACnDT,UAAU,CAACS,OAAO,CAAC;UACnB,OAAO,IAAI;QACf;QACA,OAAO,KAAK;MAChB,CAAC,MAAM;QACH,MAAM;UAAEE,GAAG;UAAE,GAAGC;QAAM,CAAC,GAAGH,OAAO;QACjCT,UAAU,CAACW,GAAG,EAAEC,KAAK,CAAC;QACtB,OAAO,IAAI;MACf;IACJ,CAAC,EACDhB,oBACJ,CAAC,CACJ;IAED,IAAIO,WAAW,KAAKO,SAAS,EAAE;MAC3BH,QAAQ,CAACM,IAAI,CACTT,MAAM,CAACI,eAAe,CAClBX,aAAa,EACbiB,KAAK,IAAI;QACL,MAAMC,SAAS,GAAGtB,aAAa,CAAC,CAAC;QACjC,IACI,CAACE,iBAAiB,CAACoB,SAAS,CAAC,IAC7BA,SAAS,CAACC,WAAW,CAAC,CAAC,IACvB,EAAEF,KAAK,YAAYG,cAAc,CAAC,IAClCH,KAAK,CAACI,aAAa,IAAI,IAAI,EAC7B;UACE,OAAO,KAAK;QAChB;QACA,MAAMC,aAAa,GAAGL,KAAK,CAACI,aAAa,CAACE,OAAO,CAAC,MAAM,CAAC;QACzD,IAAI,CAACjB,WAAW,CAACgB,aAAa,CAAC,EAAE;UAC7B,OAAO,KAAK;QAChB;QACA;QACA,IAAI,CAACJ,SAAS,CAACM,QAAQ,CAAC,CAAC,CAACC,IAAI,CAACC,IAAI,IAAI7B,cAAc,CAAC6B,IAAI,CAAC,CAAC,EAAE;UAC1DnB,MAAM,CAACoB,eAAe,CAACzB,mBAAmB,EAAEoB,aAAa,CAAC;UAC1DL,KAAK,CAACW,cAAc,CAAC,CAAC;UACtB,OAAO,IAAI;QACf;QACA,OAAO,KAAK;MAChB,CAAC,EACD7B,oBACJ,CACJ,CAAC;IACL;IAEA,OAAOJ,aAAa,CAAC,GAAGe,QAAQ,CAAC;EACrC,CAAC,EAAE,CAACH,MAAM,EAAED,WAAW,CAAC,CAAC;EAEzB,OAAO,IAAI;AACf","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare function ListPlugin(): null;