@lumx/react 3.19.1-alpha.7 → 3.19.1-alpha.9

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 (56) hide show
  1. package/_internal/index.js +20 -13
  2. package/_internal/index.js.map +1 -1
  3. package/index.d.ts +5 -6
  4. package/index.js +2400 -2440
  5. package/index.js.map +1 -1
  6. package/package.json +10 -13
  7. package/src/components/alert-dialog/AlertDialog.test.tsx +3 -2
  8. package/src/components/autocomplete/Autocomplete.test.tsx +3 -3
  9. package/src/components/button/Button.test.tsx +9 -9
  10. package/src/components/button/ButtonRoot.tsx +6 -36
  11. package/src/components/checkbox/Checkbox.test.tsx +3 -3
  12. package/src/components/chip/Chip.test.tsx +19 -17
  13. package/src/components/date-picker/DatePicker.test.tsx +3 -3
  14. package/src/components/date-picker/DatePickerControlled.test.tsx +6 -6
  15. package/src/components/date-picker/DatePickerField.test.tsx +3 -3
  16. package/src/components/dialog/Dialog.test.tsx +4 -4
  17. package/src/components/dropdown/Dropdown.test.tsx +3 -3
  18. package/src/components/expansion-panel/ExpansionPanel.test.tsx +6 -5
  19. package/src/components/icon/Icon.stories.tsx +30 -4
  20. package/src/components/icon/Icon.test.tsx +85 -2
  21. package/src/components/icon/Icon.tsx +118 -7
  22. package/src/components/image-lightbox/ImageLightbox.test.tsx +11 -7
  23. package/src/components/link/Link.test.tsx +13 -11
  24. package/src/components/link/Link.tsx +9 -20
  25. package/src/components/list/ListItem.test.tsx +5 -5
  26. package/src/components/message/Message.test.tsx +1 -1
  27. package/src/components/mosaic/Mosaic.test.tsx +3 -3
  28. package/src/components/navigation/NavigationItem.tsx +6 -10
  29. package/src/components/navigation/NavigationSection.tsx +4 -3
  30. package/src/components/notification/Notification.test.tsx +4 -3
  31. package/src/components/popover-dialog/PopoverDialog.test.tsx +1 -1
  32. package/src/components/radio-button/RadioButton.test.tsx +3 -3
  33. package/src/components/select/Select.test.tsx +8 -7
  34. package/src/components/select/SelectMultiple.test.tsx +5 -5
  35. package/src/components/side-navigation/SideNavigationItem.test.tsx +2 -2
  36. package/src/components/side-navigation/SideNavigationItem.tsx +22 -27
  37. package/src/components/slider/Slider.test.tsx +1 -1
  38. package/src/components/switch/Switch.test.tsx +5 -5
  39. package/src/components/table/TableCell.test.tsx +1 -1
  40. package/src/components/text-field/TextField.test.tsx +9 -8
  41. package/src/components/thumbnail/Thumbnail.test.tsx +29 -5
  42. package/src/components/thumbnail/Thumbnail.tsx +11 -11
  43. package/src/components/tooltip/Tooltip.test.tsx +14 -8
  44. package/src/components/uploader/Uploader.test.tsx +2 -2
  45. package/src/components/user-block/UserBlock.test.tsx +1 -1
  46. package/src/untypped-modules.d.ts +4 -0
  47. package/src/utils/Portal/PortalProvider.test.tsx +1 -1
  48. package/src/utils/date/getYearDisplayName.test.ts +1 -1
  49. package/src/utils/disabled/useDisableStateProps.test.tsx +2 -2
  50. package/src/utils/react/RawClickable.test.tsx +153 -0
  51. package/src/utils/react/RawClickable.tsx +65 -0
  52. package/src/utils/type/HasRequiredLinkHref.ts +1 -0
  53. package/src/utils/type/index.ts +1 -0
  54. package/utils/index.d.ts +1 -1
  55. package/utils/index.js +1 -1
  56. package/src/utils/react/renderButtonOrLink.tsx +0 -16
package/package.json CHANGED
@@ -6,8 +6,8 @@
6
6
  "url": "https://github.com/lumapps/design-system/issues"
7
7
  },
8
8
  "dependencies": {
9
- "@lumx/core": "^3.19.1-alpha.7",
10
- "@lumx/icons": "^3.19.1-alpha.7",
9
+ "@lumx/core": "^3.19.1-alpha.9",
10
+ "@lumx/icons": "^3.19.1-alpha.9",
11
11
  "@popperjs/core": "^2.5.4",
12
12
  "body-scroll-lock": "^3.1.5",
13
13
  "classnames": "^2.3.2",
@@ -30,24 +30,21 @@
30
30
  "@rollup/plugin-babel": "^6.0.4",
31
31
  "@rollup/plugin-commonjs": "^19.0.2",
32
32
  "@rollup/plugin-node-resolve": "16.0.0",
33
- "@rollup/pluginutils": "5.2.0",
34
33
  "@storybook/addon-a11y": "^9.1.4",
35
34
  "@storybook/addon-docs": "^9.1.4",
36
35
  "@storybook/react-vite": "^9.1.4",
37
- "@testing-library/dom": "^9.3.4",
38
- "@testing-library/jest-dom": "^5.16.4",
36
+ "@testing-library/dom": "^10.4.1",
39
37
  "@testing-library/react": "^12.1.2",
40
38
  "@testing-library/user-event": "^14.4.3",
41
39
  "@types/body-scroll-lock": "^2.6.1",
42
40
  "@types/classnames": "^2.2.9",
43
41
  "@types/dom-view-transitions": "^1.0.5",
44
- "@types/jest": "^29.2.1",
45
42
  "@types/lodash": "^4.14.149",
46
43
  "@types/react": "^17.0.2",
47
44
  "@types/react-dom": "^17.0.2",
48
45
  "@types/react-is": "^17.0.2",
46
+ "@vitest/ui": "^1.0.0",
49
47
  "autoprefixer": "^9.7.4",
50
- "babel-jest": "29.1.2",
51
48
  "babel-loader": "^8.0.6",
52
49
  "chromatic": "^13.1.4",
53
50
  "core-js": "^3.6.4",
@@ -55,8 +52,7 @@
55
52
  "glob": "^7.1.6",
56
53
  "install-peers-cli": "^2.2.0",
57
54
  "is-ci": "^2.0.0",
58
- "jest": "29.1.2",
59
- "jest-environment-jsdom": "29.1.2",
55
+ "jsdom": "^27.2.0",
60
56
  "node-notifier": "^10.0.1",
61
57
  "react": "^17.0.2",
62
58
  "react-dom": "^17.0.2",
@@ -71,12 +67,13 @@
71
67
  "typescript": "^5.4.3",
72
68
  "vite": "^6.3.5",
73
69
  "vite-tsconfig-paths": "^5.1.4",
70
+ "vitest": "^1.0.0",
74
71
  "yargs": "^15.4.1"
75
72
  },
76
73
  "peerDependencies": {
77
74
  "lodash": "4.17.21",
78
- "react": ">= 17.0.0",
79
- "react-dom": ">= 17.0.0"
75
+ "react": ">= 16.13.0",
76
+ "react-dom": ">= 16.13.0"
80
77
  },
81
78
  "description": "The official LumApps Design System (LumX) for React applications",
82
79
  "homepage": "https://github.com/lumapps/design-system",
@@ -101,10 +98,10 @@
101
98
  "scripts": {
102
99
  "build": "rollup -c",
103
100
  "prepare": "install-peers || exit 0",
104
- "test": "jest --config jest/index.js --coverage --notify --passWithNoTests --detectOpenHandles --runInBand",
101
+ "test": "vitest run",
105
102
  "start:storybook": "storybook dev -p 9000",
106
103
  "build:storybook": "storybook build"
107
104
  },
108
105
  "sideEffects": false,
109
- "version": "3.19.1-alpha.7"
106
+ "version": "3.19.1-alpha.9"
110
107
  }
@@ -3,9 +3,10 @@ import React from 'react';
3
3
  import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
4
4
  import { queryByClassName } from '@lumx/react/testing/utils/queries';
5
5
  import { render } from '@testing-library/react';
6
+ import { vi } from 'vitest';
6
7
  import { AlertDialog, AlertDialogProps } from './AlertDialog';
7
8
 
8
- jest.mock('@lumx/react/hooks/useId', () => ({ useId: () => ':r1:' }));
9
+ vi.mock('@lumx/react/hooks/useId', () => ({ useId: () => ':r1:' }));
9
10
 
10
11
  const CLASSNAME = AlertDialog.className as string;
11
12
 
@@ -17,7 +18,7 @@ const setup = (propsOverride: Partial<AlertDialogProps> = {}) => {
17
18
  title: 'Alert',
18
19
  isOpen: true,
19
20
  description: 'Deserunt et sunt qui consequat sint sit.',
20
- confirmProps: { onClick: jest.fn(), label: 'OK' },
21
+ confirmProps: { onClick: vi.fn(), label: 'OK' },
21
22
  ...propsOverride,
22
23
  };
23
24
  render(<AlertDialog {...props} />);
@@ -53,7 +53,7 @@ describe(`<${Autocomplete.displayName}>`, () => {
53
53
  describe('Events', () => {
54
54
  it('should trigger the onChange callback when there is a change on the Text Field', async () => {
55
55
  const name = 'autocomplete-name';
56
- const onChange = jest.fn();
56
+ const onChange = vi.fn();
57
57
  const { inputNative } = setup({
58
58
  name,
59
59
  onChange,
@@ -68,8 +68,8 @@ describe(`<${Autocomplete.displayName}>`, () => {
68
68
  });
69
69
 
70
70
  it('should trigger the onFocus/onBlur callback when the text field is focused and blurred', async () => {
71
- const onFocus = jest.fn();
72
- const onBlur = jest.fn();
71
+ const onFocus = vi.fn();
72
+ const onBlur = vi.fn();
73
73
  const { inputNative } = setup({
74
74
  onFocus,
75
75
  onBlur,
@@ -68,7 +68,7 @@ describe(`<${Button.displayName}>`, () => {
68
68
 
69
69
  describe('Disabled state', () => {
70
70
  it('should render disabled button', async () => {
71
- const onClick = jest.fn();
71
+ const onClick = vi.fn();
72
72
  const { button } = setup({ children: 'Label', disabled: true, onClick });
73
73
  expect(button).toHaveAttribute('disabled');
74
74
  await userEvent.click(button);
@@ -76,17 +76,18 @@ describe(`<${Button.displayName}>`, () => {
76
76
  });
77
77
 
78
78
  it('should render disabled link', async () => {
79
- const onClick = jest.fn();
79
+ const onClick = vi.fn();
80
80
  const { button } = setup({ children: 'Label', disabled: true, href: 'https://example.com', onClick });
81
- // Disabled link do not exist so we fallback to a button
82
- expect(screen.queryByRole('link')).not.toBeInTheDocument();
83
- expect(button).toHaveAttribute('disabled');
81
+ expect(screen.queryByRole('link')).toBeInTheDocument();
82
+ expect(button).toHaveAttribute('aria-disabled', 'true');
83
+ // Simulate standard disabled state (not focusable)
84
+ expect(button).toHaveAttribute('tabindex', '-1');
84
85
  await userEvent.click(button);
85
86
  expect(onClick).not.toHaveBeenCalled();
86
87
  });
87
88
 
88
89
  it('should render aria-disabled button', async () => {
89
- const onClick = jest.fn();
90
+ const onClick = vi.fn();
90
91
  const { button } = setup({ children: 'Label', 'aria-disabled': true, onClick });
91
92
  expect(button).toHaveAttribute('aria-disabled');
92
93
  await userEvent.click(button);
@@ -94,7 +95,7 @@ describe(`<${Button.displayName}>`, () => {
94
95
  });
95
96
 
96
97
  it('should render aria-disabled link', async () => {
97
- const onClick = jest.fn();
98
+ const onClick = vi.fn();
98
99
  const { button } = setup({
99
100
  children: 'Label',
100
101
  'aria-disabled': true,
@@ -102,8 +103,7 @@ describe(`<${Button.displayName}>`, () => {
102
103
  onClick,
103
104
  });
104
105
  expect(button).toHaveAccessibleName('Label');
105
- // Disabled link do not exist so we fallback to a button
106
- expect(screen.queryByRole('link')).not.toBeInTheDocument();
106
+ expect(screen.queryByRole('link')).toBeInTheDocument();
107
107
  expect(button).toHaveAttribute('aria-disabled', 'true');
108
108
  await userEvent.click(button);
109
109
  expect(onClick).not.toHaveBeenCalled();
@@ -1,17 +1,15 @@
1
1
  import React, { AriaAttributes, ButtonHTMLAttributes, DetailedHTMLProps, RefObject } from 'react';
2
2
 
3
- import isEmpty from 'lodash/isEmpty';
4
-
5
3
  import classNames from 'classnames';
6
4
 
7
5
  import { ColorPalette, Emphasis, Size, Theme } from '@lumx/react';
8
6
  import { CSS_PREFIX } from '@lumx/react/constants';
9
7
  import { GenericProps, HasTheme } from '@lumx/react/utils/type';
10
8
  import { handleBasicClasses } from '@lumx/core/js/utils/className';
11
- import { renderLink } from '@lumx/react/utils/react/renderLink';
12
9
  import { forwardRef } from '@lumx/react/utils/react/forwardRef';
13
- import { useDisableStateProps } from '@lumx/react/utils/disabled/useDisableStateProps';
14
10
  import { HasAriaDisabled } from '@lumx/react/utils/type/HasAriaDisabled';
11
+ import { RawClickable } from '@lumx/react/utils/react/RawClickable';
12
+ import { useDisableStateProps } from '@lumx/react/utils/disabled';
15
13
 
16
14
  type HTMLButtonProps = DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>;
17
15
 
@@ -107,18 +105,14 @@ export const ButtonRoot = forwardRef<ButtonRootProps, HTMLButtonElement | HTMLAn
107
105
  color,
108
106
  emphasis,
109
107
  hasBackground,
110
- href,
111
108
  isSelected,
112
109
  isActive,
113
110
  isFocused,
114
111
  isHovered,
115
112
  linkAs,
116
- name,
117
113
  size,
118
- target,
119
114
  theme,
120
115
  variant,
121
- type = 'button',
122
116
  fullWidth,
123
117
  ...forwardedProps
124
118
  } = otherProps;
@@ -139,7 +133,7 @@ export const ButtonRoot = forwardRef<ButtonRootProps, HTMLButtonElement | HTMLAn
139
133
  color: adaptedColor,
140
134
  emphasis,
141
135
  isSelected,
142
- isDisabled: isAnyDisabled,
136
+ isDisabled: props.isDisabled || props['aria-disabled'],
143
137
  isActive,
144
138
  isFocused,
145
139
  isHovered,
@@ -151,42 +145,18 @@ export const ButtonRoot = forwardRef<ButtonRootProps, HTMLButtonElement | HTMLAn
151
145
  }),
152
146
  );
153
147
 
154
- /**
155
- * If the linkAs prop is used, we use the linkAs component instead of a <button>.
156
- * If there is an href attribute, we display an <a> instead of a <button>.
157
- *
158
- * However, in any case, if the component is disabled, we returned a <button> since disabled is not compatible with <a>.
159
- */
160
- if ((linkAs || !isEmpty(props.href)) && !isAnyDisabled) {
161
- return renderLink(
162
- {
163
- linkAs,
164
- ...forwardedProps,
165
- 'aria-label': ariaLabel,
166
- href,
167
- target,
168
- className: buttonClassName,
169
- ref: ref as RefObject<HTMLAnchorElement>,
170
- },
171
- children,
172
- );
173
- }
174
148
  return (
175
- <button
149
+ <RawClickable
150
+ as={linkAs || (forwardedProps.href ? 'a' : 'button')}
176
151
  {...forwardedProps}
177
152
  {...disabledStateProps}
178
153
  aria-disabled={isAnyDisabled}
179
154
  aria-label={ariaLabel}
180
155
  ref={ref as RefObject<HTMLButtonElement>}
181
156
  className={buttonClassName}
182
- name={name}
183
- type={
184
- // eslint-disable-next-line react/button-has-type
185
- type
186
- }
187
157
  >
188
158
  {children}
189
- </button>
159
+ </RawClickable>
190
160
  );
191
161
  });
192
162
  ButtonRoot.displayName = COMPONENT_NAME;
@@ -98,7 +98,7 @@ describe(`<${Checkbox.displayName}>`, () => {
98
98
  });
99
99
 
100
100
  describe('Events', () => {
101
- const onChange = jest.fn();
101
+ const onChange = vi.fn();
102
102
 
103
103
  it('should trigger `onChange` when checkbox is clicked', async () => {
104
104
  const value = 'value';
@@ -114,7 +114,7 @@ describe(`<${Checkbox.displayName}>`, () => {
114
114
 
115
115
  describe('Disabled state', () => {
116
116
  it('should be disabled with isDisabled', async () => {
117
- const onChange = jest.fn();
117
+ const onChange = vi.fn();
118
118
  const { checkbox, input } = setup({ isDisabled: true, onChange });
119
119
 
120
120
  expect(checkbox).toHaveClass('lumx-checkbox--is-disabled');
@@ -126,7 +126,7 @@ describe(`<${Checkbox.displayName}>`, () => {
126
126
  });
127
127
 
128
128
  it('should be disabled with aria-disabled', async () => {
129
- const onChange = jest.fn();
129
+ const onChange = vi.fn();
130
130
  const { checkbox, input } = setup({ 'aria-disabled': true, onChange });
131
131
 
132
132
  expect(checkbox).toHaveClass('lumx-checkbox--is-disabled');
@@ -42,7 +42,7 @@ describe('<Chip />', () => {
42
42
  });
43
43
 
44
44
  it('should render clickable', () => {
45
- const onClick = jest.fn();
45
+ const onClick = vi.fn();
46
46
  const { chip } = setup({ children: 'Chip text', onClick });
47
47
  expect(chip).toHaveAttribute('role', 'button');
48
48
  expect(chip.className).toMatchInlineSnapshot(
@@ -70,11 +70,13 @@ describe('<Chip />', () => {
70
70
  });
71
71
 
72
72
  describe('Events', () => {
73
- const onClick = jest.fn();
74
- const onAfterClick = jest.fn();
75
- const onBeforeClick = jest.fn();
73
+ const onClick = vi.fn();
74
+ const onAfterClick = vi.fn();
75
+ const onBeforeClick = vi.fn();
76
76
 
77
- beforeEach(jest.clearAllMocks);
77
+ beforeEach(() => {
78
+ vi.clearAllMocks();
79
+ });
78
80
 
79
81
  it('should trigger onBeforeClick only when clicking on the "before" element', async () => {
80
82
  const { after, before, chip } = setup({
@@ -88,12 +90,12 @@ describe('<Chip />', () => {
88
90
  await userEvent.click(chip);
89
91
  expect(onBeforeClick).not.toHaveBeenCalled();
90
92
 
91
- jest.clearAllMocks();
93
+ vi.clearAllMocks();
92
94
 
93
95
  await userEvent.click(after as any);
94
96
  expect(onBeforeClick).not.toHaveBeenCalled();
95
97
 
96
- jest.clearAllMocks();
98
+ vi.clearAllMocks();
97
99
 
98
100
  await userEvent.click(before as any);
99
101
  expect(onBeforeClick).toHaveBeenCalled();
@@ -111,12 +113,12 @@ describe('<Chip />', () => {
111
113
  await userEvent.click(chip);
112
114
  expect(onClick).toHaveBeenCalled();
113
115
 
114
- jest.clearAllMocks();
116
+ vi.clearAllMocks();
115
117
 
116
118
  await userEvent.click(after as any);
117
119
  expect(onClick).not.toHaveBeenCalled();
118
120
 
119
- jest.clearAllMocks();
121
+ vi.clearAllMocks();
120
122
 
121
123
  await userEvent.click(before as any);
122
124
  expect(onClick).not.toHaveBeenCalled();
@@ -134,12 +136,12 @@ describe('<Chip />', () => {
134
136
  await userEvent.click(chip);
135
137
  expect(onAfterClick).not.toHaveBeenCalled();
136
138
 
137
- jest.clearAllMocks();
139
+ vi.clearAllMocks();
138
140
 
139
141
  await userEvent.click(after as any);
140
142
  expect(onAfterClick).toHaveBeenCalled();
141
143
 
142
- jest.clearAllMocks();
144
+ vi.clearAllMocks();
143
145
 
144
146
  await userEvent.click(before as any);
145
147
  expect(onAfterClick).not.toHaveBeenCalled();
@@ -162,7 +164,7 @@ describe('<Chip />', () => {
162
164
  });
163
165
 
164
166
  it('should forward key down event', async () => {
165
- const onKeyDown = jest.fn();
167
+ const onKeyDown = vi.fn();
166
168
  const { chip } = setup({ onClick, onKeyDown });
167
169
 
168
170
  fireEvent.keyDown(chip, { key: 'A', code: 'KeyA' });
@@ -171,7 +173,7 @@ describe('<Chip />', () => {
171
173
 
172
174
  it('should forward key down event and trigger `onClick` when pressing Enter', async () => {
173
175
  const user = userEvent.setup();
174
- const onKeyDown = jest.fn();
176
+ const onKeyDown = vi.fn();
175
177
  const { chip } = setup({ onClick, onKeyDown });
176
178
 
177
179
  await user.tab();
@@ -187,7 +189,7 @@ describe('<Chip />', () => {
187
189
 
188
190
  describe('Disabled state', () => {
189
191
  it('should render disabled chip button', async () => {
190
- const onClick = jest.fn();
192
+ const onClick = vi.fn();
191
193
  const { chip } = setup({ children: 'Label', isDisabled: true, onClick });
192
194
  expect(chip).toHaveAttribute('aria-disabled', 'true');
193
195
  await userEvent.click(chip);
@@ -195,7 +197,7 @@ describe('<Chip />', () => {
195
197
  });
196
198
 
197
199
  it('should render disabled chip link', async () => {
198
- const onClick = jest.fn();
200
+ const onClick = vi.fn();
199
201
  const { chip } = setup({ children: 'Label', isDisabled: true, href: 'https://example.com', onClick });
200
202
  // Disabled link should not have an href.
201
203
  expect(chip).not.toHaveAttribute('href');
@@ -205,7 +207,7 @@ describe('<Chip />', () => {
205
207
  });
206
208
 
207
209
  it('should render aria-disabled chip button', async () => {
208
- const onClick = jest.fn();
210
+ const onClick = vi.fn();
209
211
  const { chip } = setup({ children: 'Label', 'aria-disabled': true, onClick });
210
212
  expect(chip).toHaveAttribute('aria-disabled', 'true');
211
213
  await userEvent.click(chip);
@@ -214,7 +216,7 @@ describe('<Chip />', () => {
214
216
  });
215
217
 
216
218
  it('should render aria-disabled chip link', async () => {
217
- const onClick = jest.fn();
219
+ const onClick = vi.fn();
218
220
  const { chip } = setup({
219
221
  children: 'Label',
220
222
  'aria-disabled': true,
@@ -9,15 +9,15 @@ import { DatePicker } from '.';
9
9
  import { CLASSNAME } from './constants';
10
10
 
11
11
  const mockedDate = new Date(1487721600000);
12
- Date.now = jest.fn(() => mockedDate.valueOf());
13
- jest.mock('@lumx/react/utils/date/getYearDisplayName', () => ({
12
+ Date.now = vi.fn(() => mockedDate.valueOf());
13
+ vi.mock('@lumx/react/utils/date/getYearDisplayName', () => ({
14
14
  getYearDisplayName: () => 'année',
15
15
  }));
16
16
 
17
17
  const setup = (propsOverride: Partial<DatePickerProps> = {}) => {
18
18
  const props: DatePickerProps = {
19
19
  locale: 'fr',
20
- onChange: jest.fn(),
20
+ onChange: vi.fn(),
21
21
  value: mockedDate,
22
22
  nextButtonProps: { label: 'Next month' },
23
23
  previousButtonProps: { label: 'Previous month' },
@@ -10,8 +10,8 @@ import { DatePickerControlled, DatePickerControlledProps } from './DatePickerCon
10
10
  import { CLASSNAME } from './constants';
11
11
 
12
12
  const mockedDate = new Date(1487721600000);
13
- Date.now = jest.fn(() => mockedDate.valueOf());
14
- jest.mock('@lumx/react/utils/date/getYearDisplayName', () => ({
13
+ Date.now = vi.fn(() => mockedDate.valueOf());
14
+ vi.mock('@lumx/react/utils/date/getYearDisplayName', () => ({
15
15
  getYearDisplayName: () => 'année',
16
16
  }));
17
17
 
@@ -20,14 +20,14 @@ type SetupProps = Partial<DatePickerControlledProps>;
20
20
  const setup = (propsOverride: SetupProps = {}) => {
21
21
  const props: DatePickerControlledProps = {
22
22
  locale: 'fr',
23
- onChange: jest.fn(),
24
- onNextMonthChange: jest.fn(),
25
- onPrevMonthChange: jest.fn(),
23
+ onChange: vi.fn(),
24
+ onNextMonthChange: vi.fn(),
25
+ onPrevMonthChange: vi.fn(),
26
26
  selectedMonth: mockedDate,
27
27
  value: mockedDate,
28
28
  nextButtonProps: { label: 'Next month' },
29
29
  previousButtonProps: { label: 'Previous month' },
30
- onMonthChange: jest.fn(),
30
+ onMonthChange: vi.fn(),
31
31
  ...propsOverride,
32
32
  };
33
33
  render(<DatePickerControlled {...props} />);
@@ -10,8 +10,8 @@ import { DatePickerField, DatePickerFieldProps } from './DatePickerField';
10
10
  import { CLASSNAME } from './constants';
11
11
 
12
12
  const mockedDate = new Date(1487721600000);
13
- Date.now = jest.fn(() => mockedDate.valueOf());
14
- jest.mock('@lumx/react/utils/date/getYearDisplayName', () => ({
13
+ Date.now = vi.fn(() => mockedDate.valueOf());
14
+ vi.mock('@lumx/react/utils/date/getYearDisplayName', () => ({
15
15
  getYearDisplayName: () => 'année',
16
16
  }));
17
17
 
@@ -19,7 +19,7 @@ const setup = (propsOverride: Partial<DatePickerFieldProps> = {}, { wrapper }: S
19
19
  const props: DatePickerFieldProps = {
20
20
  label: 'DatePickerField',
21
21
  locale: 'fr',
22
- onChange: jest.fn(),
22
+ onChange: vi.fn(),
23
23
  value: mockedDate,
24
24
  nextButtonProps: { label: 'Next month' },
25
25
  previousButtonProps: { label: 'Previous month' },
@@ -51,7 +51,7 @@ describe(`<${Dialog.displayName}>`, () => {
51
51
 
52
52
  describe('Events', () => {
53
53
  it('should trigger `onClose` when pressing `escape` key', async () => {
54
- const onClose = jest.fn();
54
+ const onClose = vi.fn();
55
55
  setup({ isOpen: true, onClose });
56
56
 
57
57
  await userEvent.keyboard('[Escape]');
@@ -59,7 +59,7 @@ describe(`<${Dialog.displayName}>`, () => {
59
59
  });
60
60
 
61
61
  it('should not trigger `onClose` when pressing any other key', async () => {
62
- const onClose = jest.fn();
62
+ const onClose = vi.fn();
63
63
  setup({ isOpen: true, onClose });
64
64
 
65
65
  await userEvent.keyboard('a');
@@ -67,7 +67,7 @@ describe(`<${Dialog.displayName}>`, () => {
67
67
  });
68
68
 
69
69
  it('should not trigger `onClose` when pressing `escape` key with `preventAutoClose` set to `true`', async () => {
70
- const onClose = jest.fn();
70
+ const onClose = vi.fn();
71
71
  setup({ isOpen: true, onClose, preventAutoClose: true });
72
72
 
73
73
  await userEvent.keyboard('[Escape]');
@@ -75,7 +75,7 @@ describe(`<${Dialog.displayName}>`, () => {
75
75
  });
76
76
 
77
77
  it('should not trigger `onClose` when pressing `escape` key with `preventCloseOnEscape` set to `true`', async () => {
78
- const onClose = jest.fn();
78
+ const onClose = vi.fn();
79
79
  setup({ isOpen: true, onClose, preventCloseOnEscape: true });
80
80
 
81
81
  await userEvent.keyboard('[Escape]');
@@ -28,7 +28,7 @@ const setup = (propsOverride: Partial<DropdownProps> = {}) => {
28
28
  describe(`<${Dropdown.displayName}>`, () => {
29
29
  describe('Events', () => {
30
30
  it('should trigger `onClose` when pressing `escape` key', async () => {
31
- const onClose = jest.fn();
31
+ const onClose = vi.fn();
32
32
  setup({
33
33
  closeOnEscape: true,
34
34
  onClose,
@@ -40,7 +40,7 @@ describe(`<${Dropdown.displayName}>`, () => {
40
40
  });
41
41
 
42
42
  it('should not trigger `onClose` when pressing any other key', async () => {
43
- const onClose = jest.fn();
43
+ const onClose = vi.fn();
44
44
  setup({ isOpen: true, onClose, closeOnEscape: true });
45
45
 
46
46
  await userEvent.keyboard('a');
@@ -48,7 +48,7 @@ describe(`<${Dropdown.displayName}>`, () => {
48
48
  });
49
49
 
50
50
  it('should not trigger `onClose` when pressing `escape` key with `closeOnEscape` set to `false`', async () => {
51
- const onClose = jest.fn();
51
+ const onClose = vi.fn();
52
52
  setup({ isOpen: true, onClose, closeOnEscape: false });
53
53
 
54
54
  await userEvent.keyboard('[Escape]');
@@ -1,3 +1,4 @@
1
+ import { Mock } from 'vitest';
1
2
  import React from 'react';
2
3
 
3
4
  import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
@@ -11,7 +12,7 @@ import { ExpansionPanel, ExpansionPanelProps } from '.';
11
12
 
12
13
  const CLASSNAME = ExpansionPanel.className as string;
13
14
 
14
- jest.mock('@lumx/react/utils/browser/isFocusVisible');
15
+ vi.mock('@lumx/react/utils/browser/isFocusVisible');
15
16
 
16
17
  const mockChildrenContent = 'children content';
17
18
 
@@ -55,7 +56,7 @@ const setup = (
55
56
  };
56
57
 
57
58
  describe(`<${ExpansionPanel.displayName}>`, () => {
58
- (isFocusVisible as jest.Mock).mockReturnValue(false);
59
+ (isFocusVisible as Mock).mockReturnValue(false);
59
60
 
60
61
  describe('Render', () => {
61
62
  it('should render default', () => {
@@ -100,9 +101,9 @@ describe(`<${ExpansionPanel.displayName}>`, () => {
100
101
  });
101
102
 
102
103
  describe('Events', () => {
103
- const onOpen = jest.fn();
104
- const onClose = jest.fn();
105
- const onToggleOpen = jest.fn();
104
+ const onOpen = vi.fn();
105
+ const onClose = vi.fn();
106
+ const onToggleOpen = vi.fn();
106
107
 
107
108
  beforeEach(onOpen.mockClear);
108
109
  beforeEach(onClose.mockClear);
@@ -1,21 +1,47 @@
1
- import DefaultStory, { SizeAndShape as DefaultSizeAndShape } from '@lumx/core/js/components/Icon/Stories';
2
1
  import { mdiEmail } from '@lumx/icons';
3
- import { ColorPalette, ColorVariant, GridColumn, Icon, Size } from '@lumx/react';
2
+ import { ColorPalette, ColorVariant, GridColumn, Icon, IconSizes, Size } from '@lumx/react';
4
3
  import { withCombinations } from '@lumx/react/stories/decorators/withCombinations';
5
4
  import { withUndefined } from '@lumx/react/stories/controls/withUndefined';
5
+ import { iconArgType } from '@lumx/react/stories/controls/icons';
6
+ import { colorArgType, colorVariantArgType } from '@lumx/react/stories/controls/color';
6
7
  import { withWrapper } from '@lumx/react/stories/decorators/withWrapper';
7
8
 
9
+ const iconSizes: Array<IconSizes> = [Size.xxs, Size.xs, Size.s, Size.m, Size.l, Size.xl, Size.xxl];
10
+
8
11
  export default {
9
12
  title: 'LumX components/icon/Icon',
10
13
  component: Icon,
11
- ...DefaultStory,
14
+ args: Icon.defaultProps,
15
+ argTypes: {
16
+ icon: iconArgType,
17
+ hasShape: { control: 'boolean' },
18
+ color: colorArgType,
19
+ colorVariant: colorVariantArgType,
20
+ },
12
21
  };
13
22
 
14
23
  /**
15
24
  * All combinations of size and shape
16
25
  */
17
26
  export const SizeAndShape = {
18
- ...DefaultSizeAndShape,
27
+ args: {
28
+ icon: mdiEmail,
29
+ },
30
+ argTypes: {
31
+ hasShape: { control: false },
32
+ size: { control: false },
33
+ },
34
+ decorators: [
35
+ withCombinations({
36
+ combinations: {
37
+ cols: { key: 'size', options: withUndefined(iconSizes) },
38
+ rows: {
39
+ Default: {},
40
+ 'Has shape': { hasShape: true },
41
+ },
42
+ },
43
+ }),
44
+ ],
19
45
  };
20
46
 
21
47
  /**