@squiz/formatted-text-editor 1.5.1-alpha.6 → 1.12.0-alpha.10

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 (47) hide show
  1. package/README.md +81 -16
  2. package/lib/Editor/Editor.d.ts +6 -0
  3. package/lib/Editor/Editor.js +26 -0
  4. package/lib/EditorToolbar/EditorToolbar.d.ts +7 -0
  5. package/lib/EditorToolbar/EditorToolbar.js +21 -0
  6. package/lib/EditorToolbar/Tools/Bold/BoldButton.d.ts +2 -0
  7. package/lib/EditorToolbar/Tools/Bold/BoldButton.js +17 -0
  8. package/lib/EditorToolbar/Tools/Italic/ItalicButton.d.ts +2 -0
  9. package/lib/EditorToolbar/Tools/Italic/ItalicButton.js +17 -0
  10. package/lib/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.d.ts +2 -0
  11. package/lib/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.js +17 -0
  12. package/lib/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.d.ts +2 -0
  13. package/lib/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.js +17 -0
  14. package/lib/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.d.ts +2 -0
  15. package/lib/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.js +17 -0
  16. package/lib/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.d.ts +2 -0
  17. package/lib/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.js +17 -0
  18. package/lib/EditorToolbar/Tools/TextAlign/TextAlignButtons.d.ts +2 -0
  19. package/lib/EditorToolbar/Tools/TextAlign/TextAlignButtons.js +16 -0
  20. package/lib/EditorToolbar/Tools/Underline/UnderlineButton.d.ts +2 -0
  21. package/lib/EditorToolbar/Tools/Underline/UnderlineButton.js +17 -0
  22. package/lib/FormattedTextEditor.d.ts +2 -0
  23. package/lib/FormattedTextEditor.js +7 -0
  24. package/lib/index.css +3846 -0
  25. package/lib/index.d.ts +2 -0
  26. package/lib/index.js +2 -36344
  27. package/lib/ui/ToolbarButton/ToolbarButton.d.ts +10 -0
  28. package/lib/ui/ToolbarButton/ToolbarButton.js +5 -0
  29. package/package.json +47 -28
  30. package/.eslintignore +0 -6
  31. package/.eslintrc.json +0 -28
  32. package/CHANGELOG.md +0 -8
  33. package/index.html +0 -13
  34. package/lib/favicon-dxp.svg +0 -3
  35. package/lib/style.css +0 -1
  36. package/public/favicon-dxp.svg +0 -3
  37. package/src/App.tsx +0 -11
  38. package/src/FormattedTextEditor.tsx +0 -25
  39. package/src/Menu.tsx +0 -19
  40. package/src/Toolbar.tsx +0 -10
  41. package/src/index.css +0 -3
  42. package/src/main.tsx +0 -13
  43. package/src/toolbar.css +0 -9
  44. package/src/vite-env.d.ts +0 -1
  45. package/tsconfig.json +0 -21
  46. package/tsconfig.node.json +0 -9
  47. package/vite.config.ts +0 -17
package/README.md CHANGED
@@ -1,37 +1,102 @@
1
1
  # DXP Formatted text editor component
2
2
 
3
- This repo contains the necessary code to develop and publish an NPM package for creating formatted text editors for use in Squiz products.
3
+ The Squiz DXP formatted text editor, built using [Remirror](https://remirror.io/) React library.
4
4
 
5
- The formatted text editor is using the [Remirror](https://remirror.io/) React library.
5
+ It is intended that this package is used for implementing rich text editor capabilities using the DXP Content Store.
6
+
7
+ ## Tools and requirements
8
+
9
+ Tools that relate to standards, publishing and code base health should be available from the monorepo root. Package specific tools and requirements will be listed below.
6
10
 
7
11
  ### Requirements
8
12
 
9
- - [Volta](https://volta.sh/)
10
- - [Node/NPM](https://nodejs.org/en/)
13
+ There are no tools that you need locally that are specific to this repo. Please refer to the monorepo README for more information.
11
14
 
12
- ### Working locally
15
+ ### Optional tools
13
16
 
14
- Provided you have `Volta` installed as soon as you are in the `formatted-text-editor` directory you should be on the correct Node version.
15
- See the `package.json` for the specific version.
17
+ - [Volta](https://volta.sh/): Provided you have `Volta` installed as soon as you are in the `formatted-text-editor` directory you should be on the correct Node version.
16
18
 
17
- Now run the following commands from the `packages/formatted-text-editor/` directory.
19
+ ## Working locally
18
20
 
19
- ```sh
20
- npm i
21
- ```
21
+ ### Installation
22
+
23
+ Please refer to the monorepo README for getting up and running.
24
+
25
+ ### Local development
26
+
27
+ You can preview the formatted text editor in your local environment by running the following command from the `packages/formatted-text-editor` directory:
22
28
 
23
29
  ```sh
24
30
  npm run dev
25
31
  ```
32
+
26
33
  This will expose `http://localhost:5173/` and this can be viewed in the browser.
27
34
 
35
+ > TIP: Make sure you have already installed the node modules at the root level of the repo.
36
+
37
+ ### Testing
38
+
39
+ Tests must be written when contributing to this package. Tests are automatically run in CI and test failure will result in unmerged code.
40
+
41
+ #### Unit testing
42
+
43
+ This package using Jest to perform Unit testing. In addition to Jest we are using a few Testing Library utilities:
44
+
45
+ - [React testing library](https://testing-library.com/docs/react-testing-library/intro/) - Enables React component testing
46
+ - [Jest DOM](https://testing-library.com/docs/ecosystem-jest-dom/) - Enables custom matchers
47
+
48
+ Tests should be co-located with componentry and should strive for maximum coverage.
49
+
50
+ To run tests locally you can run:
51
+ ```sh
52
+ npm run test
53
+ ```
54
+ Or if you'd like to "watch" for changes:
55
+ ```sh
56
+ npm run test:watch
57
+ ```
58
+
59
+ #### End to end testing
60
+
61
+ This package uses [Cypress](https://docs.cypress.io/) for end to end testing.
62
+
63
+ To run tests locally you can run:
64
+ ```sh
65
+ npm run test:e2e
66
+ ```
67
+ Cypress is configured to look at a preview dev environment on `http://localhost:8080`.
68
+
69
+
70
+ ## Publishing
71
+
72
+ This package will be automatically compiled and published following the process defined by the monorepo. Please see the README at the root of the monorepo for more details.
28
73
 
29
- ## WIP: Contributing
74
+ We may manually publish this repo following these steps (please note that you should only ever do this from the `develop` branch):
30
75
 
31
- ### WIP: Testing
76
+ 1. Run a clean, CI install, compile and publish from the root directory
32
77
 
33
- ## Publish package to NPM
78
+ ```
79
+ npm run clean:all
80
+ npm ci
81
+ npm run compile
82
+ npx lerna publish -y --conventional-commits --ci --exact --conventional-prerelease
83
+ ```
34
84
 
35
- This package will automatically be compiled and published to NPM as part of the monorepo CI publishing processes.
85
+ 2. Move into the editor directory and check that the lib directory looks correct for publishing
36
86
 
37
- It is possible to manually compile the package using `npm run compile`. This will not publish the package to NPM.
87
+ ```
88
+ cd packages/formatted-text-editor
89
+ ls -la packages/formatted-text-editor/lib
90
+ ```
91
+
92
+ 3. Execute the NPM publishing command from the package. Watch for any errors in the console
93
+
94
+ ```
95
+ npm publish
96
+ ```
97
+
98
+ 4. Check that the package was published and pushed to NPM
99
+
100
+ ```
101
+ npm view @squiz/formatted-text-editor
102
+ ```
@@ -0,0 +1,6 @@
1
+ import { RemirrorContentType } from '@remirror/core';
2
+ type EditorProps = {
3
+ content?: RemirrorContentType;
4
+ };
5
+ declare const Editor: ({ content }: EditorProps) => JSX.Element;
6
+ export default Editor;
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import { BoldExtension, ItalicExtension, NodeFormattingExtension, UnderlineExtension, wysiwygPreset, } from 'remirror/extensions';
3
+ import { EditorComponent, Remirror, useRemirror } from '@remirror/react';
4
+ import { EditorToolbar } from '../EditorToolbar/EditorToolbar';
5
+ const Editor = ({ content }) => {
6
+ const { manager, state, setState } = useRemirror({
7
+ extensions: () => [
8
+ ...wysiwygPreset(),
9
+ new BoldExtension(),
10
+ new ItalicExtension(),
11
+ new NodeFormattingExtension(),
12
+ new UnderlineExtension(),
13
+ ],
14
+ content,
15
+ selection: 'start',
16
+ stringHandler: 'html',
17
+ });
18
+ const handleChange = (parameter) => {
19
+ setState(parameter.state);
20
+ };
21
+ return (React.createElement(Remirror, { manager: manager, state: state, onChange: handleChange, placeholder: "Write something" },
22
+ React.createElement(EditorToolbar, { manager: manager }),
23
+ React.createElement(EditorComponent, null),
24
+ React.createElement(EditorToolbar, { manager: manager, isPopover: true })));
25
+ };
26
+ export default Editor;
@@ -0,0 +1,7 @@
1
+ import { RemirrorManager } from 'remirror';
2
+ type EditorToolbarProps = {
3
+ manager: RemirrorManager<any>;
4
+ isPopover?: boolean;
5
+ };
6
+ export declare const EditorToolbar: ({ manager, isPopover }: EditorToolbarProps) => JSX.Element;
7
+ export {};
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { Toolbar, FloatingToolbar } from '@remirror/react-components';
3
+ import ItalicButton from './Tools/Italic/ItalicButton';
4
+ import UnderlineButton from './Tools/Underline/UnderlineButton';
5
+ import BoldButton from './Tools/Bold/BoldButton';
6
+ import TextAlignButtons from './Tools/TextAlign/TextAlignButtons';
7
+ // The editor main toolbar
8
+ export const EditorToolbar = ({ manager, isPopover }) => {
9
+ const extensionNames = {};
10
+ manager.extensions.forEach((extension) => {
11
+ extensionNames[extension.name] = true;
12
+ });
13
+ return (React.createElement(React.Fragment, null, !isPopover ? (React.createElement(Toolbar, { className: "remirror-toolbar editor-toolbar" },
14
+ extensionNames.bold && React.createElement(BoldButton, null),
15
+ extensionNames.italic && React.createElement(ItalicButton, null),
16
+ extensionNames.underline && React.createElement(UnderlineButton, null),
17
+ extensionNames.nodeFormatting && React.createElement(TextAlignButtons, null))) : (React.createElement(FloatingToolbar, { className: "remirror-floating-popover" },
18
+ extensionNames.bold && React.createElement(BoldButton, null),
19
+ extensionNames.italic && React.createElement(ItalicButton, null),
20
+ extensionNames.underline && React.createElement(UnderlineButton, null)))));
21
+ };
@@ -0,0 +1,2 @@
1
+ declare const BoldButton: () => JSX.Element;
2
+ export default BoldButton;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useCommands, useActive, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
4
+ import FormatBoldRoundedIcon from '@mui/icons-material/FormatBoldRounded';
5
+ const BoldButton = () => {
6
+ const { toggleBold } = useCommands();
7
+ const chain = useChainedCommands();
8
+ const active = useActive();
9
+ const enabled = toggleBold.enabled();
10
+ const handleSelect = () => {
11
+ if (toggleBold.enabled()) {
12
+ chain.toggleBold().focus().run();
13
+ }
14
+ };
15
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.bold(), icon: React.createElement(FormatBoldRoundedIcon, null), label: "Bold (cmd+B)" }));
16
+ };
17
+ export default BoldButton;
@@ -0,0 +1,2 @@
1
+ declare const ItalicButton: () => JSX.Element;
2
+ export default ItalicButton;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useCommands, useActive, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
4
+ import FormatItalicRoundedIcon from '@mui/icons-material/FormatItalicRounded';
5
+ const ItalicButton = () => {
6
+ const { toggleItalic } = useCommands();
7
+ const chain = useChainedCommands();
8
+ const active = useActive();
9
+ const enabled = toggleItalic.enabled();
10
+ const handleSelect = () => {
11
+ if (toggleItalic.enabled()) {
12
+ chain.toggleItalic().focus().run();
13
+ }
14
+ };
15
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.italic(), icon: React.createElement(FormatItalicRoundedIcon, null), label: "Italic (cmd+I)" }));
16
+ };
17
+ export default ItalicButton;
@@ -0,0 +1,2 @@
1
+ declare const CenterAlignButton: () => JSX.Element;
2
+ export default CenterAlignButton;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useCommands, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../../ui/ToolbarButton/ToolbarButton';
4
+ import FormatAlignCenterIcon from '@mui/icons-material/FormatAlignCenter';
5
+ const CenterAlignButton = () => {
6
+ const { centerAlign } = useCommands();
7
+ const chain = useChainedCommands();
8
+ const handleSelect = () => {
9
+ if (centerAlign.enabled()) {
10
+ chain.centerAlign().focus().run();
11
+ }
12
+ };
13
+ const active = centerAlign.active?.() || false;
14
+ const enabled = centerAlign.enabled();
15
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active, icon: React.createElement(FormatAlignCenterIcon, null), label: "Align center" }));
16
+ };
17
+ export default CenterAlignButton;
@@ -0,0 +1,2 @@
1
+ declare const JustifyAlignButton: () => JSX.Element;
2
+ export default JustifyAlignButton;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useCommands, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../../ui/ToolbarButton/ToolbarButton';
4
+ import FormatAlignJustifyIcon from '@mui/icons-material/FormatAlignJustify';
5
+ const JustifyAlignButton = () => {
6
+ const { justifyAlign } = useCommands();
7
+ const chain = useChainedCommands();
8
+ const handleSelect = () => {
9
+ if (justifyAlign.enabled()) {
10
+ chain.justifyAlign().focus().run();
11
+ }
12
+ };
13
+ const active = justifyAlign.active?.() || false;
14
+ const enabled = justifyAlign.enabled();
15
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active, icon: React.createElement(FormatAlignJustifyIcon, null), label: "Justify" }));
16
+ };
17
+ export default JustifyAlignButton;
@@ -0,0 +1,2 @@
1
+ declare const LeftAlignButton: () => JSX.Element;
2
+ export default LeftAlignButton;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useCommands, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../../ui/ToolbarButton/ToolbarButton';
4
+ import FormatAlignLeftIcon from '@mui/icons-material/FormatAlignLeft';
5
+ const LeftAlignButton = () => {
6
+ const { leftAlign } = useCommands();
7
+ const chain = useChainedCommands();
8
+ const handleSelect = () => {
9
+ if (leftAlign.enabled()) {
10
+ chain.leftAlign().focus().run();
11
+ }
12
+ };
13
+ const active = leftAlign.active?.() || false;
14
+ const enabled = leftAlign.enabled();
15
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active, icon: React.createElement(FormatAlignLeftIcon, null), label: "Align left" }));
16
+ };
17
+ export default LeftAlignButton;
@@ -0,0 +1,2 @@
1
+ declare const RightAlignButton: () => JSX.Element;
2
+ export default RightAlignButton;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useCommands, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../../ui/ToolbarButton/ToolbarButton';
4
+ import FormatAlignRightIcon from '@mui/icons-material/FormatAlignRight';
5
+ const RightAlignButton = () => {
6
+ const { rightAlign } = useCommands();
7
+ const chain = useChainedCommands();
8
+ const handleSelect = () => {
9
+ if (rightAlign.enabled()) {
10
+ chain.rightAlign().focus().run();
11
+ }
12
+ };
13
+ const active = rightAlign.active?.() || false;
14
+ const enabled = rightAlign.enabled();
15
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active, icon: React.createElement(FormatAlignRightIcon, null), label: "Align right" }));
16
+ };
17
+ export default RightAlignButton;
@@ -0,0 +1,2 @@
1
+ declare const TextAlignButtons: () => JSX.Element;
2
+ export default TextAlignButtons;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import LeftAlignButton from './LeftAlign/LeftAlignButton';
3
+ import CenterAlignButton from './CenterAlign/CenterAlignButton';
4
+ import RightAlignButton from './RightAlign/RightAlignButton';
5
+ import JustifyAlignButton from './JustifyAlign/JustifyAlignButton';
6
+ import { VerticalDivider } from '@remirror/react-components';
7
+ const TextAlignButtons = () => {
8
+ return (React.createElement(React.Fragment, null,
9
+ React.createElement(VerticalDivider, { className: "editor-divider" }),
10
+ React.createElement(LeftAlignButton, null),
11
+ React.createElement(CenterAlignButton, null),
12
+ React.createElement(RightAlignButton, null),
13
+ React.createElement(JustifyAlignButton, null),
14
+ React.createElement(VerticalDivider, { className: "editor-divider" })));
15
+ };
16
+ export default TextAlignButtons;
@@ -0,0 +1,2 @@
1
+ declare const UnderlineButton: () => JSX.Element;
2
+ export default UnderlineButton;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useCommands, useActive, useChainedCommands } from '@remirror/react';
3
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
4
+ import FormatUnderlinedRoundedIcon from '@mui/icons-material/FormatUnderlinedRounded';
5
+ const UnderlineButton = () => {
6
+ const { toggleUnderline } = useCommands();
7
+ const chain = useChainedCommands();
8
+ const active = useActive();
9
+ const enabled = toggleUnderline.enabled();
10
+ const handleSelect = () => {
11
+ if (toggleUnderline.enabled()) {
12
+ chain.toggleUnderline().focus().run();
13
+ }
14
+ };
15
+ return (React.createElement(ToolbarButton, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.underline(), icon: React.createElement(FormatUnderlinedRoundedIcon, null), label: "Underline (cmd+U)" }));
16
+ };
17
+ export default UnderlineButton;
@@ -0,0 +1,2 @@
1
+ declare const FormattedTextEditor: () => JSX.Element;
2
+ export default FormattedTextEditor;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ 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;