@soyfri/shared-library 2.0.0-beta.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Button-C17mExpd.cjs.map +1 -1
- package/Button-UkkP-bNw.js.map +1 -1
- package/README.md +182 -150
- package/components/ActionMenu/ActionMenu.cjs +52 -52
- package/components/ActionMenu/ActionMenu.cjs.map +1 -1
- package/components/ActionMenu/ActionMenu.d.ts +20 -36
- package/components/ActionMenu/ActionMenu.js +55 -55
- package/components/ActionMenu/ActionMenu.js.map +1 -1
- package/components/ActionMenu/index.d.ts +2 -2
- package/components/AppBar/AppBar.cjs +2 -219
- package/components/AppBar/AppBar.cjs.map +1 -1
- package/components/AppBar/AppBar.d.ts +6 -6
- package/components/AppBar/AppBar.js +5 -222
- package/components/AppBar/AppBar.js.map +1 -1
- package/components/AppBar/index.d.ts +0 -6
- package/components/Autocomplete/Autocomplete.cjs +93 -94
- package/components/Autocomplete/Autocomplete.cjs.map +1 -1
- package/components/Autocomplete/Autocomplete.d.ts +29 -26
- package/components/Autocomplete/Autocomplete.definitions.d.ts +2 -1
- package/components/Autocomplete/Autocomplete.helpers.d.ts +12 -8
- package/components/Autocomplete/Autocomplete.js +94 -95
- package/components/Autocomplete/Autocomplete.js.map +1 -1
- package/components/Autocomplete/_parts/AutocompleteChips.d.ts +7 -6
- package/components/Autocomplete/_parts/AutocompleteOption.d.ts +10 -13
- package/components/Autocomplete/index.d.ts +1 -1
- package/components/Avatar/Avatar.cjs +17 -18
- package/components/Avatar/Avatar.cjs.map +1 -1
- package/components/Avatar/Avatar.js +17 -18
- package/components/Avatar/Avatar.js.map +1 -1
- package/components/Avatar/index.d.ts +1 -0
- package/components/Button/Button.d.ts +5 -5
- package/components/Button/index.d.ts +1 -0
- package/components/Card/Card.cjs +3 -92
- package/components/Card/Card.cjs.map +1 -1
- package/components/Card/Card.d.ts +3 -50
- package/components/Card/Card.js +5 -94
- package/components/Card/Card.js.map +1 -1
- package/components/Card/Card.sx.d.ts +3 -6
- package/components/Card/index.d.ts +1 -1
- package/components/Checkbox/Checkbox.cjs +189 -0
- package/components/Checkbox/Checkbox.cjs.map +1 -0
- package/components/Checkbox/Checkbox.d.ts +55 -0
- package/components/Checkbox/Checkbox.js +189 -0
- package/components/Checkbox/Checkbox.js.map +1 -0
- package/components/Checkbox/Checkbox.sx.d.ts +13 -0
- package/components/Checkbox/index.d.ts +2 -0
- package/components/Checkbox.d.ts +6 -0
- package/components/Chip/Chip.cjs +2 -1
- package/components/Chip/Chip.cjs.map +1 -1
- package/components/Chip/Chip.js +2 -1
- package/components/Chip/Chip.js.map +1 -1
- package/components/Chip/index.d.ts +2 -1
- package/components/Chip.d.ts +4 -0
- package/components/DatePicker/DatePicker.cjs +40 -63
- package/components/DatePicker/DatePicker.cjs.map +1 -1
- package/components/DatePicker/DatePicker.d.ts +1 -13
- package/components/DatePicker/DatePicker.js +36 -59
- package/components/DatePicker/DatePicker.js.map +1 -1
- package/components/DatePicker/index.d.ts +1 -1
- package/components/DateTimePicker/DateTimePicker.cjs +58 -82
- package/components/DateTimePicker/DateTimePicker.cjs.map +1 -1
- package/components/DateTimePicker/DateTimePicker.d.ts +9 -17
- package/components/DateTimePicker/DateTimePicker.definitions.d.ts +2 -0
- package/components/DateTimePicker/DateTimePicker.helpers.d.ts +4 -2
- package/components/DateTimePicker/DateTimePicker.js +54 -78
- package/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/components/DateTimePicker/index.d.ts +1 -1
- package/components/Drawer/Drawer.cjs +12 -6
- package/components/Drawer/Drawer.cjs.map +1 -1
- package/components/Drawer/Drawer.d.ts +3 -1
- package/components/Drawer/Drawer.js +13 -7
- package/components/Drawer/Drawer.js.map +1 -1
- package/components/Drawer/DrawerItem.d.ts +6 -1
- package/components/Gallery/Gallery.cjs +154 -79
- package/components/Gallery/Gallery.cjs.map +1 -1
- package/components/Gallery/Gallery.d.ts +25 -9
- package/components/Gallery/Gallery.js +154 -79
- package/components/Gallery/Gallery.js.map +1 -1
- package/components/Gallery/GalleryLightbox.d.ts +6 -10
- package/components/Gallery/GalleryMain.d.ts +3 -7
- package/components/Gallery/GalleryThumbnails.d.ts +7 -11
- package/components/Gallery/index.d.ts +2 -1
- package/components/Gallery.d.ts +4 -0
- package/components/Icon/Icon.cjs +6 -8
- package/components/Icon/Icon.cjs.map +1 -1
- package/components/Icon/Icon.d.ts +11 -17
- package/components/Icon/Icon.js +6 -8
- package/components/Icon/Icon.js.map +1 -1
- package/components/Icon/index.d.ts +2 -1
- package/components/Icon.d.ts +4 -0
- package/components/Input/Input.cjs +26 -13
- package/components/Input/Input.cjs.map +1 -1
- package/components/Input/Input.d.ts +9 -2
- package/components/Input/Input.helpers.d.ts +3 -3
- package/components/Input/Input.js +23 -10
- package/components/Input/Input.js.map +1 -1
- package/components/Input/index.d.ts +1 -1
- package/components/InputGroup/InputGroup.cjs +23 -22
- package/components/InputGroup/InputGroup.cjs.map +1 -1
- package/components/InputGroup/InputGroup.d.ts +4 -4
- package/components/InputGroup/InputGroup.js +22 -21
- package/components/InputGroup/InputGroup.js.map +1 -1
- package/components/InputGroup/index.d.ts +2 -1
- package/components/InputGroup.d.ts +4 -0
- package/components/Modal/Modal.cjs +127 -98
- package/components/Modal/Modal.cjs.map +1 -1
- package/components/Modal/Modal.d.ts +20 -5
- package/components/Modal/Modal.js +130 -101
- package/components/Modal/Modal.js.map +1 -1
- package/components/Modal/ModalBody.d.ts +6 -1
- package/components/Modal/ModalFooter.d.ts +4 -4
- package/components/Modal/ModalHeader.d.ts +6 -1
- package/components/Modal/index.d.ts +4 -2
- package/components/Modal.d.ts +4 -0
- package/components/RadioGroup/RadioGroup.cjs +9 -7
- package/components/RadioGroup/RadioGroup.cjs.map +1 -1
- package/components/RadioGroup/RadioGroup.d.ts +9 -3
- package/components/RadioGroup/RadioGroup.js +9 -7
- package/components/RadioGroup/RadioGroup.js.map +1 -1
- package/components/RadioGroup/index.d.ts +1 -1
- package/components/Select/Select.cjs +129 -264
- package/components/Select/Select.cjs.map +1 -1
- package/components/Select/Select.d.ts +35 -20
- package/components/Select/Select.helpers.d.ts +6 -19
- package/components/Select/Select.js +134 -269
- package/components/Select/Select.js.map +1 -1
- package/components/Select/index.d.ts +1 -1
- package/components/Stat/Stat.cjs +2 -2
- package/components/Stat/Stat.cjs.map +1 -1
- package/components/Stat/Stat.js +2 -2
- package/components/Stat/Stat.js.map +1 -1
- package/components/Stat/index.d.ts +2 -1
- package/components/Stat.d.ts +4 -0
- package/components/StatusMessage/StatusMessage.cjs +84 -55
- package/components/StatusMessage/StatusMessage.cjs.map +1 -1
- package/components/StatusMessage/StatusMessage.d.ts +20 -36
- package/components/StatusMessage/StatusMessage.js +86 -57
- package/components/StatusMessage/StatusMessage.js.map +1 -1
- package/components/StatusMessage/StatusMessageContext.d.ts +16 -0
- package/components/StatusMessage/index.d.ts +4 -1
- package/components/StatusMessage.d.ts +4 -0
- package/components/Stepper/Stepper.cjs +289 -55
- package/components/Stepper/Stepper.cjs.map +1 -1
- package/components/Stepper/Stepper.d.ts +9 -20
- package/components/Stepper/Stepper.js +291 -57
- package/components/Stepper/Stepper.js.map +1 -1
- package/{hooks/Wizard/WizardContext.d.ts → components/Stepper/StepperContext.d.ts} +29 -23
- package/components/Stepper/_hooks/useHorizontalScroll.d.ts +19 -0
- package/components/Stepper/_parts/StepperScrollArrow.d.ts +19 -0
- package/components/Stepper/index.d.ts +6 -2
- package/components/Stepper.d.ts +4 -0
- package/components/Switch/Switch.cjs +5 -2
- package/components/Switch/Switch.cjs.map +1 -1
- package/components/Switch/Switch.d.ts +7 -2
- package/components/Switch/Switch.js +5 -2
- package/components/Switch/Switch.js.map +1 -1
- package/components/Tabs/Tabs.cjs +45 -29
- package/components/Tabs/Tabs.cjs.map +1 -1
- package/components/Tabs/Tabs.d.ts +21 -16
- package/components/Tabs/Tabs.js +46 -30
- package/components/Tabs/Tabs.js.map +1 -1
- package/components/Tabs/index.d.ts +4 -2
- package/components/Tabs.d.ts +4 -0
- package/components/Timeline/Timeline.cjs +3 -2
- package/components/Timeline/Timeline.cjs.map +1 -1
- package/components/Timeline/Timeline.d.ts +4 -8
- package/components/Timeline/Timeline.js +3 -2
- package/components/Timeline/Timeline.js.map +1 -1
- package/components/Timeline/index.d.ts +4 -2
- package/components/Timeline.d.ts +4 -0
- package/components/_shared/mergeSx.d.ts +7 -0
- package/{formField.sx-DfVbMe0V.js → formField.sx-8_QRnKxv.js} +2 -11
- package/formField.sx-8_QRnKxv.js.map +1 -0
- package/{formField.sx-CQ1mbk9M.cjs → formField.sx-BAX7KwMR.cjs} +10 -19
- package/formField.sx-BAX7KwMR.cjs.map +1 -0
- package/index.cjs +31 -2
- package/index.cjs.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +16 -2
- package/index.js.map +1 -1
- package/mergeSx-BXoNZjB_.js +10 -0
- package/mergeSx-BXoNZjB_.js.map +1 -0
- package/mergeSx-Dbccoo_H.cjs +9 -0
- package/mergeSx-Dbccoo_H.cjs.map +1 -0
- package/mui.d.ts +3 -2
- package/package.json +6 -16
- package/theme/componentStyles.d.ts +1 -1
- package/tokens-BRrcP_p_.js +21 -0
- package/tokens-BRrcP_p_.js.map +1 -0
- package/tokens-jaWWNk39.cjs +20 -0
- package/tokens-jaWWNk39.cjs.map +1 -0
- package/utils/index.d.ts +2 -0
- package/{components/ScrollTopButton → utils}/scrollToTop.d.ts +6 -7
- package/components/AppBar/AppBarBrand.d.ts +0 -31
- package/components/AppBar/AppBarUserMenu.d.ts +0 -65
- package/components/Autocomplete/Autocomplete.types.d.ts +0 -1
- package/components/DatePicker/DatePicker.types.d.ts +0 -1
- package/components/DateTimePicker/DateTimePicker.types.d.ts +0 -1
- package/components/Input/Input.types.d.ts +0 -1
- package/components/PageLoader/PageLoader.cjs +0 -61
- package/components/PageLoader/PageLoader.cjs.map +0 -1
- package/components/PageLoader/PageLoader.d.ts +0 -38
- package/components/PageLoader/PageLoader.js +0 -61
- package/components/PageLoader/PageLoader.js.map +0 -1
- package/components/PageLoader/index.d.ts +0 -2
- package/components/PageLoader.d.ts +0 -6
- package/components/RadioGroup/RadioGroup.types.d.ts +0 -1
- package/components/ScrollTopButton/ScrollTopButton.cjs +0 -79
- package/components/ScrollTopButton/ScrollTopButton.cjs.map +0 -1
- package/components/ScrollTopButton/ScrollTopButton.d.ts +0 -48
- package/components/ScrollTopButton/ScrollTopButton.js +0 -79
- package/components/ScrollTopButton/ScrollTopButton.js.map +0 -1
- package/components/ScrollTopButton/index.d.ts +0 -4
- package/components/ScrollTopButton.d.ts +0 -6
- package/components/Select/Select.definitions.d.ts +0 -17
- package/components/Select/Select.types.d.ts +0 -1
- package/components/Select/_parts/SelectSearchHeader.d.ts +0 -15
- package/components/Select/_parts/SelectValue.d.ts +0 -22
- package/formField.sx-CQ1mbk9M.cjs.map +0 -1
- package/formField.sx-DfVbMe0V.js.map +0 -1
- package/hooks/Wizard/Wizard.cjs +0 -7
- package/hooks/Wizard/Wizard.cjs.map +0 -1
- package/hooks/Wizard/Wizard.js +0 -7
- package/hooks/Wizard/Wizard.js.map +0 -1
- package/hooks/Wizard/index.d.ts +0 -3
- package/hooks/Wizard/useWizard.d.ts +0 -9
- package/hooks/Wizard.d.ts +0 -2
- package/useWizard-CWdIxZzX.cjs +0 -94
- package/useWizard-CWdIxZzX.cjs.map +0 -1
- package/useWizard-CWq--C3o.js +0 -95
- package/useWizard-CWq--C3o.js.map +0 -1
- /package/{styles.css → index.css} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.cjs","sources":["../../../src/components/Icon/Icon.tsx"],"sourcesContent":["import React, { type ReactNode, useMemo } from 'react';\nimport { Badge, styled } from '@mui/material';\n\nexport type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface IconProps {\n /**\n * Contenido icono. Modo legacy: acepta un elemento MUI o SVG ya armado.\n * Si se usa junto con `path` o `url`, `children` tiene prioridad.\n */\n children?: ReactNode;\n /**\n * Ruta SVG inline
|
|
1
|
+
{"version":3,"file":"Icon.cjs","sources":["../../../src/components/Icon/Icon.tsx"],"sourcesContent":["import React, { type ReactNode, useMemo } from 'react';\nimport { Badge, styled } from '@mui/material';\nimport type { SxProps, Theme } from '@mui/material/styles';\n\nexport type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface IconProps {\n /**\n * Contenido del icono. Modo legacy: acepta un elemento MUI o SVG ya armado.\n * Si se usa junto con `path` o `url`, `children` tiene prioridad.\n */\n children?: ReactNode;\n /**\n * Ruta SVG inline. Acepta dos formatos:\n * - Solo el valor del atributo `d` de un `<path>` (ej. `\"M12 2L2 22...\"`).\n * - Un SVG completo (ej. `\"<svg>...</svg>\"`).\n *\n * ⚠️ Seguridad: cuando el string empieza con `<svg`, se inyecta vía\n * `dangerouslySetInnerHTML`. **NUNCA pasar contenido proveniente de input\n * de usuario o de backends no confiables** — riesgo XSS.\n */\n path?: string;\n /**\n * URL a un archivo `.svg` (asset local o remoto). Se renderiza vía `<img>`.\n * El color del icono NO aplica en este modo (limitación de `<img>`).\n */\n url?: string;\n /** Alt text cuando se usa `url`. Default: `\"icon\"`. */\n alt?: string;\n /**\n * ViewBox cuando se usa `path`. Default: `\"0 0 24 24\"`. Ignorado si `path`\n * ya viene como `<svg>` completo.\n */\n viewBox?: string;\n color?: string;\n outlined?: boolean;\n spin?: boolean;\n badge?: string | number;\n badgeColor?: 'primary' | 'secondary' | 'error';\n badgePosition?: {\n vertical: 'top' | 'bottom';\n horizontal: 'right' | 'left';\n };\n size?: IconSize;\n black?: boolean;\n white?: boolean;\n className?: string;\n sx?: SxProps<Theme>;\n}\n\nconst sizeMap: Record<IconSize, number> = {\n xs: 18,\n sm: 24,\n md: 36,\n lg: 48,\n xl: 64,\n};\n\nconst StyledIcon = styled('span')<{\n color?: string;\n fontSize?: number;\n spin?: boolean;\n outlined?: boolean;\n}>(({ color, fontSize, spin, outlined }) => ({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: color,\n fontSize: fontSize,\n width: fontSize,\n height: fontSize,\n animation: spin ? 'spin 1s linear infinite' : undefined,\n border: outlined ? '1px solid currentColor' : undefined,\n borderRadius: '50%',\n padding: outlined ? 4 : 0,\n '@keyframes spin': {\n '0%': { transform: 'rotate(0deg)' },\n '100%': { transform: 'rotate(360deg)' },\n },\n '& svg': {\n width: '100%',\n height: '100%',\n fill: 'currentColor',\n display: 'block',\n },\n '& img': {\n width: '100%',\n height: '100%',\n display: 'block',\n },\n}));\n\nexport const Icon: React.FC<IconProps> = ({\n children,\n path,\n url,\n alt = 'icon',\n viewBox = '0 0 24 24',\n color = 'var(--primary-color)',\n outlined = false,\n spin = false,\n badge,\n badgeColor = 'primary',\n badgePosition = { vertical: 'bottom', horizontal: 'right' },\n size = 'sm',\n black,\n white,\n className,\n sx,\n}) => {\n const finalColor = white ? 'white' : black ? 'black' : color;\n const iconSize = sizeMap[size];\n\n const content = useMemo(() => {\n if (children) return children;\n\n if (path) {\n const trimmed = path.trim();\n if (trimmed.startsWith('<svg')) {\n return <span dangerouslySetInnerHTML={{ __html: trimmed }} />;\n }\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox={viewBox}\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d={trimmed} />\n </svg>\n );\n }\n\n if (url) {\n return <img src={url} alt={alt} />;\n }\n\n return null;\n }, [children, path, url, alt, viewBox]);\n\n return (\n <Badge\n badgeContent={badge}\n color={badgeColor}\n anchorOrigin={badgePosition}\n invisible={badge === undefined}\n sx={{ '.MuiBadge-badge': { transform: 'scale(1)' } }}\n >\n <StyledIcon\n color={finalColor}\n fontSize={iconSize}\n spin={spin}\n outlined={outlined}\n className={`hsi-icon ${className || ''}`}\n sx={sx}\n >\n {content}\n </StyledIcon>\n </Badge>\n );\n};\n\nexport default Icon;\n"],"names":["styled","useMemo","jsx","Badge"],"mappings":";;;;;AAkDA,MAAM,UAAoC;AAAA,EACxC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,MAAM,aAAaA,SAAAA,OAAO,MAAM,EAK7B,CAAC,EAAE,OAAO,UAAU,MAAM,gBAAgB;AAAA,EAC3C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW,OAAO,4BAA4B;AAAA,EAC9C,QAAQ,WAAW,2BAA2B;AAAA,EAC9C,cAAc;AAAA,EACd,SAAS,WAAW,IAAI;AAAA,EACxB,mBAAmB;AAAA,IACjB,MAAM,EAAE,WAAW,eAAA;AAAA,IACnB,QAAQ,EAAE,WAAW,iBAAA;AAAA,EAAiB;AAAA,EAExC,SAAS;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,EAAA;AAAA,EAEX,SAAS;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,EAAA;AAEb,EAAE;AAEK,MAAM,OAA4B,CAAC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP;AAAA,EACA,aAAa;AAAA,EACb,gBAAgB,EAAE,UAAU,UAAU,YAAY,QAAA;AAAA,EAClD,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,aAAa,QAAQ,UAAU,QAAQ,UAAU;AACvD,QAAM,WAAW,QAAQ,IAAI;AAE7B,QAAM,UAAUC,MAAAA,QAAQ,MAAM;AAC5B,QAAI,SAAU,QAAO;AAErB,QAAI,MAAM;AACR,YAAM,UAAU,KAAK,KAAA;AACrB,UAAI,QAAQ,WAAW,MAAM,GAAG;AAC9B,8CAAQ,QAAA,EAAK,yBAAyB,EAAE,QAAQ,WAAW;AAAA,MAC7D;AACA,aACEC,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN;AAAA,UACA,MAAK;AAAA,UACL,eAAY;AAAA,UAEZ,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAG,QAAA,CAAS;AAAA,QAAA;AAAA,MAAA;AAAA,IAGxB;AAEA,QAAI,KAAK;AACP,aAAOA,2BAAAA,IAAC,OAAA,EAAI,KAAK,KAAK,IAAA,CAAU;AAAA,IAClC;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,MAAM,KAAK,KAAK,OAAO,CAAC;AAEtC,SACEA,2BAAAA;AAAAA,IAACC,SAAAA;AAAAA,IAAA;AAAA,MACC,cAAc;AAAA,MACd,OAAO;AAAA,MACP,cAAc;AAAA,MACd,WAAW,UAAU;AAAA,MACrB,IAAI,EAAE,mBAAmB,EAAE,WAAW,aAAW;AAAA,MAEjD,UAAAD,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA,WAAW,YAAY,aAAa,EAAE;AAAA,UACtC;AAAA,UAEC,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACH;AAAA,EAAA;AAGN;;;"}
|
|
@@ -1,34 +1,28 @@
|
|
|
1
1
|
import { default as React, ReactNode } from 'react';
|
|
2
|
+
import { SxProps, Theme } from '@mui/material/styles';
|
|
2
3
|
export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
4
|
export interface IconProps {
|
|
4
5
|
/**
|
|
5
|
-
* Contenido icono. Modo legacy: acepta un elemento MUI o SVG ya armado.
|
|
6
|
+
* Contenido del icono. Modo legacy: acepta un elemento MUI o SVG ya armado.
|
|
6
7
|
* Si se usa junto con `path` o `url`, `children` tiene prioridad.
|
|
7
8
|
*/
|
|
8
9
|
children?: ReactNode;
|
|
9
10
|
/**
|
|
10
|
-
* Ruta SVG inline
|
|
11
|
-
*
|
|
11
|
+
* Ruta SVG inline. Acepta dos formatos:
|
|
12
|
+
* - Solo el valor del atributo `d` de un `<path>` (ej. `"M12 2L2 22..."`).
|
|
13
|
+
* - Un SVG completo (ej. `"<svg>...</svg>"`).
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Si el string contiene el tag `<svg>` completo (no solo el `d`), también
|
|
18
|
-
* se soporta y se inyecta tal cual via `dangerouslySetInnerHTML`.
|
|
15
|
+
* ⚠️ Seguridad: cuando el string empieza con `<svg`, se inyecta vía
|
|
16
|
+
* `dangerouslySetInnerHTML`. **NUNCA pasar contenido proveniente de input
|
|
17
|
+
* de usuario o de backends no confiables** — riesgo XSS.
|
|
19
18
|
*/
|
|
20
19
|
path?: string;
|
|
21
20
|
/**
|
|
22
21
|
* URL a un archivo `.svg` (asset local o remoto). Se renderiza vía `<img>`.
|
|
23
|
-
*
|
|
24
|
-
* ```tsx
|
|
25
|
-
* <Icon url="/assets/icons/custom-warning.svg" />
|
|
26
|
-
* ```
|
|
22
|
+
* El color del icono NO aplica en este modo (limitación de `<img>`).
|
|
27
23
|
*/
|
|
28
24
|
url?: string;
|
|
29
|
-
/**
|
|
30
|
-
* Alt text cuando se usa `url`. Default: `"icon"`.
|
|
31
|
-
*/
|
|
25
|
+
/** Alt text cuando se usa `url`. Default: `"icon"`. */
|
|
32
26
|
alt?: string;
|
|
33
27
|
/**
|
|
34
28
|
* ViewBox cuando se usa `path`. Default: `"0 0 24 24"`. Ignorado si `path`
|
|
@@ -44,11 +38,11 @@ export interface IconProps {
|
|
|
44
38
|
vertical: 'top' | 'bottom';
|
|
45
39
|
horizontal: 'right' | 'left';
|
|
46
40
|
};
|
|
47
|
-
badgeSize?: 'small' | 'medium' | 'large';
|
|
48
41
|
size?: IconSize;
|
|
49
42
|
black?: boolean;
|
|
50
43
|
white?: boolean;
|
|
51
44
|
className?: string;
|
|
45
|
+
sx?: SxProps<Theme>;
|
|
52
46
|
}
|
|
53
47
|
export declare const Icon: React.FC<IconProps>;
|
|
54
48
|
export default Icon;
|
package/components/Icon/Icon.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import '../../styles.css';/* empty css */
|
|
2
1
|
import { jsx } from "react/jsx-runtime";
|
|
3
2
|
import { useMemo } from "react";
|
|
4
3
|
import { styled, Badge } from "@mui/material";
|
|
@@ -52,13 +51,10 @@ const Icon = ({
|
|
|
52
51
|
size = "sm",
|
|
53
52
|
black,
|
|
54
53
|
white,
|
|
55
|
-
className
|
|
54
|
+
className,
|
|
55
|
+
sx
|
|
56
56
|
}) => {
|
|
57
|
-
const finalColor =
|
|
58
|
-
if (white) return "white";
|
|
59
|
-
if (black) return "black";
|
|
60
|
-
return color;
|
|
61
|
-
}, [color, white, black]);
|
|
57
|
+
const finalColor = white ? "white" : black ? "black" : color;
|
|
62
58
|
const iconSize = sizeMap[size];
|
|
63
59
|
const content = useMemo(() => {
|
|
64
60
|
if (children) return children;
|
|
@@ -99,6 +95,7 @@ const Icon = ({
|
|
|
99
95
|
spin,
|
|
100
96
|
outlined,
|
|
101
97
|
className: `hsi-icon ${className || ""}`,
|
|
98
|
+
sx,
|
|
102
99
|
children: content
|
|
103
100
|
}
|
|
104
101
|
)
|
|
@@ -106,6 +103,7 @@ const Icon = ({
|
|
|
106
103
|
);
|
|
107
104
|
};
|
|
108
105
|
export {
|
|
109
|
-
Icon
|
|
106
|
+
Icon,
|
|
107
|
+
Icon as default
|
|
110
108
|
};
|
|
111
109
|
//# sourceMappingURL=Icon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.js","sources":["../../../src/components/Icon/Icon.tsx"],"sourcesContent":["import React, { type ReactNode, useMemo } from 'react';\nimport { Badge, styled } from '@mui/material';\n\nexport type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface IconProps {\n /**\n * Contenido icono. Modo legacy: acepta un elemento MUI o SVG ya armado.\n * Si se usa junto con `path` o `url`, `children` tiene prioridad.\n */\n children?: ReactNode;\n /**\n * Ruta SVG inline
|
|
1
|
+
{"version":3,"file":"Icon.js","sources":["../../../src/components/Icon/Icon.tsx"],"sourcesContent":["import React, { type ReactNode, useMemo } from 'react';\nimport { Badge, styled } from '@mui/material';\nimport type { SxProps, Theme } from '@mui/material/styles';\n\nexport type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface IconProps {\n /**\n * Contenido del icono. Modo legacy: acepta un elemento MUI o SVG ya armado.\n * Si se usa junto con `path` o `url`, `children` tiene prioridad.\n */\n children?: ReactNode;\n /**\n * Ruta SVG inline. Acepta dos formatos:\n * - Solo el valor del atributo `d` de un `<path>` (ej. `\"M12 2L2 22...\"`).\n * - Un SVG completo (ej. `\"<svg>...</svg>\"`).\n *\n * ⚠️ Seguridad: cuando el string empieza con `<svg`, se inyecta vía\n * `dangerouslySetInnerHTML`. **NUNCA pasar contenido proveniente de input\n * de usuario o de backends no confiables** — riesgo XSS.\n */\n path?: string;\n /**\n * URL a un archivo `.svg` (asset local o remoto). Se renderiza vía `<img>`.\n * El color del icono NO aplica en este modo (limitación de `<img>`).\n */\n url?: string;\n /** Alt text cuando se usa `url`. Default: `\"icon\"`. */\n alt?: string;\n /**\n * ViewBox cuando se usa `path`. Default: `\"0 0 24 24\"`. Ignorado si `path`\n * ya viene como `<svg>` completo.\n */\n viewBox?: string;\n color?: string;\n outlined?: boolean;\n spin?: boolean;\n badge?: string | number;\n badgeColor?: 'primary' | 'secondary' | 'error';\n badgePosition?: {\n vertical: 'top' | 'bottom';\n horizontal: 'right' | 'left';\n };\n size?: IconSize;\n black?: boolean;\n white?: boolean;\n className?: string;\n sx?: SxProps<Theme>;\n}\n\nconst sizeMap: Record<IconSize, number> = {\n xs: 18,\n sm: 24,\n md: 36,\n lg: 48,\n xl: 64,\n};\n\nconst StyledIcon = styled('span')<{\n color?: string;\n fontSize?: number;\n spin?: boolean;\n outlined?: boolean;\n}>(({ color, fontSize, spin, outlined }) => ({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: color,\n fontSize: fontSize,\n width: fontSize,\n height: fontSize,\n animation: spin ? 'spin 1s linear infinite' : undefined,\n border: outlined ? '1px solid currentColor' : undefined,\n borderRadius: '50%',\n padding: outlined ? 4 : 0,\n '@keyframes spin': {\n '0%': { transform: 'rotate(0deg)' },\n '100%': { transform: 'rotate(360deg)' },\n },\n '& svg': {\n width: '100%',\n height: '100%',\n fill: 'currentColor',\n display: 'block',\n },\n '& img': {\n width: '100%',\n height: '100%',\n display: 'block',\n },\n}));\n\nexport const Icon: React.FC<IconProps> = ({\n children,\n path,\n url,\n alt = 'icon',\n viewBox = '0 0 24 24',\n color = 'var(--primary-color)',\n outlined = false,\n spin = false,\n badge,\n badgeColor = 'primary',\n badgePosition = { vertical: 'bottom', horizontal: 'right' },\n size = 'sm',\n black,\n white,\n className,\n sx,\n}) => {\n const finalColor = white ? 'white' : black ? 'black' : color;\n const iconSize = sizeMap[size];\n\n const content = useMemo(() => {\n if (children) return children;\n\n if (path) {\n const trimmed = path.trim();\n if (trimmed.startsWith('<svg')) {\n return <span dangerouslySetInnerHTML={{ __html: trimmed }} />;\n }\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox={viewBox}\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d={trimmed} />\n </svg>\n );\n }\n\n if (url) {\n return <img src={url} alt={alt} />;\n }\n\n return null;\n }, [children, path, url, alt, viewBox]);\n\n return (\n <Badge\n badgeContent={badge}\n color={badgeColor}\n anchorOrigin={badgePosition}\n invisible={badge === undefined}\n sx={{ '.MuiBadge-badge': { transform: 'scale(1)' } }}\n >\n <StyledIcon\n color={finalColor}\n fontSize={iconSize}\n spin={spin}\n outlined={outlined}\n className={`hsi-icon ${className || ''}`}\n sx={sx}\n >\n {content}\n </StyledIcon>\n </Badge>\n );\n};\n\nexport default Icon;\n"],"names":[],"mappings":";;;AAkDA,MAAM,UAAoC;AAAA,EACxC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,MAAM,aAAa,OAAO,MAAM,EAK7B,CAAC,EAAE,OAAO,UAAU,MAAM,gBAAgB;AAAA,EAC3C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW,OAAO,4BAA4B;AAAA,EAC9C,QAAQ,WAAW,2BAA2B;AAAA,EAC9C,cAAc;AAAA,EACd,SAAS,WAAW,IAAI;AAAA,EACxB,mBAAmB;AAAA,IACjB,MAAM,EAAE,WAAW,eAAA;AAAA,IACnB,QAAQ,EAAE,WAAW,iBAAA;AAAA,EAAiB;AAAA,EAExC,SAAS;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,EAAA;AAAA,EAEX,SAAS;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,EAAA;AAEb,EAAE;AAEK,MAAM,OAA4B,CAAC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP;AAAA,EACA,aAAa;AAAA,EACb,gBAAgB,EAAE,UAAU,UAAU,YAAY,QAAA;AAAA,EAClD,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,aAAa,QAAQ,UAAU,QAAQ,UAAU;AACvD,QAAM,WAAW,QAAQ,IAAI;AAE7B,QAAM,UAAU,QAAQ,MAAM;AAC5B,QAAI,SAAU,QAAO;AAErB,QAAI,MAAM;AACR,YAAM,UAAU,KAAK,KAAA;AACrB,UAAI,QAAQ,WAAW,MAAM,GAAG;AAC9B,mCAAQ,QAAA,EAAK,yBAAyB,EAAE,QAAQ,WAAW;AAAA,MAC7D;AACA,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN;AAAA,UACA,MAAK;AAAA,UACL,eAAY;AAAA,UAEZ,UAAA,oBAAC,QAAA,EAAK,GAAG,QAAA,CAAS;AAAA,QAAA;AAAA,MAAA;AAAA,IAGxB;AAEA,QAAI,KAAK;AACP,aAAO,oBAAC,OAAA,EAAI,KAAK,KAAK,IAAA,CAAU;AAAA,IAClC;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,MAAM,KAAK,KAAK,OAAO,CAAC;AAEtC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,cAAc;AAAA,MACd,OAAO;AAAA,MACP,cAAc;AAAA,MACd,WAAW,UAAU;AAAA,MACrB,IAAI,EAAE,mBAAmB,EAAE,WAAW,aAAW;AAAA,MAEjD,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA,WAAW,YAAY,aAAa,EAAE;AAAA,UACtC;AAAA,UAEC,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACH;AAAA,EAAA;AAGN;"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { default
|
|
1
|
+
export { Icon, default } from './Icon';
|
|
2
|
+
export type { IconProps, IconSize } from './Icon';
|
package/components/Icon.d.ts
CHANGED
|
@@ -35,7 +35,8 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
35
35
|
const material = require("@mui/material");
|
|
36
36
|
const styles = require("@mui/material/styles");
|
|
37
37
|
const reactHookForm = require("react-hook-form");
|
|
38
|
-
const formField_sx = require("../../formField.sx-
|
|
38
|
+
const formField_sx = require("../../formField.sx-BAX7KwMR.cjs");
|
|
39
|
+
const tokens = require("../../tokens-jaWWNk39.cjs");
|
|
39
40
|
const resolvePreset = require("../../resolvePreset-CT3kU-K2.cjs");
|
|
40
41
|
const parseValue = (raw, type) => {
|
|
41
42
|
if (type !== "number") return raw;
|
|
@@ -43,10 +44,10 @@ const parseValue = (raw, type) => {
|
|
|
43
44
|
const n = parseFloat(raw);
|
|
44
45
|
return isNaN(n) ? raw : n;
|
|
45
46
|
};
|
|
46
|
-
const buildSlotProps = (type, min, max, customSlotProps, customInputProps,
|
|
47
|
+
const buildSlotProps = (type, min, max, maxLength, customSlotProps, customInputProps, readOnly) => {
|
|
47
48
|
const numberAttrs = type === "number" ? __spreadValues({ min: min != null ? min : Number.NEGATIVE_INFINITY }, max !== void 0 && { max }) : {};
|
|
48
49
|
return __spreadProps(__spreadValues({}, customSlotProps), {
|
|
49
|
-
htmlInput: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, customInputProps), customSlotProps == null ? void 0 : customSlotProps.htmlInput), numberAttrs), readOnly && { readOnly: true }),
|
|
50
|
+
htmlInput: __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, customInputProps), customSlotProps == null ? void 0 : customSlotProps.htmlInput), numberAttrs), maxLength !== void 0 && { maxLength }), readOnly && { readOnly: true }),
|
|
50
51
|
// Dejamos que MUI maneje el shrink nativamente (animación inside → up).
|
|
51
52
|
// El consumidor puede forzar shrink con slotProps.inputLabel.shrink=true si lo necesita.
|
|
52
53
|
inputLabel: __spreadValues({}, customSlotProps == null ? void 0 : customSlotProps.inputLabel)
|
|
@@ -59,8 +60,8 @@ const buildInputSx = (borderRadius, labelPosition) => {
|
|
|
59
60
|
labelPosition,
|
|
60
61
|
extraOutsideSx: {
|
|
61
62
|
"& .MuiInputBase-input": {
|
|
62
|
-
paddingTop:
|
|
63
|
-
paddingBottom:
|
|
63
|
+
paddingTop: tokens.FIELD_INPUT_PADDING_Y,
|
|
64
|
+
paddingBottom: tokens.FIELD_INPUT_PADDING_Y
|
|
64
65
|
},
|
|
65
66
|
// Filled: quitar el padding-top reservado para el label flotante dentro.
|
|
66
67
|
"& .MuiFilledInput-root": {
|
|
@@ -68,7 +69,7 @@ const buildInputSx = (borderRadius, labelPosition) => {
|
|
|
68
69
|
borderRadius: `${radius} ${radius} 0 0`
|
|
69
70
|
},
|
|
70
71
|
"& .MuiFilledInput-input": {
|
|
71
|
-
paddingTop:
|
|
72
|
+
paddingTop: tokens.FIELD_INPUT_PADDING_Y
|
|
72
73
|
},
|
|
73
74
|
// Standard: quitar el margin-top reservado para el label flotante.
|
|
74
75
|
"& .MuiInput-root": {
|
|
@@ -87,10 +88,12 @@ const Input = (props) => {
|
|
|
87
88
|
preset,
|
|
88
89
|
min,
|
|
89
90
|
max,
|
|
91
|
+
maxLength,
|
|
90
92
|
readOnly,
|
|
91
93
|
inputProps,
|
|
92
94
|
slotProps,
|
|
93
|
-
sx
|
|
95
|
+
sx,
|
|
96
|
+
onBlur
|
|
94
97
|
} = _a, rest = __objRest(_a, [
|
|
95
98
|
"type",
|
|
96
99
|
"variant",
|
|
@@ -100,10 +103,12 @@ const Input = (props) => {
|
|
|
100
103
|
"preset",
|
|
101
104
|
"min",
|
|
102
105
|
"max",
|
|
106
|
+
"maxLength",
|
|
103
107
|
"readOnly",
|
|
104
108
|
"inputProps",
|
|
105
109
|
"slotProps",
|
|
106
|
-
"sx"
|
|
110
|
+
"sx",
|
|
111
|
+
"onBlur"
|
|
107
112
|
]);
|
|
108
113
|
const theme = styles.useTheme();
|
|
109
114
|
const presetSx = resolvePreset.resolvePreset("Input", preset, theme);
|
|
@@ -111,18 +116,18 @@ const Input = (props) => {
|
|
|
111
116
|
type,
|
|
112
117
|
min,
|
|
113
118
|
max,
|
|
119
|
+
maxLength,
|
|
114
120
|
slotProps,
|
|
115
121
|
inputProps,
|
|
116
|
-
labelPosition,
|
|
117
122
|
readOnly
|
|
118
123
|
);
|
|
119
124
|
const mergedSx = [
|
|
120
125
|
buildInputSx(borderRadius, labelPosition),
|
|
121
126
|
...presetSx ? [presetSx] : [],
|
|
122
|
-
...Array.isArray(sx) ? sx : [sx]
|
|
127
|
+
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
123
128
|
];
|
|
124
129
|
if ("control" in props && props.control) {
|
|
125
|
-
const { name, control, validation } = props;
|
|
130
|
+
const { name, control, validation, onValueChange } = props;
|
|
126
131
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
127
132
|
reactHookForm.Controller,
|
|
128
133
|
{
|
|
@@ -138,8 +143,15 @@ const Input = (props) => {
|
|
|
138
143
|
}, rest), {
|
|
139
144
|
name: field.name,
|
|
140
145
|
value: (_a2 = field.value) != null ? _a2 : "",
|
|
141
|
-
onChange: (e) =>
|
|
142
|
-
|
|
146
|
+
onChange: (e) => {
|
|
147
|
+
const parsed = parseValue(e.target.value, type);
|
|
148
|
+
field.onChange(parsed);
|
|
149
|
+
onValueChange == null ? void 0 : onValueChange(parsed);
|
|
150
|
+
},
|
|
151
|
+
onBlur: (e) => {
|
|
152
|
+
field.onBlur();
|
|
153
|
+
onBlur == null ? void 0 : onBlur(e);
|
|
154
|
+
},
|
|
143
155
|
inputRef: field.ref,
|
|
144
156
|
type,
|
|
145
157
|
variant,
|
|
@@ -162,6 +174,7 @@ const Input = (props) => {
|
|
|
162
174
|
}, rest), {
|
|
163
175
|
value: value != null ? value : "",
|
|
164
176
|
onChange: (e) => onChange(parseValue(e.target.value, type)),
|
|
177
|
+
onBlur,
|
|
165
178
|
type,
|
|
166
179
|
variant,
|
|
167
180
|
size,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.cjs","sources":["../../../src/components/Input/Input.helpers.ts","../../../src/components/Input/Input.sx.ts","../../../src/components/Input/Input.tsx"],"sourcesContent":["import type { InputHTMLAttributes } from 'react';\nimport type { TextFieldProps } from '@mui/material';\nimport type { InputType, LabelPosition } from './Input';\n\n/**\n * Convierte el valor raw del evento al tipo apropiado.\n * Para type=\"number\" intenta parsear a número; si falla, devuelve el raw\n * (permite estados intermedios como \"\" o \"-\" mientras el usuario tipea).\n */\nexport const parseValue = (raw: string, type: InputType): string | number => {\n if (type !== 'number') return raw;\n if (raw === '' || raw === '-') return raw;\n const n = parseFloat(raw);\n return isNaN(n) ? raw : n;\n};\n\n/**\n * Construye los slotProps del TextField consolidando htmlInput + inputLabel.\n * Maneja los atributos min/max cuando type=\"number\" y readOnly.\n */\nexport const buildSlotProps = (\n type: InputType,\n min: number | undefined,\n max: number | undefined,\n customSlotProps: TextFieldProps['slotProps'],\n customInputProps: InputHTMLAttributes<HTMLInputElement> | undefined,\n _labelPosition: LabelPosition,\n readOnly?: boolean,\n): TextFieldProps['slotProps'] => {\n const numberAttrs =\n type === 'number'\n ? { min: min ?? Number.NEGATIVE_INFINITY, ...(max !== undefined && { max }) }\n : {};\n\n return {\n ...customSlotProps,\n htmlInput: {\n ...customInputProps,\n ...(customSlotProps as any)?.htmlInput,\n ...numberAttrs,\n ...(readOnly && { readOnly: true }),\n },\n // Dejamos que MUI maneje el shrink nativamente (animación inside → up).\n // El consumidor puede forzar shrink con slotProps.inputLabel.shrink=true si lo necesita.\n inputLabel: {\n ...(customSlotProps as any)?.inputLabel,\n },\n };\n};\n","import type { TextFieldProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport { FIELD_INPUT_PADDING_Y } from '../../theme/tokens';\nimport type { LabelPosition } from './Input';\n\n/**\n * Builder de sx para el Input. Usa el builder compartido\n * `buildFormFieldSx` y añade overrides específicos de TextField\n * (padding del input base, filled, standard).\n */\nexport const buildInputSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): TextFieldProps['sx'] => {\n const radius = typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius;\n\n return buildFormFieldSx({\n borderRadius,\n labelPosition,\n extraOutsideSx: {\n '& .MuiInputBase-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n paddingBottom: FIELD_INPUT_PADDING_Y,\n },\n\n // Filled: quitar el padding-top reservado para el label flotante dentro.\n '& .MuiFilledInput-root': {\n paddingTop: 0,\n borderRadius: `${radius} ${radius} 0 0`,\n },\n '& .MuiFilledInput-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n },\n\n // Standard: quitar el margin-top reservado para el label flotante.\n '& .MuiInput-root': {\n marginTop: 0,\n },\n },\n });\n};\n","import { TextField, type TextFieldProps } from '@mui/material';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { parseValue, buildSlotProps } from './Input.helpers';\nimport { buildInputSx } from './Input.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport type InputType =\n | 'text' | 'number' | 'email' | 'password' | 'tel'\n | 'url' | 'search' | 'date' | 'datetime-local'\n | 'month' | 'week' | 'time' | 'color';\n\nexport type LabelPosition = 'outside' | 'floating';\n\n// ── Props base (todo lo común entre RHF y controlado) ────────────────────\nexport interface BaseInputProps\n extends Omit<TextFieldProps, 'value' | 'onChange' | 'type'> {\n type?: InputType;\n min?: number;\n max?: number;\n /** Border radius del input. Default: 10 */\n borderRadius?: number | string;\n /** \"outside\" = label arriba del campo (default). \"floating\" = label clásico MUI dentro del borde */\n labelPosition?: LabelPosition;\n readOnly?: boolean;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Input`.\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}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFInputProps extends BaseInputProps {\n name: string;\n control: Control<any>;\n validation?: RegisterOptions;\n value?: never;\n onChange?: never;\n}\n\nexport interface ControlledInputProps extends BaseInputProps {\n name?: string;\n control?: never;\n validation?: never;\n value: string | number;\n onChange: (value: string | number) => void;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type InputProps = RHFInputProps | ControlledInputProps;\n\nexport const Input: React.FC<InputProps> = (props) => {\n const {\n type = 'text',\n variant = 'outlined',\n size = 'small',\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n min,\n max,\n readOnly,\n inputProps,\n slotProps,\n sx,\n ...rest\n } = props as ControlledInputProps & {\n control?: Control<any>;\n validation?: RegisterOptions;\n readOnly?: boolean;\n preset?: string;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Input', preset, theme);\n\n const finalSlotProps = buildSlotProps(\n type,\n min,\n max,\n slotProps,\n inputProps,\n labelPosition,\n readOnly,\n );\n const mergedSx = [\n buildInputSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\n ...(Array.isArray(sx) ? sx : [sx]),\n ];\n\n if ('control' in props && props.control) {\n const { name, control, validation } = props as RHFInputProps;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n render={({ field, fieldState: { error } }) => (\n <TextField\n fullWidth\n {...rest}\n name={field.name}\n value={field.value ?? ''}\n onChange={(e) => field.onChange(parseValue(e.target.value, type))}\n onBlur={field.onBlur}\n inputRef={field.ref}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n error={!!error || rest.error}\n helperText={error?.message ?? rest.helperText}\n />\n )}\n />\n );\n }\n\n const { value, onChange } = props as ControlledInputProps;\n return (\n <TextField\n fullWidth\n {...rest}\n value={value ?? ''}\n onChange={(e) => onChange(parseValue(e.target.value, type))}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n />\n );\n};\n\nexport default Input;\n"],"names":["buildFormFieldSx","FIELD_INPUT_PADDING_Y","useTheme","resolvePreset","jsx","Controller","TextField","_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Input.cjs","sources":["../../../src/components/Input/Input.helpers.ts","../../../src/components/Input/Input.sx.ts","../../../src/components/Input/Input.tsx"],"sourcesContent":["import type { InputHTMLAttributes } from 'react';\nimport type { TextFieldProps } from '@mui/material';\nimport type { InputType } from './Input';\n\n/**\n * Convierte el valor raw del evento al tipo apropiado.\n * Para type=\"number\" intenta parsear a número; si falla, devuelve el raw\n * (permite estados intermedios como \"\" o \"-\" mientras el usuario tipea).\n */\nexport const parseValue = (raw: string, type: InputType): string | number => {\n if (type !== 'number') return raw;\n if (raw === '' || raw === '-') return raw;\n const n = parseFloat(raw);\n return isNaN(n) ? raw : n;\n};\n\n/**\n * Construye los slotProps del TextField consolidando htmlInput + inputLabel.\n * Maneja los atributos min/max cuando type=\"number\", maxLength y readOnly.\n */\nexport const buildSlotProps = (\n type: InputType,\n min: number | undefined,\n max: number | undefined,\n maxLength: number | undefined,\n customSlotProps: TextFieldProps['slotProps'],\n customInputProps: InputHTMLAttributes<HTMLInputElement> | undefined,\n readOnly?: boolean,\n): TextFieldProps['slotProps'] => {\n const numberAttrs =\n type === 'number'\n ? { min: min ?? Number.NEGATIVE_INFINITY, ...(max !== undefined && { max }) }\n : {};\n\n return {\n ...customSlotProps,\n htmlInput: {\n ...customInputProps,\n ...(customSlotProps as any)?.htmlInput,\n ...numberAttrs,\n ...(maxLength !== undefined && { maxLength }),\n ...(readOnly && { readOnly: true }),\n },\n // Dejamos que MUI maneje el shrink nativamente (animación inside → up).\n // El consumidor puede forzar shrink con slotProps.inputLabel.shrink=true si lo necesita.\n inputLabel: {\n ...(customSlotProps as any)?.inputLabel,\n },\n };\n};\n","import type { TextFieldProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport { FIELD_INPUT_PADDING_Y } from '../../theme/tokens';\nimport type { LabelPosition } from './Input';\n\n/**\n * Builder de sx para el Input. Usa el builder compartido\n * `buildFormFieldSx` y añade overrides específicos de TextField\n * (padding del input base, filled, standard).\n */\nexport const buildInputSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): TextFieldProps['sx'] => {\n const radius = typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius;\n\n return buildFormFieldSx({\n borderRadius,\n labelPosition,\n extraOutsideSx: {\n '& .MuiInputBase-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n paddingBottom: FIELD_INPUT_PADDING_Y,\n },\n\n // Filled: quitar el padding-top reservado para el label flotante dentro.\n '& .MuiFilledInput-root': {\n paddingTop: 0,\n borderRadius: `${radius} ${radius} 0 0`,\n },\n '& .MuiFilledInput-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n },\n\n // Standard: quitar el margin-top reservado para el label flotante.\n '& .MuiInput-root': {\n marginTop: 0,\n },\n },\n });\n};\n","import { TextField, type TextFieldProps } from '@mui/material';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { parseValue, buildSlotProps } from './Input.helpers';\nimport { buildInputSx } from './Input.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport type InputType =\n | 'text' | 'number' | 'email' | 'password' | 'tel'\n | 'url' | 'search' | 'date' | 'datetime-local'\n | 'month' | 'week' | 'time' | 'color';\n\nexport type LabelPosition = 'outside' | 'floating';\n\n// ── Props base (todo lo común entre RHF y controlado) ────────────────────\nexport interface BaseInputProps\n extends Omit<TextFieldProps, 'value' | 'onChange' | 'type'> {\n type?: InputType;\n min?: number;\n max?: number;\n maxLength?: number;\n /** Border radius del input. Default: 10 */\n borderRadius?: number | string;\n /** \"outside\" = label arriba del campo (default). \"floating\" = label clásico MUI dentro del borde */\n labelPosition?: LabelPosition;\n readOnly?: boolean;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Input`.\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}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFInputProps extends BaseInputProps {\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 o su uso involucra generics adicionales, TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda. El\n // `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del componente.\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: string | number) => void;\n value?: never;\n onChange?: never;\n}\n\nexport interface ControlledInputProps extends BaseInputProps {\n name?: string;\n control?: never;\n validation?: never;\n value: string | number;\n onChange: (value: string | number) => void;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type InputProps = RHFInputProps | ControlledInputProps;\n\nexport const Input: React.FC<InputProps> = (props) => {\n const {\n type = 'text',\n variant = 'outlined',\n size = 'small',\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n min,\n max,\n maxLength,\n readOnly,\n inputProps,\n slotProps,\n sx,\n onBlur,\n ...rest\n } = props as ControlledInputProps & {\n control?: Control<any>;\n validation?: RegisterOptions;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Input', preset, theme);\n\n const finalSlotProps = buildSlotProps(\n type,\n min,\n max,\n maxLength,\n slotProps,\n inputProps,\n readOnly,\n );\n const mergedSx = [\n buildInputSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n if ('control' in props && props.control) {\n const { name, control, validation, onValueChange } = props as RHFInputProps;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n render={({ field, fieldState: { error } }) => (\n <TextField\n fullWidth\n {...rest}\n name={field.name}\n value={field.value ?? ''}\n onChange={(e) => {\n const parsed = parseValue(e.target.value, type);\n field.onChange(parsed);\n onValueChange?.(parsed);\n }}\n onBlur={(e) => {\n field.onBlur();\n onBlur?.(e);\n }}\n inputRef={field.ref}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n error={!!error || rest.error}\n helperText={error?.message ?? rest.helperText}\n />\n )}\n />\n );\n }\n\n const { value, onChange } = props as ControlledInputProps;\n return (\n <TextField\n fullWidth\n {...rest}\n value={value ?? ''}\n onChange={(e) => onChange(parseValue(e.target.value, type))}\n onBlur={onBlur}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n />\n );\n};\n\nexport default Input;\n"],"names":["buildFormFieldSx","FIELD_INPUT_PADDING_Y","useTheme","resolvePreset","jsx","Controller","TextField","_a"],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { TextFieldProps } from '@mui/material';
|
|
2
|
-
import {
|
|
2
|
+
import { RegisterOptions } from 'react-hook-form';
|
|
3
3
|
export type InputType = 'text' | 'number' | 'email' | 'password' | 'tel' | 'url' | 'search' | 'date' | 'datetime-local' | 'month' | 'week' | 'time' | 'color';
|
|
4
4
|
export type LabelPosition = 'outside' | 'floating';
|
|
5
5
|
export interface BaseInputProps extends Omit<TextFieldProps, 'value' | 'onChange' | 'type'> {
|
|
6
6
|
type?: InputType;
|
|
7
7
|
min?: number;
|
|
8
8
|
max?: number;
|
|
9
|
+
maxLength?: number;
|
|
9
10
|
/** Border radius del input. Default: 10 */
|
|
10
11
|
borderRadius?: number | string;
|
|
11
12
|
/** "outside" = label arriba del campo (default). "floating" = label clásico MUI dentro del borde */
|
|
@@ -20,8 +21,14 @@ export interface BaseInputProps extends Omit<TextFieldProps, 'value' | 'onChange
|
|
|
20
21
|
}
|
|
21
22
|
export interface RHFInputProps extends BaseInputProps {
|
|
22
23
|
name: string;
|
|
23
|
-
control:
|
|
24
|
+
control: any;
|
|
24
25
|
validation?: RegisterOptions;
|
|
26
|
+
/**
|
|
27
|
+
* Side-effect que corre después de que RHF actualiza el form state.
|
|
28
|
+
* Útil para cascadas entre campos (ej. reset de municipio al cambiar
|
|
29
|
+
* departamento). NO reemplaza al handler de RHF.
|
|
30
|
+
*/
|
|
31
|
+
onValueChange?: (value: string | number) => void;
|
|
25
32
|
value?: never;
|
|
26
33
|
onChange?: never;
|
|
27
34
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { InputHTMLAttributes } from 'react';
|
|
2
2
|
import { TextFieldProps } from '@mui/material';
|
|
3
|
-
import { InputType
|
|
3
|
+
import { InputType } from './Input';
|
|
4
4
|
/**
|
|
5
5
|
* Convierte el valor raw del evento al tipo apropiado.
|
|
6
6
|
* Para type="number" intenta parsear a número; si falla, devuelve el raw
|
|
@@ -9,6 +9,6 @@ import { InputType, LabelPosition } from './Input';
|
|
|
9
9
|
export declare const parseValue: (raw: string, type: InputType) => string | number;
|
|
10
10
|
/**
|
|
11
11
|
* Construye los slotProps del TextField consolidando htmlInput + inputLabel.
|
|
12
|
-
* Maneja los atributos min/max cuando type="number" y readOnly.
|
|
12
|
+
* Maneja los atributos min/max cuando type="number", maxLength y readOnly.
|
|
13
13
|
*/
|
|
14
|
-
export declare const buildSlotProps: (type: InputType, min: number | undefined, max: number | undefined, customSlotProps: TextFieldProps["slotProps"], customInputProps: InputHTMLAttributes<HTMLInputElement> | undefined,
|
|
14
|
+
export declare const buildSlotProps: (type: InputType, min: number | undefined, max: number | undefined, maxLength: number | undefined, customSlotProps: TextFieldProps["slotProps"], customInputProps: InputHTMLAttributes<HTMLInputElement> | undefined, readOnly?: boolean) => TextFieldProps["slotProps"];
|
|
@@ -33,7 +33,8 @@ import { jsx } from "react/jsx-runtime";
|
|
|
33
33
|
import { TextField } from "@mui/material";
|
|
34
34
|
import { useTheme } from "@mui/material/styles";
|
|
35
35
|
import { Controller } from "react-hook-form";
|
|
36
|
-
import { b as buildFormFieldSx
|
|
36
|
+
import { b as buildFormFieldSx } from "../../formField.sx-8_QRnKxv.js";
|
|
37
|
+
import { F as FIELD_INPUT_PADDING_Y } from "../../tokens-BRrcP_p_.js";
|
|
37
38
|
import { r as resolvePreset } from "../../resolvePreset-B-IB0ehH.js";
|
|
38
39
|
const parseValue = (raw, type) => {
|
|
39
40
|
if (type !== "number") return raw;
|
|
@@ -41,10 +42,10 @@ const parseValue = (raw, type) => {
|
|
|
41
42
|
const n = parseFloat(raw);
|
|
42
43
|
return isNaN(n) ? raw : n;
|
|
43
44
|
};
|
|
44
|
-
const buildSlotProps = (type, min, max, customSlotProps, customInputProps,
|
|
45
|
+
const buildSlotProps = (type, min, max, maxLength, customSlotProps, customInputProps, readOnly) => {
|
|
45
46
|
const numberAttrs = type === "number" ? __spreadValues({ min: min != null ? min : Number.NEGATIVE_INFINITY }, max !== void 0 && { max }) : {};
|
|
46
47
|
return __spreadProps(__spreadValues({}, customSlotProps), {
|
|
47
|
-
htmlInput: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, customInputProps), customSlotProps == null ? void 0 : customSlotProps.htmlInput), numberAttrs), readOnly && { readOnly: true }),
|
|
48
|
+
htmlInput: __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, customInputProps), customSlotProps == null ? void 0 : customSlotProps.htmlInput), numberAttrs), maxLength !== void 0 && { maxLength }), readOnly && { readOnly: true }),
|
|
48
49
|
// Dejamos que MUI maneje el shrink nativamente (animación inside → up).
|
|
49
50
|
// El consumidor puede forzar shrink con slotProps.inputLabel.shrink=true si lo necesita.
|
|
50
51
|
inputLabel: __spreadValues({}, customSlotProps == null ? void 0 : customSlotProps.inputLabel)
|
|
@@ -85,10 +86,12 @@ const Input = (props) => {
|
|
|
85
86
|
preset,
|
|
86
87
|
min,
|
|
87
88
|
max,
|
|
89
|
+
maxLength,
|
|
88
90
|
readOnly,
|
|
89
91
|
inputProps,
|
|
90
92
|
slotProps,
|
|
91
|
-
sx
|
|
93
|
+
sx,
|
|
94
|
+
onBlur
|
|
92
95
|
} = _a, rest = __objRest(_a, [
|
|
93
96
|
"type",
|
|
94
97
|
"variant",
|
|
@@ -98,10 +101,12 @@ const Input = (props) => {
|
|
|
98
101
|
"preset",
|
|
99
102
|
"min",
|
|
100
103
|
"max",
|
|
104
|
+
"maxLength",
|
|
101
105
|
"readOnly",
|
|
102
106
|
"inputProps",
|
|
103
107
|
"slotProps",
|
|
104
|
-
"sx"
|
|
108
|
+
"sx",
|
|
109
|
+
"onBlur"
|
|
105
110
|
]);
|
|
106
111
|
const theme = useTheme();
|
|
107
112
|
const presetSx = resolvePreset("Input", preset, theme);
|
|
@@ -109,18 +114,18 @@ const Input = (props) => {
|
|
|
109
114
|
type,
|
|
110
115
|
min,
|
|
111
116
|
max,
|
|
117
|
+
maxLength,
|
|
112
118
|
slotProps,
|
|
113
119
|
inputProps,
|
|
114
|
-
labelPosition,
|
|
115
120
|
readOnly
|
|
116
121
|
);
|
|
117
122
|
const mergedSx = [
|
|
118
123
|
buildInputSx(borderRadius, labelPosition),
|
|
119
124
|
...presetSx ? [presetSx] : [],
|
|
120
|
-
...Array.isArray(sx) ? sx : [sx]
|
|
125
|
+
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
121
126
|
];
|
|
122
127
|
if ("control" in props && props.control) {
|
|
123
|
-
const { name, control, validation } = props;
|
|
128
|
+
const { name, control, validation, onValueChange } = props;
|
|
124
129
|
return /* @__PURE__ */ jsx(
|
|
125
130
|
Controller,
|
|
126
131
|
{
|
|
@@ -136,8 +141,15 @@ const Input = (props) => {
|
|
|
136
141
|
}, rest), {
|
|
137
142
|
name: field.name,
|
|
138
143
|
value: (_a2 = field.value) != null ? _a2 : "",
|
|
139
|
-
onChange: (e) =>
|
|
140
|
-
|
|
144
|
+
onChange: (e) => {
|
|
145
|
+
const parsed = parseValue(e.target.value, type);
|
|
146
|
+
field.onChange(parsed);
|
|
147
|
+
onValueChange == null ? void 0 : onValueChange(parsed);
|
|
148
|
+
},
|
|
149
|
+
onBlur: (e) => {
|
|
150
|
+
field.onBlur();
|
|
151
|
+
onBlur == null ? void 0 : onBlur(e);
|
|
152
|
+
},
|
|
141
153
|
inputRef: field.ref,
|
|
142
154
|
type,
|
|
143
155
|
variant,
|
|
@@ -160,6 +172,7 @@ const Input = (props) => {
|
|
|
160
172
|
}, rest), {
|
|
161
173
|
value: value != null ? value : "",
|
|
162
174
|
onChange: (e) => onChange(parseValue(e.target.value, type)),
|
|
175
|
+
onBlur,
|
|
163
176
|
type,
|
|
164
177
|
variant,
|
|
165
178
|
size,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","sources":["../../../src/components/Input/Input.helpers.ts","../../../src/components/Input/Input.sx.ts","../../../src/components/Input/Input.tsx"],"sourcesContent":["import type { InputHTMLAttributes } from 'react';\nimport type { TextFieldProps } from '@mui/material';\nimport type { InputType, LabelPosition } from './Input';\n\n/**\n * Convierte el valor raw del evento al tipo apropiado.\n * Para type=\"number\" intenta parsear a número; si falla, devuelve el raw\n * (permite estados intermedios como \"\" o \"-\" mientras el usuario tipea).\n */\nexport const parseValue = (raw: string, type: InputType): string | number => {\n if (type !== 'number') return raw;\n if (raw === '' || raw === '-') return raw;\n const n = parseFloat(raw);\n return isNaN(n) ? raw : n;\n};\n\n/**\n * Construye los slotProps del TextField consolidando htmlInput + inputLabel.\n * Maneja los atributos min/max cuando type=\"number\" y readOnly.\n */\nexport const buildSlotProps = (\n type: InputType,\n min: number | undefined,\n max: number | undefined,\n customSlotProps: TextFieldProps['slotProps'],\n customInputProps: InputHTMLAttributes<HTMLInputElement> | undefined,\n _labelPosition: LabelPosition,\n readOnly?: boolean,\n): TextFieldProps['slotProps'] => {\n const numberAttrs =\n type === 'number'\n ? { min: min ?? Number.NEGATIVE_INFINITY, ...(max !== undefined && { max }) }\n : {};\n\n return {\n ...customSlotProps,\n htmlInput: {\n ...customInputProps,\n ...(customSlotProps as any)?.htmlInput,\n ...numberAttrs,\n ...(readOnly && { readOnly: true }),\n },\n // Dejamos que MUI maneje el shrink nativamente (animación inside → up).\n // El consumidor puede forzar shrink con slotProps.inputLabel.shrink=true si lo necesita.\n inputLabel: {\n ...(customSlotProps as any)?.inputLabel,\n },\n };\n};\n","import type { TextFieldProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport { FIELD_INPUT_PADDING_Y } from '../../theme/tokens';\nimport type { LabelPosition } from './Input';\n\n/**\n * Builder de sx para el Input. Usa el builder compartido\n * `buildFormFieldSx` y añade overrides específicos de TextField\n * (padding del input base, filled, standard).\n */\nexport const buildInputSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): TextFieldProps['sx'] => {\n const radius = typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius;\n\n return buildFormFieldSx({\n borderRadius,\n labelPosition,\n extraOutsideSx: {\n '& .MuiInputBase-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n paddingBottom: FIELD_INPUT_PADDING_Y,\n },\n\n // Filled: quitar el padding-top reservado para el label flotante dentro.\n '& .MuiFilledInput-root': {\n paddingTop: 0,\n borderRadius: `${radius} ${radius} 0 0`,\n },\n '& .MuiFilledInput-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n },\n\n // Standard: quitar el margin-top reservado para el label flotante.\n '& .MuiInput-root': {\n marginTop: 0,\n },\n },\n });\n};\n","import { TextField, type TextFieldProps } from '@mui/material';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { parseValue, buildSlotProps } from './Input.helpers';\nimport { buildInputSx } from './Input.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport type InputType =\n | 'text' | 'number' | 'email' | 'password' | 'tel'\n | 'url' | 'search' | 'date' | 'datetime-local'\n | 'month' | 'week' | 'time' | 'color';\n\nexport type LabelPosition = 'outside' | 'floating';\n\n// ── Props base (todo lo común entre RHF y controlado) ────────────────────\nexport interface BaseInputProps\n extends Omit<TextFieldProps, 'value' | 'onChange' | 'type'> {\n type?: InputType;\n min?: number;\n max?: number;\n /** Border radius del input. Default: 10 */\n borderRadius?: number | string;\n /** \"outside\" = label arriba del campo (default). \"floating\" = label clásico MUI dentro del borde */\n labelPosition?: LabelPosition;\n readOnly?: boolean;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Input`.\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}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFInputProps extends BaseInputProps {\n name: string;\n control: Control<any>;\n validation?: RegisterOptions;\n value?: never;\n onChange?: never;\n}\n\nexport interface ControlledInputProps extends BaseInputProps {\n name?: string;\n control?: never;\n validation?: never;\n value: string | number;\n onChange: (value: string | number) => void;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type InputProps = RHFInputProps | ControlledInputProps;\n\nexport const Input: React.FC<InputProps> = (props) => {\n const {\n type = 'text',\n variant = 'outlined',\n size = 'small',\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n min,\n max,\n readOnly,\n inputProps,\n slotProps,\n sx,\n ...rest\n } = props as ControlledInputProps & {\n control?: Control<any>;\n validation?: RegisterOptions;\n readOnly?: boolean;\n preset?: string;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Input', preset, theme);\n\n const finalSlotProps = buildSlotProps(\n type,\n min,\n max,\n slotProps,\n inputProps,\n labelPosition,\n readOnly,\n );\n const mergedSx = [\n buildInputSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\n ...(Array.isArray(sx) ? sx : [sx]),\n ];\n\n if ('control' in props && props.control) {\n const { name, control, validation } = props as RHFInputProps;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n render={({ field, fieldState: { error } }) => (\n <TextField\n fullWidth\n {...rest}\n name={field.name}\n value={field.value ?? ''}\n onChange={(e) => field.onChange(parseValue(e.target.value, type))}\n onBlur={field.onBlur}\n inputRef={field.ref}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n error={!!error || rest.error}\n helperText={error?.message ?? rest.helperText}\n />\n )}\n />\n );\n }\n\n const { value, onChange } = props as ControlledInputProps;\n return (\n <TextField\n fullWidth\n {...rest}\n value={value ?? ''}\n onChange={(e) => onChange(parseValue(e.target.value, type))}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n />\n );\n};\n\nexport default Input;\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../../src/components/Input/Input.helpers.ts","../../../src/components/Input/Input.sx.ts","../../../src/components/Input/Input.tsx"],"sourcesContent":["import type { InputHTMLAttributes } from 'react';\nimport type { TextFieldProps } from '@mui/material';\nimport type { InputType } from './Input';\n\n/**\n * Convierte el valor raw del evento al tipo apropiado.\n * Para type=\"number\" intenta parsear a número; si falla, devuelve el raw\n * (permite estados intermedios como \"\" o \"-\" mientras el usuario tipea).\n */\nexport const parseValue = (raw: string, type: InputType): string | number => {\n if (type !== 'number') return raw;\n if (raw === '' || raw === '-') return raw;\n const n = parseFloat(raw);\n return isNaN(n) ? raw : n;\n};\n\n/**\n * Construye los slotProps del TextField consolidando htmlInput + inputLabel.\n * Maneja los atributos min/max cuando type=\"number\", maxLength y readOnly.\n */\nexport const buildSlotProps = (\n type: InputType,\n min: number | undefined,\n max: number | undefined,\n maxLength: number | undefined,\n customSlotProps: TextFieldProps['slotProps'],\n customInputProps: InputHTMLAttributes<HTMLInputElement> | undefined,\n readOnly?: boolean,\n): TextFieldProps['slotProps'] => {\n const numberAttrs =\n type === 'number'\n ? { min: min ?? Number.NEGATIVE_INFINITY, ...(max !== undefined && { max }) }\n : {};\n\n return {\n ...customSlotProps,\n htmlInput: {\n ...customInputProps,\n ...(customSlotProps as any)?.htmlInput,\n ...numberAttrs,\n ...(maxLength !== undefined && { maxLength }),\n ...(readOnly && { readOnly: true }),\n },\n // Dejamos que MUI maneje el shrink nativamente (animación inside → up).\n // El consumidor puede forzar shrink con slotProps.inputLabel.shrink=true si lo necesita.\n inputLabel: {\n ...(customSlotProps as any)?.inputLabel,\n },\n };\n};\n","import type { TextFieldProps } from '@mui/material';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport { FIELD_INPUT_PADDING_Y } from '../../theme/tokens';\nimport type { LabelPosition } from './Input';\n\n/**\n * Builder de sx para el Input. Usa el builder compartido\n * `buildFormFieldSx` y añade overrides específicos de TextField\n * (padding del input base, filled, standard).\n */\nexport const buildInputSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): TextFieldProps['sx'] => {\n const radius = typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius;\n\n return buildFormFieldSx({\n borderRadius,\n labelPosition,\n extraOutsideSx: {\n '& .MuiInputBase-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n paddingBottom: FIELD_INPUT_PADDING_Y,\n },\n\n // Filled: quitar el padding-top reservado para el label flotante dentro.\n '& .MuiFilledInput-root': {\n paddingTop: 0,\n borderRadius: `${radius} ${radius} 0 0`,\n },\n '& .MuiFilledInput-input': {\n paddingTop: FIELD_INPUT_PADDING_Y,\n },\n\n // Standard: quitar el margin-top reservado para el label flotante.\n '& .MuiInput-root': {\n marginTop: 0,\n },\n },\n });\n};\n","import { TextField, type TextFieldProps } from '@mui/material';\nimport { useTheme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { parseValue, buildSlotProps } from './Input.helpers';\nimport { buildInputSx } from './Input.sx';\nimport { resolvePreset } from '../_shared/resolvePreset';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport type InputType =\n | 'text' | 'number' | 'email' | 'password' | 'tel'\n | 'url' | 'search' | 'date' | 'datetime-local'\n | 'month' | 'week' | 'time' | 'color';\n\nexport type LabelPosition = 'outside' | 'floating';\n\n// ── Props base (todo lo común entre RHF y controlado) ────────────────────\nexport interface BaseInputProps\n extends Omit<TextFieldProps, 'value' | 'onChange' | 'type'> {\n type?: InputType;\n min?: number;\n max?: number;\n maxLength?: number;\n /** Border radius del input. Default: 10 */\n borderRadius?: number | string;\n /** \"outside\" = label arriba del campo (default). \"floating\" = label clásico MUI dentro del borde */\n labelPosition?: LabelPosition;\n readOnly?: boolean;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Input`.\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}\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface RHFInputProps extends BaseInputProps {\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 o su uso involucra generics adicionales, TS se\n // confunde narroweando el discriminated union y `Control<any>` no logra\n // absorber `Control<MyForm>` en la comparación estructural profunda. El\n // `any` plano elimina ese ruido. RHF adentro sigue teniendo sus tipos\n // fuertes — solo degradamos la superficie del prop del componente.\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: string | number) => void;\n value?: never;\n onChange?: never;\n}\n\nexport interface ControlledInputProps extends BaseInputProps {\n name?: string;\n control?: never;\n validation?: never;\n value: string | number;\n onChange: (value: string | number) => void;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type InputProps = RHFInputProps | ControlledInputProps;\n\nexport const Input: React.FC<InputProps> = (props) => {\n const {\n type = 'text',\n variant = 'outlined',\n size = 'small',\n borderRadius = 10,\n labelPosition = 'outside',\n preset,\n min,\n max,\n maxLength,\n readOnly,\n inputProps,\n slotProps,\n sx,\n onBlur,\n ...rest\n } = props as ControlledInputProps & {\n control?: Control<any>;\n validation?: RegisterOptions;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Input', preset, theme);\n\n const finalSlotProps = buildSlotProps(\n type,\n min,\n max,\n maxLength,\n slotProps,\n inputProps,\n readOnly,\n );\n const mergedSx = [\n buildInputSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n if ('control' in props && props.control) {\n const { name, control, validation, onValueChange } = props as RHFInputProps;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n render={({ field, fieldState: { error } }) => (\n <TextField\n fullWidth\n {...rest}\n name={field.name}\n value={field.value ?? ''}\n onChange={(e) => {\n const parsed = parseValue(e.target.value, type);\n field.onChange(parsed);\n onValueChange?.(parsed);\n }}\n onBlur={(e) => {\n field.onBlur();\n onBlur?.(e);\n }}\n inputRef={field.ref}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n error={!!error || rest.error}\n helperText={error?.message ?? rest.helperText}\n />\n )}\n />\n );\n }\n\n const { value, onChange } = props as ControlledInputProps;\n return (\n <TextField\n fullWidth\n {...rest}\n value={value ?? ''}\n onChange={(e) => onChange(parseValue(e.target.value, type))}\n onBlur={onBlur}\n type={type}\n variant={variant}\n size={size}\n slotProps={finalSlotProps}\n sx={mergedSx}\n />\n );\n};\n\nexport default Input;\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Input, default } from './Input';
|
|
2
|
-
export type { InputProps, BaseInputProps, RHFInputProps, ControlledInputProps, InputType, LabelPosition, } from './Input
|
|
2
|
+
export type { InputProps, BaseInputProps, RHFInputProps, ControlledInputProps, InputType, LabelPosition, } from './Input';
|