@groupeactual/ui-kit 1.7.10 → 2.0.0-beta.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 (143) hide show
  1. package/dist/cjs/index.js +15097 -66
  2. package/dist/es/{src/DesignSystemProvider.d.ts → DesignSystemProvider.d.ts} +6 -5
  3. package/dist/es/{src/components → components}/Accordion/Accordion.d.ts +1 -1
  4. package/dist/es/{src/components → components}/BannerNotification/BannerNotification.d.ts +1 -1
  5. package/dist/es/{src/components → components}/Breadcrumbs/Breadcrumbs.d.ts +2 -2
  6. package/dist/es/{src/components → components}/Button/Button.d.ts +2 -2
  7. package/dist/es/{src/components → components}/Chip/Chip.d.ts +1 -1
  8. package/dist/es/components/Datatable/Datatable.d.ts +4 -0
  9. package/dist/es/{src/components → components}/EmbbededNotification/EmbeddedNotification.d.ts +1 -1
  10. package/dist/es/{src/components/UploadDocument → components/FileUploader}/FileUploader.d.ts +1 -1
  11. package/dist/es/components/Form/AutoCompleteMulti/AutoCompleteMulti.d.ts +23 -0
  12. package/dist/es/{src/components → components}/Form/AutoCompleteSingle/AutoCompleteSingle.d.ts +8 -5
  13. package/dist/es/components/Form/Checkbox/Checkbox.d.ts +12 -0
  14. package/dist/es/components/Form/CheckboxGroup/CheckboxGroup.d.ts +12 -0
  15. package/dist/es/components/Form/CheckboxGroup/checkboxgroup.interface.d.ts +6 -0
  16. package/dist/es/{src/components → components}/Form/DatePicker/DatePicker.d.ts +6 -4
  17. package/dist/es/{src/components → components}/Form/MultiSelect/MultiSelect.d.ts +3 -3
  18. package/dist/es/components/Form/RadioGroup/RadioGroup.d.ts +16 -0
  19. package/dist/es/{src/components → components}/Form/Select/Select.d.ts +3 -3
  20. package/dist/es/components/Form/Switch/Switch.d.ts +11 -0
  21. package/dist/es/{src/components → components}/Form/TextField/TextField.d.ts +6 -5
  22. package/dist/es/{src/components → components}/Form/TimePicker/TimePicker.d.ts +3 -3
  23. package/dist/es/{src/components → components}/IconButton/IconButton.d.ts +3 -3
  24. package/dist/es/components/IconProvider/IconProvider.d.ts +24 -0
  25. package/dist/es/{src/components → components}/Link/Link.d.ts +1 -2
  26. package/dist/es/components/MenuItem/MenuItem.d.ts +9 -0
  27. package/dist/es/components/Modal/Dialog/Dialog.d.ts +4 -0
  28. package/dist/es/components/Modal/Drawer/Drawer.d.ts +4 -0
  29. package/dist/es/{src/components → components}/Navigation/Stepper/Stepper.d.ts +1 -1
  30. package/dist/es/{src/components → components}/Pagination/Pagination.d.ts +2 -1
  31. package/dist/es/{src/components → components}/Snackbar/Snackbar.d.ts +1 -1
  32. package/dist/es/components/TabsPanel/TabsPanel.d.ts +4 -0
  33. package/dist/es/components/TabsPanel/index.d.ts +1 -0
  34. package/dist/es/components/TabsPanel/tab.interface.d.ts +17 -0
  35. package/dist/es/components/Text/Text.d.ts +8 -0
  36. package/dist/es/{src/components → components}/Tooltip/Tooltip.d.ts +1 -1
  37. package/dist/es/{src/components → components}/index.d.ts +3 -2
  38. package/dist/es/index.d.ts +104 -152
  39. package/dist/es/index.js +37 -79
  40. package/package.json +20 -17
  41. package/src/DesignSystemProvider.tsx +21 -36
  42. package/src/components/Accordion/Accordion.tsx +41 -59
  43. package/src/components/BannerNotification/BannerNotification.tsx +19 -20
  44. package/src/components/Breadcrumbs/Breadcrumbs.tsx +32 -28
  45. package/src/components/Button/Button.tsx +70 -17
  46. package/src/components/Chip/Chip.tsx +88 -117
  47. package/src/components/Datatable/Datatable.tsx +49 -37
  48. package/src/components/Datatable/DatatableCellRender.tsx +1 -1
  49. package/src/components/EmbbededNotification/EmbeddedNotification.tsx +78 -69
  50. package/src/components/FileUploader/FileUploader.tsx +767 -0
  51. package/src/components/Form/AutoCompleteMulti/AutoCompleteMulti.tsx +289 -172
  52. package/src/components/Form/AutoCompleteSingle/AutoCompleteSingle.tsx +228 -126
  53. package/src/components/Form/Checkbox/Checkbox.tsx +38 -96
  54. package/src/components/Form/CheckboxGroup/CheckboxGroup.tsx +86 -60
  55. package/src/components/Form/CheckboxGroup/checkboxgroup.interface.ts +0 -15
  56. package/src/components/Form/DatePicker/DatePicker.tsx +88 -40
  57. package/src/components/Form/MultiSelect/MultiSelect.tsx +196 -171
  58. package/src/components/Form/RadioGroup/RadioGroup.tsx +76 -82
  59. package/src/components/Form/Select/Select.tsx +156 -136
  60. package/src/components/Form/Switch/Switch.tsx +87 -47
  61. package/src/components/Form/TextField/TextField.tsx +125 -76
  62. package/src/components/Form/TimePicker/TimePicker.tsx +26 -7
  63. package/src/components/IconButton/IconButton.tsx +64 -39
  64. package/src/components/IconProvider/IconProvider.tsx +90 -69
  65. package/src/components/Link/Link.tsx +6 -10
  66. package/src/components/MenuItem/MenuItem.tsx +35 -23
  67. package/src/components/Modal/Dialog/Dialog.tsx +17 -14
  68. package/src/components/Modal/Drawer/Drawer.tsx +95 -74
  69. package/src/components/Navigation/Stepper/Step.tsx +7 -6
  70. package/src/components/Navigation/Stepper/Stepper.tsx +24 -23
  71. package/src/components/NotistackAdapter/NotistackAdapter.tsx +1 -1
  72. package/src/components/Pagination/Pagination.tsx +131 -118
  73. package/src/components/Snackbar/Snackbar.tsx +29 -29
  74. package/src/components/TabsPanel/TabsPanel.tsx +151 -0
  75. package/src/components/TabsPanel/index.ts +1 -0
  76. package/src/components/TabsPanel/tab.interface.ts +20 -0
  77. package/src/components/Text/Text.tsx +25 -12
  78. package/src/components/Tooltip/Tooltip.tsx +54 -51
  79. package/src/components/index.ts +3 -2
  80. package/src/index.ts +0 -1
  81. package/dist/es/src/components/Datatable/Datatable.d.ts +0 -4
  82. package/dist/es/src/components/Form/AutoCompleteMulti/AutoCompleteMulti.d.ts +0 -19
  83. package/dist/es/src/components/Form/Checkbox/Checkbox.d.ts +0 -14
  84. package/dist/es/src/components/Form/CheckboxGroup/CheckboxGroup.d.ts +0 -12
  85. package/dist/es/src/components/Form/CheckboxGroup/checkboxgroup.interface.d.ts +0 -8
  86. package/dist/es/src/components/Form/RadioGroup/RadioGroup.d.ts +0 -18
  87. package/dist/es/src/components/Form/Switch/Switch.d.ts +0 -10
  88. package/dist/es/src/components/IconProvider/IconProvider.d.ts +0 -19
  89. package/dist/es/src/components/MenuItem/MenuItem.d.ts +0 -10
  90. package/dist/es/src/components/Modal/Dialog/Dialog.d.ts +0 -4
  91. package/dist/es/src/components/Modal/Drawer/Drawer.d.ts +0 -4
  92. package/dist/es/src/components/Text/Text.d.ts +0 -8
  93. package/dist/es/src/index.d.ts +0 -5
  94. package/dist/es/src/interfaces/theme.d.ts +0 -51
  95. package/src/components/UploadDocument/FileUploader.tsx +0 -728
  96. package/src/interfaces/theme.ts +0 -51
  97. /package/dist/es/{src/components → components}/Accordion/index.d.ts +0 -0
  98. /package/dist/es/{src/components → components}/BannerNotification/index.d.ts +0 -0
  99. /package/dist/es/{src/components → components}/Breadcrumbs/index.d.ts +0 -0
  100. /package/dist/es/{src/components → components}/Button/index.d.ts +0 -0
  101. /package/dist/es/{src/components → components}/Chip/index.d.ts +0 -0
  102. /package/dist/es/{src/components → components}/Datatable/DatatableCellRender.d.ts +0 -0
  103. /package/dist/es/{src/components → components}/Datatable/datatable.interface.d.ts +0 -0
  104. /package/dist/es/{src/components → components}/Datatable/index.d.ts +0 -0
  105. /package/dist/es/{src/components → components}/Datatable/use-pagination-props.hook.d.ts +0 -0
  106. /package/dist/es/{src/components → components}/EmbbededNotification/index.d.ts +0 -0
  107. /package/dist/es/{src/components/UploadDocument → components/FileUploader}/fileuploader.interface.d.ts +0 -0
  108. /package/dist/es/{src/components/UploadDocument → components/FileUploader}/index.d.ts +0 -0
  109. /package/dist/es/{src/components → components}/Form/AutoCompleteMulti/index.d.ts +0 -0
  110. /package/dist/es/{src/components → components}/Form/AutoCompleteSingle/index.d.ts +0 -0
  111. /package/dist/es/{src/components → components}/Form/Checkbox/index.d.ts +0 -0
  112. /package/dist/es/{src/components → components}/Form/CheckboxGroup/index.d.ts +0 -0
  113. /package/dist/es/{src/components → components}/Form/DatePicker/index.d.ts +0 -0
  114. /package/dist/es/{src/components → components}/Form/MultiSelect/index.d.ts +0 -0
  115. /package/dist/es/{src/components → components}/Form/RadioGroup/index.d.ts +0 -0
  116. /package/dist/es/{src/components → components}/Form/Select/index.d.ts +0 -0
  117. /package/dist/es/{src/components → components}/Form/Switch/index.d.ts +0 -0
  118. /package/dist/es/{src/components → components}/Form/TextField/index.d.ts +0 -0
  119. /package/dist/es/{src/components → components}/Form/TimePicker/index.d.ts +0 -0
  120. /package/dist/es/{src/components → components}/IconButton/index.d.ts +0 -0
  121. /package/dist/es/{src/components → components}/IconProvider/index.d.ts +0 -0
  122. /package/dist/es/{src/components → components}/Link/index.d.ts +0 -0
  123. /package/dist/es/{src/components → components}/MenuItem/index.d.ts +0 -0
  124. /package/dist/es/{src/components → components}/Modal/Dialog/index.d.ts +0 -0
  125. /package/dist/es/{src/components → components}/Modal/Drawer/index.d.ts +0 -0
  126. /package/dist/es/{src/components → components}/Modal/modal.interface.d.ts +0 -0
  127. /package/dist/es/{src/components → components}/Navigation/Stepper/Step.d.ts +0 -0
  128. /package/dist/es/{src/components → components}/Navigation/Stepper/index.d.ts +0 -0
  129. /package/dist/es/{src/components → components}/Navigation/Stepper/stepper.helper.d.ts +0 -0
  130. /package/dist/es/{src/components → components}/Navigation/Stepper/stepper.interface.d.ts +0 -0
  131. /package/dist/es/{src/components → components}/NotistackAdapter/NotistackAdapter.d.ts +0 -0
  132. /package/dist/es/{src/components → components}/NotistackAdapter/index.d.ts +0 -0
  133. /package/dist/es/{src/components → components}/Pagination/index.d.ts +0 -0
  134. /package/dist/es/{src/components → components}/Pagination/pagination.helper.d.ts +0 -0
  135. /package/dist/es/{src/components → components}/Snackbar/index.d.ts +0 -0
  136. /package/dist/es/{src/components → components}/Text/index.d.ts +0 -0
  137. /package/dist/es/{src/components → components}/Tooltip/index.d.ts +0 -0
  138. /package/dist/es/{src/components → components}/Tooltip/tooltip.interface.d.ts +0 -0
  139. /package/dist/es/{src/helpers → helpers}/GooglePickerWrapper.d.ts +0 -0
  140. /package/dist/es/{src/hooks → hooks}/useGooleDrivePicker.d.ts +0 -0
  141. /package/dist/es/{src/types → types}/googleDrive.d.ts +0 -0
  142. /package/src/components/{UploadDocument → FileUploader}/fileuploader.interface.ts +0 -0
  143. /package/src/components/{UploadDocument → FileUploader}/index.ts +0 -0
@@ -1,4 +1,10 @@
1
- import React, { FocusEventHandler, useMemo, useRef } from 'react';
1
+ import React, {
2
+ FocusEventHandler,
3
+ ReactNode,
4
+ useId,
5
+ useMemo,
6
+ useRef,
7
+ } from 'react';
2
8
 
3
9
  import {
4
10
  faCheck,
@@ -6,29 +12,26 @@ import {
6
12
  faTimes,
7
13
  } from '@fortawesome/pro-regular-svg-icons';
8
14
  import { faCircleX } from '@fortawesome/pro-solid-svg-icons';
9
- import { SelectStyle } from '@groupeactual/design-tokens';
10
15
  import {
11
16
  Box,
12
- FormControl,
13
17
  FormHelperText,
14
18
  InputLabel,
15
- MenuItem,
16
19
  Select as MuiSelect,
17
20
  SelectChangeEvent,
18
21
  SelectProps,
19
- styled,
20
- useTheme,
21
22
  } from '@mui/material';
22
23
 
23
24
  import Chip from '@/components/Chip';
24
25
  import IconProvider from '@/components/IconProvider';
26
+ import MenuItem from '@/components/MenuItem';
27
+ import Text from '@/components/Text';
25
28
 
26
29
  interface Props<T>
27
30
  extends Omit<
28
31
  SelectProps<T[]>,
29
32
  'value' | 'onChange' | 'value' | 'color' | 'error'
30
33
  > {
31
- label: string;
34
+ label: ReactNode;
32
35
  options: T[] | [];
33
36
  helperText?: string;
34
37
  color?: 'success';
@@ -56,26 +59,35 @@ const MenuProps = {
56
59
  },
57
60
  };
58
61
 
59
- const MultiSelect = <T,>({
60
- value,
61
- label,
62
- options,
63
- color,
64
- error,
65
- placeholder = '',
66
- helperText,
67
- width = '100%',
68
- getRenderValue,
69
- getKeyValue,
70
- onChange,
71
- disabled,
72
- ...props
73
- }: Props<T>) => {
74
- const theme = useTheme();
75
- const StyledMultiSelectForm = useMemo(
76
- () => styled(FormControl)(SelectStyle(theme)),
77
- [theme],
78
- );
62
+ function fixedForwardRef<T, P = {}>(
63
+ render: (_props: P, _ref: React.Ref<T>) => React.ReactNode,
64
+ ): (_props: P & React.RefAttributes<T>) => React.ReactNode {
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ return React.forwardRef(render as any) as any;
67
+ }
68
+
69
+ const MultiSelectComponent = <T,>(
70
+ {
71
+ value,
72
+ label,
73
+ options,
74
+ color,
75
+ error,
76
+ placeholder = '',
77
+ helperText,
78
+ width = '100%',
79
+ getRenderValue,
80
+ getKeyValue,
81
+ onChange,
82
+ disabled,
83
+ ...props
84
+ }: Props<T>,
85
+ ref: React.ForwardedRef<HTMLSelectElement>,
86
+ ) => {
87
+ const generatedId = useId();
88
+ const boxRef = useRef<HTMLHeadingElement>(null);
89
+
90
+ const inputId = props.name || `multi-select-${generatedId}`;
79
91
  const [isOpened, setIsOpened] = React.useState(props.open ?? false);
80
92
 
81
93
  const handleChange = (event: SelectChangeEvent<typeof options>) =>
@@ -90,169 +102,182 @@ const MultiSelect = <T,>({
90
102
  event.stopPropagation();
91
103
  };
92
104
 
93
- const getFormControlClassName = useMemo(() => {
105
+ const getClassName = useMemo(() => {
94
106
  const classNames = [
95
- 'DsMultiSelect',
96
- (!placeholder && 'Select-mui') || 'Select-ds',
97
- value.length > 0 && 'Mui-filled',
107
+ value && 'Mui-filled',
98
108
  error && 'Mui-error',
109
+ disabled && 'Mui-disabled',
110
+ color === 'success' && 'Mui-success',
99
111
  ];
100
112
 
101
113
  return classNames.filter(Boolean).join(' ');
102
- }, [value, error, placeholder]);
103
-
104
- const boxRef = useRef<HTMLHeadingElement>(null);
114
+ }, [value, error, color, disabled]);
105
115
 
106
116
  return (
107
- <Box sx={{ width }} ref={boxRef}>
108
- <StyledMultiSelectForm
109
- fullWidth
110
- color={color}
111
- className={getFormControlClassName}
117
+ <Box
118
+ ref={boxRef}
119
+ sx={{
120
+ '.MuiOutlinedInput-input': {
121
+ marginTop: value?.length > 0 ? '0px' : '2px',
122
+ },
123
+ }}
124
+ data-testid="ds-multi-select-container"
125
+ >
126
+ {label && (
127
+ <InputLabel
128
+ htmlFor={inputId}
129
+ disabled={disabled}
130
+ className={getClassName}
131
+ id={props?.labelId}
132
+ data-testid="ds-multi-select-label"
133
+ >
134
+ {label}
135
+ </InputLabel>
136
+ )}
137
+ <MuiSelect
138
+ ref={ref}
139
+ id={inputId}
112
140
  disabled={disabled}
141
+ className={getClassName + ' MuiMultipleSelect'}
113
142
  sx={{
114
- '.MuiOutlinedInput-input': {
115
- marginTop: value?.length > 0 ? '0px' : '2px',
116
- },
143
+ width,
144
+ color: color + '! important',
145
+ '& .MuiSelect-select .notranslate::after': placeholder
146
+ ? {
147
+ content: `"${placeholder}"`,
148
+ opacity:
149
+ label === placeholder ? '0 !important' : '1 !important',
150
+ }
151
+ : {},
117
152
  }}
118
- >
119
- <InputLabel disabled={disabled} error={!!error}>
120
- {label}
121
- </InputLabel>
122
- <MuiSelect
123
- sx={{
124
- color: color + '! important',
125
- '& .MuiSelect-select .notranslate::after': placeholder
126
- ? {
127
- content: `"${placeholder}"`,
128
- opacity:
129
- label === placeholder ? '0 !important' : '1 !important',
130
- }
131
- : {},
132
- }}
133
- multiple
134
- label={label}
135
- notched={(placeholder && true) || undefined}
136
- value={value}
137
- onChange={handleChange}
138
- renderValue={(selected) => (
139
- <Box sx={{ display: 'flex' }}>
140
- <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
141
- {selected.map((selectedOption: T) => (
142
- <Chip
143
- key={getKeyValue(selectedOption)}
144
- variant={disabled ? 'outlined' : 'filled'}
145
- color="default"
146
- label={getRenderValue(selectedOption)}
147
- onMouseDown={preventEventPropagation}
148
- disabled={disabled}
149
- suffixIcon={faCircleX}
150
- suffixAction={() =>
151
- !disabled && handleDeleteChip(selectedOption)
152
- }
153
- sx={{
154
- m: 0,
155
- maxWidth: boxRef?.current
156
- ? parseFloat(
157
- String(boxRef.current?.offsetWidth).replace(
158
- 'px',
159
- '',
160
- ),
161
- ) - 60
162
- : width,
163
- }}
164
- />
165
- ))}
166
- </Box>
167
- <Box flexGrow={1} />
168
- {!disabled && (
169
- <Box
170
- className="clear"
171
- onClick={handleClearValues}
153
+ multiple
154
+ notched={(placeholder && true) || undefined}
155
+ value={value}
156
+ onChange={handleChange}
157
+ renderValue={(selected) => (
158
+ <Box sx={{ display: 'flex' }} data-testid="ds-render-value">
159
+ <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
160
+ {selected.map((selectedOption: T) => (
161
+ <Chip
162
+ key={getKeyValue(selectedOption)}
163
+ variant={disabled ? 'outlined' : 'filled'}
164
+ color="default"
165
+ label={getRenderValue(selectedOption)}
172
166
  onMouseDown={preventEventPropagation}
173
- >
174
- <IconProvider icon={faTimes} />
175
- </Box>
176
- )}
167
+ disabled={disabled}
168
+ suffixIcon={faCircleX}
169
+ suffixAction={() =>
170
+ !disabled && handleDeleteChip(selectedOption)
171
+ }
172
+ sx={{
173
+ m: 0,
174
+ maxWidth: boxRef?.current
175
+ ? parseFloat(
176
+ String(boxRef.current?.offsetWidth).replace('px', ''),
177
+ ) - 70
178
+ : width,
179
+ }}
180
+ data-testid="ds-chip"
181
+ />
182
+ ))}
177
183
  </Box>
178
- )}
179
- IconComponent={({ className }) => (
180
- <IconProvider
181
- className={disabled ? 'Mui-disabled SelectIcon' : 'SelectIcon'}
182
- icon={color === 'success' ? faCheck : faChevronDown}
183
- size="md"
184
- onClick={() => {
185
- if (!disabled) {
186
- setIsOpened(!isOpened);
187
- }
188
- }}
189
- sx={{
190
- ':hover': {
191
- cursor: disabled ? 'auto' : 'pointer',
192
- },
193
- transform:
194
- className.toString().includes('iconOpen') &&
195
- color !== 'success'
196
- ? 'rotate(180deg)'
197
- : 'none',
198
- }}
199
- />
200
- )}
201
- MenuProps={MenuProps}
202
- {...props}
203
- open={isOpened}
204
- onClose={(e) => {
205
- if (!disabled) {
206
- if (props.onClose) {
207
- props.onClose(e);
184
+ <Box flexGrow={1} />
185
+ {!disabled && (
186
+ <Box
187
+ className="clear"
188
+ sx={{
189
+ display: 'inline-flex',
190
+ alignItems: 'center',
191
+ width: '16px',
192
+ }}
193
+ onClick={handleClearValues}
194
+ onMouseDown={preventEventPropagation}
195
+ data-testid="ds-clear-icon"
196
+ >
197
+ <IconProvider icon={faTimes} />
198
+ </Box>
199
+ )}
200
+ </Box>
201
+ )}
202
+ IconComponent={({ className }) => (
203
+ <IconProvider
204
+ className={disabled ? 'Mui-disabled SelectIcon' : 'SelectIcon'}
205
+ icon={color === 'success' ? faCheck : faChevronDown}
206
+ size="md"
207
+ onClick={() => {
208
+ if (!disabled) {
209
+ setIsOpened(!isOpened);
208
210
  }
209
-
210
- setIsOpened(false);
211
+ }}
212
+ sx={{
213
+ ':hover': {
214
+ cursor: disabled ? 'auto' : 'pointer',
215
+ },
216
+ transform:
217
+ className.toString().includes('iconOpen') && color !== 'success'
218
+ ? 'rotate(180deg)'
219
+ : 'none',
220
+ }}
221
+ data-testid="ds-icon-component"
222
+ />
223
+ )}
224
+ MenuProps={MenuProps}
225
+ {...props}
226
+ open={isOpened}
227
+ onClose={(e) => {
228
+ if (!disabled) {
229
+ if (props.onClose) {
230
+ props.onClose(e);
211
231
  }
212
- }}
213
- onOpen={(e) => {
214
- if (!disabled) {
215
- if (props.onOpen) {
216
- props.onOpen(e);
217
- }
218
232
 
219
- setIsOpened(true);
233
+ setIsOpened(false);
234
+ }
235
+ }}
236
+ onOpen={(e) => {
237
+ if (!disabled) {
238
+ if (props.onOpen) {
239
+ props.onOpen(e);
220
240
  }
221
- }}
241
+
242
+ setIsOpened(true);
243
+ }
244
+ }}
245
+ data-testid="ds-mui-select"
246
+ >
247
+ {options?.map((option) => (
248
+ <MenuItem
249
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
250
+ {...(props as any)}
251
+ key={getKeyValue(option)}
252
+ value={option as never}
253
+ data-testid={`ds-menu-item-${getKeyValue(option)}`}
254
+ sx={{
255
+ wordBreak: 'break-word',
256
+ overflowWrap: 'break-word',
257
+ whiteSpace: 'normal',
258
+ hyphens: 'auto',
259
+ width: '100%',
260
+ }}
261
+ >
262
+ <Text variant="body2">{getRenderValue(option)}</Text>
263
+ </MenuItem>
264
+ ))}
265
+ </MuiSelect>
266
+ {(error || helperText) && (
267
+ <FormHelperText
268
+ component="span"
269
+ className={getClassName}
270
+ data-testid="ds-form-helper-text"
222
271
  >
223
- {options?.map((option) => (
224
- <MenuItem
225
- key={getKeyValue(option)}
226
- value={option as never}
227
- sx={{
228
- '&:hover': {
229
- backgroundColor: theme.palette['blueHoverEquivalence'],
230
- },
231
- '&.Mui-selected': {
232
- backgroundColor: theme.palette['greyXLight'] + ' !important',
233
- },
234
- fontSize: 14,
235
- fontWeight: value.indexOf(option) === -1 ? 400 : 500,
236
- whiteSpace: 'normal',
237
- wordWrap: 'break-word',
238
- minWidth: '100%',
239
- maxWidth: '100%',
240
- backgroundColor:
241
- value.indexOf(option) === -1 ? 'white' : 'greyXLight',
242
- }}
243
- >
244
- {getRenderValue(option)}
245
- </MenuItem>
246
- ))}
247
- </MuiSelect>
248
- {(error || helperText) && (
249
- <FormHelperText component="span" className={error ? 'Mui-error' : ''}>
250
- {error || helperText}
251
- </FormHelperText>
252
- )}
253
- </StyledMultiSelectForm>
272
+ {error || helperText}
273
+ </FormHelperText>
274
+ )}
254
275
  </Box>
255
276
  );
256
277
  };
257
278
 
279
+ MultiSelectComponent.displayName = 'MultiSelect';
280
+
281
+ const MultiSelect = fixedForwardRef(MultiSelectComponent);
282
+
258
283
  export default MultiSelect;
@@ -1,7 +1,5 @@
1
- import React, { ChangeEvent, useMemo } from 'react';
1
+ import React, { ChangeEvent, ReactNode, useMemo } from 'react';
2
2
 
3
- import { faInfoCircle } from '@fortawesome/pro-solid-svg-icons';
4
- import { RadioStyle } from '@groupeactual/design-tokens';
5
3
  import {
6
4
  Box,
7
5
  FormControl,
@@ -11,36 +9,17 @@ import {
11
9
  Radio as MUIRadio,
12
10
  RadioGroup as RadioGroupMUI,
13
11
  RadioGroupProps,
14
- styled,
15
- useTheme,
16
12
  } from '@mui/material';
17
13
 
18
- import IconProvider from '@/components/IconProvider';
19
14
  import Text from '@/components/Text';
20
- import Tooltip from '@/components/Tooltip';
21
15
 
22
16
  interface ItemType<T> {
23
- label: string;
17
+ label?: ReactNode;
24
18
  value: T;
25
- infoBubbleContent?: string;
26
- infoBubblePosition?:
27
- | 'top'
28
- | 'right'
29
- | 'bottom'
30
- | 'left'
31
- | 'bottom-end'
32
- | 'bottom-start'
33
- | 'left-end'
34
- | 'left-start'
35
- | 'right-end'
36
- | 'right-start'
37
- | 'top-end'
38
- | 'top-start'
39
- | undefined;
40
19
  }
41
20
 
42
21
  interface Props<T> extends Omit<RadioGroupProps, 'onChange'> {
43
- label: string;
22
+ label?: ReactNode;
44
23
  options: ItemType<T>[];
45
24
  onChange: (_value: T) => void;
46
25
  error?: string;
@@ -48,84 +27,99 @@ interface Props<T> extends Omit<RadioGroupProps, 'onChange'> {
48
27
  disabled?: boolean;
49
28
  }
50
29
 
51
- const RadioGroup = <T,>({
52
- options,
53
- value,
54
- label,
55
- onChange,
56
- helperText,
57
- disabled = false,
58
- error = '',
59
- ...props
60
- }: Props<T>) => {
61
- const theme = useTheme();
62
- const StyledRadioForm = useMemo(
63
- () => styled(FormControl)(RadioStyle(theme)),
64
- [theme],
65
- );
30
+ function fixedForwardRef<T, P = {}>(
31
+ render: (_props: P, _ref: React.Ref<T>) => React.ReactNode,
32
+ ): (_props: P & React.RefAttributes<T>) => React.ReactNode {
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ return React.forwardRef(render as any) as any;
35
+ }
66
36
 
37
+ const RadioGroupComponent = <T,>(
38
+ {
39
+ options,
40
+ value,
41
+ label,
42
+ onChange,
43
+ helperText,
44
+ disabled = false,
45
+ error = '',
46
+ ...props
47
+ }: Props<T>,
48
+ ref: React.ForwardedRef<HTMLTableElement>,
49
+ ) => {
67
50
  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
68
51
  onChange((event.target as HTMLInputElement).value as T);
69
52
  };
70
53
 
71
- const getFormControlClassName = useMemo(() => {
54
+ const getClassName = useMemo(() => {
72
55
  const classNames = [disabled && 'Mui-disabled', error && 'Mui-error'];
73
56
 
74
57
  return classNames.filter(Boolean).join(' ');
75
58
  }, [disabled, error]);
76
59
 
77
60
  return (
78
- <StyledRadioForm
61
+ <FormControl
79
62
  disabled={disabled}
80
63
  error={!!error}
81
- className={getFormControlClassName}
64
+ ref={ref}
65
+ data-testid="ds-radio-group-form-control"
82
66
  >
83
- <FormLabel>{label}</FormLabel>
84
- <RadioGroupMUI value={value} onChange={handleChange} {...props}>
85
- {options
86
- ?.slice(0, 7)
87
- .map(
88
- (
89
- { value, label, infoBubbleContent, infoBubblePosition },
90
- index,
91
- ) => (
92
- <FormControlLabel
93
- key={index}
94
- control={<MUIRadio size="small" />}
95
- value={value}
96
- label={
97
- <Box>
98
- <Text component="span" variant="body1">
99
- {label}
100
- </Text>
101
- {infoBubbleContent && (
102
- <Tooltip
103
- title={infoBubbleContent}
104
- placement={infoBubblePosition}
105
- sx={{
106
- ml: '6px',
107
- }}
108
- >
109
- <IconProvider
110
- icon={faInfoCircle}
111
- size="sm"
112
- color="blueInfo"
113
- />
114
- </Tooltip>
115
- )}
116
- </Box>
117
- }
118
- />
119
- ),
120
- )}
67
+ {label && (
68
+ <FormLabel
69
+ component="legend"
70
+ className={getClassName}
71
+ sx={{
72
+ marginLeft: '-6px',
73
+ marginBottom: '4px',
74
+ }}
75
+ data-testid="ds-radio-group-label"
76
+ >
77
+ {label}
78
+ </FormLabel>
79
+ )}
80
+ <RadioGroupMUI
81
+ value={value}
82
+ onChange={handleChange}
83
+ {...props}
84
+ data-testid="ds-radio-group"
85
+ >
86
+ {options?.slice(0, 7).map(({ value, label }, index) => (
87
+ <FormControlLabel
88
+ key={index}
89
+ control={
90
+ <MUIRadio size="small" data-testid={`ds-radio-${index}`} />
91
+ }
92
+ value={value}
93
+ label={
94
+ <Box
95
+ display="flex"
96
+ alignItems="center"
97
+ data-testid={`ds-radio-label-${index}`}
98
+ >
99
+ <Text component="span" variant="body1">
100
+ {label}
101
+ </Text>
102
+ </Box>
103
+ }
104
+ />
105
+ ))}
121
106
  </RadioGroupMUI>
122
107
  {((error || helperText) && (
123
- <FormHelperText component="span" className={error ? 'Mui-error' : ''}>
108
+ <FormHelperText
109
+ component="span"
110
+ className={getClassName}
111
+ sx={{ marginTop: '3px', marginLeft: '-6px' }}
112
+ data-testid="ds-radio-group-helper-text"
113
+ >
124
114
  {error || helperText}
125
115
  </FormHelperText>
126
116
  )) || <Box height={18} />}
127
- </StyledRadioForm>
117
+ </FormControl>
128
118
  );
129
119
  };
130
120
 
121
+ RadioGroupComponent.displayName = 'RadioGroup';
122
+
123
+ const RadioGroup = fixedForwardRef(RadioGroupComponent);
124
+
131
125
  export default RadioGroup;