@squiz/formatted-text-editor 1.12.0-alpha.14 → 1.12.0-alpha.16

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.
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { BoldExtension, ItalicExtension, NodeFormattingExtension, UnderlineExtension, wysiwygPreset, } from 'remirror/extensions';
2
+ import { BoldExtension, ItalicExtension, NodeFormattingExtension, UnderlineExtension, HistoryExtension, wysiwygPreset, } from 'remirror/extensions';
3
3
  import { EditorComponent, Remirror, useRemirror } from '@remirror/react';
4
4
  import { EditorToolbar } from '../EditorToolbar/EditorToolbar';
5
5
  const Editor = ({ content }) => {
@@ -10,6 +10,7 @@ const Editor = ({ content }) => {
10
10
  new ItalicExtension(),
11
11
  new NodeFormattingExtension(),
12
12
  new UnderlineExtension(),
13
+ new HistoryExtension(),
13
14
  ],
14
15
  content,
15
16
  selection: 'start',
@@ -18,7 +19,7 @@ const Editor = ({ content }) => {
18
19
  const handleChange = (parameter) => {
19
20
  setState(parameter.state);
20
21
  };
21
- return (React.createElement(Remirror, { manager: manager, state: state, onChange: handleChange, placeholder: "Write something" },
22
+ return (React.createElement(Remirror, { manager: manager, state: state, onChange: handleChange, placeholder: "Write something", label: "Text editor" },
22
23
  React.createElement(EditorToolbar, { manager: manager }),
23
24
  React.createElement(EditorComponent, null),
24
25
  React.createElement(EditorToolbar, { manager: manager, isPopover: true })));
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
- import { Toolbar, FloatingToolbar } from '@remirror/react-components';
2
+ import { Toolbar, FloatingToolbar, VerticalDivider } from '@remirror/react-components';
3
3
  import ItalicButton from './Tools/Italic/ItalicButton';
4
4
  import UnderlineButton from './Tools/Underline/UnderlineButton';
5
5
  import BoldButton from './Tools/Bold/BoldButton';
6
6
  import TextAlignButtons from './Tools/TextAlign/TextAlignButtons';
7
+ import UndoButton from './Tools/Undo/UndoButton';
8
+ import RedoButton from './Tools/Redo/RedoButton';
7
9
  // The editor main toolbar
8
10
  export const EditorToolbar = ({ manager, isPopover }) => {
9
11
  const extensionNames = {};
@@ -11,6 +13,10 @@ export const EditorToolbar = ({ manager, isPopover }) => {
11
13
  extensionNames[extension.name] = true;
12
14
  });
13
15
  return (React.createElement(React.Fragment, null, !isPopover ? (React.createElement(Toolbar, { className: "remirror-toolbar editor-toolbar" },
16
+ extensionNames.history && (React.createElement(React.Fragment, null,
17
+ React.createElement(UndoButton, null),
18
+ React.createElement(RedoButton, null),
19
+ React.createElement(VerticalDivider, { className: "editor-divider" }))),
14
20
  extensionNames.bold && React.createElement(BoldButton, null),
15
21
  extensionNames.italic && React.createElement(ItalicButton, null),
16
22
  extensionNames.underline && React.createElement(UnderlineButton, null),
@@ -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;
@@ -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;
package/lib/index.css CHANGED
@@ -3843,7 +3843,8 @@ button:active .remirror-menu-pane-shortcut,
3843
3843
  .toolbar-button ~ .toolbar-button {
3844
3844
  margin-left: 2px;
3845
3845
  }
3846
- .toolbar-button.is-active {
3846
+ .toolbar-button.is-active,
3847
+ .toolbar-button:active {
3847
3848
  background-color: var(--blue-100);
3848
3849
  color: var(--blue-300);
3849
3850
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squiz/formatted-text-editor",
3
- "version": "1.12.0-alpha.14",
3
+ "version": "1.12.0-alpha.16",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "scripts": {
@@ -55,5 +55,5 @@
55
55
  "volta": {
56
56
  "node": "16.19.0"
57
57
  },
58
- "gitHead": "76fa4ca4f3c3fa3b0a808232474df640550871cc"
58
+ "gitHead": "25328af157198a2b393ebab5896efa9b28cbdd69"
59
59
  }
@@ -4,6 +4,7 @@ import {
4
4
  ItalicExtension,
5
5
  NodeFormattingExtension,
6
6
  UnderlineExtension,
7
+ HistoryExtension,
7
8
  wysiwygPreset,
8
9
  } from 'remirror/extensions';
9
10
  import { EditorComponent, Remirror, useRemirror } from '@remirror/react';
@@ -22,6 +23,7 @@ const Editor = ({ content }: EditorProps) => {
22
23
  new ItalicExtension(),
23
24
  new NodeFormattingExtension(),
24
25
  new UnderlineExtension(),
26
+ new HistoryExtension(),
25
27
  ],
26
28
  content,
27
29
  selection: 'start',
@@ -33,7 +35,7 @@ const Editor = ({ content }: EditorProps) => {
33
35
  };
34
36
 
35
37
  return (
36
- <Remirror manager={manager} state={state} onChange={handleChange} placeholder="Write something">
38
+ <Remirror manager={manager} state={state} onChange={handleChange} placeholder="Write something" label="Text editor">
37
39
  <EditorToolbar manager={manager} />
38
40
  <EditorComponent />
39
41
  <EditorToolbar manager={manager} isPopover />
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
- import { Toolbar, FloatingToolbar } from '@remirror/react-components';
2
+ import { Toolbar, FloatingToolbar, VerticalDivider } from '@remirror/react-components';
3
3
  import { RemirrorManager } from 'remirror';
4
4
  import ItalicButton from './Tools/Italic/ItalicButton';
5
5
  import UnderlineButton from './Tools/Underline/UnderlineButton';
6
6
  import BoldButton from './Tools/Bold/BoldButton';
7
7
  import TextAlignButtons from './Tools/TextAlign/TextAlignButtons';
8
+ import UndoButton from './Tools/Undo/UndoButton';
9
+ import RedoButton from './Tools/Redo/RedoButton';
8
10
 
9
11
  type EditorToolbarProps = {
10
12
  manager: RemirrorManager<any>;
@@ -23,6 +25,13 @@ export const EditorToolbar = ({ manager, isPopover }: EditorToolbarProps) => {
23
25
  <>
24
26
  {!isPopover ? (
25
27
  <Toolbar className="remirror-toolbar editor-toolbar">
28
+ {extensionNames.history && (
29
+ <>
30
+ <UndoButton />
31
+ <RedoButton />
32
+ <VerticalDivider className="editor-divider" />
33
+ </>
34
+ )}
26
35
  {extensionNames.bold && <BoldButton />}
27
36
  {extensionNames.italic && <ItalicButton />}
28
37
  {extensionNames.underline && <UnderlineButton />}
@@ -0,0 +1,59 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import Editor from '../../../Editor/Editor';
4
+ import React from 'react';
5
+
6
+ describe('Redo button', () => {
7
+ it('Renders the redo button', () => {
8
+ render(<Editor />);
9
+ expect(screen.getByRole('button', { name: 'Redo (shift+cmd+Z)' })).toBeInTheDocument();
10
+ });
11
+
12
+ it('Renders a disabled button if you have not made any changes yet', () => {
13
+ render(<Editor />);
14
+ const redo = screen.getByRole('button', { name: 'Redo (shift+cmd+Z)' });
15
+ expect(redo).toBeDisabled();
16
+ });
17
+
18
+ it('Enables the button when you perform an action and then revert it', () => {
19
+ const { baseElement } = render(<Editor />);
20
+
21
+ // perform some action
22
+ const leftAlignButton = baseElement.querySelector('button[title="Align left"]') as HTMLButtonElement;
23
+ expect(leftAlignButton).toBeTruthy();
24
+ fireEvent.click(leftAlignButton);
25
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeTruthy();
26
+
27
+ // Revert this action
28
+ const undo = screen.getByRole('button', { name: 'Undo (cmd+Z)' });
29
+ fireEvent.click(undo);
30
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeFalsy();
31
+
32
+ // Check that this enables the redo button
33
+ const redo = screen.getByRole('button', { name: 'Redo (shift+cmd+Z)' });
34
+ expect(redo).not.toBeDisabled();
35
+ });
36
+
37
+ it('Reverts this action when clicked', () => {
38
+ const { baseElement } = render(<Editor />);
39
+
40
+ // perform some action
41
+ const leftAlignButton = baseElement.querySelector('button[title="Align left"]') as HTMLButtonElement;
42
+ expect(leftAlignButton).toBeTruthy();
43
+ fireEvent.click(leftAlignButton);
44
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeTruthy();
45
+
46
+ // Revert this action
47
+ const undo = screen.getByRole('button', { name: 'Undo (cmd+Z)' });
48
+ fireEvent.click(undo);
49
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeFalsy();
50
+
51
+ // Check that this enables the redo button
52
+ const redo = screen.getByRole('button', { name: 'Redo (shift+cmd+Z)' });
53
+ expect(redo).not.toBeDisabled();
54
+
55
+ // Click the redo button and check that this has reverted the previous action
56
+ fireEvent.click(redo);
57
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeTruthy();
58
+ });
59
+ });
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { useCommands, useHelpers } from '@remirror/react';
3
+ import { HistoryExtension } from 'remirror/extensions';
4
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
5
+ import RedoRoundedIcon from '@mui/icons-material/RedoRounded';
6
+
7
+ const RedoButton = () => {
8
+ const { redo } = useCommands<HistoryExtension>();
9
+ const { redoDepth } = useHelpers<HistoryExtension>(true);
10
+
11
+ const handleSelect = () => {
12
+ if (redo.enabled()) {
13
+ redo();
14
+ }
15
+ };
16
+
17
+ const enabled = redoDepth() > 0;
18
+
19
+ return (
20
+ <ToolbarButton
21
+ handleOnClick={handleSelect}
22
+ isDisabled={!enabled}
23
+ isActive={false}
24
+ icon={<RedoRoundedIcon />}
25
+ label="Redo (shift+cmd+Z)"
26
+ />
27
+ );
28
+ };
29
+
30
+ export default RedoButton;
@@ -0,0 +1,49 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import Editor from '../../../Editor/Editor';
4
+ import React from 'react';
5
+
6
+ describe('Undo button', () => {
7
+ it('Renders the undo button', () => {
8
+ render(<Editor />);
9
+ expect(screen.getByRole('button', { name: 'Undo (cmd+Z)' })).toBeInTheDocument();
10
+ });
11
+
12
+ it('Renders a disabled button if you have not made any changes yet', () => {
13
+ render(<Editor />);
14
+ const undo = screen.getByRole('button', { name: 'Undo (cmd+Z)' });
15
+ expect(undo).toBeDisabled();
16
+ });
17
+
18
+ it('Enables the button when you perform an action', () => {
19
+ const { baseElement } = render(<Editor />);
20
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeFalsy();
21
+
22
+ const leftAlignButton = baseElement.querySelector('button[title="Align left"]') as HTMLButtonElement;
23
+ expect(leftAlignButton).toBeTruthy();
24
+
25
+ fireEvent.click(leftAlignButton);
26
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeTruthy();
27
+ const undo = screen.getByRole('button', { name: 'Undo (cmd+Z)' });
28
+ expect(undo).not.toBeDisabled();
29
+ });
30
+
31
+ it('Reverts this action when clicked', () => {
32
+ const { baseElement } = render(<Editor />);
33
+
34
+ // perform some action
35
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeFalsy();
36
+ const leftAlignButton = baseElement.querySelector('button[title="Align left"]') as HTMLButtonElement;
37
+ expect(leftAlignButton).toBeTruthy();
38
+ fireEvent.click(leftAlignButton);
39
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeTruthy();
40
+
41
+ // Check that this enables the undo button
42
+ const undo = screen.getByRole('button', { name: 'Undo (cmd+Z)' });
43
+ expect(undo).not.toBeDisabled();
44
+
45
+ // Click the undo button and check that this has reverted the previous action
46
+ fireEvent.click(undo);
47
+ expect(baseElement.querySelector('p[data-node-text-align="left"]')).toBeFalsy();
48
+ });
49
+ });
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { useCommands, useHelpers } from '@remirror/react';
3
+ import { HistoryExtension } from 'remirror/extensions';
4
+ import ToolbarButton from '../../../ui/ToolbarButton/ToolbarButton';
5
+ import UndoRoundedIcon from '@mui/icons-material/UndoRounded';
6
+
7
+ const UndoButton = () => {
8
+ const { undo } = useCommands<HistoryExtension>();
9
+ const { undoDepth } = useHelpers<HistoryExtension>(true);
10
+
11
+ const handleSelect = () => {
12
+ if (undo.enabled()) {
13
+ undo();
14
+ }
15
+ };
16
+
17
+ const enabled = undoDepth() > 0;
18
+
19
+ return (
20
+ <ToolbarButton
21
+ handleOnClick={handleSelect}
22
+ isDisabled={!enabled}
23
+ isActive={false}
24
+ icon={<UndoRoundedIcon />}
25
+ label="Undo (cmd+Z)"
26
+ />
27
+ );
28
+ };
29
+
30
+ export default UndoButton;
@@ -10,7 +10,6 @@
10
10
  > *:not(:first-child) {
11
11
  margin: 0 0 0 2px;
12
12
  }
13
-
14
13
  .editor-divider {
15
14
  margin: -4px 2px -4px 4px;
16
15
  border-width: 1px;
@@ -33,7 +33,8 @@
33
33
  margin-left: 2px;
34
34
  }
35
35
 
36
- &.is-active {
36
+ &.is-active,
37
+ &:active {
37
38
  background-color: var(--blue-100);
38
39
  color: var(--blue-300);
39
40
  }