@soyfri/shared-library 1.5.0 → 2.0.0-beta.1
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/build.js +75 -38
- package/dist/components/ActionMenu/ActionMenu.cjs +107 -0
- package/dist/components/ActionMenu/ActionMenu.cjs.map +1 -0
- package/dist/components/ActionMenu/ActionMenu.d.ts +60 -0
- package/dist/components/ActionMenu/ActionMenu.js +107 -0
- package/dist/components/ActionMenu/ActionMenu.js.map +1 -0
- package/dist/components/ActionMenu/index.d.ts +2 -0
- package/dist/components/ActionMenu.d.ts +6 -0
- package/dist/components/AppBar/AppBar.cjs +346 -0
- package/dist/components/AppBar/AppBar.cjs.map +1 -0
- package/dist/components/AppBar/AppBar.d.ts +55 -0
- package/dist/components/AppBar/AppBar.js +346 -0
- package/dist/components/AppBar/AppBar.js.map +1 -0
- package/dist/components/AppBar/AppBar.sx.d.ts +12 -0
- package/dist/components/AppBar/AppBarBrand.d.ts +31 -0
- package/dist/components/AppBar/AppBarContext.d.ts +18 -0
- package/dist/components/AppBar/AppBarMenuToggle.d.ts +39 -0
- package/dist/components/AppBar/AppBarUserMenu.d.ts +65 -0
- package/dist/components/AppBar/index.d.ts +12 -0
- package/dist/components/AppBar.d.ts +6 -0
- package/dist/components/Autocomplete/Autocomplete.cjs +259 -54
- package/dist/components/Autocomplete/Autocomplete.cjs.map +1 -1
- package/dist/components/Autocomplete/Autocomplete.d.ts +64 -9
- package/dist/components/Autocomplete/Autocomplete.definitions.d.ts +6 -0
- package/dist/components/Autocomplete/Autocomplete.helpers.d.ts +18 -0
- package/dist/components/Autocomplete/Autocomplete.js +261 -56
- package/dist/components/Autocomplete/Autocomplete.js.map +1 -1
- package/dist/components/Autocomplete/Autocomplete.sx.d.ts +7 -0
- package/dist/components/Autocomplete/Autocomplete.types.d.ts +1 -0
- package/dist/components/Autocomplete/_parts/AutocompleteChips.d.ts +19 -0
- package/dist/components/Autocomplete/_parts/AutocompleteLoader.d.ts +9 -0
- package/dist/components/Autocomplete/_parts/AutocompleteOption.d.ts +19 -0
- package/dist/components/Autocomplete/index.d.ts +2 -1
- package/dist/components/Autocomplete.d.ts +4 -0
- package/dist/components/Avatar/Avatar.cjs +116 -79
- package/dist/components/Avatar/Avatar.cjs.map +1 -1
- package/dist/components/Avatar/Avatar.d.ts +16 -2
- package/dist/components/Avatar/Avatar.definitions.d.ts +11 -0
- package/dist/components/Avatar/Avatar.js +117 -80
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Card/Card.cjs +168 -9
- package/dist/components/Card/Card.cjs.map +1 -1
- package/dist/components/Card/Card.d.ts +78 -8
- package/dist/components/Card/Card.js +170 -11
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Card/Card.sx.d.ts +17 -0
- package/dist/components/Card/index.d.ts +4 -1
- package/dist/components/Card.d.ts +4 -0
- package/dist/components/DatePicker/DatePicker.cjs +201 -3
- package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +47 -9
- package/dist/components/DatePicker/DatePicker.definitions.d.ts +1 -0
- package/dist/components/DatePicker/DatePicker.helpers.d.ts +7 -0
- package/dist/components/DatePicker/DatePicker.js +200 -2
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.sx.d.ts +9 -0
- package/dist/components/DatePicker/DatePicker.types.d.ts +1 -0
- package/dist/components/DatePicker/index.d.ts +2 -1
- package/dist/components/DatePicker.d.ts +4 -0
- package/dist/components/DateTimePicker/DateTimePicker.cjs +152 -138
- package/dist/components/DateTimePicker/DateTimePicker.cjs.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts +46 -9
- package/dist/components/DateTimePicker/DateTimePicker.definitions.d.ts +1 -0
- package/dist/components/DateTimePicker/DateTimePicker.helpers.d.ts +11 -0
- package/dist/components/DateTimePicker/DateTimePicker.js +152 -138
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.sx.d.ts +7 -0
- package/dist/components/DateTimePicker/DateTimePicker.types.d.ts +1 -0
- package/dist/components/DateTimePicker/index.d.ts +2 -1
- package/dist/components/DateTimePicker.d.ts +4 -0
- package/dist/components/Drawer/Drawer.cjs +271 -0
- package/dist/components/Drawer/Drawer.cjs.map +1 -0
- package/dist/components/Drawer/Drawer.d.ts +51 -0
- package/dist/components/Drawer/Drawer.js +271 -0
- package/dist/components/Drawer/Drawer.js.map +1 -0
- package/dist/components/Drawer/Drawer.sx.d.ts +23 -0
- package/dist/components/Drawer/DrawerContext.d.ts +18 -0
- package/dist/components/Drawer/DrawerItem.d.ts +35 -0
- package/dist/components/Drawer/index.d.ts +6 -0
- package/dist/components/Drawer.d.ts +6 -0
- package/dist/components/Icon/Icon.cjs +44 -3
- package/dist/components/Icon/Icon.cjs.map +1 -1
- package/dist/components/Icon/Icon.d.ts +34 -1
- package/dist/components/Icon/Icon.js +44 -3
- package/dist/components/Icon/Icon.js.map +1 -1
- package/dist/components/Input/Input.cjs +173 -3
- package/dist/components/Input/Input.cjs.map +1 -1
- package/dist/components/Input/Input.d.ts +20 -15
- package/dist/components/Input/Input.definitions.d.ts +5 -2
- package/dist/components/Input/Input.helpers.d.ts +14 -0
- package/dist/components/Input/Input.js +172 -2
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/Input/Input.sx.d.ts +8 -0
- package/dist/components/Input/Input.types.d.ts +1 -0
- package/dist/components/Input/index.d.ts +2 -1
- package/dist/components/Input.d.ts +4 -0
- package/dist/components/InputGroup/InputGroup.cjs +104 -91
- package/dist/components/InputGroup/InputGroup.cjs.map +1 -1
- package/dist/components/InputGroup/InputGroup.d.ts +37 -1
- package/dist/components/InputGroup/InputGroup.definitions.d.ts +6 -0
- package/dist/components/InputGroup/InputGroup.js +106 -93
- package/dist/components/InputGroup/InputGroup.js.map +1 -1
- package/dist/components/Modal/Modal.cjs +226 -116
- package/dist/components/Modal/Modal.cjs.map +1 -1
- package/dist/components/Modal/Modal.d.ts +38 -2
- package/dist/components/Modal/Modal.js +227 -117
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Modal/ModalFooter.d.ts +9 -1
- package/dist/components/Modal/index.d.ts +5 -0
- package/dist/components/PageLoader/PageLoader.cjs +61 -0
- package/dist/components/PageLoader/PageLoader.cjs.map +1 -0
- package/dist/components/PageLoader/PageLoader.d.ts +38 -0
- package/dist/components/PageLoader/PageLoader.js +61 -0
- package/dist/components/PageLoader/PageLoader.js.map +1 -0
- package/dist/components/PageLoader/index.d.ts +2 -0
- package/dist/components/PageLoader.d.ts +6 -0
- package/dist/components/ScrollTopButton/ScrollTopButton.cjs +79 -0
- package/dist/components/ScrollTopButton/ScrollTopButton.cjs.map +1 -0
- package/dist/components/ScrollTopButton/ScrollTopButton.d.ts +48 -0
- package/dist/components/ScrollTopButton/ScrollTopButton.js +79 -0
- package/dist/components/ScrollTopButton/ScrollTopButton.js.map +1 -0
- package/dist/components/ScrollTopButton/index.d.ts +4 -0
- package/dist/components/ScrollTopButton/scrollToTop.d.ts +29 -0
- package/dist/components/ScrollTopButton.d.ts +6 -0
- package/dist/components/Select/Select.cjs +446 -4
- package/dist/components/Select/Select.cjs.map +1 -1
- package/dist/components/Select/Select.d.ts +33 -13
- package/dist/components/Select/Select.definitions.d.ts +3 -0
- package/dist/components/Select/Select.helpers.d.ts +28 -0
- package/dist/components/Select/Select.js +445 -3
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/Select.sx.d.ts +7 -0
- package/dist/components/Select/Select.types.d.ts +1 -0
- package/dist/components/Select/_parts/SelectMenuItem.d.ts +20 -0
- package/dist/components/Select/_parts/SelectSearchHeader.d.ts +15 -0
- package/dist/components/Select/_parts/SelectValue.d.ts +22 -0
- package/dist/components/Select/index.d.ts +2 -1
- package/dist/components/Select.d.ts +4 -0
- package/dist/components/Stat/Stat.cjs +1 -1
- package/dist/components/Stat/Stat.js +1 -1
- package/dist/components/Stepper/Stepper.cjs +4 -1
- package/dist/components/Stepper/Stepper.cjs.map +1 -1
- package/dist/components/Stepper/Stepper.d.ts +5 -0
- package/dist/components/Stepper/Stepper.js +4 -1
- package/dist/components/Stepper/Stepper.js.map +1 -1
- package/dist/components/_shared/formField.sx.d.ts +33 -0
- package/dist/components/_shared/resolvePreset.d.ts +18 -0
- package/dist/formField.sx-CQ1mbk9M.cjs +76 -0
- package/dist/formField.sx-CQ1mbk9M.cjs.map +1 -0
- package/dist/formField.sx-DfVbMe0V.js +77 -0
- package/dist/formField.sx-DfVbMe0V.js.map +1 -0
- package/dist/hooks/Wizard/Wizard.cjs +7 -0
- package/dist/hooks/Wizard/Wizard.cjs.map +1 -0
- package/dist/hooks/Wizard/Wizard.js +7 -0
- package/dist/hooks/Wizard/Wizard.js.map +1 -0
- package/dist/hooks/Wizard/WizardContext.d.ts +67 -0
- package/dist/hooks/Wizard/index.d.ts +3 -0
- package/dist/hooks/Wizard/useWizard.d.ts +9 -0
- package/dist/hooks/Wizard.d.ts +2 -0
- package/dist/index.cjs +99 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +31 -2
- package/dist/index.js.map +1 -1
- package/dist/mui.d.ts +5 -0
- package/dist/resolvePreset-B-IB0ehH.js +15 -0
- package/dist/resolvePreset-B-IB0ehH.js.map +1 -0
- package/dist/resolvePreset-CT3kU-K2.cjs +14 -0
- package/dist/resolvePreset-CT3kU-K2.cjs.map +1 -0
- package/dist/styles.css +3 -112
- package/dist/theme/componentStyles.d.ts +32 -0
- package/dist/theme/tokens.d.ts +28 -0
- package/dist/useWizard-CWdIxZzX.cjs +94 -0
- package/dist/useWizard-CWdIxZzX.cjs.map +1 -0
- package/dist/useWizard-CWq--C3o.js +95 -0
- package/dist/useWizard-CWq--C3o.js.map +1 -0
- package/package.json +1 -1
- package/src/components/ActionMenu/ActionMenu.stories.tsx +230 -0
- package/src/components/ActionMenu/ActionMenu.tsx +174 -0
- package/src/components/ActionMenu/index.ts +2 -0
- package/src/components/AppBar/AppBar.stories.tsx +272 -0
- package/src/components/AppBar/AppBar.sx.ts +32 -0
- package/src/components/AppBar/AppBar.tsx +123 -0
- package/src/components/AppBar/AppBarBrand.tsx +120 -0
- package/src/components/AppBar/AppBarContext.ts +25 -0
- package/src/components/AppBar/AppBarMenuToggle.tsx +90 -0
- package/src/components/AppBar/AppBarUserMenu.tsx +217 -0
- package/src/components/AppBar/index.ts +25 -0
- package/src/components/Autocomplete/Autocomplete.definitions.ts +223 -0
- package/src/components/Autocomplete/Autocomplete.helpers.ts +60 -0
- package/src/components/Autocomplete/Autocomplete.stories.tsx +363 -2
- package/src/components/Autocomplete/Autocomplete.sx.ts +30 -0
- package/src/components/Autocomplete/Autocomplete.tsx +312 -90
- package/src/components/Autocomplete/Autocomplete.types.ts +13 -0
- package/src/components/Autocomplete/_parts/AutocompleteChips.tsx +55 -0
- package/src/components/Autocomplete/_parts/AutocompleteLoader.tsx +17 -0
- package/src/components/Autocomplete/_parts/AutocompleteOption.tsx +31 -0
- package/src/components/Autocomplete/index.ts +12 -1
- package/src/components/Avatar/Avatar.definitions.ts +162 -0
- package/src/components/Avatar/Avatar.stories.tsx +205 -1
- package/src/components/Avatar/Avatar.tsx +166 -103
- package/src/components/Card/Card.stories.tsx +205 -16
- package/src/components/Card/Card.sx.ts +104 -0
- package/src/components/Card/Card.tsx +191 -35
- package/src/components/Card/index.ts +9 -1
- package/src/components/DatePicker/DatePicker.definitions.ts +24 -1
- package/src/components/DatePicker/DatePicker.helpers.ts +24 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +29 -2
- package/src/components/DatePicker/DatePicker.sx.ts +33 -0
- package/src/components/DatePicker/DatePicker.tsx +163 -139
- package/src/components/DatePicker/DatePicker.types.ts +10 -0
- package/src/components/DatePicker/index.ts +9 -1
- package/src/components/DateTimePicker/DateTimePicker.definitions.ts +24 -0
- package/src/components/DateTimePicker/DateTimePicker.helpers.ts +38 -0
- package/src/components/DateTimePicker/DateTimePicker.stories.tsx +29 -1
- package/src/components/DateTimePicker/DateTimePicker.sx.ts +30 -0
- package/src/components/DateTimePicker/DateTimePicker.tsx +200 -166
- package/src/components/DateTimePicker/DateTimePicker.types.ts +10 -0
- package/src/components/DateTimePicker/index.ts +9 -1
- package/src/components/Drawer/Drawer.stories.tsx +270 -0
- package/src/components/Drawer/Drawer.sx.ts +106 -0
- package/src/components/Drawer/Drawer.tsx +214 -0
- package/src/components/Drawer/DrawerContext.ts +26 -0
- package/src/components/Drawer/DrawerItem.tsx +110 -0
- package/src/components/Drawer/index.ts +10 -0
- package/src/components/Flyout/Flyout.stories.tsx +26 -18
- package/src/components/Icon/Icon.stories.tsx +68 -1
- package/src/components/Icon/Icon.tsx +87 -6
- package/src/components/Input/Input.definitions.ts +74 -2
- package/src/components/Input/Input.helpers.ts +49 -0
- package/src/components/Input/Input.stories.tsx +116 -4
- package/src/components/Input/Input.sx.ts +42 -0
- package/src/components/Input/Input.tsx +117 -162
- package/src/components/Input/Input.types.ts +10 -0
- package/src/components/Input/index.ts +9 -1
- package/src/components/InputGroup/InputGroup.definitions.ts +158 -0
- package/src/components/InputGroup/InputGroup.stories.tsx +159 -28
- package/src/components/InputGroup/InputGroup.tsx +159 -116
- package/src/components/Modal/Modal.stories.tsx +434 -6
- package/src/components/Modal/Modal.tsx +303 -121
- package/src/components/Modal/ModalFooter.tsx +22 -12
- package/src/components/Modal/index.ts +6 -1
- package/src/components/PageLoader/PageLoader.stories.tsx +217 -0
- package/src/components/PageLoader/PageLoader.tsx +96 -0
- package/src/components/PageLoader/index.ts +2 -0
- package/src/components/ScrollTopButton/ScrollTopButton.stories.tsx +158 -0
- package/src/components/ScrollTopButton/ScrollTopButton.tsx +135 -0
- package/src/components/ScrollTopButton/index.ts +8 -0
- package/src/components/ScrollTopButton/scrollToTop.ts +37 -0
- package/src/components/Select/Select.definitions.ts +114 -0
- package/src/components/Select/Select.helpers.ts +71 -0
- package/src/components/Select/Select.stories.tsx +126 -8
- package/src/components/Select/Select.sx.ts +14 -0
- package/src/components/Select/Select.tsx +246 -285
- package/src/components/Select/Select.types.ts +15 -0
- package/src/components/Select/_parts/SelectMenuItem.tsx +40 -0
- package/src/components/Select/_parts/SelectSearchHeader.tsx +51 -0
- package/src/components/Select/_parts/SelectValue.tsx +96 -0
- package/src/components/Select/index.ts +14 -1
- package/src/components/Stepper/Stepper.tsx +17 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +15 -3
- package/src/components/_shared/formField.sx.ts +118 -0
- package/src/components/_shared/resolvePreset.ts +35 -0
- package/src/hooks/Wizard/Wizard.stories.tsx +301 -0
- package/src/hooks/Wizard/WizardContext.tsx +166 -0
- package/src/hooks/Wizard/index.ts +6 -0
- package/src/hooks/Wizard/useWizard.ts +13 -0
- package/src/index.ts +17 -1
- package/src/mui.ts +44 -0
- package/src/theme/componentStyles.ts +47 -0
- package/src/theme/tokens.ts +43 -0
- package/dist/DatePicker-BSNboVhN.js +0 -201
- package/dist/DatePicker-BSNboVhN.js.map +0 -1
- package/dist/DatePicker-BoqxWAhj.cjs +0 -200
- package/dist/DatePicker-BoqxWAhj.cjs.map +0 -1
- package/dist/Input-DFHs7cJ_.js +0 -171
- package/dist/Input-DFHs7cJ_.js.map +0 -1
- package/dist/Input-c8MwNNPg.cjs +0 -170
- package/dist/Input-c8MwNNPg.cjs.map +0 -1
- package/dist/Select-BO2N56sm.cjs +0 -411
- package/dist/Select-BO2N56sm.cjs.map +0 -1
- package/dist/Select-BcLkyHSE.js +0 -412
- package/dist/Select-BcLkyHSE.js.map +0 -1
- package/dist/index.css +0 -3
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import { Avatar as MuiAvatar, Tooltip } from '@mui/material';
|
|
2
|
-
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
|
3
1
|
import React, { useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Avatar as MuiAvatar,
|
|
4
|
+
Box,
|
|
5
|
+
Tooltip,
|
|
6
|
+
Typography,
|
|
7
|
+
type SxProps,
|
|
8
|
+
type Theme,
|
|
9
|
+
} from '@mui/material';
|
|
10
|
+
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
|
4
11
|
|
|
5
12
|
export interface AvatarItem {
|
|
6
13
|
text?: string;
|
|
@@ -10,27 +17,59 @@ export interface AvatarItem {
|
|
|
10
17
|
backgroundColor?: string;
|
|
11
18
|
}
|
|
12
19
|
|
|
20
|
+
export type AvatarSize = 'sm' | 'md' | 'lg' | 'xl' | number;
|
|
21
|
+
|
|
13
22
|
export interface AvatarProps {
|
|
14
23
|
type?: string;
|
|
15
24
|
items: AvatarItem[];
|
|
16
25
|
displayedAvatars?: number;
|
|
17
|
-
size?:
|
|
18
|
-
trustUrls?: boolean;
|
|
26
|
+
size?: AvatarSize;
|
|
19
27
|
showText?: boolean;
|
|
20
28
|
showTooltip?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* sx aplicado al contenedor raíz.
|
|
31
|
+
*/
|
|
32
|
+
sx?: SxProps<Theme>;
|
|
33
|
+
/**
|
|
34
|
+
* sx aplicado a cada MuiAvatar individual (se mergea sobre los defaults).
|
|
35
|
+
*/
|
|
36
|
+
avatarSx?: SxProps<Theme>;
|
|
37
|
+
className?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Overlap (px) entre avatares cuando hay varios. Default depende del tamaño.
|
|
40
|
+
*/
|
|
41
|
+
overlap?: number;
|
|
21
42
|
}
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
44
|
+
// Escala alineada con la escala de MUI (sm=32, md=40, lg=56, xl=96) con borde
|
|
45
|
+
// proporcional para el efecto stacked.
|
|
46
|
+
const sizeMap: Record<
|
|
47
|
+
Exclude<AvatarSize, number>,
|
|
48
|
+
{ px: number; border: number; font: number; overlap: number }
|
|
49
|
+
> = {
|
|
50
|
+
sm: { px: 32, border: 2, font: 14, overlap: 8 },
|
|
51
|
+
md: { px: 40, border: 2, font: 16, overlap: 10 },
|
|
52
|
+
lg: { px: 56, border: 3, font: 22, overlap: 14 },
|
|
53
|
+
xl: { px: 96, border: 4, font: 36, overlap: 20 },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const resolveSize = (size: AvatarSize) => {
|
|
57
|
+
if (typeof size === 'number') {
|
|
58
|
+
return {
|
|
59
|
+
px: size,
|
|
60
|
+
border: Math.max(2, Math.round(size * 0.05)),
|
|
61
|
+
font: Math.round(size * 0.4),
|
|
62
|
+
overlap: Math.round(size * 0.25),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return sizeMap[size];
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const mergeSx = (base: SxProps<Theme>, extra?: SxProps<Theme>): SxProps<Theme> => {
|
|
69
|
+
if (!extra) return base;
|
|
70
|
+
const baseArr = Array.isArray(base) ? base : [base];
|
|
71
|
+
const extraArr = Array.isArray(extra) ? extra : [extra];
|
|
72
|
+
return [...baseArr, ...extraArr] as SxProps<Theme>;
|
|
34
73
|
};
|
|
35
74
|
|
|
36
75
|
export const Avatar: React.FC<AvatarProps> = ({
|
|
@@ -38,106 +77,130 @@ export const Avatar: React.FC<AvatarProps> = ({
|
|
|
38
77
|
type,
|
|
39
78
|
displayedAvatars = 4,
|
|
40
79
|
size = 'sm',
|
|
41
|
-
trustUrls = false,
|
|
42
80
|
showText = true,
|
|
43
81
|
showTooltip = false,
|
|
82
|
+
sx,
|
|
83
|
+
avatarSx,
|
|
84
|
+
className,
|
|
85
|
+
overlap,
|
|
44
86
|
}) => {
|
|
45
87
|
const [errorIndex, setErrorIndex] = useState<Set<number>>(new Set());
|
|
46
88
|
|
|
47
89
|
const handleImageError = (index: number) => {
|
|
48
|
-
setErrorIndex((prev) =>
|
|
90
|
+
setErrorIndex((prev) => {
|
|
91
|
+
const next = new Set(prev);
|
|
92
|
+
next.add(index);
|
|
93
|
+
return next;
|
|
94
|
+
});
|
|
49
95
|
};
|
|
50
96
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{showBadge && (
|
|
98
|
-
<span
|
|
99
|
-
data-testid="badge"
|
|
100
|
-
aria-label={item.text}
|
|
101
|
-
style={{
|
|
102
|
-
...style.badge,
|
|
103
|
-
display: 'inline-block',
|
|
104
|
-
backgroundColor: item.backgroundColor || '#c8d5e9',
|
|
105
|
-
color: item.color || '#667688',
|
|
106
|
-
fontWeight: 700,
|
|
107
|
-
textAlign: 'center',
|
|
108
|
-
borderRadius: '9999px',
|
|
109
|
-
border: `${style.badge.borderWidth}px solid white`,
|
|
110
|
-
lineHeight: style.badge.height,
|
|
111
|
-
fontSize: style.badge.fontSize,
|
|
112
|
-
marginTop: style.badge.marginTop,
|
|
113
|
-
marginBottom: style.badge.marginTop,
|
|
114
|
-
}}
|
|
115
|
-
>
|
|
116
|
-
{item.badge}
|
|
117
|
-
</span>
|
|
118
|
-
)}
|
|
97
|
+
if (!items || items.length === 0) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const s = resolveSize(size);
|
|
102
|
+
const effectiveOverlap = overlap ?? s.overlap;
|
|
103
|
+
const visibleItems = items.slice(0, displayedAvatars);
|
|
104
|
+
|
|
105
|
+
const baseAvatarSx: SxProps<Theme> = {
|
|
106
|
+
width: s.px,
|
|
107
|
+
height: s.px,
|
|
108
|
+
fontSize: s.font,
|
|
109
|
+
fontWeight: 700,
|
|
110
|
+
border: (theme) => `${s.border}px solid ${theme.palette.background.paper}`,
|
|
111
|
+
boxSizing: 'content-box',
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const renderSingleAvatar = (item: AvatarItem, i: number) => {
|
|
115
|
+
const hasImage = !!item.imageUrl && !errorIndex.has(i);
|
|
116
|
+
const showBadgeFallback = !!item.badge;
|
|
117
|
+
|
|
118
|
+
// Defaults tirando al theme; item.color / item.backgroundColor tienen prioridad.
|
|
119
|
+
const itemSx: SxProps<Theme> = {
|
|
120
|
+
bgcolor: item.backgroundColor ?? 'action.selected',
|
|
121
|
+
color: item.color ?? 'text.secondary',
|
|
122
|
+
// Stacking manual: margen negativo al segundo avatar en adelante.
|
|
123
|
+
...(i > 0 && { marginLeft: `-${effectiveOverlap}px` }),
|
|
124
|
+
zIndex: visibleItems.length - i,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const finalSx = mergeSx(mergeSx(baseAvatarSx, itemSx), avatarSx);
|
|
128
|
+
|
|
129
|
+
const avatarEl = (
|
|
130
|
+
<MuiAvatar
|
|
131
|
+
data-testid="avatar"
|
|
132
|
+
alt={item.text || 'User avatar'}
|
|
133
|
+
src={hasImage ? item.imageUrl : undefined}
|
|
134
|
+
imgProps={{
|
|
135
|
+
'data-testid': 'image',
|
|
136
|
+
onError: () => handleImageError(i),
|
|
137
|
+
} as React.ImgHTMLAttributes<HTMLImageElement>}
|
|
138
|
+
sx={finalSx}
|
|
139
|
+
>
|
|
140
|
+
{!hasImage && showBadgeFallback ? (
|
|
141
|
+
<span data-testid="badge" aria-label={item.text}>
|
|
142
|
+
{item.badge}
|
|
119
143
|
</span>
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{
|
|
125
|
-
|
|
126
|
-
) :
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<
|
|
144
|
+
) : !hasImage ? (
|
|
145
|
+
<AccountCircleIcon
|
|
146
|
+
data-testid="icon"
|
|
147
|
+
aria-label={item.text}
|
|
148
|
+
sx={{ width: '100%', height: '100%' }}
|
|
149
|
+
/>
|
|
150
|
+
) : null}
|
|
151
|
+
</MuiAvatar>
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
if (showTooltip && item.text) {
|
|
155
|
+
return (
|
|
156
|
+
<Tooltip key={i} title={item.text}>
|
|
157
|
+
{avatarEl}
|
|
158
|
+
</Tooltip>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
return <React.Fragment key={i}>{avatarEl}</React.Fragment>;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<Box
|
|
166
|
+
data-testid="avatar-container"
|
|
167
|
+
className={className}
|
|
168
|
+
sx={mergeSx(
|
|
169
|
+
{
|
|
170
|
+
display: 'flex',
|
|
171
|
+
alignItems: 'center',
|
|
172
|
+
lineHeight: 1,
|
|
173
|
+
width: 'fit-content',
|
|
174
|
+
},
|
|
175
|
+
sx,
|
|
176
|
+
)}
|
|
177
|
+
>
|
|
178
|
+
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
179
|
+
{visibleItems.map((item, i) => renderSingleAvatar(item, i))}
|
|
180
|
+
</Box>
|
|
181
|
+
|
|
182
|
+
{showText && items[0]?.text && (
|
|
183
|
+
<Typography
|
|
184
|
+
data-testid="text"
|
|
185
|
+
variant="caption"
|
|
186
|
+
sx={{
|
|
187
|
+
ml: 1,
|
|
188
|
+
fontSize: '0.75rem',
|
|
189
|
+
fontWeight: 400,
|
|
190
|
+
color: 'text.primary',
|
|
191
|
+
}}
|
|
192
|
+
>
|
|
133
193
|
{type && items.length === 1 && (
|
|
134
|
-
<span data-testid="type"
|
|
194
|
+
<Box component="span" data-testid="type" sx={{ mr: 0.5 }}>
|
|
195
|
+
{type}:
|
|
196
|
+
</Box>
|
|
135
197
|
)}
|
|
136
|
-
{items[0].text}
|
|
137
|
-
|
|
198
|
+
{items[0].text}
|
|
199
|
+
{items.length > 1 && ` +${items.length - 1}`}
|
|
200
|
+
</Typography>
|
|
138
201
|
)}
|
|
139
|
-
</
|
|
202
|
+
</Box>
|
|
140
203
|
);
|
|
141
204
|
};
|
|
142
205
|
|
|
143
|
-
export default Avatar;
|
|
206
|
+
export default Avatar;
|
|
@@ -1,32 +1,221 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { Box, Button, Chip, Stack, Typography } from '@mui/material';
|
|
4
|
+
import EditIcon from '@mui/icons-material/Edit';
|
|
5
|
+
import DeleteIcon from '@mui/icons-material/Delete';
|
|
6
|
+
import PersonIcon from '@mui/icons-material/Person';
|
|
7
|
+
|
|
8
|
+
import { Card } from './Card';
|
|
9
|
+
import { ActionMenu } from '../ActionMenu';
|
|
4
10
|
|
|
5
11
|
const meta: Meta<typeof Card> = {
|
|
6
|
-
title:
|
|
12
|
+
title: 'Components/Card',
|
|
7
13
|
component: Card,
|
|
14
|
+
tags: ['autodocs'],
|
|
8
15
|
parameters: {
|
|
9
|
-
layout:
|
|
16
|
+
layout: 'padded',
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component:
|
|
20
|
+
'Contenedor semántico con slots `title` / `subtitle` / `actions` / `footer`. Reemplaza el patrón `.card` + `.card-header` + `.card-body` de Metronic con composición declarativa. Backward-compat: si solo se pasa `children`, se comporta como el Card original.',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
argTypes: {
|
|
25
|
+
variant: {
|
|
26
|
+
control: 'select',
|
|
27
|
+
options: ['elevated', 'outlined', 'plain'],
|
|
28
|
+
},
|
|
29
|
+
padding: {
|
|
30
|
+
control: 'select',
|
|
31
|
+
options: ['none', 'dense', 'normal', 'loose'],
|
|
32
|
+
},
|
|
33
|
+
clickable: { control: 'boolean' },
|
|
10
34
|
},
|
|
11
|
-
tags: ["autodocs"]
|
|
12
35
|
};
|
|
13
36
|
|
|
14
37
|
export default meta;
|
|
15
|
-
|
|
16
38
|
type Story = StoryObj<typeof Card>;
|
|
17
39
|
|
|
18
|
-
|
|
40
|
+
// ── Stories ──────────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
export const LegacyBodyOnly: Story = {
|
|
19
43
|
args: {
|
|
20
|
-
children:
|
|
44
|
+
children: 'Contenido simple del card — sin header ni footer.',
|
|
21
45
|
},
|
|
22
46
|
parameters: {
|
|
23
47
|
docs: {
|
|
24
48
|
description: {
|
|
25
|
-
story:
|
|
49
|
+
story:
|
|
50
|
+
'Modo backward-compat: pasando solo `children` el Card se comporta como el original (body con padding, sombra sutil).',
|
|
26
51
|
},
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const WithTitleAndSubtitle: Story = {
|
|
57
|
+
args: {
|
|
58
|
+
title: 'Datos del cliente',
|
|
59
|
+
subtitle: 'Última actualización: hace 2 horas',
|
|
60
|
+
children: (
|
|
61
|
+
<Typography variant="body2" color="text.secondary">
|
|
62
|
+
Aquí va el contenido del card, por ejemplo un formulario o una tabla.
|
|
63
|
+
</Typography>
|
|
64
|
+
),
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const WithActions: Story = {
|
|
69
|
+
args: {
|
|
70
|
+
title: 'Afiliación #12458',
|
|
71
|
+
subtitle: 'Aprobada el 10 abril 2026',
|
|
72
|
+
actions: (
|
|
73
|
+
<ActionMenu
|
|
74
|
+
items={[
|
|
75
|
+
{ label: 'Editar', icon: <EditIcon fontSize="small" />, onClick: () => {} },
|
|
76
|
+
{
|
|
77
|
+
label: 'Eliminar',
|
|
78
|
+
icon: <DeleteIcon fontSize="small" />,
|
|
79
|
+
onClick: () => {},
|
|
80
|
+
danger: true,
|
|
81
|
+
dividerBefore: true,
|
|
82
|
+
},
|
|
83
|
+
]}
|
|
84
|
+
/>
|
|
85
|
+
),
|
|
86
|
+
children: (
|
|
87
|
+
<Stack direction="row" spacing={2} alignItems="center">
|
|
88
|
+
<PersonIcon color="action" />
|
|
89
|
+
<Box>
|
|
90
|
+
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
|
91
|
+
Andrea Pineda
|
|
92
|
+
</Typography>
|
|
93
|
+
<Typography variant="caption" color="text.secondary">
|
|
94
|
+
andrea@soyfri.com
|
|
95
|
+
</Typography>
|
|
96
|
+
</Box>
|
|
97
|
+
<Chip label="Activo" color="success" size="small" sx={{ ml: 'auto' }} />
|
|
98
|
+
</Stack>
|
|
99
|
+
),
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const WithFooter: Story = {
|
|
104
|
+
args: {
|
|
105
|
+
title: 'Nueva afiliación',
|
|
106
|
+
children: (
|
|
107
|
+
<Stack spacing={1}>
|
|
108
|
+
<Typography variant="body2">
|
|
109
|
+
Confirma los datos antes de enviar la solicitud.
|
|
110
|
+
</Typography>
|
|
111
|
+
<Typography variant="caption" color="text.secondary">
|
|
112
|
+
Campos marcados con * son obligatorios.
|
|
113
|
+
</Typography>
|
|
114
|
+
</Stack>
|
|
115
|
+
),
|
|
116
|
+
footer: (
|
|
117
|
+
<>
|
|
118
|
+
<Button variant="outlined" color="secondary">
|
|
119
|
+
Cancelar
|
|
120
|
+
</Button>
|
|
121
|
+
<Button variant="contained">Enviar</Button>
|
|
122
|
+
</>
|
|
123
|
+
),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const OutlinedVariant: Story = {
|
|
128
|
+
args: {
|
|
129
|
+
variant: 'outlined',
|
|
130
|
+
title: 'Card outlined',
|
|
131
|
+
subtitle: 'Sin sombra, solo borde',
|
|
132
|
+
children: (
|
|
133
|
+
<Typography variant="body2">
|
|
134
|
+
Útil cuando el card vive sobre un fondo con elevation mayor, o para
|
|
135
|
+
evitar stacked shadows en listas densas.
|
|
136
|
+
</Typography>
|
|
137
|
+
),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export const PlainVariant: Story = {
|
|
142
|
+
args: {
|
|
143
|
+
variant: 'plain',
|
|
144
|
+
title: 'Card plain',
|
|
145
|
+
subtitle: 'Sin borde ni sombra',
|
|
146
|
+
children: (
|
|
147
|
+
<Typography variant="body2">
|
|
148
|
+
Perfecto para composición interna — por ejemplo, cuando un card va
|
|
149
|
+
dentro de otro y quieres evitar doble sombra.
|
|
150
|
+
</Typography>
|
|
151
|
+
),
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const Clickable: Story = {
|
|
156
|
+
args: {
|
|
157
|
+
clickable: true,
|
|
158
|
+
title: 'Haz click en este card',
|
|
159
|
+
subtitle: 'Fíjate en el hover',
|
|
160
|
+
children: (
|
|
161
|
+
<Typography variant="body2" color="text.secondary">
|
|
162
|
+
El cursor cambia y aparece un lift sutil en hover. Se dispara `onClick`.
|
|
163
|
+
</Typography>
|
|
164
|
+
),
|
|
165
|
+
onClick: () => console.log('card clicked'),
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export const DensePadding: Story = {
|
|
170
|
+
args: {
|
|
171
|
+
padding: 'dense',
|
|
172
|
+
title: 'Card denso',
|
|
173
|
+
subtitle: 'Padding reducido',
|
|
174
|
+
children: (
|
|
175
|
+
<Stack spacing={0.5}>
|
|
176
|
+
<Typography variant="body2">Línea 1</Typography>
|
|
177
|
+
<Typography variant="body2">Línea 2</Typography>
|
|
178
|
+
<Typography variant="body2">Línea 3</Typography>
|
|
179
|
+
</Stack>
|
|
180
|
+
),
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
export const CustomHeader: Story = {
|
|
185
|
+
args: {
|
|
186
|
+
header: (
|
|
187
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, width: '100%' }}>
|
|
188
|
+
<Box
|
|
189
|
+
sx={{
|
|
190
|
+
width: 40,
|
|
191
|
+
height: 40,
|
|
192
|
+
borderRadius: 2,
|
|
193
|
+
bgcolor: 'primary.main',
|
|
194
|
+
color: 'primary.contrastText',
|
|
195
|
+
display: 'flex',
|
|
196
|
+
alignItems: 'center',
|
|
197
|
+
justifyContent: 'center',
|
|
198
|
+
fontWeight: 700,
|
|
199
|
+
}}
|
|
200
|
+
>
|
|
201
|
+
42
|
|
202
|
+
</Box>
|
|
203
|
+
<Box sx={{ flex: 1 }}>
|
|
204
|
+
<Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
|
|
205
|
+
Header totalmente custom
|
|
206
|
+
</Typography>
|
|
207
|
+
<Typography variant="caption" color="text.secondary">
|
|
208
|
+
Tomas control del slot entero
|
|
209
|
+
</Typography>
|
|
210
|
+
</Box>
|
|
211
|
+
<Chip label="v2" size="small" variant="outlined" />
|
|
212
|
+
</Box>
|
|
213
|
+
),
|
|
214
|
+
children: (
|
|
215
|
+
<Typography variant="body2">
|
|
216
|
+
Cuando `header` se usa, los props `title`/`subtitle`/`actions` son
|
|
217
|
+
ignorados.
|
|
218
|
+
</Typography>
|
|
219
|
+
),
|
|
220
|
+
},
|
|
221
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
2
|
+
|
|
3
|
+
export type CardVariant = 'elevated' | 'outlined' | 'plain';
|
|
4
|
+
export type CardPadding = 'none' | 'dense' | 'normal' | 'loose';
|
|
5
|
+
|
|
6
|
+
export interface BuildCardSxArgs {
|
|
7
|
+
variant: CardVariant;
|
|
8
|
+
padding: CardPadding;
|
|
9
|
+
clickable: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const paddingMap: Record<CardPadding, number> = {
|
|
13
|
+
none: 0,
|
|
14
|
+
dense: 1.5,
|
|
15
|
+
normal: 2.5,
|
|
16
|
+
loose: 4,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Estilo base del Card (root). La props `sx` del consumer se compone encima
|
|
21
|
+
* junto al preset resuelto (en Card.tsx). Este builder solo se ocupa del
|
|
22
|
+
* variant + padding, para que siga siendo predecible.
|
|
23
|
+
*/
|
|
24
|
+
export function buildCardSx({
|
|
25
|
+
variant,
|
|
26
|
+
padding,
|
|
27
|
+
clickable,
|
|
28
|
+
}: BuildCardSxArgs): SxProps<Theme> {
|
|
29
|
+
return (theme) => ({
|
|
30
|
+
borderRadius: 2,
|
|
31
|
+
backgroundColor: 'background.paper',
|
|
32
|
+
boxShadow:
|
|
33
|
+
variant === 'elevated'
|
|
34
|
+
? theme.shadows[1]
|
|
35
|
+
: 'none',
|
|
36
|
+
border:
|
|
37
|
+
variant === 'outlined'
|
|
38
|
+
? `1px solid ${theme.palette.divider}`
|
|
39
|
+
: 'none',
|
|
40
|
+
transition: theme.transitions.create(
|
|
41
|
+
['box-shadow', 'transform', 'border-color'],
|
|
42
|
+
{ duration: theme.transitions.duration.shorter },
|
|
43
|
+
),
|
|
44
|
+
cursor: clickable ? 'pointer' : 'default',
|
|
45
|
+
...(clickable && {
|
|
46
|
+
'&:hover': {
|
|
47
|
+
boxShadow:
|
|
48
|
+
variant === 'elevated'
|
|
49
|
+
? theme.shadows[3]
|
|
50
|
+
: variant === 'outlined'
|
|
51
|
+
? theme.shadows[1]
|
|
52
|
+
: 'none',
|
|
53
|
+
transform: variant !== 'plain' ? 'translateY(-1px)' : 'none',
|
|
54
|
+
},
|
|
55
|
+
'&:active': {
|
|
56
|
+
transform: 'translateY(0)',
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
// Body padding (cuando no hay header/footer envolventes). Para el caso
|
|
60
|
+
// compuesto los slots manejan su propio padding, dejamos el root en 0.
|
|
61
|
+
p: paddingMap[padding],
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function buildCardHeaderSx(): SxProps<Theme> {
|
|
66
|
+
return (theme) => ({
|
|
67
|
+
display: 'flex',
|
|
68
|
+
alignItems: 'center',
|
|
69
|
+
gap: 1.5,
|
|
70
|
+
px: 2.5,
|
|
71
|
+
py: 1.75,
|
|
72
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
73
|
+
'& .card-header-text': {
|
|
74
|
+
flex: 1,
|
|
75
|
+
minWidth: 0,
|
|
76
|
+
},
|
|
77
|
+
'& .card-header-actions': {
|
|
78
|
+
display: 'flex',
|
|
79
|
+
alignItems: 'center',
|
|
80
|
+
gap: 0.5,
|
|
81
|
+
flexShrink: 0,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function buildCardBodySx(padding: CardPadding): SxProps<Theme> {
|
|
87
|
+
return {
|
|
88
|
+
px: padding === 'none' ? 0 : padding === 'dense' ? 1.5 : padding === 'loose' ? 4 : 2.5,
|
|
89
|
+
py: padding === 'none' ? 0 : padding === 'dense' ? 1.5 : padding === 'loose' ? 4 : 2.5,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function buildCardFooterSx(): SxProps<Theme> {
|
|
94
|
+
return (theme) => ({
|
|
95
|
+
display: 'flex',
|
|
96
|
+
alignItems: 'center',
|
|
97
|
+
justifyContent: 'flex-end',
|
|
98
|
+
gap: 1,
|
|
99
|
+
px: 2.5,
|
|
100
|
+
py: 1.5,
|
|
101
|
+
borderTop: `1px solid ${theme.palette.divider}`,
|
|
102
|
+
backgroundColor: theme.palette.action.hover,
|
|
103
|
+
});
|
|
104
|
+
}
|