@squiz/formatted-text-editor 1.12.0-alpha.38 → 1.12.0-alpha.40
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/README.md +2 -0
- package/lib/Editor/Editor.js +2 -13
- package/lib/Extensions/Extensions.d.ts +3 -0
- package/lib/Extensions/Extensions.js +13 -0
- package/lib/{extensions → Extensions}/PreformattedExtension/PreformattedExtension.d.ts +0 -0
- package/lib/{extensions → Extensions}/PreformattedExtension/PreformattedExtension.js +0 -0
- package/lib/index.css +381 -37
- package/lib/ui/DropdownButton/DropdownButton.js +1 -1
- package/lib/ui/ToolbarDropdown/ToolbarDropdown.d.ts +1 -0
- package/lib/ui/ToolbarDropdown/ToolbarDropdown.js +7 -8
- package/package.json +4 -4
- package/src/Editor/Editor.mock.tsx +40 -0
- package/src/Editor/Editor.spec.tsx +36 -10
- package/src/Editor/Editor.tsx +3 -23
- package/src/Editor/_editor.scss +44 -0
- package/src/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.tsx +1 -1
- package/src/EditorToolbar/Tools/TextType/TextTypeDropdown.tsx +1 -1
- package/src/Extensions/Extensions.tsx +24 -0
- package/src/{extensions → Extensions}/PreformattedExtension/PreformattedExtension.tsx +0 -0
- package/src/FormattedTextEditor.spec.tsx +10 -0
- package/src/ui/DropdownButton/DropdownButton.tsx +1 -1
- package/src/ui/DropdownButton/_dropdown-button.scss +4 -4
- package/src/ui/ToolbarDropdown/ToolbarDropdown.tsx +17 -12
- package/src/ui/ToolbarDropdown/_toolbar-dropdown.scss +20 -18
- package/tailwind.config.cjs +3 -2
package/README.md
CHANGED
@@ -51,6 +51,8 @@ Or if you'd like to "watch" for changes:
|
|
51
51
|
npm run test:watch
|
52
52
|
```
|
53
53
|
|
54
|
+
When testing text input in the text editor, it is recommended to use the `<MockEditor />` component, which is a simple wrapper around the Remirror component that provides additional functionality for testing (supplying text into the editor).
|
55
|
+
|
54
56
|
### End to end testing
|
55
57
|
|
56
58
|
This package uses [Cypress](https://docs.cypress.io/) for end to end testing.
|
package/lib/Editor/Editor.js
CHANGED
@@ -1,21 +1,10 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { BoldExtension, HeadingExtension, ItalicExtension, NodeFormattingExtension, ParagraphExtension, UnderlineExtension, HistoryExtension, wysiwygPreset, } from 'remirror/extensions';
|
3
2
|
import { EditorComponent, Remirror, useRemirror } from '@remirror/react';
|
4
3
|
import { EditorToolbar } from '../EditorToolbar/EditorToolbar';
|
5
|
-
import {
|
4
|
+
import { Extensions } from '../Extensions/Extensions';
|
6
5
|
const Editor = ({ content }) => {
|
7
6
|
const { manager, state, setState } = useRemirror({
|
8
|
-
extensions:
|
9
|
-
...wysiwygPreset(),
|
10
|
-
new BoldExtension(),
|
11
|
-
new HeadingExtension(),
|
12
|
-
new ItalicExtension(),
|
13
|
-
new NodeFormattingExtension(),
|
14
|
-
new ParagraphExtension(),
|
15
|
-
new PreformattedExtension(),
|
16
|
-
new UnderlineExtension(),
|
17
|
-
new HistoryExtension(),
|
18
|
-
],
|
7
|
+
extensions: Extensions,
|
19
8
|
content,
|
20
9
|
selection: 'start',
|
21
10
|
stringHandler: 'html',
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import { BoldExtension, HeadingExtension, NodeFormattingExtension, HistoryExtension } from 'remirror/extensions';
|
2
|
+
import { Extension } from '@remirror/core';
|
3
|
+
export declare const Extensions: () => (BoldExtension | HistoryExtension | HeadingExtension | NodeFormattingExtension | Extension<import("@remirror/core").EmptyShape>)[];
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { BoldExtension, HeadingExtension, ItalicExtension, NodeFormattingExtension, ParagraphExtension, UnderlineExtension, HistoryExtension, wysiwygPreset, } from 'remirror/extensions';
|
2
|
+
import { PreformattedExtension } from './PreformattedExtension/PreformattedExtension';
|
3
|
+
export const Extensions = () => [
|
4
|
+
...wysiwygPreset(),
|
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
|
+
];
|
File without changes
|
File without changes
|
package/lib/index.css
CHANGED
@@ -3882,7 +3882,7 @@ textarea {
|
|
3882
3882
|
input::placeholder,
|
3883
3883
|
textarea::placeholder {
|
3884
3884
|
opacity: 1;
|
3885
|
-
color: #
|
3885
|
+
color: #9CA3AF;
|
3886
3886
|
}
|
3887
3887
|
button,
|
3888
3888
|
[role=button] {
|
@@ -3910,6 +3910,309 @@ video {
|
|
3910
3910
|
[hidden] {
|
3911
3911
|
display: none;
|
3912
3912
|
}
|
3913
|
+
[type=text],
|
3914
|
+
[type=email],
|
3915
|
+
[type=url],
|
3916
|
+
[type=password],
|
3917
|
+
[type=number],
|
3918
|
+
[type=date],
|
3919
|
+
[type=datetime-local],
|
3920
|
+
[type=month],
|
3921
|
+
[type=search],
|
3922
|
+
[type=tel],
|
3923
|
+
[type=time],
|
3924
|
+
[type=week],
|
3925
|
+
[multiple],
|
3926
|
+
textarea,
|
3927
|
+
select {
|
3928
|
+
appearance: none;
|
3929
|
+
background-color: #fff;
|
3930
|
+
border-color: #6B7280;
|
3931
|
+
border-width: 1px;
|
3932
|
+
border-radius: 0px;
|
3933
|
+
padding-top: 0.5rem;
|
3934
|
+
padding-right: 0.75rem;
|
3935
|
+
padding-bottom: 0.5rem;
|
3936
|
+
padding-left: 0.75rem;
|
3937
|
+
font-size: 1rem;
|
3938
|
+
line-height: 1.5rem;
|
3939
|
+
--tw-shadow: 0 0 #0000;
|
3940
|
+
}
|
3941
|
+
[type=text]:focus,
|
3942
|
+
[type=email]:focus,
|
3943
|
+
[type=url]:focus,
|
3944
|
+
[type=password]:focus,
|
3945
|
+
[type=number]:focus,
|
3946
|
+
[type=date]:focus,
|
3947
|
+
[type=datetime-local]:focus,
|
3948
|
+
[type=month]:focus,
|
3949
|
+
[type=search]:focus,
|
3950
|
+
[type=tel]:focus,
|
3951
|
+
[type=time]:focus,
|
3952
|
+
[type=week]:focus,
|
3953
|
+
[multiple]:focus,
|
3954
|
+
textarea:focus,
|
3955
|
+
select:focus {
|
3956
|
+
outline: 2px solid transparent;
|
3957
|
+
outline-offset: 2px;
|
3958
|
+
--tw-ring-inset: var(--tw-empty, );
|
3959
|
+
--tw-ring-offset-width: 0px;
|
3960
|
+
--tw-ring-offset-color: #fff;
|
3961
|
+
--tw-ring-color: #1C64F2;
|
3962
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
3963
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
3964
|
+
box-shadow:
|
3965
|
+
var(--tw-ring-offset-shadow),
|
3966
|
+
var(--tw-ring-shadow),
|
3967
|
+
var(--tw-shadow);
|
3968
|
+
border-color: #1C64F2;
|
3969
|
+
}
|
3970
|
+
input::placeholder,
|
3971
|
+
textarea::placeholder {
|
3972
|
+
color: #6B7280;
|
3973
|
+
opacity: 1;
|
3974
|
+
}
|
3975
|
+
::-webkit-datetime-edit-fields-wrapper {
|
3976
|
+
padding: 0;
|
3977
|
+
}
|
3978
|
+
::-webkit-date-and-time-value {
|
3979
|
+
min-height: 1.5em;
|
3980
|
+
}
|
3981
|
+
select:not([size]) {
|
3982
|
+
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
3983
|
+
background-position: right 0.5rem center;
|
3984
|
+
background-repeat: no-repeat;
|
3985
|
+
background-size: 1.5em 1.5em;
|
3986
|
+
padding-right: 2.5rem;
|
3987
|
+
print-color-adjust: exact;
|
3988
|
+
}
|
3989
|
+
[multiple] {
|
3990
|
+
background-image: initial;
|
3991
|
+
background-position: initial;
|
3992
|
+
background-repeat: unset;
|
3993
|
+
background-size: initial;
|
3994
|
+
padding-right: 0.75rem;
|
3995
|
+
print-color-adjust: unset;
|
3996
|
+
}
|
3997
|
+
[type=checkbox],
|
3998
|
+
[type=radio] {
|
3999
|
+
appearance: none;
|
4000
|
+
padding: 0;
|
4001
|
+
print-color-adjust: exact;
|
4002
|
+
display: inline-block;
|
4003
|
+
vertical-align: middle;
|
4004
|
+
background-origin: border-box;
|
4005
|
+
user-select: none;
|
4006
|
+
flex-shrink: 0;
|
4007
|
+
height: 1rem;
|
4008
|
+
width: 1rem;
|
4009
|
+
color: #1C64F2;
|
4010
|
+
background-color: #fff;
|
4011
|
+
border-color: #6B7280;
|
4012
|
+
border-width: 1px;
|
4013
|
+
--tw-shadow: 0 0 #0000;
|
4014
|
+
}
|
4015
|
+
[type=checkbox] {
|
4016
|
+
border-radius: 0px;
|
4017
|
+
}
|
4018
|
+
[type=radio] {
|
4019
|
+
border-radius: 100%;
|
4020
|
+
}
|
4021
|
+
[type=checkbox]:focus,
|
4022
|
+
[type=radio]:focus {
|
4023
|
+
outline: 2px solid transparent;
|
4024
|
+
outline-offset: 2px;
|
4025
|
+
--tw-ring-inset: var(--tw-empty, );
|
4026
|
+
--tw-ring-offset-width: 2px;
|
4027
|
+
--tw-ring-offset-color: #fff;
|
4028
|
+
--tw-ring-color: #1C64F2;
|
4029
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
4030
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
4031
|
+
box-shadow:
|
4032
|
+
var(--tw-ring-offset-shadow),
|
4033
|
+
var(--tw-ring-shadow),
|
4034
|
+
var(--tw-shadow);
|
4035
|
+
}
|
4036
|
+
[type=checkbox]:checked,
|
4037
|
+
[type=radio]:checked,
|
4038
|
+
.dark [type=checkbox]:checked,
|
4039
|
+
.dark [type=radio]:checked {
|
4040
|
+
border-color: transparent;
|
4041
|
+
background-color: currentColor;
|
4042
|
+
background-size: 100% 100%;
|
4043
|
+
background-position: center;
|
4044
|
+
background-repeat: no-repeat;
|
4045
|
+
}
|
4046
|
+
[type=checkbox]:checked {
|
4047
|
+
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
4048
|
+
}
|
4049
|
+
[type=radio]:checked {
|
4050
|
+
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
4051
|
+
}
|
4052
|
+
[type=checkbox]:indeterminate {
|
4053
|
+
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
4054
|
+
border-color: transparent;
|
4055
|
+
background-color: currentColor;
|
4056
|
+
background-size: 100% 100%;
|
4057
|
+
background-position: center;
|
4058
|
+
background-repeat: no-repeat;
|
4059
|
+
}
|
4060
|
+
[type=checkbox]:indeterminate:hover,
|
4061
|
+
[type=checkbox]:indeterminate:focus {
|
4062
|
+
border-color: transparent;
|
4063
|
+
background-color: currentColor;
|
4064
|
+
}
|
4065
|
+
[type=file] {
|
4066
|
+
background: unset;
|
4067
|
+
border-color: inherit;
|
4068
|
+
border-width: 0;
|
4069
|
+
border-radius: 0;
|
4070
|
+
padding: 0;
|
4071
|
+
font-size: unset;
|
4072
|
+
line-height: inherit;
|
4073
|
+
}
|
4074
|
+
[type=file]:focus {
|
4075
|
+
outline: 1px auto inherit;
|
4076
|
+
}
|
4077
|
+
input[type=file]::file-selector-button {
|
4078
|
+
color: white;
|
4079
|
+
background: #1F2937;
|
4080
|
+
border: 0;
|
4081
|
+
font-weight: 500;
|
4082
|
+
font-size: 0.8125rem;
|
4083
|
+
cursor: pointer;
|
4084
|
+
padding-top: 0.625rem;
|
4085
|
+
padding-bottom: 0.625rem;
|
4086
|
+
padding-left: 2rem;
|
4087
|
+
padding-right: 1rem;
|
4088
|
+
margin-inline-start: -1rem;
|
4089
|
+
margin-inline-end: 1rem;
|
4090
|
+
}
|
4091
|
+
input[type=file]::file-selector-button:hover {
|
4092
|
+
background: #374151;
|
4093
|
+
}
|
4094
|
+
input[type=range]::-webkit-slider-thumb {
|
4095
|
+
height: 1.25rem;
|
4096
|
+
width: 1.25rem;
|
4097
|
+
background: #1C64F2;
|
4098
|
+
border-radius: 9999px;
|
4099
|
+
border: 0;
|
4100
|
+
appearance: none;
|
4101
|
+
-moz-appearance: none;
|
4102
|
+
-webkit-appearance: none;
|
4103
|
+
cursor: pointer;
|
4104
|
+
}
|
4105
|
+
input[type=range]:disabled::-webkit-slider-thumb {
|
4106
|
+
background: #9CA3AF;
|
4107
|
+
}
|
4108
|
+
input[type=range]:focus::-webkit-slider-thumb {
|
4109
|
+
outline: 2px solid transparent;
|
4110
|
+
outline-offset: 2px;
|
4111
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
4112
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
4113
|
+
box-shadow:
|
4114
|
+
var(--tw-ring-offset-shadow),
|
4115
|
+
var(--tw-ring-shadow),
|
4116
|
+
var(--tw-shadow, 0 0 #0000);
|
4117
|
+
--tw-ring-opacity: 1px;
|
4118
|
+
--tw-ring-color: rgb(164 202 254 / var(--tw-ring-opacity));
|
4119
|
+
}
|
4120
|
+
input[type=range]::-moz-range-thumb {
|
4121
|
+
height: 1.25rem;
|
4122
|
+
width: 1.25rem;
|
4123
|
+
background: #1C64F2;
|
4124
|
+
border-radius: 9999px;
|
4125
|
+
border: 0;
|
4126
|
+
appearance: none;
|
4127
|
+
-moz-appearance: none;
|
4128
|
+
-webkit-appearance: none;
|
4129
|
+
cursor: pointer;
|
4130
|
+
}
|
4131
|
+
input[type=range]:disabled::-moz-range-thumb {
|
4132
|
+
background: #9CA3AF;
|
4133
|
+
}
|
4134
|
+
input[type=range]::-moz-range-progress {
|
4135
|
+
background: #3F83F8;
|
4136
|
+
}
|
4137
|
+
input[type=range]::-ms-fill-lower {
|
4138
|
+
background: #3F83F8;
|
4139
|
+
}
|
4140
|
+
[data-popper-arrow],
|
4141
|
+
[data-popper-arrow]:before {
|
4142
|
+
position: absolute;
|
4143
|
+
width: 8px;
|
4144
|
+
height: 8px;
|
4145
|
+
background: inherit;
|
4146
|
+
}
|
4147
|
+
[data-popper-arrow] {
|
4148
|
+
visibility: hidden;
|
4149
|
+
}
|
4150
|
+
[data-popper-arrow]:before {
|
4151
|
+
content: "";
|
4152
|
+
visibility: visible;
|
4153
|
+
transform: rotate(45deg);
|
4154
|
+
}
|
4155
|
+
[data-popper-arrow]:after {
|
4156
|
+
content: "";
|
4157
|
+
visibility: visible;
|
4158
|
+
transform: rotate(45deg);
|
4159
|
+
position: absolute;
|
4160
|
+
width: 9px;
|
4161
|
+
height: 9px;
|
4162
|
+
background: inherit;
|
4163
|
+
}
|
4164
|
+
[role=tooltip] > [data-popper-arrow]:before {
|
4165
|
+
border-style: solid;
|
4166
|
+
border-color: #e5e7eb;
|
4167
|
+
}
|
4168
|
+
[role=tooltip] > [data-popper-arrow]:after {
|
4169
|
+
border-style: solid;
|
4170
|
+
border-color: #e5e7eb;
|
4171
|
+
}
|
4172
|
+
[data-popover][role=tooltip][data-popper-placement^=top] > [data-popper-arrow]:before {
|
4173
|
+
border-bottom-width: 1px;
|
4174
|
+
border-right-width: 1px;
|
4175
|
+
}
|
4176
|
+
[data-popover][role=tooltip][data-popper-placement^=top] > [data-popper-arrow]:after {
|
4177
|
+
border-bottom-width: 1px;
|
4178
|
+
border-right-width: 1px;
|
4179
|
+
}
|
4180
|
+
[data-popover][role=tooltip][data-popper-placement^=right] > [data-popper-arrow]:before {
|
4181
|
+
border-bottom-width: 1px;
|
4182
|
+
border-left-width: 1px;
|
4183
|
+
}
|
4184
|
+
[data-popover][role=tooltip][data-popper-placement^=right] > [data-popper-arrow]:after {
|
4185
|
+
border-bottom-width: 1px;
|
4186
|
+
border-left-width: 1px;
|
4187
|
+
}
|
4188
|
+
[data-popover][role=tooltip][data-popper-placement^=bottom] > [data-popper-arrow]:before {
|
4189
|
+
border-top-width: 1px;
|
4190
|
+
border-left-width: 1px;
|
4191
|
+
}
|
4192
|
+
[data-popover][role=tooltip][data-popper-placement^=bottom] > [data-popper-arrow]:after {
|
4193
|
+
border-top-width: 1px;
|
4194
|
+
border-left-width: 1px;
|
4195
|
+
}
|
4196
|
+
[data-popover][role=tooltip][data-popper-placement^=left] > [data-popper-arrow]:before {
|
4197
|
+
border-top-width: 1px;
|
4198
|
+
border-right-width: 1px;
|
4199
|
+
}
|
4200
|
+
[data-popover][role=tooltip][data-popper-placement^=left] > [data-popper-arrow]:after {
|
4201
|
+
border-top-width: 1px;
|
4202
|
+
border-right-width: 1px;
|
4203
|
+
}
|
4204
|
+
[data-popover][role=tooltip][data-popper-placement^=top] > [data-popper-arrow] {
|
4205
|
+
bottom: -5px;
|
4206
|
+
}
|
4207
|
+
[data-popover][role=tooltip][data-popper-placement^=bottom] > [data-popper-arrow] {
|
4208
|
+
top: -5px;
|
4209
|
+
}
|
4210
|
+
[data-popover][role=tooltip][data-popper-placement^=left] > [data-popper-arrow] {
|
4211
|
+
right: -5px;
|
4212
|
+
}
|
4213
|
+
[data-popover][role=tooltip][data-popper-placement^=right] > [data-popper-arrow] {
|
4214
|
+
left: -5px;
|
4215
|
+
}
|
3913
4216
|
*,
|
3914
4217
|
::before,
|
3915
4218
|
::after {
|
@@ -3934,7 +4237,7 @@ video {
|
|
3934
4237
|
--tw-ring-inset: ;
|
3935
4238
|
--tw-ring-offset-width: 0px;
|
3936
4239
|
--tw-ring-offset-color: #fff;
|
3937
|
-
--tw-ring-color: rgb(
|
4240
|
+
--tw-ring-color: rgb(63 131 248 / 0.5);
|
3938
4241
|
--tw-ring-offset-shadow: 0 0 #0000;
|
3939
4242
|
--tw-ring-shadow: 0 0 #0000;
|
3940
4243
|
--tw-shadow: 0 0 #0000;
|
@@ -3980,7 +4283,7 @@ video {
|
|
3980
4283
|
--tw-ring-inset: ;
|
3981
4284
|
--tw-ring-offset-width: 0px;
|
3982
4285
|
--tw-ring-offset-color: #fff;
|
3983
|
-
--tw-ring-color: rgb(
|
4286
|
+
--tw-ring-color: rgb(63 131 248 / 0.5);
|
3984
4287
|
--tw-ring-offset-shadow: 0 0 #0000;
|
3985
4288
|
--tw-ring-shadow: 0 0 #0000;
|
3986
4289
|
--tw-shadow: 0 0 #0000;
|
@@ -4004,48 +4307,44 @@ video {
|
|
4004
4307
|
--tw-backdrop-saturate: ;
|
4005
4308
|
--tw-backdrop-sepia: ;
|
4006
4309
|
}
|
4007
|
-
.fixed {
|
4008
|
-
position: fixed;
|
4009
|
-
}
|
4010
|
-
.left-20 {
|
4011
|
-
left: 5rem;
|
4012
|
-
}
|
4013
4310
|
.z-10 {
|
4014
4311
|
z-index: 10;
|
4015
4312
|
}
|
4016
|
-
.mt-2 {
|
4017
|
-
margin-top: 0.5rem;
|
4018
|
-
}
|
4019
4313
|
.block {
|
4020
4314
|
display: block;
|
4021
4315
|
}
|
4022
4316
|
.inline {
|
4023
4317
|
display: inline;
|
4024
4318
|
}
|
4025
|
-
.
|
4026
|
-
|
4319
|
+
.hidden {
|
4320
|
+
display: none;
|
4027
4321
|
}
|
4028
|
-
.
|
4029
|
-
|
4322
|
+
.w-169 {
|
4323
|
+
width: 169px;
|
4030
4324
|
}
|
4031
|
-
.
|
4032
|
-
|
4325
|
+
.divide-y > :not([hidden]) ~ :not([hidden]) {
|
4326
|
+
--tw-divide-y-reverse: 0;
|
4327
|
+
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
4328
|
+
border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
|
4329
|
+
}
|
4330
|
+
.divide-gray-100 > :not([hidden]) ~ :not([hidden]) {
|
4331
|
+
--tw-divide-opacity: 1;
|
4332
|
+
border-color: rgb(243 244 246 / var(--tw-divide-opacity));
|
4333
|
+
}
|
4334
|
+
.rounded-lg {
|
4335
|
+
border-radius: 0.5rem;
|
4033
4336
|
}
|
4034
4337
|
.bg-white {
|
4035
4338
|
--tw-bg-opacity: 1;
|
4036
4339
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
4037
4340
|
}
|
4038
|
-
.py-1 {
|
4039
|
-
padding-top: 0.25rem;
|
4040
|
-
padding-bottom: 0.25rem;
|
4041
|
-
}
|
4042
4341
|
.italic {
|
4043
4342
|
font-style: italic;
|
4044
4343
|
}
|
4045
4344
|
.underline {
|
4046
4345
|
text-decoration-line: underline;
|
4047
4346
|
}
|
4048
|
-
.shadow
|
4347
|
+
.shadow {
|
4049
4348
|
--tw-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 12px 4px rgba(0,0,0,0.12);
|
4050
4349
|
--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color), 0 1px 12px 4px var(--tw-shadow-color);
|
4051
4350
|
box-shadow:
|
@@ -4053,6 +4352,9 @@ video {
|
|
4053
4352
|
var(--tw-ring-shadow, 0 0 #0000),
|
4054
4353
|
var(--tw-shadow);
|
4055
4354
|
}
|
4355
|
+
.formatted-text-editor {
|
4356
|
+
font-family: "Open Sans" !important;
|
4357
|
+
}
|
4056
4358
|
.formatted-text-editor.editor-wrapper {
|
4057
4359
|
border-radius: 4px;
|
4058
4360
|
border-width: 2px;
|
@@ -4094,6 +4396,42 @@ video {
|
|
4094
4396
|
var(--tw-ring-shadow, 0 0 #0000),
|
4095
4397
|
var(--tw-shadow);
|
4096
4398
|
}
|
4399
|
+
.remirror-theme h1 {
|
4400
|
+
font-size: 1.625rem;
|
4401
|
+
font-weight: 600;
|
4402
|
+
letter-spacing: -0.2px;
|
4403
|
+
line-height: 2rem;
|
4404
|
+
}
|
4405
|
+
.remirror-theme h2 {
|
4406
|
+
font-size: 1.25rem;
|
4407
|
+
font-weight: 600;
|
4408
|
+
letter-spacing: -0.5px;
|
4409
|
+
line-height: 1.5rem;
|
4410
|
+
}
|
4411
|
+
.remirror-theme h3 {
|
4412
|
+
font-size: 1.125rem;
|
4413
|
+
font-weight: 600;
|
4414
|
+
letter-spacing: -0.2px;
|
4415
|
+
line-height: 1.375rem;
|
4416
|
+
}
|
4417
|
+
.remirror-theme h4 {
|
4418
|
+
font-size: 1rem;
|
4419
|
+
font-weight: 700;
|
4420
|
+
letter-spacing: -0.2px;
|
4421
|
+
line-height: 1.25rem;
|
4422
|
+
}
|
4423
|
+
.remirror-theme h5 {
|
4424
|
+
font-size: 1rem;
|
4425
|
+
font-weight: 600;
|
4426
|
+
letter-spacing: -0.2px;
|
4427
|
+
line-height: 1.25rem;
|
4428
|
+
}
|
4429
|
+
.remirror-theme h6 {
|
4430
|
+
font-size: 0.875rem;
|
4431
|
+
font-weight: 600;
|
4432
|
+
letter-spacing: -0.2px;
|
4433
|
+
line-height: 1.25rem;
|
4434
|
+
}
|
4097
4435
|
.formatted-text-editor .editor-toolbar {
|
4098
4436
|
border-radius: 4px;
|
4099
4437
|
border-width: 2px;
|
@@ -4172,10 +4510,7 @@ video {
|
|
4172
4510
|
--tw-text-opacity: 1;
|
4173
4511
|
color: rgb(7 116 210 / var(--tw-text-opacity));
|
4174
4512
|
}
|
4175
|
-
.toolbar-
|
4176
|
-
align-self: center;
|
4177
|
-
}
|
4178
|
-
.toolbar-dropdown .toolbar-dropdown__button {
|
4513
|
+
.toolbar-dropdown__button {
|
4179
4514
|
font-family:
|
4180
4515
|
Open Sans,
|
4181
4516
|
Arial,
|
@@ -4184,25 +4519,34 @@ video {
|
|
4184
4519
|
font-weight: 600;
|
4185
4520
|
--tw-text-opacity: 1;
|
4186
4521
|
color: rgb(112 112 112 / var(--tw-text-opacity));
|
4522
|
+
align-self: center;
|
4187
4523
|
height: 2rem;
|
4188
4524
|
padding-left: 0.5rem;
|
4189
4525
|
}
|
4190
|
-
.toolbar-
|
4191
|
-
.toolbar-
|
4192
|
-
.toolbar-
|
4526
|
+
.toolbar-dropdown__button:active,
|
4527
|
+
.toolbar-dropdown__button:hover,
|
4528
|
+
.toolbar-dropdown__button:focus {
|
4193
4529
|
background-color: rgba(0, 0, 0, 0.04);
|
4194
4530
|
}
|
4195
|
-
.toolbar-
|
4196
|
-
|
4531
|
+
.toolbar-dropdown__button .toolbar-dropdown__label {
|
4532
|
+
display: inline-flex;
|
4533
|
+
width: 7rem;
|
4197
4534
|
}
|
4198
|
-
.toolbar-
|
4535
|
+
.toolbar-dropdown__button .toolbar-dropdown__icon {
|
4199
4536
|
width: 1rem;
|
4200
4537
|
height: 1.5rem;
|
4201
4538
|
}
|
4539
|
+
.toolbar-dropdown__menu {
|
4540
|
+
inset: 0rem auto auto 1rem !important;
|
4541
|
+
}
|
4202
4542
|
.dropdown-button {
|
4203
|
-
|
4204
|
-
|
4205
|
-
|
4206
|
-
border-radius: 0;
|
4543
|
+
padding: 4px 8px;
|
4544
|
+
color: #707070;
|
4545
|
+
height: 40px;
|
4207
4546
|
width: 100%;
|
4547
|
+
justify-content: space-between;
|
4548
|
+
}
|
4549
|
+
.dark .dark\:bg-gray-700 {
|
4550
|
+
--tw-bg-opacity: 1;
|
4551
|
+
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
4208
4552
|
}
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
2
2
|
import CheckIcon from '@mui/icons-material/Check';
|
3
3
|
const DropdownButton = ({ children, handleOnClick, isDisabled, isActive, label }) => {
|
4
4
|
return (React.createElement("button", { "aria-label": label, title: label, type: "button", onClick: handleOnClick, disabled: isDisabled, className: `btn dropdown-button ${isActive ? 'is-active' : ''}` },
|
5
|
-
children || label,
|
5
|
+
React.createElement("span", null, children || label),
|
6
6
|
isActive && React.createElement(CheckIcon, { className: "dropdown-button-icon" })));
|
7
7
|
};
|
8
8
|
export default DropdownButton;
|
@@ -1,13 +1,12 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { Menu } from '@headlessui/react';
|
3
2
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
3
|
+
import 'flowbite';
|
4
4
|
const ToolbarDropdown = ({ children, label }) => {
|
5
|
-
return (React.createElement(
|
6
|
-
React.createElement("
|
7
|
-
React.createElement(
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
React.createElement("div", { className: "py-1" }, children))));
|
5
|
+
return (React.createElement(React.Fragment, null,
|
6
|
+
React.createElement("button", { id: "dropdownHoverButton", "data-dropdown-toggle": "dropdown", className: "toolbar-dropdown__button", type: "button" },
|
7
|
+
React.createElement("span", { className: "toolbar-dropdown__label" }, label),
|
8
|
+
React.createElement(ExpandMoreIcon, { className: "toolbar-dropdown__icon", "aria-hidden": "true" })),
|
9
|
+
React.createElement("div", { id: "dropdown", className: "toolbar-dropdown__menu z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow w-169 dark:bg-gray-700" },
|
10
|
+
React.createElement("ul", { "aria-labelledby": "dropdownHoverButton" }, children))));
|
12
11
|
};
|
13
12
|
export default ToolbarDropdown;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/formatted-text-editor",
|
3
|
-
"version": "1.12.0-alpha.
|
3
|
+
"version": "1.12.0-alpha.40",
|
4
4
|
"main": "lib/index.js",
|
5
5
|
"types": "lib/index.d.ts",
|
6
6
|
"scripts": {
|
@@ -16,9 +16,9 @@
|
|
16
16
|
"test:e2e": "vite build && vite preview --port 8080 & cypress open"
|
17
17
|
},
|
18
18
|
"dependencies": {
|
19
|
-
"@headlessui/react": "^1.7.10",
|
20
19
|
"@mui/icons-material": "5.11.0",
|
21
|
-
"@remirror/react": "2.0.25"
|
20
|
+
"@remirror/react": "2.0.25",
|
21
|
+
"flowbite": "^1.6.3"
|
22
22
|
},
|
23
23
|
"devDependencies": {
|
24
24
|
"@testing-library/cypress": "9.0.0",
|
@@ -61,5 +61,5 @@
|
|
61
61
|
"volta": {
|
62
62
|
"node": "16.19.0"
|
63
63
|
},
|
64
|
-
"gitHead": "
|
64
|
+
"gitHead": "8db852ade2813dc297b7d0fa4975e0c5a57ac83e"
|
65
65
|
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { Remirror, useRemirror, useRemirrorContext } from '@remirror/react';
|
2
|
+
import React from 'react';
|
3
|
+
import { EditorToolbar } from '../EditorToolbar/EditorToolbar';
|
4
|
+
import { Extensions } from '../Extensions/Extensions';
|
5
|
+
|
6
|
+
type MockEditorProps = {
|
7
|
+
setContent?: any;
|
8
|
+
};
|
9
|
+
|
10
|
+
export const MockEditor = ({ setContent }: MockEditorProps) => {
|
11
|
+
const { manager, state, setState } = useRemirror({
|
12
|
+
extensions: Extensions,
|
13
|
+
selection: 'start',
|
14
|
+
stringHandler: 'html',
|
15
|
+
});
|
16
|
+
|
17
|
+
const Component = () => {
|
18
|
+
setContent && setContent.mockImplementation(useRemirrorContext().setContent);
|
19
|
+
return null;
|
20
|
+
};
|
21
|
+
|
22
|
+
const handleChange = (parameter: { state: any }) => {
|
23
|
+
setState(parameter.state);
|
24
|
+
};
|
25
|
+
|
26
|
+
return (
|
27
|
+
<Remirror
|
28
|
+
manager={manager}
|
29
|
+
onChange={handleChange}
|
30
|
+
placeholder="Write something"
|
31
|
+
label="Text editor"
|
32
|
+
state={state}
|
33
|
+
autoRender="start"
|
34
|
+
>
|
35
|
+
<EditorToolbar manager={manager} />
|
36
|
+
<Component />
|
37
|
+
<EditorToolbar manager={manager} isPopover />
|
38
|
+
</Remirror>
|
39
|
+
);
|
40
|
+
};
|
@@ -1,7 +1,11 @@
|
|
1
|
+
import { jest } from '@jest/globals';
|
1
2
|
import React from 'react';
|
2
|
-
import '@testing-library/
|
3
|
+
import { act, fireEvent, render, screen } from '@testing-library/react';
|
4
|
+
import { MockEditor } from './Editor.mock';
|
3
5
|
import Editor from './Editor';
|
4
|
-
import
|
6
|
+
import '@testing-library/jest-dom';
|
7
|
+
|
8
|
+
const setContent: any = jest.fn();
|
5
9
|
|
6
10
|
describe('Formatted text editor', () => {
|
7
11
|
it('Renders the text editor', () => {
|
@@ -92,7 +96,7 @@ describe('Formatted text editor', () => {
|
|
92
96
|
|
93
97
|
expect(baseElement.querySelector('div.remirror-editor h1')).toBeFalsy();
|
94
98
|
|
95
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
99
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
96
100
|
expect(headingDropdown).toBeTruthy();
|
97
101
|
fireEvent.click(headingDropdown);
|
98
102
|
|
@@ -109,7 +113,7 @@ describe('Formatted text editor', () => {
|
|
109
113
|
|
110
114
|
expect(baseElement.querySelector('div.remirror-editor h2')).toBeFalsy();
|
111
115
|
|
112
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
116
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
113
117
|
expect(headingDropdown).toBeTruthy();
|
114
118
|
fireEvent.click(headingDropdown);
|
115
119
|
|
@@ -126,7 +130,7 @@ describe('Formatted text editor', () => {
|
|
126
130
|
|
127
131
|
expect(baseElement.querySelector('div.remirror-editor h3')).toBeFalsy();
|
128
132
|
|
129
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
133
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
130
134
|
expect(headingDropdown).toBeTruthy();
|
131
135
|
fireEvent.click(headingDropdown);
|
132
136
|
|
@@ -143,7 +147,7 @@ describe('Formatted text editor', () => {
|
|
143
147
|
|
144
148
|
expect(baseElement.querySelector('div.remirror-editor h4')).toBeFalsy();
|
145
149
|
|
146
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
150
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
147
151
|
expect(headingDropdown).toBeTruthy();
|
148
152
|
fireEvent.click(headingDropdown);
|
149
153
|
|
@@ -160,7 +164,7 @@ describe('Formatted text editor', () => {
|
|
160
164
|
|
161
165
|
expect(baseElement.querySelector('div.remirror-editor h5')).toBeFalsy();
|
162
166
|
|
163
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
167
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
164
168
|
expect(headingDropdown).toBeTruthy();
|
165
169
|
fireEvent.click(headingDropdown);
|
166
170
|
|
@@ -177,7 +181,7 @@ describe('Formatted text editor', () => {
|
|
177
181
|
|
178
182
|
expect(baseElement.querySelector('div.remirror-editor h6')).toBeFalsy();
|
179
183
|
|
180
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
184
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
181
185
|
expect(headingDropdown).toBeTruthy();
|
182
186
|
fireEvent.click(headingDropdown);
|
183
187
|
|
@@ -194,7 +198,7 @@ describe('Formatted text editor', () => {
|
|
194
198
|
|
195
199
|
expect(baseElement.querySelector('div.remirror-editor pre')).toBeFalsy();
|
196
200
|
|
197
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
201
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
198
202
|
expect(headingDropdown).toBeTruthy();
|
199
203
|
fireEvent.click(headingDropdown);
|
200
204
|
|
@@ -211,7 +215,7 @@ describe('Formatted text editor', () => {
|
|
211
215
|
|
212
216
|
expect(baseElement.querySelectorAll('div.remirror-editor p')).toHaveLength(1);
|
213
217
|
|
214
|
-
const headingDropdown = baseElement.querySelector('.toolbar-
|
218
|
+
const headingDropdown = baseElement.querySelector('.toolbar-dropdown__button') as HTMLButtonElement;
|
215
219
|
expect(headingDropdown).toBeTruthy();
|
216
220
|
fireEvent.click(headingDropdown);
|
217
221
|
|
@@ -225,4 +229,26 @@ describe('Formatted text editor', () => {
|
|
225
229
|
|
226
230
|
expect(baseElement.querySelectorAll('div.remirror-editor p')).toHaveLength(2);
|
227
231
|
});
|
232
|
+
|
233
|
+
it('Should allow text input & undo input upon clicking undo button', () => {
|
234
|
+
const { baseElement, getByLabelText } = render(<MockEditor setContent={setContent} />);
|
235
|
+
|
236
|
+
const textContent = `This is a string with a random number: ${Math.random() * 9999}`;
|
237
|
+
|
238
|
+
// This sets the content of the text editor
|
239
|
+
act(() => {
|
240
|
+
setContent(`<p>${textContent}</p>`, { triggerChange: true });
|
241
|
+
});
|
242
|
+
|
243
|
+
const editorNode = getByLabelText(`Text editor`);
|
244
|
+
expect(editorNode).toBeTruthy();
|
245
|
+
expect(editorNode.textContent).toBe(textContent);
|
246
|
+
|
247
|
+
// Testing if clicking undo button removes text from editor
|
248
|
+
const undoButton = baseElement.querySelector('button[title="Undo (cmd+Z)"]') as HTMLButtonElement;
|
249
|
+
expect(undoButton).toBeTruthy();
|
250
|
+
fireEvent.click(undoButton);
|
251
|
+
|
252
|
+
expect(editorNode.textContent).toBe('');
|
253
|
+
});
|
228
254
|
});
|
package/src/Editor/Editor.tsx
CHANGED
@@ -1,18 +1,8 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import {
|
3
|
-
BoldExtension,
|
4
|
-
HeadingExtension,
|
5
|
-
ItalicExtension,
|
6
|
-
NodeFormattingExtension,
|
7
|
-
ParagraphExtension,
|
8
|
-
UnderlineExtension,
|
9
|
-
HistoryExtension,
|
10
|
-
wysiwygPreset,
|
11
|
-
} from 'remirror/extensions';
|
12
2
|
import { EditorComponent, Remirror, useRemirror } from '@remirror/react';
|
13
|
-
import { RemirrorContentType
|
3
|
+
import { RemirrorContentType } from '@remirror/core';
|
14
4
|
import { EditorToolbar } from '../EditorToolbar/EditorToolbar';
|
15
|
-
import {
|
5
|
+
import { Extensions } from '../Extensions/Extensions';
|
16
6
|
|
17
7
|
type EditorProps = {
|
18
8
|
content?: RemirrorContentType;
|
@@ -20,17 +10,7 @@ type EditorProps = {
|
|
20
10
|
|
21
11
|
const Editor = ({ content }: EditorProps) => {
|
22
12
|
const { manager, state, setState } = useRemirror({
|
23
|
-
extensions:
|
24
|
-
...(wysiwygPreset() as Extension[]),
|
25
|
-
new BoldExtension(),
|
26
|
-
new HeadingExtension(),
|
27
|
-
new ItalicExtension(),
|
28
|
-
new NodeFormattingExtension(),
|
29
|
-
new ParagraphExtension(),
|
30
|
-
new PreformattedExtension(),
|
31
|
-
new UnderlineExtension(),
|
32
|
-
new HistoryExtension(),
|
33
|
-
],
|
13
|
+
extensions: Extensions,
|
34
14
|
content,
|
35
15
|
selection: 'start',
|
36
16
|
stringHandler: 'html',
|
package/src/Editor/_editor.scss
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
.formatted-text-editor {
|
2
|
+
font-family: 'Open Sans' !important;
|
3
|
+
|
2
4
|
&.editor-wrapper {
|
3
5
|
@apply bg-white rounded border-gray-300 border-2 border-solid;
|
4
6
|
}
|
@@ -29,3 +31,45 @@
|
|
29
31
|
@apply shadow-none;
|
30
32
|
}
|
31
33
|
}
|
34
|
+
|
35
|
+
.remirror-theme h1 {
|
36
|
+
font-size: 1.625rem;
|
37
|
+
font-weight: 600;
|
38
|
+
letter-spacing: -0.2px;
|
39
|
+
line-height: 2rem;
|
40
|
+
}
|
41
|
+
|
42
|
+
.remirror-theme h2 {
|
43
|
+
font-size: 1.25rem;
|
44
|
+
font-weight: 600;
|
45
|
+
letter-spacing: -0.5px;
|
46
|
+
line-height: 1.5rem;
|
47
|
+
}
|
48
|
+
|
49
|
+
.remirror-theme h3 {
|
50
|
+
font-size: 1.125rem;
|
51
|
+
font-weight: 600;
|
52
|
+
letter-spacing: -0.2px;
|
53
|
+
line-height: 1.375rem;
|
54
|
+
}
|
55
|
+
|
56
|
+
.remirror-theme h4 {
|
57
|
+
font-size: 1rem;
|
58
|
+
font-weight: 700;
|
59
|
+
letter-spacing: -0.2px;
|
60
|
+
line-height: 1.25rem;
|
61
|
+
}
|
62
|
+
|
63
|
+
.remirror-theme h5 {
|
64
|
+
font-size: 1rem;
|
65
|
+
font-weight: 600;
|
66
|
+
letter-spacing: -0.2px;
|
67
|
+
line-height: 1.25rem;
|
68
|
+
}
|
69
|
+
|
70
|
+
.remirror-theme h6 {
|
71
|
+
font-size: 0.875rem;
|
72
|
+
font-weight: 600;
|
73
|
+
letter-spacing: -0.2px;
|
74
|
+
line-height: 1.25rem;
|
75
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useCommands, useActive } from '@remirror/react';
|
3
|
-
import { PreformattedExtension } from '../../../../
|
3
|
+
import { PreformattedExtension } from '../../../../Extensions/PreformattedExtension/PreformattedExtension';
|
4
4
|
import DropdownButton from '../../../../ui/DropdownButton/DropdownButton';
|
5
5
|
|
6
6
|
const PreformattedButton = () => {
|
@@ -4,7 +4,7 @@ import ParagraphButton from './Paragraph/ParagraphButton';
|
|
4
4
|
import PreformattedButton from './Preformatted/PreformattedButton';
|
5
5
|
import ToolbarDropdown from '../../../ui/ToolbarDropdown/ToolbarDropdown';
|
6
6
|
import { useActive, VerticalDivider } from '@remirror/react';
|
7
|
-
import { PreformattedExtension } from '../../../
|
7
|
+
import { PreformattedExtension } from '../../../Extensions/PreformattedExtension/PreformattedExtension';
|
8
8
|
|
9
9
|
const TextTypeDropdown = () => {
|
10
10
|
const active = useActive<PreformattedExtension>();
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import {
|
2
|
+
BoldExtension,
|
3
|
+
HeadingExtension,
|
4
|
+
ItalicExtension,
|
5
|
+
NodeFormattingExtension,
|
6
|
+
ParagraphExtension,
|
7
|
+
UnderlineExtension,
|
8
|
+
HistoryExtension,
|
9
|
+
wysiwygPreset,
|
10
|
+
} from 'remirror/extensions';
|
11
|
+
import { PreformattedExtension } from './PreformattedExtension/PreformattedExtension';
|
12
|
+
import { Extension } from '@remirror/core';
|
13
|
+
|
14
|
+
export const Extensions = () => [
|
15
|
+
...(wysiwygPreset() as Extension[]),
|
16
|
+
new BoldExtension(),
|
17
|
+
new HeadingExtension(),
|
18
|
+
new ItalicExtension(),
|
19
|
+
new NodeFormattingExtension(),
|
20
|
+
new ParagraphExtension(),
|
21
|
+
new PreformattedExtension(),
|
22
|
+
new UnderlineExtension(),
|
23
|
+
new HistoryExtension(),
|
24
|
+
];
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { render } from '@testing-library/react';
|
2
|
+
import { FormattedTextEditor } from './';
|
3
|
+
import React from 'react';
|
4
|
+
|
5
|
+
describe('<FormattedTextEditor />', () => {
|
6
|
+
it('should render "<FormattedTextEditor />" component', () => {
|
7
|
+
const { baseElement } = render(<FormattedTextEditor />);
|
8
|
+
expect(baseElement).toBeTruthy();
|
9
|
+
});
|
10
|
+
});
|
@@ -19,7 +19,7 @@ const DropdownButton = ({ children, handleOnClick, isDisabled, isActive, label }
|
|
19
19
|
disabled={isDisabled}
|
20
20
|
className={`btn dropdown-button ${isActive ? 'is-active' : ''}`}
|
21
21
|
>
|
22
|
-
{children || label}
|
22
|
+
<span>{children || label}</span>
|
23
23
|
{isActive && <CheckIcon className="dropdown-button-icon" />}
|
24
24
|
</button>
|
25
25
|
);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { Menu } from '@headlessui/react';
|
3
2
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
3
|
+
import 'flowbite';
|
4
4
|
|
5
5
|
type ToolbarDropdownProps = {
|
6
6
|
children: JSX.Element | JSX.Element[];
|
@@ -9,18 +9,23 @@ type ToolbarDropdownProps = {
|
|
9
9
|
|
10
10
|
const ToolbarDropdown = ({ children, label }: ToolbarDropdownProps) => {
|
11
11
|
return (
|
12
|
-
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
<>
|
13
|
+
<button
|
14
|
+
id="dropdownHoverButton"
|
15
|
+
data-dropdown-toggle="dropdown"
|
16
|
+
className="toolbar-dropdown__button"
|
17
|
+
type="button"
|
18
|
+
>
|
19
|
+
<span className="toolbar-dropdown__label">{label}</span>
|
20
|
+
<ExpandMoreIcon className="toolbar-dropdown__icon" aria-hidden="true" />
|
21
|
+
</button>
|
22
|
+
<div
|
23
|
+
id="dropdown"
|
24
|
+
className="toolbar-dropdown__menu z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow w-169 dark:bg-gray-700"
|
25
|
+
>
|
26
|
+
<ul aria-labelledby="dropdownHoverButton">{children}</ul>
|
18
27
|
</div>
|
19
|
-
|
20
|
-
<Menu.Items className="fixed left-20 z-10 mt-2 w-56 origin-top-right rounded-md bg-white shadow-md ">
|
21
|
-
<div className="py-1">{children}</div>
|
22
|
-
</Menu.Items>
|
23
|
-
</Menu>
|
28
|
+
</>
|
24
29
|
);
|
25
30
|
};
|
26
31
|
|
@@ -1,25 +1,27 @@
|
|
1
|
-
.toolbar-
|
1
|
+
.toolbar-dropdown__button {
|
2
|
+
@apply font-base text-md font-semibold text-gray-600;
|
2
3
|
align-self: center;
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
height: 2rem;
|
6
|
+
padding-left: 0.5rem;
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
&:focus {
|
13
|
-
background-color: rgba(black, 0.04);
|
14
|
-
}
|
8
|
+
&:active,
|
9
|
+
&:hover,
|
10
|
+
&:focus {
|
11
|
+
background-color: rgba(black, 0.04);
|
12
|
+
}
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
.toolbar-dropdown__label {
|
15
|
+
display: inline-flex;
|
16
|
+
width: 7rem;
|
17
|
+
}
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
}
|
19
|
+
.toolbar-dropdown__icon {
|
20
|
+
width: 1rem;
|
21
|
+
height: 1.5rem;
|
24
22
|
}
|
25
23
|
}
|
24
|
+
|
25
|
+
.toolbar-dropdown__menu {
|
26
|
+
inset: 0rem auto auto 1rem !important;
|
27
|
+
}
|
package/tailwind.config.cjs
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/** @type {import('tailwindcss').Config} */
|
2
2
|
module.exports = {
|
3
|
-
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
3
|
+
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}', './node_modules/flowbite/**/*.js'],
|
4
4
|
theme: {
|
5
5
|
extend: {
|
6
6
|
borderRadius: {
|
@@ -40,6 +40,7 @@ module.exports = {
|
|
40
40
|
6: '1.5rem', // 24px
|
41
41
|
7: '1.75rem', // 28px
|
42
42
|
8: '2rem', // 32px
|
43
|
+
169: '169px', // 169px
|
43
44
|
},
|
44
45
|
colors: {
|
45
46
|
gray: {
|
@@ -57,5 +58,5 @@ module.exports = {
|
|
57
58
|
},
|
58
59
|
},
|
59
60
|
},
|
60
|
-
plugins: [],
|
61
|
+
plugins: [require('flowbite/plugin')],
|
61
62
|
};
|