@zauru-sdk/components 6.2.28 → 6.3.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.
Files changed (98) hide show
  1. package/.ladle/components.tsx +30 -0
  2. package/.ladle/config.mjs +9 -0
  3. package/.ladle/vite.config.ts +23 -0
  4. package/CHANGELOG.md +14 -0
  5. package/PLAYGROUND.md +59 -0
  6. package/dist/Alerts/StaticAlert.d.ts +1 -1
  7. package/dist/Buttons/ActionList.d.ts +17 -0
  8. package/dist/Buttons/Button.d.ts +1 -1
  9. package/dist/Buttons/index.d.ts +1 -0
  10. package/dist/Containers/ButtonSectionContainer.d.ts +2 -0
  11. package/dist/Containers/Container.d.ts +3 -1
  12. package/dist/DynamicTable/GenericDynamicTable.d.ts +2 -0
  13. package/dist/Form/FileUpload/index.d.ts +1 -0
  14. package/dist/Form/FormLayout/index.d.ts +11 -0
  15. package/dist/Form/RadioButtonGroup/index.d.ts +1 -0
  16. package/dist/Form/SelectField/index.d.ts +4 -1
  17. package/dist/Form/index.d.ts +2 -0
  18. package/dist/Labels/SearchFiltersSummary.d.ts +12 -0
  19. package/dist/Labels/index.d.ts +1 -0
  20. package/dist/Layouts/errorLayout/index.d.ts +4 -1
  21. package/dist/NavBar/NavBar.d.ts +1 -1
  22. package/dist/NavBar/NavBar.types.d.ts +1 -0
  23. package/dist/Table/ZauruTable.d.ts +5 -0
  24. package/dist/Tooltip/Tooltip.d.ts +7 -0
  25. package/dist/Tooltip/index.d.ts +1 -0
  26. package/dist/WithTooltip/WithTooltip.d.ts +7 -0
  27. package/dist/WithTooltip/index.d.ts +1 -0
  28. package/dist/esm/Alerts/StaticAlert.js +6 -0
  29. package/dist/esm/BlockUI/BlockUI.js +1 -1
  30. package/dist/esm/Buttons/ActionList.js +8 -0
  31. package/dist/esm/Buttons/Button.js +5 -5
  32. package/dist/esm/Buttons/index.js +1 -0
  33. package/dist/esm/Containers/ButtonSectionContainer.js +2 -2
  34. package/dist/esm/Containers/Container.js +7 -2
  35. package/dist/esm/Containers/OutletContainer.js +1 -1
  36. package/dist/esm/DynamicTable/GenericDynamicTable.js +6 -3
  37. package/dist/esm/Footer/Footer.js +1 -1
  38. package/dist/esm/Form/FileUpload/index.js +2 -2
  39. package/dist/esm/Form/FormLayout/index.js +7 -0
  40. package/dist/esm/Form/RadioButtonGroup/index.js +1 -0
  41. package/dist/esm/Form/SelectField/index.js +16 -6
  42. package/dist/esm/Form/TextField/index.js +13 -3
  43. package/dist/esm/Form/index.js +2 -0
  44. package/dist/esm/Labels/SearchFiltersSummary.js +7 -0
  45. package/dist/esm/Labels/index.js +1 -0
  46. package/dist/esm/Layouts/errorLayout/index.js +9 -3
  47. package/dist/esm/Modal/ItemModal.js +7 -4
  48. package/dist/esm/NavBar/NavBar.js +8 -3
  49. package/dist/esm/Table/ZauruTable.js +67 -8
  50. package/dist/esm/Tooltip/Tooltip.js +14 -0
  51. package/dist/esm/Tooltip/index.js +1 -0
  52. package/dist/esm/WithTooltip/WithTooltip.js +5 -0
  53. package/dist/esm/WithTooltip/index.js +1 -0
  54. package/dist/esm/index.js +2 -0
  55. package/dist/index.d.ts +2 -0
  56. package/package.json +10 -3
  57. package/postcss.config.cjs +6 -0
  58. package/src/Alerts/StaticAlert.tsx +11 -1
  59. package/src/BlockUI/BlockUI.tsx +1 -1
  60. package/src/Buttons/ActionList.tsx +56 -0
  61. package/src/Buttons/Button.tsx +15 -9
  62. package/src/Buttons/index.ts +1 -0
  63. package/src/Containers/ButtonSectionContainer.tsx +4 -2
  64. package/src/Containers/Container.tsx +43 -13
  65. package/src/Containers/OutletContainer.tsx +1 -1
  66. package/src/DynamicTable/GenericDynamicTable.tsx +26 -9
  67. package/src/Footer/Footer.tsx +2 -1
  68. package/src/Form/FileUpload/index.tsx +3 -0
  69. package/src/Form/FormLayout/index.tsx +35 -0
  70. package/src/Form/RadioButtonGroup/index.tsx +4 -0
  71. package/src/Form/SelectField/index.tsx +44 -23
  72. package/src/Form/TextField/index.tsx +14 -1
  73. package/src/Form/index.ts +2 -0
  74. package/src/Labels/SearchFiltersSummary.tsx +34 -0
  75. package/src/Labels/index.tsx +1 -0
  76. package/src/Layouts/errorLayout/index.tsx +11 -2
  77. package/src/Modal/ItemModal.tsx +18 -5
  78. package/src/NavBar/NavBar.tsx +20 -2
  79. package/src/NavBar/NavBar.types.ts +1 -0
  80. package/src/Table/ZauruTable.tsx +83 -7
  81. package/src/Tooltip/Tooltip.tsx +42 -0
  82. package/src/Tooltip/index.ts +1 -0
  83. package/src/WithTooltip/WithTooltip.tsx +22 -0
  84. package/src/WithTooltip/index.tsx +1 -0
  85. package/src/index.ts +2 -0
  86. package/stories/Alerts.stories.tsx +17 -0
  87. package/stories/Button.stories.tsx +52 -0
  88. package/stories/Card.stories.tsx +7 -0
  89. package/stories/Container.stories.tsx +24 -0
  90. package/stories/Form.stories.tsx +58 -0
  91. package/stories/Labels.stories.tsx +17 -0
  92. package/stories/Modal.stories.tsx +21 -0
  93. package/stories/Tab.stories.tsx +10 -0
  94. package/stories/Table.stories.tsx +37 -0
  95. package/stories/Titles.stories.tsx +11 -0
  96. package/stories/Tooltip.stories.tsx +15 -0
  97. package/tailwind.config.cjs +12 -0
  98. package/tsconfig.json +1 -0
@@ -0,0 +1,30 @@
1
+ import type { ReactNode } from "react";
2
+ import { FormProvider, useForm } from "react-hook-form";
3
+ import { Provider as ReduxProvider } from "react-redux";
4
+ import { configureStore } from "@reduxjs/toolkit";
5
+ import { MemoryRouter } from "react-router-dom";
6
+ import "../src/tailwind.css";
7
+
8
+ const playgroundStore = configureStore({
9
+ reducer: {
10
+ formValidation: (
11
+ state = { formValidations: {} as Record<string, unknown> }
12
+ ) => state,
13
+ },
14
+ });
15
+
16
+ export const Provider = ({ children }: { children: ReactNode }) => {
17
+ const methods = useForm({ mode: "onChange" });
18
+
19
+ return (
20
+ <ReduxProvider store={playgroundStore}>
21
+ <FormProvider {...methods}>
22
+ <MemoryRouter>
23
+ <div className="min-h-screen bg-gray-50 p-6 text-gray-900">
24
+ {children}
25
+ </div>
26
+ </MemoryRouter>
27
+ </FormProvider>
28
+ </ReduxProvider>
29
+ );
30
+ };
@@ -0,0 +1,9 @@
1
+ /** @type {import('@ladle/react').UserConfig} */
2
+ export default {
3
+ stories: "stories/**/*.stories.{js,jsx,ts,tsx}",
4
+ port: 61000,
5
+ viteConfig: ".ladle/vite.config.ts",
6
+ addons: {
7
+ a11y: { enabled: true },
8
+ },
9
+ };
@@ -0,0 +1,23 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { defineConfig } from "vite";
4
+
5
+ const ladleDir = fileURLToPath(new URL(".", import.meta.url));
6
+ const webapp = path.resolve(ladleDir, "../..");
7
+
8
+ export default defineConfig({
9
+ resolve: {
10
+ dedupe: ["react", "react-dom"],
11
+ alias: {
12
+ "@zauru-sdk/icons": path.resolve(webapp, "icons/src/index.ts"),
13
+ "@zauru-sdk/common": path.resolve(webapp, "common/src/index.ts"),
14
+ "@zauru-sdk/types": path.resolve(webapp, "types/src/index.ts"),
15
+ "@zauru-sdk/redux": path.resolve(webapp, "redux/src/index.ts"),
16
+ "@zauru-sdk/hooks": path.resolve(webapp, "hooks/src/index.ts"),
17
+ "@zauru-sdk/utils": path.resolve(webapp, "utils/src/index.ts"),
18
+ "@zauru-sdk/graphql": path.resolve(webapp, "graphql/src/index.ts"),
19
+ "@zauru-sdk/services": path.resolve(webapp, "services/src/index.ts"),
20
+ "@zauru-sdk/config": path.resolve(webapp, "config/src/index.ts"),
21
+ },
22
+ },
23
+ });
package/CHANGELOG.md CHANGED
@@ -3,6 +3,20 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [6.3.0](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.2.28...@zauru-sdk/components@6.3.0) (2026-09-14)
7
+
8
+
9
+ ### Features
10
+
11
+ * agregar ActionList y SearchFiltersSummary genéricos ([775d986](https://github.com/intuitiva/zauru-typescript-sdk/commit/775d986cf06aeefd7a4269947ab96280ea167314))
12
+ * agregar playground Ladle para los componentes webapp ([a616a77](https://github.com/intuitiva/zauru-typescript-sdk/commit/a616a77484f02ef71f5b6ff96ad6d6e98f789cb5))
13
+ * mostrar títulos de tabla completos y scroll interno al expandir ([b62a253](https://github.com/intuitiva/zauru-typescript-sdk/commit/b62a253a3a5d8879572f9db00b2a86737b8886cc))
14
+ * unificar componentes webapp con las copias remix-* ([714274a](https://github.com/intuitiva/zauru-typescript-sdk/commit/714274abd5ccc5e77affa3da41787b381c47de5f))
15
+
16
+
17
+
18
+
19
+
6
20
  ## [6.2.28](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.2.27...@zauru-sdk/components@6.2.28) (2026-09-14)
7
21
 
8
22
  **Note:** Version bump only for package @zauru-sdk/components
package/PLAYGROUND.md ADDED
@@ -0,0 +1,59 @@
1
+ # Playground de `@zauru-sdk/components`
2
+
3
+ Taller visual de los componentes Remix/Tailwind de Zauru. Usa [Ladle](https://www.ladle.dev) (Vite + formato CSF) en lugar de Storybook: arranque más liviano para verificar UI en aislamiento. Las stories se pueden reusar si más adelante se pasa a Storybook.
4
+
5
+ ## Requisitos
6
+
7
+ - Node >= 18
8
+ - pnpm >= 9
9
+ - Dependencias del monorepo instaladas (`pnpm install` en la raíz de `zauru-typescript-sdk`)
10
+
11
+ ## Arrancar
12
+
13
+ Desde la raíz del SDK:
14
+
15
+ ```bash
16
+ pnpm components:play
17
+ ```
18
+
19
+ O desde este paquete:
20
+
21
+ ```bash
22
+ pnpm --filter @zauru-sdk/components play
23
+ ```
24
+
25
+ Abre [http://localhost:61000](http://localhost:61000). El menú a la izquierda lista las stories.
26
+
27
+ ## Qué cubre
28
+
29
+ Stories en `stories/`:
30
+
31
+ - Button (colores, loading, disabled, dropdown)
32
+ - Container (header, colapsable)
33
+ - Form (TextField, SelectField, Checkbox, DatePicker, FileUpload, FormLayout, RadioButtonGroup)
34
+ - Tooltip / WithTooltip
35
+ - ProgressModal
36
+ - GenericDynamicTable y ZauruTable
37
+ - Títulos, StaticAlert, Card, Tabs
38
+
39
+ Los componentes atados a sesión Zauru (`HomeLayout`, `Zendesk`, `ValidateEmployeeAccess`) no tienen story: requieren la webapp host.
40
+
41
+ El playground envuelve cada story con:
42
+
43
+ - `react-hook-form` (`FormProvider`)
44
+ - Redux (store mínimo para `useAppSelector`)
45
+ - `MemoryRouter` de React Router 6 (el mismo que usa Remix 2) para `Link`, `Form` y `useSearchParams`
46
+
47
+ ## Build estático
48
+
49
+ ```bash
50
+ pnpm --filter @zauru-sdk/components play:build
51
+ ```
52
+
53
+ Sale a `build/` (no se publica en npm). Para previsualizar: `pnpm --filter @zauru-sdk/components exec ladle preview`.
54
+
55
+ ## Notas
56
+
57
+ - Tailwind se procesa solo para este playground (`tailwind.config.cjs` + `postcss.config.cjs`). Las webapps siguen usando su propio Tailwind.
58
+ - Las stories viven fuera de `src/` para que `tsc` no las compile al `dist` del paquete.
59
+ - Vite alias `@zauru-sdk/*` a los `src` de los paquetes hermanos (el `dist` ESM del monorepo no exporta named ESM que Vite pueda resolver).
@@ -4,7 +4,7 @@ type Props = {
4
4
  description: any;
5
5
  showCloseButton?: boolean;
6
6
  onClose?: () => void;
7
- type?: "success" | "info";
7
+ type?: "success" | "info" | "warning";
8
8
  loading?: boolean;
9
9
  };
10
10
  export declare const StaticAlert: (props: Props) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ export type ActionListItem = {
2
+ key: string;
3
+ label: string;
4
+ loadingLabel?: string;
5
+ loading?: boolean;
6
+ badge?: string;
7
+ badgeClassName?: string;
8
+ disabled?: boolean;
9
+ onClick: () => void;
10
+ };
11
+ type ActionListProps = {
12
+ items: ActionListItem[];
13
+ disabled?: boolean;
14
+ className?: string;
15
+ };
16
+ export declare const ActionList: ({ items, disabled, className, }: ActionListProps) => import("react/jsx-runtime").JSX.Element;
17
+ export {};
@@ -1,4 +1,4 @@
1
- type DropdownOption = {
1
+ export type DropdownOption = {
2
2
  label: string;
3
3
  value: string;
4
4
  onClick: () => void;
@@ -1 +1,2 @@
1
1
  export * from "./Button.js";
2
+ export * from "./ActionList.js";
@@ -2,6 +2,8 @@ import React from "react";
2
2
  type Props = {
3
3
  children: React.ReactNode;
4
4
  className?: string;
5
+ /** Fondo gris de pie de formulario. El nombre `whitBg` se conserva por compatibilidad con las webapps. */
6
+ whitBg?: boolean;
5
7
  };
6
8
  export declare const ButtonSectionContainer: (props: Props) => import("react/jsx-runtime").JSX.Element;
7
9
  export {};
@@ -1,10 +1,12 @@
1
1
  import React from "react";
2
2
  type Props = {
3
- title?: string;
3
+ title?: React.ReactNode;
4
4
  description?: string;
5
5
  children: React.ReactNode;
6
6
  className?: string;
7
7
  rightContent?: React.ReactNode;
8
+ collapsible?: boolean;
9
+ defaultOpen?: boolean;
8
10
  };
9
11
  export declare const Container: (props: Props) => import("react/jsx-runtime").JSX.Element;
10
12
  export {};
@@ -40,6 +40,8 @@ type Props = {
40
40
  * es decir, sin permitir ningún tipo de interacción de edición o eliminación.
41
41
  */
42
42
  readOnly?: boolean;
43
+ /** Contenido extra debajo de cada fila (p. ej. un resumen). */
44
+ rowSummary?: (rowData: RowDataType) => React.ReactNode;
43
45
  };
44
46
  /**
45
47
  *
@@ -17,6 +17,7 @@ type Props = {
17
17
  zauruBaseURL?: string;
18
18
  setProcessing?: (processing: boolean) => void;
19
19
  signature?: boolean;
20
+ capture?: "user" | "environment";
20
21
  };
21
22
  export declare const FileUploadField: (props: Props) => import("react/jsx-runtime").JSX.Element;
22
23
  export {};
@@ -0,0 +1,11 @@
1
+ import { type FormMethod } from "@remix-run/react";
2
+ import { type ReactNode } from "react";
3
+ type Props = {
4
+ formId: string;
5
+ title?: string;
6
+ children: ReactNode;
7
+ buttons?: ReactNode;
8
+ method?: FormMethod;
9
+ };
10
+ export declare const FormLayout: (props: Props) => import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1 @@
1
+ export { RadioButton as RadioButtonGroup, RadioButton as RadioButtonGroupWithoutValidation, } from "../RadioButton/index.js";
@@ -6,7 +6,10 @@ type Props = {
6
6
  defaultValue?: SelectFieldOption;
7
7
  defaultValueMulti?: SelectFieldOption[];
8
8
  helpText?: string;
9
- options: Array<SelectFieldOption>;
9
+ options: Array<SelectFieldOption & {
10
+ disabled?: boolean;
11
+ disabledLabel?: string;
12
+ }>;
10
13
  onChange?: (value: SelectFieldOption | null) => void;
11
14
  onChangeMulti?: (value: SelectFieldOption[]) => void;
12
15
  onInputChange?: (newValue: string) => void;
@@ -5,6 +5,7 @@ export * from "./DynamicBaculoForm/index.js";
5
5
  export * from "./FieldContainer/index.js";
6
6
  export * from "./FileUpload/index.js";
7
7
  export * from "./FormButtons/index.js";
8
+ export * from "./FormLayout/index.js";
8
9
  export * from "./SelectField/index.js";
9
10
  export * from "./TextArea/index.js";
10
11
  export * from "./TextField/index.js";
@@ -12,3 +13,4 @@ export * from "./TimePicker/index.js";
12
13
  export * from "./YesNo/index.js";
13
14
  export * from "./ReactZodForm/index.js";
14
15
  export * from "./RadioButton/index.js";
16
+ export * from "./RadioButtonGroup/index.js";
@@ -0,0 +1,12 @@
1
+ export type SearchFilterItem = {
2
+ key: string;
3
+ label: string;
4
+ value: string;
5
+ };
6
+ type Props = {
7
+ items?: SearchFilterItem[];
8
+ emptyText?: string;
9
+ className?: string;
10
+ };
11
+ export declare const SearchFiltersSummary: ({ items, emptyText, className, }: Props) => import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -1 +1,2 @@
1
1
  export * from "./InfoLabel/index.js";
2
+ export * from "./SearchFiltersSummary.js";
@@ -1,5 +1,8 @@
1
- export declare const ErrorLayout: ({ from, isRootLevel, error: parentError, }: {
1
+ export declare const ErrorLayout: ({ from, isRootLevel, error: parentError, onError, }: {
2
2
  from?: string;
3
3
  isRootLevel?: boolean;
4
4
  error?: Error;
5
+ onError?: (error: Error, meta: {
6
+ from?: string;
7
+ }) => void;
5
8
  }) => import("react/jsx-runtime").JSX.Element | null;
@@ -1,2 +1,2 @@
1
1
  import type { NavBarProps } from "./NavBar.types.js";
2
- export declare const NavBar: ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, }: NavBarProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const NavBar: ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, showDarkModeToggle, }: NavBarProps) => import("react/jsx-runtime").JSX.Element;
@@ -17,6 +17,7 @@ export type NavBarProps = {
17
17
  LinkComponent?: any;
18
18
  version?: string;
19
19
  reloadCatalogsOption?: boolean;
20
+ showDarkModeToggle?: boolean;
20
21
  };
21
22
  export type NavBarStateProps = {
22
23
  NavBarOpen: boolean;
@@ -1,4 +1,5 @@
1
1
  import type { TableProps } from "react-data-table-component";
2
+ import { ExpandableRowsComponent } from "react-data-table-component/dist/DataTable/types.js";
2
3
  type Props = TableProps<any> & {
3
4
  columns: any;
4
5
  conditionalRowStyles?: any;
@@ -13,6 +14,10 @@ type Props = TableProps<any> & {
13
14
  search?: {
14
15
  placeholderSearch?: string;
15
16
  };
17
+ expandable?: {
18
+ expandableRowExpanded?: (row: any) => boolean;
19
+ expandableRowsComponent?: ExpandableRowsComponent<any>;
20
+ };
16
21
  theme?: "solarized" | "subTable";
17
22
  className?: string;
18
23
  };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ type Props = {
3
+ children: React.ReactNode;
4
+ text: string;
5
+ };
6
+ export declare const Tooltip: ({ children, text }: Props) => import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1 @@
1
+ export * from "./Tooltip.js";
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ type Props = {
3
+ children: React.ReactNode;
4
+ text: string;
5
+ };
6
+ export declare const WithTooltip: (props: Props) => import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1 @@
1
+ export * from "./WithTooltip.js";
@@ -13,6 +13,12 @@ const getConfig = (type) => {
13
13
  buttonClassName: "rounded-md focus:outline-none focus:ring-2 focus:ring-green-500",
14
14
  path: (_jsx("path", { d: "M8.445 12.6675A.9.9 0 0 0 7.1424 13.91l2.5726 2.7448c.3679.3856.9884.3689 1.335-.036l5.591-7.0366a.9.9 0 0 0-1.3674-1.1705l-4.6548 5.9132a.4.4 0 0 1-.607.0252l-1.567-1.6826zM1.9995 12c0-5.5 4.5-10 10-10s10 4.5 10 10-4.5 10-10 10-10-4.5-10-10z" })),
15
15
  };
16
+ case "warning":
17
+ return {
18
+ containerClassName: "text-yellow-900 bg-yellow-100 border border-yellow-200 rounded-md",
19
+ buttonClassName: "rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500",
20
+ path: (_jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm.93 14.93h-1.86c-.41 0-.75-.34-.75-.75s.34-.75.75-.75h1.86c.41 0 .75.34.75.75s-.34.75-.75.75zm.57-4.42l-.57 2.36h-1.86l-.57-2.36c-.13-.54.21-1.08.76-1.08h1.48c.55 0 .88.54.76 1.08zm0-2.36h-2.58c-.55 0-.88-.54-.76-1.08l.57-2.36h1.86l.57 2.36c.12.54-.21 1.08-.76 1.08z" })),
21
+ };
16
22
  default:
17
23
  return {
18
24
  containerClassName: "text-blue-900 bg-blue-100 border border-blue-200 rounded-md",
@@ -4,5 +4,5 @@ export const BlockUI = (props) => {
4
4
  if (!active) {
5
5
  return _jsx(_Fragment, { children: children });
6
6
  }
7
- return (_jsx("div", { children: _jsxs("div", { className: "relative", children: [_jsx("div", { className: "absolute bg-gray-100 bg-opacity-80 z-10 h-full w-full flex items-center justify-center", children: _jsxs("div", { className: "flex items-center", children: [_jsx("span", { className: "text-3xl mr-4", children: loadingText }), _jsxs("svg", { className: "animate-spin h-36 w-36 text-gray-600", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] })] }) }), children] }) }));
7
+ return (_jsx("div", { children: _jsxs("div", { className: "relative", children: [_jsx("div", { className: "absolute bg-gray-100 bg-opacity-80 z-10 h-full w-full flex items-center justify-center", children: _jsxs("div", { className: "flex items-center", children: [_jsx("span", { className: "text-3xl mr-4", children: loadingText }), _jsxs("svg", { className: "animate-spin h-5 w-5 text-gray-600", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] })] }) }), children] }) }));
8
8
  };
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export const ActionList = ({ items, disabled = false, className = "", }) => {
3
+ return (_jsx("div", { className: `flex flex-col gap-1 ${className}`, children: items.map((item) => {
4
+ const itemBusy = Boolean(item.loading);
5
+ const itemDisabled = disabled || item.disabled || itemBusy;
6
+ return (_jsxs("button", { type: "button", disabled: itemDisabled, onClick: item.onClick, className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-1 disabled:cursor-progress disabled:opacity-60", children: [item.badge ? (_jsx("span", { className: `inline-flex min-w-[2.25rem] justify-center rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${item.badgeClassName ?? "bg-gray-100 text-gray-700"}`, children: item.badge })) : null, _jsx("span", { children: itemBusy ? (item.loadingLabel ?? item.label) : item.label })] }, item.key));
7
+ }) }));
8
+ };
@@ -80,19 +80,19 @@ export const Button = (props) => {
80
80
  if (!hasDropdown) {
81
81
  const buttonContent = (_jsx("button", { type: type, name: "action", value: name, disabled: isButtonDisabled, onClick: onClickSave, className: `${isButtonDisabled ? " bg-opacity-25 " : ""} ${loading
82
82
  ? " cursor-progress"
83
- : `${isButtonDisabled ? "" : `hover:${color.bg700}`}`} inline-flex justify-center rounded-md border border-transparent ${color.bg600} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${color.ring500} focus:ring-offset-2 ${className}`, children: loading ? children ?? loadingText : children ?? title }));
83
+ : `${isButtonDisabled ? " cursor-not-allowed" : `cursor-pointer hover:${color.bg700}`}`} inline-flex justify-center rounded-md border border-transparent ${color.bg600} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${color.ring500} focus:ring-offset-2 ${className}`, children: loading ? children ?? loadingText : children ?? title }));
84
84
  return (_jsxs(_Fragment, { children: [(enableFormErrorsValidation && formHasErrors && errorMessage) ||
85
85
  (enableFormErrorsDescriptions && errorMessage) ? (_jsx("div", { className: "flex flex-col items-end mb-2", children: _jsx("div", { className: "p-2 bg-red-100 border border-red-400 text-red-700 rounded-md shadow-sm", children: _jsx("p", { className: "text-sm", children: errorMessage }) }) })) : null, buttonContent] }));
86
86
  }
87
87
  // Comportamiento con dropdown
88
- const dropdownContent = (_jsxs("div", { className: "relative inline-block text-left", ref: dropdownRef, children: [_jsx("div", { children: _jsxs("button", { type: "button", disabled: isButtonDisabled, onClick: () => setIsDropdownOpen(!isDropdownOpen), className: `${isButtonDisabled ? " bg-opacity-25 " : ""} ${loading
88
+ const dropdownContent = (_jsxs("div", { className: "relative inline-block text-left", ref: dropdownRef, children: [_jsx("div", { children: _jsxs("button", { type: "button", disabled: isButtonDisabled, "aria-haspopup": "menu", "aria-expanded": isDropdownOpen, onClick: () => setIsDropdownOpen(!isDropdownOpen), className: `${isButtonDisabled ? " bg-opacity-25 " : ""} ${loading
89
89
  ? " cursor-progress"
90
- : `${isButtonDisabled ? "" : `hover:${color.bg700}`}`} inline-flex justify-center items-center rounded-md border border-transparent ${color.bg600} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${color.ring500} focus:ring-offset-2 ${className}`, children: [loading
90
+ : `${isButtonDisabled ? " cursor-not-allowed" : `cursor-pointer hover:${color.bg700}`}`} inline-flex justify-center items-center rounded-md border border-transparent ${color.bg600} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${color.ring500} focus:ring-offset-2 ${className}`, children: [loading
91
91
  ? children ?? loadingText
92
- : children ?? dropdownTitle ?? title, _jsx("svg", { className: `ml-2 -mr-1 h-4 w-4 transition-transform ${isDropdownOpen ? "rotate-180" : ""}`, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", clipRule: "evenodd" }) })] }) }), isDropdownOpen && (_jsx("div", { className: "absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none", children: _jsx("div", { className: "py-1", children: dropdownOptions.map((option, index) => (_jsx("button", { type: "button", onClick: () => {
92
+ : children ?? dropdownTitle ?? title, _jsx("svg", { className: `ml-2 -mr-1 h-4 w-4 transition-transform ${isDropdownOpen ? "rotate-180" : ""}`, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", clipRule: "evenodd" }) })] }) }), isDropdownOpen && !isButtonDisabled ? (_jsx("div", { role: "menu", className: "absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none", children: _jsx("div", { className: "py-1", children: dropdownOptions.map((option) => (_jsx("button", { type: "button", role: "menuitem", onClick: () => {
93
93
  option.onClick();
94
94
  setIsDropdownOpen(false);
95
- }, className: "block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 text-left", children: option.label }, index))) }) }))] }));
95
+ }, className: "block w-full cursor-pointer px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 text-left", children: option.label }, option.value))) }) })) : null] }));
96
96
  return (_jsxs(_Fragment, { children: [(enableFormErrorsValidation && formHasErrors && errorMessage) ||
97
97
  (enableFormErrorsDescriptions && errorMessage) ? (_jsx("div", { className: "flex flex-col items-end mb-2", children: _jsx("div", { className: "p-2 bg-red-100 border border-red-400 text-red-700 rounded-md shadow-sm", children: _jsx("p", { className: "text-sm", children: errorMessage }) }) })) : null, dropdownContent] }));
98
98
  };
@@ -1 +1,2 @@
1
1
  export * from "./Button.js";
2
+ export * from "./ActionList.js";
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  export const ButtonSectionContainer = (props) => {
3
- const { children, className } = props;
4
- return (_jsx("div", { className: `mt-5 flex flex-col md:flex-row md:justify-end md:items-center space-x-0 space-y-4 md:space-y-0 md:space-x-4 ${className}`, children: children }));
3
+ const { children, className, whitBg = false } = props;
4
+ return (_jsx("div", { className: `${whitBg ? "bg-gray-50 px-4 py-3 sm:px-6" : ""} mt-5 flex flex-col md:flex-row md:justify-end md:items-center space-x-0 space-y-4 md:space-y-0 md:space-x-4 ${className}`, children: children }));
5
5
  };
@@ -1,6 +1,11 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  export const Container = (props) => {
3
- const { title, description, children, className = "", rightContent } = props;
3
+ const { title, description, children, className = "", rightContent, collapsible = false, defaultOpen = true, } = props;
4
4
  const titleInfo = (_jsxs(_Fragment, { children: [title && (_jsx("h3", { className: "text-3xl font-bold leading-8 text-gray-900", children: title })), description && (_jsx("p", { className: "mt-1 text-md text-gray-600", children: description }))] }));
5
- return (_jsx(_Fragment, { children: _jsxs("div", { className: `mx-2 ${className}`, children: [rightContent && (_jsxs("div", { className: "flex flex-col sm:flex-row sm:justify-between sm:items-start gap-4", children: [_jsx("div", { className: "max-w-3xl", children: titleInfo }), _jsx("div", { className: "flex-shrink-0", children: rightContent })] })), !rightContent && titleInfo, _jsx("div", { className: "mt-5 space-y-5", children: children })] }) }));
5
+ const header = rightContent ? (_jsxs("div", { className: "flex flex-col sm:flex-row sm:justify-between sm:items-start gap-4", children: [_jsx("div", { className: "max-w-3xl", children: titleInfo }), _jsx("div", { className: "flex-shrink-0", children: rightContent })] })) : (titleInfo);
6
+ const body = _jsx("div", { className: "mt-5 space-y-5", children: children });
7
+ if (collapsible) {
8
+ return (_jsx("div", { className: `mx-2 ${className}`, children: _jsxs("details", { className: "group", ...(defaultOpen ? { open: true } : {}), children: [_jsxs("summary", { className: "flex cursor-pointer list-none items-start gap-3 rounded-md py-1 focus:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 focus-visible:ring-offset-2 [&::-webkit-details-marker]:hidden", children: [_jsx("span", { "aria-hidden": "true", className: "mt-2 inline-block h-0 w-0 shrink-0 border-y-[5px] border-l-[7px] border-y-transparent border-l-gray-700 transition-transform group-open:rotate-90" }), _jsx("div", { className: "min-w-0 flex-1", children: header })] }), body] }) }));
9
+ }
10
+ return (_jsxs("div", { className: `mx-2 ${className}`, children: [header, body] }));
6
11
  };
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  export const OutletContainer = (props) => {
3
3
  const { children } = props;
4
- return (_jsx("div", { className: "flex-1 overflow-x-auto", suppressHydrationWarning: true, children: children }));
4
+ return (_jsx("div", { className: "min-w-0 flex-1 overflow-x-auto", suppressHydrationWarning: true, children: children }));
5
5
  };
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
2
+ import React, { useEffect, useState } from "react";
3
3
  import { SelectField } from "../Form/SelectField/index.js";
4
4
  import { TextField } from "../Form/TextField/index.js";
5
5
  import { CheckBox } from "../Form/Checkbox/index.js";
@@ -97,7 +97,7 @@ const GenericDynamicTableErrorComponent = ({ name }) => {
97
97
  */
98
98
  export const GenericDynamicTable = (props) => {
99
99
  const { columns, onChange, className, footerRow, defaultValue = [], thCSSProperties, thElementsClassName = "", editable = true, readOnly = false, // Nuevo prop
100
- searcheables = [], loading = false, paginated = true, defaultItemsPerPage = 10, itemsPerPageOptions = [10, 50, 100], name, withoutBg = false, orientation = "horizontal", maxRows, confirmDelete = true, addRowButtonHandler, } = props;
100
+ searcheables = [], loading = false, paginated = true, defaultItemsPerPage = 10, itemsPerPageOptions = [10, 50, 100], name, withoutBg = false, orientation = "horizontal", maxRows, confirmDelete = true, addRowButtonHandler, rowSummary, } = props;
101
101
  /**
102
102
  * Definimos una variable interna para saber si los campos son
103
103
  * efectivamente editables: solo si `editable` es true y `readOnly` es false.
@@ -185,7 +185,10 @@ export const GenericDynamicTable = (props) => {
185
185
  const renderRow = (rowData, index) => {
186
186
  const rendereableColumns = columns.filter((column) => column.type !== "hidden");
187
187
  if (orientation === "horizontal") {
188
- return (_jsxs("tr", { className: index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "", children: [rendereableColumns.map((column) => renderCell(rowData, column)), isEditable && renderDeleteButton(rowData)] }, rowData.id));
188
+ const rowClassName = index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "";
189
+ const summaryColSpan = rendereableColumns.length + (isEditable ? 1 : 0);
190
+ const summaryContent = rowSummary?.(rowData);
191
+ return (_jsxs(React.Fragment, { children: [_jsxs("tr", { className: rowClassName, children: [rendereableColumns.map((column) => renderCell(rowData, column)), isEditable && renderDeleteButton(rowData)] }), summaryContent ? (_jsx("tr", { className: rowClassName, children: _jsxs("td", { colSpan: summaryColSpan, className: "px-2 pb-3 pt-0 text-sm text-gray-700 border-b border-gray-300", children: [_jsx("span", { className: "font-medium text-gray-500", children: "Resumen: " }), summaryContent] }) })) : null] }, rowData.id));
189
192
  }
190
193
  else {
191
194
  // Orientación vertical
@@ -13,5 +13,5 @@ const COLORS = {
13
13
  };
14
14
  export const Footer = ({ href, selectedColor, showConnection = false, version = "2.0.5", }) => {
15
15
  const color = COLORS[selectedColor];
16
- return (_jsx("footer", { className: `inset-x-0 bottom-0 px-2 py-[20px] ${color}`, children: _jsxs("div", { className: "px-4 mx-auto flex flex-wrap items-center justify-center", children: [_jsxs("p", { className: "text-white text-[1.2rem]", children: [`Creado en `, " ", _jsx("a", { href: href, children: "Zauru" }), " ", `con ❤️ v.${version}`] }), showConnection && (_jsx("div", { className: "ml-5", children: _jsx(ConnectionState, {}) }))] }) }));
16
+ return (_jsx("footer", { className: `inset-x-0 bottom-0 px-2 py-[20px] ${color}`, children: _jsxs("div", { className: "px-4 mx-auto flex flex-wrap items-center justify-center", children: [_jsxs("p", { className: "text-white text-[1.2rem]", children: [`Creado en `, " ", _jsx("a", { href: href, children: "Zauru" }), " ", `con ❤️ ${new Date().getFullYear()} v.${version}`] }), showConnection && (_jsx("div", { className: "ml-5", children: _jsx(ConnectionState, {}) }))] }) }));
17
17
  };
@@ -4,7 +4,7 @@ import { useState, useEffect, useRef } from "react";
4
4
  import { useFormContext } from "react-hook-form";
5
5
  import { Button } from "../../Buttons/index.js";
6
6
  export const FileUploadField = (props) => {
7
- const { id, name, title, helpText, hint, onChange, readOnly = false, fileTypes = [], showAvailableTypes = false, className, defaultValue, download = false, required = false, optimizeImages = true, zauruBaseURL = "https://zauru.herokuapp.com", setProcessing, signature = false, } = props;
7
+ const { id, name, title, helpText, hint, onChange, readOnly = false, fileTypes = [], showAvailableTypes = false, className, defaultValue, download = false, required = false, optimizeImages = true, zauruBaseURL = "https://zauru.herokuapp.com", setProcessing, signature = false, capture, } = props;
8
8
  const { register: tempRegister, setValue, formState: { errors }, } = useFormContext() || { formState: {} };
9
9
  const error = errors ? errors[name] : undefined;
10
10
  const register = tempRegister ? tempRegister(name, { required }) : undefined;
@@ -285,5 +285,5 @@ export const FileUploadField = (props) => {
285
285
  }, className: "cursor-pointer border border-gray-300 h-48 w-48 flex items-center justify-center", children: previewSrc || (typeof defaultValue === "string" && defaultValue) ? (_jsx("img", { src: previewSrc ??
286
286
  (typeof defaultValue === "string" && defaultValue
287
287
  ? defaultValue
288
- : undefined), alt: name, className: "h-48 w-48", style: { objectFit: "contain" } })) : (_jsx("span", { className: "text-gray-400", children: "No image" })) }), (previewSrc || (typeof defaultValue === "string" && defaultValue)) && (_jsx("button", { type: "button", onClick: deleteFile, className: "ml-2 text-red-600 underline text-sm", children: "Eliminar archivo" }))] }), _jsxs("div", { className: "flex relative items-center", children: [_jsx("input", { type: "file", id: id ?? name, accept: fileTypes.map((ft) => `.${ft}`).join(", "), className: `block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm`, ...(register ?? {}), ref: fileInputRef, name: name, onChange: handleInputChange }), helpText && (_jsx("div", { className: "flex items-center relative ml-3", children: _jsxs("div", { className: "relative cursor-pointer", onMouseEnter: () => setShowTooltip(true), onMouseLeave: () => setShowTooltip(false), children: [_jsx(IdeaIconSVG, {}), showTooltip && (_jsx("div", { className: "absolute -left-48 top-0 mt-8 p-2 bg-white border rounded shadow text-black z-50", children: helpText }))] }) }))] }), _jsx("div", { className: "mt-2 min-h-[60px] flex items-center justify-center border border-dashed border-gray-200 rounded", children: optimizing || uploading ? (_jsxs(_Fragment, { children: [optimizing && (_jsxs("div", { className: "w-full", children: [_jsx("progress", { value: optimizationProgress, max: "100", className: "w-full" }), _jsxs("p", { className: "text-sm text-blue-600 mt-1 text-center", children: ["Optimizando imagen a webp: ", optimizationProgress, "%"] })] })), uploading && (_jsxs("div", { className: "w-full", children: [_jsx("progress", { value: uploadProgress, max: "100", className: "w-full" }), _jsxs("p", { className: "text-sm text-blue-600 mt-1 text-center", children: ["Subiendo archivo: ", uploadProgress, "%"] })] }))] })) : (_jsx("span", { className: "text-sm text-gray-500", children: "Informaci\u00F3n de progreso" })) }), error && (_jsxs("p", { className: "mt-2 text-sm text-red-600", children: [_jsx("span", { className: "font-medium", children: "\u00A1Oops!" }), " ", error.message?.toString()] })), !error && hintMessage && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500`, children: hintMessage }))] }));
288
+ : undefined), alt: name, className: "h-48 w-48", style: { objectFit: "contain" } })) : (_jsx("span", { className: "text-gray-400", children: "No image" })) }), (previewSrc || (typeof defaultValue === "string" && defaultValue)) && (_jsx("button", { type: "button", onClick: deleteFile, className: "ml-2 text-red-600 underline text-sm", children: "Eliminar archivo" }))] }), _jsxs("div", { className: "flex relative items-center", children: [_jsx("input", { type: "file", id: id ?? name, accept: fileTypes.map((ft) => `.${ft}`).join(", "), capture: capture, className: `block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm`, ...(register ?? {}), ref: fileInputRef, name: name, onChange: handleInputChange }), helpText && (_jsx("div", { className: "flex items-center relative ml-3", children: _jsxs("div", { className: "relative cursor-pointer", onMouseEnter: () => setShowTooltip(true), onMouseLeave: () => setShowTooltip(false), children: [_jsx(IdeaIconSVG, {}), showTooltip && (_jsx("div", { className: "absolute -left-48 top-0 mt-8 p-2 bg-white border rounded shadow text-black z-50", children: helpText }))] }) }))] }), _jsx("div", { className: "mt-2 min-h-[60px] flex items-center justify-center border border-dashed border-gray-200 rounded", children: optimizing || uploading ? (_jsxs(_Fragment, { children: [optimizing && (_jsxs("div", { className: "w-full", children: [_jsx("progress", { value: optimizationProgress, max: "100", className: "w-full" }), _jsxs("p", { className: "text-sm text-blue-600 mt-1 text-center", children: ["Optimizando imagen a webp: ", optimizationProgress, "%"] })] })), uploading && (_jsxs("div", { className: "w-full", children: [_jsx("progress", { value: uploadProgress, max: "100", className: "w-full" }), _jsxs("p", { className: "text-sm text-blue-600 mt-1 text-center", children: ["Subiendo archivo: ", uploadProgress, "%"] })] }))] })) : (_jsx("span", { className: "text-sm text-gray-500", children: "Informaci\u00F3n de progreso" })) }), error && (_jsxs("p", { className: "mt-2 text-sm text-red-600", children: [_jsx("span", { className: "font-medium", children: "\u00A1Oops!" }), " ", error.message?.toString()] })), !error && hintMessage && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500`, children: hintMessage }))] }));
289
289
  };
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Form } from "@remix-run/react";
3
+ import { ButtonSectionContainer } from "../../Containers/index.js";
4
+ export const FormLayout = (props) => {
5
+ const { title, children, buttons, method, formId } = props;
6
+ return (_jsxs(Form, { id: formId, name: formId, method: method ?? "post", children: [title && (_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-3", children: title })), _jsxs("div", { className: "shadow sm:overflow-hidden sm:rounded-md", children: [_jsx("div", { className: "space-y-6 bg-white px-4 py-5 sm:p-6", children: children }), buttons && (_jsx(ButtonSectionContainer, { whitBg: true, children: buttons }))] })] }, formId));
7
+ };
@@ -0,0 +1 @@
1
+ export { RadioButton as RadioButtonGroup, RadioButton as RadioButtonGroupWithoutValidation, } from "../RadioButton/index.js";
@@ -137,6 +137,9 @@ export const SelectField = (props) => {
137
137
  setFilteredOptions(options.filter((option) => option.label.toLowerCase().includes(newValue.toLowerCase())));
138
138
  }, [register, options]);
139
139
  const handleOptionClick = useCallback((option) => {
140
+ if (option.disabled) {
141
+ return;
142
+ }
140
143
  if (isMulti) {
141
144
  handleAddMultiValue(option);
142
145
  }
@@ -241,11 +244,18 @@ export const SelectField = (props) => {
241
244
  ? "text-red-700 dark:text-red-500"
242
245
  : "text-gray-700 dark:text-gray-500"}`, children: [title, required && _jsx("span", { className: "text-red-500", children: "*" })] })), _jsxs("div", { className: "relative", children: [_jsxs("div", { className: "flex items-center", children: [_jsx("input", { type: "text", id: id, value: inputValue, onFocus: () => setIsOpen(true), onKeyDown: handleKeyDown, readOnly: isReadOnly, disabled: disabled, className: `block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm pr-10`, placeholder: isMulti ? "Select options..." : "Select an option...", autoComplete: "off", onChange: handleInputChange, onBlur: handleBlur, required: required }), isClearable && (value || valueMulti.length > 0) && (_jsx("button", { type: "button", onClick: handleClear, className: "absolute inset-y-0 right-0 pr-3 flex items-center", children: "\u00D7" })), helpText && (_jsx("div", { className: "flex items-center relative ml-3", children: _jsxs("div", { className: "relative cursor-pointer", onMouseEnter: () => setShowTooltip(true), onMouseLeave: () => setShowTooltip(false), children: [_jsx(IdeaIconSVG, {}), showTooltip && (_jsx("div", { className: "absolute -left-48 top-0 mt-8 p-2 bg-white border rounded shadow text-black z-50", children: helpText }))] }) }))] }), _jsx("input", { type: "hidden", ...(register ?? {}), name: name, value: isMulti
243
246
  ? valueMulti.map((v) => v.value).join(",")
244
- : value?.value || "" }), isOpen && !isReadOnly && (_jsx("ul", { ref: optionsRef, className: "absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: filteredOptions.map((option, index) => (_jsx("li", { className: `cursor-pointer select-none relative py-2 pl-3 pr-9 ${(isMulti
247
+ : value?.value || "" }), isOpen && !isReadOnly && (_jsx("ul", { ref: optionsRef, className: "absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: filteredOptions.map((option, index) => {
248
+ const isDisabled = Boolean(option.disabled);
249
+ const disabledLabel = option.disabledLabel;
250
+ const isSelected = isMulti
245
251
  ? valueMulti.some((v) => v.value === option.value)
246
- : value?.value === option.value)
247
- ? "text-white bg-indigo-600"
248
- : index === highlightedIndex
249
- ? "text-black bg-sky-200"
250
- : "text-gray-900"}`, onClick: () => handleOptionClick(option), onMouseEnter: () => setHighlightedIndex(index), onMouseLeave: () => setHighlightedIndex(-1), children: option.label }, `${option.value}-${index}`))) }))] }), isMulti && valueMulti.length > 0 && (_jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: valueMulti.map((option, index) => (_jsxs("span", { className: "bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded", children: [option.label, _jsx("button", { type: "button", onClick: () => handleRemoveMultiValue(option), className: "ml-1 text-blue-600 hover:text-blue-800", children: "\u00D7" })] }, `${option.value}-${index}`))) })), error && (_jsxs("p", { className: `mt-2 text-sm text-${color}-600 dark:text-${color}-500`, children: [_jsx("span", { className: "font-medium", children: "Oops!" }), " ", error?.message?.toString() || "Error desconocido"] })), !error && hint && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500 dark:text-${color}-400`, children: hint }))] }));
252
+ : value?.value === option.value;
253
+ return (_jsxs("li", { className: `select-none relative py-2 pl-3 pr-9 ${isDisabled
254
+ ? "cursor-not-allowed text-gray-400 bg-gray-50"
255
+ : isSelected
256
+ ? "cursor-pointer text-white bg-indigo-600"
257
+ : index === highlightedIndex
258
+ ? "cursor-pointer text-black bg-sky-200"
259
+ : "cursor-pointer text-gray-900"}`, onClick: () => !isDisabled && handleOptionClick(option), onMouseEnter: () => !isDisabled && setHighlightedIndex(index), onMouseLeave: () => setHighlightedIndex(-1), children: [option.label, isDisabled && disabledLabel && (_jsxs("span", { className: "ml-2 text-xs text-gray-400", children: ["(", disabledLabel, ")"] }))] }, `${option.value}-${index}`));
260
+ }) }))] }), isMulti && valueMulti.length > 0 && (_jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: valueMulti.map((option, index) => (_jsxs("span", { className: "bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded", children: [option.label, _jsx("button", { type: "button", onClick: () => handleRemoveMultiValue(option), className: "ml-1 text-blue-600 hover:text-blue-800", children: "\u00D7" })] }, `${option.value}-${index}`))) })), error && (_jsxs("p", { className: `mt-2 text-sm text-${color}-600 dark:text-${color}-500`, children: [_jsx("span", { className: "font-medium", children: "Oops!" }), " ", error?.message?.toString() || "Error desconocido"] })), !error && hint && (_jsx("p", { className: `mt-2 italic text-sm text-${color}-500 dark:text-${color}-400`, children: hint }))] }));
251
261
  };