@centreon/ui 23.10.89 → 23.10.91

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "23.10.89",
3
+ "version": "23.10.91",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
@@ -6,7 +6,7 @@ import {
6
6
  ReactElement
7
7
  } from 'react';
8
8
 
9
- import { isNil } from 'ramda';
9
+ import { isNil, prop } from 'ramda';
10
10
 
11
11
  import { Card, useTheme } from '@mui/material';
12
12
 
@@ -59,10 +59,13 @@ const Item = forwardRef(
59
59
  return useMemoComponent({
60
60
  Component: (
61
61
  <div
62
+ {...cardContainerListeners}
62
63
  className={className}
63
64
  ref={ref}
64
- style={style}
65
- {...cardContainerListeners}
65
+ style={{
66
+ ...style,
67
+ width: `calc(${prop('width', style) || '0px'} - 12px)`
68
+ }}
66
69
  >
67
70
  <Card className={classes.widgetContainer}>
68
71
  {header && (
@@ -331,6 +331,29 @@ describe('Rich Text Editor', () => {
331
331
  cy.findByText(blockType).click();
332
332
 
333
333
  cy.get('[data-testid="RichTextEditor"]').find(tag).should('be.visible');
334
+
335
+ cy.makeSnapshot();
336
+ });
337
+ });
338
+ });
339
+
340
+ describe('Aligns', () => {
341
+ beforeEach(() => {
342
+ cy.mount({
343
+ Component: <RichTextEditor editable />
344
+ });
345
+ });
346
+
347
+ const testCases = ['Center', 'Right'];
348
+
349
+ testCases.forEach((label) => {
350
+ it(`aligns the text to the ${label} when the corresponding button is clicked`, () => {
351
+ cy.get('[data-testid="RichTextEditor"]').type('Example');
352
+
353
+ cy.findByLabelText('left').click();
354
+ cy.contains(label).click();
355
+
356
+ cy.makeSnapshot();
334
357
  });
335
358
  });
336
359
  });
@@ -63,7 +63,8 @@ withMacrosPlugin.args = {
63
63
 
64
64
  export const withEditableFalse = Template.bind({});
65
65
  withEditableFalse.args = {
66
- editable: false,
66
+ editable: true,
67
+ editorState: JSON.stringify(initialEditorState),
67
68
  initialEditorState: JSON.stringify(initialEditorState)
68
69
  };
69
70
 
@@ -71,7 +72,8 @@ export const Disabled = Template.bind({});
71
72
  Disabled.args = {
72
73
  disabled: true,
73
74
  editable: false,
74
- editorState: JSON.stringify(initialEditorState)
75
+ editorState: JSON.stringify(initialEditorState),
76
+ initialEditorState: JSON.stringify(initialEditorState)
75
77
  };
76
78
 
77
79
  const StoryWithEditableFalseLikePreview = (): JSX.Element => {
@@ -0,0 +1,115 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+
3
+ import {
4
+ $getSelection,
5
+ $isElementNode,
6
+ $isRangeSelection,
7
+ ElementFormatType,
8
+ FORMAT_ELEMENT_COMMAND
9
+ } from 'lexical';
10
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
11
+ import { equals } from 'ramda';
12
+
13
+ import FormatAlignLeftIcon from '@mui/icons-material/FormatAlignLeft';
14
+ import FormatAlignCenterIcon from '@mui/icons-material/FormatAlignCenter';
15
+ import FormatAlignRightIcon from '@mui/icons-material/FormatAlignRight';
16
+ import { OverridableComponent } from '@mui/material/OverridableComponent';
17
+ import { SvgIconTypeMap } from '@mui/material';
18
+
19
+ import { Menu } from '../../../components';
20
+ import { getSelectedNode } from '../../utils/getSelectedNode';
21
+
22
+ import { useAlignPickerStyles } from './ToolbarPlugin.styles';
23
+
24
+ const formatOptions: Array<{
25
+ Icon: OverridableComponent<SvgIconTypeMap<object, 'svg'>>;
26
+ label: string;
27
+ value: ElementFormatType;
28
+ }> = [
29
+ {
30
+ Icon: FormatAlignLeftIcon,
31
+ label: 'Left',
32
+ value: 'left'
33
+ },
34
+ {
35
+ Icon: FormatAlignCenterIcon,
36
+ label: 'Center',
37
+ value: 'center'
38
+ },
39
+ {
40
+ Icon: FormatAlignRightIcon,
41
+ label: 'Right',
42
+ value: 'right'
43
+ }
44
+ ];
45
+
46
+ interface Props {
47
+ disabled: boolean;
48
+ }
49
+
50
+ const AlignPicker = ({ disabled }: Props): JSX.Element => {
51
+ const { classes } = useAlignPickerStyles();
52
+
53
+ const [elementFormat, setElementFormat] = useState<ElementFormatType>('left');
54
+
55
+ const [editor] = useLexicalComposerContext();
56
+
57
+ const dispatchAlignment = (alignment: ElementFormatType) => () => {
58
+ editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, alignment);
59
+ };
60
+
61
+ const updateElementFormat = useCallback(() => {
62
+ const selection = $getSelection();
63
+
64
+ if (!$isRangeSelection(selection)) {
65
+ return;
66
+ }
67
+
68
+ const node = getSelectedNode(selection);
69
+ const parent = node.getParent();
70
+
71
+ setElementFormat(
72
+ ($isElementNode(node) ? node.getFormatType() : parent?.getFormatType()) ||
73
+ 'left'
74
+ );
75
+ }, [editor]);
76
+
77
+ const selectedFormat = formatOptions.find(({ value }) =>
78
+ equals(value, elementFormat)
79
+ );
80
+
81
+ useEffect(() => {
82
+ return editor.registerUpdateListener(({ editorState }) => {
83
+ editorState.read(() => {
84
+ updateElementFormat();
85
+ });
86
+ });
87
+ }, [editor, updateElementFormat]);
88
+
89
+ return (
90
+ <Menu>
91
+ <Menu.Button ariaLabel={elementFormat} disabled={disabled}>
92
+ {selectedFormat && (
93
+ <div className={classes.button}>
94
+ <selectedFormat.Icon /> {selectedFormat.label}
95
+ </div>
96
+ )}
97
+ </Menu.Button>
98
+ <Menu.Items>
99
+ {formatOptions.map(({ Icon, label, value }) => (
100
+ <Menu.Item
101
+ isActive={equals(value, elementFormat)}
102
+ key={value}
103
+ onClick={dispatchAlignment(value)}
104
+ >
105
+ <div className={classes.option}>
106
+ <Icon /> {label}
107
+ </div>
108
+ </Menu.Item>
109
+ ))}
110
+ </Menu.Items>
111
+ </Menu>
112
+ );
113
+ };
114
+
115
+ export default AlignPicker;
@@ -5,3 +5,18 @@ export const useBlockButtonsStyles = makeStyles()((theme) => ({
5
5
  width: theme.spacing(17)
6
6
  }
7
7
  }));
8
+
9
+ export const useAlignPickerStyles = makeStyles()((theme) => ({
10
+ button: {
11
+ alignItems: 'center',
12
+ display: 'flex',
13
+ flexDirection: 'row',
14
+ gap: theme.spacing(1)
15
+ },
16
+ option: {
17
+ alignItems: 'center',
18
+ display: 'flex',
19
+ flexDirection: 'row',
20
+ gap: theme.spacing(2)
21
+ }
22
+ }));
@@ -6,6 +6,7 @@ import FormatButtons from './FormatButtons';
6
6
  import UndoRedoButtons from './UndoRedoButtons';
7
7
  import MacrosButton from './MacrosButton';
8
8
  import BlockButtons from './BlockButtons';
9
+ import AlignPicker from './AlignPicker';
9
10
 
10
11
  interface Props {
11
12
  disabled: boolean;
@@ -56,6 +57,7 @@ const ToolbarPlugin = ({
56
57
  <MacrosButton disabled={disabled} />
57
58
  </>
58
59
  )}
60
+ <AlignPicker disabled={disabled} />
59
61
  </div>
60
62
  ) : null;
61
63
  };
@@ -26,7 +26,7 @@ const useStyles = makeStyles()((theme) => ({
26
26
  borderBottom: `1px solid ${theme.palette.header.page.border}`,
27
27
  display: 'flex',
28
28
  gap: theme.spacing(4),
29
- paddingBottom: theme.spacing(2)
29
+ paddingBottom: theme.spacing(1.5)
30
30
  },
31
31
  pageHeaderActions: {
32
32
  '& > button': {
@@ -25,18 +25,17 @@ export const useStyles = makeStyles()((theme) => ({
25
25
  display: 'grid',
26
26
  gridTemplateRows: 'min-content',
27
27
  overflow: 'hidden',
28
- padding: theme.spacing(2, 3, 5)
28
+ padding: theme.spacing(1.5, 3, 5)
29
29
  },
30
30
  pageLayoutHeader: {
31
31
  '[data-variant="fixed-header"] &': {
32
32
  backgroundColor: theme.palette.layout.header.background,
33
33
  borderBottom: `1px solid ${theme.palette.layout.header.border}`,
34
- padding: theme.spacing(5, 4, 2),
34
+ padding: theme.spacing(3, 4, 2),
35
35
  position: 'sticky',
36
36
  top: 0,
37
37
  zIndex: `calc(${theme.zIndex.mobileStepper} - 100)`
38
38
  },
39
-
40
- padding: theme.spacing(5, 3, 0)
39
+ padding: theme.spacing(3, 3, 0)
41
40
  }
42
41
  }));
@@ -13,6 +13,7 @@ import { useMenu } from '../useMenu';
13
13
  import { useStyles } from './MenuButton.styles';
14
14
 
15
15
  type MenuButtonProps = {
16
+ ariaLabel?: string;
16
17
  children?: ReactNode;
17
18
  hasArrow?: boolean;
18
19
  isOpen?: boolean;
@@ -27,6 +28,7 @@ const MenuButton = ({
27
28
  hasArrow = true,
28
29
  size = 'small',
29
30
  variant = 'ghost',
31
+ ariaLabel,
30
32
  ...attr
31
33
  }: MenuButtonProps): ReactElement => {
32
34
  const { classes } = useStyles();
@@ -47,6 +49,7 @@ const MenuButton = ({
47
49
  return (
48
50
  <Button
49
51
  {...attr}
52
+ aria-label={ariaLabel}
50
53
  className={classes.menuButton}
51
54
  data-is-active={isMenuOpen}
52
55
  size={size}
File without changes