@centreon/ui 23.10.119 → 23.10.120
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/package.json +16 -12
- package/src/Button/Save/StartIcon.tsx +3 -3
- package/src/Dashboard/Item.tsx +1 -1
- package/src/Dashboard/Layout.tsx +2 -2
- package/src/FileDropZone/index.tsx +3 -1
- package/src/Form/Inputs/CheckboxGroup.tsx +1 -4
- package/src/Form/Inputs/index.tsx +1 -1
- package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
- package/src/Graph/LineChart/BasicComponents/Lines/Threshold/index.tsx +5 -4
- package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
- package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
- package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
- package/src/Graph/LineChart/InteractiveComponents/Annotations/Annotation/index.tsx +2 -3
- package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
- package/src/Graph/LineChart/Legend/useLegend.ts +5 -5
- package/src/Graph/LineChart/LineChart.tsx +5 -2
- package/src/Graph/LineChart/helpers/doc.ts +16 -13
- package/src/Graph/LineChart/helpers/index.ts +1 -1
- package/src/Graph/LineChart/index.stories.tsx +1 -2
- package/src/Graph/SingleBar/Thresholds.tsx +2 -2
- package/src/Graph/Text/Text.stories.tsx +60 -4
- package/src/Graph/common/timeSeries/index.ts +3 -3
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +10 -7
- package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
- package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
- package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
- package/src/InputField/Select/IconPopover/index.tsx +2 -2
- package/src/InputField/Select/index.tsx +1 -1
- package/src/Listing/Header/ListingHeader.tsx +1 -1
- package/src/Listing/index.stories.tsx +12 -1
- package/src/Listing/index.tsx +1 -1
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +100 -52
- package/src/RichTextEditor/RichTextEditor.tsx +21 -4
- package/src/RichTextEditor/plugins/ToolbarPlugin/AlignPicker.tsx +21 -20
- package/src/RichTextEditor/plugins/ToolbarPlugin/BlockButtons.tsx +35 -77
- package/src/RichTextEditor/plugins/ToolbarPlugin/FormatButtons.tsx +29 -83
- package/src/RichTextEditor/plugins/ToolbarPlugin/LinkButton.tsx +106 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/ListButton.tsx +155 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/MacrosButton.tsx +23 -39
- package/src/RichTextEditor/plugins/ToolbarPlugin/ToolbarPlugin.styles.ts +24 -14
- package/src/RichTextEditor/plugins/ToolbarPlugin/UndoRedoButtons.tsx +6 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/index.tsx +5 -10
- package/src/RichTextEditor/translatedLabels.ts +3 -0
- package/src/SortableItems/index.tsx +2 -7
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -3
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -2
- package/src/TimePeriods/DateTimePickerInput.tsx +45 -17
- package/src/TimePeriods/TimePeriods.cypress.spec.tsx +9 -33
- package/src/TimePeriods/helpers/index.ts +1 -1
- package/src/TimePeriods/index.tsx +2 -2
- package/src/api/QueryProvider.tsx +1 -1
- package/src/api/TestQueryProvider.tsx +1 -1
- package/src/api/useFetchQuery/index.ts +28 -24
- package/src/api/useMutationQuery/index.ts +39 -17
- package/src/components/DataTable/Item/DataTableItem.tsx +2 -2
- package/src/components/Form/AccessRights/__fixtures__/contactAccessRight.mock.ts +2 -0
- package/src/components/Form/AccessRights/useAccessRightsForm.utils.ts +1 -1
- package/src/components/Form/Dashboard/DashboardForm.tsx +15 -12
- package/src/components/ItemComposition/ItemComposition.tsx +4 -2
- package/src/components/Menu/Button/MenuButton.tsx +4 -2
- package/src/components/Menu/MenuItem.tsx +5 -3
- package/src/components/Menu/MenuItems.tsx +4 -3
- package/src/index.ts +1 -0
- package/src/queryParameters/url/index.ts +5 -1
- package/src/utils/index.ts +0 -1
- package/src/utils/{useLicenseExpirationWarning.cypress.spec.tsx → useLicenseExpirationWarning.test.tsx} +48 -37
- package/src/utils/useLicenseExpirationWarning.ts +18 -18
- package/src/screens/dashboard/DashboardsDetail.stories.tsx +0 -108
- package/src/screens/dashboard/DashboardsOverview.stories.tsx +0 -281
- package/src/utils/useDateTimePickerAdapter.ts +0 -309
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import RichTextEditor from './RichTextEditor';
|
|
2
2
|
import { standardMacros } from './plugins/ToolbarPlugin/MacrosButton';
|
|
3
|
+
import { labelAlignPicker } from './translatedLabels';
|
|
3
4
|
|
|
4
5
|
interface CheckElementStyleOnRichTextEditorProps {
|
|
5
6
|
check: boolean;
|
|
@@ -47,16 +48,30 @@ describe('Rich Text Editor', () => {
|
|
|
47
48
|
it('displays all elements when RichTextEditor is called with required props', () => {
|
|
48
49
|
cy.findByLabelText('Undo').should('be.visible');
|
|
49
50
|
cy.findByLabelText('Redo').should('be.visible');
|
|
50
|
-
cy.findByLabelText('
|
|
51
|
-
cy.findByLabelText('
|
|
52
|
-
cy.findByLabelText('
|
|
53
|
-
cy.findByLabelText('strikethrough').should('be.visible');
|
|
51
|
+
cy.findByLabelText('align picker').should('be.visible');
|
|
52
|
+
cy.findByLabelText('block').should('be.visible');
|
|
53
|
+
cy.findByLabelText('format').should('be.visible');
|
|
54
54
|
cy.findByLabelText('link').should('be.visible');
|
|
55
|
+
cy.findByLabelText('list').should('be.visible');
|
|
56
|
+
|
|
55
57
|
cy.findByLabelText('RichTextEditor')
|
|
56
58
|
.should('be.visible')
|
|
57
59
|
.and('have.value', '');
|
|
58
60
|
|
|
59
61
|
cy.findByLabelText('RichTextEditor').parent().contains('Type here...');
|
|
62
|
+
|
|
63
|
+
cy.makeSnapshot();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('displays all format actions when the format button is clicked', () => {
|
|
67
|
+
cy.findByLabelText('format').click();
|
|
68
|
+
|
|
69
|
+
cy.findByLabelText('bold').should('be.visible');
|
|
70
|
+
cy.findByLabelText('italic').should('be.visible');
|
|
71
|
+
cy.findByLabelText('underline').should('be.visible');
|
|
72
|
+
cy.findByLabelText('strikethrough').should('be.visible');
|
|
73
|
+
|
|
74
|
+
cy.makeSnapshot();
|
|
60
75
|
});
|
|
61
76
|
|
|
62
77
|
it('displays changes with undo redo buttons', () => {
|
|
@@ -80,21 +95,36 @@ describe('Rich Text Editor', () => {
|
|
|
80
95
|
|
|
81
96
|
it('displays changes with bold, italic, underline and strikethrough buttons', () => {
|
|
82
97
|
cy.get('[data-testid="RichTextEditor"]').type('cypress test');
|
|
98
|
+
|
|
83
99
|
cy.get('[data-testid="RichTextEditor"]').focus().type('{selectAll}');
|
|
84
100
|
|
|
85
|
-
cy.
|
|
86
|
-
cy.
|
|
87
|
-
|
|
88
|
-
cy.
|
|
101
|
+
cy.findByLabelText('format').click();
|
|
102
|
+
cy.findByLabelText('bold').click();
|
|
103
|
+
|
|
104
|
+
cy.findByLabelText('format').click();
|
|
105
|
+
cy.findByLabelText('italic').click();
|
|
106
|
+
|
|
107
|
+
cy.findByLabelText('format').click();
|
|
108
|
+
cy.findByLabelText('underline').click();
|
|
109
|
+
|
|
110
|
+
cy.findByLabelText('format').click();
|
|
111
|
+
cy.findByLabelText('strikethrough').click();
|
|
89
112
|
|
|
90
113
|
cy.findByTestId('RichTextEditor').then((element: HTMLElement) => {
|
|
91
114
|
checkElementStyleOnRichTextEditor({ check: true, element });
|
|
92
115
|
});
|
|
93
116
|
|
|
94
|
-
cy.
|
|
95
|
-
cy.
|
|
96
|
-
|
|
97
|
-
cy.
|
|
117
|
+
cy.findByLabelText('format').click();
|
|
118
|
+
cy.findByLabelText('bold').click();
|
|
119
|
+
|
|
120
|
+
cy.findByLabelText('format').click();
|
|
121
|
+
cy.findByLabelText('italic').click();
|
|
122
|
+
|
|
123
|
+
cy.findByLabelText('format').click();
|
|
124
|
+
cy.findByLabelText('underline').click();
|
|
125
|
+
|
|
126
|
+
cy.findByLabelText('format').click();
|
|
127
|
+
cy.findByLabelText('strikethrough').click();
|
|
98
128
|
|
|
99
129
|
cy.findByTestId('RichTextEditor').then((element: HTMLElement) => {
|
|
100
130
|
checkElementStyleOnRichTextEditor({ check: false, element });
|
|
@@ -105,7 +135,7 @@ describe('Rich Text Editor', () => {
|
|
|
105
135
|
cy.get('[data-testid="RichTextEditor"]').type('cypress');
|
|
106
136
|
cy.get('[data-testid="RichTextEditor"]').focus().type('{selectAll}');
|
|
107
137
|
|
|
108
|
-
cy.
|
|
138
|
+
cy.findByLabelText('link').click();
|
|
109
139
|
|
|
110
140
|
cy.findByLabelText('Saved link').should('have.text', 'https://');
|
|
111
141
|
|
|
@@ -130,7 +160,7 @@ describe('Rich Text Editor', () => {
|
|
|
130
160
|
|
|
131
161
|
cy.get('[data-testid="RichTextEditor"]').focus().type('{selectAll}');
|
|
132
162
|
|
|
133
|
-
cy.
|
|
163
|
+
cy.findByLabelText('link').click();
|
|
134
164
|
|
|
135
165
|
cy.findByText('cypress')
|
|
136
166
|
.parent()
|
|
@@ -153,7 +183,7 @@ describe('Rich Text Editor', () => {
|
|
|
153
183
|
cy.get('[data-testid="RichTextEditor"]').type('cypress');
|
|
154
184
|
cy.get('[data-testid="RichTextEditor"]').focus().type('{selectAll}');
|
|
155
185
|
|
|
156
|
-
cy.
|
|
186
|
+
cy.findByLabelText('link').click();
|
|
157
187
|
|
|
158
188
|
cy.findByLabelText('Saved link').should('have.text', 'https://');
|
|
159
189
|
|
|
@@ -189,11 +219,11 @@ describe('Rich Text Editor', () => {
|
|
|
189
219
|
it('displays editor when editable props is false and an initialState exist', () => {
|
|
190
220
|
cy.findByLabelText('Undo').should('not.exist');
|
|
191
221
|
cy.findByLabelText('Redo').should('not.exist');
|
|
192
|
-
cy.findByLabelText(
|
|
193
|
-
cy.findByLabelText('
|
|
194
|
-
cy.findByLabelText('
|
|
195
|
-
cy.findByLabelText('strikethrough').should('not.exist');
|
|
222
|
+
cy.findByLabelText(labelAlignPicker).should('not.exist');
|
|
223
|
+
cy.findByLabelText('block').should('not.exist');
|
|
224
|
+
cy.findByLabelText('format').should('not.exist');
|
|
196
225
|
cy.findByLabelText('link').should('not.exist');
|
|
226
|
+
cy.findByLabelText('list').should('not.exist');
|
|
197
227
|
});
|
|
198
228
|
});
|
|
199
229
|
|
|
@@ -213,11 +243,11 @@ describe('Rich Text Editor', () => {
|
|
|
213
243
|
it('displays editor when editable props is false and an initialState exist', () => {
|
|
214
244
|
cy.findByLabelText('Undo').should('be.disabled');
|
|
215
245
|
cy.findByLabelText('Redo').should('be.disabled');
|
|
216
|
-
cy.findByLabelText(
|
|
217
|
-
cy.findByLabelText('
|
|
218
|
-
cy.findByLabelText('
|
|
219
|
-
cy.findByLabelText('strikethrough').should('be.disabled');
|
|
246
|
+
cy.findByLabelText(labelAlignPicker).should('be.disabled');
|
|
247
|
+
cy.findByLabelText('block').should('be.disabled');
|
|
248
|
+
cy.findByLabelText('format').should('be.disabled');
|
|
220
249
|
cy.findByLabelText('link').should('be.disabled');
|
|
250
|
+
cy.findByLabelText('list').should('be.disabled');
|
|
221
251
|
});
|
|
222
252
|
});
|
|
223
253
|
|
|
@@ -262,7 +292,6 @@ describe('Rich Text Editor', () => {
|
|
|
262
292
|
});
|
|
263
293
|
|
|
264
294
|
it('displays the Macros button when the "displayMacrosButton" prop is set to true', () => {
|
|
265
|
-
cy.findByLabelText('Macros').should('be.visible');
|
|
266
295
|
cy.findByLabelText('Macros').click();
|
|
267
296
|
|
|
268
297
|
standardMacros.forEach((macro) => {
|
|
@@ -273,10 +302,10 @@ describe('Rich Text Editor', () => {
|
|
|
273
302
|
it('ensures that the selected macro is inserted into the RichTextEditor', () => {
|
|
274
303
|
cy.get('[data-testid="RichTextEditor"]').type('macro : ');
|
|
275
304
|
|
|
276
|
-
cy.findByLabelText('Macros').click({});
|
|
277
|
-
|
|
278
305
|
standardMacros.forEach((macro) => {
|
|
279
|
-
cy.
|
|
306
|
+
cy.findByLabelText('Macros').click();
|
|
307
|
+
cy.findByText(macro).click();
|
|
308
|
+
|
|
280
309
|
cy.get('[data-testid="RichTextEditor"]').should('contain', macro);
|
|
281
310
|
});
|
|
282
311
|
});
|
|
@@ -291,44 +320,59 @@ describe('Rich Text Editor', () => {
|
|
|
291
320
|
|
|
292
321
|
const testCases = [
|
|
293
322
|
{
|
|
294
|
-
blockType: '
|
|
295
|
-
tag: 'h1'
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
blockType: 'Heading 2',
|
|
299
|
-
tag: 'h2'
|
|
300
|
-
},
|
|
301
|
-
{
|
|
302
|
-
blockType: 'Heading 3',
|
|
323
|
+
blockType: 'Huge',
|
|
303
324
|
tag: 'h3'
|
|
304
325
|
},
|
|
305
326
|
{
|
|
306
|
-
blockType: '
|
|
307
|
-
tag: '
|
|
327
|
+
blockType: 'Large',
|
|
328
|
+
tag: 'h5'
|
|
308
329
|
},
|
|
309
330
|
{
|
|
310
|
-
blockType: '
|
|
311
|
-
tag: '
|
|
331
|
+
blockType: 'Normal',
|
|
332
|
+
tag: 'p'
|
|
312
333
|
},
|
|
313
334
|
{
|
|
314
|
-
blockType: '
|
|
335
|
+
blockType: 'Small',
|
|
315
336
|
tag: 'h6'
|
|
316
|
-
}
|
|
337
|
+
}
|
|
338
|
+
];
|
|
339
|
+
|
|
340
|
+
testCases.forEach(({ blockType, tag }) => {
|
|
341
|
+
it(`displays ${blockType} when the corresponding block type button is selected`, () => {
|
|
342
|
+
cy.get('[data-testid="RichTextEditor"]').type('Example');
|
|
343
|
+
cy.findByLabelText('block').click();
|
|
344
|
+
cy.findByText(blockType).click();
|
|
345
|
+
|
|
346
|
+
cy.get('[data-testid="RichTextEditor"]').find(tag).should('be.visible');
|
|
347
|
+
|
|
348
|
+
cy.makeSnapshot();
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
describe('List type', () => {
|
|
354
|
+
beforeEach(() => {
|
|
355
|
+
cy.mount({
|
|
356
|
+
Component: <RichTextEditor editable />
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
const testCases = [
|
|
317
361
|
{
|
|
318
|
-
|
|
362
|
+
listType: 'Unordered List',
|
|
319
363
|
tag: 'ul'
|
|
320
364
|
},
|
|
321
365
|
{
|
|
322
|
-
|
|
366
|
+
listType: 'Ordered List',
|
|
323
367
|
tag: 'ol'
|
|
324
368
|
}
|
|
325
369
|
];
|
|
326
370
|
|
|
327
|
-
testCases.forEach(({
|
|
328
|
-
it(`displays ${
|
|
371
|
+
testCases.forEach(({ listType, tag }) => {
|
|
372
|
+
it(`displays ${listType} when the corresponding list type button is selected`, () => {
|
|
329
373
|
cy.get('[data-testid="RichTextEditor"]').type('Example');
|
|
330
|
-
cy.
|
|
331
|
-
cy.
|
|
374
|
+
cy.findByLabelText('list').click();
|
|
375
|
+
cy.findByLabelText(listType).click();
|
|
332
376
|
|
|
333
377
|
cy.get('[data-testid="RichTextEditor"]').find(tag).should('be.visible');
|
|
334
378
|
|
|
@@ -344,14 +388,18 @@ describe('Rich Text Editor', () => {
|
|
|
344
388
|
});
|
|
345
389
|
});
|
|
346
390
|
|
|
347
|
-
const testCases = ['Center', 'Right'];
|
|
391
|
+
const testCases = ['Center', 'Right', 'Left'];
|
|
348
392
|
|
|
349
393
|
testCases.forEach((label) => {
|
|
350
|
-
it(`aligns the text to the ${label} when the corresponding button
|
|
394
|
+
it(`aligns the text to the ${label} when the corresponding button was clicked`, () => {
|
|
351
395
|
cy.get('[data-testid="RichTextEditor"]').type('Example');
|
|
352
396
|
|
|
353
|
-
cy.findByLabelText(
|
|
354
|
-
cy.
|
|
397
|
+
cy.findByLabelText(labelAlignPicker).click();
|
|
398
|
+
cy.findByLabelText(label).click();
|
|
399
|
+
|
|
400
|
+
cy.findByText('Example')
|
|
401
|
+
.parent()
|
|
402
|
+
.should('have.css', 'text-align', label.toLowerCase());
|
|
355
403
|
|
|
356
404
|
cy.makeSnapshot();
|
|
357
405
|
});
|
|
@@ -12,6 +12,7 @@ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
|
|
|
12
12
|
import { equals } from 'ramda';
|
|
13
13
|
import { ListPlugin } from '@lexical/react/LexicalListPlugin';
|
|
14
14
|
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
|
|
15
|
+
import { $generateHtmlFromNodes } from '@lexical/html';
|
|
15
16
|
|
|
16
17
|
import { Typography } from '@mui/material';
|
|
17
18
|
|
|
@@ -38,6 +39,7 @@ export interface RichTextEditorProps {
|
|
|
38
39
|
openLinkInNewTab?: boolean;
|
|
39
40
|
placeholder?: string;
|
|
40
41
|
resetEditorToInitialStateCondition?: () => boolean;
|
|
42
|
+
setHtmlString?: (htmlString: string) => void;
|
|
41
43
|
toolbarClassName?: string;
|
|
42
44
|
toolbarPositions?: 'start' | 'end';
|
|
43
45
|
}
|
|
@@ -92,9 +94,9 @@ const useStyles = makeStyles<{ toolbarPositions: 'start' | 'end' }>()(
|
|
|
92
94
|
lineHeight: theme.typography.h5.lineHeight
|
|
93
95
|
},
|
|
94
96
|
h6: {
|
|
95
|
-
fontSize: theme.typography.
|
|
96
|
-
fontWeight: theme.typography.
|
|
97
|
-
lineHeight: theme.typography.
|
|
97
|
+
fontSize: theme.typography.body2.fontSize,
|
|
98
|
+
fontWeight: theme.typography.body2.fontWeight,
|
|
99
|
+
lineHeight: theme.typography.body2.lineHeight
|
|
98
100
|
},
|
|
99
101
|
italic: {
|
|
100
102
|
fontStyle: 'italic'
|
|
@@ -102,6 +104,11 @@ const useStyles = makeStyles<{ toolbarPositions: 'start' | 'end' }>()(
|
|
|
102
104
|
link: {
|
|
103
105
|
color: theme.palette.primary.main
|
|
104
106
|
},
|
|
107
|
+
paragraph: {
|
|
108
|
+
fontSize: theme.typography.body1.fontSize,
|
|
109
|
+
fontWeight: theme.typography.body1.fontWeight,
|
|
110
|
+
lineHeight: theme.typography.body1.lineHeight
|
|
111
|
+
},
|
|
105
112
|
strikethrough: {
|
|
106
113
|
textDecoration: 'line-through'
|
|
107
114
|
},
|
|
@@ -138,6 +145,7 @@ const RichTextEditor = ({
|
|
|
138
145
|
openLinkInNewTab = true,
|
|
139
146
|
initialize,
|
|
140
147
|
displayBlockButtons = true,
|
|
148
|
+
setHtmlString,
|
|
141
149
|
toolbarClassName
|
|
142
150
|
}: RichTextEditorProps): JSX.Element => {
|
|
143
151
|
const { classes } = useStyles({ toolbarPositions });
|
|
@@ -162,6 +170,7 @@ const RichTextEditor = ({
|
|
|
162
170
|
h6: classes.h6
|
|
163
171
|
},
|
|
164
172
|
link: classes.link,
|
|
173
|
+
paragraph: classes.paragraph,
|
|
165
174
|
text: {
|
|
166
175
|
bold: classes.bold,
|
|
167
176
|
italic: classes.italic,
|
|
@@ -172,6 +181,13 @@ const RichTextEditor = ({
|
|
|
172
181
|
}
|
|
173
182
|
};
|
|
174
183
|
|
|
184
|
+
const change = (state: EditorState, editor: LexicalEditor): void => {
|
|
185
|
+
editor.update(() => {
|
|
186
|
+
setHtmlString?.($generateHtmlFromNodes(editor, null));
|
|
187
|
+
});
|
|
188
|
+
getEditorState?.(state, editor);
|
|
189
|
+
};
|
|
190
|
+
|
|
175
191
|
return (
|
|
176
192
|
<LexicalComposer initialConfig={initialConfig}>
|
|
177
193
|
<div className={classes.container}>
|
|
@@ -204,6 +220,7 @@ const RichTextEditor = ({
|
|
|
204
220
|
resetEditorToInitialStateCondition={
|
|
205
221
|
resetEditorToInitialStateCondition
|
|
206
222
|
}
|
|
223
|
+
setHtmlString={setHtmlString}
|
|
207
224
|
onBlur={onBlur}
|
|
208
225
|
/>
|
|
209
226
|
}
|
|
@@ -212,7 +229,7 @@ const RichTextEditor = ({
|
|
|
212
229
|
<HistoryPlugin />
|
|
213
230
|
<LinkPlugin />
|
|
214
231
|
<ListPlugin />
|
|
215
|
-
<OnChangePlugin onChange={
|
|
232
|
+
<OnChangePlugin onChange={change} />
|
|
216
233
|
<AutoCompleteLinkPlugin openLinkInNewTab={openLinkInNewTab} />
|
|
217
234
|
<FloatingLinkEditorPlugin
|
|
218
235
|
editable={editable}
|
|
@@ -18,8 +18,9 @@ import { SvgIconTypeMap } from '@mui/material';
|
|
|
18
18
|
|
|
19
19
|
import { Menu } from '../../../components';
|
|
20
20
|
import { getSelectedNode } from '../../utils/getSelectedNode';
|
|
21
|
+
import { labelAlignPicker } from '../../translatedLabels';
|
|
21
22
|
|
|
22
|
-
import {
|
|
23
|
+
import { useStyles } from './ToolbarPlugin.styles';
|
|
23
24
|
|
|
24
25
|
const formatOptions: Array<{
|
|
25
26
|
Icon: OverridableComponent<SvgIconTypeMap<object, 'svg'>>;
|
|
@@ -48,7 +49,7 @@ interface Props {
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
const AlignPicker = ({ disabled }: Props): JSX.Element => {
|
|
51
|
-
const { classes } =
|
|
52
|
+
const { classes } = useStyles();
|
|
52
53
|
|
|
53
54
|
const [elementFormat, setElementFormat] = useState<ElementFormatType>('left');
|
|
54
55
|
|
|
@@ -88,25 +89,25 @@ const AlignPicker = ({ disabled }: Props): JSX.Element => {
|
|
|
88
89
|
|
|
89
90
|
return (
|
|
90
91
|
<Menu>
|
|
91
|
-
<Menu.Button
|
|
92
|
-
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
<Menu.Button
|
|
93
|
+
ariaLabel={labelAlignPicker}
|
|
94
|
+
className={classes.button}
|
|
95
|
+
disabled={disabled}
|
|
96
|
+
>
|
|
97
|
+
{selectedFormat && <selectedFormat.Icon />}
|
|
97
98
|
</Menu.Button>
|
|
98
|
-
<Menu.Items>
|
|
99
|
-
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<Icon
|
|
107
|
-
</
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
<Menu.Items className={classes.menuItems}>
|
|
100
|
+
<div className={classes.menu}>
|
|
101
|
+
{formatOptions.map(({ Icon, value, label }) => (
|
|
102
|
+
<Menu.Item
|
|
103
|
+
isActive={equals(value, elementFormat)}
|
|
104
|
+
key={value}
|
|
105
|
+
onClick={dispatchAlignment(value)}
|
|
106
|
+
>
|
|
107
|
+
<Icon aria-label={label} />
|
|
108
|
+
</Menu.Item>
|
|
109
|
+
))}
|
|
110
|
+
</div>
|
|
110
111
|
</Menu.Items>
|
|
111
112
|
</Menu>
|
|
112
113
|
);
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
4
|
-
import {
|
|
5
|
-
$isListNode,
|
|
6
|
-
INSERT_ORDERED_LIST_COMMAND,
|
|
7
|
-
INSERT_UNORDERED_LIST_COMMAND,
|
|
8
|
-
ListNode,
|
|
9
|
-
REMOVE_LIST_COMMAND
|
|
10
|
-
} from '@lexical/list';
|
|
11
4
|
import {
|
|
12
5
|
$createParagraphNode,
|
|
13
6
|
$getSelection,
|
|
@@ -23,43 +16,27 @@ import {
|
|
|
23
16
|
} from '@lexical/rich-text';
|
|
24
17
|
import { $setBlocksType } from '@lexical/selection';
|
|
25
18
|
import { T, always, cond, equals, isNil } from 'ramda';
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
$getNearestNodeOfType,
|
|
29
|
-
mergeRegister
|
|
30
|
-
} from '@lexical/utils';
|
|
19
|
+
import { $findMatchingParent, mergeRegister } from '@lexical/utils';
|
|
20
|
+
import { useTranslation } from 'react-i18next';
|
|
31
21
|
|
|
32
|
-
import
|
|
22
|
+
import TextSizeIcon from '@mui/icons-material/TextFields';
|
|
33
23
|
|
|
34
|
-
import {
|
|
24
|
+
import { Menu } from '../../../components';
|
|
25
|
+
|
|
26
|
+
import { useStyles } from './ToolbarPlugin.styles';
|
|
35
27
|
|
|
36
28
|
interface Props {
|
|
37
29
|
disabled: boolean;
|
|
38
30
|
}
|
|
39
31
|
|
|
40
32
|
const blockTypeToBlockName = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
h3: 'Heading 3',
|
|
45
|
-
h4: 'Heading 4',
|
|
46
|
-
h5: 'Heading 5',
|
|
47
|
-
h6: 'Heading 6',
|
|
48
|
-
number: 'Number List',
|
|
33
|
+
h3: 'Huge',
|
|
34
|
+
h5: 'Large',
|
|
35
|
+
h6: 'Small',
|
|
49
36
|
paragraph: 'Normal'
|
|
50
37
|
};
|
|
51
38
|
|
|
52
|
-
const blockTypes = [
|
|
53
|
-
'h1',
|
|
54
|
-
'h2',
|
|
55
|
-
'h3',
|
|
56
|
-
'h4',
|
|
57
|
-
'h5',
|
|
58
|
-
'h6',
|
|
59
|
-
'bullet',
|
|
60
|
-
'number',
|
|
61
|
-
'paragraph'
|
|
62
|
-
];
|
|
39
|
+
const blockTypes = ['h3', 'h5', 'paragraph', 'h6'];
|
|
63
40
|
|
|
64
41
|
const blockTypeOptions = blockTypes.map((blockType) => ({
|
|
65
42
|
id: blockType,
|
|
@@ -67,7 +44,8 @@ const blockTypeOptions = blockTypes.map((blockType) => ({
|
|
|
67
44
|
}));
|
|
68
45
|
|
|
69
46
|
const BlockButtons = ({ disabled }: Props): JSX.Element => {
|
|
70
|
-
const { classes } =
|
|
47
|
+
const { classes } = useStyles();
|
|
48
|
+
const { t } = useTranslation();
|
|
71
49
|
|
|
72
50
|
const [blockType, setBlockType] =
|
|
73
51
|
useState<keyof typeof blockTypeToBlockName>('paragraph');
|
|
@@ -81,22 +59,6 @@ const BlockButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
81
59
|
});
|
|
82
60
|
};
|
|
83
61
|
|
|
84
|
-
const formatBulletList = (): void => {
|
|
85
|
-
if (blockType !== 'bullet') {
|
|
86
|
-
editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
87
|
-
} else {
|
|
88
|
-
editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const formatNumberedList = (): void => {
|
|
93
|
-
if (blockType !== 'number') {
|
|
94
|
-
editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
|
|
95
|
-
} else {
|
|
96
|
-
editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
62
|
const formatHeading = (headingSize: HeadingTagType): void => {
|
|
101
63
|
if (blockType !== headingSize) {
|
|
102
64
|
editor.update(() => {
|
|
@@ -108,18 +70,13 @@ const BlockButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
108
70
|
}
|
|
109
71
|
};
|
|
110
72
|
|
|
111
|
-
const changeBlockType = (
|
|
73
|
+
const changeBlockType = (newBlockType): void => {
|
|
112
74
|
const formatFunction = cond<Array<string>, (value?) => void>([
|
|
113
|
-
[equals('bullet'), always(formatBulletList)],
|
|
114
|
-
[equals('number'), always(formatNumberedList)],
|
|
115
|
-
[equals('h1'), always(() => formatHeading('h1'))],
|
|
116
|
-
[equals('h2'), always(() => formatHeading('h2'))],
|
|
117
75
|
[equals('h3'), always(() => formatHeading('h3'))],
|
|
118
|
-
[equals('h4'), always(() => formatHeading('h4'))],
|
|
119
76
|
[equals('h5'), always(() => formatHeading('h5'))],
|
|
120
77
|
[equals('h6'), always(() => formatHeading('h6'))],
|
|
121
78
|
[T, always(formatParagraph)]
|
|
122
|
-
])(newBlockType
|
|
79
|
+
])(newBlockType || '');
|
|
123
80
|
|
|
124
81
|
formatFunction();
|
|
125
82
|
};
|
|
@@ -142,23 +99,13 @@ const BlockButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
142
99
|
return;
|
|
143
100
|
}
|
|
144
101
|
|
|
145
|
-
if ($isListNode(element)) {
|
|
146
|
-
const parentList = $getNearestNodeOfType(anchorNode, ListNode);
|
|
147
|
-
const type = parentList
|
|
148
|
-
? parentList.getListType()
|
|
149
|
-
: element.getListType();
|
|
150
|
-
setBlockType(type);
|
|
151
|
-
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
102
|
const type = $isHeadingNode(element) ? element.getTag() : element.getType();
|
|
103
|
+
|
|
155
104
|
if (type in blockTypeToBlockName) {
|
|
156
105
|
setBlockType(type as keyof typeof blockTypeToBlockName);
|
|
157
106
|
}
|
|
158
107
|
}, [editor]);
|
|
159
108
|
|
|
160
|
-
const value = blockTypeOptions.find((option) => option.id === blockType);
|
|
161
|
-
|
|
162
109
|
useEffect(() => {
|
|
163
110
|
return editor.registerCommand(
|
|
164
111
|
SELECTION_CHANGE_COMMAND,
|
|
@@ -182,15 +129,26 @@ const BlockButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
182
129
|
}, [editor, updateToolbar]);
|
|
183
130
|
|
|
184
131
|
return (
|
|
185
|
-
<
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
132
|
+
<Menu>
|
|
133
|
+
<Menu.Button
|
|
134
|
+
ariaLabel="block"
|
|
135
|
+
className={classes.button}
|
|
136
|
+
disabled={disabled}
|
|
137
|
+
>
|
|
138
|
+
<TextSizeIcon />
|
|
139
|
+
</Menu.Button>
|
|
140
|
+
<Menu.Items className={classes.menuItems}>
|
|
141
|
+
{blockTypeOptions.map(({ id, name }) => (
|
|
142
|
+
<Menu.Item
|
|
143
|
+
isActive={equals(id, blockType)}
|
|
144
|
+
key={name}
|
|
145
|
+
onClick={() => changeBlockType(id)}
|
|
146
|
+
>
|
|
147
|
+
{t(name)}
|
|
148
|
+
</Menu.Item>
|
|
149
|
+
))}
|
|
150
|
+
</Menu.Items>
|
|
151
|
+
</Menu>
|
|
194
152
|
);
|
|
195
153
|
};
|
|
196
154
|
|