@squiz/formatted-text-editor 1.16.0 → 1.21.1-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.
- package/.eslintrc.json +7 -0
- package/README.md +10 -0
- package/demo/App.tsx +18 -4
- package/demo/index.scss +16 -10
- package/jest.config.ts +8 -9
- package/lib/Editor/Editor.js +18 -13
- package/lib/EditorToolbar/FloatingToolbar.js +50 -20
- package/lib/EditorToolbar/Toolbar.js +33 -24
- package/lib/EditorToolbar/Tools/Bold/BoldButton.js +14 -9
- package/lib/EditorToolbar/Tools/Image/Form/ImageForm.d.ts +17 -0
- package/lib/EditorToolbar/Tools/Image/Form/ImageForm.js +84 -0
- package/lib/EditorToolbar/Tools/Image/ImageButton.d.ts +2 -0
- package/lib/EditorToolbar/Tools/Image/ImageButton.js +67 -0
- package/lib/EditorToolbar/Tools/Image/ImageModal.d.ts +8 -0
- package/lib/EditorToolbar/Tools/Image/ImageModal.js +19 -0
- package/lib/EditorToolbar/Tools/Italic/ItalicButton.js +14 -9
- package/lib/EditorToolbar/Tools/Link/Form/LinkForm.js +20 -15
- package/lib/EditorToolbar/Tools/Link/LinkButton.js +42 -14
- package/lib/EditorToolbar/Tools/Link/LinkModal.js +16 -11
- package/lib/EditorToolbar/Tools/Link/RemoveLinkButton.js +13 -8
- package/lib/EditorToolbar/Tools/Redo/RedoButton.js +13 -8
- package/lib/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.js +13 -8
- package/lib/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.js +13 -8
- package/lib/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.js +13 -8
- package/lib/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.js +13 -8
- package/lib/EditorToolbar/Tools/TextAlign/TextAlignButtons.js +19 -14
- package/lib/EditorToolbar/Tools/TextType/Heading/HeadingButton.js +19 -14
- package/lib/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.js +14 -9
- package/lib/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.js +13 -8
- package/lib/EditorToolbar/Tools/TextType/TextTypeDropdown.js +24 -19
- package/lib/EditorToolbar/Tools/Underline/UnderlineButton.js +14 -9
- package/lib/EditorToolbar/Tools/Undo/UndoButton.js +13 -8
- package/lib/EditorToolbar/index.js +18 -2
- package/lib/Extensions/Extensions.d.ts +2 -4
- package/lib/Extensions/Extensions.js +19 -13
- package/lib/Extensions/ImageExtension/ImageExtension.d.ts +3 -0
- package/lib/Extensions/ImageExtension/ImageExtension.js +7 -0
- package/lib/Extensions/LinkExtension/LinkExtension.js +17 -11
- package/lib/Extensions/PreformattedExtension/PreformattedExtension.d.ts +1 -1
- package/lib/Extensions/PreformattedExtension/PreformattedExtension.js +10 -7
- package/lib/FormattedTextEditor.js +7 -2
- package/lib/hooks/index.js +17 -1
- package/lib/hooks/useExtensionNames.js +9 -5
- package/lib/index.css +133 -76
- package/lib/index.d.ts +3 -1
- package/lib/index.js +12 -2
- package/lib/ui/Button/Button.d.ts +11 -0
- package/lib/ui/Button/Button.js +14 -0
- package/lib/ui/Fields/Input/Input.d.ts +4 -0
- package/lib/ui/Fields/Input/Input.js +33 -0
- package/lib/ui/Fields/Select/Select.js +53 -0
- package/lib/ui/Modal/FormModal.js +33 -5
- package/lib/ui/Modal/Modal.js +50 -22
- package/lib/ui/ToolbarDropdown/ToolbarDropdown.js +38 -10
- package/lib/ui/ToolbarDropdownButton/ToolbarDropdownButton.js +11 -6
- package/lib/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.d.ts +10 -0
- package/lib/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.js +160 -0
- package/lib/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.d.ts +9 -0
- package/lib/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.js +105 -0
- package/lib/utils/converters/validNodeTypes.d.ts +2 -0
- package/lib/utils/converters/validNodeTypes.js +21 -0
- package/lib/utils/createToolbarPositioner.js +16 -12
- package/lib/utils/getCursorRect.js +5 -1
- package/package.json +7 -3
- package/src/Editor/_editor.scss +2 -49
- package/src/EditorToolbar/FloatingToolbar.tsx +1 -1
- package/src/EditorToolbar/Toolbar.tsx +2 -0
- package/src/EditorToolbar/Tools/Bold/BoldButton.spec.tsx +1 -1
- package/src/EditorToolbar/Tools/Bold/BoldButton.tsx +2 -2
- package/src/EditorToolbar/Tools/Image/Form/ImageForm.spec.tsx +23 -0
- package/src/EditorToolbar/Tools/Image/Form/ImageForm.tsx +92 -0
- package/src/EditorToolbar/Tools/Image/ImageButton.spec.tsx +79 -0
- package/src/EditorToolbar/Tools/Image/ImageButton.tsx +57 -0
- package/src/EditorToolbar/Tools/Image/ImageModal.spec.tsx +83 -0
- package/src/EditorToolbar/Tools/Image/ImageModal.tsx +29 -0
- package/src/EditorToolbar/Tools/Italic/ItalicButton.spec.tsx +1 -1
- package/src/EditorToolbar/Tools/Italic/ItalicButton.tsx +2 -2
- package/src/EditorToolbar/Tools/Link/Form/LinkForm.tsx +5 -5
- package/src/EditorToolbar/Tools/Link/LinkButton.tsx +2 -2
- package/src/EditorToolbar/Tools/Link/RemoveLinkButton.tsx +2 -2
- package/src/EditorToolbar/Tools/Redo/RedoButton.tsx +2 -2
- package/src/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.tsx +2 -2
- package/src/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.tsx +2 -2
- package/src/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.tsx +2 -2
- package/src/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.tsx +2 -2
- package/src/EditorToolbar/Tools/Underline/Underline.spec.tsx +1 -1
- package/src/EditorToolbar/Tools/Underline/UnderlineButton.tsx +2 -2
- package/src/EditorToolbar/Tools/Undo/UndoButton.tsx +2 -2
- package/src/EditorToolbar/_floating-toolbar.scss +6 -0
- package/src/EditorToolbar/_toolbar.scss +8 -2
- package/src/Extensions/Extensions.ts +5 -2
- package/src/Extensions/ImageExtension/ImageExtension.ts +3 -0
- package/src/Extensions/LinkExtension/LinkExtension.ts +8 -5
- package/src/index.scss +2 -2
- package/src/index.ts +3 -1
- package/src/ui/Button/Button.spec.tsx +44 -0
- package/src/ui/Button/Button.tsx +31 -0
- package/src/ui/{_buttons.scss → Button/_button.scss} +19 -1
- package/src/ui/{Inputs/Text/TextInput.spec.tsx → Fields/Input/Input.spec.tsx} +8 -8
- package/src/ui/{Inputs/Text/TextInput.tsx → Fields/Input/Input.tsx} +4 -4
- package/src/ui/Modal/Modal.tsx +1 -0
- package/src/ui/ToolbarDropdown/ToolbarDropdown.spec.tsx +4 -2
- package/src/ui/ToolbarDropdown/ToolbarDropdown.tsx +1 -1
- package/src/ui/_typography.scss +46 -0
- package/src/utils/converters/mocks/squizNodeJson.mock.ts +75 -0
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.spec.ts +445 -0
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.ts +191 -0
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.spec.ts +307 -0
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.ts +123 -0
- package/src/utils/converters/validNodeTypes.spec.ts +33 -0
- package/src/utils/converters/validNodeTypes.ts +21 -0
- package/tests/renderWithEditor.tsx +2 -2
- package/tsconfig.json +1 -1
- package/lib/ui/Inputs/Select/Select.js +0 -23
- package/lib/ui/Inputs/Text/TextInput.d.ts +0 -4
- package/lib/ui/Inputs/Text/TextInput.js +0 -7
- package/lib/ui/ToolbarButton/ToolbarButton.d.ts +0 -10
- package/lib/ui/ToolbarButton/ToolbarButton.js +0 -5
- package/src/ui/ToolbarButton/ToolbarButton.tsx +0 -26
- package/src/ui/ToolbarButton/_toolbar-button.scss +0 -17
- /package/lib/ui/{Inputs → Fields}/Select/Select.d.ts +0 -0
- /package/src/ui/{Inputs → Fields}/Select/Select.spec.tsx +0 -0
- /package/src/ui/{Inputs → Fields}/Select/Select.tsx +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useCommands, useChainedCommands } from '@remirror/react';
|
3
3
|
import { NodeFormattingExtension } from '@remirror/extension-node-formatting';
|
4
|
-
import
|
4
|
+
import Button from '../../../../ui/Button/Button';
|
5
5
|
import FormatAlignJustifyIcon from '@mui/icons-material/FormatAlignJustify';
|
6
6
|
|
7
7
|
const JustifyAlignButton = () => {
|
@@ -18,7 +18,7 @@ const JustifyAlignButton = () => {
|
|
18
18
|
const enabled = justifyAlign.enabled();
|
19
19
|
|
20
20
|
return (
|
21
|
-
<
|
21
|
+
<Button
|
22
22
|
handleOnClick={handleSelect}
|
23
23
|
isDisabled={!enabled}
|
24
24
|
isActive={active}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useCommands, useChainedCommands } from '@remirror/react';
|
3
3
|
import { NodeFormattingExtension } from '@remirror/extension-node-formatting';
|
4
|
-
import
|
4
|
+
import Button from '../../../../ui/Button/Button';
|
5
5
|
import FormatAlignLeftIcon from '@mui/icons-material/FormatAlignLeft';
|
6
6
|
|
7
7
|
const LeftAlignButton = () => {
|
@@ -18,7 +18,7 @@ const LeftAlignButton = () => {
|
|
18
18
|
const enabled = leftAlign.enabled();
|
19
19
|
|
20
20
|
return (
|
21
|
-
<
|
21
|
+
<Button
|
22
22
|
handleOnClick={handleSelect}
|
23
23
|
isDisabled={!enabled}
|
24
24
|
isActive={active}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useCommands, useChainedCommands } from '@remirror/react';
|
3
3
|
import { NodeFormattingExtension } from '@remirror/extension-node-formatting';
|
4
|
-
import
|
4
|
+
import Button from '../../../../ui/Button/Button';
|
5
5
|
import FormatAlignRightIcon from '@mui/icons-material/FormatAlignRight';
|
6
6
|
|
7
7
|
const RightAlignButton = () => {
|
@@ -18,7 +18,7 @@ const RightAlignButton = () => {
|
|
18
18
|
const enabled = rightAlign.enabled();
|
19
19
|
|
20
20
|
return (
|
21
|
-
<
|
21
|
+
<Button
|
22
22
|
handleOnClick={handleSelect}
|
23
23
|
isDisabled={!enabled}
|
24
24
|
isActive={active}
|
@@ -14,6 +14,6 @@ describe('Underline button', () => {
|
|
14
14
|
expect(screen.getByRole('button', { name: 'Underline (cmd+U)' }).classList.contains('squiz-fte-btn')).toBeTruthy();
|
15
15
|
const underline = screen.getByRole('button', { name: 'Underline (cmd+U)' });
|
16
16
|
fireEvent.click(underline);
|
17
|
-
expect(underline.classList.contains('is-active')).toBeTruthy();
|
17
|
+
expect(underline.classList.contains('squiz-fte-btn--is-active')).toBeTruthy();
|
18
18
|
});
|
19
19
|
});
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useCommands, useActive, useChainedCommands } from '@remirror/react';
|
3
3
|
import { UnderlineExtension } from '@remirror/extension-underline';
|
4
|
-
import
|
4
|
+
import Button from '../../../ui/Button/Button';
|
5
5
|
import FormatUnderlinedRoundedIcon from '@mui/icons-material/FormatUnderlinedRounded';
|
6
6
|
|
7
7
|
const UnderlineButton = () => {
|
@@ -17,7 +17,7 @@ const UnderlineButton = () => {
|
|
17
17
|
};
|
18
18
|
|
19
19
|
return (
|
20
|
-
<
|
20
|
+
<Button
|
21
21
|
handleOnClick={handleSelect}
|
22
22
|
isDisabled={!enabled}
|
23
23
|
isActive={active.underline()}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useCommands, useHelpers } from '@remirror/react';
|
3
3
|
import { HistoryExtension } from 'remirror/extensions';
|
4
|
-
import
|
4
|
+
import Button from '../../../ui/Button/Button';
|
5
5
|
import UndoRoundedIcon from '@mui/icons-material/UndoRounded';
|
6
6
|
|
7
7
|
const UndoButton = () => {
|
@@ -17,7 +17,7 @@ const UndoButton = () => {
|
|
17
17
|
const enabled = undoDepth() > 0;
|
18
18
|
|
19
19
|
return (
|
20
|
-
<
|
20
|
+
<Button
|
21
21
|
handleOnClick={handleSelect}
|
22
22
|
isDisabled={!enabled}
|
23
23
|
isActive={false}
|
@@ -1,4 +1,10 @@
|
|
1
1
|
/// This class is excluded from the scope of squiz-fte-scope as it is outside of the scoped element
|
2
2
|
.squiz-fte-scope__floating-popover {
|
3
3
|
@apply bg-white border-gray-200 p-1 shadow rounded-md border flex;
|
4
|
+
.squiz-fte-btn {
|
5
|
+
@apply p-1;
|
6
|
+
~ .squiz-fte-btn {
|
7
|
+
margin-left: 2px;
|
8
|
+
}
|
9
|
+
}
|
4
10
|
}
|
@@ -1,10 +1,10 @@
|
|
1
|
-
.
|
1
|
+
.editor-toolbar {
|
2
2
|
@apply bg-white border-gray-200 border-b-2 border-solid p-1;
|
3
3
|
|
4
4
|
display: flex;
|
5
5
|
justify-items: center;
|
6
6
|
|
7
|
-
> *:not(:first-child) {
|
7
|
+
> *:not(:first-child, .editor-divider) {
|
8
8
|
margin: 0 0 0 2px;
|
9
9
|
}
|
10
10
|
|
@@ -13,4 +13,10 @@
|
|
13
13
|
margin-right: 2px;
|
14
14
|
height: auto;
|
15
15
|
}
|
16
|
+
.squiz-fte-btn {
|
17
|
+
@apply p-1;
|
18
|
+
~ .squiz-fte-btn {
|
19
|
+
margin-left: 2px;
|
20
|
+
}
|
21
|
+
}
|
16
22
|
}
|
@@ -9,16 +9,19 @@ import {
|
|
9
9
|
} from 'remirror/extensions';
|
10
10
|
import { PreformattedExtension } from './PreformattedExtension/PreformattedExtension';
|
11
11
|
import { LinkExtension } from './LinkExtension/LinkExtension';
|
12
|
+
import { ImageExtension } from './ImageExtension/ImageExtension';
|
13
|
+
import { Extension } from '@remirror/core';
|
12
14
|
|
13
|
-
export const Extensions = () => [
|
15
|
+
export const Extensions = (): Extension[] => [
|
14
16
|
new BoldExtension(),
|
15
17
|
new HeadingExtension(),
|
16
18
|
new ItalicExtension(),
|
17
|
-
new NodeFormattingExtension(),
|
19
|
+
new NodeFormattingExtension({ indents: [] }),
|
18
20
|
new ParagraphExtension(),
|
19
21
|
new PreformattedExtension(),
|
20
22
|
new UnderlineExtension(),
|
21
23
|
new HistoryExtension(),
|
24
|
+
new ImageExtension(),
|
22
25
|
new LinkExtension({
|
23
26
|
supportedTargets: [
|
24
27
|
// '_self' is the browser default and will be used when encountering a link with a
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { ApplySchemaAttributes, getMarkRanges, isElementDomNode, MarkExtensionSpec, MarkSpecOverride } from 'remirror';
|
2
|
-
import { getTextSelection, getMarkRange, KeyBindingProps
|
2
|
+
import { getTextSelection, getMarkRange, KeyBindingProps } from '@remirror/core';
|
3
3
|
import { CommandFunction } from '@remirror/pm';
|
4
4
|
import { LinkAttributes as RemirrorLinkAttributes, LinkExtension as RemirrorLinkExtension } from 'remirror/extensions';
|
5
5
|
|
@@ -95,19 +95,22 @@ export class LinkExtension extends RemirrorLinkExtension {
|
|
95
95
|
|
96
96
|
if (text !== selectedText) {
|
97
97
|
// update the text in the editor if it was updated, update the range to cover the length of the new text.
|
98
|
-
|
98
|
+
tr.insertText(text);
|
99
99
|
range.to = range.from + text.length;
|
100
100
|
}
|
101
101
|
|
102
102
|
// apply the link, or remove it if no URL was provided.
|
103
103
|
if (attrs.href.length > 0) {
|
104
|
-
|
104
|
+
tr.addMark(range.from, range.to, this.type.create(attrs));
|
105
105
|
} else {
|
106
|
-
removeMark(
|
106
|
+
tr.removeMark(range.from, range.to, this.type);
|
107
107
|
}
|
108
108
|
|
109
109
|
// move the cursor to the end of the link and re-focus the editor.
|
110
|
-
|
110
|
+
tr.setSelection(getTextSelection({ from: range.to, to: range.to }, tr.doc));
|
111
|
+
|
112
|
+
// apply the transaction.
|
113
|
+
dispatch?.(tr);
|
111
114
|
view?.focus();
|
112
115
|
|
113
116
|
return true;
|
package/src/index.scss
CHANGED
@@ -4,15 +4,15 @@
|
|
4
4
|
@import 'tailwindcss/utilities';
|
5
5
|
|
6
6
|
/* Global */
|
7
|
+
@import './ui/typography';
|
7
8
|
@import './ui/forms';
|
8
|
-
@import './ui/buttons';
|
9
9
|
|
10
10
|
/* Components */
|
11
11
|
@import './Editor/editor';
|
12
12
|
@import './EditorToolbar/toolbar';
|
13
13
|
@import './EditorToolbar/floating-toolbar';
|
14
14
|
|
15
|
-
@import './ui/
|
15
|
+
@import './ui/Button/button';
|
16
16
|
@import './ui/ToolbarDropdown/toolbar-dropdown';
|
17
17
|
@import './ui/ToolbarDropdownButton/toolbar-dropdown-button';
|
18
18
|
|
package/src/index.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
1
|
import FormattedTextEditor from './FormattedTextEditor';
|
2
|
+
import { remirrorNodeToSquizNode } from './utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode';
|
3
|
+
import { squizNodeToRemirrorNode } from './utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode';
|
2
4
|
|
3
|
-
export { FormattedTextEditor };
|
5
|
+
export { FormattedTextEditor, remirrorNodeToSquizNode, squizNodeToRemirrorNode };
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import '@testing-library/jest-dom';
|
2
|
+
import { render, screen } from '@testing-library/react';
|
3
|
+
import React from 'react';
|
4
|
+
import Button from './Button';
|
5
|
+
import AccessTimeRoundedIcon from '@mui/icons-material/AccessTimeRounded';
|
6
|
+
|
7
|
+
describe('Button', () => {
|
8
|
+
const mockOnClick = jest.fn();
|
9
|
+
|
10
|
+
const ButtonComponent = () => {
|
11
|
+
return (
|
12
|
+
<Button
|
13
|
+
handleOnClick={mockOnClick}
|
14
|
+
isDisabled
|
15
|
+
isActive
|
16
|
+
label="Am a button"
|
17
|
+
text="Hello"
|
18
|
+
icon={<AccessTimeRoundedIcon />}
|
19
|
+
/>
|
20
|
+
);
|
21
|
+
};
|
22
|
+
|
23
|
+
it('Renders the label, text and icon', () => {
|
24
|
+
render(<ButtonComponent />);
|
25
|
+
const label = screen.getByLabelText('Am a button');
|
26
|
+
expect(label).toBeInTheDocument();
|
27
|
+
const text = screen.getByText('Hello');
|
28
|
+
expect(text).toBeInTheDocument();
|
29
|
+
const icon = screen.getByTestId('AccessTimeRoundedIcon');
|
30
|
+
expect(icon).toBeInTheDocument();
|
31
|
+
});
|
32
|
+
|
33
|
+
it('Renders the button in a disabled state if set to be disabled', () => {
|
34
|
+
render(<ButtonComponent />);
|
35
|
+
const button = screen.getByLabelText('Am a button');
|
36
|
+
expect(button).toBeDisabled();
|
37
|
+
});
|
38
|
+
|
39
|
+
it('Adds the active class is set to be active', () => {
|
40
|
+
render(<ButtonComponent />);
|
41
|
+
const button = screen.getByLabelText('Am a button');
|
42
|
+
expect(button).toHaveClass('squiz-fte-btn--is-active');
|
43
|
+
});
|
44
|
+
});
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import React, { ReactElement } from 'react';
|
2
|
+
import clsx from 'clsx';
|
3
|
+
|
4
|
+
type ButtonProps = {
|
5
|
+
handleOnClick: () => void;
|
6
|
+
isDisabled?: boolean;
|
7
|
+
isActive: boolean;
|
8
|
+
label: string;
|
9
|
+
text?: string;
|
10
|
+
icon?: ReactElement;
|
11
|
+
};
|
12
|
+
|
13
|
+
const Button = ({ handleOnClick, isDisabled, isActive, label, text, icon }: ButtonProps) => {
|
14
|
+
return (
|
15
|
+
<button
|
16
|
+
aria-label={label}
|
17
|
+
title={label}
|
18
|
+
type="button"
|
19
|
+
onClick={handleOnClick}
|
20
|
+
disabled={isDisabled}
|
21
|
+
className={clsx('squiz-fte-btn', isActive && 'squiz-fte-btn--is-active', icon && ' squiz-fte-btn--is-icon')}
|
22
|
+
>
|
23
|
+
<>
|
24
|
+
{text && <span>{text}</span>}
|
25
|
+
{icon && icon}
|
26
|
+
</>
|
27
|
+
</button>
|
28
|
+
);
|
29
|
+
};
|
30
|
+
|
31
|
+
export default Button;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
.squiz-fte-btn {
|
2
|
-
@apply font-normal rounded ease-linear transition-all duration-150;
|
2
|
+
@apply font-normal rounded ease-linear transition-all bg-white text-gray-600 duration-150;
|
3
3
|
display: flex;
|
4
4
|
align-items: center;
|
5
5
|
text-align: center;
|
@@ -11,9 +11,27 @@
|
|
11
11
|
border: 1px solid transparent;
|
12
12
|
padding: 6px 12px;
|
13
13
|
|
14
|
+
&--is-icon {
|
15
|
+
padding: 6px;
|
16
|
+
}
|
17
|
+
|
18
|
+
~ .squiz-fte-btn {
|
19
|
+
margin-left: 2px;
|
20
|
+
}
|
21
|
+
|
14
22
|
&.disabled,
|
15
23
|
&[disabled] {
|
16
24
|
cursor: not-allowed;
|
17
25
|
@apply opacity-50;
|
18
26
|
}
|
27
|
+
|
28
|
+
&:hover,
|
29
|
+
&:focus {
|
30
|
+
background-color: rgba(black, 0.04);
|
31
|
+
}
|
32
|
+
|
33
|
+
&--is-active,
|
34
|
+
&:active {
|
35
|
+
@apply text-blue-300 bg-blue-100;
|
36
|
+
}
|
19
37
|
}
|
@@ -1,30 +1,30 @@
|
|
1
1
|
import '@testing-library/jest-dom';
|
2
2
|
import { render, screen, fireEvent } from '@testing-library/react';
|
3
3
|
import React from 'react';
|
4
|
-
import {
|
4
|
+
import { Input } from './Input';
|
5
5
|
|
6
|
-
describe('
|
6
|
+
describe('Input', () => {
|
7
7
|
const mockOnChange = jest.fn();
|
8
8
|
|
9
|
-
const
|
10
|
-
return <
|
9
|
+
const InputComponent = () => {
|
10
|
+
return <Input name="text-input" defaultValue="Water" label="Text input" onChange={mockOnChange} />;
|
11
11
|
};
|
12
12
|
|
13
13
|
it('Renders the label', () => {
|
14
|
-
render(<
|
14
|
+
render(<InputComponent />);
|
15
15
|
// Check that the supplied label renders
|
16
16
|
const inputLabel = screen.getByLabelText('Text input');
|
17
17
|
expect(inputLabel).toBeInTheDocument();
|
18
18
|
});
|
19
19
|
|
20
20
|
it('Renders the default value', () => {
|
21
|
-
render(<
|
21
|
+
render(<InputComponent />);
|
22
22
|
// Check that default value supplied renders
|
23
23
|
expect(screen.getByDisplayValue('Water')).toBeInTheDocument();
|
24
24
|
});
|
25
25
|
|
26
26
|
it('Changes the value when new value entered', () => {
|
27
|
-
render(<
|
27
|
+
render(<InputComponent />);
|
28
28
|
const input = screen.getByLabelText('Text input') as HTMLInputElement;
|
29
29
|
// Check that default value supplied renders
|
30
30
|
expect(input.value).toBe('Water');
|
@@ -33,7 +33,7 @@ describe('Text input', () => {
|
|
33
33
|
});
|
34
34
|
|
35
35
|
it('Fires the change function when new value entered', () => {
|
36
|
-
render(<
|
36
|
+
render(<InputComponent />);
|
37
37
|
const input = screen.getByLabelText('Text input') as HTMLInputElement;
|
38
38
|
// Check that default value supplied renders
|
39
39
|
expect(input.value).toBe('Water');
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import React, { ForwardedRef, forwardRef, InputHTMLAttributes } from 'react';
|
2
2
|
|
3
|
-
type
|
3
|
+
type InputProps = InputHTMLAttributes<HTMLInputElement> & {
|
4
4
|
label?: string;
|
5
5
|
};
|
6
6
|
|
7
|
-
const
|
7
|
+
const InputInternal = ({ name, label, type = 'text', ...rest }: InputProps, ref: ForwardedRef<HTMLInputElement>) => {
|
8
8
|
return (
|
9
9
|
<>
|
10
10
|
{label && (
|
@@ -12,9 +12,9 @@ const TextInputInternal = ({ name, label, ...rest }: TextInputProps, ref: Forwar
|
|
12
12
|
{label}
|
13
13
|
</label>
|
14
14
|
)}
|
15
|
-
<input ref={ref} id={name} name={name} type=
|
15
|
+
<input ref={ref} id={name} name={name} type={type} className="squiz-fte-form-control" {...rest} />
|
16
16
|
</>
|
17
17
|
);
|
18
18
|
};
|
19
19
|
|
20
|
-
export const
|
20
|
+
export const Input = forwardRef(InputInternal);
|
package/src/ui/Modal/Modal.tsx
CHANGED
@@ -56,6 +56,7 @@ const Modal = (
|
|
56
56
|
<div className="squiz-fte-modal-header p-6 pb-2">
|
57
57
|
<h2 className="font-semibold text-gray-900 text-heading-2">{title}</h2>
|
58
58
|
<button
|
59
|
+
type="button"
|
59
60
|
className="ml-auto -mr-3 -mt-3 bg-transparent border-0 text-gray-600 font-semibold outline-none focus:outline-none hover:text-color-gray-800"
|
60
61
|
onClick={onCancel}
|
61
62
|
aria-label="Close"
|
@@ -2,13 +2,14 @@ import '@testing-library/jest-dom';
|
|
2
2
|
import { fireEvent, render, screen } from '@testing-library/react';
|
3
3
|
import React from 'react';
|
4
4
|
import ToolbarDropdown from './ToolbarDropdown';
|
5
|
+
import ToolbarDropdownButton from '../ToolbarDropdownButton/ToolbarDropdownButton';
|
5
6
|
|
6
7
|
describe('Toolbar dropdown', () => {
|
7
8
|
const ToolbarDropdownComponent = () => {
|
8
9
|
return (
|
9
10
|
<ToolbarDropdown label="Test dropdown">
|
10
|
-
<
|
11
|
-
<
|
11
|
+
<ToolbarDropdownButton label="Test button" isDisabled={false} isActive={false} handleOnClick={jest.fn()} />
|
12
|
+
<ToolbarDropdownButton label="Test button 2" isDisabled={false} isActive={false} handleOnClick={jest.fn()} />
|
12
13
|
</ToolbarDropdown>
|
13
14
|
);
|
14
15
|
};
|
@@ -17,6 +18,7 @@ describe('Toolbar dropdown', () => {
|
|
17
18
|
render(<ToolbarDropdownComponent />);
|
18
19
|
// Check that the supplied label renders
|
19
20
|
const dropdownButton = screen.getByRole('button', { name: 'Test dropdown' });
|
21
|
+
expect(dropdownButton).toHaveAttribute('type', 'button');
|
20
22
|
expect(dropdownButton).toBeInTheDocument();
|
21
23
|
});
|
22
24
|
|
@@ -21,7 +21,7 @@ const ToolbarDropdown = ({ children, label }: ToolbarDropdownProps) => {
|
|
21
21
|
|
22
22
|
return (
|
23
23
|
<div className="toolbar-dropdown" onBlur={handleBlur}>
|
24
|
-
<button id="dropdownHoverButton" className="toolbar-dropdown__button" onClick={handleDropDown}>
|
24
|
+
<button id="dropdownHoverButton" className="toolbar-dropdown__button" type="button" onClick={handleDropDown}>
|
25
25
|
<span className="toolbar-dropdown__label">{label}</span>
|
26
26
|
<ExpandMoreIcon className="toolbar-dropdown__icon" aria-hidden="true" />
|
27
27
|
</button>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
a {
|
2
|
+
@apply text-blue-300;
|
3
|
+
text-decoration: underline;
|
4
|
+
}
|
5
|
+
|
6
|
+
h1 {
|
7
|
+
font-size: 1.625rem;
|
8
|
+
font-weight: 600;
|
9
|
+
letter-spacing: -0.2px;
|
10
|
+
line-height: 2rem;
|
11
|
+
}
|
12
|
+
|
13
|
+
h2 {
|
14
|
+
font-size: 1.25rem;
|
15
|
+
font-weight: 600;
|
16
|
+
letter-spacing: -0.5px;
|
17
|
+
line-height: 1.5rem;
|
18
|
+
}
|
19
|
+
|
20
|
+
h3 {
|
21
|
+
font-size: 1.125rem;
|
22
|
+
font-weight: 600;
|
23
|
+
letter-spacing: -0.2px;
|
24
|
+
line-height: 1.375rem;
|
25
|
+
}
|
26
|
+
|
27
|
+
h4 {
|
28
|
+
font-size: 1rem;
|
29
|
+
font-weight: 700;
|
30
|
+
letter-spacing: -0.2px;
|
31
|
+
line-height: 1.25rem;
|
32
|
+
}
|
33
|
+
|
34
|
+
h5 {
|
35
|
+
font-size: 1rem;
|
36
|
+
font-weight: 600;
|
37
|
+
letter-spacing: -0.2px;
|
38
|
+
line-height: 1.25rem;
|
39
|
+
}
|
40
|
+
|
41
|
+
h6 {
|
42
|
+
font-size: 0.875rem;
|
43
|
+
font-weight: 600;
|
44
|
+
letter-spacing: -0.2px;
|
45
|
+
line-height: 1.25rem;
|
46
|
+
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import { FORMATTED_TEXT_MODELS as FormattedTextModels } from '@squiz/dx-json-schema-lib';
|
2
|
+
|
3
|
+
export const mockSquizNodeJson: FormattedTextModels.v1.FormattedText = [
|
4
|
+
{
|
5
|
+
children: [
|
6
|
+
{
|
7
|
+
type: 'text',
|
8
|
+
value: 'Hello ',
|
9
|
+
},
|
10
|
+
{
|
11
|
+
children: [
|
12
|
+
{
|
13
|
+
type: 'text',
|
14
|
+
value: 'Mr Bean',
|
15
|
+
},
|
16
|
+
],
|
17
|
+
attributes: {
|
18
|
+
href: 'https://www.google.com',
|
19
|
+
},
|
20
|
+
font: {
|
21
|
+
bold: true,
|
22
|
+
},
|
23
|
+
type: 'tag',
|
24
|
+
tag: 'a',
|
25
|
+
},
|
26
|
+
{
|
27
|
+
type: 'text',
|
28
|
+
value: ', nice to ',
|
29
|
+
},
|
30
|
+
{
|
31
|
+
children: [
|
32
|
+
{
|
33
|
+
type: 'text',
|
34
|
+
value: 'meet you',
|
35
|
+
},
|
36
|
+
],
|
37
|
+
attributes: {
|
38
|
+
href: 'https://www.google.com',
|
39
|
+
},
|
40
|
+
type: 'tag',
|
41
|
+
tag: 'a',
|
42
|
+
},
|
43
|
+
{
|
44
|
+
type: 'text',
|
45
|
+
value: '.',
|
46
|
+
},
|
47
|
+
{
|
48
|
+
children: [],
|
49
|
+
attributes: {
|
50
|
+
alt: 'Test',
|
51
|
+
height: '150',
|
52
|
+
width: '200',
|
53
|
+
src: 'https://media2.giphy.com/media/3o6ozsIxg5legYvggo/giphy.gif',
|
54
|
+
title: '',
|
55
|
+
resizable: 'false',
|
56
|
+
},
|
57
|
+
type: 'tag',
|
58
|
+
tag: 'img',
|
59
|
+
},
|
60
|
+
],
|
61
|
+
type: 'tag',
|
62
|
+
tag: 'p',
|
63
|
+
},
|
64
|
+
];
|
65
|
+
|
66
|
+
export const mockSquizNodeTextJson: FormattedTextModels.v1.FormattedText = [
|
67
|
+
{
|
68
|
+
value: 'Hello world!',
|
69
|
+
type: 'text',
|
70
|
+
},
|
71
|
+
{
|
72
|
+
value: 'Another one...',
|
73
|
+
type: 'text',
|
74
|
+
},
|
75
|
+
];
|