flysoft-react-ui 0.5.2 → 1.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.
Files changed (152) hide show
  1. package/dist/App.d.ts.map +1 -1
  2. package/dist/App.js +5 -6
  3. package/dist/components/form-controls/AutocompleteInput.d.ts.map +1 -1
  4. package/dist/components/form-controls/AutocompleteInput.js +177 -131
  5. package/dist/components/form-controls/Button.d.ts +3 -0
  6. package/dist/components/form-controls/Button.d.ts.map +1 -1
  7. package/dist/components/form-controls/Button.js +160 -19
  8. package/dist/components/form-controls/Checkbox.d.ts.map +1 -1
  9. package/dist/components/form-controls/Checkbox.js +3 -1
  10. package/dist/components/form-controls/DateInput.d.ts +5 -1
  11. package/dist/components/form-controls/DateInput.d.ts.map +1 -1
  12. package/dist/components/form-controls/DateInput.js +94 -27
  13. package/dist/components/form-controls/Input.d.ts.map +1 -1
  14. package/dist/components/form-controls/Input.js +2 -1
  15. package/dist/components/form-controls/LinkButton.d.ts +15 -0
  16. package/dist/components/form-controls/LinkButton.d.ts.map +1 -0
  17. package/dist/components/form-controls/LinkButton.js +248 -0
  18. package/dist/components/form-controls/SearchSelectInput-OLD.d.ts.map +1 -1
  19. package/dist/components/form-controls/SearchSelectInput-OLD.js +5 -4
  20. package/dist/components/form-controls/SearchSelectInput.d.ts.map +1 -1
  21. package/dist/components/form-controls/SearchSelectInput.js +3 -2
  22. package/dist/components/form-controls/index.d.ts +2 -0
  23. package/dist/components/form-controls/index.d.ts.map +1 -1
  24. package/dist/components/form-controls/index.js +1 -0
  25. package/dist/components/layout/Accordion.d.ts +13 -0
  26. package/dist/components/layout/Accordion.d.ts.map +1 -0
  27. package/dist/components/layout/Accordion.js +67 -0
  28. package/dist/components/layout/AppLayout.d.ts.map +1 -1
  29. package/dist/components/layout/AppLayout.js +7 -7
  30. package/dist/components/layout/Card.d.ts +8 -3
  31. package/dist/components/layout/Card.d.ts.map +1 -1
  32. package/dist/components/layout/Card.js +21 -22
  33. package/dist/components/layout/DataTable.js +1 -1
  34. package/dist/components/layout/DropdownMenu.d.ts.map +1 -0
  35. package/dist/components/{utils → layout}/DropdownMenu.js +12 -6
  36. package/dist/components/layout/DropdownPanel.d.ts +7 -0
  37. package/dist/components/layout/DropdownPanel.d.ts.map +1 -0
  38. package/dist/components/layout/DropdownPanel.js +137 -0
  39. package/dist/components/{utils → layout}/Filter.d.ts +5 -0
  40. package/dist/components/layout/Filter.d.ts.map +1 -0
  41. package/dist/components/{utils → layout}/Filter.js +18 -9
  42. package/dist/components/layout/Menu.d.ts +31 -0
  43. package/dist/components/layout/Menu.d.ts.map +1 -0
  44. package/dist/components/layout/Menu.js +21 -0
  45. package/dist/components/layout/index.d.ts +10 -0
  46. package/dist/components/layout/index.d.ts.map +1 -1
  47. package/dist/components/layout/index.js +5 -0
  48. package/dist/components/utils/Badge.d.ts.map +1 -1
  49. package/dist/components/utils/Badge.js +3 -2
  50. package/dist/components/utils/Dialog.d.ts +2 -2
  51. package/dist/components/utils/Dialog.d.ts.map +1 -1
  52. package/dist/components/utils/Dialog.js +4 -3
  53. package/dist/components/utils/FiltersDialog.d.ts +1 -1
  54. package/dist/components/utils/FiltersDialog.d.ts.map +1 -1
  55. package/dist/components/utils/FiltersDialog.js +2 -2
  56. package/dist/components/utils/Loader.js +1 -1
  57. package/dist/components/utils/RoadMap.d.ts.map +1 -1
  58. package/dist/components/utils/RoadMap.js +2 -1
  59. package/dist/components/utils/Snackbar.d.ts.map +1 -1
  60. package/dist/components/utils/Snackbar.js +2 -1
  61. package/dist/components/utils/iconUtils.d.ts +16 -0
  62. package/dist/components/utils/iconUtils.d.ts.map +1 -0
  63. package/dist/components/utils/iconUtils.js +40 -0
  64. package/dist/components/utils/index.d.ts +0 -2
  65. package/dist/components/utils/index.d.ts.map +1 -1
  66. package/dist/components/utils/index.js +0 -1
  67. package/dist/contexts/CrudContext.d.ts +62 -0
  68. package/dist/contexts/CrudContext.d.ts.map +1 -0
  69. package/dist/contexts/CrudContext.js +333 -0
  70. package/dist/contexts/index.d.ts +2 -2
  71. package/dist/contexts/index.d.ts.map +1 -1
  72. package/dist/contexts/index.js +2 -2
  73. package/dist/docs/AccordionDocs.d.ts +4 -0
  74. package/dist/docs/AccordionDocs.d.ts.map +1 -0
  75. package/dist/docs/AccordionDocs.js +21 -0
  76. package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +3 -5
  77. package/dist/docs/AutocompleteInputDocs.js +1 -1
  78. package/dist/docs/ButtonDocs.d.ts.map +1 -1
  79. package/dist/docs/ButtonDocs.js +1 -1
  80. package/dist/docs/CardDocs.d.ts.map +1 -1
  81. package/dist/docs/CardDocs.js +17 -8
  82. package/dist/docs/DataTableDocs.js +3 -3
  83. package/dist/docs/DialogDocs.d.ts.map +1 -1
  84. package/dist/docs/DialogDocs.js +1 -1
  85. package/dist/docs/DocAdmin.js +1 -1
  86. package/dist/docs/DocsMenu.d.ts.map +1 -1
  87. package/dist/docs/DocsMenu.js +3 -3
  88. package/dist/docs/DocsRouter.d.ts.map +1 -1
  89. package/dist/docs/DocsRouter.js +5 -1
  90. package/dist/docs/DropdownMenuDocs.js +1 -1
  91. package/dist/docs/DropdownPanelDocs.d.ts +4 -0
  92. package/dist/docs/DropdownPanelDocs.d.ts.map +1 -0
  93. package/dist/docs/DropdownPanelDocs.js +7 -0
  94. package/dist/docs/FilterDocs.d.ts.map +1 -1
  95. package/dist/docs/FilterDocs.js +19 -1
  96. package/dist/docs/LinkButtonDocs.d.ts +4 -0
  97. package/dist/docs/LinkButtonDocs.d.ts.map +1 -0
  98. package/dist/docs/LinkButtonDocs.js +7 -0
  99. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +0 -9
  100. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +1 -1
  101. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +32 -16
  102. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts +2 -0
  103. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts.map +1 -0
  104. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.js +34 -0
  105. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts +2 -0
  106. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts.map +1 -0
  107. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.js +66 -0
  108. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts +2 -0
  109. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts.map +1 -0
  110. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.js +7 -0
  111. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts +10 -0
  112. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts.map +1 -0
  113. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.js +39 -0
  114. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +1 -1
  115. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +33 -27
  116. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts +9 -0
  117. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts.map +1 -0
  118. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.js +30 -0
  119. package/dist/docs/MenuDocs.d.ts +4 -0
  120. package/dist/docs/MenuDocs.d.ts.map +1 -0
  121. package/dist/docs/MenuDocs.js +26 -0
  122. package/dist/docs/SearchSelectInputDocs.js +1 -1
  123. package/dist/docs/docMockServices/empresaService.d.ts +5 -5
  124. package/dist/docs/docMockServices/empresaService.d.ts.map +1 -1
  125. package/dist/docs/docMockServices/empresaService.js +20 -11
  126. package/dist/docs/docMockServices/interfaces.d.ts +12 -0
  127. package/dist/docs/docMockServices/interfaces.d.ts.map +1 -1
  128. package/dist/docs/docMockServices/personaEmpresaService.d.ts +6 -6
  129. package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +1 -1
  130. package/dist/docs/docMockServices/personaEmpresaService.js +52 -14
  131. package/dist/docs/docMockServices/personaService.d.ts +2 -2
  132. package/dist/docs/docMockServices/personaService.d.ts.map +1 -1
  133. package/dist/docs/docMockServices/personaService.js +17 -7
  134. package/dist/index.css +1 -1
  135. package/dist/index.d.ts +12 -4
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/index.js +6 -2
  138. package/dist/index.js.map +1 -1
  139. package/dist/templates/forms/ContactForm.js +2 -2
  140. package/dist/templates/forms/LoginForm.js +1 -1
  141. package/dist/templates/forms/RegistrationForm.js +1 -1
  142. package/dist/templates/layouts/SidebarLayout.d.ts.map +1 -1
  143. package/dist/templates/layouts/SidebarLayout.js +3 -2
  144. package/dist/templates/patterns/FormPattern.d.ts.map +1 -1
  145. package/dist/templates/patterns/FormPattern.js +4 -3
  146. package/package.json +4 -3
  147. package/dist/components/utils/DropdownMenu.d.ts.map +0 -1
  148. package/dist/components/utils/Filter.d.ts.map +0 -1
  149. package/dist/contexts/ListCrudContext.d.ts +0 -29
  150. package/dist/contexts/ListCrudContext.d.ts.map +0 -1
  151. package/dist/contexts/ListCrudContext.js +0 -209
  152. /package/dist/components/{utils → layout}/DropdownMenu.d.ts +0 -0
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
- import { DropdownMenu } from "../utils/DropdownMenu";
4
- export const Card = ({ title, subtitle, children, className = "", headerActions, footer, variant = "default", }) => {
3
+ export const Card = ({ title, subtitle, children, className = "", headerActions, footer, variant = "default", alwaysDisplayHeaderActions = false, }) => {
5
4
  // Separar clases de background del className
6
5
  const classArray = className.trim().split(/\s+/).filter(Boolean);
7
6
  const bgClasses = [];
@@ -16,9 +15,9 @@ export const Card = ({ title, subtitle, children, className = "", headerActions,
16
15
  }
17
16
  });
18
17
  const backgroundClass = bgClasses.length > 0 ? bgClasses.join(" ") : "bg-[var(--color-bg-default)]";
19
- const baseClasses = `
20
- ${backgroundClass} rounded-lg border
21
- font-[var(--font-default)]
18
+ const baseClasses = `
19
+ ${backgroundClass} rounded-lg border
20
+ font-[var(--font-default)]
22
21
  `;
23
22
  const variantClasses = {
24
23
  default: `border-[var(--color-border-default)]`,
@@ -26,22 +25,11 @@ export const Card = ({ title, subtitle, children, className = "", headerActions,
26
25
  outlined: `border-[var(--color-gray-300)]`,
27
26
  };
28
27
  const classes = `${baseClasses} ${variantClasses[variant]} ${otherClasses.join(" ")}`;
29
- // Convertir array de ReactNode a array de ActionItem para DropdownMenu
30
- const convertActionsToOptions = (actions) => {
31
- return actions.map((action, index) => ({
32
- id: index,
33
- content: (_jsx("div", { onClick: (e) => {
34
- // Detener la propagación para que el onClick del DropdownMenu no interfiera
35
- e.stopPropagation();
36
- }, children: action })),
37
- }));
38
- };
39
- const headerActionsArray = headerActions?.();
40
- const hasHeaderActions = headerActionsArray && headerActionsArray.length > 0;
41
28
  const [isHovered, setIsHovered] = React.useState(false);
42
29
  const [isLargeScreen, setIsLargeScreen] = React.useState(false);
43
30
  React.useEffect(() => {
44
31
  const checkScreenSize = () => {
32
+ // md breakpoint en Tailwind es 768px, así que lg es 1024px
45
33
  setIsLargeScreen(window.innerWidth >= 1024);
46
34
  };
47
35
  checkScreenSize();
@@ -50,9 +38,20 @@ export const Card = ({ title, subtitle, children, className = "", headerActions,
50
38
  window.removeEventListener("resize", checkScreenSize);
51
39
  };
52
40
  }, []);
53
- return (_jsxs("div", { className: `${classes} relative`, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [(title || subtitle || hasHeaderActions) && (_jsx("div", { className: "px-6 pt-4", children: _jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { children: [title && (_jsx("h3", { className: "text-lg font-semibold text-[var(--color-text-primary)]", children: title })), subtitle && (_jsx("p", { className: "text-sm text-[var(--color-text-secondary)] mt-1", children: subtitle }))] }) }) })), hasHeaderActions && (_jsx("div", { className: "absolute top-2 right-2 transition-opacity", style: {
54
- opacity: isLargeScreen ? (isHovered ? 1 : 0) : 1,
55
- }, children: _jsx(DropdownMenu, { options: convertActionsToOptions(headerActionsArray), onOptionSelected: () => {
56
- // Las acciones ya manejan sus propios eventos
57
- }, renderOption: (item) => item.content, replaceOnSingleOption: true }) })), _jsx("div", { className: "px-6 py-4", children: children }), footer && _jsx("div", { className: "px-6 pb-4", children: footer })] }));
41
+ // Determinar la opacidad de las headerActions
42
+ const getHeaderActionsOpacity = () => {
43
+ if (!headerActions)
44
+ return 0;
45
+ // En pantallas pequeñas (md e inferiores) siempre se muestran
46
+ if (!isLargeScreen)
47
+ return 1;
48
+ // Si alwaysDisplayHeaderActions es true, siempre se muestran
49
+ if (alwaysDisplayHeaderActions)
50
+ return 1;
51
+ // Si es false y pantalla grande, solo al hacer hover
52
+ return isHovered ? 1 : 0;
53
+ };
54
+ return (_jsxs("div", { className: `${classes} relative`, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [(title || subtitle || headerActions) && (_jsx("div", { className: "px-6 pt-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [title && (_jsx("h3", { className: "text-lg font-semibold text-[var(--color-text-primary)]", children: title })), subtitle && (_jsx("div", { className: "text-sm text-[var(--color-text-secondary)] mt-1", children: subtitle }))] }), headerActions && (_jsx("div", { className: "flex items-center transition-opacity", style: {
55
+ opacity: getHeaderActionsOpacity(),
56
+ }, children: headerActions }))] }) })), children && _jsx("div", { className: "px-6 py-4", children: children }), footer && _jsx("div", { className: "px-6 pb-4 flex items-center justify-end", children: footer })] }));
58
57
  };
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
- import { DropdownMenu } from "../utils/DropdownMenu";
3
+ import { DropdownMenu } from "./DropdownMenu";
4
4
  export const DataTable = ({ columns, rows, className = "", maxRows, locale = "es-AR", isLoading = false, loadingRows = 5, }) => {
5
5
  // Calcular si necesitamos scroll
6
6
  const displayRows = isLoading ? loadingRows : rows.length;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/components/layout/DropdownMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;IACtD,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,gBAAgB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAAG,iGAOlD,iBAAiB,CAAC,CAAC,CAAC,4CAuNtB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useState, useRef, useEffect, useCallback, useMemo, } from "react";
3
+ import { createPortal } from "react-dom";
3
4
  import { Button } from "../form-controls/Button";
4
5
  export const DropdownMenu = ({ options, onOptionSelected, renderNode, getOptionLabel, renderOption, replaceOnSingleOption = false, }) => {
5
6
  const [isOpen, setIsOpen] = useState(false);
@@ -136,10 +137,15 @@ export const DropdownMenu = ({ options, onOptionSelected, renderNode, getOptionL
136
137
  if (shouldReplace && singleOption) {
137
138
  return (_jsx("div", { onClick: () => handleOptionClick(singleOption), className: "cursor-pointer", children: renderOption ? renderOption(singleOption) : labelGetter(singleOption) }));
138
139
  }
139
- return (_jsxs("div", { className: "relative inline-block", ref: triggerRef, children: [_jsx("div", { onClick: handleToggle, className: "cursor-pointer", children: renderNode ? (renderNode) : (_jsx(Button, { variant: "ghost", icon: "fa-ellipsis-h" })) }), isOpen && (_jsx("div", { ref: menuRef, className: "absolute z-[1000] bg-[var(--color-bg-default)] border border-[var(--color-border-default)] rounded-md shadow-[var(--shadow-lg)] py-1 min-w-[160px] font-[var(--font-default)]", style: menuStyles, children: options.map((option, index) => {
140
- const key = String(option?.id ??
141
- labelGetter(option) ??
142
- index);
143
- return (_jsx("div", { onClick: () => handleOptionClick(option), className: "px-4 py-2 text-sm text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] cursor-pointer transition-colors flex items-center", children: renderOption ? renderOption(option) : labelGetter(option) }, key));
144
- }) }))] }));
140
+ return (_jsxs("div", { className: "relative inline-block", ref: triggerRef, children: [_jsx("div", { onClick: handleToggle, className: "cursor-pointer", children: renderNode ? (renderNode) : (_jsx(Button, { variant: "ghost", icon: "fa-ellipsis-h" })) }), isOpen &&
141
+ (typeof document !== "undefined" && document.body
142
+ ? createPortal(_jsx("div", { ref: menuRef, className: "fixed z-[2000] bg-[var(--color-bg-default)] border border-[var(--color-border-default)] rounded-md shadow-[var(--shadow-lg)] py-1 min-w-[160px] font-[var(--font-default)]", style: menuStyles, children: options.map((option, index) => {
143
+ const key = String(option?.id ??
144
+ labelGetter(option) ??
145
+ index);
146
+ return (_jsx("div", { onClick: () => handleOptionClick(option), className: "px-4 py-2 text-sm text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] cursor-pointer transition-colors flex items-center", children: renderOption
147
+ ? renderOption(option)
148
+ : labelGetter(option) }, key));
149
+ }) }), document.body)
150
+ : null)] }));
145
151
  };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ export interface DropdownPanelProps {
3
+ renderNode?: React.ReactNode;
4
+ children: React.ReactNode;
5
+ }
6
+ export declare const DropdownPanel: ({ renderNode, children, }: DropdownPanelProps) => import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=DropdownPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropdownPanel.d.ts","sourceRoot":"","sources":["../../../src/components/layout/DropdownPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,kBAAkB;IAC/B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,eAAO,MAAM,aAAa,GAAI,2BAG3B,kBAAkB,4CAmLpB,CAAC"}
@@ -0,0 +1,137 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useState, useRef, useEffect, useCallback, useMemo, } from "react";
3
+ import { createPortal } from "react-dom";
4
+ import { Button } from "../form-controls/Button";
5
+ export const DropdownPanel = ({ renderNode, children, }) => {
6
+ const [isOpen, setIsOpen] = useState(false);
7
+ const [menuPosition, setMenuPosition] = useState("bottom");
8
+ const [scrollUpdate, setScrollUpdate] = useState(0);
9
+ const triggerRef = useRef(null);
10
+ const menuRef = useRef(null);
11
+ // Calcular posición del menú
12
+ const calculatePosition = useCallback(() => {
13
+ if (isOpen && triggerRef.current) {
14
+ const triggerRect = triggerRef.current.getBoundingClientRect();
15
+ const viewportHeight = window.innerHeight;
16
+ // Intentar obtener la altura real del menú, o usar una estimación si no está montado aún
17
+ let menuHeight = 200; // valor por defecto
18
+ if (menuRef.current) {
19
+ menuHeight = menuRef.current.getBoundingClientRect().height;
20
+ }
21
+ const menuMargin = 4;
22
+ // Calcular espacio disponible arriba y abajo
23
+ const spaceBelow = viewportHeight - triggerRect.bottom - menuMargin;
24
+ const spaceAbove = triggerRect.top - menuMargin;
25
+ // Si no hay suficiente espacio abajo pero sí arriba, mostrar arriba
26
+ if (spaceBelow < menuHeight && spaceAbove > spaceBelow) {
27
+ setMenuPosition("top");
28
+ }
29
+ else {
30
+ setMenuPosition("bottom"); // Preferir abajo si cabe o si es el que más espacio tiene, o por defecto
31
+ }
32
+ }
33
+ }, [isOpen]);
34
+ // Recalcular posición cuando cambia isOpen (y cuando el contenido podría haber cambiado el tamaño)
35
+ useEffect(() => {
36
+ calculatePosition();
37
+ // Podríamos necesitar un ResizeObserver para ser más robustos si el contenido cambia
38
+ }, [calculatePosition]);
39
+ // Recalcular posición al hacer scroll o redimensionar
40
+ useEffect(() => {
41
+ if (isOpen) {
42
+ const handleScroll = () => {
43
+ calculatePosition();
44
+ // Forzar actualización del estilo del menú
45
+ setScrollUpdate((prev) => prev + 1);
46
+ };
47
+ window.addEventListener("scroll", handleScroll, true);
48
+ window.addEventListener("resize", handleScroll);
49
+ return () => {
50
+ window.removeEventListener("scroll", handleScroll, true);
51
+ window.removeEventListener("resize", handleScroll);
52
+ };
53
+ }
54
+ }, [isOpen, calculatePosition]);
55
+ // Cerrar menú al hacer click fuera
56
+ useEffect(() => {
57
+ const handleClickOutside = (event) => {
58
+ if (isOpen &&
59
+ triggerRef.current &&
60
+ menuRef.current &&
61
+ !triggerRef.current.contains(event.target) &&
62
+ !menuRef.current.contains(event.target)) {
63
+ setIsOpen(false);
64
+ }
65
+ };
66
+ if (isOpen) {
67
+ document.addEventListener("mousedown", handleClickOutside);
68
+ }
69
+ return () => {
70
+ document.removeEventListener("mousedown", handleClickOutside);
71
+ };
72
+ }, [isOpen]);
73
+ // Cerrar menú al presionar Escape
74
+ useEffect(() => {
75
+ const handleEscape = (event) => {
76
+ if (event.key === "Escape" && isOpen) {
77
+ setIsOpen(false);
78
+ }
79
+ };
80
+ if (isOpen) {
81
+ document.addEventListener("keydown", handleEscape);
82
+ }
83
+ return () => {
84
+ document.removeEventListener("keydown", handleEscape);
85
+ };
86
+ }, [isOpen]);
87
+ const handleToggle = () => {
88
+ setIsOpen(!isOpen);
89
+ };
90
+ const menuStyles = useMemo(() => {
91
+ if (!isOpen || !triggerRef.current) {
92
+ return {};
93
+ }
94
+ const triggerRect = triggerRef.current.getBoundingClientRect();
95
+ const menuMargin = 4;
96
+ // Asegurar que el menú no se salga de la pantalla horizontalmente
97
+ let leftPosition = triggerRect.left;
98
+ const menuMinWidth = 160;
99
+ const viewportWidth = window.innerWidth;
100
+ // Si el menú se sale por la derecha, ajustar la posición
101
+ // Nota: Como el ancho es dinámico (basado en children), idealmente deberíamos medirlo.
102
+ // Usaremos menuRef si está disponible o un estimado.
103
+ let currentMenuWidth = menuMinWidth;
104
+ if (menuRef.current) {
105
+ currentMenuWidth = menuRef.current.getBoundingClientRect().width;
106
+ }
107
+ if (leftPosition + currentMenuWidth > viewportWidth) {
108
+ leftPosition = viewportWidth - currentMenuWidth - 8; // 8px de margen
109
+ }
110
+ // Asegurar que no se salga por la izquierda
111
+ if (leftPosition < 8) {
112
+ leftPosition = 8;
113
+ }
114
+ if (menuPosition === "top") {
115
+ return {
116
+ position: "fixed",
117
+ bottom: window.innerHeight - triggerRect.top + menuMargin,
118
+ left: leftPosition,
119
+ minWidth: Math.max(triggerRect.width, menuMinWidth), // Mantener el minWidth del trigger o 160
120
+ };
121
+ }
122
+ else {
123
+ return {
124
+ position: "fixed",
125
+ top: triggerRect.bottom + menuMargin,
126
+ left: leftPosition,
127
+ minWidth: Math.max(triggerRect.width, menuMinWidth),
128
+ };
129
+ }
130
+ // scrollUpdate se usa intencionalmente para forzar el recálculo en scroll
131
+ // eslint-disable-next-line react-hooks/exhaustive-deps
132
+ }, [isOpen, menuPosition, scrollUpdate]);
133
+ return (_jsxs("div", { className: "relative inline-block", ref: triggerRef, children: [_jsx("div", { onClick: handleToggle, className: "cursor-pointer", children: renderNode ? (renderNode) : (_jsx(Button, { variant: "ghost", icon: "fa-ellipsis-h" })) }), isOpen &&
134
+ (typeof document !== "undefined" && document.body
135
+ ? createPortal(_jsx("div", { ref: menuRef, className: "fixed z-[2000] bg-[var(--color-bg-default)] border border-[var(--color-border-default)] rounded-md shadow-[var(--shadow-lg)] py-1 min-w-[160px] font-[var(--font-default)]", style: menuStyles, children: children }), document.body)
136
+ : null)] }));
137
+ };
@@ -18,6 +18,11 @@ interface BaseFilterProps {
18
18
  * Por defecto es false.
19
19
  */
20
20
  hideEmpty?: boolean;
21
+ /**
22
+ * Si es true, el componente se muestra con opacidad y no permite interacciones.
23
+ * Si el panel está abierto, se cerrará automáticamente.
24
+ */
25
+ disabled?: boolean;
21
26
  }
22
27
  export interface TextFilterProps extends BaseFilterProps {
23
28
  filterType?: "text";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Filter.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Filter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAIvE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC/C;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAGD,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,UAAU,EAAE,QAAQ,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,GAAG,MAAM,CACzE,SAAQ,eAAe;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,UAAU,EAAE,QAAQ,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,GAAG,MAAM,CACzE,SAAQ,eAAe;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,iBAAiB,EAAE,CACjB,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,uBAAuB,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9D,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAGD,MAAM,MAAM,WAAW,GACnB,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,uBAAuB,GACvB,iBAAiB,GACjB,uBAAuB,CAAC;AAE5B,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAy+BxC,CAAC"}
@@ -8,9 +8,10 @@ import { Input } from "../form-controls/Input";
8
8
  import { DateInput } from "../form-controls/DateInput";
9
9
  import { AutocompleteInput } from "../form-controls/AutocompleteInput";
10
10
  import { SearchSelectInput } from "../form-controls/SearchSelectInput";
11
- import { DataField } from "../layout/DataField";
11
+ import { DataField } from "./DataField";
12
+ import { normalizeIconClass } from "../utils/iconUtils";
12
13
  export const Filter = (props) => {
13
- const { paramName, label, staticOptions, inputWidth, value: propValue, onChange, hideEmpty = false, } = props;
14
+ const { paramName, label, staticOptions, inputWidth, value: propValue, onChange, hideEmpty = false, disabled = false, } = props;
14
15
  const filterType = props.filterType || "text";
15
16
  // Calcular el ancho por defecto según el tipo de filtro
16
17
  const defaultInputWidth = filterType === "date" || filterType === "autocomplete" ? "160px" : "200px";
@@ -157,6 +158,12 @@ export const Filter = (props) => {
157
158
  document.removeEventListener("mousedown", handleClickOutside);
158
159
  };
159
160
  }, [isOpen]);
161
+ // Cerrar el panel si el componente se deshabilita
162
+ useEffect(() => {
163
+ if (disabled) {
164
+ setIsOpen(false);
165
+ }
166
+ }, [disabled]);
160
167
  const handleSetFilter = () => {
161
168
  const newValue = inputValue.trim() || undefined;
162
169
  // Si hay onChange, llamarlo con el nuevo valor
@@ -439,6 +446,8 @@ export const Filter = (props) => {
439
446
  }
440
447
  };
441
448
  const handleTogglePanel = () => {
449
+ if (disabled)
450
+ return;
442
451
  if (!isOpen) {
443
452
  // Calcular posición antes de abrir
444
453
  if (containerRef.current) {
@@ -499,10 +508,10 @@ export const Filter = (props) => {
499
508
  }
500
509
  // Contenedor tipo badge con diseño similar al Input
501
510
  // Altura ajustada para coincidir con input sm: py-1.5 (6px arriba y abajo) + text-sm (14px línea) = ~26px total
502
- const badgeContainer = (_jsxs("div", { className: "inline-flex items-center gap-2 px-3 py-1.5 h-[2.1rem] rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-default)] text-[var(--color-text-primary)] font-[var(--font-default)] cursor-pointer text-sm transition-colors", onClick: handleTogglePanel, children: [_jsx("span", { className: "text-sm min-w-[1rem]", children: getDisplayValue() || "\u00A0" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "p-0.5 hover:bg-[var(--color-bg-secondary)] rounded transition-colors flex items-center justify-center", children: _jsx("i", { className: `fa fa-chevron-down text-xs text-[var(--color-text-muted)] hover:text-[var(--color-primary)] transition-all ${isOpen ? "rotate-180" : ""}` }) }), currentValue && (_jsx("button", { onClick: handleClearFilter, className: "p-0.5 hover:bg-[var(--color-bg-secondary)] rounded transition-colors flex items-center justify-center", "aria-label": "Borrar filtro", type: "button", children: _jsx("i", { className: "fa fa-times text-xs text-[var(--color-text-muted)] hover:text-[var(--color-primary)] transition-colors" }) }))] })] }));
511
+ const badgeContainer = (_jsxs("div", { className: "inline-flex items-center gap-2 px-3 py-1.5 h-[2.1rem] rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-default)] text-[var(--color-text-primary)] font-[var(--font-default)] cursor-pointer text-sm transition-colors", onClick: handleTogglePanel, children: [_jsx("span", { className: "text-sm min-w-[1rem]", children: getDisplayValue() || "\u00A0" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("span", { className: "p-0.5 hover:bg-[var(--color-bg-secondary)] rounded transition-colors flex items-center justify-center", children: _jsx("i", { className: `${normalizeIconClass("fa-chevron-down")} text-xs text-[var(--color-text-muted)] hover:text-[var(--color-primary)] transition-all ${isOpen ? "rotate-180" : ""}` }) }), currentValue && (_jsx("button", { onClick: handleClearFilter, className: "p-0.5 hover:bg-[var(--color-bg-secondary)] rounded transition-colors flex items-center justify-center", "aria-label": "Borrar filtro", type: "button", children: _jsx("i", { className: `${normalizeIconClass("fa-times")} text-xs text-[var(--color-text-muted)] hover:text-[var(--color-primary)] transition-colors` }) }))] })] }));
503
512
  // Renderizar según el tipo de filtro
504
513
  if (filterType === "autocomplete") {
505
- return (_jsxs("div", { ref: containerRef, className: "relative inline-block", children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
514
+ return (_jsxs("div", { ref: containerRef, className: `relative inline-block ${disabled ? "opacity-50 pointer-events-none" : ""}`, children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
506
515
  panelPosition &&
507
516
  typeof document !== "undefined" &&
508
517
  document.body &&
@@ -514,10 +523,10 @@ export const Filter = (props) => {
514
523
  : "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (e) => {
515
524
  e.preventDefault();
516
525
  handleStaticOptionSelect(option);
517
- }, children: _jsx("span", { className: "font-[var(--font-default)]", children: option.text }) }, option.value))) })), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { style: { width: finalInputWidth }, children: _jsx(AutocompleteInput, { ref: autocompleteInputRef, options: props.options, value: isUserTyping ? undefined : autocompleteValue, onChange: handleAutocompleteChange, getOptionLabel: props.getOptionLabel, getOptionValue: props.getOptionValue, renderOption: props.renderOption, noResultsText: props.noResultsText, onSelectOption: handleAutocompleteOptionSelect }) }), _jsx(Button, { onClick: handleAutocompleteSelect, icon: "fa-arrow-right", variant: "ghost" })] })] }) }), document.body)] }));
526
+ }, children: _jsx("span", { className: "font-[var(--font-default)]", children: option.text }) }, option.value))) })), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { style: { width: finalInputWidth }, children: _jsx(AutocompleteInput, { ref: autocompleteInputRef, options: props.options, value: isUserTyping ? undefined : autocompleteValue, onChange: handleAutocompleteChange, getOptionLabel: props.getOptionLabel, getOptionValue: props.getOptionValue, renderOption: props.renderOption, noResultsText: props.noResultsText, onSelectOption: handleAutocompleteOptionSelect, disabled: disabled }) }), _jsx(Button, { onClick: handleAutocompleteSelect, icon: "fa-arrow-right", variant: "ghost" })] })] }) }), document.body)] }));
518
527
  }
519
528
  if (filterType === "date") {
520
- return (_jsxs("div", { ref: containerRef, className: "relative inline-block", children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
529
+ return (_jsxs("div", { ref: containerRef, className: `relative inline-block ${disabled ? "opacity-50 pointer-events-none" : ""}`, children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
521
530
  panelPosition &&
522
531
  typeof document !== "undefined" &&
523
532
  document.body &&
@@ -534,7 +543,7 @@ export const Filter = (props) => {
534
543
  // Para searchSelect
535
544
  if (filterType === "searchSelect") {
536
545
  const searchSelectProps = props;
537
- return (_jsxs("div", { ref: containerRef, className: "relative inline-block", children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
546
+ return (_jsxs("div", { ref: containerRef, className: `relative inline-block ${disabled ? "opacity-50 pointer-events-none" : ""}`, children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
538
547
  panelPosition &&
539
548
  typeof document !== "undefined" &&
540
549
  document.body &&
@@ -553,10 +562,10 @@ export const Filter = (props) => {
553
562
  // Mostrar X solo si hay un valor actual Y el texto del input coincide con ese valor
554
563
  const hasValue = !!currentValue;
555
564
  const valueMatches = hasValue && searchValue.trim() === currentValue;
556
- return (_jsx("div", { ref: containerRef, className: "relative inline-block", children: _jsx(DataField, { label: label, value: _jsx("div", { style: { width: finalInputWidth }, children: _jsx(Input, { ref: searchInputRef, type: "text", value: searchValue, onChange: handleSearchChange, onKeyDown: handleSearchKeyDown, icon: valueMatches ? "fa-times" : "fa-search", iconPosition: "right", onIconClick: handleSearchIconClick, placeholder: "Buscar...", size: "sm" }) }), className: "inline-block" }) }));
565
+ return (_jsx("div", { ref: containerRef, className: `relative inline-block ${disabled ? "opacity-50 pointer-events-none" : ""}`, children: _jsx(DataField, { label: label, value: _jsx("div", { style: { width: finalInputWidth }, children: _jsx(Input, { ref: searchInputRef, type: "text", value: searchValue, onChange: handleSearchChange, onKeyDown: handleSearchKeyDown, icon: valueMatches ? "fa-times" : "fa-search", iconPosition: "right", onIconClick: handleSearchIconClick, placeholder: "Buscar...", size: "sm", disabled: disabled }) }), className: "inline-block" }) }));
557
566
  }
558
567
  // Para text y number
559
- return (_jsxs("div", { ref: containerRef, className: "relative inline-block", children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
568
+ return (_jsxs("div", { ref: containerRef, className: `relative inline-block ${disabled ? "opacity-50 pointer-events-none" : ""}`, children: [_jsx(DataField, { label: label, value: badgeContainer, className: "inline-block" }), isOpen &&
560
569
  panelPosition &&
561
570
  typeof document !== "undefined" &&
562
571
  document.body &&
@@ -0,0 +1,31 @@
1
+ import React from "react";
2
+ export interface MenuProps<T = {
3
+ label: string;
4
+ }> {
5
+ options: T[];
6
+ onOptionSelected: (item: T) => void;
7
+ /**
8
+ * Obtiene el label que se muestra para cada opción. Por defecto usa la propiedad "label".
9
+ */
10
+ getOptionLabel?: (item: T) => string;
11
+ /**
12
+ * Renderizado personalizado de cada opción. Si se define, se ignora el render por defecto.
13
+ */
14
+ renderOption?: (item: T) => React.ReactNode;
15
+ /**
16
+ * Clases adicionales para el contenedor del menú. Permite sobreescribir los estilos por defecto.
17
+ */
18
+ className?: string;
19
+ /**
20
+ * Estilos adicionales para el contenedor del menú.
21
+ */
22
+ style?: React.CSSProperties;
23
+ /**
24
+ * Clases adicionales para cada opción del menú.
25
+ */
26
+ itemClassName?: string;
27
+ }
28
+ export declare const Menu: <T = {
29
+ label: string;
30
+ }>({ options, onOptionSelected, getOptionLabel, renderOption, className, style, itemClassName, }: MenuProps<T>) => import("react/jsx-runtime").JSX.Element;
31
+ //# sourceMappingURL=Menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAG3C,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;IAC5C,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,gBAAgB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACpC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,IAAI,GAAI,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAAG,+FAQ1C,SAAS,CAAC,CAAC,CAAC,4CA8Cd,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useCallback } from "react";
3
+ import { twMerge } from "tailwind-merge";
4
+ export const Menu = ({ options, onOptionSelected, getOptionLabel, renderOption, className, style, itemClassName, }) => {
5
+ const labelGetter = useCallback((item) => {
6
+ if (getOptionLabel)
7
+ return getOptionLabel(item);
8
+ const anyItem = item;
9
+ return (anyItem.label ?? "").toString();
10
+ }, [getOptionLabel]);
11
+ const handleOptionClick = (item) => {
12
+ onOptionSelected(item);
13
+ };
14
+ const mergedClassName = twMerge("bg-[var(--color-bg-default)] border border-[var(--color-border-default)] rounded-md shadow-[var(--shadow-sm)] py-1 min-w-[160px] font-[var(--font-default)] inline-block", className);
15
+ return (_jsx("div", { className: mergedClassName, style: style, children: options.map((option, index) => {
16
+ const key = String(option?.id ??
17
+ labelGetter(option) ??
18
+ index);
19
+ return (_jsx("div", { onClick: () => handleOptionClick(option), className: twMerge("px-4 py-2 text-sm text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] cursor-pointer transition-colors flex items-center", itemClassName), children: renderOption ? renderOption(option) : labelGetter(option) }, key));
20
+ }) }));
21
+ };
@@ -12,4 +12,14 @@ export { TabPanel } from "./TabPanel";
12
12
  export type { TabPanelProps } from "./TabPanel";
13
13
  export { DataTable } from "./DataTable";
14
14
  export type { DataTableProps, DataTableColumn } from "./DataTable";
15
+ export { Accordion } from "./Accordion";
16
+ export type { AccordionProps } from "./Accordion";
17
+ export { Menu } from "./Menu";
18
+ export type { MenuProps } from "./Menu";
19
+ export { DropdownMenu } from "./DropdownMenu";
20
+ export type { DropdownMenuProps } from "./DropdownMenu";
21
+ export { DropdownPanel } from "./DropdownPanel";
22
+ export type { DropdownPanelProps } from "./DropdownPanel";
23
+ export { Filter } from "./Filter";
24
+ export type { FilterProps } from "./Filter";
15
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/layout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/layout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
@@ -5,3 +5,8 @@ export { DataField } from "./DataField";
5
5
  export { TabsGroup } from "./TabsGroup";
6
6
  export { TabPanel } from "./TabPanel";
7
7
  export { DataTable } from "./DataTable";
8
+ export { Accordion } from "./Accordion";
9
+ export { Menu } from "./Menu";
10
+ export { DropdownMenu } from "./DropdownMenu";
11
+ export { DropdownPanel } from "./DropdownPanel";
12
+ export { Filter } from "./Filter";
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/utils/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAiC1B,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9E,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CAC1D;AAED,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA2KtC,CAAC"}
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/utils/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkC1B,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9E,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CAC1D;AAED,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA2KtC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
+ import { normalizeIconClass } from "./iconUtils";
3
4
  // Función helper para convertir nombres de colores comunes a valores CSS válidos
4
5
  const getColorValue = (color) => {
5
6
  if (!color)
@@ -109,8 +110,8 @@ export const Badge = ({ children, variant = "primary", size = "md", rounded = fa
109
110
  return null;
110
111
  // Si hay onClick y hay iconos, el onClick se aplica solo a los iconos
111
112
  const iconClasses = onClick
112
- ? `fa ${icon} ${iconSizeClasses} cursor-pointer`
113
- : `fa ${icon} ${iconSizeClasses}`;
113
+ ? `${normalizeIconClass(icon)} ${iconSizeClasses} cursor-pointer`
114
+ : `${normalizeIconClass(icon)} ${iconSizeClasses}`;
114
115
  return (_jsx("span", { className: iconPaddingClasses, children: _jsx("i", { className: iconClasses, "aria-hidden": !iconLabel, "aria-label": iconLabel, onClick: onClick, role: onClick ? "button" : undefined, tabIndex: onClick ? 0 : undefined, onKeyDown: onClick
115
116
  ? (e) => {
116
117
  if (e.key === "Enter" || e.key === " ") {
@@ -2,8 +2,8 @@ import React from "react";
2
2
  export interface DialogProps {
3
3
  isOpen: boolean;
4
4
  title: React.ReactNode;
5
- dialogBody: React.ReactNode;
6
- dialogActions: React.ReactNode;
5
+ children: React.ReactNode;
6
+ footer?: React.ReactNode;
7
7
  onClose?: () => void;
8
8
  closeOnOverlayClick?: boolean;
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/utils/Dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAyGxC,CAAC"}
1
+ {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/utils/Dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAGzC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CA2GxC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useEffect } from "react";
3
- export const Dialog = ({ isOpen, title, dialogBody, dialogActions, onClose, closeOnOverlayClick = false, }) => {
3
+ import { normalizeIconClass } from "./iconUtils";
4
+ export const Dialog = ({ isOpen, title, children, footer, onClose, closeOnOverlayClick = false, }) => {
4
5
  // Prevenir scroll del body cuando el dialog está abierto
5
6
  useEffect(() => {
6
7
  if (isOpen) {
@@ -35,9 +36,9 @@ export const Dialog = ({ isOpen, title, dialogBody, dialogActions, onClose, clos
35
36
  onClose();
36
37
  }
37
38
  };
38
- return (_jsxs("div", { className: "fixed inset-0 z-[2000] flex items-center justify-center p-4", role: "dialog", "aria-modal": "true", "aria-labelledby": "dialog-title", children: [_jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: handleOverlayClick }), _jsxs("div", { className: "relative w-auto max-w-lg min-w-[400px] bg-[var(--color-bg-default)] rounded-lg shadow-[var(--shadow-xl)] border border-[var(--color-border-default)] font-[var(--font-default)] max-h-[90vh] flex flex-col", onClick: (e) => e.stopPropagation(), style: { overflow: "visible" }, children: [_jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-[var(--color-border-default)] flex-shrink-0", children: [_jsx("h2", { id: "dialog-title", className: "text-lg font-semibold text-[var(--color-text-primary)]", children: title }), onClose && (_jsx("button", { onClick: onClose, className: "ml-4 p-1 rounded-md text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] transition-colors cursor-pointer", "aria-label": "Cerrar dialog", children: _jsx("i", { className: "fa fa-times" }) }))] }), _jsx("div", { className: "px-6 py-4 flex-1 text-[var(--color-text-primary)] min-w-0", style: {
39
+ return (_jsxs("div", { className: "fixed inset-0 z-[2000] flex items-center justify-center p-4", role: "dialog", "aria-modal": "true", "aria-labelledby": "dialog-title", children: [_jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: handleOverlayClick }), _jsxs("div", { className: "relative w-auto max-w-lg min-w-[400px] bg-[var(--color-bg-default)] rounded-lg shadow-[var(--shadow-xl)] border border-[var(--color-border-default)] font-[var(--font-default)] max-h-[90vh] flex flex-col", onClick: (e) => e.stopPropagation(), style: { overflow: "visible" }, children: [_jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-[var(--color-border-default)] flex-shrink-0", children: [_jsx("h2", { id: "dialog-title", className: "text-lg font-semibold text-[var(--color-text-primary)]", children: title }), onClose && (_jsx("button", { onClick: onClose, className: "ml-4 p-1 rounded-md text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] transition-colors cursor-pointer", "aria-label": "Cerrar dialog", children: _jsx("i", { className: normalizeIconClass("fa-times") }) }))] }), _jsx("div", { className: "px-6 py-4 flex-1 text-[var(--color-text-primary)] min-w-0", style: {
39
40
  overflowY: "auto",
40
41
  overflowX: "visible",
41
42
  maxHeight: "calc(90vh - 200px)"
42
- }, children: dialogBody }), _jsx("div", { className: "px-6 py-4 border-t border-[var(--color-border-default)] flex items-center justify-end gap-2 flex-shrink-0 flex-wrap", children: dialogActions })] })] }));
43
+ }, children: children }), footer && (_jsx("div", { className: "px-6 py-4 border-t border-[var(--color-border-default)] flex items-center justify-end gap-2 flex-shrink-0 flex-wrap", children: footer }))] })] }));
43
44
  };
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { type FilterProps } from "./Filter";
2
+ import { type FilterProps } from "../layout/Filter";
3
3
  export interface FilterConfig {
4
4
  filterType: FilterProps["filterType"];
5
5
  paramName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"FiltersDialog.d.ts","sourceRoot":"","sources":["../../../src/components/utils/FiltersDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAGpD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;IACvC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;IACpC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAgJtD,CAAC"}
1
+ {"version":3,"file":"FiltersDialog.d.ts","sourceRoot":"","sources":["../../../src/components/utils/FiltersDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG5D,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;IACvC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;IACpC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA+ItD,CAAC"}
@@ -3,7 +3,7 @@ import React, { useState, useEffect } from "react";
3
3
  import { useSearchParams } from "react-router-dom";
4
4
  import { Button } from "../form-controls/Button";
5
5
  import { Dialog } from "./Dialog";
6
- import { Filter } from "./Filter";
6
+ import { Filter } from "../layout/Filter";
7
7
  import { Collection } from "../layout/Collection";
8
8
  export const FiltersDialog = ({ filters }) => {
9
9
  const [searchParams, setSearchParams] = useSearchParams();
@@ -100,5 +100,5 @@ export const FiltersDialog = ({ filters }) => {
100
100
  };
101
101
  }
102
102
  };
103
- return (_jsxs(_Fragment, { children: [_jsx(Button, { icon: "fa-filter", variant: "outline", size: "sm", onClick: handleOpen, "aria-label": "Abrir filtros", children: "Filtrar" }), _jsx(Dialog, { isOpen: isOpen, title: "Filtros", dialogBody: _jsx("div", { className: "space-y-4", children: _jsx(Collection, { direction: "column", gap: "1rem", children: filters.map((filter) => (_jsx(Filter, { ...getFilterProps(filter) }, filter.paramName))) }) }), dialogActions: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: handleClose, children: "Cerrar" }), _jsx(Button, { variant: "primary", onClick: handleApplyFilters, children: "Aplicar filtros" })] }), onClose: handleClose, closeOnOverlayClick: false })] }));
103
+ return (_jsxs(_Fragment, { children: [_jsx(Button, { icon: "fa-filter", variant: "outline", size: "sm", onClick: handleOpen, "aria-label": "Abrir filtros", children: "Filtrar" }), _jsx(Dialog, { isOpen: isOpen, title: "Filtros", footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: handleClose, children: "Cerrar" }), _jsx(Button, { variant: "primary", onClick: handleApplyFilters, children: "Aplicar filtros" })] }), onClose: handleClose, closeOnOverlayClick: false, children: _jsx("div", { className: "space-y-4", children: _jsx(Collection, { direction: "column", gap: "1rem", children: filters.map((filter) => (_jsx(Filter, { ...getFilterProps(filter) }, filter.paramName))) }) }) })] }));
104
104
  };
@@ -3,7 +3,7 @@ import React from "react";
3
3
  import { useTheme } from "../../contexts/ThemeContext";
4
4
  export const Loader = ({ isLoading = false, text, children, keepContentWhileLoading, contentLoadingNode, overlayClassName, }) => {
5
5
  const { theme } = useTheme();
6
- const displayText = text || "Cargando...";
6
+ const displayText = text;
7
7
  // Clases por defecto del overlay (negro semitransparente con blur)
8
8
  const defaultOverlayClasses = "bg-black/50 backdrop-blur-sm";
9
9
  // Combinar clases por defecto con las personalizadas
@@ -1 +1 @@
1
- {"version":3,"file":"RoadMap.d.ts","sourceRoot":"","sources":["../../../src/components/utils/RoadMap.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AA4E1B,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9E;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAgH1C,CAAC"}
1
+ {"version":3,"file":"RoadMap.d.ts","sourceRoot":"","sources":["../../../src/components/utils/RoadMap.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AA6E1B,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9E;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAgH1C,CAAC"}