@soyfri/shared-library 4.0.1 → 4.0.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.
- package/{ActionMenu-wNWkDZWh.cjs → ActionMenu-D81Xb35f.cjs} +3 -3
- package/ActionMenu-D81Xb35f.cjs.map +1 -0
- package/{ActionMenu-BXRVKopM.js → ActionMenu-DYPA_tYk.js} +3 -3
- package/ActionMenu-DYPA_tYk.js.map +1 -0
- package/{Select-BaY3zJhq.js → Select-BIUq3ZPy.js} +8 -3
- package/Select-BIUq3ZPy.js.map +1 -0
- package/{Select-WpHNCHHz.cjs → Select-C06gHRqZ.cjs} +8 -3
- package/Select-C06gHRqZ.cjs.map +1 -0
- package/components/ActionMenu/ActionMenu.cjs +1 -1
- package/components/ActionMenu/ActionMenu.js +1 -1
- package/components/Select/Select.cjs +1 -1
- package/components/Select/Select.js +1 -1
- package/components/StatusMessage/StatusMessageContext.d.ts +16 -0
- package/hooks/ClipBoard/ClipBoard.cjs +43 -24
- package/hooks/ClipBoard/ClipBoard.cjs.map +1 -1
- package/hooks/ClipBoard/ClipBoard.d.ts +1 -1
- package/hooks/ClipBoard/ClipBoard.js +43 -24
- package/hooks/ClipBoard/ClipBoard.js.map +1 -1
- package/index.cjs +34 -2
- package/index.cjs.map +1 -1
- package/index.js +11 -3
- package/mui.d.ts +1 -0
- package/package.json +1 -1
- package/ActionMenu-BXRVKopM.js.map +0 -1
- package/ActionMenu-wNWkDZWh.cjs.map +0 -1
- package/Select-BaY3zJhq.js.map +0 -1
- package/Select-WpHNCHHz.cjs.map +0 -1
|
@@ -55,7 +55,7 @@ const ActionMenu = ({
|
|
|
55
55
|
const triggerElement = trigger ? React.cloneElement(trigger, {
|
|
56
56
|
onClick: openMenu,
|
|
57
57
|
disabled
|
|
58
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { title: triggerTooltip, arrow: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
58
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { title: triggerTooltip, arrow: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
59
59
|
material.IconButton,
|
|
60
60
|
{
|
|
61
61
|
size: "small",
|
|
@@ -64,7 +64,7 @@ const ActionMenu = ({
|
|
|
64
64
|
"aria-label": triggerTooltip,
|
|
65
65
|
children: /* @__PURE__ */ jsxRuntime.jsx(MoreVertIcon, { fontSize: "small" })
|
|
66
66
|
}
|
|
67
|
-
) });
|
|
67
|
+
) }) });
|
|
68
68
|
const paperSx = [
|
|
69
69
|
{ minWidth: 180 },
|
|
70
70
|
...Array.isArray(menuSx) ? menuSx : menuSx ? [menuSx] : []
|
|
@@ -102,4 +102,4 @@ const ActionMenuItem = React.forwardRef(
|
|
|
102
102
|
);
|
|
103
103
|
exports.ActionMenu = ActionMenu;
|
|
104
104
|
exports.ActionMenuItem = ActionMenuItem;
|
|
105
|
-
//# sourceMappingURL=ActionMenu-
|
|
105
|
+
//# sourceMappingURL=ActionMenu-D81Xb35f.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionMenu-D81Xb35f.cjs","sources":["../src/components/ActionMenu/ActionMenu.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useContext,\n useState,\n type ReactElement,\n type ReactNode,\n type MouseEvent,\n} from 'react';\nimport {\n IconButton,\n Menu,\n MenuItem,\n ListItemIcon,\n ListItemText,\n Tooltip,\n type MenuItemProps as MuiMenuItemProps,\n} from '@mui/material';\nimport MoreVertIcon from '@mui/icons-material/MoreVert';\nimport type { SxProps, Theme } from '@mui/material/styles';\n\nexport interface ActionMenuProps {\n /** Items del menú. Normalmente `<ActionMenuItem>` o `<Divider />`. */\n children: ReactNode;\n /**\n * Elemento disparador — cualquier componente clickeable (Button, Chip, IconButton…).\n * El ActionMenu le inyecta `onClick` automáticamente. Si se omite, se usa un\n * IconButton de tres puntos por defecto.\n */\n trigger?: ReactElement;\n /** Texto de tooltip sobre el trigger default. Default: \"Acciones\". */\n triggerTooltip?: string;\n /** Anchor origin del menu. Default: { vertical: 'bottom', horizontal: 'right' }. */\n anchorOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** Transform origin del menu. Default: { vertical: 'top', horizontal: 'right' }. */\n transformOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** sx del Menu (Paper interno). */\n menuSx?: SxProps<Theme>;\n /** Deshabilita el trigger entero. */\n disabled?: boolean;\n}\n\ninterface ActionMenuContextValue {\n close: () => void;\n}\n\nconst ActionMenuContext = createContext<ActionMenuContextValue | null>(null);\n\nexport const ActionMenu: React.FC<ActionMenuProps> = ({\n children,\n trigger,\n triggerTooltip,\n anchorOrigin = { vertical: 'bottom', horizontal: 'right' },\n transformOrigin = { vertical: 'top', horizontal: 'right' },\n menuSx,\n disabled = false,\n}) => {\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const open = Boolean(anchorEl);\n\n const handleClose = () => setAnchorEl(null);\n\n // Abre el menú anclándolo al elemento que recibió el click.\n const openMenu = (event: MouseEvent<HTMLElement>) => {\n if (disabled) return;\n event.stopPropagation();\n setAnchorEl(event.currentTarget);\n };\n\n // Si el consumer pasó un trigger (ej. <Button>), le inyectamos onClick.\n // Si no, usamos el IconButton de tres puntos por defecto.\n const triggerElement = trigger ? (\n React.cloneElement(trigger as ReactElement<any>, {\n onClick: openMenu,\n disabled,\n })\n ) : (\n <Tooltip title={triggerTooltip} arrow>\n {/*\n El <span> no es decorativo: un botón deshabilitado no dispara eventos,\n así que el Tooltip se queda sin nada que escuchar y MUI avisa por\n consola. El wrapper le da el elemento que necesita y, de paso, el\n tooltip sigue apareciendo cuando el menú está deshabilitado — que es\n justo cuando el usuario quiere saber por qué no puede hacer clic.\n */}\n <span>\n <IconButton\n size=\"small\"\n onClick={openMenu}\n disabled={disabled}\n aria-label={triggerTooltip}\n >\n <MoreVertIcon fontSize=\"small\" />\n </IconButton>\n </span>\n </Tooltip>\n );\n\n const paperSx = [\n { minWidth: 180 },\n ...(Array.isArray(menuSx) ? menuSx : menuSx ? [menuSx] : []),\n ] as SxProps<Theme>;\n\n return (\n <>\n {triggerElement}\n <Menu\n anchorEl={anchorEl}\n open={open}\n onClose={handleClose}\n anchorOrigin={anchorOrigin}\n transformOrigin={transformOrigin}\n slotProps={{ paper: { sx: paperSx } }}\n >\n <ActionMenuContext.Provider value={{ close: handleClose }}>\n {children}\n </ActionMenuContext.Provider>\n </Menu>\n </>\n );\n};\n\nexport interface ActionMenuItemProps\n extends Omit<MuiMenuItemProps, 'children' | 'onClick'> {\n /** Icono opcional a la izquierda. */\n icon?: ReactNode;\n /** Texto (o nodo) del item. */\n children: ReactNode;\n /** Handler de click. El menú se cierra automáticamente después. */\n onClick?: (event: MouseEvent<HTMLLIElement>) => void;\n}\n\n/**\n * Item del `ActionMenu`. Se cierra automáticamente al hacer click.\n * Acepta todos los props de `MenuItem` de MUI (disabled, selected, sx, …).\n */\nexport const ActionMenuItem = forwardRef<HTMLLIElement, ActionMenuItemProps>(\n function ActionMenuItem({ icon, children, onClick, ...rest }, ref) {\n const ctx = useContext(ActionMenuContext);\n\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n event.stopPropagation();\n onClick?.(event);\n ctx?.close();\n };\n\n return (\n <MenuItem ref={ref} onClick={handleClick} {...rest}>\n {icon && <ListItemIcon sx={{ minWidth: 32 }}>{icon}</ListItemIcon>}\n <ListItemText primary={children} />\n </MenuItem>\n );\n },\n);\n\nexport default ActionMenu;\n"],"names":["createContext","useState","jsx","Tooltip","IconButton","jsxs","Fragment","Menu","forwardRef","ActionMenuItem","useContext","MenuItem","ListItemIcon","ListItemText"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAM,oBAAoBA,MAAAA,cAA6C,IAAI;AAEpE,MAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,EAAE,UAAU,UAAU,YAAY,QAAA;AAAA,EACjD,kBAAkB,EAAE,UAAU,OAAO,YAAY,QAAA;AAAA,EACjD;AAAA,EACA,WAAW;AACb,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAIC,MAAAA,SAA6B,IAAI;AACjE,QAAM,OAAO,QAAQ,QAAQ;AAE7B,QAAM,cAAc,MAAM,YAAY,IAAI;AAG1C,QAAM,WAAW,CAAC,UAAmC;AACnD,QAAI,SAAU;AACd,UAAM,gBAAA;AACN,gBAAY,MAAM,aAAa;AAAA,EACjC;AAIA,QAAM,iBAAiB,UACrB,MAAM,aAAa,SAA8B;AAAA,IAC/C,SAAS;AAAA,IACT;AAAA,EAAA,CACD,IAEDC,2BAAAA,IAACC,SAAAA,SAAA,EAAQ,OAAO,gBAAgB,OAAK,MAQnC,UAAAD,2BAAAA,IAAC,QAAA,EACC,UAAAA,2BAAAA;AAAAA,IAACE,SAAAA;AAAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,cAAY;AAAA,MAEZ,UAAAF,2BAAAA,IAAC,cAAA,EAAa,UAAS,QAAA,CAAQ;AAAA,IAAA;AAAA,EAAA,GAEnC,EAAA,CACF;AAGF,QAAM,UAAU;AAAA,IACd,EAAE,UAAU,IAAA;AAAA,IACZ,GAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,CAAC,MAAM,IAAI,CAAA;AAAA,EAAC;AAG5D,SACEG,2BAAAA,KAAAC,qBAAA,EACG,UAAA;AAAA,IAAA;AAAA,IACDJ,2BAAAA;AAAAA,MAACK,SAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,WAAW,EAAE,OAAO,EAAE,IAAI,UAAQ;AAAA,QAElC,UAAAL,2BAAAA,IAAC,kBAAkB,UAAlB,EAA2B,OAAO,EAAE,OAAO,YAAA,GACzC,SAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;AAgBO,MAAM,iBAAiBM,MAAAA;AAAAA,EAC5B,SAASC,gBAAe,IAAsC,KAAK;AAA3C,iBAAE,QAAM,UAAU,YAAlB,IAA8B,iBAA9B,IAA8B,CAA5B,QAAM,YAAU;AACxC,UAAM,MAAMC,MAAAA,WAAW,iBAAiB;AAExC,UAAM,cAAc,CAAC,UAAqC;AACxD,YAAM,gBAAA;AACN,yCAAU;AACV,iCAAK;AAAA,IACP;AAEA,2CACGC,SAAAA,UAAA,+BAAS,KAAU,SAAS,eAAiB,OAA7C,EACE,UAAA;AAAA,MAAA,uCAASC,SAAAA,cAAA,EAAa,IAAI,EAAE,UAAU,GAAA,GAAO,UAAA,MAAK;AAAA,MACnDV,2BAAAA,IAACW,SAAAA,cAAA,EAAa,SAAS,SAAA,CAAU;AAAA,IAAA,IACnC;AAAA,EAEJ;AACF;;;"}
|
|
@@ -54,7 +54,7 @@ const ActionMenu = ({
|
|
|
54
54
|
const triggerElement = trigger ? React__default.cloneElement(trigger, {
|
|
55
55
|
onClick: openMenu,
|
|
56
56
|
disabled
|
|
57
|
-
}) : /* @__PURE__ */ jsx(Tooltip, { title: triggerTooltip, arrow: true, children: /* @__PURE__ */ jsx(
|
|
57
|
+
}) : /* @__PURE__ */ jsx(Tooltip, { title: triggerTooltip, arrow: true, children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
|
|
58
58
|
IconButton,
|
|
59
59
|
{
|
|
60
60
|
size: "small",
|
|
@@ -63,7 +63,7 @@ const ActionMenu = ({
|
|
|
63
63
|
"aria-label": triggerTooltip,
|
|
64
64
|
children: /* @__PURE__ */ jsx(MoreVertIcon, { fontSize: "small" })
|
|
65
65
|
}
|
|
66
|
-
) });
|
|
66
|
+
) }) });
|
|
67
67
|
const paperSx = [
|
|
68
68
|
{ minWidth: 180 },
|
|
69
69
|
...Array.isArray(menuSx) ? menuSx : menuSx ? [menuSx] : []
|
|
@@ -103,4 +103,4 @@ export {
|
|
|
103
103
|
ActionMenu as A,
|
|
104
104
|
ActionMenuItem as a
|
|
105
105
|
};
|
|
106
|
-
//# sourceMappingURL=ActionMenu-
|
|
106
|
+
//# sourceMappingURL=ActionMenu-DYPA_tYk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionMenu-DYPA_tYk.js","sources":["../src/components/ActionMenu/ActionMenu.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useContext,\n useState,\n type ReactElement,\n type ReactNode,\n type MouseEvent,\n} from 'react';\nimport {\n IconButton,\n Menu,\n MenuItem,\n ListItemIcon,\n ListItemText,\n Tooltip,\n type MenuItemProps as MuiMenuItemProps,\n} from '@mui/material';\nimport MoreVertIcon from '@mui/icons-material/MoreVert';\nimport type { SxProps, Theme } from '@mui/material/styles';\n\nexport interface ActionMenuProps {\n /** Items del menú. Normalmente `<ActionMenuItem>` o `<Divider />`. */\n children: ReactNode;\n /**\n * Elemento disparador — cualquier componente clickeable (Button, Chip, IconButton…).\n * El ActionMenu le inyecta `onClick` automáticamente. Si se omite, se usa un\n * IconButton de tres puntos por defecto.\n */\n trigger?: ReactElement;\n /** Texto de tooltip sobre el trigger default. Default: \"Acciones\". */\n triggerTooltip?: string;\n /** Anchor origin del menu. Default: { vertical: 'bottom', horizontal: 'right' }. */\n anchorOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** Transform origin del menu. Default: { vertical: 'top', horizontal: 'right' }. */\n transformOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** sx del Menu (Paper interno). */\n menuSx?: SxProps<Theme>;\n /** Deshabilita el trigger entero. */\n disabled?: boolean;\n}\n\ninterface ActionMenuContextValue {\n close: () => void;\n}\n\nconst ActionMenuContext = createContext<ActionMenuContextValue | null>(null);\n\nexport const ActionMenu: React.FC<ActionMenuProps> = ({\n children,\n trigger,\n triggerTooltip,\n anchorOrigin = { vertical: 'bottom', horizontal: 'right' },\n transformOrigin = { vertical: 'top', horizontal: 'right' },\n menuSx,\n disabled = false,\n}) => {\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const open = Boolean(anchorEl);\n\n const handleClose = () => setAnchorEl(null);\n\n // Abre el menú anclándolo al elemento que recibió el click.\n const openMenu = (event: MouseEvent<HTMLElement>) => {\n if (disabled) return;\n event.stopPropagation();\n setAnchorEl(event.currentTarget);\n };\n\n // Si el consumer pasó un trigger (ej. <Button>), le inyectamos onClick.\n // Si no, usamos el IconButton de tres puntos por defecto.\n const triggerElement = trigger ? (\n React.cloneElement(trigger as ReactElement<any>, {\n onClick: openMenu,\n disabled,\n })\n ) : (\n <Tooltip title={triggerTooltip} arrow>\n {/*\n El <span> no es decorativo: un botón deshabilitado no dispara eventos,\n así que el Tooltip se queda sin nada que escuchar y MUI avisa por\n consola. El wrapper le da el elemento que necesita y, de paso, el\n tooltip sigue apareciendo cuando el menú está deshabilitado — que es\n justo cuando el usuario quiere saber por qué no puede hacer clic.\n */}\n <span>\n <IconButton\n size=\"small\"\n onClick={openMenu}\n disabled={disabled}\n aria-label={triggerTooltip}\n >\n <MoreVertIcon fontSize=\"small\" />\n </IconButton>\n </span>\n </Tooltip>\n );\n\n const paperSx = [\n { minWidth: 180 },\n ...(Array.isArray(menuSx) ? menuSx : menuSx ? [menuSx] : []),\n ] as SxProps<Theme>;\n\n return (\n <>\n {triggerElement}\n <Menu\n anchorEl={anchorEl}\n open={open}\n onClose={handleClose}\n anchorOrigin={anchorOrigin}\n transformOrigin={transformOrigin}\n slotProps={{ paper: { sx: paperSx } }}\n >\n <ActionMenuContext.Provider value={{ close: handleClose }}>\n {children}\n </ActionMenuContext.Provider>\n </Menu>\n </>\n );\n};\n\nexport interface ActionMenuItemProps\n extends Omit<MuiMenuItemProps, 'children' | 'onClick'> {\n /** Icono opcional a la izquierda. */\n icon?: ReactNode;\n /** Texto (o nodo) del item. */\n children: ReactNode;\n /** Handler de click. El menú se cierra automáticamente después. */\n onClick?: (event: MouseEvent<HTMLLIElement>) => void;\n}\n\n/**\n * Item del `ActionMenu`. Se cierra automáticamente al hacer click.\n * Acepta todos los props de `MenuItem` de MUI (disabled, selected, sx, …).\n */\nexport const ActionMenuItem = forwardRef<HTMLLIElement, ActionMenuItemProps>(\n function ActionMenuItem({ icon, children, onClick, ...rest }, ref) {\n const ctx = useContext(ActionMenuContext);\n\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n event.stopPropagation();\n onClick?.(event);\n ctx?.close();\n };\n\n return (\n <MenuItem ref={ref} onClick={handleClick} {...rest}>\n {icon && <ListItemIcon sx={{ minWidth: 32 }}>{icon}</ListItemIcon>}\n <ListItemText primary={children} />\n </MenuItem>\n );\n },\n);\n\nexport default ActionMenu;\n"],"names":["React","ActionMenuItem"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAM,oBAAoB,cAA6C,IAAI;AAEpE,MAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,EAAE,UAAU,UAAU,YAAY,QAAA;AAAA,EACjD,kBAAkB,EAAE,UAAU,OAAO,YAAY,QAAA;AAAA,EACjD;AAAA,EACA,WAAW;AACb,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAI,SAA6B,IAAI;AACjE,QAAM,OAAO,QAAQ,QAAQ;AAE7B,QAAM,cAAc,MAAM,YAAY,IAAI;AAG1C,QAAM,WAAW,CAAC,UAAmC;AACnD,QAAI,SAAU;AACd,UAAM,gBAAA;AACN,gBAAY,MAAM,aAAa;AAAA,EACjC;AAIA,QAAM,iBAAiB,UACrBA,eAAM,aAAa,SAA8B;AAAA,IAC/C,SAAS;AAAA,IACT;AAAA,EAAA,CACD,IAED,oBAAC,SAAA,EAAQ,OAAO,gBAAgB,OAAK,MAQnC,UAAA,oBAAC,QAAA,EACC,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,cAAY;AAAA,MAEZ,UAAA,oBAAC,cAAA,EAAa,UAAS,QAAA,CAAQ;AAAA,IAAA;AAAA,EAAA,GAEnC,EAAA,CACF;AAGF,QAAM,UAAU;AAAA,IACd,EAAE,UAAU,IAAA;AAAA,IACZ,GAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,CAAC,MAAM,IAAI,CAAA;AAAA,EAAC;AAG5D,SACE,qBAAA,UAAA,EACG,UAAA;AAAA,IAAA;AAAA,IACD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,WAAW,EAAE,OAAO,EAAE,IAAI,UAAQ;AAAA,QAElC,UAAA,oBAAC,kBAAkB,UAAlB,EAA2B,OAAO,EAAE,OAAO,YAAA,GACzC,SAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;AAgBO,MAAM,iBAAiB;AAAA,EAC5B,SAASC,gBAAe,IAAsC,KAAK;AAA3C,iBAAE,QAAM,UAAU,YAAlB,IAA8B,iBAA9B,IAA8B,CAA5B,QAAM,YAAU;AACxC,UAAM,MAAM,WAAW,iBAAiB;AAExC,UAAM,cAAc,CAAC,UAAqC;AACxD,YAAM,gBAAA;AACN,yCAAU;AACV,iCAAK;AAAA,IACP;AAEA,gCACG,UAAA,+BAAS,KAAU,SAAS,eAAiB,OAA7C,EACE,UAAA;AAAA,MAAA,4BAAS,cAAA,EAAa,IAAI,EAAE,UAAU,GAAA,GAAO,UAAA,MAAK;AAAA,MACnD,oBAAC,cAAA,EAAa,SAAS,SAAA,CAAU;AAAA,IAAA,IACnC;AAAA,EAEJ;AACF;"}
|
|
@@ -151,7 +151,8 @@ function Select(props) {
|
|
|
151
151
|
control: _controlIgnored,
|
|
152
152
|
validation: _validationIgnored,
|
|
153
153
|
value: _valueIgnored,
|
|
154
|
-
onChange: _onChangeIgnored
|
|
154
|
+
onChange: _onChangeIgnored,
|
|
155
|
+
onValueChange: _onValueChangeIgnored
|
|
155
156
|
} = _a, rest = __objRest(_a, [
|
|
156
157
|
"label",
|
|
157
158
|
"options",
|
|
@@ -181,7 +182,11 @@ function Select(props) {
|
|
|
181
182
|
"control",
|
|
182
183
|
"validation",
|
|
183
184
|
"value",
|
|
184
|
-
"onChange"
|
|
185
|
+
"onChange",
|
|
186
|
+
// Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en
|
|
187
|
+
// `rest` hasta el DOM del MuiSelect: "Unknown event handler property
|
|
188
|
+
// `onValueChange`. It will be ignored." en cada render del select en cascada.
|
|
189
|
+
"onValueChange"
|
|
185
190
|
]);
|
|
186
191
|
const theme = useTheme();
|
|
187
192
|
const presetSx = resolvePreset("Select", preset, theme);
|
|
@@ -374,4 +379,4 @@ export {
|
|
|
374
379
|
Option as O,
|
|
375
380
|
Select as S
|
|
376
381
|
};
|
|
377
|
-
//# sourceMappingURL=Select-
|
|
382
|
+
//# sourceMappingURL=Select-BIUq3ZPy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select-BIUq3ZPy.js","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/_parts/SelectValue.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import { Avatar, Box, Chip, Typography } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n SelectOption,\n RenderChipLabel,\n ChipVariant,\n} from '../Select';\n\ninterface SelectValueProps<TValue extends SelectOption['value']> {\n selected: TValue | TValue[] | null | undefined;\n options: SelectOption[];\n multiple: boolean;\n placeholder?: string;\n maxChipsToShow: number;\n chipVariant: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n /** Solo relevante en modo multiple. Recibe el nuevo array de valores. */\n onDeleteChip?: (nextValues: TValue[]) => void;\n /** Array de valores actuales (para componer el nuevo array al borrar chips). */\n currentValues?: TValue[];\n}\n\n/**\n * Render del valor seleccionado del Select.\n * - single: texto (label) o lo que devuelva `renderChipLabel`.\n * - multiple: chips con delete. Trunca después de `maxChipsToShow` mostrando \"+N más\".\n * - empty: placeholder en color disabled.\n */\nexport function SelectValue<TValue extends SelectOption['value']>(\n props: SelectValueProps<TValue>,\n) {\n const {\n selected,\n options,\n multiple,\n placeholder,\n maxChipsToShow,\n chipVariant,\n renderChipLabel,\n onDeleteChip,\n currentValues,\n } = props;\n\n const isEmpty =\n !selected || (Array.isArray(selected) && selected.length === 0);\n\n if (isEmpty) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>{placeholder || ''}</Typography>\n );\n }\n\n if (!multiple) {\n const item = options.find((opt) => opt.value === selected);\n if (renderChipLabel && item) return <>{renderChipLabel(item)}</>;\n return <>{item?.label ?? String(selected)}</>;\n }\n\n const selectedValuesArray = selected as TValue[];\n const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);\n const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;\n\n const handleDelete = (chipValue: TValue) => {\n if (!onDeleteChip || !currentValues) return;\n onDeleteChip(currentValues.filter((v) => v !== chipValue));\n };\n\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {displayedChips.map((val) => {\n const item = options.find((o) => o.value === val);\n if (!item) return null;\n\n return (\n <Chip\n variant={chipVariant}\n color=\"primary\"\n size=\"small\"\n key={String(val)}\n label={renderChipLabel ? renderChipLabel(item) : item.label}\n avatar={item.img ? <Avatar src={item.img} /> : undefined}\n onDelete={() => handleDelete(val)}\n deleteIcon={<ClearIcon fontSize=\"small\" />}\n />\n );\n })}\n {hiddenChipsCount > 0 && (\n <Chip size=\"small\" variant={chipVariant} label={`+${hiddenChipsCount} más`} />\n )}\n </Box>\n );\n}\n\nexport default SelectValue;\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n TextField,\n InputAdornment,\n Box,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport SearchIcon from '@mui/icons-material/Search';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport { FIELD_BORDER_RADIUS } from '../../theme/tokens';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\nimport { SelectValue } from './_parts/SelectValue';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n/** Variante visual de los chips en modo `multiple`. */\nexport type ChipVariant = 'filled' | 'outlined';\n/** Render custom del label de cada chip/valor seleccionado. */\nexport type RenderChipLabel = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n /** Si `true`, muestra un buscador arriba del menú para filtrar opciones. */\n filterable?: boolean;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n multiple?: false;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple?: false;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\nexport interface MultipleSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple: true;\n value: TValue[];\n onChange: (val: TValue[]) => void;\n /** Máximo de chips visibles antes de truncar con \"+N más\". Default: 3. */\n maxChipsToShow?: number;\n /** Variante visual de los chips. Default: 'filled'. */\n chipVariant?: ChipVariant;\n /** Render custom del label de cada chip. */\n renderChipLabel?: RenderChipLabel;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> =\n | RHFSelectProps<TValue>\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = FIELD_BORDER_RADIUS,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n multiple = false,\n maxChipsToShow = 3,\n chipVariant = 'filled',\n renderChipLabel,\n filterable = false,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n // Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en\n // `rest` hasta el DOM del MuiSelect: \"Unknown event handler property\n // `onValueChange`. It will be ignored.\" en cada render del select en cascada.\n onValueChange: _onValueChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n onValueChange?: (value: TValue) => void;\n multiple?: boolean;\n maxChipsToShow?: number;\n chipVariant?: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n filterable?: boolean;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n // Texto del buscador (modo `filterable`).\n const [searchText, setSearchText] = useState('');\n\n const filteredOptions = useMemo(() => {\n if (!filterable || !searchText.trim()) return options;\n const q = searchText.trim().toLowerCase();\n return options.filter((opt) => opt.label.toLowerCase().includes(q));\n }, [options, filterable, searchText]);\n\n const groupedOptions = useMemo(\n () => groupOptions(filteredOptions),\n [filteredOptions],\n );\n\n // Items del menú (grupos + opciones). El buscador se inyecta aparte.\n const buildMenuItems = (currentValue: TValue | TValue[] | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = Array.isArray(currentValue)\n ? currentValue.includes(opt.value as TValue)\n : currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | TValue[] | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue | TValue[]>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n onValuesChange?: (next: TValue[]) => void,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = multiple\n ? ((selectValue as TValue[] | null | undefined) ?? [])\n : normalizeSelectValue(selectValue as TValue | null | undefined);\n const isEmpty = multiple\n ? (normalizedValue as TValue[]).length === 0\n : isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue | TValue[]>\n multiple={multiple}\n value={normalizedValue as TValue | TValue[]}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => {\n setIsOpen(false);\n if (filterable) setSearchText('');\n }}\n renderValue={(selected) => (\n <SelectValue<TValue>\n selected={selected as TValue | TValue[]}\n options={options}\n multiple={multiple}\n placeholder={placeholder}\n maxChipsToShow={maxChipsToShow}\n chipVariant={chipVariant}\n renderChipLabel={renderChipLabel}\n currentValues={multiple ? (selected as TValue[]) : undefined}\n onDeleteChip={onValuesChange}\n />\n )}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {filterable && (\n <Box\n sx={{ px: 1.5, py: 1, position: 'sticky', top: 0, zIndex: 1, bgcolor: 'background.paper' }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <TextField\n size=\"small\"\n fullWidth\n autoFocus\n placeholder=\"Buscar...\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n </Box>\n )}\n {buildMenuItems(normalizedValue as TValue | TValue[] | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n (nextVals) => {\n field.onChange(nextVals);\n onValueChange?.(nextVals as unknown as TValue);\n },\n )\n }\n />\n );\n }\n\n // ── Controlled mode (single o multiple) ───────────────────────────────\n const { value, onChange } = props as\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n const handleChange = onChange as (val: TValue | TValue[]) => void;\n return renderSelect(\n value as TValue | TValue[],\n (e) => handleChange(e.target.value as TValue | TValue[]),\n undefined,\n undefined,\n undefined,\n undefined,\n (next) => (onChange as (val: TValue[]) => void)(next),\n );\n}\n\nexport default Select;\n"],"names":["_a","MuiSelect"],"mappings":"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"}
|
|
@@ -152,7 +152,8 @@ function Select(props) {
|
|
|
152
152
|
control: _controlIgnored,
|
|
153
153
|
validation: _validationIgnored,
|
|
154
154
|
value: _valueIgnored,
|
|
155
|
-
onChange: _onChangeIgnored
|
|
155
|
+
onChange: _onChangeIgnored,
|
|
156
|
+
onValueChange: _onValueChangeIgnored
|
|
156
157
|
} = _a, rest = __objRest(_a, [
|
|
157
158
|
"label",
|
|
158
159
|
"options",
|
|
@@ -182,7 +183,11 @@ function Select(props) {
|
|
|
182
183
|
"control",
|
|
183
184
|
"validation",
|
|
184
185
|
"value",
|
|
185
|
-
"onChange"
|
|
186
|
+
"onChange",
|
|
187
|
+
// Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en
|
|
188
|
+
// `rest` hasta el DOM del MuiSelect: "Unknown event handler property
|
|
189
|
+
// `onValueChange`. It will be ignored." en cada render del select en cascada.
|
|
190
|
+
"onValueChange"
|
|
186
191
|
]);
|
|
187
192
|
const theme = styles.useTheme();
|
|
188
193
|
const presetSx = resolvePreset.resolvePreset("Select", preset, theme);
|
|
@@ -373,4 +378,4 @@ function Select(props) {
|
|
|
373
378
|
}
|
|
374
379
|
exports.Option = Option;
|
|
375
380
|
exports.Select = Select;
|
|
376
|
-
//# sourceMappingURL=Select-
|
|
381
|
+
//# sourceMappingURL=Select-C06gHRqZ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select-C06gHRqZ.cjs","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/_parts/SelectValue.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import { Avatar, Box, Chip, Typography } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n SelectOption,\n RenderChipLabel,\n ChipVariant,\n} from '../Select';\n\ninterface SelectValueProps<TValue extends SelectOption['value']> {\n selected: TValue | TValue[] | null | undefined;\n options: SelectOption[];\n multiple: boolean;\n placeholder?: string;\n maxChipsToShow: number;\n chipVariant: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n /** Solo relevante en modo multiple. Recibe el nuevo array de valores. */\n onDeleteChip?: (nextValues: TValue[]) => void;\n /** Array de valores actuales (para componer el nuevo array al borrar chips). */\n currentValues?: TValue[];\n}\n\n/**\n * Render del valor seleccionado del Select.\n * - single: texto (label) o lo que devuelva `renderChipLabel`.\n * - multiple: chips con delete. Trunca después de `maxChipsToShow` mostrando \"+N más\".\n * - empty: placeholder en color disabled.\n */\nexport function SelectValue<TValue extends SelectOption['value']>(\n props: SelectValueProps<TValue>,\n) {\n const {\n selected,\n options,\n multiple,\n placeholder,\n maxChipsToShow,\n chipVariant,\n renderChipLabel,\n onDeleteChip,\n currentValues,\n } = props;\n\n const isEmpty =\n !selected || (Array.isArray(selected) && selected.length === 0);\n\n if (isEmpty) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>{placeholder || ''}</Typography>\n );\n }\n\n if (!multiple) {\n const item = options.find((opt) => opt.value === selected);\n if (renderChipLabel && item) return <>{renderChipLabel(item)}</>;\n return <>{item?.label ?? String(selected)}</>;\n }\n\n const selectedValuesArray = selected as TValue[];\n const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);\n const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;\n\n const handleDelete = (chipValue: TValue) => {\n if (!onDeleteChip || !currentValues) return;\n onDeleteChip(currentValues.filter((v) => v !== chipValue));\n };\n\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {displayedChips.map((val) => {\n const item = options.find((o) => o.value === val);\n if (!item) return null;\n\n return (\n <Chip\n variant={chipVariant}\n color=\"primary\"\n size=\"small\"\n key={String(val)}\n label={renderChipLabel ? renderChipLabel(item) : item.label}\n avatar={item.img ? <Avatar src={item.img} /> : undefined}\n onDelete={() => handleDelete(val)}\n deleteIcon={<ClearIcon fontSize=\"small\" />}\n />\n );\n })}\n {hiddenChipsCount > 0 && (\n <Chip size=\"small\" variant={chipVariant} label={`+${hiddenChipsCount} más`} />\n )}\n </Box>\n );\n}\n\nexport default SelectValue;\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n TextField,\n InputAdornment,\n Box,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport SearchIcon from '@mui/icons-material/Search';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport { FIELD_BORDER_RADIUS } from '../../theme/tokens';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\nimport { SelectValue } from './_parts/SelectValue';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n/** Variante visual de los chips en modo `multiple`. */\nexport type ChipVariant = 'filled' | 'outlined';\n/** Render custom del label de cada chip/valor seleccionado. */\nexport type RenderChipLabel = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n /** Si `true`, muestra un buscador arriba del menú para filtrar opciones. */\n filterable?: boolean;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n multiple?: false;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple?: false;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\nexport interface MultipleSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple: true;\n value: TValue[];\n onChange: (val: TValue[]) => void;\n /** Máximo de chips visibles antes de truncar con \"+N más\". Default: 3. */\n maxChipsToShow?: number;\n /** Variante visual de los chips. Default: 'filled'. */\n chipVariant?: ChipVariant;\n /** Render custom del label de cada chip. */\n renderChipLabel?: RenderChipLabel;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> =\n | RHFSelectProps<TValue>\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = FIELD_BORDER_RADIUS,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n multiple = false,\n maxChipsToShow = 3,\n chipVariant = 'filled',\n renderChipLabel,\n filterable = false,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n // Se consume aparte en la rama RHF (más abajo). Sin sacarlo acá viajaba en\n // `rest` hasta el DOM del MuiSelect: \"Unknown event handler property\n // `onValueChange`. It will be ignored.\" en cada render del select en cascada.\n onValueChange: _onValueChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n onValueChange?: (value: TValue) => void;\n multiple?: boolean;\n maxChipsToShow?: number;\n chipVariant?: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n filterable?: boolean;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n // Texto del buscador (modo `filterable`).\n const [searchText, setSearchText] = useState('');\n\n const filteredOptions = useMemo(() => {\n if (!filterable || !searchText.trim()) return options;\n const q = searchText.trim().toLowerCase();\n return options.filter((opt) => opt.label.toLowerCase().includes(q));\n }, [options, filterable, searchText]);\n\n const groupedOptions = useMemo(\n () => groupOptions(filteredOptions),\n [filteredOptions],\n );\n\n // Items del menú (grupos + opciones). El buscador se inyecta aparte.\n const buildMenuItems = (currentValue: TValue | TValue[] | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = Array.isArray(currentValue)\n ? currentValue.includes(opt.value as TValue)\n : currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | TValue[] | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue | TValue[]>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n onValuesChange?: (next: TValue[]) => void,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = multiple\n ? ((selectValue as TValue[] | null | undefined) ?? [])\n : normalizeSelectValue(selectValue as TValue | null | undefined);\n const isEmpty = multiple\n ? (normalizedValue as TValue[]).length === 0\n : isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue | TValue[]>\n multiple={multiple}\n value={normalizedValue as TValue | TValue[]}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => {\n setIsOpen(false);\n if (filterable) setSearchText('');\n }}\n renderValue={(selected) => (\n <SelectValue<TValue>\n selected={selected as TValue | TValue[]}\n options={options}\n multiple={multiple}\n placeholder={placeholder}\n maxChipsToShow={maxChipsToShow}\n chipVariant={chipVariant}\n renderChipLabel={renderChipLabel}\n currentValues={multiple ? (selected as TValue[]) : undefined}\n onDeleteChip={onValuesChange}\n />\n )}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {filterable && (\n <Box\n sx={{ px: 1.5, py: 1, position: 'sticky', top: 0, zIndex: 1, bgcolor: 'background.paper' }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <TextField\n size=\"small\"\n fullWidth\n autoFocus\n placeholder=\"Buscar...\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n </Box>\n )}\n {buildMenuItems(normalizedValue as TValue | TValue[] | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n (nextVals) => {\n field.onChange(nextVals);\n onValueChange?.(nextVals as unknown as TValue);\n },\n )\n }\n />\n );\n }\n\n // ── Controlled mode (single o multiple) ───────────────────────────────\n const { value, onChange } = props as\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n const handleChange = onChange as (val: TValue | TValue[]) => void;\n return renderSelect(\n value as TValue | TValue[],\n (e) => handleChange(e.target.value as TValue | TValue[]),\n undefined,\n undefined,\n undefined,\n undefined,\n (next) => (onChange as (val: TValue[]) => void)(next),\n );\n}\n\nexport default Select;\n"],"names":["buildFormFieldSx","jsxs","MenuItem","jsx","ListItemIcon","Typography","Fragment","Box","Chip","Avatar","FIELD_BORDER_RADIUS","useTheme","resolvePreset","useMemo","Children","isValidElement","_a","useState","ListSubheader","FilledInput","OutlinedInput","FormControl","InputLabel","MuiSelect","TextField","InputAdornment","FormHelperText","Controller"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
-
const ActionMenu = require("../../ActionMenu-
|
|
3
|
+
const ActionMenu = require("../../ActionMenu-D81Xb35f.cjs");
|
|
4
4
|
exports.ActionMenu = ActionMenu.ActionMenu;
|
|
5
5
|
exports.ActionMenuItem = ActionMenu.ActionMenuItem;
|
|
6
6
|
exports.default = ActionMenu.ActionMenu;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
-
const Select = require("../../Select-
|
|
3
|
+
const Select = require("../../Select-C06gHRqZ.cjs");
|
|
4
4
|
exports.Option = Select.Option;
|
|
5
5
|
exports.Select = Select.Select;
|
|
6
6
|
exports.default = Select.Select;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Dispatch, SetStateAction, ReactNode } from 'react';
|
|
2
|
+
import { StatusMessageProps } from './StatusMessage';
|
|
3
|
+
export type StatusMessageState = {
|
|
4
|
+
[K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;
|
|
5
|
+
} & Pick<StatusMessageProps, 'displayType'>;
|
|
6
|
+
interface StatusMessageContextValue {
|
|
7
|
+
state: StatusMessageState | undefined;
|
|
8
|
+
setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;
|
|
9
|
+
cleanMessage: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const useStatusMessageContext: () => StatusMessageContextValue;
|
|
12
|
+
interface StatusMessageProviderProps {
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export declare const StatusMessageProvider: ({ children }: StatusMessageProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
@@ -17,37 +17,56 @@ function useClipboard(options) {
|
|
|
17
17
|
}
|
|
18
18
|
setSnackbarOpen(false);
|
|
19
19
|
}, []);
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} else {
|
|
26
|
-
const textarea = document.createElement("textarea");
|
|
27
|
-
textarea.value = text;
|
|
28
|
-
document.body.appendChild(textarea);
|
|
29
|
-
textarea.select();
|
|
30
|
-
document.execCommand("copy");
|
|
31
|
-
document.body.removeChild(textarea);
|
|
32
|
-
}
|
|
33
|
-
setSnackbarMessage((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
|
|
34
|
-
setSnackbarSeverity((options == null ? void 0 : options.severity) || "success");
|
|
20
|
+
const mostrarSnackbar = React.useCallback(
|
|
21
|
+
(mensaje, severidad) => {
|
|
22
|
+
var _a2;
|
|
23
|
+
setSnackbarMessage(mensaje);
|
|
24
|
+
setSnackbarSeverity(severidad);
|
|
35
25
|
setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
|
|
36
26
|
setSnackbarDuration((_a2 = options == null ? void 0 : options.duration) != null ? _a2 : 3e3);
|
|
37
27
|
setSnackbarOpen(true);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
28
|
+
},
|
|
29
|
+
[options]
|
|
30
|
+
);
|
|
31
|
+
const copiarConTextarea = React.useCallback((text) => {
|
|
32
|
+
const textarea = document.createElement("textarea");
|
|
33
|
+
textarea.value = text;
|
|
34
|
+
textarea.style.position = "fixed";
|
|
35
|
+
textarea.style.top = "0";
|
|
36
|
+
textarea.style.opacity = "0";
|
|
37
|
+
document.body.appendChild(textarea);
|
|
38
|
+
textarea.select();
|
|
39
|
+
try {
|
|
40
|
+
return document.execCommand("copy");
|
|
41
|
+
} catch (e) {
|
|
42
|
+
return false;
|
|
43
|
+
} finally {
|
|
44
|
+
document.body.removeChild(textarea);
|
|
45
45
|
}
|
|
46
|
-
}, [
|
|
46
|
+
}, []);
|
|
47
|
+
const executeCopy = React.useCallback(
|
|
48
|
+
async (text) => {
|
|
49
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
50
|
+
try {
|
|
51
|
+
await navigator.clipboard.writeText(text);
|
|
52
|
+
mostrarSnackbar((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!", (options == null ? void 0 : options.severity) || "success");
|
|
53
|
+
return true;
|
|
54
|
+
} catch (e) {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (copiarConTextarea(text)) {
|
|
58
|
+
mostrarSnackbar((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!", (options == null ? void 0 : options.severity) || "success");
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
mostrarSnackbar("No se pudo copiar al portapapeles.", "error");
|
|
62
|
+
return false;
|
|
63
|
+
},
|
|
64
|
+
[copiarConTextarea, mostrarSnackbar, options]
|
|
65
|
+
);
|
|
47
66
|
const copyFromRef = React.useCallback(() => {
|
|
48
67
|
if (elementRef.current) {
|
|
49
68
|
const textToCopy = elementRef.current.innerText || "";
|
|
50
|
-
executeCopy(textToCopy);
|
|
69
|
+
void executeCopy(textToCopy);
|
|
51
70
|
}
|
|
52
71
|
}, [executeCopy]);
|
|
53
72
|
React.useEffect(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClipBoard.cjs","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["// useClipboard.tsx (Versión Unificada)\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Proporciona funcionalidad de copiado de texto y feedback visual (Snackbar).\n * Permite dos modos de uso:\n * 1. Uso por Referencia (ref): Se adjunta a un elemento, copia su innerText al hacer clic.\n * 2. Uso por Función (copy): Recibe el texto a copiar directamente como argumento.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una React Ref para adjuntar a un elemento (Modo Ref).\n * - 'copy': Una función (text: string) => void para copiar texto (Modo Función).\n * - 'CopyMessage': El componente Snackbar para renderizar el feedback.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n // --- Elementos de Copiado por Referencia ---\n const elementRef = useRef<HTMLElement>(null);\n\n // --- Estados y Opciones del Snackbar ---\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState<import('@mui/material').SnackbarOrigin>(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration ?? 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n /**\n * FUNCIÓN PRINCIPAL DE COPIADO.\n * Se usa internamente para 'ref' y se expone para 'copy(text)'.\n * @param text El texto exacto a copiar.\n */\n const
|
|
1
|
+
{"version":3,"file":"ClipBoard.cjs","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["// useClipboard.tsx (Versión Unificada)\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Proporciona funcionalidad de copiado de texto y feedback visual (Snackbar).\n * Permite dos modos de uso:\n * 1. Uso por Referencia (ref): Se adjunta a un elemento, copia su innerText al hacer clic.\n * 2. Uso por Función (copy): Recibe el texto a copiar directamente como argumento.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una React Ref para adjuntar a un elemento (Modo Ref).\n * - 'copy': Una función (text: string) => void para copiar texto (Modo Función).\n * - 'CopyMessage': El componente Snackbar para renderizar el feedback.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n // --- Elementos de Copiado por Referencia ---\n const elementRef = useRef<HTMLElement>(null);\n\n // --- Estados y Opciones del Snackbar ---\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState<import('@mui/material').SnackbarOrigin>(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration ?? 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n /**\n * FUNCIÓN PRINCIPAL DE COPIADO.\n * Se usa internamente para 'ref' y se expone para 'copy(text)'.\n * @param text El texto exacto a copiar.\n */\n const mostrarSnackbar = useCallback(\n (mensaje: string, severidad: AlertProps['severity']) => {\n setSnackbarMessage(mensaje);\n setSnackbarSeverity(severidad);\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration ?? 3000);\n setSnackbarOpen(true);\n },\n [options],\n );\n\n /** Fallback legacy. `execCommand` devuelve `false` en vez de tirar cuando falla. */\n const copiarConTextarea = useCallback((text: string): boolean => {\n const textarea = document.createElement('textarea');\n textarea.value = text;\n // Fuera de la vista pero seleccionable: sin esto la página salta al final.\n textarea.style.position = 'fixed';\n textarea.style.top = '0';\n textarea.style.opacity = '0';\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand('copy');\n } catch {\n return false;\n } finally {\n document.body.removeChild(textarea);\n }\n }, []);\n\n const executeCopy = useCallback(\n async (text: string): Promise<boolean> => {\n // `writeText` es ASÍNCRONA: llamarla sin await/catch dejaba la promesa\n // suelta, y cuando el navegador la rechaza —documento sin foco, permiso\n // denegado, contexto no seguro— la rejection escapaba al `window` de la\n // app que consume la librería. El try/catch de antes sólo atrapaba\n // errores síncronos, así que no cubría nada de eso.\n if (navigator.clipboard && window.isSecureContext) {\n try {\n await navigator.clipboard.writeText(text);\n mostrarSnackbar(options?.message || '¡Copiado al portapapeles!', options?.severity || 'success');\n return true;\n } catch {\n // Puede ser sólo falta de foco: se intenta el fallback antes de rendirse.\n }\n }\n\n if (copiarConTextarea(text)) {\n mostrarSnackbar(options?.message || '¡Copiado al portapapeles!', options?.severity || 'success');\n return true;\n }\n\n mostrarSnackbar('No se pudo copiar al portapapeles.', 'error');\n return false;\n },\n [copiarConTextarea, mostrarSnackbar, options],\n );\n\n // --- Lógica del Modo Ref ---\n const copyFromRef = useCallback(() => {\n if (elementRef.current) {\n const textToCopy = elementRef.current.innerText || '';\n // `void`: el listener del DOM no puede esperar la promesa, y ésta ya\n // maneja sus propios errores adentro.\n void executeCopy(textToCopy);\n }\n }, [executeCopy]);\n\n // Adjunta un event listener de clic al elemento referenciado (Modo Ref)\n useEffect(() => {\n const currentElement = elementRef.current;\n if (currentElement) {\n currentElement.style.cursor = 'pointer';\n // Adjuntamos la función que copia el texto del ref\n currentElement.addEventListener('click', copyFromRef);\n }\n\n return () => {\n if (currentElement) {\n currentElement.removeEventListener('click', copyFromRef);\n }\n };\n }, [copyFromRef]);\n\n\n // Componente Snackbar encapsulado. Solo se renderiza si duration es > 0.\n const CopyMessage = () => {\n if (snackbarDuration <= 0) return null; // No renderizar si la duración es 0\n\n return (\n <Snackbar\n open={snackbarOpen}\n autoHideDuration={snackbarDuration}\n onClose={handleSnackbarClose}\n anchorOrigin={snackbarPosition}\n >\n <Alert onClose={handleSnackbarClose} severity={snackbarSeverity} sx={{ width: '100%' }}>\n {snackbarMessage}\n </Alert>\n </Snackbar>\n );\n };\n\n // Retorna ambas funcionalidades para que el usuario elija\n return { ref: elementRef, copy: executeCopy, CopyMessage };\n}\n\nexport default useClipboard;"],"names":["useRef","useState","useCallback","_a","useEffect","jsx","Snackbar","Alert"],"mappings":"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"}
|
|
@@ -24,7 +24,7 @@ interface SnackbarOptions {
|
|
|
24
24
|
*/
|
|
25
25
|
export declare function useClipboard(options?: SnackbarOptions): {
|
|
26
26
|
ref: React.RefObject<HTMLElement | null>;
|
|
27
|
-
copy: (text: string) =>
|
|
27
|
+
copy: (text: string) => Promise<boolean>;
|
|
28
28
|
CopyMessage: () => import("react/jsx-runtime").JSX.Element | null;
|
|
29
29
|
};
|
|
30
30
|
export default useClipboard;
|
|
@@ -15,37 +15,56 @@ function useClipboard(options) {
|
|
|
15
15
|
}
|
|
16
16
|
setSnackbarOpen(false);
|
|
17
17
|
}, []);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} else {
|
|
24
|
-
const textarea = document.createElement("textarea");
|
|
25
|
-
textarea.value = text;
|
|
26
|
-
document.body.appendChild(textarea);
|
|
27
|
-
textarea.select();
|
|
28
|
-
document.execCommand("copy");
|
|
29
|
-
document.body.removeChild(textarea);
|
|
30
|
-
}
|
|
31
|
-
setSnackbarMessage((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
|
|
32
|
-
setSnackbarSeverity((options == null ? void 0 : options.severity) || "success");
|
|
18
|
+
const mostrarSnackbar = useCallback(
|
|
19
|
+
(mensaje, severidad) => {
|
|
20
|
+
var _a2;
|
|
21
|
+
setSnackbarMessage(mensaje);
|
|
22
|
+
setSnackbarSeverity(severidad);
|
|
33
23
|
setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
|
|
34
24
|
setSnackbarDuration((_a2 = options == null ? void 0 : options.duration) != null ? _a2 : 3e3);
|
|
35
25
|
setSnackbarOpen(true);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
26
|
+
},
|
|
27
|
+
[options]
|
|
28
|
+
);
|
|
29
|
+
const copiarConTextarea = useCallback((text) => {
|
|
30
|
+
const textarea = document.createElement("textarea");
|
|
31
|
+
textarea.value = text;
|
|
32
|
+
textarea.style.position = "fixed";
|
|
33
|
+
textarea.style.top = "0";
|
|
34
|
+
textarea.style.opacity = "0";
|
|
35
|
+
document.body.appendChild(textarea);
|
|
36
|
+
textarea.select();
|
|
37
|
+
try {
|
|
38
|
+
return document.execCommand("copy");
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return false;
|
|
41
|
+
} finally {
|
|
42
|
+
document.body.removeChild(textarea);
|
|
43
43
|
}
|
|
44
|
-
}, [
|
|
44
|
+
}, []);
|
|
45
|
+
const executeCopy = useCallback(
|
|
46
|
+
async (text) => {
|
|
47
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
48
|
+
try {
|
|
49
|
+
await navigator.clipboard.writeText(text);
|
|
50
|
+
mostrarSnackbar((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!", (options == null ? void 0 : options.severity) || "success");
|
|
51
|
+
return true;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (copiarConTextarea(text)) {
|
|
56
|
+
mostrarSnackbar((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!", (options == null ? void 0 : options.severity) || "success");
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
mostrarSnackbar("No se pudo copiar al portapapeles.", "error");
|
|
60
|
+
return false;
|
|
61
|
+
},
|
|
62
|
+
[copiarConTextarea, mostrarSnackbar, options]
|
|
63
|
+
);
|
|
45
64
|
const copyFromRef = useCallback(() => {
|
|
46
65
|
if (elementRef.current) {
|
|
47
66
|
const textToCopy = elementRef.current.innerText || "";
|
|
48
|
-
executeCopy(textToCopy);
|
|
67
|
+
void executeCopy(textToCopy);
|
|
49
68
|
}
|
|
50
69
|
}, [executeCopy]);
|
|
51
70
|
useEffect(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClipBoard.js","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["// useClipboard.tsx (Versión Unificada)\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Proporciona funcionalidad de copiado de texto y feedback visual (Snackbar).\n * Permite dos modos de uso:\n * 1. Uso por Referencia (ref): Se adjunta a un elemento, copia su innerText al hacer clic.\n * 2. Uso por Función (copy): Recibe el texto a copiar directamente como argumento.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una React Ref para adjuntar a un elemento (Modo Ref).\n * - 'copy': Una función (text: string) => void para copiar texto (Modo Función).\n * - 'CopyMessage': El componente Snackbar para renderizar el feedback.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n // --- Elementos de Copiado por Referencia ---\n const elementRef = useRef<HTMLElement>(null);\n\n // --- Estados y Opciones del Snackbar ---\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState<import('@mui/material').SnackbarOrigin>(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration ?? 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n /**\n * FUNCIÓN PRINCIPAL DE COPIADO.\n * Se usa internamente para 'ref' y se expone para 'copy(text)'.\n * @param text El texto exacto a copiar.\n */\n const
|
|
1
|
+
{"version":3,"file":"ClipBoard.js","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["// useClipboard.tsx (Versión Unificada)\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Proporciona funcionalidad de copiado de texto y feedback visual (Snackbar).\n * Permite dos modos de uso:\n * 1. Uso por Referencia (ref): Se adjunta a un elemento, copia su innerText al hacer clic.\n * 2. Uso por Función (copy): Recibe el texto a copiar directamente como argumento.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una React Ref para adjuntar a un elemento (Modo Ref).\n * - 'copy': Una función (text: string) => void para copiar texto (Modo Función).\n * - 'CopyMessage': El componente Snackbar para renderizar el feedback.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n // --- Elementos de Copiado por Referencia ---\n const elementRef = useRef<HTMLElement>(null);\n\n // --- Estados y Opciones del Snackbar ---\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState<import('@mui/material').SnackbarOrigin>(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration ?? 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n /**\n * FUNCIÓN PRINCIPAL DE COPIADO.\n * Se usa internamente para 'ref' y se expone para 'copy(text)'.\n * @param text El texto exacto a copiar.\n */\n const mostrarSnackbar = useCallback(\n (mensaje: string, severidad: AlertProps['severity']) => {\n setSnackbarMessage(mensaje);\n setSnackbarSeverity(severidad);\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration ?? 3000);\n setSnackbarOpen(true);\n },\n [options],\n );\n\n /** Fallback legacy. `execCommand` devuelve `false` en vez de tirar cuando falla. */\n const copiarConTextarea = useCallback((text: string): boolean => {\n const textarea = document.createElement('textarea');\n textarea.value = text;\n // Fuera de la vista pero seleccionable: sin esto la página salta al final.\n textarea.style.position = 'fixed';\n textarea.style.top = '0';\n textarea.style.opacity = '0';\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand('copy');\n } catch {\n return false;\n } finally {\n document.body.removeChild(textarea);\n }\n }, []);\n\n const executeCopy = useCallback(\n async (text: string): Promise<boolean> => {\n // `writeText` es ASÍNCRONA: llamarla sin await/catch dejaba la promesa\n // suelta, y cuando el navegador la rechaza —documento sin foco, permiso\n // denegado, contexto no seguro— la rejection escapaba al `window` de la\n // app que consume la librería. El try/catch de antes sólo atrapaba\n // errores síncronos, así que no cubría nada de eso.\n if (navigator.clipboard && window.isSecureContext) {\n try {\n await navigator.clipboard.writeText(text);\n mostrarSnackbar(options?.message || '¡Copiado al portapapeles!', options?.severity || 'success');\n return true;\n } catch {\n // Puede ser sólo falta de foco: se intenta el fallback antes de rendirse.\n }\n }\n\n if (copiarConTextarea(text)) {\n mostrarSnackbar(options?.message || '¡Copiado al portapapeles!', options?.severity || 'success');\n return true;\n }\n\n mostrarSnackbar('No se pudo copiar al portapapeles.', 'error');\n return false;\n },\n [copiarConTextarea, mostrarSnackbar, options],\n );\n\n // --- Lógica del Modo Ref ---\n const copyFromRef = useCallback(() => {\n if (elementRef.current) {\n const textToCopy = elementRef.current.innerText || '';\n // `void`: el listener del DOM no puede esperar la promesa, y ésta ya\n // maneja sus propios errores adentro.\n void executeCopy(textToCopy);\n }\n }, [executeCopy]);\n\n // Adjunta un event listener de clic al elemento referenciado (Modo Ref)\n useEffect(() => {\n const currentElement = elementRef.current;\n if (currentElement) {\n currentElement.style.cursor = 'pointer';\n // Adjuntamos la función que copia el texto del ref\n currentElement.addEventListener('click', copyFromRef);\n }\n\n return () => {\n if (currentElement) {\n currentElement.removeEventListener('click', copyFromRef);\n }\n };\n }, [copyFromRef]);\n\n\n // Componente Snackbar encapsulado. Solo se renderiza si duration es > 0.\n const CopyMessage = () => {\n if (snackbarDuration <= 0) return null; // No renderizar si la duración es 0\n\n return (\n <Snackbar\n open={snackbarOpen}\n autoHideDuration={snackbarDuration}\n onClose={handleSnackbarClose}\n anchorOrigin={snackbarPosition}\n >\n <Alert onClose={handleSnackbarClose} severity={snackbarSeverity} sx={{ width: '100%' }}>\n {snackbarMessage}\n </Alert>\n </Snackbar>\n );\n };\n\n // Retorna ambas funcionalidades para que el usuario elija\n return { ref: elementRef, copy: executeCopy, CopyMessage };\n}\n\nexport default useClipboard;"],"names":["_a"],"mappings":"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"}
|
package/index.cjs
CHANGED
|
@@ -23,7 +23,7 @@ const Table = require("./Table-BpnAkCgd.cjs");
|
|
|
23
23
|
const StatusMessage = require("./StatusMessage-B3nXpuRl.cjs");
|
|
24
24
|
const Modal = require("./Modal-Cfyr-RsW.cjs");
|
|
25
25
|
const Input = require("./Input-Bpjw7qwq.cjs");
|
|
26
|
-
const Select = require("./Select-
|
|
26
|
+
const Select = require("./Select-C06gHRqZ.cjs");
|
|
27
27
|
const Autocomplete = require("./Autocomplete-Bd3bN4Cw.cjs");
|
|
28
28
|
const Switch = require("./Switch-B4ex7yKR.cjs");
|
|
29
29
|
const RadioGroup = require("./RadioGroup-DVvmmDs3.cjs");
|
|
@@ -31,7 +31,7 @@ const Checkbox = require("./Checkbox-Bx4Asmg7.cjs");
|
|
|
31
31
|
const DatePicker = require("./DatePicker-CMcQddi1.cjs");
|
|
32
32
|
const DateTimePicker = require("./DateTimePicker-BVJGq1A0.cjs");
|
|
33
33
|
const InputGroup = require("./InputGroup-BZ7cmAcg.cjs");
|
|
34
|
-
const ActionMenu = require("./ActionMenu-
|
|
34
|
+
const ActionMenu = require("./ActionMenu-D81Xb35f.cjs");
|
|
35
35
|
const AppBarMenuToggle = require("./AppBarMenuToggle-D_RJGtHO.cjs");
|
|
36
36
|
const DrawerItem = require("./DrawerItem-DlnG_NdY.cjs");
|
|
37
37
|
const Flyout = require("./Flyout-fycujUVf.cjs");
|
|
@@ -118,6 +118,38 @@ Object.defineProperty(exports, "ListSubheader", {
|
|
|
118
118
|
enumerable: true,
|
|
119
119
|
get: () => material.ListSubheader
|
|
120
120
|
});
|
|
121
|
+
Object.defineProperty(exports, "MuiTable", {
|
|
122
|
+
enumerable: true,
|
|
123
|
+
get: () => material.Table
|
|
124
|
+
});
|
|
125
|
+
Object.defineProperty(exports, "MuiTableBody", {
|
|
126
|
+
enumerable: true,
|
|
127
|
+
get: () => material.TableBody
|
|
128
|
+
});
|
|
129
|
+
Object.defineProperty(exports, "MuiTableCell", {
|
|
130
|
+
enumerable: true,
|
|
131
|
+
get: () => material.TableCell
|
|
132
|
+
});
|
|
133
|
+
Object.defineProperty(exports, "MuiTableContainer", {
|
|
134
|
+
enumerable: true,
|
|
135
|
+
get: () => material.TableContainer
|
|
136
|
+
});
|
|
137
|
+
Object.defineProperty(exports, "MuiTableHead", {
|
|
138
|
+
enumerable: true,
|
|
139
|
+
get: () => material.TableHead
|
|
140
|
+
});
|
|
141
|
+
Object.defineProperty(exports, "MuiTablePagination", {
|
|
142
|
+
enumerable: true,
|
|
143
|
+
get: () => material.TablePagination
|
|
144
|
+
});
|
|
145
|
+
Object.defineProperty(exports, "MuiTableRow", {
|
|
146
|
+
enumerable: true,
|
|
147
|
+
get: () => material.TableRow
|
|
148
|
+
});
|
|
149
|
+
Object.defineProperty(exports, "MuiTableSortLabel", {
|
|
150
|
+
enumerable: true,
|
|
151
|
+
get: () => material.TableSortLabel
|
|
152
|
+
});
|
|
121
153
|
Object.defineProperty(exports, "Paper", {
|
|
122
154
|
enumerable: true,
|
|
123
155
|
get: () => material.Paper
|
package/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/utils/scrollToTop.ts"],"sourcesContent":["export interface ScrollToTopOptions {\n /** Comportamiento del scroll. Default: `'smooth'`. */\n behavior?: ScrollBehavior;\n /**\n * Elemento target del scroll. Default: `window`. Útil cuando el contenedor\n * scrolleable NO es `window` (p.ej. un `<Box>` con `overflow: auto`).\n */\n target?: Window | HTMLElement;\n /** Offset desde el top. Default: `0`. */\n top?: number;\n}\n\n/**\n * Hace scroll al tope (por default con animación suave). Safe en SSR — si\n * `window` no existe, es un no-op.\n *\n * Llamar tras mutaciones / cambios de filtros / apertura de modales para\n * asegurar que el usuario vea el mensaje de confirmación en la parte\n * superior de la página.\n *\n * ```ts\n * import { scrollToTop } from '@soyfri/shared-library';\n *\n * scrollToTop(); // window, smooth\n * scrollToTop({ behavior: 'auto' }); // window, instantáneo\n * scrollToTop({ target: myScrollableRef.current }); // container custom\n * ```\n */\nexport function scrollToTop({\n behavior = 'smooth',\n target = typeof window !== 'undefined' ? window : undefined,\n top = 0,\n}: ScrollToTopOptions = {}): void {\n if (!target) return;\n target.scrollTo({ top, left: 0, behavior });\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BO,SAAS,YAAY;AAAA,EAC1B,WAAW;AAAA,EACX,SAAS,OAAO,WAAW,cAAc,SAAS;AAAA,EAClD,MAAM;AACR,IAAwB,IAAU;AAChC,MAAI,CAAC,OAAQ;AACb,SAAO,SAAS,EAAE,KAAK,MAAM,GAAG,UAAU;AAC5C
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/utils/scrollToTop.ts"],"sourcesContent":["export interface ScrollToTopOptions {\n /** Comportamiento del scroll. Default: `'smooth'`. */\n behavior?: ScrollBehavior;\n /**\n * Elemento target del scroll. Default: `window`. Útil cuando el contenedor\n * scrolleable NO es `window` (p.ej. un `<Box>` con `overflow: auto`).\n */\n target?: Window | HTMLElement;\n /** Offset desde el top. Default: `0`. */\n top?: number;\n}\n\n/**\n * Hace scroll al tope (por default con animación suave). Safe en SSR — si\n * `window` no existe, es un no-op.\n *\n * Llamar tras mutaciones / cambios de filtros / apertura de modales para\n * asegurar que el usuario vea el mensaje de confirmación en la parte\n * superior de la página.\n *\n * ```ts\n * import { scrollToTop } from '@soyfri/shared-library';\n *\n * scrollToTop(); // window, smooth\n * scrollToTop({ behavior: 'auto' }); // window, instantáneo\n * scrollToTop({ target: myScrollableRef.current }); // container custom\n * ```\n */\nexport function scrollToTop({\n behavior = 'smooth',\n target = typeof window !== 'undefined' ? window : undefined,\n top = 0,\n}: ScrollToTopOptions = {}): void {\n if (!target) return;\n target.scrollTo({ top, left: 0, behavior });\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BO,SAAS,YAAY;AAAA,EAC1B,WAAW;AAAA,EACX,SAAS,OAAO,WAAW,cAAc,SAAS;AAAA,EAClD,MAAM;AACR,IAAwB,IAAU;AAChC,MAAI,CAAC,OAAQ;AACb,SAAO,SAAS,EAAE,KAAK,MAAM,GAAG,UAAU;AAC5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { D, r } from "./resolvePreset-K6_BfWHD.js";
|
|
2
|
-
import { AlertTitle, Backdrop, Box, CircularProgress, Collapse, Container, Fade, Grid, Grow, LinearProgress, Link, List, ListItem, ListItemButton, ListItemIcon, ListItemText, ListSubheader, Paper, Skeleton, Snackbar, Stack, ThemeProvider, Typography, Zoom, alpha, createTheme, styled, useMediaQuery, useTheme } from "@mui/material";
|
|
2
|
+
import { AlertTitle, Backdrop, Box, CircularProgress, Collapse, Container, Fade, Grid, Grow, LinearProgress, Link, List, ListItem, ListItemButton, ListItemIcon, ListItemText, ListSubheader, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, Paper, Skeleton, Snackbar, Stack, ThemeProvider, Typography, Zoom, alpha, createTheme, styled, useMediaQuery, useTheme } from "@mui/material";
|
|
3
3
|
import { renderMultiSectionDigitalClockTimeView } from "@mui/x-date-pickers/timeViewRenderers";
|
|
4
4
|
import { B } from "./Button-UkkP-bNw.js";
|
|
5
5
|
import { C } from "./Card-DYKGY-NG.js";
|
|
@@ -21,7 +21,7 @@ import { T as T2 } from "./Table-BuALBQWX.js";
|
|
|
21
21
|
import { S as S4 } from "./StatusMessage-D0WgSBx7.js";
|
|
22
22
|
import { M, b, c, a as a3 } from "./Modal-BqW0Nk3l.js";
|
|
23
23
|
import { I } from "./Input-BibHlnGN.js";
|
|
24
|
-
import { O, S as S5 } from "./Select-
|
|
24
|
+
import { O, S as S5 } from "./Select-BIUq3ZPy.js";
|
|
25
25
|
import { A as A3, a as a4 } from "./Autocomplete-E5aSUGVK.js";
|
|
26
26
|
import { S as S6 } from "./Switch-CY1Dd2ff.js";
|
|
27
27
|
import { R } from "./RadioGroup-cKCpag8W.js";
|
|
@@ -29,7 +29,7 @@ import { C as C3 } from "./Checkbox-BL4kvHFB.js";
|
|
|
29
29
|
import { D as D4 } from "./DatePicker-D__RSgs-.js";
|
|
30
30
|
import { D as D5 } from "./DateTimePicker-LeaE716a.js";
|
|
31
31
|
import { I as I2 } from "./InputGroup-D5pXKGjZ.js";
|
|
32
|
-
import { A as A4, a as a5 } from "./ActionMenu-
|
|
32
|
+
import { A as A4, a as a5 } from "./ActionMenu-DYPA_tYk.js";
|
|
33
33
|
import { A as A5, a as a6, u } from "./AppBarMenuToggle-BpXBMeca.js";
|
|
34
34
|
import { D as D6, a as a7, u as u2 } from "./DrawerItem-at1lsEo9.js";
|
|
35
35
|
import { F } from "./Flyout-DCcDBYKT.js";
|
|
@@ -97,6 +97,14 @@ export {
|
|
|
97
97
|
b as ModalBody,
|
|
98
98
|
c as ModalFooter,
|
|
99
99
|
a3 as ModalHeader,
|
|
100
|
+
Table as MuiTable,
|
|
101
|
+
TableBody as MuiTableBody,
|
|
102
|
+
TableCell as MuiTableCell,
|
|
103
|
+
TableContainer as MuiTableContainer,
|
|
104
|
+
TableHead as MuiTableHead,
|
|
105
|
+
TablePagination as MuiTablePagination,
|
|
106
|
+
TableRow as MuiTableRow,
|
|
107
|
+
TableSortLabel as MuiTableSortLabel,
|
|
100
108
|
O as Option,
|
|
101
109
|
P as PageHeader,
|
|
102
110
|
Paper,
|
package/mui.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { Box, Stack, Grid, Container, Paper, Divider, } from '@mui/material';
|
|
|
2
2
|
export { Typography, Link } from '@mui/material';
|
|
3
3
|
export { List, ListItem, ListItemButton, ListItemIcon, ListItemText, ListSubheader, } from '@mui/material';
|
|
4
4
|
export { CircularProgress, LinearProgress, Skeleton, Alert, AlertTitle, Snackbar, Backdrop, Fade, Grow, Zoom, Collapse, } from '@mui/material';
|
|
5
|
+
export { Table as MuiTable, TableBody as MuiTableBody, TableCell as MuiTableCell, TableContainer as MuiTableContainer, TableHead as MuiTableHead, TableRow as MuiTableRow, TableSortLabel as MuiTableSortLabel, TablePagination as MuiTablePagination, } from '@mui/material';
|
|
5
6
|
export { useTheme, useMediaQuery, alpha, styled, createTheme, ThemeProvider } from '@mui/material';
|
|
6
7
|
export type { SxProps, Theme } from '@mui/material/styles';
|
|
7
8
|
export { renderMultiSectionDigitalClockTimeView } from '@mui/x-date-pickers/timeViewRenderers';
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ActionMenu-BXRVKopM.js","sources":["../src/components/ActionMenu/ActionMenu.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useContext,\n useState,\n type ReactElement,\n type ReactNode,\n type MouseEvent,\n} from 'react';\nimport {\n IconButton,\n Menu,\n MenuItem,\n ListItemIcon,\n ListItemText,\n Tooltip,\n type MenuItemProps as MuiMenuItemProps,\n} from '@mui/material';\nimport MoreVertIcon from '@mui/icons-material/MoreVert';\nimport type { SxProps, Theme } from '@mui/material/styles';\n\nexport interface ActionMenuProps {\n /** Items del menú. Normalmente `<ActionMenuItem>` o `<Divider />`. */\n children: ReactNode;\n /**\n * Elemento disparador — cualquier componente clickeable (Button, Chip, IconButton…).\n * El ActionMenu le inyecta `onClick` automáticamente. Si se omite, se usa un\n * IconButton de tres puntos por defecto.\n */\n trigger?: ReactElement;\n /** Texto de tooltip sobre el trigger default. Default: \"Acciones\". */\n triggerTooltip?: string;\n /** Anchor origin del menu. Default: { vertical: 'bottom', horizontal: 'right' }. */\n anchorOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** Transform origin del menu. Default: { vertical: 'top', horizontal: 'right' }. */\n transformOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** sx del Menu (Paper interno). */\n menuSx?: SxProps<Theme>;\n /** Deshabilita el trigger entero. */\n disabled?: boolean;\n}\n\ninterface ActionMenuContextValue {\n close: () => void;\n}\n\nconst ActionMenuContext = createContext<ActionMenuContextValue | null>(null);\n\nexport const ActionMenu: React.FC<ActionMenuProps> = ({\n children,\n trigger,\n triggerTooltip,\n anchorOrigin = { vertical: 'bottom', horizontal: 'right' },\n transformOrigin = { vertical: 'top', horizontal: 'right' },\n menuSx,\n disabled = false,\n}) => {\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const open = Boolean(anchorEl);\n\n const handleClose = () => setAnchorEl(null);\n\n // Abre el menú anclándolo al elemento que recibió el click.\n const openMenu = (event: MouseEvent<HTMLElement>) => {\n if (disabled) return;\n event.stopPropagation();\n setAnchorEl(event.currentTarget);\n };\n\n // Si el consumer pasó un trigger (ej. <Button>), le inyectamos onClick.\n // Si no, usamos el IconButton de tres puntos por defecto.\n const triggerElement = trigger ? (\n React.cloneElement(trigger as ReactElement<any>, {\n onClick: openMenu,\n disabled,\n })\n ) : (\n <Tooltip title={triggerTooltip} arrow>\n <IconButton\n size=\"small\"\n onClick={openMenu}\n disabled={disabled}\n aria-label={triggerTooltip}\n >\n <MoreVertIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n );\n\n const paperSx = [\n { minWidth: 180 },\n ...(Array.isArray(menuSx) ? menuSx : menuSx ? [menuSx] : []),\n ] as SxProps<Theme>;\n\n return (\n <>\n {triggerElement}\n <Menu\n anchorEl={anchorEl}\n open={open}\n onClose={handleClose}\n anchorOrigin={anchorOrigin}\n transformOrigin={transformOrigin}\n slotProps={{ paper: { sx: paperSx } }}\n >\n <ActionMenuContext.Provider value={{ close: handleClose }}>\n {children}\n </ActionMenuContext.Provider>\n </Menu>\n </>\n );\n};\n\nexport interface ActionMenuItemProps\n extends Omit<MuiMenuItemProps, 'children' | 'onClick'> {\n /** Icono opcional a la izquierda. */\n icon?: ReactNode;\n /** Texto (o nodo) del item. */\n children: ReactNode;\n /** Handler de click. El menú se cierra automáticamente después. */\n onClick?: (event: MouseEvent<HTMLLIElement>) => void;\n}\n\n/**\n * Item del `ActionMenu`. Se cierra automáticamente al hacer click.\n * Acepta todos los props de `MenuItem` de MUI (disabled, selected, sx, …).\n */\nexport const ActionMenuItem = forwardRef<HTMLLIElement, ActionMenuItemProps>(\n function ActionMenuItem({ icon, children, onClick, ...rest }, ref) {\n const ctx = useContext(ActionMenuContext);\n\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n event.stopPropagation();\n onClick?.(event);\n ctx?.close();\n };\n\n return (\n <MenuItem ref={ref} onClick={handleClick} {...rest}>\n {icon && <ListItemIcon sx={{ minWidth: 32 }}>{icon}</ListItemIcon>}\n <ListItemText primary={children} />\n </MenuItem>\n );\n },\n);\n\nexport default ActionMenu;\n"],"names":["React","ActionMenuItem"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAM,oBAAoB,cAA6C,IAAI;AAEpE,MAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,EAAE,UAAU,UAAU,YAAY,QAAA;AAAA,EACjD,kBAAkB,EAAE,UAAU,OAAO,YAAY,QAAA;AAAA,EACjD;AAAA,EACA,WAAW;AACb,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAI,SAA6B,IAAI;AACjE,QAAM,OAAO,QAAQ,QAAQ;AAE7B,QAAM,cAAc,MAAM,YAAY,IAAI;AAG1C,QAAM,WAAW,CAAC,UAAmC;AACnD,QAAI,SAAU;AACd,UAAM,gBAAA;AACN,gBAAY,MAAM,aAAa;AAAA,EACjC;AAIA,QAAM,iBAAiB,UACrBA,eAAM,aAAa,SAA8B;AAAA,IAC/C,SAAS;AAAA,IACT;AAAA,EAAA,CACD,IAED,oBAAC,WAAQ,OAAO,gBAAgB,OAAK,MACnC,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,cAAY;AAAA,MAEZ,UAAA,oBAAC,cAAA,EAAa,UAAS,QAAA,CAAQ;AAAA,IAAA;AAAA,EAAA,GAEnC;AAGF,QAAM,UAAU;AAAA,IACd,EAAE,UAAU,IAAA;AAAA,IACZ,GAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,CAAC,MAAM,IAAI,CAAA;AAAA,EAAC;AAG5D,SACE,qBAAA,UAAA,EACG,UAAA;AAAA,IAAA;AAAA,IACD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,WAAW,EAAE,OAAO,EAAE,IAAI,UAAQ;AAAA,QAElC,UAAA,oBAAC,kBAAkB,UAAlB,EAA2B,OAAO,EAAE,OAAO,YAAA,GACzC,SAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;AAgBO,MAAM,iBAAiB;AAAA,EAC5B,SAASC,gBAAe,IAAsC,KAAK;AAA3C,iBAAE,QAAM,UAAU,YAAlB,IAA8B,iBAA9B,IAA8B,CAA5B,QAAM,YAAU;AACxC,UAAM,MAAM,WAAW,iBAAiB;AAExC,UAAM,cAAc,CAAC,UAAqC;AACxD,YAAM,gBAAA;AACN,yCAAU;AACV,iCAAK;AAAA,IACP;AAEA,gCACG,UAAA,+BAAS,KAAU,SAAS,eAAiB,OAA7C,EACE,UAAA;AAAA,MAAA,4BAAS,cAAA,EAAa,IAAI,EAAE,UAAU,GAAA,GAAO,UAAA,MAAK;AAAA,MACnD,oBAAC,cAAA,EAAa,SAAS,SAAA,CAAU;AAAA,IAAA,IACnC;AAAA,EAEJ;AACF;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ActionMenu-wNWkDZWh.cjs","sources":["../src/components/ActionMenu/ActionMenu.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useContext,\n useState,\n type ReactElement,\n type ReactNode,\n type MouseEvent,\n} from 'react';\nimport {\n IconButton,\n Menu,\n MenuItem,\n ListItemIcon,\n ListItemText,\n Tooltip,\n type MenuItemProps as MuiMenuItemProps,\n} from '@mui/material';\nimport MoreVertIcon from '@mui/icons-material/MoreVert';\nimport type { SxProps, Theme } from '@mui/material/styles';\n\nexport interface ActionMenuProps {\n /** Items del menú. Normalmente `<ActionMenuItem>` o `<Divider />`. */\n children: ReactNode;\n /**\n * Elemento disparador — cualquier componente clickeable (Button, Chip, IconButton…).\n * El ActionMenu le inyecta `onClick` automáticamente. Si se omite, se usa un\n * IconButton de tres puntos por defecto.\n */\n trigger?: ReactElement;\n /** Texto de tooltip sobre el trigger default. Default: \"Acciones\". */\n triggerTooltip?: string;\n /** Anchor origin del menu. Default: { vertical: 'bottom', horizontal: 'right' }. */\n anchorOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** Transform origin del menu. Default: { vertical: 'top', horizontal: 'right' }. */\n transformOrigin?: {\n vertical: 'top' | 'center' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n /** sx del Menu (Paper interno). */\n menuSx?: SxProps<Theme>;\n /** Deshabilita el trigger entero. */\n disabled?: boolean;\n}\n\ninterface ActionMenuContextValue {\n close: () => void;\n}\n\nconst ActionMenuContext = createContext<ActionMenuContextValue | null>(null);\n\nexport const ActionMenu: React.FC<ActionMenuProps> = ({\n children,\n trigger,\n triggerTooltip,\n anchorOrigin = { vertical: 'bottom', horizontal: 'right' },\n transformOrigin = { vertical: 'top', horizontal: 'right' },\n menuSx,\n disabled = false,\n}) => {\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const open = Boolean(anchorEl);\n\n const handleClose = () => setAnchorEl(null);\n\n // Abre el menú anclándolo al elemento que recibió el click.\n const openMenu = (event: MouseEvent<HTMLElement>) => {\n if (disabled) return;\n event.stopPropagation();\n setAnchorEl(event.currentTarget);\n };\n\n // Si el consumer pasó un trigger (ej. <Button>), le inyectamos onClick.\n // Si no, usamos el IconButton de tres puntos por defecto.\n const triggerElement = trigger ? (\n React.cloneElement(trigger as ReactElement<any>, {\n onClick: openMenu,\n disabled,\n })\n ) : (\n <Tooltip title={triggerTooltip} arrow>\n <IconButton\n size=\"small\"\n onClick={openMenu}\n disabled={disabled}\n aria-label={triggerTooltip}\n >\n <MoreVertIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n );\n\n const paperSx = [\n { minWidth: 180 },\n ...(Array.isArray(menuSx) ? menuSx : menuSx ? [menuSx] : []),\n ] as SxProps<Theme>;\n\n return (\n <>\n {triggerElement}\n <Menu\n anchorEl={anchorEl}\n open={open}\n onClose={handleClose}\n anchorOrigin={anchorOrigin}\n transformOrigin={transformOrigin}\n slotProps={{ paper: { sx: paperSx } }}\n >\n <ActionMenuContext.Provider value={{ close: handleClose }}>\n {children}\n </ActionMenuContext.Provider>\n </Menu>\n </>\n );\n};\n\nexport interface ActionMenuItemProps\n extends Omit<MuiMenuItemProps, 'children' | 'onClick'> {\n /** Icono opcional a la izquierda. */\n icon?: ReactNode;\n /** Texto (o nodo) del item. */\n children: ReactNode;\n /** Handler de click. El menú se cierra automáticamente después. */\n onClick?: (event: MouseEvent<HTMLLIElement>) => void;\n}\n\n/**\n * Item del `ActionMenu`. Se cierra automáticamente al hacer click.\n * Acepta todos los props de `MenuItem` de MUI (disabled, selected, sx, …).\n */\nexport const ActionMenuItem = forwardRef<HTMLLIElement, ActionMenuItemProps>(\n function ActionMenuItem({ icon, children, onClick, ...rest }, ref) {\n const ctx = useContext(ActionMenuContext);\n\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n event.stopPropagation();\n onClick?.(event);\n ctx?.close();\n };\n\n return (\n <MenuItem ref={ref} onClick={handleClick} {...rest}>\n {icon && <ListItemIcon sx={{ minWidth: 32 }}>{icon}</ListItemIcon>}\n <ListItemText primary={children} />\n </MenuItem>\n );\n },\n);\n\nexport default ActionMenu;\n"],"names":["createContext","useState","jsx","Tooltip","IconButton","jsxs","Fragment","Menu","forwardRef","ActionMenuItem","useContext","MenuItem","ListItemIcon","ListItemText"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAM,oBAAoBA,MAAAA,cAA6C,IAAI;AAEpE,MAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,EAAE,UAAU,UAAU,YAAY,QAAA;AAAA,EACjD,kBAAkB,EAAE,UAAU,OAAO,YAAY,QAAA;AAAA,EACjD;AAAA,EACA,WAAW;AACb,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,IAAIC,MAAAA,SAA6B,IAAI;AACjE,QAAM,OAAO,QAAQ,QAAQ;AAE7B,QAAM,cAAc,MAAM,YAAY,IAAI;AAG1C,QAAM,WAAW,CAAC,UAAmC;AACnD,QAAI,SAAU;AACd,UAAM,gBAAA;AACN,gBAAY,MAAM,aAAa;AAAA,EACjC;AAIA,QAAM,iBAAiB,UACrB,MAAM,aAAa,SAA8B;AAAA,IAC/C,SAAS;AAAA,IACT;AAAA,EAAA,CACD,IAEDC,2BAAAA,IAACC,SAAAA,WAAQ,OAAO,gBAAgB,OAAK,MACnC,UAAAD,2BAAAA;AAAAA,IAACE,SAAAA;AAAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,cAAY;AAAA,MAEZ,UAAAF,2BAAAA,IAAC,cAAA,EAAa,UAAS,QAAA,CAAQ;AAAA,IAAA;AAAA,EAAA,GAEnC;AAGF,QAAM,UAAU;AAAA,IACd,EAAE,UAAU,IAAA;AAAA,IACZ,GAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,CAAC,MAAM,IAAI,CAAA;AAAA,EAAC;AAG5D,SACEG,2BAAAA,KAAAC,qBAAA,EACG,UAAA;AAAA,IAAA;AAAA,IACDJ,2BAAAA;AAAAA,MAACK,SAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,WAAW,EAAE,OAAO,EAAE,IAAI,UAAQ;AAAA,QAElC,UAAAL,2BAAAA,IAAC,kBAAkB,UAAlB,EAA2B,OAAO,EAAE,OAAO,YAAA,GACzC,SAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;AAgBO,MAAM,iBAAiBM,MAAAA;AAAAA,EAC5B,SAASC,gBAAe,IAAsC,KAAK;AAA3C,iBAAE,QAAM,UAAU,YAAlB,IAA8B,iBAA9B,IAA8B,CAA5B,QAAM,YAAU;AACxC,UAAM,MAAMC,MAAAA,WAAW,iBAAiB;AAExC,UAAM,cAAc,CAAC,UAAqC;AACxD,YAAM,gBAAA;AACN,yCAAU;AACV,iCAAK;AAAA,IACP;AAEA,2CACGC,SAAAA,UAAA,+BAAS,KAAU,SAAS,eAAiB,OAA7C,EACE,UAAA;AAAA,MAAA,uCAASC,SAAAA,cAAA,EAAa,IAAI,EAAE,UAAU,GAAA,GAAO,UAAA,MAAK;AAAA,MACnDV,2BAAAA,IAACW,SAAAA,cAAA,EAAa,SAAS,SAAA,CAAU;AAAA,IAAA,IACnC;AAAA,EAEJ;AACF;;;"}
|
package/Select-BaY3zJhq.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Select-BaY3zJhq.js","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/_parts/SelectValue.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import { Avatar, Box, Chip, Typography } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n SelectOption,\n RenderChipLabel,\n ChipVariant,\n} from '../Select';\n\ninterface SelectValueProps<TValue extends SelectOption['value']> {\n selected: TValue | TValue[] | null | undefined;\n options: SelectOption[];\n multiple: boolean;\n placeholder?: string;\n maxChipsToShow: number;\n chipVariant: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n /** Solo relevante en modo multiple. Recibe el nuevo array de valores. */\n onDeleteChip?: (nextValues: TValue[]) => void;\n /** Array de valores actuales (para componer el nuevo array al borrar chips). */\n currentValues?: TValue[];\n}\n\n/**\n * Render del valor seleccionado del Select.\n * - single: texto (label) o lo que devuelva `renderChipLabel`.\n * - multiple: chips con delete. Trunca después de `maxChipsToShow` mostrando \"+N más\".\n * - empty: placeholder en color disabled.\n */\nexport function SelectValue<TValue extends SelectOption['value']>(\n props: SelectValueProps<TValue>,\n) {\n const {\n selected,\n options,\n multiple,\n placeholder,\n maxChipsToShow,\n chipVariant,\n renderChipLabel,\n onDeleteChip,\n currentValues,\n } = props;\n\n const isEmpty =\n !selected || (Array.isArray(selected) && selected.length === 0);\n\n if (isEmpty) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>{placeholder || ''}</Typography>\n );\n }\n\n if (!multiple) {\n const item = options.find((opt) => opt.value === selected);\n if (renderChipLabel && item) return <>{renderChipLabel(item)}</>;\n return <>{item?.label ?? String(selected)}</>;\n }\n\n const selectedValuesArray = selected as TValue[];\n const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);\n const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;\n\n const handleDelete = (chipValue: TValue) => {\n if (!onDeleteChip || !currentValues) return;\n onDeleteChip(currentValues.filter((v) => v !== chipValue));\n };\n\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {displayedChips.map((val) => {\n const item = options.find((o) => o.value === val);\n if (!item) return null;\n\n return (\n <Chip\n variant={chipVariant}\n color=\"primary\"\n size=\"small\"\n key={String(val)}\n label={renderChipLabel ? renderChipLabel(item) : item.label}\n avatar={item.img ? <Avatar src={item.img} /> : undefined}\n onDelete={() => handleDelete(val)}\n deleteIcon={<ClearIcon fontSize=\"small\" />}\n />\n );\n })}\n {hiddenChipsCount > 0 && (\n <Chip size=\"small\" variant={chipVariant} label={`+${hiddenChipsCount} más`} />\n )}\n </Box>\n );\n}\n\nexport default SelectValue;\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n TextField,\n InputAdornment,\n Box,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport SearchIcon from '@mui/icons-material/Search';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport { FIELD_BORDER_RADIUS } from '../../theme/tokens';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\nimport { SelectValue } from './_parts/SelectValue';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n/** Variante visual de los chips en modo `multiple`. */\nexport type ChipVariant = 'filled' | 'outlined';\n/** Render custom del label de cada chip/valor seleccionado. */\nexport type RenderChipLabel = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n /** Si `true`, muestra un buscador arriba del menú para filtrar opciones. */\n filterable?: boolean;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n multiple?: false;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple?: false;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\nexport interface MultipleSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple: true;\n value: TValue[];\n onChange: (val: TValue[]) => void;\n /** Máximo de chips visibles antes de truncar con \"+N más\". Default: 3. */\n maxChipsToShow?: number;\n /** Variante visual de los chips. Default: 'filled'. */\n chipVariant?: ChipVariant;\n /** Render custom del label de cada chip. */\n renderChipLabel?: RenderChipLabel;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> =\n | RHFSelectProps<TValue>\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = FIELD_BORDER_RADIUS,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n multiple = false,\n maxChipsToShow = 3,\n chipVariant = 'filled',\n renderChipLabel,\n filterable = false,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n multiple?: boolean;\n maxChipsToShow?: number;\n chipVariant?: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n filterable?: boolean;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n // Texto del buscador (modo `filterable`).\n const [searchText, setSearchText] = useState('');\n\n const filteredOptions = useMemo(() => {\n if (!filterable || !searchText.trim()) return options;\n const q = searchText.trim().toLowerCase();\n return options.filter((opt) => opt.label.toLowerCase().includes(q));\n }, [options, filterable, searchText]);\n\n const groupedOptions = useMemo(\n () => groupOptions(filteredOptions),\n [filteredOptions],\n );\n\n // Items del menú (grupos + opciones). El buscador se inyecta aparte.\n const buildMenuItems = (currentValue: TValue | TValue[] | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = Array.isArray(currentValue)\n ? currentValue.includes(opt.value as TValue)\n : currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | TValue[] | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue | TValue[]>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n onValuesChange?: (next: TValue[]) => void,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = multiple\n ? ((selectValue as TValue[] | null | undefined) ?? [])\n : normalizeSelectValue(selectValue as TValue | null | undefined);\n const isEmpty = multiple\n ? (normalizedValue as TValue[]).length === 0\n : isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue | TValue[]>\n multiple={multiple}\n value={normalizedValue as TValue | TValue[]}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => {\n setIsOpen(false);\n if (filterable) setSearchText('');\n }}\n renderValue={(selected) => (\n <SelectValue<TValue>\n selected={selected as TValue | TValue[]}\n options={options}\n multiple={multiple}\n placeholder={placeholder}\n maxChipsToShow={maxChipsToShow}\n chipVariant={chipVariant}\n renderChipLabel={renderChipLabel}\n currentValues={multiple ? (selected as TValue[]) : undefined}\n onDeleteChip={onValuesChange}\n />\n )}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {filterable && (\n <Box\n sx={{ px: 1.5, py: 1, position: 'sticky', top: 0, zIndex: 1, bgcolor: 'background.paper' }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <TextField\n size=\"small\"\n fullWidth\n autoFocus\n placeholder=\"Buscar...\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n </Box>\n )}\n {buildMenuItems(normalizedValue as TValue | TValue[] | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n (nextVals) => {\n field.onChange(nextVals);\n onValueChange?.(nextVals as unknown as TValue);\n },\n )\n }\n />\n );\n }\n\n // ── Controlled mode (single o multiple) ───────────────────────────────\n const { value, onChange } = props as\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n const handleChange = onChange as (val: TValue | TValue[]) => void;\n return renderSelect(\n value as TValue | TValue[],\n (e) => handleChange(e.target.value as TValue | TValue[]),\n undefined,\n undefined,\n undefined,\n undefined,\n (next) => (onChange as (val: TValue[]) => void)(next),\n );\n}\n\nexport default Select;\n"],"names":["_a","MuiSelect"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASO,MAAM,gBAAgB,CAC3B,cACA,kBAEA,iBAAiB,EAAE,cAAc,eAAe;ACN3C,MAAM,eAAe,CAC1B,YACmC;AACnC,QAAM,SAAyC,CAAA;AAC/C,UAAQ,QAAQ,CAAC,QAAQ;AACvB,UAAM,QAAQ,IAAI,SAAS;AAC3B,QAAI,CAAC,OAAO,KAAK,EAAG,QAAO,KAAK,IAAI,CAAA;AACpC,WAAO,KAAK,EAAE,KAAK,GAAG;AAAA,EACxB,CAAC;AACD,SAAO;AACT;AAMO,MAAM,uBAAuB,CAAI,UACrC,wBAAS;AAGL,MAAM,qBAAqB,CAAC,oBACjC,oBAAoB,MACpB,oBAAoB,QACpB,oBAAoB;ACPf,MAAM,uBAAuB,CAAC;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IAEC,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB;AAAA,IAEA,UAAA;AAAA,MAAA,oBAAC,cAAA,EAAa,IAAI,EAAE,UAAU,GAAA,GAC3B,UAAA,YAAY,oBAAC,WAAA,EAAU,OAAM,WAAU,UAAS,SAAQ,GAC3D;AAAA,MACC,eAAe,aAAa,MAAM,IAAI,OAAO;AAAA,IAAA;AAAA,EAAA;AAAA,EARzC,OAAO,OAAO,KAAK;AAS1B;ACTK,SAAS,YACd,OACA;;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AAEJ,QAAM,UACJ,CAAC,YAAa,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW;AAE/D,MAAI,SAAS;AACX,WACE,oBAAC,cAAW,IAAI,EAAE,OAAO,gBAAA,GAAoB,yBAAe,IAAG;AAAA,EAEnE;AAEA,MAAI,CAAC,UAAU;AACb,UAAM,OAAO,QAAQ,KAAK,CAAC,QAAQ,IAAI,UAAU,QAAQ;AACzD,QAAI,mBAAmB,KAAM,QAAO,oBAAA,UAAA,EAAG,UAAA,gBAAgB,IAAI,GAAE;AAC7D,WAAO,oBAAA,UAAA,EAAG,WAAA,kCAAM,UAAN,YAAe,OAAO,QAAQ,GAAE;AAAA,EAC5C;AAEA,QAAM,sBAAsB;AAC5B,QAAM,iBAAiB,oBAAoB,MAAM,GAAG,cAAc;AAClE,QAAM,mBAAmB,oBAAoB,SAAS;AAEtD,QAAM,eAAe,CAAC,cAAsB;AAC1C,QAAI,CAAC,gBAAgB,CAAC,cAAe;AACrC,iBAAa,cAAc,OAAO,CAAC,MAAM,MAAM,SAAS,CAAC;AAAA,EAC3D;AAEA,SACE,qBAAC,KAAA,EAAI,IAAI,EAAE,SAAS,QAAQ,UAAU,QAAQ,KAAK,IAAA,GAChD,UAAA;AAAA,IAAA,eAAe,IAAI,CAAC,QAAQ;AAC3B,YAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG;AAChD,UAAI,CAAC,KAAM,QAAO;AAElB,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS;AAAA,UACT,OAAM;AAAA,UACN,MAAK;AAAA,UAEL,OAAO,kBAAkB,gBAAgB,IAAI,IAAI,KAAK;AAAA,UACtD,QAAQ,KAAK,MAAM,oBAAC,UAAO,KAAK,KAAK,KAAK,IAAK;AAAA,UAC/C,UAAU,MAAM,aAAa,GAAG;AAAA,UAChC,YAAY,oBAAC,WAAA,EAAU,UAAS,QAAA,CAAQ;AAAA,QAAA;AAAA,QAJnC,OAAO,GAAG;AAAA,MAAA;AAAA,IAOrB,CAAC;AAAA,IACA,mBAAmB,KAClB,oBAAC,MAAA,EAAK,MAAK,SAAQ,SAAS,aAAa,OAAO,IAAI,gBAAgB,OAAA,CAAQ;AAAA,EAAA,GAEhF;AAEJ;ACsEO,SAAS,OAAO,QAAqB;AAC1C,SAAO;AACT;AACA,OAAO,cAAc;AAGd,SAAS,OAEd,OAA4B;AAC5B,QA+BI,YA9BF;AAAA;AAAA,IACA,UAAU,CAAA;AAAA,IACV;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA,WAAW;AAAA,IACX,QAAQ;AAAA,IACR;AAAA,IACA,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd;AAAA,IACA,aAAa;AAAA,IAGb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,UAAU;AAAA,MAER,IADC,iBACD,IADC;AAAA,IA7BH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAaF,QAAM,QAAQ,SAAA;AACd,QAAM,WAAW,cAAc,UAAU,QAAQ,KAAK;AAEtD,QAAM,YAAY,aAAa,SAAU,MAAiC,YAAY;AAGtF,QAAM,eAAwC,QAAQ,MAAM;;AAC1D,QAAI,SAAS,MAAM,QAAQ,MAAM,GAAG;AAClC,YAAM,QAAQ,SAAS,KAAK,QAAQ;AACpC,UAAI,eAAe,KAAK,OAAMA,MAAA,MAAM,SAAN,gBAAAA,IAAoB,iBAAgB,UAAU;AAC1E,eAAQ,MAAM,MAAsB;AAAA,MACtC;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,EAAE;AAE/C,QAAM,kBAAkB,QAAQ,MAAM;AACpC,QAAI,CAAC,cAAc,CAAC,WAAW,KAAA,EAAQ,QAAO;AAC9C,UAAM,IAAI,WAAW,KAAA,EAAO,YAAA;AAC5B,WAAO,QAAQ,OAAO,CAAC,QAAQ,IAAI,MAAM,YAAA,EAAc,SAAS,CAAC,CAAC;AAAA,EACpE,GAAG,CAAC,SAAS,YAAY,UAAU,CAAC;AAEpC,QAAM,iBAAiB;AAAA,IACrB,MAAM,aAAa,eAAe;AAAA,IAClC,CAAC,eAAe;AAAA,EAAA;AAIlB,QAAM,iBAAiB,CAAC,iBAAyC;AAC/D,UAAM,QAAqB,CAAA;AAC3B,WAAO,QAAQ,cAAc,EAAE,QAAQ,CAAC,CAAC,OAAO,IAAI,MAAM;AACxD,UAAI,UAAU,aAAa;AACzB,cAAM;AAAA,UACJ,oBAAC,eAAA,EAA0B,eAAa,MACrC,mBADiB,KAEpB;AAAA,QAAA;AAAA,MAEJ;AACA,WAAK,QAAQ,CAAC,QAAQ;AACpB,cAAM,WAAW,MAAM,QAAQ,YAAY,IACvC,aAAa,SAAS,IAAI,KAAe,IACzC,iBAAiB,IAAI;AACzB,cAAM;AAAA,UACJ,qBAAqB;AAAA,YACnB,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,UAAA,CACD;AAAA,QAAA;AAAA,MAEL,CAAC;AAAA,IACH,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,WAAW;AAAA,IACf,GAAI,WAAW,CAAC,QAAQ,IAAI,CAAC,cAAc,cAAc,aAAa,CAAC;AAAA,IACvE,GAAI,MAAM,QAAQ,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,IAAI,CAAA;AAAA,EAAC;AAI5C,QAAM,eAAe,CACnB,aACA,gBACA,QACA,UACA,UACA,eACA,mBACG;AACH,UAAM,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC;AACnC,UAAM,kBAAkB,wCAAiB;AAEzC,UAAM,eACJ,YAAY,WACR,oBAAC,aAAA,CAAA,CAAY,IACb,kBAAkB,aAChB,oBAAC,eAAA,EAAc,MAAA,CAAc,wBAC5B,eAAA,EAAc;AAEvB,UAAM,kBAAkB,WAClB,oCAA+C,CAAA,IACjD,qBAAqB,WAAwC;AACjE,UAAM,UAAU,WACX,gBAA6B,WAAW,IACzC,mBAAmB,eAAe;AAGtC,UAAM,eAAe,CAAC,WAAW,aAAa;AAE9C,UAAM,2BACJ,YAAY,aAAa,WAAW,CAAC,CAAC;AAExC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,IAAI;AAAA,QAEH,UAAA;AAAA,UAAA,SAAS,oBAAC,YAAA,EAAW,QAAQ,cAAe,UAAA,OAAM;AAAA,UACnD;AAAA,YAACC;AAAAA,YAAA;AAAA,cACC;AAAA,cACA,OAAO;AAAA,cACP,UAAU;AAAA,cACV,QAAQ,CAAC,MAAM;AACb,6BAAa,KAAK;AAClB,iDAAS;AAAA,cACX;AAAA,cACA,SAAS,MAAM,aAAa,IAAI;AAAA,cAChC,QAAQ,MAAM,UAAU,IAAI;AAAA,cAC5B,SAAS,MAAM;AACb,0BAAU,KAAK;AACf,oBAAI,0BAA0B,EAAE;AAAA,cAClC;AAAA,cACA,aAAa,CAAC,aACZ;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA,eAAe,WAAY,WAAwB;AAAA,kBACnD,cAAc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGlB,cAAc;AAAA,cACd,OAAO;AAAA,cACP;AAAA,cACA,WAAW;AAAA,gBACT,YAAY;AAAA,kBACV,OAAO,EAAE,WAAW,SAAA;AAAA,gBAAS;AAAA,cAC/B;AAAA,cAEF;AAAA,eACK,OApCN;AAAA,cAsCE,UAAA;AAAA,gBAAA,cACC;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,UAAU,UAAU,KAAK,GAAG,QAAQ,GAAG,SAAS,mBAAA;AAAA,oBACtE,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,oBAClB,WAAW,CAAC,MAAM,EAAE,gBAAA;AAAA,oBAEpB,UAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAK;AAAA,wBACL,WAAS;AAAA,wBACT,WAAS;AAAA,wBACT,aAAY;AAAA,wBACZ,OAAO;AAAA,wBACP,UAAU,CAAC,MAAM,cAAc,EAAE,OAAO,KAAK;AAAA,wBAC7C,WAAW;AAAA,0BACT,OAAO;AAAA,4BACL,oCACG,gBAAA,EAAe,UAAS,SACvB,UAAA,oBAAC,YAAA,EAAW,UAAS,QAAA,CAAQ,EAAA,CAC/B;AAAA,0BAAA;AAAA,wBAEJ;AAAA,sBACF;AAAA,oBAAA;AAAA,kBACF;AAAA,gBAAA;AAAA,gBAGH,eAAe,eAAyC;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAE1D,mBAAmB,oBAAC,gBAAA,EAAgB,UAAA,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3D;AAGA,MAAI,WAAW;AACb,UAAM,EAAE,MAAM,SAAS,YAAY,kBAAkB;AACrD,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA,QAAQ,CAAC,EAAE,OAAO,YAAY,EAAE,OAAO,WAAA,EAAW;;AAChD;AAAA,aACED,MAAA,MAAM,UAAN,OAAAA,MAAe;AAAA,YACf,CAAC,MAAM;AACL,oBAAM,OAAO,EAAE,OAAO;AACtB,oBAAM,SAAS,IAAI;AACnB,6DAAgB;AAAA,YAClB;AAAA,YACA,MAAM;AAAA,YACN,MAAM;AAAA,YACN,CAAC,CAAC;AAAA,YACF,yCAAY;AAAA,YACZ,CAAC,aAAa;AACZ,oBAAM,SAAS,QAAQ;AACvB,6DAAgB;AAAA,YAClB;AAAA,UAAA;AAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAIR;AAGA,QAAM,EAAE,OAAO,SAAA,IAAa;AAG5B,QAAM,eAAe;AACrB,SAAO;AAAA,IACL;AAAA,IACA,CAAC,MAAM,aAAa,EAAE,OAAO,KAA0B;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC,SAAU,SAAqC,IAAI;AAAA,EAAA;AAExD;"}
|
package/Select-WpHNCHHz.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Select-WpHNCHHz.cjs","sources":["../src/components/Select/Select.sx.ts","../src/components/Select/Select.helpers.ts","../src/components/Select/_parts/SelectMenuItem.tsx","../src/components/Select/_parts/SelectValue.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import type { SelectProps as MuiSelectProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Select';\n\n/**\n * Builder de sx para el Select. Usa el builder compartido\n * `buildFormFieldSx`. El Select no necesita overrides específicos.\n */\nexport const buildSelectSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): MuiSelectProps['sx'] =>\n buildFormFieldSx({ borderRadius, labelPosition }) as MuiSelectProps['sx'];\n","import type { SelectOption } from './Select';\n\n/**\n * Agrupa opciones por la propiedad `group`. Las opciones sin group caen\n * bajo la key especial `__default`. Devuelve un Record para iterar en orden\n * de inserción con Object.entries.\n */\nexport const groupOptions = (\n options: SelectOption[],\n): Record<string, SelectOption[]> => {\n const groups: Record<string, SelectOption[]> = {};\n options.forEach((opt) => {\n const group = opt.group || '__default';\n if (!groups[group]) groups[group] = [];\n groups[group].push(opt);\n });\n return groups;\n};\n\n/**\n * Normaliza el valor single al shape que espera MUI Select: string vacío si\n * el valor es `null`/`undefined`.\n */\nexport const normalizeSelectValue = <T>(value: T | null | undefined): T | '' =>\n (value ?? '') as T | '';\n\n/** `true` si el valor está vacío (para shrink del label + placeholder). */\nexport const isSelectValueEmpty = (normalizedValue: unknown): boolean =>\n normalizedValue === '' ||\n normalizedValue === null ||\n normalizedValue === undefined;\n","import React from 'react';\nimport { ListItemIcon, MenuItem } from '@mui/material';\nimport CheckIcon from '@mui/icons-material/Check';\n\nimport type { SelectOption, RenderOptionItem } from '../Select';\n\ninterface RenderSelectMenuItemArgs {\n option: SelectOption;\n selected: boolean;\n customRender?: RenderOptionItem | null;\n}\n\n/**\n * Render helper (no componente) que devuelve un <MenuItem> listo para\n * colocarse como hijo directo del <MuiSelect>. Se implementa como función\n * y no como componente porque MUI Select inspecciona `props.value` de sus\n * children para resolver la selección, y envolverlo en un componente extra\n * rompe esa detección.\n *\n * Incluye el icono de check a la izquierda cuando `selected` es true. Si el\n * consumer pasó un `<Option>{(opt) => ...}</Option>`, usa ese render para el\n * contenido principal; de lo contrario muestra `option.label`.\n */\nexport const renderSelectMenuItem = ({\n option,\n selected,\n customRender,\n}: RenderSelectMenuItemArgs): React.ReactElement => (\n <MenuItem\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n selected={selected}\n >\n <ListItemIcon sx={{ minWidth: 32 }}>\n {selected && <CheckIcon color=\"success\" fontSize=\"small\" />}\n </ListItemIcon>\n {customRender ? customRender(option) : option.label}\n </MenuItem>\n);\n","import { Avatar, Box, Chip, Typography } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n SelectOption,\n RenderChipLabel,\n ChipVariant,\n} from '../Select';\n\ninterface SelectValueProps<TValue extends SelectOption['value']> {\n selected: TValue | TValue[] | null | undefined;\n options: SelectOption[];\n multiple: boolean;\n placeholder?: string;\n maxChipsToShow: number;\n chipVariant: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n /** Solo relevante en modo multiple. Recibe el nuevo array de valores. */\n onDeleteChip?: (nextValues: TValue[]) => void;\n /** Array de valores actuales (para componer el nuevo array al borrar chips). */\n currentValues?: TValue[];\n}\n\n/**\n * Render del valor seleccionado del Select.\n * - single: texto (label) o lo que devuelva `renderChipLabel`.\n * - multiple: chips con delete. Trunca después de `maxChipsToShow` mostrando \"+N más\".\n * - empty: placeholder en color disabled.\n */\nexport function SelectValue<TValue extends SelectOption['value']>(\n props: SelectValueProps<TValue>,\n) {\n const {\n selected,\n options,\n multiple,\n placeholder,\n maxChipsToShow,\n chipVariant,\n renderChipLabel,\n onDeleteChip,\n currentValues,\n } = props;\n\n const isEmpty =\n !selected || (Array.isArray(selected) && selected.length === 0);\n\n if (isEmpty) {\n return (\n <Typography sx={{ color: 'text.disabled' }}>{placeholder || ''}</Typography>\n );\n }\n\n if (!multiple) {\n const item = options.find((opt) => opt.value === selected);\n if (renderChipLabel && item) return <>{renderChipLabel(item)}</>;\n return <>{item?.label ?? String(selected)}</>;\n }\n\n const selectedValuesArray = selected as TValue[];\n const displayedChips = selectedValuesArray.slice(0, maxChipsToShow);\n const hiddenChipsCount = selectedValuesArray.length - maxChipsToShow;\n\n const handleDelete = (chipValue: TValue) => {\n if (!onDeleteChip || !currentValues) return;\n onDeleteChip(currentValues.filter((v) => v !== chipValue));\n };\n\n return (\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>\n {displayedChips.map((val) => {\n const item = options.find((o) => o.value === val);\n if (!item) return null;\n\n return (\n <Chip\n variant={chipVariant}\n color=\"primary\"\n size=\"small\"\n key={String(val)}\n label={renderChipLabel ? renderChipLabel(item) : item.label}\n avatar={item.img ? <Avatar src={item.img} /> : undefined}\n onDelete={() => handleDelete(val)}\n deleteIcon={<ClearIcon fontSize=\"small\" />}\n />\n );\n })}\n {hiddenChipsCount > 0 && (\n <Chip size=\"small\" variant={chipVariant} label={`+${hiddenChipsCount} más`} />\n )}\n </Box>\n );\n}\n\nexport default SelectValue;\n","import {\n Children,\n isValidElement,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n FilledInput,\n FormControl,\n FormHelperText,\n InputLabel,\n ListSubheader,\n OutlinedInput,\n Select as MuiSelect,\n TextField,\n InputAdornment,\n Box,\n type SelectChangeEvent,\n type SelectProps as MuiSelectProps,\n} from '@mui/material';\nimport SearchIcon from '@mui/icons-material/Search';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildSelectSx } from './Select.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport { FIELD_BORDER_RADIUS } from '../../theme/tokens';\nimport {\n groupOptions,\n isSelectValueEmpty,\n normalizeSelectValue,\n} from './Select.helpers';\nimport { renderSelectMenuItem } from './_parts/SelectMenuItem';\nimport { SelectValue } from './_parts/SelectValue';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type SelectSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\n\n/** Variante visual de los chips en modo `multiple`. */\nexport type ChipVariant = 'filled' | 'outlined';\n/** Render custom del label de cada chip/valor seleccionado. */\nexport type RenderChipLabel = (item: SelectOption) => ReactNode;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport interface OptionProps {\n children: RenderOptionItem;\n}\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport interface BaseSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> {\n label?: string;\n options?: SelectOption[];\n defaultValue?: TValue;\n size?: SelectSize;\n placeholder?: string;\n children?: ReactElement<{ children: RenderOptionItem }>;\n maxHeight?: number | string;\n maxWidth?: number | string;\n /** Si `true`, muestra un buscador arriba del menú para filtrar opciones. */\n filterable?: boolean;\n disabled?: boolean;\n error?: boolean;\n helperText?: string;\n /** Border radius del input (px o string CSS). Default: 10 */\n borderRadius?: number | string;\n /**\n * Posición del label.\n * - \"outside\" (default): label arriba del input, sin animación.\n * - \"floating\": label clásico de MUI (flota dentro del notched outline).\n */\n labelPosition?: LabelPosition;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Select`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** MUI input variant. Default: 'outlined'. */\n variant?: 'outlined' | 'filled';\n sx?: MuiSelectProps['sx'];\n className?: string;\n}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name: string;\n // `any` plano (no `Control<any>`): RHF tipa `Control<T>` con generics en\n // posiciones tanto contravariantes como covariantes (ej. `_subjects.state`).\n // Cuando el componente tiene generics propios (como `TValue` acá), TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda.\n // El `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del Select.\n control: any;\n validation?: RegisterOptions;\n /**\n * Side-effect que corre después de que RHF actualiza el form state.\n * Útil para cascadas entre campos (ej. reset de municipio al cambiar\n * departamento). NO reemplaza al handler de RHF.\n */\n onValueChange?: (value: TValue) => void;\n multiple?: false;\n value?: never;\n onChange?: never;\n}\n\nexport interface StandardSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple?: false;\n value: TValue;\n onChange: (val: TValue) => void;\n}\n\nexport interface MultipleSelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseSelectProps<TValue> {\n name?: string;\n control?: never;\n validation?: never;\n multiple: true;\n value: TValue[];\n onChange: (val: TValue[]) => void;\n /** Máximo de chips visibles antes de truncar con \"+N más\". Default: 3. */\n maxChipsToShow?: number;\n /** Variante visual de los chips. Default: 'filled'. */\n chipVariant?: ChipVariant;\n /** Render custom del label de cada chip. */\n renderChipLabel?: RenderChipLabel;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type SelectProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> =\n | RHFSelectProps<TValue>\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n\n// ── Sub-componente declarativo <Option> ──────────────────────────────────\nexport function Option(_props: OptionProps) {\n return null;\n}\nOption.displayName = 'Option';\n\n// ── Componente ───────────────────────────────────────────────────────────\nexport function Select<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: SelectProps<TValue>) {\n const {\n label,\n options = [],\n defaultValue,\n size = 'small',\n placeholder,\n children,\n maxHeight = 300,\n maxWidth,\n disabled = false,\n error = false,\n helperText,\n borderRadius = FIELD_BORDER_RADIUS,\n labelPosition = 'outside',\n preset,\n variant = 'outlined',\n sx,\n className,\n multiple = false,\n maxChipsToShow = 3,\n chipVariant = 'filled',\n renderChipLabel,\n filterable = false,\n // Separamos estos aunque no se usen directamente acá — evita que lleguen\n // al DOM del MuiSelect via `{...rest}` y generen warnings de React.\n name: _nameIgnored,\n control: _controlIgnored,\n validation: _validationIgnored,\n value: _valueIgnored,\n onChange: _onChangeIgnored,\n ...rest\n } = props as StandardSelectProps<TValue> & {\n name?: string;\n control?: Control<any>;\n validation?: RegisterOptions;\n multiple?: boolean;\n maxChipsToShow?: number;\n chipVariant?: ChipVariant;\n renderChipLabel?: RenderChipLabel;\n filterable?: boolean;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Select', preset, theme);\n\n const isRHFMode = 'control' in props && (props as RHFSelectProps<TValue>).control !== undefined;\n\n // Custom render opcional vía <Option>{item => ...}</Option>\n const customRender: RenderOptionItem | null = useMemo(() => {\n if (Children.count(children) === 1) {\n const child = Children.only(children);\n if (isValidElement(child) && (child.type as any)?.displayName === 'Option') {\n return (child.props as OptionProps).children;\n }\n }\n return null;\n }, [children]);\n\n // Focus/open tracking para el comportamiento del label \"outside\".\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n // Texto del buscador (modo `filterable`).\n const [searchText, setSearchText] = useState('');\n\n const filteredOptions = useMemo(() => {\n if (!filterable || !searchText.trim()) return options;\n const q = searchText.trim().toLowerCase();\n return options.filter((opt) => opt.label.toLowerCase().includes(q));\n }, [options, filterable, searchText]);\n\n const groupedOptions = useMemo(\n () => groupOptions(filteredOptions),\n [filteredOptions],\n );\n\n // Items del menú (grupos + opciones). El buscador se inyecta aparte.\n const buildMenuItems = (currentValue: TValue | TValue[] | '') => {\n const items: ReactNode[] = [];\n Object.entries(groupedOptions).forEach(([group, opts]) => {\n if (group !== '__default') {\n items.push(\n <ListSubheader key={group} disableSticky>\n {group}\n </ListSubheader>,\n );\n }\n opts.forEach((opt) => {\n const selected = Array.isArray(currentValue)\n ? currentValue.includes(opt.value as TValue)\n : currentValue === opt.value;\n items.push(\n renderSelectMenuItem({\n option: opt,\n selected,\n customRender,\n }),\n );\n });\n });\n return items;\n };\n\n const mergedSx = [\n ...(presetSx ? [presetSx] : [buildSelectSx(borderRadius, labelPosition)]),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n // Render base (común a RHF y controlled)\n const renderSelect = (\n selectValue: TValue | TValue[] | null | undefined,\n selectOnChange: (event: SelectChangeEvent<TValue | TValue[]>) => void,\n onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void,\n inputRef?: React.Ref<HTMLInputElement>,\n rhfError?: boolean,\n rhfHelperText?: string,\n onValuesChange?: (next: TValue[]) => void,\n ) => {\n const finalError = !!rhfError || !!error;\n const finalHelperText = rhfHelperText ?? helperText;\n\n const inputElement =\n variant === 'filled'\n ? <FilledInput />\n : labelPosition === 'floating'\n ? <OutlinedInput label={label} />\n : <OutlinedInput />;\n\n const normalizedValue = multiple\n ? ((selectValue as TValue[] | null | undefined) ?? [])\n : normalizeSelectValue(selectValue as TValue | null | undefined);\n const isEmpty = multiple\n ? (normalizedValue as TValue[]).length === 0\n : isSelectValueEmpty(normalizedValue);\n\n // Shrink cuando hay valor, foco, o dropdown abierto.\n const shouldShrink = !isEmpty || isFocused || isOpen;\n // Placeholder solo cuando el label ya subió.\n const shouldDisplayPlaceholder =\n isEmpty && (isFocused || isOpen) && !!placeholder;\n\n return (\n <FormControl\n fullWidth\n size={size}\n variant={variant}\n error={finalError}\n disabled={disabled}\n className={className}\n sx={mergedSx}\n >\n {label && <InputLabel shrink={shouldShrink}>{label}</InputLabel>}\n <MuiSelect<TValue | TValue[]>\n multiple={multiple}\n value={normalizedValue as TValue | TValue[]}\n onChange={selectOnChange}\n onBlur={(e) => {\n setIsFocused(false);\n onBlur?.(e);\n }}\n onFocus={() => setIsFocused(true)}\n onOpen={() => setIsOpen(true)}\n onClose={() => {\n setIsOpen(false);\n if (filterable) setSearchText('');\n }}\n renderValue={(selected) => (\n <SelectValue<TValue>\n selected={selected as TValue | TValue[]}\n options={options}\n multiple={multiple}\n placeholder={placeholder}\n maxChipsToShow={maxChipsToShow}\n chipVariant={chipVariant}\n renderChipLabel={renderChipLabel}\n currentValues={multiple ? (selected as TValue[]) : undefined}\n onDeleteChip={onValuesChange}\n />\n )}\n displayEmpty={shouldDisplayPlaceholder}\n input={inputElement}\n disabled={disabled}\n MenuProps={{\n PaperProps: {\n style: { maxHeight, maxWidth },\n },\n }}\n inputRef={inputRef}\n {...(rest as any)}\n >\n {filterable && (\n <Box\n sx={{ px: 1.5, py: 1, position: 'sticky', top: 0, zIndex: 1, bgcolor: 'background.paper' }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <TextField\n size=\"small\"\n fullWidth\n autoFocus\n placeholder=\"Buscar...\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n },\n }}\n />\n </Box>\n )}\n {buildMenuItems(normalizedValue as TValue | TValue[] | '')}\n </MuiSelect>\n {finalHelperText && <FormHelperText>{finalHelperText}</FormHelperText>}\n </FormControl>\n );\n };\n\n // ── RHF mode ──────────────────────────────────────────────────────────\n if (isRHFMode) {\n const { name, control, validation, onValueChange } = props as RHFSelectProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n defaultValue={defaultValue}\n render={({ field, fieldState: { error: fieldError } }) =>\n renderSelect(\n field.value ?? null,\n (e) => {\n const next = e.target.value as TValue;\n field.onChange(next);\n onValueChange?.(next);\n },\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n (nextVals) => {\n field.onChange(nextVals);\n onValueChange?.(nextVals as unknown as TValue);\n },\n )\n }\n />\n );\n }\n\n // ── Controlled mode (single o multiple) ───────────────────────────────\n const { value, onChange } = props as\n | StandardSelectProps<TValue>\n | MultipleSelectProps<TValue>;\n const handleChange = onChange as (val: TValue | TValue[]) => void;\n return renderSelect(\n value as TValue | TValue[],\n (e) => handleChange(e.target.value as TValue | TValue[]),\n undefined,\n undefined,\n undefined,\n undefined,\n (next) => (onChange as (val: TValue[]) => void)(next),\n );\n}\n\nexport default Select;\n"],"names":["buildFormFieldSx","jsxs","MenuItem","jsx","ListItemIcon","Typography","Fragment","Box","Chip","Avatar","FIELD_BORDER_RADIUS","useTheme","resolvePreset","useMemo","Children","isValidElement","_a","useState","ListSubheader","FilledInput","OutlinedInput","FormControl","InputLabel","MuiSelect","TextField","InputAdornment","FormHelperText","Controller"],"mappings":"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"}
|