@soyfri/shared-library 2.0.0-beta.0 → 2.0.0-beta.2

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 (181) hide show
  1. package/dist/components/Icon/Icon.js +1 -1
  2. package/dist/components/Table/Table.js +1 -1
  3. package/package.json +32 -4
  4. package/.dockerignore +0 -8
  5. package/.github/workflows/publish.yml +0 -107
  6. package/.prettierrc +0 -3
  7. package/.storybook/main.ts +0 -19
  8. package/.storybook/preview.ts +0 -14
  9. package/.storybook/vitest.setup.ts +0 -9
  10. package/Dockerfile +0 -37
  11. package/build.js +0 -102
  12. package/chromatic.config.json +0 -5
  13. package/cleanDirectories.js +0 -40
  14. package/rollup.config.cjs +0 -87
  15. package/src/components/ActionMenu/ActionMenu.stories.tsx +0 -230
  16. package/src/components/ActionMenu/ActionMenu.tsx +0 -174
  17. package/src/components/ActionMenu/index.ts +0 -2
  18. package/src/components/AppBar/AppBar.stories.tsx +0 -272
  19. package/src/components/AppBar/AppBar.sx.ts +0 -32
  20. package/src/components/AppBar/AppBar.tsx +0 -123
  21. package/src/components/AppBar/AppBarBrand.tsx +0 -120
  22. package/src/components/AppBar/AppBarContext.ts +0 -25
  23. package/src/components/AppBar/AppBarMenuToggle.tsx +0 -90
  24. package/src/components/AppBar/AppBarUserMenu.tsx +0 -217
  25. package/src/components/AppBar/index.ts +0 -25
  26. package/src/components/Autocomplete/Autocomplete.definitions.ts +0 -477
  27. package/src/components/Autocomplete/Autocomplete.helpers.ts +0 -60
  28. package/src/components/Autocomplete/Autocomplete.stories.tsx +0 -748
  29. package/src/components/Autocomplete/Autocomplete.sx.ts +0 -30
  30. package/src/components/Autocomplete/Autocomplete.tsx +0 -361
  31. package/src/components/Autocomplete/Autocomplete.types.ts +0 -13
  32. package/src/components/Autocomplete/_parts/AutocompleteChips.tsx +0 -55
  33. package/src/components/Autocomplete/_parts/AutocompleteLoader.tsx +0 -17
  34. package/src/components/Autocomplete/_parts/AutocompleteOption.tsx +0 -31
  35. package/src/components/Autocomplete/index.ts +0 -12
  36. package/src/components/Avatar/Avatar.definitions.ts +0 -162
  37. package/src/components/Avatar/Avatar.stories.tsx +0 -258
  38. package/src/components/Avatar/Avatar.tsx +0 -206
  39. package/src/components/Avatar/index.ts +0 -1
  40. package/src/components/Button/Button.definition.ts +0 -97
  41. package/src/components/Button/Button.stories.tsx +0 -285
  42. package/src/components/Button/Button.tsx +0 -67
  43. package/src/components/Button/index.ts +0 -1
  44. package/src/components/Card/Card.definition.ts +0 -5
  45. package/src/components/Card/Card.stories.tsx +0 -221
  46. package/src/components/Card/Card.sx.ts +0 -104
  47. package/src/components/Card/Card.tsx +0 -200
  48. package/src/components/Card/index.ts +0 -9
  49. package/src/components/Chip/Chip.definitions.ts +0 -167
  50. package/src/components/Chip/Chip.stories.tsx +0 -265
  51. package/src/components/Chip/Chip.tsx +0 -61
  52. package/src/components/Chip/index.ts +0 -1
  53. package/src/components/Column/Column.tsx +0 -29
  54. package/src/components/Column/index.ts +0 -1
  55. package/src/components/DatePicker/DatePicker.definitions.ts +0 -228
  56. package/src/components/DatePicker/DatePicker.helpers.ts +0 -24
  57. package/src/components/DatePicker/DatePicker.stories.tsx +0 -309
  58. package/src/components/DatePicker/DatePicker.sx.ts +0 -33
  59. package/src/components/DatePicker/DatePicker.tsx +0 -189
  60. package/src/components/DatePicker/DatePicker.types.ts +0 -10
  61. package/src/components/DatePicker/index.ts +0 -9
  62. package/src/components/DateRangePicker/DateRangePicker.definitions.ts +0 -191
  63. package/src/components/DateRangePicker/DateRangePicker.stories.tsx +0 -252
  64. package/src/components/DateRangePicker/DateRangePicker.tsx +0 -56
  65. package/src/components/DateRangePicker/index.ts +0 -1
  66. package/src/components/DateTimePicker/DateTimePicker.definitions.ts +0 -256
  67. package/src/components/DateTimePicker/DateTimePicker.helpers.ts +0 -38
  68. package/src/components/DateTimePicker/DateTimePicker.stories.tsx +0 -418
  69. package/src/components/DateTimePicker/DateTimePicker.sx.ts +0 -30
  70. package/src/components/DateTimePicker/DateTimePicker.tsx +0 -225
  71. package/src/components/DateTimePicker/DateTimePicker.types.ts +0 -10
  72. package/src/components/DateTimePicker/index.ts +0 -9
  73. package/src/components/Drawer/Drawer.stories.tsx +0 -270
  74. package/src/components/Drawer/Drawer.sx.ts +0 -106
  75. package/src/components/Drawer/Drawer.tsx +0 -214
  76. package/src/components/Drawer/DrawerContext.ts +0 -26
  77. package/src/components/Drawer/DrawerItem.tsx +0 -110
  78. package/src/components/Drawer/index.ts +0 -10
  79. package/src/components/Flyout/Flyout.stories.tsx +0 -282
  80. package/src/components/Flyout/Flyout.tsx +0 -122
  81. package/src/components/Flyout/index.ts +0 -1
  82. package/src/components/Gallery/Gallery.definition.tsx +0 -37
  83. package/src/components/Gallery/Gallery.stories.tsx +0 -82
  84. package/src/components/Gallery/Gallery.tsx +0 -118
  85. package/src/components/Gallery/GalleryLightbox.tsx +0 -170
  86. package/src/components/Gallery/GalleryMain.tsx +0 -84
  87. package/src/components/Gallery/GalleryThumbnails.tsx +0 -106
  88. package/src/components/Gallery/index.ts +0 -1
  89. package/src/components/Icon/Icon.stories.tsx +0 -121
  90. package/src/components/Icon/Icon.tsx +0 -175
  91. package/src/components/Icon/index.ts +0 -2
  92. package/src/components/Input/Input.definitions.ts +0 -324
  93. package/src/components/Input/Input.helpers.ts +0 -49
  94. package/src/components/Input/Input.stories.tsx +0 -499
  95. package/src/components/Input/Input.sx.ts +0 -42
  96. package/src/components/Input/Input.tsx +0 -141
  97. package/src/components/Input/Input.types.ts +0 -10
  98. package/src/components/Input/index.ts +0 -9
  99. package/src/components/InputGroup/InputGroup.definitions.ts +0 -158
  100. package/src/components/InputGroup/InputGroup.stories.tsx +0 -267
  101. package/src/components/InputGroup/InputGroup.tsx +0 -179
  102. package/src/components/InputGroup/index.ts +0 -1
  103. package/src/components/MenuButton/MenuButton.stories.tsx +0 -197
  104. package/src/components/MenuButton/MenuButton.tsx +0 -100
  105. package/src/components/MenuButton/index.ts +0 -1
  106. package/src/components/Modal/Modal.stories.tsx +0 -721
  107. package/src/components/Modal/Modal.tsx +0 -355
  108. package/src/components/Modal/ModalBody.tsx +0 -16
  109. package/src/components/Modal/ModalFooter.tsx +0 -71
  110. package/src/components/Modal/ModalHeader.tsx +0 -18
  111. package/src/components/Modal/index.ts +0 -6
  112. package/src/components/PageLoader/PageLoader.stories.tsx +0 -217
  113. package/src/components/PageLoader/PageLoader.tsx +0 -96
  114. package/src/components/PageLoader/index.ts +0 -2
  115. package/src/components/ScrollTopButton/ScrollTopButton.stories.tsx +0 -158
  116. package/src/components/ScrollTopButton/ScrollTopButton.tsx +0 -135
  117. package/src/components/ScrollTopButton/index.ts +0 -8
  118. package/src/components/ScrollTopButton/scrollToTop.ts +0 -37
  119. package/src/components/Select/Select.definitions.ts +0 -602
  120. package/src/components/Select/Select.helpers.ts +0 -71
  121. package/src/components/Select/Select.stories.tsx +0 -687
  122. package/src/components/Select/Select.sx.ts +0 -14
  123. package/src/components/Select/Select.tsx +0 -429
  124. package/src/components/Select/Select.types.ts +0 -15
  125. package/src/components/Select/_parts/SelectMenuItem.tsx +0 -40
  126. package/src/components/Select/_parts/SelectSearchHeader.tsx +0 -51
  127. package/src/components/Select/_parts/SelectValue.tsx +0 -96
  128. package/src/components/Select/index.ts +0 -14
  129. package/src/components/Stat/Stat.stories.tsx +0 -85
  130. package/src/components/Stat/Stat.tsx +0 -117
  131. package/src/components/Stat/index.ts +0 -2
  132. package/src/components/StatusMessage/StatusMessage.stories.tsx +0 -130
  133. package/src/components/StatusMessage/StatusMessage.tsx +0 -162
  134. package/src/components/StatusMessage/index.ts +0 -2
  135. package/src/components/Stepper/Step.tsx +0 -21
  136. package/src/components/Stepper/Stepper.definition.ts +0 -75
  137. package/src/components/Stepper/Stepper.stories.tsx +0 -122
  138. package/src/components/Stepper/Stepper.tsx +0 -75
  139. package/src/components/Stepper/index.ts +0 -2
  140. package/src/components/Table/EmptyTable.png +0 -0
  141. package/src/components/Table/Table.definition.ts +0 -580
  142. package/src/components/Table/Table.stories.tsx +0 -853
  143. package/src/components/Table/Table.tsx +0 -495
  144. package/src/components/Table/data.ts +0 -134
  145. package/src/components/Table/exportsUtils.ts +0 -195
  146. package/src/components/Table/index.ts +0 -3
  147. package/src/components/Table/types.ts +0 -34
  148. package/src/components/Tabs/Tab.definition.ts +0 -53
  149. package/src/components/Tabs/Tab.tsx +0 -19
  150. package/src/components/Tabs/Tabs.stories.tsx +0 -118
  151. package/src/components/Tabs/Tabs.tsx +0 -99
  152. package/src/components/Tabs/_tabUtils.tsx +0 -4
  153. package/src/components/Tabs/index.ts +0 -2
  154. package/src/components/Timeline/Timeline.definition.ts +0 -43
  155. package/src/components/Timeline/Timeline.stories.tsx +0 -108
  156. package/src/components/Timeline/Timeline.tsx +0 -49
  157. package/src/components/Timeline/TimelineItem.tsx +0 -31
  158. package/src/components/Timeline/index.ts +0 -2
  159. package/src/components/Tooltip/Tooltip.stories.tsx +0 -129
  160. package/src/components/Tooltip/Tooltip.tsx +0 -58
  161. package/src/components/Tooltip/index.ts +0 -1
  162. package/src/components/_shared/formField.sx.ts +0 -118
  163. package/src/components/_shared/resolvePreset.ts +0 -35
  164. package/src/hooks/ClipBoard/ClipBoard.stories.tsx +0 -168
  165. package/src/hooks/ClipBoard/ClipBoard.tsx +0 -131
  166. package/src/hooks/ClipBoard/ClipboardUnifiedDemo.tsx +0 -111
  167. package/src/hooks/ClipBoard/index.ts +0 -1
  168. package/src/hooks/Wizard/Wizard.stories.tsx +0 -301
  169. package/src/hooks/Wizard/WizardContext.tsx +0 -166
  170. package/src/hooks/Wizard/index.ts +0 -6
  171. package/src/hooks/Wizard/useWizard.ts +0 -13
  172. package/src/index.ts +0 -17
  173. package/src/mui.ts +0 -44
  174. package/src/styles.css +0 -3
  175. package/src/theme/componentStyles.ts +0 -47
  176. package/src/theme/tokens.ts +0 -43
  177. package/tailwind.config.js +0 -10
  178. package/tsconfig.json +0 -48
  179. package/tsup.config.js +0 -41
  180. package/vite.config.js +0 -132
  181. package/vitest.config.ts +0 -35
@@ -1,32 +0,0 @@
1
- import type { SxProps, Theme } from '@mui/material/styles';
2
-
3
- export interface BuildAppBarSxArgs {
4
- /** Altura en px. Default: 64. */
5
- height?: number;
6
- /** Color del AppBar (se pasa al MuiAppBar). */
7
- transparent?: boolean;
8
- }
9
-
10
- /**
11
- * sx del root del MuiAppBar. Define altura fija y layout flex del Toolbar
12
- * interno. El color/elevación se dejan a las props nativas de MuiAppBar.
13
- */
14
- export function buildAppBarSx({
15
- height = 64,
16
- transparent = false,
17
- }: BuildAppBarSxArgs): SxProps<Theme> {
18
- return (theme) => ({
19
- minHeight: height,
20
- justifyContent: 'center',
21
- backgroundImage: 'none',
22
- ...(transparent && {
23
- backgroundColor: 'transparent',
24
- boxShadow: 'none',
25
- borderBottom: `1px solid ${theme.palette.divider}`,
26
- }),
27
- '& .MuiToolbar-root': {
28
- minHeight: height,
29
- gap: 1.5,
30
- },
31
- });
32
- }
@@ -1,123 +0,0 @@
1
- import React, { useMemo, type ReactNode } from 'react';
2
- import {
3
- AppBar as MuiAppBar,
4
- Toolbar,
5
- type AppBarProps as MuiAppBarProps,
6
- } from '@mui/material';
7
- import {
8
- useTheme,
9
- type SxProps,
10
- type Theme,
11
- } from '@mui/material/styles';
12
-
13
- import { AppBarContext } from './AppBarContext';
14
- import { buildAppBarSx } from './AppBar.sx';
15
- import { resolvePreset } from '../_shared/resolvePreset';
16
-
17
- export type AppBarPosition = 'fixed' | 'sticky' | 'static' | 'absolute' | 'relative';
18
- export type AppBarColor =
19
- | 'default'
20
- | 'primary'
21
- | 'secondary'
22
- | 'transparent'
23
- | 'inherit';
24
-
25
- export interface AppBarProps {
26
- /** Contenido del AppBar (típicamente sub-componentes + acciones custom). */
27
- children?: ReactNode;
28
- /** Posicionamiento. Default: `'sticky'`. */
29
- position?: AppBarPosition;
30
- /** Color. Default: `'default'`. */
31
- color?: AppBarColor;
32
- /** Nivel de sombra. Default: 1. */
33
- elevation?: number;
34
- /** Altura en px. Default: 64. */
35
- height?: number;
36
- /**
37
- * Handler del botón hamburguesa. Se expone vía AppBarContext para que el
38
- * sub-componente `<AppBarMenuToggle>` lo consuma sin prop drilling.
39
- */
40
- onMenuToggle?: () => void;
41
- /** Estado del drawer asociado (para que el icono del toggle cambie). */
42
- menuOpen?: boolean;
43
- /**
44
- * Nombre del preset de estilo registrado en `theme.styles.AppBar`.
45
- * - `"default"` (o ausente) = estilo built-in del paquete.
46
- */
47
- preset?: string;
48
- /** sx del root (se mergea después del preset). */
49
- sx?: SxProps<Theme>;
50
- /** sx del Toolbar interno. */
51
- toolbarSx?: SxProps<Theme>;
52
- className?: string;
53
- /** Otras props nativas del MuiAppBar (ej. `enableColorOnDark`). */
54
- appBarProps?: Omit<
55
- MuiAppBarProps,
56
- 'position' | 'color' | 'elevation' | 'sx' | 'children' | 'className'
57
- >;
58
- }
59
-
60
- /**
61
- * AppBar (header superior) del paquete. Se diseñó como un shell compositivo
62
- * — el consumer arma el contenido con los sub-componentes que exporta el
63
- * paquete (`AppBarBrand`, `AppBarMenuToggle`, `AppBarUserMenu`) + cualquier
64
- * otra cosa custom.
65
- *
66
- * Patrón recomendado para navegación en dashboards:
67
- *
68
- * ```tsx
69
- * <AppBar onMenuToggle={toggleDrawer}>
70
- * <AppBarMenuToggle />
71
- * <AppBarBrand logo={<Logo />} title="Afiliaciones" />
72
- * <Box sx={{ flex: 1 }} />
73
- * <AppBarUserMenu user={user} items={menuItems} />
74
- * </AppBar>
75
- * ```
76
- */
77
- export function AppBar({
78
- children,
79
- position = 'sticky',
80
- color = 'default',
81
- elevation = 1,
82
- height = 64,
83
- onMenuToggle,
84
- menuOpen,
85
- preset,
86
- sx,
87
- toolbarSx,
88
- className,
89
- appBarProps,
90
- }: AppBarProps) {
91
- const theme = useTheme();
92
- const presetSx = resolvePreset('AppBar', preset, theme);
93
-
94
- const transparent = color === 'transparent';
95
-
96
- const rootSx: SxProps<Theme> = [
97
- buildAppBarSx({ height, transparent }),
98
- ...(presetSx ? [presetSx] : []),
99
- ...(Array.isArray(sx) ? sx : sx ? [sx] : []),
100
- ];
101
-
102
- const contextValue = useMemo(
103
- () => ({ onMenuToggle, menuOpen }),
104
- [onMenuToggle, menuOpen],
105
- );
106
-
107
- return (
108
- <AppBarContext.Provider value={contextValue}>
109
- <MuiAppBar
110
- position={position}
111
- color={color === 'transparent' ? 'transparent' : color}
112
- elevation={elevation}
113
- className={className}
114
- sx={rootSx}
115
- {...appBarProps}
116
- >
117
- <Toolbar sx={toolbarSx}>{children}</Toolbar>
118
- </MuiAppBar>
119
- </AppBarContext.Provider>
120
- );
121
- }
122
-
123
- export default AppBar;
@@ -1,120 +0,0 @@
1
- import React, { type ReactNode, type MouseEvent } from 'react';
2
- import { Box, Typography } from '@mui/material';
3
- import type { SxProps, Theme } from '@mui/material/styles';
4
-
5
- export interface AppBarBrandProps {
6
- /** Logo (img, svg, componente). Se muestra a la izquierda del título. */
7
- logo?: ReactNode;
8
- /** Título del sistema. */
9
- title?: ReactNode;
10
- /** Subtítulo opcional (p.ej. nombre de módulo actual). */
11
- subtitle?: ReactNode;
12
- /** Handler de click sobre todo el brand (típicamente navega al home). */
13
- onClick?: (event: MouseEvent<HTMLDivElement>) => void;
14
- /** Oculta solo el título en viewports pequeños (mantiene el logo). Default: true. */
15
- hideTitleOnMobile?: boolean;
16
- sx?: SxProps<Theme>;
17
- className?: string;
18
- }
19
-
20
- /**
21
- * Brand del AppBar: combina logo + título + subtítulo opcional con un
22
- * click handler global (típicamente para navegar al home).
23
- *
24
- * ```tsx
25
- * <AppBarBrand
26
- * logo={<img src={logo} alt="" height={32} />}
27
- * title="Afiliaciones"
28
- * subtitle="Panel administrativo"
29
- * onClick={() => navigate('/')}
30
- * />
31
- * ```
32
- */
33
- export function AppBarBrand({
34
- logo,
35
- title,
36
- subtitle,
37
- onClick,
38
- hideTitleOnMobile = true,
39
- sx,
40
- className,
41
- }: AppBarBrandProps) {
42
- const clickable = !!onClick;
43
-
44
- const rootSx: SxProps<Theme> = [
45
- {
46
- display: 'flex',
47
- alignItems: 'center',
48
- gap: 1.25,
49
- cursor: clickable ? 'pointer' : 'default',
50
- userSelect: 'none',
51
- minWidth: 0,
52
- },
53
- ...(Array.isArray(sx) ? sx : sx ? [sx] : []),
54
- ];
55
-
56
- return (
57
- <Box
58
- role={clickable ? 'button' : undefined}
59
- tabIndex={clickable ? 0 : undefined}
60
- onClick={onClick}
61
- onKeyDown={(event) => {
62
- if (!clickable) return;
63
- if (event.key === 'Enter' || event.key === ' ') {
64
- event.preventDefault();
65
- onClick?.(event as unknown as MouseEvent<HTMLDivElement>);
66
- }
67
- }}
68
- className={className}
69
- sx={rootSx}
70
- >
71
- {logo && (
72
- <Box
73
- component="span"
74
- sx={{
75
- display: 'flex',
76
- alignItems: 'center',
77
- flexShrink: 0,
78
- }}
79
- >
80
- {logo}
81
- </Box>
82
- )}
83
- {(title || subtitle) && (
84
- <Box
85
- sx={{
86
- display: hideTitleOnMobile
87
- ? { xs: 'none', sm: 'flex' }
88
- : 'flex',
89
- flexDirection: 'column',
90
- minWidth: 0,
91
- lineHeight: 1.2,
92
- }}
93
- >
94
- {title && (
95
- <Typography
96
- component="span"
97
- variant="subtitle1"
98
- noWrap
99
- sx={{ fontWeight: 700 }}
100
- >
101
- {title}
102
- </Typography>
103
- )}
104
- {subtitle && (
105
- <Typography
106
- component="span"
107
- variant="caption"
108
- color="text.secondary"
109
- noWrap
110
- >
111
- {subtitle}
112
- </Typography>
113
- )}
114
- </Box>
115
- )}
116
- </Box>
117
- );
118
- }
119
-
120
- export default AppBarBrand;
@@ -1,25 +0,0 @@
1
- import { createContext, useContext } from 'react';
2
-
3
- /**
4
- * Context interno del AppBar. Permite que sub-componentes (MenuToggle, etc.)
5
- * consuman callbacks registrados en el AppBar padre sin tener que pasarlos
6
- * por props explícitas.
7
- */
8
- export interface AppBarContextValue {
9
- /** Handler del botón hamburguesa. Si es undefined, el toggle se oculta. */
10
- onMenuToggle?: () => void;
11
- /** Estado actual del drawer asociado (usado por el icono del toggle). */
12
- menuOpen?: boolean;
13
- }
14
-
15
- export const AppBarContext = createContext<AppBarContextValue | null>(null);
16
-
17
- /**
18
- * Hook para leer el contexto del AppBar. Si se llama fuera de un `<AppBar>`,
19
- * devuelve un objeto vacío — los sub-componentes caen en modo "standalone"
20
- * con sus defaults en lugar de romper.
21
- */
22
- export function useAppBarContext(): AppBarContextValue {
23
- const ctx = useContext(AppBarContext);
24
- return ctx ?? {};
25
- }
@@ -1,90 +0,0 @@
1
- import React, { type ReactNode } from 'react';
2
- import { IconButton, Tooltip } from '@mui/material';
3
- import MenuIcon from '@mui/icons-material/Menu';
4
- import MenuOpenIcon from '@mui/icons-material/MenuOpen';
5
- import type { SxProps, Theme } from '@mui/material/styles';
6
-
7
- import { useAppBarContext } from './AppBarContext';
8
-
9
- export interface AppBarMenuToggleProps {
10
- /**
11
- * Callback explícito. Si se omite, se consume del `AppBarContext`. Útil para
12
- * usar el toggle fuera de un `<AppBar>` (p.ej. en un header custom).
13
- */
14
- onClick?: () => void;
15
- /** Estado del drawer asociado. Si se omite, se lee del `AppBarContext`. */
16
- menuOpen?: boolean;
17
- /** Icono custom cuando el drawer está cerrado. Default: `<MenuIcon />`. */
18
- closedIcon?: ReactNode;
19
- /** Icono custom cuando el drawer está abierto. Default: `<MenuOpenIcon />`. */
20
- openIcon?: ReactNode;
21
- /** Texto de tooltip. Default: "Menú". */
22
- tooltip?: string;
23
- /** aria-label del botón. Default: el mismo tooltip. */
24
- ariaLabel?: string;
25
- /** Tamaño del IconButton. Default: `'medium'`. */
26
- size?: 'small' | 'medium' | 'large';
27
- /** Oculta el botón cuando no hay handler disponible. Default: true. */
28
- hideIfNoHandler?: boolean;
29
- sx?: SxProps<Theme>;
30
- className?: string;
31
- }
32
-
33
- /**
34
- * Botón hamburguesa del AppBar. Por default consume `onMenuToggle` y
35
- * `menuOpen` del `AppBarContext` (pattern composicional), pero permite
36
- * overrides explícitos si se usa fuera de un `<AppBar>`.
37
- *
38
- * ```tsx
39
- * <AppBar onMenuToggle={toggleDrawer} menuOpen={open}>
40
- * <AppBarMenuToggle />
41
- * ...
42
- * </AppBar>
43
- * ```
44
- */
45
- export function AppBarMenuToggle({
46
- onClick,
47
- menuOpen,
48
- closedIcon,
49
- openIcon,
50
- tooltip = 'Menú',
51
- ariaLabel,
52
- size = 'medium',
53
- hideIfNoHandler = true,
54
- sx,
55
- className,
56
- }: AppBarMenuToggleProps) {
57
- const ctx = useAppBarContext();
58
-
59
- const handler = onClick ?? ctx.onMenuToggle;
60
- const open = menuOpen ?? ctx.menuOpen ?? false;
61
-
62
- if (!handler && hideIfNoHandler) {
63
- return null;
64
- }
65
-
66
- const icon = open
67
- ? (openIcon ?? <MenuOpenIcon />)
68
- : (closedIcon ?? <MenuIcon />);
69
-
70
- return (
71
- <Tooltip title={tooltip} arrow>
72
- <span>
73
- <IconButton
74
- size={size}
75
- edge="start"
76
- color="inherit"
77
- aria-label={ariaLabel ?? tooltip}
78
- onClick={handler}
79
- disabled={!handler}
80
- className={className}
81
- sx={sx}
82
- >
83
- {icon}
84
- </IconButton>
85
- </span>
86
- </Tooltip>
87
- );
88
- }
89
-
90
- export default AppBarMenuToggle;
@@ -1,217 +0,0 @@
1
- import React, { useState, type ReactNode, type MouseEvent } from 'react';
2
- import {
3
- Avatar,
4
- Box,
5
- Divider,
6
- IconButton,
7
- ListItemIcon,
8
- ListItemText,
9
- Menu,
10
- MenuItem,
11
- Tooltip,
12
- Typography,
13
- } from '@mui/material';
14
- import type { SxProps, Theme } from '@mui/material/styles';
15
-
16
- export interface AppBarUserMenuItem {
17
- /** Key única. Si no se provee, se usa el label. */
18
- key?: string;
19
- /** Texto del item. */
20
- label: ReactNode;
21
- /** Icono opcional a la izquierda. */
22
- icon?: ReactNode;
23
- /** Handler de click. */
24
- onClick?: (event: MouseEvent<HTMLLIElement>) => void;
25
- /** Deshabilita el item. */
26
- disabled?: boolean;
27
- /** Pinta el item en color error (típico para "Cerrar sesión"). */
28
- danger?: boolean;
29
- /** Inserta un `<Divider />` ANTES de este item. */
30
- dividerBefore?: boolean;
31
- }
32
-
33
- export interface AppBarUserMenuUser {
34
- /** Nombre a mostrar en el header del menú. */
35
- name?: ReactNode;
36
- /** Email / subtítulo secundario. */
37
- email?: ReactNode;
38
- /** URL del avatar. Si se omite, se muestran iniciales del `name`. */
39
- avatarUrl?: string;
40
- /** Iniciales custom. Si se omite, se calculan del `name`. */
41
- initials?: string;
42
- }
43
-
44
- export interface AppBarUserMenuProps {
45
- /** Datos del usuario a mostrar. */
46
- user?: AppBarUserMenuUser;
47
- /** Items del menú. */
48
- items: AppBarUserMenuItem[];
49
- /**
50
- * Si `true`, oculta la fila con nombre + email en el tope del menú.
51
- * Default: `false`.
52
- */
53
- hideUserHeader?: boolean;
54
- /** Tooltip del trigger. Default: "Cuenta". */
55
- triggerTooltip?: string;
56
- /** Tamaño del Avatar en px. Default: 36. */
57
- avatarSize?: number;
58
- /** sx del Paper del Menu. */
59
- menuSx?: SxProps<Theme>;
60
- /** sx del trigger (IconButton). */
61
- triggerSx?: SxProps<Theme>;
62
- className?: string;
63
- }
64
-
65
- function computeInitials(name?: ReactNode): string {
66
- if (typeof name !== 'string') return '?';
67
- const parts = name.trim().split(/\s+/).filter(Boolean);
68
- if (parts.length === 0) return '?';
69
- const first = parts[0]?.charAt(0) ?? '';
70
- const last = parts.length > 1 ? (parts[parts.length - 1]?.charAt(0) ?? '') : '';
71
- return (first + last).toUpperCase();
72
- }
73
-
74
- /**
75
- * Menú de usuario del AppBar: avatar clickable que despliega un menú con la
76
- * info del usuario (nombre + email) y una lista de acciones (perfil, cerrar
77
- * sesión, etc).
78
- *
79
- * ```tsx
80
- * <AppBarUserMenu
81
- * user={{ name: 'Andrea', email: 'a@soyfri.com' }}
82
- * items={[
83
- * { label: 'Perfil', icon: <PersonIcon />, onClick: goToProfile },
84
- * { label: 'Cerrar sesión', icon: <LogoutIcon />, onClick: logout, danger: true, dividerBefore: true },
85
- * ]}
86
- * />
87
- * ```
88
- */
89
- export function AppBarUserMenu({
90
- user,
91
- items,
92
- hideUserHeader = false,
93
- triggerTooltip = 'Cuenta',
94
- avatarSize = 36,
95
- menuSx,
96
- triggerSx,
97
- className,
98
- }: AppBarUserMenuProps) {
99
- const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
100
- const open = Boolean(anchorEl);
101
-
102
- const handleOpen = (event: MouseEvent<HTMLElement>) => {
103
- setAnchorEl(event.currentTarget);
104
- };
105
- const handleClose = () => setAnchorEl(null);
106
-
107
- const handleItemClick = (
108
- event: MouseEvent<HTMLLIElement>,
109
- item: AppBarUserMenuItem,
110
- ) => {
111
- event.stopPropagation();
112
- item.onClick?.(event);
113
- handleClose();
114
- };
115
-
116
- const initials = user?.initials ?? computeInitials(user?.name);
117
- const showUserHeader = !hideUserHeader && (user?.name || user?.email);
118
-
119
- return (
120
- <Box component="span" className={className}>
121
- <Tooltip title={triggerTooltip} arrow>
122
- <IconButton
123
- onClick={handleOpen}
124
- size="small"
125
- aria-label={triggerTooltip}
126
- aria-haspopup="menu"
127
- aria-expanded={open || undefined}
128
- sx={[{ p: 0.5 }, ...(Array.isArray(triggerSx) ? triggerSx : triggerSx ? [triggerSx] : [])]}
129
- >
130
- <Avatar
131
- src={user?.avatarUrl}
132
- sx={{
133
- width: avatarSize,
134
- height: avatarSize,
135
- fontSize: avatarSize * 0.4,
136
- fontWeight: 600,
137
- }}
138
- >
139
- {!user?.avatarUrl && initials}
140
- </Avatar>
141
- </IconButton>
142
- </Tooltip>
143
-
144
- <Menu
145
- anchorEl={anchorEl}
146
- open={open}
147
- onClose={handleClose}
148
- anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
149
- transformOrigin={{ vertical: 'top', horizontal: 'right' }}
150
- slotProps={{
151
- paper: {
152
- sx: { minWidth: 240, ...(menuSx as any) },
153
- },
154
- }}
155
- >
156
- {showUserHeader && (
157
- <Box
158
- sx={{
159
- px: 2,
160
- py: 1.25,
161
- display: 'flex',
162
- flexDirection: 'column',
163
- gap: 0.25,
164
- }}
165
- >
166
- {user?.name && (
167
- <Typography variant="subtitle2" noWrap sx={{ fontWeight: 700 }}>
168
- {user.name}
169
- </Typography>
170
- )}
171
- {user?.email && (
172
- <Typography variant="caption" color="text.secondary" noWrap>
173
- {user.email}
174
- </Typography>
175
- )}
176
- </Box>
177
- )}
178
- {showUserHeader && <Divider />}
179
-
180
- {items.map((item, idx) => {
181
- const key = item.key ?? `${String(item.label)}-${idx}`;
182
- const node = (
183
- <MenuItem
184
- key={key}
185
- disabled={item.disabled}
186
- onClick={(event) => handleItemClick(event, item)}
187
- sx={(theme) => ({
188
- color: item.danger ? theme.palette.error.main : 'inherit',
189
- '& .MuiListItemIcon-root': {
190
- color: item.danger
191
- ? theme.palette.error.main
192
- : 'inherit',
193
- minWidth: 32,
194
- },
195
- })}
196
- >
197
- {item.icon && <ListItemIcon>{item.icon}</ListItemIcon>}
198
- <ListItemText primary={item.label} />
199
- </MenuItem>
200
- );
201
-
202
- if (item.dividerBefore && idx > 0) {
203
- return (
204
- <React.Fragment key={`${key}-frag`}>
205
- <Divider />
206
- {node}
207
- </React.Fragment>
208
- );
209
- }
210
- return node;
211
- })}
212
- </Menu>
213
- </Box>
214
- );
215
- }
216
-
217
- export default AppBarUserMenu;
@@ -1,25 +0,0 @@
1
- export { AppBar, default } from './AppBar';
2
- export type {
3
- AppBarProps,
4
- AppBarPosition,
5
- AppBarColor,
6
- } from './AppBar';
7
-
8
- export { AppBarBrand } from './AppBarBrand';
9
- export type { AppBarBrandProps } from './AppBarBrand';
10
-
11
- export { AppBarMenuToggle } from './AppBarMenuToggle';
12
- export type { AppBarMenuToggleProps } from './AppBarMenuToggle';
13
-
14
- export { AppBarUserMenu } from './AppBarUserMenu';
15
- export type {
16
- AppBarUserMenuProps,
17
- AppBarUserMenuItem,
18
- AppBarUserMenuUser,
19
- } from './AppBarUserMenu';
20
-
21
- export { AppBarContext, useAppBarContext } from './AppBarContext';
22
- export type { AppBarContextValue } from './AppBarContext';
23
-
24
- export { buildAppBarSx } from './AppBar.sx';
25
- export type { BuildAppBarSxArgs } from './AppBar.sx';