@squiz/formatted-text-editor 1.12.0-alpha.8 → 1.12.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/.eslintrc.json +34 -0
  2. package/CHANGELOG.md +48 -0
  3. package/README.md +2 -3
  4. package/build.js +21 -0
  5. package/cypress/e2e/bold.spec.cy.ts +18 -0
  6. package/cypress/global.d.ts +9 -0
  7. package/cypress/support/commands.ts +130 -0
  8. package/cypress/support/e2e.ts +20 -0
  9. package/cypress/tsconfig.json +8 -0
  10. package/cypress.config.ts +7 -0
  11. package/demo/App.tsx +39 -0
  12. package/demo/index.html +13 -0
  13. package/demo/index.scss +40 -0
  14. package/demo/main.tsx +10 -0
  15. package/demo/public/favicon-dxp.svg +3 -0
  16. package/demo/vite-env.d.ts +1 -0
  17. package/file-transformer.js +1 -0
  18. package/jest.bootstrap.ts +3 -0
  19. package/jest.config.ts +30 -0
  20. package/lib/Editor/Editor.d.ts +4 -2
  21. package/lib/Editor/Editor.js +11 -14
  22. package/lib/EditorToolbar/FloatingToolbar.d.ts +1 -0
  23. package/lib/EditorToolbar/FloatingToolbar.js +31 -0
  24. package/lib/EditorToolbar/Toolbar.d.ts +1 -0
  25. package/lib/EditorToolbar/Toolbar.js +25 -0
  26. package/lib/EditorToolbar/Tools/Link/Form/LinkForm.d.ts +10 -0
  27. package/lib/EditorToolbar/Tools/Link/Form/LinkForm.js +23 -0
  28. package/lib/EditorToolbar/Tools/Link/LinkButton.d.ts +5 -0
  29. package/lib/EditorToolbar/Tools/Link/LinkButton.js +34 -0
  30. package/lib/EditorToolbar/Tools/Link/LinkModal.d.ts +8 -0
  31. package/lib/EditorToolbar/Tools/Link/LinkModal.js +14 -0
  32. package/lib/EditorToolbar/Tools/Link/RemoveLinkButton.d.ts +2 -0
  33. package/lib/EditorToolbar/Tools/Link/RemoveLinkButton.js +16 -0
  34. package/lib/EditorToolbar/Tools/Redo/RedoButton.d.ts +2 -0
  35. package/lib/EditorToolbar/Tools/Redo/RedoButton.js +16 -0
  36. package/lib/EditorToolbar/Tools/TextAlign/TextAlignButtons.js +4 -1
  37. package/lib/EditorToolbar/Tools/TextType/Heading/HeadingButton.d.ts +5 -0
  38. package/lib/EditorToolbar/Tools/TextType/Heading/HeadingButton.js +32 -0
  39. package/lib/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.d.ts +2 -0
  40. package/lib/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.js +16 -0
  41. package/lib/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.d.ts +2 -0
  42. package/lib/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.js +16 -0
  43. package/lib/EditorToolbar/Tools/TextType/TextTypeDropdown.d.ts +2 -0
  44. package/lib/EditorToolbar/Tools/TextType/TextTypeDropdown.js +35 -0
  45. package/lib/EditorToolbar/Tools/Undo/UndoButton.d.ts +2 -0
  46. package/lib/EditorToolbar/Tools/Undo/UndoButton.js +16 -0
  47. package/lib/EditorToolbar/index.d.ts +2 -0
  48. package/lib/EditorToolbar/index.js +2 -0
  49. package/lib/Extensions/Extensions.d.ts +4 -0
  50. package/lib/Extensions/Extensions.js +20 -0
  51. package/lib/Extensions/LinkExtension/LinkExtension.d.ts +16 -0
  52. package/lib/Extensions/LinkExtension/LinkExtension.js +91 -0
  53. package/lib/Extensions/PreformattedExtension/PreformattedExtension.d.ts +10 -0
  54. package/lib/Extensions/PreformattedExtension/PreformattedExtension.js +46 -0
  55. package/lib/FormattedTextEditor.d.ts +2 -2
  56. package/lib/FormattedTextEditor.js +1 -6
  57. package/lib/hooks/index.d.ts +1 -0
  58. package/lib/hooks/index.js +1 -0
  59. package/lib/hooks/useExtensionNames.d.ts +1 -0
  60. package/lib/hooks/useExtensionNames.js +12 -0
  61. package/lib/index.css +787 -3686
  62. package/lib/ui/Inputs/Select/Select.d.ts +12 -0
  63. package/lib/ui/Inputs/Select/Select.js +23 -0
  64. package/lib/ui/Inputs/Text/TextInput.d.ts +4 -0
  65. package/lib/ui/Inputs/Text/TextInput.js +7 -0
  66. package/lib/ui/Modal/FormModal.d.ts +5 -0
  67. package/lib/ui/Modal/FormModal.js +11 -0
  68. package/lib/ui/Modal/Modal.d.ts +10 -0
  69. package/lib/ui/Modal/Modal.js +48 -0
  70. package/lib/ui/ToolbarButton/ToolbarButton.d.ts +1 -1
  71. package/lib/ui/ToolbarButton/ToolbarButton.js +1 -1
  72. package/lib/ui/ToolbarDropdown/ToolbarDropdown.d.ts +6 -0
  73. package/lib/ui/ToolbarDropdown/ToolbarDropdown.js +20 -0
  74. package/lib/ui/ToolbarDropdownButton/ToolbarDropdownButton.d.ts +9 -0
  75. package/lib/ui/ToolbarDropdownButton/ToolbarDropdownButton.js +8 -0
  76. package/lib/utils/createToolbarPositioner.d.ts +18 -0
  77. package/lib/utils/createToolbarPositioner.js +81 -0
  78. package/lib/utils/getCursorRect.d.ts +2 -0
  79. package/lib/utils/getCursorRect.js +3 -0
  80. package/package.json +22 -13
  81. package/postcss.config.js +12 -0
  82. package/src/Editor/Editor.mock.tsx +43 -0
  83. package/src/Editor/Editor.spec.tsx +254 -0
  84. package/src/Editor/Editor.tsx +46 -0
  85. package/src/Editor/_editor.scss +82 -0
  86. package/src/EditorToolbar/FloatingToolbar.spec.tsx +30 -0
  87. package/src/EditorToolbar/FloatingToolbar.tsx +40 -0
  88. package/src/EditorToolbar/Toolbar.tsx +33 -0
  89. package/src/EditorToolbar/Tools/Bold/BoldButton.spec.tsx +19 -0
  90. package/src/EditorToolbar/Tools/Bold/BoldButton.tsx +30 -0
  91. package/src/EditorToolbar/Tools/Italic/ItalicButton.spec.tsx +19 -0
  92. package/src/EditorToolbar/Tools/Italic/ItalicButton.tsx +30 -0
  93. package/src/EditorToolbar/Tools/Link/Form/LinkForm.spec.tsx +30 -0
  94. package/src/EditorToolbar/Tools/Link/Form/LinkForm.tsx +48 -0
  95. package/src/EditorToolbar/Tools/Link/LinkButton.spec.tsx +277 -0
  96. package/src/EditorToolbar/Tools/Link/LinkButton.tsx +56 -0
  97. package/src/EditorToolbar/Tools/Link/LinkModal.tsx +29 -0
  98. package/src/EditorToolbar/Tools/Link/RemoveLinkButton.spec.tsx +46 -0
  99. package/src/EditorToolbar/Tools/Link/RemoveLinkButton.tsx +27 -0
  100. package/src/EditorToolbar/Tools/Redo/RedoButton.spec.tsx +59 -0
  101. package/src/EditorToolbar/Tools/Redo/RedoButton.tsx +30 -0
  102. package/src/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.spec.tsx +39 -0
  103. package/src/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.tsx +31 -0
  104. package/src/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.spec.tsx +39 -0
  105. package/src/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.tsx +31 -0
  106. package/src/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.spec.tsx +39 -0
  107. package/src/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.tsx +31 -0
  108. package/src/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.spec.tsx +39 -0
  109. package/src/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.tsx +31 -0
  110. package/src/EditorToolbar/Tools/TextAlign/TextAlignButtons.tsx +21 -0
  111. package/src/EditorToolbar/Tools/TextType/Heading/HeadingButton.spec.tsx +56 -0
  112. package/src/EditorToolbar/Tools/TextType/Heading/HeadingButton.tsx +52 -0
  113. package/src/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.spec.tsx +30 -0
  114. package/src/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.tsx +25 -0
  115. package/src/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.spec.tsx +47 -0
  116. package/src/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.tsx +30 -0
  117. package/src/EditorToolbar/Tools/TextType/TextTypeDropdown.spec.tsx +51 -0
  118. package/src/EditorToolbar/Tools/TextType/TextTypeDropdown.tsx +44 -0
  119. package/src/EditorToolbar/Tools/Underline/Underline.spec.tsx +19 -0
  120. package/src/EditorToolbar/Tools/Underline/UnderlineButton.tsx +30 -0
  121. package/src/EditorToolbar/Tools/Undo/UndoButton.spec.tsx +49 -0
  122. package/src/EditorToolbar/Tools/Undo/UndoButton.tsx +30 -0
  123. package/src/EditorToolbar/_floating-toolbar.scss +4 -0
  124. package/src/EditorToolbar/_toolbar.scss +16 -0
  125. package/src/EditorToolbar/index.ts +2 -0
  126. package/src/Extensions/Extensions.ts +29 -0
  127. package/src/Extensions/LinkExtension/LinkExtension.ts +116 -0
  128. package/src/Extensions/PreformattedExtension/PreformattedExtension.ts +50 -0
  129. package/src/FormattedTextEditor.spec.tsx +10 -0
  130. package/src/FormattedTextEditor.tsx +3 -0
  131. package/src/hooks/index.ts +1 -0
  132. package/src/hooks/useExtensionNames.ts +15 -0
  133. package/src/index.scss +19 -0
  134. package/src/index.ts +3 -0
  135. package/src/ui/Inputs/Select/Select.spec.tsx +30 -0
  136. package/src/ui/Inputs/Select/Select.tsx +66 -0
  137. package/src/ui/Inputs/Text/TextInput.spec.tsx +43 -0
  138. package/src/ui/Inputs/Text/TextInput.tsx +20 -0
  139. package/src/ui/Modal/FormModal.spec.tsx +20 -0
  140. package/src/ui/Modal/FormModal.tsx +17 -0
  141. package/src/ui/Modal/Modal.spec.tsx +113 -0
  142. package/src/ui/Modal/Modal.tsx +97 -0
  143. package/src/ui/Modal/_modal.scss +24 -0
  144. package/src/ui/ToolbarButton/ToolbarButton.tsx +26 -0
  145. package/src/ui/ToolbarButton/_toolbar-button.scss +17 -0
  146. package/src/ui/ToolbarDropdown/ToolbarDropdown.spec.tsx +78 -0
  147. package/src/ui/ToolbarDropdown/ToolbarDropdown.tsx +42 -0
  148. package/src/ui/ToolbarDropdown/_toolbar-dropdown.scss +32 -0
  149. package/src/ui/ToolbarDropdownButton/ToolbarDropdownButton.spec.tsx +48 -0
  150. package/src/ui/ToolbarDropdownButton/ToolbarDropdownButton.tsx +29 -0
  151. package/src/ui/ToolbarDropdownButton/_toolbar-dropdown-button.scss +14 -0
  152. package/src/ui/_buttons.scss +19 -0
  153. package/src/ui/_forms.scss +16 -0
  154. package/src/utils/createToolbarPositioner.ts +115 -0
  155. package/src/utils/getCursorRect.ts +5 -0
  156. package/tailwind.config.cjs +83 -0
  157. package/tests/index.ts +2 -0
  158. package/tests/renderWithEditor.tsx +110 -0
  159. package/tests/select.tsx +16 -0
  160. package/tsconfig.json +22 -0
  161. package/vite.config.ts +19 -0
  162. package/lib/EditorToolbar/EditorToolbar.d.ts +0 -7
  163. package/lib/EditorToolbar/EditorToolbar.js +0 -22
@@ -0,0 +1,34 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import InsertLinkRoundedIcon from '@mui/icons-material/InsertLinkRounded';
3
+ import LinkModal from './LinkModal';
4
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
5
+ import { useActive, useCommands, useExtensionEvent } from '@remirror/react';
6
+ import { LinkExtension } from '../../../Extensions/LinkExtension/LinkExtension';
7
+ const LinkButton = ({ inPopover = false }) => {
8
+ const [showModal, setShowModal] = useState(false);
9
+ const { selectLink, updateLink } = useCommands();
10
+ const active = useActive();
11
+ const handleClick = () => {
12
+ if (!showModal) {
13
+ selectLink();
14
+ // form element are uncontrolled, let the event loop run to
15
+ // update the selected text in state before showing the modal.
16
+ requestAnimationFrame(() => {
17
+ setShowModal(true);
18
+ });
19
+ }
20
+ };
21
+ const handleSubmit = (data) => {
22
+ updateLink(data);
23
+ setShowModal(false);
24
+ };
25
+ if (!inPopover) {
26
+ // when Ctrl+K is pressed show the modal, only registered in the toolbar button instance to avoid the key press
27
+ // being double handled.
28
+ useExtensionEvent(LinkExtension, 'onShortcut', useCallback(() => handleClick(), []));
29
+ }
30
+ return (React.createElement(React.Fragment, null,
31
+ React.createElement(ToolbarButton, { handleOnClick: handleClick, isActive: active.link(), icon: React.createElement(InsertLinkRoundedIcon, null), label: "Link (cmd+K)" }),
32
+ showModal && React.createElement(LinkModal, { onCancel: () => setShowModal(false), onSubmit: handleSubmit })));
33
+ };
34
+ export default LinkButton;
@@ -0,0 +1,8 @@
1
+ import { LinkFormData } from './Form/LinkForm';
2
+ import { SubmitHandler } from 'react-hook-form';
3
+ type LinkModalProps = {
4
+ onCancel: () => void;
5
+ onSubmit: SubmitHandler<LinkFormData>;
6
+ };
7
+ declare const LinkModal: ({ onCancel, onSubmit }: LinkModalProps) => JSX.Element;
8
+ export default LinkModal;
@@ -0,0 +1,14 @@
1
+ import { getMarkRanges } from 'remirror';
2
+ import LinkForm from './Form/LinkForm';
3
+ import React from 'react';
4
+ import { useRemirrorContext, useCurrentSelection } from '@remirror/react';
5
+ import FormModal from '../../../ui/Modal/FormModal';
6
+ const LinkModal = ({ onCancel, onSubmit }) => {
7
+ const { helpers, view: { state }, } = useRemirrorContext();
8
+ const selection = useCurrentSelection();
9
+ const currentLink = getMarkRanges(selection, 'link')[0];
10
+ const selectedText = helpers.getTextBetween(selection.from, selection.to, state.doc);
11
+ return (React.createElement(FormModal, { title: "Link", onCancel: onCancel },
12
+ React.createElement(LinkForm, { data: { ...currentLink?.mark.attrs, text: selectedText }, onSubmit: onSubmit })));
13
+ };
14
+ export default LinkModal;
@@ -0,0 +1,2 @@
1
+ declare const RemoveLinkButton: () => JSX.Element;
2
+ export default RemoveLinkButton;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { useRemirrorContext, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
4
+ import LinkOffIcon from '@mui/icons-material/LinkOff';
5
+ const RemoveLinkButton = () => {
6
+ const { commands } = useRemirrorContext({ autoUpdate: true });
7
+ const chain = useChainedCommands();
8
+ const enabled = commands.removeLink.enabled();
9
+ const handleClick = () => {
10
+ if (enabled) {
11
+ chain.removeLink().focus().run();
12
+ }
13
+ };
14
+ return (React.createElement(ToolbarButton, { handleOnClick: handleClick, isActive: false, isDisabled: !enabled, icon: React.createElement(LinkOffIcon, null), label: "Remove link" }));
15
+ };
16
+ export default RemoveLinkButton;
@@ -0,0 +1,2 @@
1
+ declare const RedoButton: () => JSX.Element;
2
+ export default RedoButton;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { useCommands, useHelpers } from '@remirror/react';
3
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
4
+ import RedoRoundedIcon from '@mui/icons-material/RedoRounded';
5
+ const RedoButton = () => {
6
+ const { redo } = useCommands();
7
+ const { redoDepth } = useHelpers(true);
8
+ const handleSelect = () => {
9
+ if (redo.enabled()) {
10
+ redo();
11
+ }
12
+ };
13
+ const enabled = redoDepth() > 0;
14
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: false, icon: React.createElement(RedoRoundedIcon, null), label: "Redo (shift+cmd+Z)" }));
15
+ };
16
+ export default RedoButton;
@@ -3,11 +3,14 @@ import LeftAlignButton from './LeftAlign/LeftAlignButton';
3
3
  import CenterAlignButton from './CenterAlign/CenterAlignButton';
4
4
  import RightAlignButton from './RightAlign/RightAlignButton';
5
5
  import JustifyAlignButton from './JustifyAlign/JustifyAlignButton';
6
+ import { VerticalDivider } from '@remirror/react-components';
6
7
  const TextAlignButtons = () => {
7
8
  return (React.createElement(React.Fragment, null,
9
+ React.createElement(VerticalDivider, { className: "editor-divider" }),
8
10
  React.createElement(LeftAlignButton, null),
9
11
  React.createElement(CenterAlignButton, null),
10
12
  React.createElement(RightAlignButton, null),
11
- React.createElement(JustifyAlignButton, null)));
13
+ React.createElement(JustifyAlignButton, null),
14
+ React.createElement(VerticalDivider, { className: "editor-divider" })));
12
15
  };
13
16
  export default TextAlignButtons;
@@ -0,0 +1,5 @@
1
+ type HeadingButtonProps = {
2
+ level: number;
3
+ };
4
+ declare const HeadingButton: ({ level }: HeadingButtonProps) => JSX.Element;
5
+ export default HeadingButton;
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { useCommands, useChainedCommands, useActive } from '@remirror/react';
3
+ import DropdownButton from '../../../../ui/ToolbarDropdownButton/ToolbarDropdownButton';
4
+ const HeadingButton = ({ level }) => {
5
+ const { toggleHeading } = useCommands();
6
+ const chain = useChainedCommands();
7
+ const active = useActive();
8
+ const enabled = toggleHeading.enabled({ level });
9
+ const handleSelect = () => {
10
+ if (toggleHeading.enabled({ level })) {
11
+ chain.toggleHeading({ level }).focus().run();
12
+ }
13
+ };
14
+ const headingContent = () => {
15
+ switch (level) {
16
+ case 1:
17
+ return React.createElement("h1", null, "Heading 1");
18
+ case 2:
19
+ return React.createElement("h2", null, "Heading 2");
20
+ case 3:
21
+ return React.createElement("h3", null, "Heading 3");
22
+ case 4:
23
+ return React.createElement("h4", null, "Heading 4");
24
+ case 5:
25
+ return React.createElement("h5", null, "Heading 5");
26
+ case 6:
27
+ return React.createElement("h6", null, "Heading 6");
28
+ }
29
+ };
30
+ return (React.createElement(DropdownButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.heading({ level }), label: `Heading ${level}` }, headingContent()));
31
+ };
32
+ export default HeadingButton;
@@ -0,0 +1,2 @@
1
+ declare const ParagraphButton: () => JSX.Element;
2
+ export default ParagraphButton;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { useCommands, useChainedCommands, useActive } from '@remirror/react';
3
+ import DropdownButton from '../../../../ui/ToolbarDropdownButton/ToolbarDropdownButton';
4
+ const ParagraphButton = () => {
5
+ const { convertParagraph } = useCommands();
6
+ const chain = useChainedCommands();
7
+ const active = useActive();
8
+ const handleSelect = () => {
9
+ if (convertParagraph.enabled()) {
10
+ chain.convertParagraph().focus().run();
11
+ }
12
+ };
13
+ return (React.createElement(DropdownButton, { handleOnClick: handleSelect, isDisabled: false, isActive: active.paragraph(), label: "Paragraph" },
14
+ React.createElement("p", null, "Paragraph")));
15
+ };
16
+ export default ParagraphButton;
@@ -0,0 +1,2 @@
1
+ declare const PreformattedButton: () => JSX.Element;
2
+ export default PreformattedButton;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { useCommands, useActive } from '@remirror/react';
3
+ import DropdownButton from '../../../../ui/ToolbarDropdownButton/ToolbarDropdownButton';
4
+ const PreformattedButton = () => {
5
+ const { togglePreformatted } = useCommands();
6
+ const active = useActive();
7
+ const enabled = togglePreformatted.enabled();
8
+ const handleSelect = () => {
9
+ if (togglePreformatted.enabled()) {
10
+ togglePreformatted();
11
+ }
12
+ };
13
+ return (React.createElement(DropdownButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.preformatted(), label: "Preformatted" },
14
+ React.createElement("pre", null, "Preformatted")));
15
+ };
16
+ export default PreformattedButton;
@@ -0,0 +1,2 @@
1
+ declare const TextTypeDropdown: () => JSX.Element;
2
+ export default TextTypeDropdown;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import HeadingButton from './Heading/HeadingButton';
3
+ import ParagraphButton from './Paragraph/ParagraphButton';
4
+ import PreformattedButton from './Preformatted/PreformattedButton';
5
+ import ToolbarDropdown from '../../../ui/ToolbarDropdown/ToolbarDropdown';
6
+ import { useActive, VerticalDivider } from '@remirror/react';
7
+ const TextTypeDropdown = () => {
8
+ const active = useActive();
9
+ const activeLabel = () => {
10
+ // Determine if preformatted is active
11
+ if (active.preformatted()) {
12
+ return 'Preformatted';
13
+ }
14
+ // Determine if a heading is active
15
+ for (let i = 1; i <= 6; i++) {
16
+ if (active.heading({ level: i })) {
17
+ return `Heading ${i}`;
18
+ }
19
+ }
20
+ // Default to paragraph
21
+ return 'Paragraph';
22
+ };
23
+ return (React.createElement(React.Fragment, null,
24
+ React.createElement(ToolbarDropdown, { label: activeLabel() },
25
+ React.createElement(ParagraphButton, null),
26
+ React.createElement(HeadingButton, { level: 1 }),
27
+ React.createElement(HeadingButton, { level: 2 }),
28
+ React.createElement(HeadingButton, { level: 3 }),
29
+ React.createElement(HeadingButton, { level: 4 }),
30
+ React.createElement(HeadingButton, { level: 5 }),
31
+ React.createElement(HeadingButton, { level: 6 }),
32
+ React.createElement(PreformattedButton, null)),
33
+ React.createElement(VerticalDivider, { className: "editor-divider" })));
34
+ };
35
+ export default TextTypeDropdown;
@@ -0,0 +1,2 @@
1
+ declare const UndoButton: () => JSX.Element;
2
+ export default UndoButton;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { useCommands, useHelpers } from '@remirror/react';
3
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
4
+ import UndoRoundedIcon from '@mui/icons-material/UndoRounded';
5
+ const UndoButton = () => {
6
+ const { undo } = useCommands();
7
+ const { undoDepth } = useHelpers(true);
8
+ const handleSelect = () => {
9
+ if (undo.enabled()) {
10
+ undo();
11
+ }
12
+ };
13
+ const enabled = undoDepth() > 0;
14
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: false, icon: React.createElement(UndoRoundedIcon, null), label: "Undo (cmd+Z)" }));
15
+ };
16
+ export default UndoButton;
@@ -0,0 +1,2 @@
1
+ export * from './FloatingToolbar';
2
+ export * from './Toolbar';
@@ -0,0 +1,2 @@
1
+ export * from './FloatingToolbar';
2
+ export * from './Toolbar';
@@ -0,0 +1,4 @@
1
+ import { BoldExtension, HeadingExtension, ItalicExtension, NodeFormattingExtension, ParagraphExtension, UnderlineExtension, HistoryExtension } from 'remirror/extensions';
2
+ import { PreformattedExtension } from './PreformattedExtension/PreformattedExtension';
3
+ import { LinkExtension } from './LinkExtension/LinkExtension';
4
+ export declare const Extensions: () => (BoldExtension | HistoryExtension | HeadingExtension | ItalicExtension | NodeFormattingExtension | ParagraphExtension | UnderlineExtension | LinkExtension | PreformattedExtension)[];
@@ -0,0 +1,20 @@
1
+ import { BoldExtension, HeadingExtension, ItalicExtension, NodeFormattingExtension, ParagraphExtension, UnderlineExtension, HistoryExtension, } from 'remirror/extensions';
2
+ import { PreformattedExtension } from './PreformattedExtension/PreformattedExtension';
3
+ import { LinkExtension } from './LinkExtension/LinkExtension';
4
+ export const Extensions = () => [
5
+ new BoldExtension(),
6
+ new HeadingExtension(),
7
+ new ItalicExtension(),
8
+ new NodeFormattingExtension(),
9
+ new ParagraphExtension(),
10
+ new PreformattedExtension(),
11
+ new UnderlineExtension(),
12
+ new HistoryExtension(),
13
+ new LinkExtension({
14
+ supportedTargets: [
15
+ // '_self' is the browser default and will be used when encountering a link with a
16
+ // different target is encountered.
17
+ '_blank',
18
+ ],
19
+ }),
20
+ ];
@@ -0,0 +1,16 @@
1
+ import { ApplySchemaAttributes, MarkExtensionSpec, MarkSpecOverride } from 'remirror';
2
+ import { KeyBindingProps } from '@remirror/core';
3
+ import { CommandFunction } from '@remirror/pm';
4
+ import { LinkAttributes as RemirrorLinkAttributes, LinkExtension as RemirrorLinkExtension } from 'remirror/extensions';
5
+ export type UpdateLinkOptions = LinkAttributes & {
6
+ text: string;
7
+ };
8
+ export type LinkAttributes = RemirrorLinkAttributes & {
9
+ title?: string;
10
+ };
11
+ export declare class LinkExtension extends RemirrorLinkExtension {
12
+ createMarkSpec(extra: ApplySchemaAttributes, override: MarkSpecOverride): MarkExtensionSpec;
13
+ shortcut({ tr }: KeyBindingProps): boolean;
14
+ selectLink(): CommandFunction;
15
+ updateLink(options: UpdateLinkOptions): CommandFunction;
16
+ }
@@ -0,0 +1,91 @@
1
+ import { getMarkRanges, isElementDomNode } from 'remirror';
2
+ import { getTextSelection, getMarkRange, updateMark, removeMark } from '@remirror/core';
3
+ import { LinkExtension as RemirrorLinkExtension } from 'remirror/extensions';
4
+ export class LinkExtension extends RemirrorLinkExtension {
5
+ createMarkSpec(extra, override) {
6
+ const spec = super.createMarkSpec(extra, override);
7
+ return {
8
+ ...spec,
9
+ excludes: undefined,
10
+ attrs: {
11
+ ...spec.attrs,
12
+ title: { default: undefined },
13
+ },
14
+ parseDOM: [
15
+ {
16
+ tag: 'a[href]',
17
+ getAttrs: (node) => {
18
+ if (!isElementDomNode(node)) {
19
+ return false;
20
+ }
21
+ return {
22
+ ...extra.parse(node),
23
+ auto: false,
24
+ href: node.getAttribute('href'),
25
+ target: node.getAttribute('target'),
26
+ title: node.getAttribute('title'),
27
+ };
28
+ },
29
+ },
30
+ ],
31
+ };
32
+ }
33
+ shortcut({ tr }) {
34
+ // override parent implementation to allow a link to be inserted without requiring a text selection first.
35
+ const { from, to, $from } = tr.selection;
36
+ const mark = getMarkRange($from, this.type);
37
+ const selectedText = tr.doc.textBetween(from, to);
38
+ this.options.onShortcut({
39
+ activeLink: mark ? { attrs: mark.mark.attrs, from: mark.from, to: mark.to } : undefined,
40
+ selectedText,
41
+ from,
42
+ to,
43
+ });
44
+ return true;
45
+ }
46
+ selectLink() {
47
+ // parent implementation selects only the link text, this mimics closer to Google Docs where
48
+ // the select text is widened to include the link but retains non-link selected text as well.
49
+ return (props) => {
50
+ const { tr } = props;
51
+ const ranges = getMarkRanges(tr.selection, this.type);
52
+ if (ranges.length === 0) {
53
+ return false;
54
+ }
55
+ // work out the start position of the first link and end position of the last link in the selection.
56
+ const from = Math.min(tr.selection.from, ...ranges.map((range) => range.from));
57
+ const to = Math.max(tr.selection.to, ...ranges.map((range) => range.to));
58
+ // don't need to widen the selection, return early.
59
+ if (tr.selection.from === from && tr.selection.to === to) {
60
+ return false;
61
+ }
62
+ // widen the selection to make sure the full link is included.
63
+ this.store.commands.selectText.original({ from, to })(props);
64
+ return true;
65
+ };
66
+ }
67
+ updateLink(options) {
68
+ const { text, ...attrs } = options;
69
+ return (props) => {
70
+ const { tr, dispatch, view } = props;
71
+ const range = { from: tr.selection.from, to: tr.selection.to };
72
+ const selectedText = tr.doc.textBetween(range.from, range.to);
73
+ if (text !== selectedText) {
74
+ // update the text in the editor if it was updated, update the range to cover the length of the new text.
75
+ dispatch?.(tr.insertText(text));
76
+ range.to = range.from + text.length;
77
+ }
78
+ // apply the link, or remove it if no URL was provided.
79
+ if (attrs.href.length > 0) {
80
+ updateMark({ type: this.type, attrs, range })(props);
81
+ }
82
+ else {
83
+ removeMark({ type: this.type, range })(props);
84
+ }
85
+ // move the cursor to the end of the link and re-focus the editor.
86
+ dispatch?.(tr.setSelection(getTextSelection({ from: range.to, to: range.to }, tr.doc)));
87
+ view?.focus();
88
+ return true;
89
+ };
90
+ }
91
+ }
@@ -0,0 +1,10 @@
1
+ import { ApplySchemaAttributes, CommandFunction, NodeExtension, NodeExtensionSpec, NodeSpecOverride } from '@remirror/core';
2
+ export declare class PreformattedExtension extends NodeExtension {
3
+ get name(): "preformatted";
4
+ createTags(): ("formattingNode" | "block" | "textBlock")[];
5
+ createNodeSpec(extra: ApplySchemaAttributes, override: NodeSpecOverride): NodeExtensionSpec;
6
+ /**
7
+ * Toggle the <pre> for the current block.
8
+ */
9
+ togglePreformatted(): CommandFunction;
10
+ }
@@ -0,0 +1,46 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { command, extension, ExtensionTag, NodeExtension, toggleBlockItem, } from '@remirror/core';
8
+ let PreformattedExtension = class PreformattedExtension extends NodeExtension {
9
+ get name() {
10
+ return 'preformatted';
11
+ }
12
+ createTags() {
13
+ return [ExtensionTag.Block, ExtensionTag.TextBlock, ExtensionTag.FormattingNode];
14
+ }
15
+ createNodeSpec(extra, override) {
16
+ return {
17
+ content: 'inline*',
18
+ defining: true,
19
+ draggable: false,
20
+ ...override,
21
+ attrs: {
22
+ ...extra.defaults(),
23
+ },
24
+ parseDOM: [...(override.parseDOM ?? [])],
25
+ toDOM: (node) => {
26
+ return [`pre`, extra.dom(node), 0];
27
+ },
28
+ };
29
+ }
30
+ /**
31
+ * Toggle the <pre> for the current block.
32
+ */
33
+ togglePreformatted() {
34
+ return toggleBlockItem({
35
+ type: this.type,
36
+ toggleType: 'paragraph',
37
+ });
38
+ }
39
+ };
40
+ __decorate([
41
+ command()
42
+ ], PreformattedExtension.prototype, "togglePreformatted", null);
43
+ PreformattedExtension = __decorate([
44
+ extension({})
45
+ ], PreformattedExtension);
46
+ export { PreformattedExtension };
@@ -1,2 +1,2 @@
1
- declare const FormattedTextEditor: () => JSX.Element;
2
- export default FormattedTextEditor;
1
+ import Editor from './Editor/Editor';
2
+ export default Editor;
@@ -1,7 +1,2 @@
1
- import React from 'react';
2
1
  import Editor from './Editor/Editor';
3
- const FormattedTextEditor = () => {
4
- return (React.createElement("div", { className: "remirror-theme formatted-text-editor editor-wrapper" },
5
- React.createElement(Editor, null)));
6
- };
7
- export default FormattedTextEditor;
2
+ export default Editor;
@@ -0,0 +1 @@
1
+ export * from './useExtensionNames';
@@ -0,0 +1 @@
1
+ export * from './useExtensionNames';
@@ -0,0 +1 @@
1
+ export declare const useExtensionNames: () => Record<string, true>;
@@ -0,0 +1,12 @@
1
+ import { useRemirrorContext } from '@remirror/react';
2
+ import { useMemo } from 'react';
3
+ export const useExtensionNames = () => {
4
+ const { manager } = useRemirrorContext();
5
+ return useMemo(() => {
6
+ const extensionNames = {};
7
+ manager.extensions.forEach((extension) => {
8
+ extensionNames[extension.name] = true;
9
+ });
10
+ return extensionNames;
11
+ }, [manager]);
12
+ };