@scality/core-ui 0.163.0 → 0.165.0

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.
Files changed (32) hide show
  1. package/dist/components/barchartv2/Barchart.component.d.ts +10 -2
  2. package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
  3. package/dist/components/barchartv2/Barchart.component.js +20 -11
  4. package/dist/components/barchartv2/utils.d.ts +10 -3
  5. package/dist/components/barchartv2/utils.d.ts.map +1 -1
  6. package/dist/components/barchartv2/utils.js +45 -22
  7. package/dist/index.d.ts +0 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +0 -1
  10. package/dist/next.d.ts +2 -0
  11. package/dist/next.d.ts.map +1 -1
  12. package/dist/next.js +2 -0
  13. package/package.json +1 -1
  14. package/src/lib/components/accordion/Accordion.test.tsx +1 -1
  15. package/src/lib/components/barchartv2/Barchart.component.test.tsx +41 -18
  16. package/src/lib/components/barchartv2/Barchart.component.tsx +56 -14
  17. package/src/lib/components/barchartv2/utils.test.ts +82 -47
  18. package/src/lib/components/barchartv2/utils.ts +53 -16
  19. package/src/lib/components/healthselectorv2/HealthSelector.component.test.tsx +7 -7
  20. package/src/lib/components/infomessage/InfoMessageUtils.test.tsx +0 -1
  21. package/src/lib/components/inlineinput/InlineInput.test.tsx +10 -7
  22. package/src/lib/components/inputlist/InputList.test.tsx +1 -2
  23. package/src/lib/components/linetemporalchart/ChartUtil.test.ts +5 -4
  24. package/src/lib/components/selectv2/selectv2.test.tsx +8 -4
  25. package/src/lib/components/tablev2/TableSync.test.tsx +2 -3
  26. package/src/lib/components/tablev2/TableUtils.test.ts +6 -3
  27. package/src/lib/components/tablev2/Tablev2.test.tsx +2 -3
  28. package/src/lib/components/toggle/Toggle.test.tsx +1 -1
  29. package/src/lib/index.ts +0 -1
  30. package/src/lib/next.ts +2 -0
  31. package/stories/BarChart/barchart.stories.tsx +96 -5
  32. package/tsconfig.json +0 -1
@@ -1,4 +1,4 @@
1
- import React, { PropsWithChildren } from 'react';
1
+ import { PropsWithChildren } from 'react';
2
2
  import {
3
3
  QueryClient,
4
4
  QueryClientProvider,
@@ -11,7 +11,6 @@ import {
11
11
  render,
12
12
  screen,
13
13
  waitFor,
14
- waitForElementToBeRemoved,
15
14
  within,
16
15
  } from '@testing-library/react';
17
16
  import userEvent from '@testing-library/user-event';
@@ -77,9 +76,10 @@ describe('InlineInput', () => {
77
76
  /// Then press enter to edit the input
78
77
  await act(() => userEvent.keyboard('{enter}'));
79
78
  /// Then type a new value
80
- await act(() => userEvent.type(document.activeElement, 'new value'));
79
+ await act(() => userEvent.type(document.activeElement!, 'new value'));
81
80
  /// Then press enter to confirm the new value
82
81
  await act(() => userEvent.keyboard('{enter}'));
82
+ await waitFor(() => screen.findByText('testnew value'));
83
83
  expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
84
84
 
85
85
  //V
@@ -115,13 +115,16 @@ describe('InlineInput', () => {
115
115
  /// Then press enter to edit the input
116
116
  await act(() => userEvent.keyboard('{enter}'));
117
117
  /// Then type a new value
118
- await act(() => userEvent.type(document.activeElement, 'new value'));
118
+ await act(() => userEvent.type(document.activeElement!, 'new value'));
119
119
  /// Then press enter to confirm the new value
120
+
120
121
  await act(() => userEvent.keyboard('{enter}'));
122
+ await waitFor(() => screen.findByRole('dialog', { name: /Confirm/i }));
121
123
  /// Expect the confirmation modal to be opened
122
124
  expect(selectors.confirmationModal()).toBeInTheDocument()
123
125
  /// Click the confirm button
124
126
  await act(() => userEvent.click(screen.getByRole('button', { name: /confirm/i })));
127
+
125
128
  /// modal should be closed
126
129
  expect(screen.queryByRole('dialog', { name: /Confirm/i })).not.toBeInTheDocument();
127
130
 
@@ -156,7 +159,7 @@ describe('InlineInput', () => {
156
159
  /// Then press enter to edit the input
157
160
  await act(() => userEvent.keyboard('{enter}'));
158
161
  /// Then type a new value
159
- await act(() => userEvent.type(document.activeElement, 'new value'));
162
+ await act(() => userEvent.type(document.activeElement!, 'new value'));
160
163
  /// Then press escape to cancel the new value
161
164
  await act(() => userEvent.keyboard('{esc}'));
162
165
 
@@ -191,7 +194,7 @@ describe('InlineInput', () => {
191
194
  /// Then press enter to edit the input
192
195
  await act(() => userEvent.keyboard('{enter}'));
193
196
  /// Then type a new value
194
- await act(() => userEvent.type(document.activeElement, 'new value'));
197
+ await act(() => userEvent.type(document.activeElement!, 'new value'));
195
198
  /// Then press enter to confirm the new value
196
199
  await act(() => userEvent.keyboard('{enter}'));
197
200
  /// Expect the confirmation modal to be opened
@@ -208,7 +211,7 @@ describe('InlineInput', () => {
208
211
  //V
209
212
  expect(mock).not.toHaveBeenCalled();
210
213
  expect(screen.getByRole('textbox')).toBeInTheDocument();
211
- expect(screen.getByRole('textbox').value).toBe('testnew value');
214
+ expect((screen.getByRole('textbox') as HTMLInputElement).value).toBe('testnew value');
212
215
  });
213
216
  });
214
217
  });
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
3
2
  import { InputList, InputListProps } from './InputList.component';
4
3
  import { FormSection } from '../form/Form.component';
@@ -6,7 +5,7 @@ import { FormSection } from '../form/Form.component';
6
5
  describe('InputList', () => {
7
6
  const onChangeMock = jest.fn();
8
7
 
9
- const renderInputList = (props: InputListProps<string[]>) => {
8
+ const renderInputList = (props: InputListProps<string>) => {
10
9
  render(
11
10
  <FormSection>
12
11
  <InputList
@@ -3,7 +3,8 @@ import {
3
3
  getUnitLabel,
4
4
  addMissingDataPoint,
5
5
  } from './ChartUtil';
6
- const series = [
6
+ import { Serie } from './LineTemporalChart.component';
7
+ const series: Serie[] = [
7
8
  {
8
9
  resource: 'node1',
9
10
  data: [
@@ -11,7 +12,7 @@ const series = [
11
12
  [1627460952, '18.73333333333335'],
12
13
  ],
13
14
  getTooltipLabel: (metricPrefix, resource) => {
14
- return resource;
15
+ return `${resource}`;
15
16
  },
16
17
  isLineDashed: false,
17
18
  },
@@ -22,12 +23,12 @@ const series = [
22
23
  [1627460952, null],
23
24
  ],
24
25
  getTooltipLabel: (metricPrefix, resource) => {
25
- return resource;
26
+ return `${resource}`;
26
27
  },
27
28
  isLineDashed: false,
28
29
  },
29
30
  ];
30
- const seriesSymmetrical = [
31
+ const seriesSymmetrical: Serie[] = [
31
32
  {
32
33
  metricPrefix: 'read',
33
34
  resource: 'node1',
@@ -2,6 +2,7 @@ import { act, screen, render as testingRender, waitFor } from '@testing-library/
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import React, { useState, useRef } from 'react';
4
4
  import { Option, Select, SelectRef } from '../selectv2/Selectv2.component';
5
+ import { GroupTypeBase, OptionTypeBase } from 'react-select';
5
6
 
6
7
  const render = (args) => {
7
8
  return testingRender(args);
@@ -66,7 +67,10 @@ describe('SelectV2', () => {
66
67
  };
67
68
 
68
69
  it('should throw error if <Option/> is outside <Select/>', () => {
70
+ // mock console.error as this is the only way to silent expected error thrown by the component
71
+ const consoleErrorFn = jest.spyOn(console, 'error').mockImplementation(() => jest.fn());
69
72
  expect(() => render(<Option value="Option 1" />)).toThrowError();
73
+ consoleErrorFn.mockRestore();
70
74
  });
71
75
 
72
76
  it('should open/close on click', async () => {
@@ -458,7 +462,7 @@ describe('SelectV2', () => {
458
462
  describe('Ref API', () => {
459
463
  it('should expose focus method via ref', async () => {
460
464
  const RefTestComponent = () => {
461
- const selectRef = useRef<SelectRef>(null);
465
+ const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
462
466
  const [value, setValue] = useState<string>('');
463
467
 
464
468
  return (
@@ -486,7 +490,7 @@ describe('SelectV2', () => {
486
490
 
487
491
  it('should expose openMenu and closeMenu methods via ref', async () => {
488
492
  const RefTestComponent = () => {
489
- const selectRef = useRef<SelectRef>(null);
493
+ const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
490
494
  const [value, setValue] = useState<string>('');
491
495
 
492
496
  return (
@@ -529,7 +533,7 @@ describe('SelectV2', () => {
529
533
 
530
534
  const RefTestComponent = () => {
531
535
  const [value, setValue] = useState('');
532
- const selectRef = useRef<SelectRef>(null);
536
+ const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
533
537
 
534
538
  return (
535
539
  <div>
@@ -582,7 +586,7 @@ describe('SelectV2', () => {
582
586
 
583
587
  it('should expose blur method via ref', async () => {
584
588
  const RefTestComponent = () => {
585
- const selectRef = useRef<SelectRef>(null);
589
+ const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
586
590
  const [value, setValue] = useState<string>('');
587
591
 
588
592
  return (
@@ -1,12 +1,11 @@
1
1
  import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
2
- import React from 'react';
3
2
  import { TableSync } from './TableSync';
4
3
 
5
4
  describe('TableSync', () => {
6
5
  it('should render correctly', async () => {
7
6
  const onSync = jest.fn();
8
7
  render(
9
- <TableSync onSync={onSync} />
8
+ <TableSync onSync={onSync} tooltipOverlay='sync' />
10
9
  );
11
10
  await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
12
11
 
@@ -17,7 +16,7 @@ describe('TableSync', () => {
17
16
  it('should call onSync when clicked', async () => {
18
17
  const onSync = jest.fn();
19
18
  render(
20
- <TableSync onSync={onSync} />
19
+ <TableSync onSync={onSync} tooltipOverlay='sync' />
21
20
  );
22
21
  await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
23
22
 
@@ -9,9 +9,12 @@ it('should return -1 or 1 to sort the status', () => {
9
9
  expect(result).toEqual(1);
10
10
  expect(result2).toEqual(-1);
11
11
  });
12
- it('should return undefine for the unknown status', () => {
13
- const result = compareHealth('invalidStatus', 'healthy');
14
- const result2 = compareHealth('none', 'invalidStatus');
12
+ it('should return undefined for the unknown status', () => {
13
+ const consoleErrorMockHandle = jest.spyOn(console, 'error').mockImplementation(() => {});
14
+ const result = compareHealth('invalidStatus' as any, 'healthy');
15
+ const result2 = compareHealth('none', 'invalidStatus' as any);
16
+ expect(consoleErrorMockHandle).toHaveBeenCalled();
17
+ consoleErrorMockHandle.mockRestore();
15
18
  expect(result).toEqual(undefined);
16
19
  expect(result2).toEqual(undefined);
17
20
  });
@@ -1,5 +1,4 @@
1
- import { Table } from './Tablev2.component';
2
- import React from 'react';
1
+ import { Table, TableProps } from './Tablev2.component';
3
2
  import { render, screen, waitFor } from '@testing-library/react';
4
3
 
5
4
  jest.mock('./TableUtils', () => ({
@@ -42,7 +41,7 @@ const data = [
42
41
  health: 'healthy',
43
42
  },
44
43
  ];
45
- const columns = [
44
+ const columns: TableProps['columns'] = [
46
45
  {
47
46
  Header: 'First Name',
48
47
  accessor: 'firstName',
@@ -1,5 +1,5 @@
1
1
  import { render, screen } from '@testing-library/react';
2
- import React, { useState } from 'react';
2
+ import { useState } from 'react';
3
3
  import { Props, Toggle } from './Toggle.component';
4
4
  import userEvent from '@testing-library/user-event';
5
5
 
package/src/lib/index.ts CHANGED
@@ -82,4 +82,3 @@ export { InfoMessage } from './components/infomessage/InfoMessage.component';
82
82
  export { InputList } from './components/inputlist/InputList.component';
83
83
  export { InlineInput } from './components/inlineinput/InlineInput';
84
84
  export { UnsuccessfulResult } from './components/UnsuccessfulResult.component';
85
- export { LineTimeSerieChart } from './components/linetimeseriechart/linetimeseriechart.component';
package/src/lib/next.ts CHANGED
@@ -22,3 +22,5 @@ export {
22
22
  BarchartTooltipFn,
23
23
  } from './components/barchartv2/Barchart.component';
24
24
  export { ChartLegendWrapper } from './components/chartlegend/ChartLegendWrapper';
25
+ export { ChartLegend } from './components/chartlegend/ChartLegend';
26
+ export { LineTimeSerieChart } from './components/linetimeseriechart/linetimeseriechart.component';
@@ -360,7 +360,7 @@ export const CapacityWithUnitRange: Story = {
360
360
 
361
361
  const stackedData: BarchartProps<
362
362
  {
363
- label: 'Success' | 'Failed';
363
+ label: 'Success' | 'Failed' | 'Warning';
364
364
  data: [string, number][];
365
365
  }[]
366
366
  >['bars'] = [
@@ -375,9 +375,17 @@ const stackedData: BarchartProps<
375
375
  {
376
376
  label: 'Failed',
377
377
  data: [
378
- ['category1', 8],
379
- ['category2', 10],
380
- ['category3', 25],
378
+ ['category1', 0],
379
+ ['category2', 0],
380
+ ['category3', 0],
381
+ ],
382
+ },
383
+ {
384
+ label: 'Warning',
385
+ data: [
386
+ ['category1', 0],
387
+ ['category2', 0],
388
+ ['category3', 0],
381
389
  ],
382
390
  },
383
391
  ];
@@ -390,6 +398,7 @@ export const Stacked: Story = {
390
398
  colorSet={{
391
399
  Success: theme.statusHealthy,
392
400
  Failed: theme.statusCritical,
401
+ Warning: theme.statusWarning,
393
402
  }}
394
403
  >
395
404
  <Stack direction="vertical" gap="r16">
@@ -736,6 +745,88 @@ export const BarchartsWithSingleLegend: Story = {
736
745
  );
737
746
  },
738
747
  };
748
+
749
+ export const ErrorState: Story = {
750
+ render: () => {
751
+ const theme = useTheme() as CoreUITheme;
752
+ return (
753
+ <ChartLegendWrapper
754
+ colorSet={{
755
+ Success: theme.statusHealthy,
756
+ Failed: theme.statusCritical,
757
+ }}
758
+ >
759
+ <Barchart
760
+ type="category"
761
+ bars={[]}
762
+ isError
763
+ title="Error State"
764
+ helpTooltip="This chart data could not be loaded"
765
+ />
766
+ <ChartLegend shape="rectangle" />
767
+ </ChartLegendWrapper>
768
+ );
769
+ },
770
+ };
771
+
772
+ export const StackedBarSort: Story = {
773
+ render: () => {
774
+ const theme = useTheme() as CoreUITheme;
775
+ const [sort, setSort] = useState<'default' | 'legend'>('default');
776
+ const statusesData = [
777
+ {
778
+ label: 'Success',
779
+ data: [
780
+ ['category1', 100],
781
+ ['category2', 80],
782
+ ['category3', 50],
783
+ ],
784
+ },
785
+ {
786
+ label: 'Warning',
787
+ data: [
788
+ ['category1', 10],
789
+ ['category2', 20],
790
+ ['category3', 30],
791
+ ],
792
+ },
793
+ {
794
+ label: 'Failed',
795
+ data: [
796
+ ['category1', 30],
797
+ ['category2', 40],
798
+ ['category3', 50],
799
+ ],
800
+ },
801
+ ] as const;
802
+ return (
803
+ <ChartLegendWrapper
804
+ colorSet={{
805
+ Success: theme.statusHealthy,
806
+ Warning: theme.statusWarning,
807
+ Failed: theme.statusCritical,
808
+ }}
809
+ >
810
+ <Barchart
811
+ type="category"
812
+ bars={statusesData}
813
+ stacked
814
+ stackedBarSort={sort}
815
+ title="Stacked Bar Chart"
816
+ helpTooltip="This chart data could not be loaded"
817
+ rightTitle={
818
+ <Button
819
+ label={sort === 'default' ? 'Sort by Legend' : 'Sort by Default'}
820
+ onClick={() => setSort(sort === 'default' ? 'legend' : 'default')}
821
+ />
822
+ }
823
+ />
824
+ <ChartLegend shape="rectangle" />
825
+ </ChartLegendWrapper>
826
+ );
827
+ },
828
+ };
829
+
739
830
  export const CompleteExample: Story = {
740
831
  render: () => {
741
832
  const theme = useTheme() as CoreUITheme;
@@ -809,7 +900,7 @@ export const CompleteExample: Story = {
809
900
  }}
810
901
  />
811
902
  }
812
- bars={data || []}
903
+ bars={data}
813
904
  tooltip={customTooltip}
814
905
  isLoading={isLoading}
815
906
  height={200}
package/tsconfig.json CHANGED
@@ -15,7 +15,6 @@
15
15
  "strictFunctionTypes": true,
16
16
  "noImplicitAny": false, //For now it is too costly to enable this one
17
17
  "esModuleInterop": true,
18
- "allowSyntheticDefaultImports": true,
19
18
  "forceConsistentCasingInFileNames": true
20
19
  }
21
20
  }