flysoft-react-ui 0.5.3 → 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 (92) hide show
  1. package/dist/components/form-controls/AutocompleteInput.d.ts.map +1 -1
  2. package/dist/components/form-controls/AutocompleteInput.js +175 -130
  3. package/dist/components/form-controls/SearchSelectInput-OLD.d.ts.map +1 -1
  4. package/dist/components/form-controls/SearchSelectInput-OLD.js +2 -2
  5. package/dist/components/form-controls/SearchSelectInput.d.ts.map +1 -1
  6. package/dist/components/form-controls/SearchSelectInput.js +1 -1
  7. package/dist/components/layout/AppLayout.d.ts.map +1 -1
  8. package/dist/components/layout/AppLayout.js +7 -7
  9. package/dist/components/layout/Card.d.ts.map +1 -1
  10. package/dist/components/layout/Card.js +4 -4
  11. package/dist/components/layout/DataTable.js +1 -1
  12. package/dist/components/layout/DropdownMenu.d.ts.map +1 -0
  13. package/dist/components/{utils → layout}/DropdownMenu.js +12 -6
  14. package/dist/components/layout/DropdownPanel.d.ts +7 -0
  15. package/dist/components/layout/DropdownPanel.d.ts.map +1 -0
  16. package/dist/components/layout/DropdownPanel.js +137 -0
  17. package/dist/components/{utils → layout}/Filter.d.ts +5 -0
  18. package/dist/components/layout/Filter.d.ts.map +1 -0
  19. package/dist/components/{utils → layout}/Filter.js +17 -9
  20. package/dist/components/layout/Menu.d.ts +31 -0
  21. package/dist/components/layout/Menu.d.ts.map +1 -0
  22. package/dist/components/layout/Menu.js +21 -0
  23. package/dist/components/layout/index.d.ts +8 -0
  24. package/dist/components/layout/index.d.ts.map +1 -1
  25. package/dist/components/layout/index.js +4 -0
  26. package/dist/components/utils/Dialog.d.ts +2 -2
  27. package/dist/components/utils/Dialog.d.ts.map +1 -1
  28. package/dist/components/utils/Dialog.js +2 -2
  29. package/dist/components/utils/FiltersDialog.d.ts +1 -1
  30. package/dist/components/utils/FiltersDialog.d.ts.map +1 -1
  31. package/dist/components/utils/FiltersDialog.js +2 -2
  32. package/dist/components/utils/index.d.ts +0 -2
  33. package/dist/components/utils/index.d.ts.map +1 -1
  34. package/dist/components/utils/index.js +0 -1
  35. package/dist/contexts/{ListCrudContext.d.ts → CrudContext.d.ts} +20 -8
  36. package/dist/contexts/CrudContext.d.ts.map +1 -0
  37. package/dist/contexts/{ListCrudContext.js → CrudContext.js} +102 -22
  38. package/dist/contexts/index.d.ts +2 -2
  39. package/dist/contexts/index.d.ts.map +1 -1
  40. package/dist/contexts/index.js +2 -2
  41. package/dist/docs/DialogDocs.d.ts.map +1 -1
  42. package/dist/docs/DialogDocs.js +1 -1
  43. package/dist/docs/DocsMenu.d.ts.map +1 -1
  44. package/dist/docs/DocsMenu.js +1 -1
  45. package/dist/docs/DocsRouter.d.ts.map +1 -1
  46. package/dist/docs/DocsRouter.js +3 -1
  47. package/dist/docs/DropdownPanelDocs.d.ts +4 -0
  48. package/dist/docs/DropdownPanelDocs.d.ts.map +1 -0
  49. package/dist/docs/DropdownPanelDocs.js +7 -0
  50. package/dist/docs/FilterDocs.d.ts.map +1 -1
  51. package/dist/docs/FilterDocs.js +19 -1
  52. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +1 -1
  53. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +26 -14
  54. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts +2 -0
  55. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts.map +1 -0
  56. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.js +34 -0
  57. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts +2 -0
  58. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts.map +1 -0
  59. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.js +66 -0
  60. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts.map +1 -1
  61. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.js +5 -5
  62. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts +10 -0
  63. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts.map +1 -0
  64. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.js +39 -0
  65. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +1 -1
  66. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +3 -3
  67. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts.map +1 -1
  68. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.js +4 -4
  69. package/dist/docs/MenuDocs.d.ts +4 -0
  70. package/dist/docs/MenuDocs.d.ts.map +1 -0
  71. package/dist/docs/MenuDocs.js +26 -0
  72. package/dist/docs/docMockServices/empresaService.d.ts +5 -5
  73. package/dist/docs/docMockServices/empresaService.d.ts.map +1 -1
  74. package/dist/docs/docMockServices/empresaService.js +18 -10
  75. package/dist/docs/docMockServices/interfaces.d.ts +12 -0
  76. package/dist/docs/docMockServices/interfaces.d.ts.map +1 -1
  77. package/dist/docs/docMockServices/personaEmpresaService.d.ts +6 -6
  78. package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +1 -1
  79. package/dist/docs/docMockServices/personaEmpresaService.js +52 -14
  80. package/dist/docs/docMockServices/personaService.d.ts +1 -1
  81. package/dist/docs/docMockServices/personaService.d.ts.map +1 -1
  82. package/dist/docs/docMockServices/personaService.js +14 -5
  83. package/dist/index.css +1 -1
  84. package/dist/index.d.ts +8 -4
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +4 -2
  87. package/dist/index.js.map +1 -1
  88. package/package.json +4 -3
  89. package/dist/components/utils/DropdownMenu.d.ts.map +0 -1
  90. package/dist/components/utils/Filter.d.ts.map +0 -1
  91. package/dist/contexts/ListCrudContext.d.ts.map +0 -1
  92. /package/dist/components/{utils → layout}/DropdownMenu.d.ts +0 -0
@@ -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,10 +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";
12
- import { normalizeIconClass } from "./iconUtils";
11
+ import { DataField } from "./DataField";
12
+ import { normalizeIconClass } from "../utils/iconUtils";
13
13
  export const Filter = (props) => {
14
- 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;
15
15
  const filterType = props.filterType || "text";
16
16
  // Calcular el ancho por defecto según el tipo de filtro
17
17
  const defaultInputWidth = filterType === "date" || filterType === "autocomplete" ? "160px" : "200px";
@@ -158,6 +158,12 @@ export const Filter = (props) => {
158
158
  document.removeEventListener("mousedown", handleClickOutside);
159
159
  };
160
160
  }, [isOpen]);
161
+ // Cerrar el panel si el componente se deshabilita
162
+ useEffect(() => {
163
+ if (disabled) {
164
+ setIsOpen(false);
165
+ }
166
+ }, [disabled]);
161
167
  const handleSetFilter = () => {
162
168
  const newValue = inputValue.trim() || undefined;
163
169
  // Si hay onChange, llamarlo con el nuevo valor
@@ -440,6 +446,8 @@ export const Filter = (props) => {
440
446
  }
441
447
  };
442
448
  const handleTogglePanel = () => {
449
+ if (disabled)
450
+ return;
443
451
  if (!isOpen) {
444
452
  // Calcular posición antes de abrir
445
453
  if (containerRef.current) {
@@ -503,7 +511,7 @@ export const Filter = (props) => {
503
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` }) }))] })] }));
504
512
  // Renderizar según el tipo de filtro
505
513
  if (filterType === "autocomplete") {
506
- 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 &&
507
515
  panelPosition &&
508
516
  typeof document !== "undefined" &&
509
517
  document.body &&
@@ -515,10 +523,10 @@ export const Filter = (props) => {
515
523
  : "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (e) => {
516
524
  e.preventDefault();
517
525
  handleStaticOptionSelect(option);
518
- }, 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)] }));
519
527
  }
520
528
  if (filterType === "date") {
521
- 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 &&
522
530
  panelPosition &&
523
531
  typeof document !== "undefined" &&
524
532
  document.body &&
@@ -535,7 +543,7 @@ export const Filter = (props) => {
535
543
  // Para searchSelect
536
544
  if (filterType === "searchSelect") {
537
545
  const searchSelectProps = props;
538
- 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 &&
539
547
  panelPosition &&
540
548
  typeof document !== "undefined" &&
541
549
  document.body &&
@@ -554,10 +562,10 @@ export const Filter = (props) => {
554
562
  // Mostrar X solo si hay un valor actual Y el texto del input coincide con ese valor
555
563
  const hasValue = !!currentValue;
556
564
  const valueMatches = hasValue && searchValue.trim() === currentValue;
557
- 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" }) }));
558
566
  }
559
567
  // Para text y number
560
- 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 &&
561
569
  panelPosition &&
562
570
  typeof document !== "undefined" &&
563
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
+ };
@@ -14,4 +14,12 @@ export { DataTable } from "./DataTable";
14
14
  export type { DataTableProps, DataTableColumn } from "./DataTable";
15
15
  export { Accordion } from "./Accordion";
16
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";
17
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;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,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"}
@@ -6,3 +6,7 @@ export { TabsGroup } from "./TabsGroup";
6
6
  export { TabPanel } from "./TabPanel";
7
7
  export { DataTable } from "./DataTable";
8
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";
@@ -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;AAGzC,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,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useEffect } from "react";
3
3
  import { normalizeIconClass } from "./iconUtils";
4
- export const Dialog = ({ isOpen, title, dialogBody, dialogActions, onClose, closeOnOverlayClick = false, }) => {
4
+ export const Dialog = ({ isOpen, title, children, footer, onClose, closeOnOverlayClick = false, }) => {
5
5
  // Prevenir scroll del body cuando el dialog está abierto
6
6
  useEffect(() => {
7
7
  if (isOpen) {
@@ -40,5 +40,5 @@ export const Dialog = ({ isOpen, title, dialogBody, dialogActions, onClose, clos
40
40
  overflowY: "auto",
41
41
  overflowX: "visible",
42
42
  maxHeight: "calc(90vh - 200px)"
43
- }, 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 }))] })] }));
44
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
  };
@@ -8,8 +8,6 @@ export { Dialog } from "./Dialog";
8
8
  export type { DialogProps } from "./Dialog";
9
9
  export { Loader } from "./Loader";
10
10
  export type { LoaderProps } from "./Loader";
11
- export { Filter } from "./Filter";
12
- export type { FilterProps } from "./Filter";
13
11
  export { FiltersDialog } from "./FiltersDialog";
14
12
  export type { FiltersDialogProps, FilterConfig } from "./FiltersDialog";
15
13
  export { Snackbar } from "./Snackbar";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -3,7 +3,6 @@ export { Avatar } from "./Avatar";
3
3
  export { RoadMap } from "./RoadMap";
4
4
  export { Dialog } from "./Dialog";
5
5
  export { Loader } from "./Loader";
6
- export { Filter } from "./Filter";
7
6
  export { FiltersDialog } from "./FiltersDialog";
8
7
  export { Snackbar } from "./Snackbar";
9
8
  export { SnackbarContainer } from "./SnackbarContainer";
@@ -1,7 +1,8 @@
1
- import { type ReactNode } from "react";
1
+ import { type ReactNode, type Dispatch, type SetStateAction } from "react";
2
2
  import { type PaginationInterface } from "../components/form-controls/Pagination";
3
- export interface ListCrudContextType<T> {
3
+ export interface CrudContextType<T> {
4
4
  list: Array<T> | undefined;
5
+ item: T | undefined;
5
6
  page: number;
6
7
  pages: number;
7
8
  total: number;
@@ -9,10 +10,16 @@ export interface ListCrudContextType<T> {
9
10
  isLoading: boolean;
10
11
  pagination: ReactNode;
11
12
  params: Record<string, any>;
13
+ extraData?: Record<string, any>;
14
+ setExtraData: Dispatch<SetStateAction<Record<string, any> | undefined>>;
12
15
  fetchItems: {
13
16
  execute: (params?: Record<string, any>) => Promise<void>;
14
17
  isLoading: boolean;
15
18
  };
19
+ fetchItem: {
20
+ execute: (params?: Record<string, any> | string | number) => Promise<T | undefined>;
21
+ isLoading: boolean;
22
+ };
16
23
  createItem: {
17
24
  execute: (item: T) => Promise<T | undefined | null>;
18
25
  isLoading: boolean;
@@ -26,25 +33,30 @@ export interface ListCrudContextType<T> {
26
33
  isLoading: boolean;
27
34
  };
28
35
  }
29
- export declare const ListCrudContext: import("react").Context<ListCrudContextType<any> | undefined>;
36
+ export declare const CrudContext: import("react").Context<CrudContextType<any> | undefined>;
30
37
  export interface PromiseWithOptions<TResult, TParams extends any[] = []> {
31
38
  execute: (...params: TParams) => Promise<TResult>;
32
39
  successMessage?: string;
33
40
  errorMessage?: string;
34
41
  }
35
- interface ListCrudProviderProps<T> {
42
+ interface CrudProviderProps<T> {
36
43
  children: ReactNode;
37
- getPromise: ((params?: Record<string, any>) => Promise<Array<T> | PaginationInterface<T> | undefined>) | PromiseWithOptions<Array<T> | PaginationInterface<T> | undefined, [
44
+ getPromise?: ((params?: Record<string, any>) => Promise<Array<T> | PaginationInterface<T> | undefined>) | PromiseWithOptions<Array<T> | PaginationInterface<T> | undefined, [
38
45
  params?: Record<string, any>
39
46
  ]>;
47
+ getItemPromise?: ((params?: Record<string, any> | string | number) => Promise<T | undefined>) | PromiseWithOptions<T | undefined, [
48
+ params?: Record<string, any> | string | number
49
+ ]>;
40
50
  postPromise?: ((item: T) => Promise<T | undefined | null>) | PromiseWithOptions<T | undefined | null, [item: T]>;
41
51
  putPromise?: ((item: T) => Promise<T | undefined | null>) | PromiseWithOptions<T | undefined | null, [item: T]>;
42
52
  deletePromise?: ((item: T) => Promise<void>) | PromiseWithOptions<void, [item: T]>;
43
53
  urlParams?: Array<string>;
44
54
  limit?: number;
45
55
  pageParam?: string;
56
+ singleItemId?: string | number;
57
+ extraData?: Record<string, any>;
46
58
  }
47
- export declare function ListCrudProvider<T>({ children, getPromise, postPromise, putPromise, deletePromise, limit, pageParam, urlParams, }: ListCrudProviderProps<T>): import("react/jsx-runtime").JSX.Element;
48
- export declare function useListCrud<T>(): ListCrudContextType<T>;
59
+ export declare function CrudProvider<T>({ children, getPromise, getItemPromise, postPromise, putPromise, deletePromise, limit, pageParam, urlParams, singleItemId, extraData: extraDataProp, }: CrudProviderProps<T>): import("react/jsx-runtime").JSX.Element;
60
+ export declare function useCrud<T>(): CrudContextType<T>;
49
61
  export {};
50
- //# sourceMappingURL=ListCrudContext.d.ts.map
62
+ //# sourceMappingURL=CrudContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CrudContext.d.ts","sourceRoot":"","sources":["../../src/contexts/CrudContext.tsx"],"names":[],"mappings":"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"}