@soyfri/shared-library 2.0.0-beta.35 → 2.0.0-beta.37

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.
@@ -58,6 +58,8 @@ const Tabs = ({
58
58
  onChangeValue == null ? void 0 : onChangeValue(newValue);
59
59
  };
60
60
  const effectiveCentered = centered && variant !== "scrollable" && variant !== "fullWidth";
61
+ const hasPanels = tabs.some((tab) => tab.props.children != null);
62
+ const renderPanels = !nav && hasPanels;
61
63
  const { display, flexDirection } = TAB_DISPLAY_MAP[orientation];
62
64
  return /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { display, flexDirection }, children: [
63
65
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -106,7 +108,7 @@ const Tabs = ({
106
108
  })
107
109
  }
108
110
  ),
109
- !nav && /* @__PURE__ */ jsxRuntime.jsx(material.Box, { m: 2, sx: { width: "100%" }, children: keepMounted ? tabs.map((tab, idx) => {
111
+ renderPanels && /* @__PURE__ */ jsxRuntime.jsx(material.Box, { m: 2, sx: { width: "100%" }, children: keepMounted ? tabs.map((tab, idx) => {
110
112
  var _a2;
111
113
  const value = (_a2 = tab.props.value) != null ? _a2 : idx;
112
114
  const isActive = value === currentValue;
@@ -132,4 +134,4 @@ const Tab = (_) => null;
132
134
  Tab.displayName = "Tab";
133
135
  exports.Tab = Tab;
134
136
  exports.Tabs = Tabs;
135
- //# sourceMappingURL=Tab-D-zNS5TI.cjs.map
137
+ //# sourceMappingURL=Tab-D1S7kxXI.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tab-D1S7kxXI.cjs","sources":["../src/components/Tabs/_tabUtils.tsx","../src/components/Tabs/Tabs.tsx","../src/components/Tabs/Tab.tsx"],"sourcesContent":["export const TAB_DISPLAY_MAP: Record<\"horizontal\" | \"vertical\", { display: string, flexDirection: string }> = {\n horizontal: { display: \"flex\", flexDirection: \"column\" },\n vertical: { display: \"flex\", flexDirection: \"row\" }\n};","import {\n Children,\n isValidElement,\n useState,\n type FC,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n} from 'react';\nimport {\n Tabs as MuiTabs,\n Tab as MuiTab,\n Box,\n type TabsProps as MuiTabsProps,\n} from '@mui/material';\n\nimport { TabProps } from './Tab';\nimport { TAB_DISPLAY_MAP } from './_tabUtils';\nimport { mergeSx } from '../_shared/mergeSx';\n\ntype PickTabsProps = Pick<\n MuiTabsProps,\n | 'centered'\n | 'indicatorColor'\n | 'orientation'\n | 'scrollButtons'\n | 'variant'\n | 'className'\n | 'sx'\n | 'visibleScrollbar'\n | 'allowScrollButtonsMobile'\n>;\n\nexport interface TabsProps extends PickTabsProps {\n /** Uno o varios `<Tab>`. Children que no sean `<Tab>` se ignoran. */\n children: ReactNode;\n /** Valor del tab inicialmente activo. Si no se provee, toma el `value` del primer `<Tab>` o `0`. */\n defaultValue?: number | string;\n /**\n * Valor activo **controlado**. Si se provee, el consumer maneja el estado\n * (típico en modo `nav`, donde el valor lo dicta la ruta). `false` = ningún\n * tab activo (ej. ruta que no corresponde a ninguna tab).\n */\n value?: number | string | false;\n /** Callback al cambiar de tab. Recibe el `value` del tab nuevo. */\n onChangeValue?: (newValue: number | string) => void;\n labelColor?: 'primary' | 'secondary' | 'inherit';\n /**\n * Modo **navegación**: las tabs son enlaces (`<Tab component={Link} to=.. />`),\n * el `value` activo es controlado externamente (por la ruta) y **no** se\n * renderizan paneles. `<Tab>` reenvía `component`/`to`/`href`/`onClick`.\n */\n nav?: boolean;\n /**\n * Cómo se manejan los paneles al cambiar de tab:\n * - `false` (default): **unmount** — solo se renderiza el panel activo; los\n * demás se desmontan. El state interno de los hijos se pierde al navegar.\n * Menor uso de memoria.\n * - `true`: **keep mounted** — renderiza todos los paneles pero oculta los\n * no activos con `display: none`. El state se preserva (inputs, scroll,\n * timers, subscripciones) al navegar entre tabs.\n */\n keepMounted?: boolean;\n}\n\nexport const Tabs: FC<TabsProps> = ({\n children,\n defaultValue,\n value: controlledValue,\n onChangeValue,\n centered = true,\n orientation = 'horizontal',\n scrollButtons = 'auto',\n variant = 'standard',\n indicatorColor = 'primary',\n labelColor = 'primary',\n className,\n allowScrollButtonsMobile = true,\n keepMounted = false,\n nav = false,\n sx,\n}) => {\n // Filtra a solo <Tab> children — acepta arrays, single child, fragments,\n // y descarta cualquier otra cosa (strings, null, condicionales falsy).\n const tabs: ReactElement<TabProps>[] = Children.toArray(children).filter(\n (child): child is ReactElement<TabProps> =>\n isValidElement(child) &&\n (child.type as { displayName?: string })?.displayName === 'Tab',\n );\n\n const firstValue = tabs[0]?.props.value;\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<string | number>(\n defaultValue ?? firstValue ?? 0,\n );\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const handleChange = (_event: SyntheticEvent, newValue: number | string) => {\n // En modo nav (o controlado) el consumer/ruta maneja el valor.\n if (!isControlled && !nav) setInternalValue(newValue);\n onChangeValue?.(newValue);\n };\n\n // MUI no permite `centered` con variant scrollable/fullWidth.\n const effectiveCentered =\n centered && variant !== 'scrollable' && variant !== 'fullWidth';\n\n // Si ningún `<Tab>` trae contenido (`children`), es una barra controlada y\n // los paneles los renderiza el consumer aparte — no generamos paneles vacíos.\n const hasPanels = tabs.some((tab) => tab.props.children != null);\n const renderPanels = !nav && hasPanels;\n\n const { display, flexDirection } = TAB_DISPLAY_MAP[orientation];\n\n return (\n <Box sx={{ display, flexDirection }}>\n <MuiTabs\n value={currentValue}\n onChange={handleChange}\n centered={effectiveCentered}\n indicatorColor={indicatorColor}\n orientation={orientation}\n scrollButtons={scrollButtons}\n variant={variant}\n className={className}\n textColor={labelColor}\n allowScrollButtonsMobile={allowScrollButtonsMobile}\n sx={mergeSx({}, sx)}\n >\n {tabs.map((tab, idx) => {\n const {\n label,\n icon,\n value = idx,\n disabled,\n wrapped,\n iconPosition,\n className: tabClassName,\n sx: tabSx,\n component,\n to,\n href,\n onClick,\n } = tab.props;\n return (\n <MuiTab\n key={value}\n label={label}\n icon={icon}\n value={value}\n disabled={disabled}\n wrapped={wrapped}\n iconPosition={iconPosition}\n className={tabClassName}\n sx={tabSx}\n // Modo nav: reenvía props de enlace/click.\n {...(component ? { component } : {})}\n {...(to ? { to } : {})}\n {...(href ? { href } : {})}\n {...(onClick ? { onClick } : {})}\n />\n );\n })}\n </MuiTabs>\n\n {renderPanels && (\n <Box m={2} sx={{ width: '100%' }}>\n {keepMounted\n ? tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n const isActive = value === currentValue;\n return (\n <Box\n key={value}\n role=\"tabpanel\"\n // `display: none` mantiene el nodo en el DOM — state de los\n // hijos (inputs, useState, etc.) no se pierde al navegar.\n sx={{ display: isActive ? 'block' : 'none' }}\n aria-hidden={!isActive}\n >\n {tab.props.children}\n </Box>\n );\n })\n : tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n if (value !== currentValue) return null;\n return (\n <Box key={value} role=\"tabpanel\">\n {tab.props.children}\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n );\n};\n\nexport default Tabs;\n","import React from \"react\";\nimport { TabProps as MuiTabProps } from \"@mui/material\";\n\ntype PickMuiTabProps = Pick<\n MuiTabProps,\n \"label\" | \"icon\" | \"disabled\" | \"sx\" | \"value\" | \"wrapped\" | \"iconPosition\" | \"className\" | \"disabled\"| 'disableRipple'\n>;\n\nexport interface TabProps extends Omit<PickMuiTabProps, 'value'> {\n value?: number | string;\n onChange?: () => void;\n children?: React.ReactNode;\n /**\n * Componente a renderizar (modo `nav`): ej. `Link` de react-router.\n * Junto con `to`/`href` convierte la tab en un enlace de navegación.\n */\n component?: React.ElementType;\n /** Destino de navegación (react-router `Link`). Solo en modo `nav`. */\n to?: string;\n /** Destino de navegación (ancla nativa). Solo en modo `nav`. */\n href?: string;\n /** Click handler (ej. para tabs de navegación sin router). */\n onClick?: () => void;\n}\n\nexport const Tab = (_: TabProps): null => null;\n\nTab.displayName = \"Tab\";\n\nexport default Tab;\n"],"names":["Children","isValidElement","_a","useState","Box","jsx","MuiTabs","mergeSx","MuiTab"],"mappings":"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"}
@@ -57,6 +57,8 @@ const Tabs = ({
57
57
  onChangeValue == null ? void 0 : onChangeValue(newValue);
58
58
  };
59
59
  const effectiveCentered = centered && variant !== "scrollable" && variant !== "fullWidth";
60
+ const hasPanels = tabs.some((tab) => tab.props.children != null);
61
+ const renderPanels = !nav && hasPanels;
60
62
  const { display, flexDirection } = TAB_DISPLAY_MAP[orientation];
61
63
  return /* @__PURE__ */ jsxs(Box, { sx: { display, flexDirection }, children: [
62
64
  /* @__PURE__ */ jsx(
@@ -105,7 +107,7 @@ const Tabs = ({
105
107
  })
106
108
  }
107
109
  ),
108
- !nav && /* @__PURE__ */ jsx(Box, { m: 2, sx: { width: "100%" }, children: keepMounted ? tabs.map((tab, idx) => {
110
+ renderPanels && /* @__PURE__ */ jsx(Box, { m: 2, sx: { width: "100%" }, children: keepMounted ? tabs.map((tab, idx) => {
109
111
  var _a2;
110
112
  const value = (_a2 = tab.props.value) != null ? _a2 : idx;
111
113
  const isActive = value === currentValue;
@@ -133,4 +135,4 @@ export {
133
135
  Tabs as T,
134
136
  Tab as a
135
137
  };
136
- //# sourceMappingURL=Tab-B1mpmXRC.js.map
138
+ //# sourceMappingURL=Tab-DycIMXmQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tab-DycIMXmQ.js","sources":["../src/components/Tabs/_tabUtils.tsx","../src/components/Tabs/Tabs.tsx","../src/components/Tabs/Tab.tsx"],"sourcesContent":["export const TAB_DISPLAY_MAP: Record<\"horizontal\" | \"vertical\", { display: string, flexDirection: string }> = {\n horizontal: { display: \"flex\", flexDirection: \"column\" },\n vertical: { display: \"flex\", flexDirection: \"row\" }\n};","import {\n Children,\n isValidElement,\n useState,\n type FC,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n} from 'react';\nimport {\n Tabs as MuiTabs,\n Tab as MuiTab,\n Box,\n type TabsProps as MuiTabsProps,\n} from '@mui/material';\n\nimport { TabProps } from './Tab';\nimport { TAB_DISPLAY_MAP } from './_tabUtils';\nimport { mergeSx } from '../_shared/mergeSx';\n\ntype PickTabsProps = Pick<\n MuiTabsProps,\n | 'centered'\n | 'indicatorColor'\n | 'orientation'\n | 'scrollButtons'\n | 'variant'\n | 'className'\n | 'sx'\n | 'visibleScrollbar'\n | 'allowScrollButtonsMobile'\n>;\n\nexport interface TabsProps extends PickTabsProps {\n /** Uno o varios `<Tab>`. Children que no sean `<Tab>` se ignoran. */\n children: ReactNode;\n /** Valor del tab inicialmente activo. Si no se provee, toma el `value` del primer `<Tab>` o `0`. */\n defaultValue?: number | string;\n /**\n * Valor activo **controlado**. Si se provee, el consumer maneja el estado\n * (típico en modo `nav`, donde el valor lo dicta la ruta). `false` = ningún\n * tab activo (ej. ruta que no corresponde a ninguna tab).\n */\n value?: number | string | false;\n /** Callback al cambiar de tab. Recibe el `value` del tab nuevo. */\n onChangeValue?: (newValue: number | string) => void;\n labelColor?: 'primary' | 'secondary' | 'inherit';\n /**\n * Modo **navegación**: las tabs son enlaces (`<Tab component={Link} to=.. />`),\n * el `value` activo es controlado externamente (por la ruta) y **no** se\n * renderizan paneles. `<Tab>` reenvía `component`/`to`/`href`/`onClick`.\n */\n nav?: boolean;\n /**\n * Cómo se manejan los paneles al cambiar de tab:\n * - `false` (default): **unmount** — solo se renderiza el panel activo; los\n * demás se desmontan. El state interno de los hijos se pierde al navegar.\n * Menor uso de memoria.\n * - `true`: **keep mounted** — renderiza todos los paneles pero oculta los\n * no activos con `display: none`. El state se preserva (inputs, scroll,\n * timers, subscripciones) al navegar entre tabs.\n */\n keepMounted?: boolean;\n}\n\nexport const Tabs: FC<TabsProps> = ({\n children,\n defaultValue,\n value: controlledValue,\n onChangeValue,\n centered = true,\n orientation = 'horizontal',\n scrollButtons = 'auto',\n variant = 'standard',\n indicatorColor = 'primary',\n labelColor = 'primary',\n className,\n allowScrollButtonsMobile = true,\n keepMounted = false,\n nav = false,\n sx,\n}) => {\n // Filtra a solo <Tab> children — acepta arrays, single child, fragments,\n // y descarta cualquier otra cosa (strings, null, condicionales falsy).\n const tabs: ReactElement<TabProps>[] = Children.toArray(children).filter(\n (child): child is ReactElement<TabProps> =>\n isValidElement(child) &&\n (child.type as { displayName?: string })?.displayName === 'Tab',\n );\n\n const firstValue = tabs[0]?.props.value;\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<string | number>(\n defaultValue ?? firstValue ?? 0,\n );\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const handleChange = (_event: SyntheticEvent, newValue: number | string) => {\n // En modo nav (o controlado) el consumer/ruta maneja el valor.\n if (!isControlled && !nav) setInternalValue(newValue);\n onChangeValue?.(newValue);\n };\n\n // MUI no permite `centered` con variant scrollable/fullWidth.\n const effectiveCentered =\n centered && variant !== 'scrollable' && variant !== 'fullWidth';\n\n // Si ningún `<Tab>` trae contenido (`children`), es una barra controlada y\n // los paneles los renderiza el consumer aparte — no generamos paneles vacíos.\n const hasPanels = tabs.some((tab) => tab.props.children != null);\n const renderPanels = !nav && hasPanels;\n\n const { display, flexDirection } = TAB_DISPLAY_MAP[orientation];\n\n return (\n <Box sx={{ display, flexDirection }}>\n <MuiTabs\n value={currentValue}\n onChange={handleChange}\n centered={effectiveCentered}\n indicatorColor={indicatorColor}\n orientation={orientation}\n scrollButtons={scrollButtons}\n variant={variant}\n className={className}\n textColor={labelColor}\n allowScrollButtonsMobile={allowScrollButtonsMobile}\n sx={mergeSx({}, sx)}\n >\n {tabs.map((tab, idx) => {\n const {\n label,\n icon,\n value = idx,\n disabled,\n wrapped,\n iconPosition,\n className: tabClassName,\n sx: tabSx,\n component,\n to,\n href,\n onClick,\n } = tab.props;\n return (\n <MuiTab\n key={value}\n label={label}\n icon={icon}\n value={value}\n disabled={disabled}\n wrapped={wrapped}\n iconPosition={iconPosition}\n className={tabClassName}\n sx={tabSx}\n // Modo nav: reenvía props de enlace/click.\n {...(component ? { component } : {})}\n {...(to ? { to } : {})}\n {...(href ? { href } : {})}\n {...(onClick ? { onClick } : {})}\n />\n );\n })}\n </MuiTabs>\n\n {renderPanels && (\n <Box m={2} sx={{ width: '100%' }}>\n {keepMounted\n ? tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n const isActive = value === currentValue;\n return (\n <Box\n key={value}\n role=\"tabpanel\"\n // `display: none` mantiene el nodo en el DOM — state de los\n // hijos (inputs, useState, etc.) no se pierde al navegar.\n sx={{ display: isActive ? 'block' : 'none' }}\n aria-hidden={!isActive}\n >\n {tab.props.children}\n </Box>\n );\n })\n : tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n if (value !== currentValue) return null;\n return (\n <Box key={value} role=\"tabpanel\">\n {tab.props.children}\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n );\n};\n\nexport default Tabs;\n","import React from \"react\";\nimport { TabProps as MuiTabProps } from \"@mui/material\";\n\ntype PickMuiTabProps = Pick<\n MuiTabProps,\n \"label\" | \"icon\" | \"disabled\" | \"sx\" | \"value\" | \"wrapped\" | \"iconPosition\" | \"className\" | \"disabled\"| 'disableRipple'\n>;\n\nexport interface TabProps extends Omit<PickMuiTabProps, 'value'> {\n value?: number | string;\n onChange?: () => void;\n children?: React.ReactNode;\n /**\n * Componente a renderizar (modo `nav`): ej. `Link` de react-router.\n * Junto con `to`/`href` convierte la tab en un enlace de navegación.\n */\n component?: React.ElementType;\n /** Destino de navegación (react-router `Link`). Solo en modo `nav`. */\n to?: string;\n /** Destino de navegación (ancla nativa). Solo en modo `nav`. */\n href?: string;\n /** Click handler (ej. para tabs de navegación sin router). */\n onClick?: () => void;\n}\n\nexport const Tab = (_: TabProps): null => null;\n\nTab.displayName = \"Tab\";\n\nexport default Tab;\n"],"names":["_a","MuiTabs","MuiTab"],"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 Tab = require("../../Tab-D-zNS5TI.cjs");
3
+ const Tab = require("../../Tab-D1S7kxXI.cjs");
4
4
  exports.Tab = Tab.Tab;
5
5
  exports.Tabs = Tab.Tabs;
6
6
  exports.default = Tab.Tabs;
@@ -8,9 +8,10 @@ export interface TabsProps extends PickTabsProps {
8
8
  defaultValue?: number | string;
9
9
  /**
10
10
  * Valor activo **controlado**. Si se provee, el consumer maneja el estado
11
- * (típico en modo `nav`, donde el valor lo dicta la ruta).
11
+ * (típico en modo `nav`, donde el valor lo dicta la ruta). `false` = ningún
12
+ * tab activo (ej. ruta que no corresponde a ninguna tab).
12
13
  */
13
- value?: number | string;
14
+ value?: number | string | false;
14
15
  /** Callback al cambiar de tab. Recibe el `value` del tab nuevo. */
15
16
  onChangeValue?: (newValue: number | string) => void;
16
17
  labelColor?: 'primary' | 'secondary' | 'inherit';
@@ -1,4 +1,4 @@
1
- import { a, T, T as T2 } from "../../Tab-B1mpmXRC.js";
1
+ import { a, T, T as T2 } from "../../Tab-DycIMXmQ.js";
2
2
  export {
3
3
  a as Tab,
4
4
  T as Tabs,
package/index.cjs CHANGED
@@ -15,7 +15,7 @@ const Divider = require("./Divider-CIY0JK4U.cjs");
15
15
  const ButtonGroup = require("./ButtonGroup-CNunDofQ.cjs");
16
16
  const Breadcrumbs = require("./Breadcrumbs-B9I3vxPb.cjs");
17
17
  const Step = require("./Step-Nd7SJbRZ.cjs");
18
- const Tab = require("./Tab-D-zNS5TI.cjs");
18
+ const Tab = require("./Tab-D1S7kxXI.cjs");
19
19
  const Table = require("./Table-C4OM6rrC.cjs");
20
20
  const StatusMessage = require("./StatusMessage-B3nXpuRl.cjs");
21
21
  const Modal = require("./Modal-D_6ZdSzw.cjs");
package/index.js CHANGED
@@ -13,7 +13,7 @@ import { D as D2 } from "./Divider-BApcM5CV.js";
13
13
  import { B as B2 } from "./ButtonGroup-CcKUZ-lT.js";
14
14
  import { B as B3 } from "./Breadcrumbs-C41SPbtX.js";
15
15
  import { a, S as S3 } from "./Step-BArsou1V.js";
16
- import { a as a2, T } from "./Tab-B1mpmXRC.js";
16
+ import { a as a2, T } from "./Tab-DycIMXmQ.js";
17
17
  import { T as T2 } from "./Table-C2LbW0B1.js";
18
18
  import { S as S4 } from "./StatusMessage-D0WgSBx7.js";
19
19
  import { M, b, c, a as a3 } from "./Modal-C_QY7ZzY.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soyfri/shared-library",
3
- "version": "2.0.0-beta.35",
3
+ "version": "2.0.0-beta.37",
4
4
  "main": "./index.cjs",
5
5
  "module": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -1 +0,0 @@
1
- {"version":3,"file":"Tab-B1mpmXRC.js","sources":["../src/components/Tabs/_tabUtils.tsx","../src/components/Tabs/Tabs.tsx","../src/components/Tabs/Tab.tsx"],"sourcesContent":["export const TAB_DISPLAY_MAP: Record<\"horizontal\" | \"vertical\", { display: string, flexDirection: string }> = {\n horizontal: { display: \"flex\", flexDirection: \"column\" },\n vertical: { display: \"flex\", flexDirection: \"row\" }\n};","import {\n Children,\n isValidElement,\n useState,\n type FC,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n} from 'react';\nimport {\n Tabs as MuiTabs,\n Tab as MuiTab,\n Box,\n type TabsProps as MuiTabsProps,\n} from '@mui/material';\n\nimport { TabProps } from './Tab';\nimport { TAB_DISPLAY_MAP } from './_tabUtils';\nimport { mergeSx } from '../_shared/mergeSx';\n\ntype PickTabsProps = Pick<\n MuiTabsProps,\n | 'centered'\n | 'indicatorColor'\n | 'orientation'\n | 'scrollButtons'\n | 'variant'\n | 'className'\n | 'sx'\n | 'visibleScrollbar'\n | 'allowScrollButtonsMobile'\n>;\n\nexport interface TabsProps extends PickTabsProps {\n /** Uno o varios `<Tab>`. Children que no sean `<Tab>` se ignoran. */\n children: ReactNode;\n /** Valor del tab inicialmente activo. Si no se provee, toma el `value` del primer `<Tab>` o `0`. */\n defaultValue?: number | string;\n /**\n * Valor activo **controlado**. Si se provee, el consumer maneja el estado\n * (típico en modo `nav`, donde el valor lo dicta la ruta).\n */\n value?: number | string;\n /** Callback al cambiar de tab. Recibe el `value` del tab nuevo. */\n onChangeValue?: (newValue: number | string) => void;\n labelColor?: 'primary' | 'secondary' | 'inherit';\n /**\n * Modo **navegación**: las tabs son enlaces (`<Tab component={Link} to=.. />`),\n * el `value` activo es controlado externamente (por la ruta) y **no** se\n * renderizan paneles. `<Tab>` reenvía `component`/`to`/`href`/`onClick`.\n */\n nav?: boolean;\n /**\n * Cómo se manejan los paneles al cambiar de tab:\n * - `false` (default): **unmount** — solo se renderiza el panel activo; los\n * demás se desmontan. El state interno de los hijos se pierde al navegar.\n * Menor uso de memoria.\n * - `true`: **keep mounted** — renderiza todos los paneles pero oculta los\n * no activos con `display: none`. El state se preserva (inputs, scroll,\n * timers, subscripciones) al navegar entre tabs.\n */\n keepMounted?: boolean;\n}\n\nexport const Tabs: FC<TabsProps> = ({\n children,\n defaultValue,\n value: controlledValue,\n onChangeValue,\n centered = true,\n orientation = 'horizontal',\n scrollButtons = 'auto',\n variant = 'standard',\n indicatorColor = 'primary',\n labelColor = 'primary',\n className,\n allowScrollButtonsMobile = true,\n keepMounted = false,\n nav = false,\n sx,\n}) => {\n // Filtra a solo <Tab> children — acepta arrays, single child, fragments,\n // y descarta cualquier otra cosa (strings, null, condicionales falsy).\n const tabs: ReactElement<TabProps>[] = Children.toArray(children).filter(\n (child): child is ReactElement<TabProps> =>\n isValidElement(child) &&\n (child.type as { displayName?: string })?.displayName === 'Tab',\n );\n\n const firstValue = tabs[0]?.props.value;\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<string | number>(\n defaultValue ?? firstValue ?? 0,\n );\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const handleChange = (_event: SyntheticEvent, newValue: number | string) => {\n // En modo nav (o controlado) el consumer/ruta maneja el valor.\n if (!isControlled && !nav) setInternalValue(newValue);\n onChangeValue?.(newValue);\n };\n\n // MUI no permite `centered` con variant scrollable/fullWidth.\n const effectiveCentered =\n centered && variant !== 'scrollable' && variant !== 'fullWidth';\n\n const { display, flexDirection } = TAB_DISPLAY_MAP[orientation];\n\n return (\n <Box sx={{ display, flexDirection }}>\n <MuiTabs\n value={currentValue}\n onChange={handleChange}\n centered={effectiveCentered}\n indicatorColor={indicatorColor}\n orientation={orientation}\n scrollButtons={scrollButtons}\n variant={variant}\n className={className}\n textColor={labelColor}\n allowScrollButtonsMobile={allowScrollButtonsMobile}\n sx={mergeSx({}, sx)}\n >\n {tabs.map((tab, idx) => {\n const {\n label,\n icon,\n value = idx,\n disabled,\n wrapped,\n iconPosition,\n className: tabClassName,\n sx: tabSx,\n component,\n to,\n href,\n onClick,\n } = tab.props;\n return (\n <MuiTab\n key={value}\n label={label}\n icon={icon}\n value={value}\n disabled={disabled}\n wrapped={wrapped}\n iconPosition={iconPosition}\n className={tabClassName}\n sx={tabSx}\n // Modo nav: reenvía props de enlace/click.\n {...(component ? { component } : {})}\n {...(to ? { to } : {})}\n {...(href ? { href } : {})}\n {...(onClick ? { onClick } : {})}\n />\n );\n })}\n </MuiTabs>\n\n {!nav && (\n <Box m={2} sx={{ width: '100%' }}>\n {keepMounted\n ? tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n const isActive = value === currentValue;\n return (\n <Box\n key={value}\n role=\"tabpanel\"\n // `display: none` mantiene el nodo en el DOM — state de los\n // hijos (inputs, useState, etc.) no se pierde al navegar.\n sx={{ display: isActive ? 'block' : 'none' }}\n aria-hidden={!isActive}\n >\n {tab.props.children}\n </Box>\n );\n })\n : tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n if (value !== currentValue) return null;\n return (\n <Box key={value} role=\"tabpanel\">\n {tab.props.children}\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n );\n};\n\nexport default Tabs;\n","import React from \"react\";\nimport { TabProps as MuiTabProps } from \"@mui/material\";\n\ntype PickMuiTabProps = Pick<\n MuiTabProps,\n \"label\" | \"icon\" | \"disabled\" | \"sx\" | \"value\" | \"wrapped\" | \"iconPosition\" | \"className\" | \"disabled\"| 'disableRipple'\n>;\n\nexport interface TabProps extends Omit<PickMuiTabProps, 'value'> {\n value?: number | string;\n onChange?: () => void;\n children?: React.ReactNode;\n /**\n * Componente a renderizar (modo `nav`): ej. `Link` de react-router.\n * Junto con `to`/`href` convierte la tab en un enlace de navegación.\n */\n component?: React.ElementType;\n /** Destino de navegación (react-router `Link`). Solo en modo `nav`. */\n to?: string;\n /** Destino de navegación (ancla nativa). Solo en modo `nav`. */\n href?: string;\n /** Click handler (ej. para tabs de navegación sin router). */\n onClick?: () => void;\n}\n\nexport const Tab = (_: TabProps): null => null;\n\nTab.displayName = \"Tab\";\n\nexport default Tab;\n"],"names":["_a","MuiTabs","MuiTab"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Tab-D-zNS5TI.cjs","sources":["../src/components/Tabs/_tabUtils.tsx","../src/components/Tabs/Tabs.tsx","../src/components/Tabs/Tab.tsx"],"sourcesContent":["export const TAB_DISPLAY_MAP: Record<\"horizontal\" | \"vertical\", { display: string, flexDirection: string }> = {\n horizontal: { display: \"flex\", flexDirection: \"column\" },\n vertical: { display: \"flex\", flexDirection: \"row\" }\n};","import {\n Children,\n isValidElement,\n useState,\n type FC,\n type ReactElement,\n type ReactNode,\n type SyntheticEvent,\n} from 'react';\nimport {\n Tabs as MuiTabs,\n Tab as MuiTab,\n Box,\n type TabsProps as MuiTabsProps,\n} from '@mui/material';\n\nimport { TabProps } from './Tab';\nimport { TAB_DISPLAY_MAP } from './_tabUtils';\nimport { mergeSx } from '../_shared/mergeSx';\n\ntype PickTabsProps = Pick<\n MuiTabsProps,\n | 'centered'\n | 'indicatorColor'\n | 'orientation'\n | 'scrollButtons'\n | 'variant'\n | 'className'\n | 'sx'\n | 'visibleScrollbar'\n | 'allowScrollButtonsMobile'\n>;\n\nexport interface TabsProps extends PickTabsProps {\n /** Uno o varios `<Tab>`. Children que no sean `<Tab>` se ignoran. */\n children: ReactNode;\n /** Valor del tab inicialmente activo. Si no se provee, toma el `value` del primer `<Tab>` o `0`. */\n defaultValue?: number | string;\n /**\n * Valor activo **controlado**. Si se provee, el consumer maneja el estado\n * (típico en modo `nav`, donde el valor lo dicta la ruta).\n */\n value?: number | string;\n /** Callback al cambiar de tab. Recibe el `value` del tab nuevo. */\n onChangeValue?: (newValue: number | string) => void;\n labelColor?: 'primary' | 'secondary' | 'inherit';\n /**\n * Modo **navegación**: las tabs son enlaces (`<Tab component={Link} to=.. />`),\n * el `value` activo es controlado externamente (por la ruta) y **no** se\n * renderizan paneles. `<Tab>` reenvía `component`/`to`/`href`/`onClick`.\n */\n nav?: boolean;\n /**\n * Cómo se manejan los paneles al cambiar de tab:\n * - `false` (default): **unmount** — solo se renderiza el panel activo; los\n * demás se desmontan. El state interno de los hijos se pierde al navegar.\n * Menor uso de memoria.\n * - `true`: **keep mounted** — renderiza todos los paneles pero oculta los\n * no activos con `display: none`. El state se preserva (inputs, scroll,\n * timers, subscripciones) al navegar entre tabs.\n */\n keepMounted?: boolean;\n}\n\nexport const Tabs: FC<TabsProps> = ({\n children,\n defaultValue,\n value: controlledValue,\n onChangeValue,\n centered = true,\n orientation = 'horizontal',\n scrollButtons = 'auto',\n variant = 'standard',\n indicatorColor = 'primary',\n labelColor = 'primary',\n className,\n allowScrollButtonsMobile = true,\n keepMounted = false,\n nav = false,\n sx,\n}) => {\n // Filtra a solo <Tab> children — acepta arrays, single child, fragments,\n // y descarta cualquier otra cosa (strings, null, condicionales falsy).\n const tabs: ReactElement<TabProps>[] = Children.toArray(children).filter(\n (child): child is ReactElement<TabProps> =>\n isValidElement(child) &&\n (child.type as { displayName?: string })?.displayName === 'Tab',\n );\n\n const firstValue = tabs[0]?.props.value;\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<string | number>(\n defaultValue ?? firstValue ?? 0,\n );\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const handleChange = (_event: SyntheticEvent, newValue: number | string) => {\n // En modo nav (o controlado) el consumer/ruta maneja el valor.\n if (!isControlled && !nav) setInternalValue(newValue);\n onChangeValue?.(newValue);\n };\n\n // MUI no permite `centered` con variant scrollable/fullWidth.\n const effectiveCentered =\n centered && variant !== 'scrollable' && variant !== 'fullWidth';\n\n const { display, flexDirection } = TAB_DISPLAY_MAP[orientation];\n\n return (\n <Box sx={{ display, flexDirection }}>\n <MuiTabs\n value={currentValue}\n onChange={handleChange}\n centered={effectiveCentered}\n indicatorColor={indicatorColor}\n orientation={orientation}\n scrollButtons={scrollButtons}\n variant={variant}\n className={className}\n textColor={labelColor}\n allowScrollButtonsMobile={allowScrollButtonsMobile}\n sx={mergeSx({}, sx)}\n >\n {tabs.map((tab, idx) => {\n const {\n label,\n icon,\n value = idx,\n disabled,\n wrapped,\n iconPosition,\n className: tabClassName,\n sx: tabSx,\n component,\n to,\n href,\n onClick,\n } = tab.props;\n return (\n <MuiTab\n key={value}\n label={label}\n icon={icon}\n value={value}\n disabled={disabled}\n wrapped={wrapped}\n iconPosition={iconPosition}\n className={tabClassName}\n sx={tabSx}\n // Modo nav: reenvía props de enlace/click.\n {...(component ? { component } : {})}\n {...(to ? { to } : {})}\n {...(href ? { href } : {})}\n {...(onClick ? { onClick } : {})}\n />\n );\n })}\n </MuiTabs>\n\n {!nav && (\n <Box m={2} sx={{ width: '100%' }}>\n {keepMounted\n ? tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n const isActive = value === currentValue;\n return (\n <Box\n key={value}\n role=\"tabpanel\"\n // `display: none` mantiene el nodo en el DOM — state de los\n // hijos (inputs, useState, etc.) no se pierde al navegar.\n sx={{ display: isActive ? 'block' : 'none' }}\n aria-hidden={!isActive}\n >\n {tab.props.children}\n </Box>\n );\n })\n : tabs.map((tab, idx) => {\n const value = tab.props.value ?? idx;\n if (value !== currentValue) return null;\n return (\n <Box key={value} role=\"tabpanel\">\n {tab.props.children}\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n );\n};\n\nexport default Tabs;\n","import React from \"react\";\nimport { TabProps as MuiTabProps } from \"@mui/material\";\n\ntype PickMuiTabProps = Pick<\n MuiTabProps,\n \"label\" | \"icon\" | \"disabled\" | \"sx\" | \"value\" | \"wrapped\" | \"iconPosition\" | \"className\" | \"disabled\"| 'disableRipple'\n>;\n\nexport interface TabProps extends Omit<PickMuiTabProps, 'value'> {\n value?: number | string;\n onChange?: () => void;\n children?: React.ReactNode;\n /**\n * Componente a renderizar (modo `nav`): ej. `Link` de react-router.\n * Junto con `to`/`href` convierte la tab en un enlace de navegación.\n */\n component?: React.ElementType;\n /** Destino de navegación (react-router `Link`). Solo en modo `nav`. */\n to?: string;\n /** Destino de navegación (ancla nativa). Solo en modo `nav`. */\n href?: string;\n /** Click handler (ej. para tabs de navegación sin router). */\n onClick?: () => void;\n}\n\nexport const Tab = (_: TabProps): null => null;\n\nTab.displayName = \"Tab\";\n\nexport default Tab;\n"],"names":["Children","isValidElement","_a","useState","Box","jsx","MuiTabs","mergeSx","MuiTab"],"mappings":"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"}