@squiz/formatted-text-editor 1.12.0-alpha.44 → 1.12.0-alpha.46
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/lib/EditorToolbar/EditorToolbar.js +1 -1
- package/lib/EditorToolbar/Tools/Link/Form/LinkForm.js +5 -5
- package/lib/EditorToolbar/Tools/TextType/Heading/HeadingButton.js +1 -1
- package/lib/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.js +2 -3
- package/lib/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.js +1 -1
- package/lib/FormattedTextEditor.js +3 -2
- package/lib/index.css +161 -459
- package/lib/ui/Inputs/Select/Select.js +1 -1
- package/lib/ui/Inputs/Text/TextInput.js +2 -2
- package/lib/ui/Modal/Modal.js +7 -7
- package/lib/ui/ToolbarButton/ToolbarButton.js +1 -1
- package/lib/ui/ToolbarDropdown/ToolbarDropdown.d.ts +0 -1
- package/lib/ui/ToolbarDropdown/ToolbarDropdown.js +14 -6
- package/lib/ui/{DropdownButton/DropdownButton.js → ToolbarDropdownButton/ToolbarDropdownButton.js} +1 -1
- package/package.json +4 -4
- package/postcss.config.js +9 -1
- package/src/Editor/_editor.scss +1 -1
- package/src/EditorToolbar/EditorToolbar.tsx +1 -1
- package/src/EditorToolbar/Tools/Bold/BoldButton.spec.tsx +1 -1
- package/src/EditorToolbar/Tools/Italic/ItalicButton.spec.tsx +1 -1
- package/src/EditorToolbar/Tools/Link/Form/LinkForm.spec.tsx +1 -1
- package/src/EditorToolbar/Tools/Link/Form/LinkForm.tsx +5 -5
- package/src/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.spec.tsx +39 -0
- package/src/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.spec.tsx +39 -0
- package/src/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.spec.tsx +39 -0
- package/src/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.spec.tsx +39 -0
- package/src/EditorToolbar/Tools/TextType/Heading/HeadingButton.spec.tsx +56 -0
- package/src/EditorToolbar/Tools/TextType/Heading/HeadingButton.tsx +1 -1
- package/src/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.spec.tsx +30 -0
- package/src/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.tsx +2 -3
- package/src/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.spec.tsx +47 -0
- package/src/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.tsx +1 -1
- package/src/EditorToolbar/Tools/TextType/TextTypeDropdown.spec.tsx +51 -0
- package/src/EditorToolbar/Tools/Underline/Underline.spec.tsx +1 -1
- package/src/EditorToolbar/_editor-toolbar.scss +4 -2
- package/src/FormattedTextEditor.tsx +4 -2
- package/src/index.scss +2 -2
- package/src/ui/Inputs/Select/Select.tsx +1 -1
- package/src/ui/Inputs/Text/TextInput.tsx +2 -2
- package/src/ui/Modal/Modal.tsx +7 -7
- package/src/ui/Modal/_modal.scss +2 -2
- package/src/ui/ToolbarButton/ToolbarButton.tsx +1 -1
- package/src/ui/ToolbarDropdown/ToolbarDropdown.spec.tsx +78 -0
- package/src/ui/ToolbarDropdown/ToolbarDropdown.tsx +22 -12
- package/src/ui/ToolbarDropdown/_toolbar-dropdown.scss +25 -20
- package/src/ui/ToolbarDropdownButton/ToolbarDropdownButton.spec.tsx +48 -0
- package/src/ui/{DropdownButton/DropdownButton.tsx → ToolbarDropdownButton/ToolbarDropdownButton.tsx} +1 -0
- package/src/ui/{DropdownButton/_dropdown-button.scss → ToolbarDropdownButton/_toolbar-dropdown-button.scss} +7 -1
- package/src/ui/_buttons.scss +1 -1
- package/src/ui/_forms.scss +1 -1
- package/tailwind.config.cjs +2 -4
- /package/lib/ui/{DropdownButton/DropdownButton.d.ts → ToolbarDropdownButton/ToolbarDropdownButton.d.ts} +0 -0
@@ -3,8 +3,10 @@ import Editor from './Editor/Editor';
|
|
3
3
|
|
4
4
|
const FormattedTextEditor = () => {
|
5
5
|
return (
|
6
|
-
<div className="
|
7
|
-
<
|
6
|
+
<div className="squiz-fte-scope">
|
7
|
+
<div className="remirror-theme formatted-text-editor editor-wrapper">
|
8
|
+
<Editor />
|
9
|
+
</div>
|
8
10
|
</div>
|
9
11
|
);
|
10
12
|
};
|
package/src/index.scss
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* Tailwind base */
|
1
|
+
/* Tailwind base styles, but scoped to the editor */
|
2
2
|
@import 'tailwindcss/base';
|
3
3
|
@import 'tailwindcss/components';
|
4
4
|
@import 'tailwindcss/utilities';
|
@@ -13,6 +13,6 @@
|
|
13
13
|
|
14
14
|
@import './ui/ToolbarButton/toolbar-button';
|
15
15
|
@import './ui/ToolbarDropdown/toolbar-dropdown';
|
16
|
-
@import './ui/
|
16
|
+
@import './ui/ToolbarDropdownButton/toolbar-dropdown-button';
|
17
17
|
|
18
18
|
@import './ui/Modal/modal';
|
@@ -10,11 +10,11 @@ export const TextInput = ({ id, label, value, ...rest }: TextInputProps) => {
|
|
10
10
|
return (
|
11
11
|
<>
|
12
12
|
{label && (
|
13
|
-
<label htmlFor={id} className="
|
13
|
+
<label htmlFor={id} className="squiz-fte-form-label">
|
14
14
|
{label}
|
15
15
|
</label>
|
16
16
|
)}
|
17
|
-
<input name={id} id={id} type="text" className="
|
17
|
+
<input name={id} id={id} type="text" className="squiz-fte-form-control" defaultValue={value} {...rest} />
|
18
18
|
</>
|
19
19
|
);
|
20
20
|
};
|
package/src/ui/Modal/Modal.tsx
CHANGED
@@ -25,10 +25,10 @@ const Modal = ({ children, onCancel, onSubmit, className }: ModalProps): ReactEl
|
|
25
25
|
|
26
26
|
return (
|
27
27
|
<>
|
28
|
-
<div className={`
|
28
|
+
<div className={`squiz-fte-modal-wrapper ${className ? className : ''}`}>
|
29
29
|
<div className="w-modal-sm my-6 mx-auto">
|
30
|
-
<div className="
|
31
|
-
<div className="
|
30
|
+
<div className="squiz-fte-modal">
|
31
|
+
<div className="squiz-fte-modal-header p-6 pb-2">
|
32
32
|
<h2 className="font-semibold text-gray-900 text-heading-2">Link</h2>
|
33
33
|
<button
|
34
34
|
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"
|
@@ -38,10 +38,10 @@ const Modal = ({ children, onCancel, onSubmit, className }: ModalProps): ReactEl
|
|
38
38
|
<CloseRoundedIcon />
|
39
39
|
</button>
|
40
40
|
</div>
|
41
|
-
<div className="
|
42
|
-
<div className="
|
41
|
+
<div className="squiz-fte-modal-content">{children}</div>
|
42
|
+
<div className="squiz-fte-modal-footer p-6 pt-3">
|
43
43
|
<button
|
44
|
-
className="
|
44
|
+
className="squiz-fte-modal-footer__button bg-gray-200 text-gray-700 mr-2 hover:bg-gray-300"
|
45
45
|
type="button"
|
46
46
|
onClick={onCancel}
|
47
47
|
aria-label="Cancel"
|
@@ -50,7 +50,7 @@ const Modal = ({ children, onCancel, onSubmit, className }: ModalProps): ReactEl
|
|
50
50
|
</button>
|
51
51
|
{onSubmit && (
|
52
52
|
<button
|
53
|
-
className="
|
53
|
+
className="squiz-fte-modal-footer__button bg-blue-300 text-white hover:bg-blue-400"
|
54
54
|
type="button"
|
55
55
|
onClick={onSubmit}
|
56
56
|
aria-label="Apply"
|
package/src/ui/Modal/_modal.scss
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
.
|
1
|
+
.squiz-fte-modal {
|
2
2
|
@apply border-0 rounded shadow-lg flex flex-col w-full bg-white font-base;
|
3
3
|
border-radius: 8px;
|
4
4
|
|
@@ -18,7 +18,7 @@
|
|
18
18
|
@apply flex items-center justify-end rounded-b;
|
19
19
|
|
20
20
|
&__button {
|
21
|
-
@apply
|
21
|
+
@apply squiz-fte-btn text-md font-bold;
|
22
22
|
}
|
23
23
|
}
|
24
24
|
}
|
@@ -16,7 +16,7 @@ const ToolbarButton = ({ handleOnClick, isDisabled, isActive, icon, label }: Too
|
|
16
16
|
type="button"
|
17
17
|
onClick={handleOnClick}
|
18
18
|
disabled={isDisabled}
|
19
|
-
className={`
|
19
|
+
className={`squiz-fte-btn toolbar-button ${isActive ? 'is-active' : ''}`}
|
20
20
|
>
|
21
21
|
{icon}
|
22
22
|
</button>
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import '@testing-library/jest-dom';
|
2
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
3
|
+
import React from 'react';
|
4
|
+
import ToolbarDropdown from './ToolbarDropdown';
|
5
|
+
|
6
|
+
describe('Toolbar dropdown', () => {
|
7
|
+
const ToolbarDropdownComponent = () => {
|
8
|
+
return (
|
9
|
+
<ToolbarDropdown label="Test dropdown">
|
10
|
+
<button>Test button</button>
|
11
|
+
<button>Test button 2</button>
|
12
|
+
</ToolbarDropdown>
|
13
|
+
);
|
14
|
+
};
|
15
|
+
|
16
|
+
it('Renders the dropdown button', () => {
|
17
|
+
render(<ToolbarDropdownComponent />);
|
18
|
+
// Check that the supplied label renders
|
19
|
+
const dropdownButton = screen.getByRole('button', { name: 'Test dropdown' });
|
20
|
+
expect(dropdownButton).toBeInTheDocument();
|
21
|
+
});
|
22
|
+
|
23
|
+
it('Renders the child elements for the dropdown', () => {
|
24
|
+
render(<ToolbarDropdownComponent />);
|
25
|
+
// Check that default value supplied renders
|
26
|
+
expect(screen.getByRole('button', { name: 'Test button' })).toBeInTheDocument();
|
27
|
+
expect(screen.getByRole('button', { name: 'Test button 2' })).toBeInTheDocument();
|
28
|
+
});
|
29
|
+
|
30
|
+
it('Renders the dropdown menu after clicking the dropdown button', () => {
|
31
|
+
const { baseElement } = render(<ToolbarDropdownComponent />);
|
32
|
+
expect(baseElement).toBeTruthy();
|
33
|
+
|
34
|
+
const dropdownButton = baseElement.querySelector('button#dropdownHoverButton') as HTMLButtonElement;
|
35
|
+
expect(dropdownButton).toBeTruthy();
|
36
|
+
fireEvent.click(dropdownButton);
|
37
|
+
|
38
|
+
const dropdownMenu = baseElement.querySelector('div.toolbar-dropdown__menu') as HTMLDivElement;
|
39
|
+
expect(dropdownMenu).toBeTruthy();
|
40
|
+
expect(dropdownMenu.classList).toContain('block');
|
41
|
+
});
|
42
|
+
|
43
|
+
it('Handles the onBlur call when focusing out of the menu', () => {
|
44
|
+
const { baseElement } = render(<ToolbarDropdownComponent />);
|
45
|
+
expect(baseElement).toBeTruthy();
|
46
|
+
|
47
|
+
const dropdownButton = baseElement.querySelector('button#dropdownHoverButton') as HTMLButtonElement;
|
48
|
+
expect(dropdownButton).toBeTruthy();
|
49
|
+
fireEvent.click(dropdownButton);
|
50
|
+
|
51
|
+
const dropdownMenu = baseElement.querySelector('div.toolbar-dropdown__menu') as HTMLDivElement;
|
52
|
+
expect(dropdownMenu).toBeTruthy();
|
53
|
+
expect(dropdownMenu.classList).toContain('block');
|
54
|
+
|
55
|
+
fireEvent.blur(dropdownMenu);
|
56
|
+
|
57
|
+
expect(dropdownMenu.classList).toContain('hidden');
|
58
|
+
});
|
59
|
+
|
60
|
+
it('Closes the dropdown menu after clicking a child element', () => {
|
61
|
+
const { baseElement } = render(<ToolbarDropdownComponent />);
|
62
|
+
expect(baseElement).toBeTruthy();
|
63
|
+
|
64
|
+
const dropdownButton = baseElement.querySelector('button#dropdownHoverButton') as HTMLButtonElement;
|
65
|
+
expect(dropdownButton).toBeTruthy();
|
66
|
+
fireEvent.click(dropdownButton);
|
67
|
+
|
68
|
+
const dropdownMenu = baseElement.querySelector('div.toolbar-dropdown__menu') as HTMLDivElement;
|
69
|
+
expect(dropdownMenu).toBeTruthy();
|
70
|
+
expect(dropdownMenu.classList).toContain('block');
|
71
|
+
|
72
|
+
const childElement = screen.getByRole('button', { name: 'Test button' });
|
73
|
+
expect(childElement).toBeTruthy();
|
74
|
+
fireEvent.click(childElement);
|
75
|
+
|
76
|
+
expect(dropdownMenu.classList).toContain('hidden');
|
77
|
+
});
|
78
|
+
});
|
@@ -1,6 +1,5 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { FocusEventHandler, useState } from 'react';
|
2
2
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
3
|
-
import 'flowbite';
|
4
3
|
|
5
4
|
type ToolbarDropdownProps = {
|
6
5
|
children: JSX.Element | JSX.Element[];
|
@@ -8,24 +7,35 @@ type ToolbarDropdownProps = {
|
|
8
7
|
};
|
9
8
|
|
10
9
|
const ToolbarDropdown = ({ children, label }: ToolbarDropdownProps) => {
|
10
|
+
const [isOpen, setOpen] = useState<boolean>(false);
|
11
|
+
|
12
|
+
const handleDropDown = () => {
|
13
|
+
setOpen(!isOpen);
|
14
|
+
};
|
15
|
+
|
16
|
+
const handleBlur: FocusEventHandler<HTMLDivElement> = (event) => {
|
17
|
+
if (event.relatedTarget?.id !== 'dropdownMenuButton' && !event.target?.className.includes('is-active')) {
|
18
|
+
isOpen && handleDropDown();
|
19
|
+
}
|
20
|
+
};
|
21
|
+
|
11
22
|
return (
|
12
|
-
|
13
|
-
<button
|
14
|
-
id="dropdownHoverButton"
|
15
|
-
data-dropdown-toggle="dropdown"
|
16
|
-
className="toolbar-dropdown__button"
|
17
|
-
type="button"
|
18
|
-
>
|
23
|
+
<div className="toolbar-dropdown" onBlur={handleBlur}>
|
24
|
+
<button id="dropdownHoverButton" className="toolbar-dropdown__button" onClick={handleDropDown}>
|
19
25
|
<span className="toolbar-dropdown__label">{label}</span>
|
20
26
|
<ExpandMoreIcon className="toolbar-dropdown__icon" aria-hidden="true" />
|
21
27
|
</button>
|
28
|
+
|
22
29
|
<div
|
23
30
|
id="dropdown"
|
24
|
-
className=
|
31
|
+
className={`toolbar-dropdown__menu z-10 ${isOpen ? 'block' : 'hidden'} bg-white divide-y w-169`}
|
25
32
|
>
|
26
|
-
|
33
|
+
{/* eslint-disable-next-line */}
|
34
|
+
<ul aria-labelledby="dropdownHoverButton" onClick={handleDropDown}>
|
35
|
+
{children}
|
36
|
+
</ul>
|
27
37
|
</div>
|
28
|
-
|
38
|
+
</div>
|
29
39
|
);
|
30
40
|
};
|
31
41
|
|
@@ -1,27 +1,32 @@
|
|
1
|
-
.toolbar-
|
2
|
-
|
3
|
-
|
1
|
+
.toolbar-dropdown {
|
2
|
+
&__button {
|
3
|
+
@apply flex items-center font-base text-md font-semibold text-gray-600;
|
4
|
+
align-self: center;
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
height: 2rem;
|
7
|
+
padding-left: 0.5rem;
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
&:active,
|
10
|
+
&:hover,
|
11
|
+
&:focus {
|
12
|
+
background-color: rgba(black, 0.04);
|
13
|
+
}
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
.toolbar-dropdown__label {
|
16
|
+
display: inline-flex;
|
17
|
+
width: 7rem;
|
18
|
+
}
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
.toolbar-dropdown__icon {
|
21
|
+
width: 1rem;
|
22
|
+
height: 1.5rem;
|
23
|
+
}
|
22
24
|
}
|
23
|
-
}
|
24
25
|
|
25
|
-
|
26
|
-
|
26
|
+
&__menu {
|
27
|
+
@apply rounded shadow-sm border border-gray-300;
|
28
|
+
|
29
|
+
position: absolute;
|
30
|
+
margin-top: 0.75rem;
|
31
|
+
}
|
27
32
|
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import '@testing-library/jest-dom';
|
2
|
+
import { render } from '@testing-library/react';
|
3
|
+
import React from 'react';
|
4
|
+
import ToolbarDropdownButton from './ToolbarDropdownButton';
|
5
|
+
|
6
|
+
describe('Toolbar dropdown', () => {
|
7
|
+
const handleSelect = jest.fn();
|
8
|
+
|
9
|
+
const ToolbarDropdownButtonComponent = () => {
|
10
|
+
return (
|
11
|
+
<ToolbarDropdownButton handleOnClick={handleSelect} isDisabled={false} isActive={true} label={'Test label'}>
|
12
|
+
<h1>Test heading 1</h1>
|
13
|
+
</ToolbarDropdownButton>
|
14
|
+
);
|
15
|
+
};
|
16
|
+
|
17
|
+
const EmptyToolbarDropdownButtonComponent = () => {
|
18
|
+
return (
|
19
|
+
<ToolbarDropdownButton handleOnClick={handleSelect} isDisabled={false} isActive={false} label={'Test label'} />
|
20
|
+
);
|
21
|
+
};
|
22
|
+
|
23
|
+
it('Renders the dropdown menu button', () => {
|
24
|
+
const { baseElement } = render(<ToolbarDropdownButtonComponent />);
|
25
|
+
expect(baseElement).toBeTruthy();
|
26
|
+
|
27
|
+
const buttonElement = baseElement.querySelector('button#dropdownMenuButton') as HTMLButtonElement;
|
28
|
+
expect(buttonElement).toBeTruthy();
|
29
|
+
expect(buttonElement.textContent).toBe('Test heading 1');
|
30
|
+
});
|
31
|
+
|
32
|
+
it('Renders the dropdown menu button active icon', () => {
|
33
|
+
const { baseElement } = render(<ToolbarDropdownButtonComponent />);
|
34
|
+
expect(baseElement).toBeTruthy();
|
35
|
+
|
36
|
+
const iconElement = baseElement.querySelector('svg.dropdown-button-icon') as SVGElement;
|
37
|
+
expect(iconElement).toBeTruthy();
|
38
|
+
});
|
39
|
+
|
40
|
+
it('Should render the label as button text if no children are provided', () => {
|
41
|
+
const { baseElement } = render(<EmptyToolbarDropdownButtonComponent />);
|
42
|
+
expect(baseElement).toBeTruthy();
|
43
|
+
|
44
|
+
const buttonElement = baseElement.querySelector('button#dropdownMenuButton') as HTMLButtonElement;
|
45
|
+
expect(buttonElement).toBeTruthy();
|
46
|
+
expect(buttonElement.textContent).toBe('Test label');
|
47
|
+
});
|
48
|
+
});
|
@@ -1,8 +1,14 @@
|
|
1
1
|
.dropdown-button {
|
2
|
+
@apply px-2 py-1 text-gray-600;
|
3
|
+
|
2
4
|
height: 40px;
|
3
5
|
width: 100%;
|
4
6
|
justify-content: space-between;
|
5
7
|
align-items: center;
|
6
8
|
display: flex;
|
7
|
-
|
9
|
+
|
10
|
+
&:hover,
|
11
|
+
&:focus {
|
12
|
+
background-color: rgba(black, 0.04);
|
13
|
+
}
|
8
14
|
}
|
package/src/ui/_buttons.scss
CHANGED
package/src/ui/_forms.scss
CHANGED
package/tailwind.config.cjs
CHANGED
File without changes
|