flysoft-react-ui 1.2.4 → 1.2.6

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 (265) hide show
  1. package/AI_CONTEXT.md +1400 -217
  2. package/AI_INTEGRATION_GUIDE.md +343 -0
  3. package/INTEGRATION_GUIDE.md +60 -0
  4. package/README.md +5 -3
  5. package/dist/components/form-controls/Input.d.ts.map +1 -1
  6. package/dist/components/layout/Accordion.d.ts +1 -0
  7. package/dist/components/layout/Accordion.d.ts.map +1 -1
  8. package/dist/components/layout/DataTable.d.ts.map +1 -1
  9. package/dist/components/layout/DropdownMenu.d.ts +2 -1
  10. package/dist/components/layout/DropdownMenu.d.ts.map +1 -1
  11. package/dist/components/layout/DropdownPanel.d.ts +2 -1
  12. package/dist/components/layout/DropdownPanel.d.ts.map +1 -1
  13. package/dist/components/layout/Filter.d.ts +1 -0
  14. package/dist/components/layout/Filter.d.ts.map +1 -1
  15. package/dist/components/layout/Menu.d.ts +2 -1
  16. package/dist/components/layout/Menu.d.ts.map +1 -1
  17. package/dist/components/layout/TabsGroup.d.ts +1 -0
  18. package/dist/components/layout/TabsGroup.d.ts.map +1 -1
  19. package/dist/index.css +1 -1
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +11190 -24
  23. package/dist/index.js.map +1 -1
  24. package/dist/templates/forms/ContactForm.d.ts +1 -0
  25. package/dist/templates/forms/ContactForm.d.ts.map +1 -1
  26. package/dist/templates/forms/LoginForm.d.ts +1 -0
  27. package/dist/templates/forms/LoginForm.d.ts.map +1 -1
  28. package/dist/templates/forms/RegistrationForm.d.ts +1 -0
  29. package/dist/templates/forms/RegistrationForm.d.ts.map +1 -1
  30. package/dist/templates/layouts/DashboardLayout.d.ts +1 -0
  31. package/dist/templates/layouts/DashboardLayout.d.ts.map +1 -1
  32. package/dist/templates/layouts/SidebarLayout.d.ts +1 -0
  33. package/dist/templates/layouts/SidebarLayout.d.ts.map +1 -1
  34. package/dist/templates/patterns/FormPattern.d.ts +1 -0
  35. package/dist/templates/patterns/FormPattern.d.ts.map +1 -1
  36. package/dist/templates/patterns/ListPattern.d.ts +77 -0
  37. package/dist/templates/patterns/ListPattern.d.ts.map +1 -0
  38. package/package.json +8 -4
  39. package/dist/App.d.ts +0 -4
  40. package/dist/App.d.ts.map +0 -1
  41. package/dist/App.js +0 -30
  42. package/dist/components/ThemeSwitcher.js +0 -12
  43. package/dist/components/form-controls/AutocompleteInput.js +0 -680
  44. package/dist/components/form-controls/Button.js +0 -211
  45. package/dist/components/form-controls/Checkbox.js +0 -79
  46. package/dist/components/form-controls/CurrencyInput.js +0 -106
  47. package/dist/components/form-controls/DateInput.js +0 -578
  48. package/dist/components/form-controls/DatePicker.js +0 -144
  49. package/dist/components/form-controls/Input.js +0 -35
  50. package/dist/components/form-controls/LinkButton.js +0 -248
  51. package/dist/components/form-controls/Pagination.js +0 -23
  52. package/dist/components/form-controls/RadioButtonGroup.js +0 -220
  53. package/dist/components/form-controls/SearchSelectInput.js +0 -336
  54. package/dist/components/form-controls/index.js +0 -11
  55. package/dist/components/index.js +0 -7
  56. package/dist/components/layout/Accordion.js +0 -67
  57. package/dist/components/layout/AppLayout.js +0 -230
  58. package/dist/components/layout/Card.js +0 -54
  59. package/dist/components/layout/Collection.js +0 -18
  60. package/dist/components/layout/DataField.js +0 -38
  61. package/dist/components/layout/DataTable.js +0 -164
  62. package/dist/components/layout/DropdownMenu.js +0 -176
  63. package/dist/components/layout/DropdownPanel.js +0 -162
  64. package/dist/components/layout/Filter.js +0 -629
  65. package/dist/components/layout/Menu.js +0 -21
  66. package/dist/components/layout/TabPanel.js +0 -11
  67. package/dist/components/layout/TabsGroup.js +0 -52
  68. package/dist/components/layout/index.js +0 -12
  69. package/dist/components/utils/Avatar.js +0 -77
  70. package/dist/components/utils/Badge.js +0 -151
  71. package/dist/components/utils/Dialog.js +0 -44
  72. package/dist/components/utils/FiltersDialog.js +0 -104
  73. package/dist/components/utils/Loader.js +0 -44
  74. package/dist/components/utils/RoadMap.js +0 -139
  75. package/dist/components/utils/Skeleton.js +0 -10
  76. package/dist/components/utils/Snackbar.js +0 -136
  77. package/dist/components/utils/SnackbarContainer.js +0 -26
  78. package/dist/components/utils/iconUtils.js +0 -40
  79. package/dist/components/utils/index.js +0 -9
  80. package/dist/contexts/AppLayoutContext.js +0 -104
  81. package/dist/contexts/AuthContext.js +0 -224
  82. package/dist/contexts/CrudContext.js +0 -333
  83. package/dist/contexts/SnackbarContext.js +0 -41
  84. package/dist/contexts/ThemeContext.js +0 -197
  85. package/dist/contexts/index.js +0 -13
  86. package/dist/contexts/presets.js +0 -311
  87. package/dist/contexts/types.js +0 -1
  88. package/dist/docs/AccordionDocs.d.ts +0 -4
  89. package/dist/docs/AccordionDocs.d.ts.map +0 -1
  90. package/dist/docs/AccordionDocs.js +0 -21
  91. package/dist/docs/AuthDocs.tsx/AuthDocs.d.ts +0 -13
  92. package/dist/docs/AuthDocs.tsx/AuthDocs.d.ts.map +0 -1
  93. package/dist/docs/AuthDocs.tsx/AuthDocs.js +0 -18
  94. package/dist/docs/AuthDocs.tsx/AuthDocsContent.d.ts +0 -2
  95. package/dist/docs/AuthDocs.tsx/AuthDocsContent.d.ts.map +0 -1
  96. package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +0 -22
  97. package/dist/docs/AuthDocs.tsx/mockAuthService.d.ts +0 -24
  98. package/dist/docs/AuthDocs.tsx/mockAuthService.d.ts.map +0 -1
  99. package/dist/docs/AuthDocs.tsx/mockAuthService.js +0 -78
  100. package/dist/docs/AutocompleteInputDocs.d.ts +0 -4
  101. package/dist/docs/AutocompleteInputDocs.d.ts.map +0 -1
  102. package/dist/docs/AutocompleteInputDocs.js +0 -84
  103. package/dist/docs/AvatarDocs.d.ts +0 -4
  104. package/dist/docs/AvatarDocs.d.ts.map +0 -1
  105. package/dist/docs/AvatarDocs.js +0 -7
  106. package/dist/docs/BadgeDocs.d.ts +0 -4
  107. package/dist/docs/BadgeDocs.d.ts.map +0 -1
  108. package/dist/docs/BadgeDocs.js +0 -9
  109. package/dist/docs/ButtonDocs.d.ts +0 -4
  110. package/dist/docs/ButtonDocs.d.ts.map +0 -1
  111. package/dist/docs/ButtonDocs.js +0 -7
  112. package/dist/docs/CardDocs.d.ts +0 -4
  113. package/dist/docs/CardDocs.d.ts.map +0 -1
  114. package/dist/docs/CardDocs.js +0 -22
  115. package/dist/docs/CheckboxDocs.d.ts +0 -4
  116. package/dist/docs/CheckboxDocs.d.ts.map +0 -1
  117. package/dist/docs/CheckboxDocs.js +0 -7
  118. package/dist/docs/CurrencyInputDocs.d.ts +0 -4
  119. package/dist/docs/CurrencyInputDocs.d.ts.map +0 -1
  120. package/dist/docs/CurrencyInputDocs.js +0 -22
  121. package/dist/docs/DataFieldDocs.d.ts +0 -4
  122. package/dist/docs/DataFieldDocs.d.ts.map +0 -1
  123. package/dist/docs/DataFieldDocs.js +0 -7
  124. package/dist/docs/DataTableDocs.d.ts +0 -4
  125. package/dist/docs/DataTableDocs.d.ts.map +0 -1
  126. package/dist/docs/DataTableDocs.js +0 -244
  127. package/dist/docs/DateInputDocs.d.ts +0 -5
  128. package/dist/docs/DateInputDocs.d.ts.map +0 -1
  129. package/dist/docs/DateInputDocs.js +0 -19
  130. package/dist/docs/DatePickerDocs.d.ts +0 -5
  131. package/dist/docs/DatePickerDocs.d.ts.map +0 -1
  132. package/dist/docs/DatePickerDocs.js +0 -16
  133. package/dist/docs/DialogDocs.d.ts +0 -4
  134. package/dist/docs/DialogDocs.d.ts.map +0 -1
  135. package/dist/docs/DialogDocs.js +0 -13
  136. package/dist/docs/DocAdmin.d.ts +0 -4
  137. package/dist/docs/DocAdmin.d.ts.map +0 -1
  138. package/dist/docs/DocAdmin.js +0 -68
  139. package/dist/docs/DocsMenu.d.ts +0 -2
  140. package/dist/docs/DocsMenu.d.ts.map +0 -1
  141. package/dist/docs/DocsMenu.js +0 -5
  142. package/dist/docs/DocsRouter.d.ts +0 -4
  143. package/dist/docs/DocsRouter.d.ts.map +0 -1
  144. package/dist/docs/DocsRouter.js +0 -39
  145. package/dist/docs/DropdownMenuDocs.d.ts +0 -4
  146. package/dist/docs/DropdownMenuDocs.d.ts.map +0 -1
  147. package/dist/docs/DropdownMenuDocs.js +0 -66
  148. package/dist/docs/DropdownPanelDocs.d.ts +0 -4
  149. package/dist/docs/DropdownPanelDocs.d.ts.map +0 -1
  150. package/dist/docs/DropdownPanelDocs.js +0 -7
  151. package/dist/docs/ExampleFormDocs.d.ts +0 -4
  152. package/dist/docs/ExampleFormDocs.d.ts.map +0 -1
  153. package/dist/docs/ExampleFormDocs.js +0 -153
  154. package/dist/docs/FilterDocs.d.ts +0 -4
  155. package/dist/docs/FilterDocs.d.ts.map +0 -1
  156. package/dist/docs/FilterDocs.js +0 -130
  157. package/dist/docs/InputDocs.d.ts +0 -4
  158. package/dist/docs/InputDocs.d.ts.map +0 -1
  159. package/dist/docs/InputDocs.js +0 -17
  160. package/dist/docs/LinkButtonDocs.d.ts +0 -4
  161. package/dist/docs/LinkButtonDocs.d.ts.map +0 -1
  162. package/dist/docs/LinkButtonDocs.js +0 -7
  163. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +0 -2
  164. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +0 -1
  165. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +0 -47
  166. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts +0 -2
  167. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts.map +0 -1
  168. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.js +0 -34
  169. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts +0 -2
  170. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts.map +0 -1
  171. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.js +0 -66
  172. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts +0 -2
  173. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts.map +0 -1
  174. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.js +0 -7
  175. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts +0 -10
  176. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts.map +0 -1
  177. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.js +0 -39
  178. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts +0 -2
  179. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +0 -1
  180. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +0 -57
  181. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts +0 -9
  182. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts.map +0 -1
  183. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.js +0 -30
  184. package/dist/docs/LoaderDocs.d.ts +0 -4
  185. package/dist/docs/LoaderDocs.d.ts.map +0 -1
  186. package/dist/docs/LoaderDocs.js +0 -33
  187. package/dist/docs/MenuDocs.d.ts +0 -4
  188. package/dist/docs/MenuDocs.d.ts.map +0 -1
  189. package/dist/docs/MenuDocs.js +0 -26
  190. package/dist/docs/PaginationDocs.d.ts +0 -4
  191. package/dist/docs/PaginationDocs.d.ts.map +0 -1
  192. package/dist/docs/PaginationDocs.js +0 -38
  193. package/dist/docs/RadioButtonGroupDocs.d.ts +0 -4
  194. package/dist/docs/RadioButtonGroupDocs.d.ts.map +0 -1
  195. package/dist/docs/RadioButtonGroupDocs.js +0 -46
  196. package/dist/docs/RoadMapDocs.d.ts +0 -4
  197. package/dist/docs/RoadMapDocs.d.ts.map +0 -1
  198. package/dist/docs/RoadMapDocs.js +0 -171
  199. package/dist/docs/SearchSelectInputDocs.d.ts +0 -4
  200. package/dist/docs/SearchSelectInputDocs.d.ts.map +0 -1
  201. package/dist/docs/SearchSelectInputDocs.js +0 -168
  202. package/dist/docs/SkeletonDocs.d.ts +0 -4
  203. package/dist/docs/SkeletonDocs.d.ts.map +0 -1
  204. package/dist/docs/SkeletonDocs.js +0 -7
  205. package/dist/docs/SnackbarDocs.d.ts +0 -4
  206. package/dist/docs/SnackbarDocs.d.ts.map +0 -1
  207. package/dist/docs/SnackbarDocs.js +0 -69
  208. package/dist/docs/TabsGroupDocs.d.ts +0 -4
  209. package/dist/docs/TabsGroupDocs.d.ts.map +0 -1
  210. package/dist/docs/TabsGroupDocs.js +0 -38
  211. package/dist/docs/ThemeSwitcherDocs.d.ts +0 -4
  212. package/dist/docs/ThemeSwitcherDocs.d.ts.map +0 -1
  213. package/dist/docs/ThemeSwitcherDocs.js +0 -11
  214. package/dist/docs/docMockServices/empresaService.d.ts +0 -38
  215. package/dist/docs/docMockServices/empresaService.d.ts.map +0 -1
  216. package/dist/docs/docMockServices/empresaService.js +0 -125
  217. package/dist/docs/docMockServices/index.d.ts +0 -9
  218. package/dist/docs/docMockServices/index.d.ts.map +0 -1
  219. package/dist/docs/docMockServices/index.js +0 -8
  220. package/dist/docs/docMockServices/initialData.d.ts +0 -6
  221. package/dist/docs/docMockServices/initialData.d.ts.map +0 -1
  222. package/dist/docs/docMockServices/initialData.js +0 -132
  223. package/dist/docs/docMockServices/interfaces.d.ts +0 -38
  224. package/dist/docs/docMockServices/interfaces.d.ts.map +0 -1
  225. package/dist/docs/docMockServices/interfaces.js +0 -1
  226. package/dist/docs/docMockServices/personaEmpresaService.d.ts +0 -43
  227. package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +0 -1
  228. package/dist/docs/docMockServices/personaEmpresaService.js +0 -151
  229. package/dist/docs/docMockServices/personaService.d.ts +0 -39
  230. package/dist/docs/docMockServices/personaService.d.ts.map +0 -1
  231. package/dist/docs/docMockServices/personaService.js +0 -190
  232. package/dist/helpers/currencyFormat.js +0 -3
  233. package/dist/helpers/getErrorMessage.js +0 -13
  234. package/dist/helpers/getInitialLetters.js +0 -5
  235. package/dist/helpers/getQueryString.js +0 -13
  236. package/dist/helpers/index.js +0 -9
  237. package/dist/helpers/mappers.js +0 -27
  238. package/dist/helpers/nameValueArrayToObject.js +0 -3
  239. package/dist/helpers/objectToQueryString.js +0 -3
  240. package/dist/helpers/queryStringToObject.js +0 -13
  241. package/dist/helpers/regularExpressions.js +0 -5
  242. package/dist/hooks/index.js +0 -6
  243. package/dist/hooks/useAsyncRequest.js +0 -53
  244. package/dist/hooks/useBreakpoint.js +0 -59
  245. package/dist/hooks/useElementScroll.js +0 -58
  246. package/dist/hooks/useEnum.js +0 -21
  247. package/dist/hooks/useGlobalThemeStyles.js +0 -40
  248. package/dist/hooks/useThemeOverride.js +0 -99
  249. package/dist/interfaces/index.js +0 -1
  250. package/dist/interfaces/name-value.interface.js +0 -1
  251. package/dist/interfaces/pagination.interface.js +0 -1
  252. package/dist/main.d.ts +0 -2
  253. package/dist/main.d.ts.map +0 -1
  254. package/dist/main.js +0 -6
  255. package/dist/services/apiClient.js +0 -216
  256. package/dist/services/index.js +0 -1
  257. package/dist/styles.d.ts +0 -2
  258. package/dist/styles.d.ts.map +0 -1
  259. package/dist/styles.js +0 -3
  260. package/dist/templates/forms/ContactForm.js +0 -58
  261. package/dist/templates/forms/LoginForm.js +0 -36
  262. package/dist/templates/forms/RegistrationForm.js +0 -54
  263. package/dist/templates/layouts/DashboardLayout.js +0 -26
  264. package/dist/templates/layouts/SidebarLayout.js +0 -28
  265. package/dist/templates/patterns/FormPattern.js +0 -68
@@ -1,629 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useState, useEffect, useRef } from "react";
3
- import { createPortal } from "react-dom";
4
- import { useSearchParams } from "react-router-dom";
5
- import dayjs, {} from "dayjs";
6
- import { Button } from "../form-controls/Button";
7
- import { Input } from "../form-controls/Input";
8
- import { DateInput } from "../form-controls/DateInput";
9
- import { AutocompleteInput } from "../form-controls/AutocompleteInput";
10
- import { SearchSelectInput } from "../form-controls/SearchSelectInput";
11
- import { DataField } from "./DataField";
12
- import { normalizeIconClass } from "../utils/iconUtils";
13
- export const Filter = (props) => {
14
- const { paramName, label, staticOptions, inputWidth, value: propValue, onChange, hideEmpty = false, disabled = false, } = props;
15
- const filterType = props.filterType || "text";
16
- // Calcular el ancho por defecto según el tipo de filtro
17
- const defaultInputWidth = filterType === "date" || filterType === "autocomplete" ? "160px" : "200px";
18
- const finalInputWidth = inputWidth || defaultInputWidth;
19
- const [searchParams, setSearchParams] = useSearchParams();
20
- const urlValue = paramName
21
- ? searchParams.get(paramName) || undefined
22
- : undefined;
23
- // Usar propValue si está presente, sino usar urlValue
24
- const currentValue = propValue !== undefined ? propValue : urlValue;
25
- const [inputValue, setInputValue] = useState(currentValue || "");
26
- const [searchValue, setSearchValue] = useState(currentValue || "");
27
- const [dateValue, setDateValue] = useState(null);
28
- const [autocompleteValue, setAutocompleteValue] = useState(currentValue ?
29
- (props.filterType === "autocomplete" && props.multiple ? currentValue.split("|") : currentValue)
30
- : "");
31
- const [searchSelectValue, setSearchSelectValue] = useState(currentValue || undefined);
32
- const [searchSelectLabel, setSearchSelectLabel] = useState("");
33
- const [isUserTyping, setIsUserTyping] = useState(false);
34
- const [isOpen, setIsOpen] = useState(false);
35
- const [panelPosition, setPanelPosition] = useState(null);
36
- const containerRef = useRef(null);
37
- const panelRef = useRef(null);
38
- const inputRef = useRef(null);
39
- const searchInputRef = useRef(null);
40
- const searchSelectInputRef = useRef(null);
41
- const dateInputRef = useRef(null);
42
- const autocompleteInputRef = useRef(null);
43
- // Sincronizar el input con el valor actual (propValue o urlValue)
44
- useEffect(() => {
45
- if (filterType !== "autocomplete" &&
46
- filterType !== "search" &&
47
- filterType !== "searchSelect") {
48
- setInputValue(currentValue || "");
49
- }
50
- }, [currentValue, filterType]);
51
- // Sincronizar el searchValue con el valor actual (propValue o urlValue)
52
- useEffect(() => {
53
- if (filterType === "search") {
54
- setSearchValue(currentValue || "");
55
- }
56
- }, [currentValue, filterType]);
57
- // Sincronizar el searchSelectValue con el valor actual (propValue o urlValue)
58
- // y buscar el label si no está disponible
59
- useEffect(() => {
60
- if (filterType === "searchSelect" && currentValue) {
61
- const searchSelectProps = props;
62
- const getOptionLabel = searchSelectProps.getOptionLabel || ((item) => item.label || "");
63
- const getOptionValue = searchSelectProps.getOptionValue || ((item) => item.value || "");
64
- const onSingleSearchPromiseFn = searchSelectProps.onSingleSearchPromiseFn;
65
- // Si searchSelectValue es un objeto, extraer el label directamente
66
- if (searchSelectValue && typeof searchSelectValue === "object") {
67
- const label = getOptionLabel(searchSelectValue);
68
- const value = String(getOptionValue(searchSelectValue));
69
- if (value === String(currentValue)) {
70
- setSearchSelectLabel(label);
71
- return;
72
- }
73
- }
74
- // Si no tenemos el objeto completo, usar onSingleSearchPromiseFn para obtenerlo
75
- if (onSingleSearchPromiseFn) {
76
- onSingleSearchPromiseFn(currentValue)
77
- .then((option) => {
78
- if (option) {
79
- setSearchSelectValue(option);
80
- setSearchSelectLabel(getOptionLabel(option));
81
- }
82
- else {
83
- setSearchSelectLabel(String(currentValue));
84
- }
85
- })
86
- .catch(() => {
87
- setSearchSelectLabel(String(currentValue));
88
- });
89
- }
90
- else {
91
- setSearchSelectLabel(String(currentValue));
92
- }
93
- }
94
- else if (filterType === "searchSelect" && !currentValue) {
95
- setSearchSelectValue(undefined);
96
- setSearchSelectLabel("");
97
- }
98
- // eslint-disable-next-line react-hooks/exhaustive-deps
99
- }, [currentValue, filterType]);
100
- // Sincronizar el dateValue con el valor actual (propValue o urlValue)
101
- useEffect(() => {
102
- if (filterType === "date") {
103
- if (currentValue) {
104
- const date = dayjs(currentValue, "YYYY-MM-DD");
105
- setDateValue(date.isValid() ? date : null);
106
- }
107
- else {
108
- setDateValue(null);
109
- }
110
- }
111
- }, [currentValue, filterType]);
112
- // Sincronizar el autocompleteValue con el valor actual (propValue o urlValue)
113
- // Para autocomplete, mantener el value (no el label) para que AutocompleteInput pueda encontrar la opción
114
- useEffect(() => {
115
- if (filterType === "autocomplete") {
116
- const isMultiple = props.multiple;
117
- // Mantener el value, el AutocompleteInput se encargará de mostrar el label
118
- setAutocompleteValue(currentValue ? (isMultiple ? currentValue.split("|") : currentValue) : (isMultiple ? [] : ""));
119
- setIsUserTyping(false);
120
- }
121
- }, [currentValue, filterType, props]);
122
- // Cerrar el panel al hacer clic fuera
123
- useEffect(() => {
124
- if (!isOpen)
125
- return;
126
- const handleClickOutside = (event) => {
127
- const target = event.target;
128
- const isClickInsideContainer = containerRef.current?.contains(target);
129
- const isClickInsidePanel = panelRef.current?.contains(target);
130
- // Verificar si el click está dentro de un elemento con portal (DatePicker, AutocompleteInput, etc.)
131
- // Estos elementos tienen z-[2001] y están posicionados fixed
132
- let isClickInsidePortal = false;
133
- if (target instanceof Element) {
134
- let element = target;
135
- // Subir por el árbol DOM buscando elementos con z-index alto que sean portales
136
- while (element && element !== document.body) {
137
- const computedStyle = window.getComputedStyle(element);
138
- const zIndex = computedStyle.zIndex;
139
- const position = computedStyle.position;
140
- // Si encontramos un elemento fixed con z-index alto, probablemente es un portal
141
- if (position === "fixed" &&
142
- (zIndex === "2001" || parseInt(zIndex) >= 2001)) {
143
- isClickInsidePortal = true;
144
- break;
145
- }
146
- element = element.parentElement;
147
- }
148
- }
149
- if (!isClickInsideContainer &&
150
- !isClickInsidePanel &&
151
- !isClickInsidePortal) {
152
- setIsOpen(false);
153
- }
154
- };
155
- // Pequeño delay para asegurar que el portal esté montado
156
- const timer = setTimeout(() => {
157
- document.addEventListener("mousedown", handleClickOutside);
158
- }, 0);
159
- return () => {
160
- clearTimeout(timer);
161
- document.removeEventListener("mousedown", handleClickOutside);
162
- };
163
- }, [isOpen]);
164
- // Cerrar el panel si el componente se deshabilita
165
- useEffect(() => {
166
- if (disabled) {
167
- setIsOpen(false);
168
- }
169
- }, [disabled]);
170
- const handleSetFilter = () => {
171
- const newValue = inputValue.trim() || undefined;
172
- // Si hay onChange, llamarlo con el nuevo valor
173
- if (onChange) {
174
- onChange(newValue);
175
- }
176
- // Si hay paramName, actualizar el query param
177
- if (paramName) {
178
- const newSearchParams = new URLSearchParams(searchParams);
179
- if (newValue) {
180
- newSearchParams.set(paramName, newValue);
181
- }
182
- else {
183
- newSearchParams.delete(paramName);
184
- }
185
- // Usar replace: true para reemplazar la URL sin agregar una nueva entrada al historial
186
- setSearchParams(newSearchParams, { replace: true });
187
- }
188
- setIsOpen(false);
189
- };
190
- const handleSearchChange = (e) => {
191
- setSearchValue(e.target.value);
192
- };
193
- const handleSearchKeyDown = (e) => {
194
- if (e.key === "Enter") {
195
- handleSearchSubmit();
196
- }
197
- };
198
- const handleSearchSubmit = () => {
199
- const newValue = searchValue.trim() || undefined;
200
- // Si hay onChange, llamarlo con el nuevo valor
201
- if (onChange) {
202
- onChange(newValue);
203
- }
204
- // Si hay paramName, actualizar el query param
205
- if (paramName) {
206
- const newSearchParams = new URLSearchParams(searchParams);
207
- if (newValue) {
208
- newSearchParams.set(paramName, newValue);
209
- }
210
- else {
211
- newSearchParams.delete(paramName);
212
- }
213
- setSearchParams(newSearchParams, { replace: true });
214
- }
215
- };
216
- const handleSearchIconClick = () => {
217
- // Verificar si el texto actual coincide con el valor actual
218
- const valueMatches = currentValue && searchValue.trim() === currentValue;
219
- if (valueMatches) {
220
- // Si coincide, limpiar
221
- const newValue = undefined;
222
- // Si hay onChange, llamarlo con undefined
223
- if (onChange) {
224
- onChange(newValue);
225
- }
226
- // Si hay paramName, actualizar el query param
227
- if (paramName) {
228
- const newSearchParams = new URLSearchParams(searchParams);
229
- newSearchParams.delete(paramName);
230
- setSearchParams(newSearchParams, { replace: true });
231
- }
232
- setSearchValue("");
233
- }
234
- else {
235
- // Si no coincide, hacer submit
236
- handleSearchSubmit();
237
- }
238
- };
239
- const handleAutocompleteChange = (val) => {
240
- // Si viene undefined pero estamos en múltiple, podría ser por limpieza
241
- if (val !== undefined && Array.isArray(val) && props.multiple) {
242
- setAutocompleteValue(val);
243
- // En múltiple no manejamos "free text" que no sea opción
244
- setIsUserTyping(false);
245
- }
246
- else {
247
- // Marcar que el usuario está escribiendo libremente (input manual simple mode)
248
- setIsUserTyping(true);
249
- }
250
- };
251
- const handleAutocompleteSelect = () => {
252
- // Obtener el valor actual del input del AutocompleteInput
253
- const currentInputValue = autocompleteInputRef.current?.value || "";
254
- // Buscar si el texto actual coincide con alguna opción
255
- if (filterType === "autocomplete") {
256
- const autocompleteProps = props;
257
- const getOptionLabel = autocompleteProps.getOptionLabel || ((item) => item.label || "");
258
- const getOptionValue = autocompleteProps.getOptionValue || ((item) => item.value || "");
259
- // Buscar opción por label
260
- const matchingOption = autocompleteProps.options.find((opt) => getOptionLabel(opt).toLowerCase() === currentInputValue.toLowerCase());
261
- let newValue;
262
- if (autocompleteProps.multiple) {
263
- // Extraemos del estado que ya contiene el arreglo
264
- newValue = Array.isArray(autocompleteValue) && autocompleteValue.length > 0 ? autocompleteValue.join("|") : undefined;
265
- setIsUserTyping(false);
266
- }
267
- else {
268
- if (matchingOption) {
269
- newValue = String(getOptionValue(matchingOption));
270
- setAutocompleteValue(newValue);
271
- setIsUserTyping(false);
272
- }
273
- else if (currentInputValue.trim()) {
274
- // Si no coincide con ninguna opción, guardar el texto tal cual
275
- newValue = currentInputValue.trim();
276
- setAutocompleteValue(newValue);
277
- setIsUserTyping(false);
278
- }
279
- else {
280
- newValue = undefined;
281
- setAutocompleteValue("");
282
- setIsUserTyping(false);
283
- }
284
- }
285
- // Si hay onChange, llamarlo con el nuevo valor
286
- if (onChange) {
287
- onChange(newValue);
288
- }
289
- // Si hay paramName, actualizar el query param
290
- if (paramName) {
291
- const newSearchParams = new URLSearchParams(searchParams);
292
- if (newValue) {
293
- newSearchParams.set(paramName, newValue);
294
- }
295
- else {
296
- newSearchParams.delete(paramName);
297
- }
298
- setSearchParams(newSearchParams, { replace: true });
299
- }
300
- setIsOpen(false);
301
- }
302
- };
303
- const handleAutocompleteOptionSelect = (option) => {
304
- if (filterType === "autocomplete") {
305
- const autocompleteProps = props;
306
- const getOptionValue = autocompleteProps.getOptionValue || ((item) => item.value || "");
307
- const optionValueStr = String(getOptionValue(option));
308
- let newValueToEmit;
309
- if (autocompleteProps.multiple) {
310
- // El onChange directo del AutocompleteInput ya maneja el arreglo,
311
- // pero si por alguna razón onSelect atrapa esto, actualizamos el array (aunque lo hace en setAutocompleteValue arriba)
312
- // El array completo actual deberia estar en `autocompleteValue` pero asíncronamente;
313
- // mejor confiamos en la lógica de `AutocompleteInput` de toggle.
314
- // En modo onSelect individual (cuando se clickea una recien), solo la disparamos o dejamos que HandleAutoCompleteChange actúe.
315
- return; // Para múltiple dejamos que submit o el Autocomplete lo haga, o lo sincronizamos a nivel onChange general de autComplete y en Confirm.
316
- }
317
- else {
318
- newValueToEmit = optionValueStr;
319
- setAutocompleteValue(newValueToEmit);
320
- setIsUserTyping(false);
321
- }
322
- // Si hay onChange, llamarlo con el nuevo valor
323
- if (onChange) {
324
- onChange(newValueToEmit);
325
- }
326
- // Si hay paramName, actualizar el query param
327
- if (paramName) {
328
- const newSearchParams = new URLSearchParams(searchParams);
329
- newSearchParams.set(paramName, newValueToEmit);
330
- setSearchParams(newSearchParams, { replace: true });
331
- }
332
- setIsOpen(false);
333
- }
334
- };
335
- const handleSearchSelectChange = (value) => {
336
- if (filterType === "searchSelect") {
337
- const searchSelectProps = props;
338
- const getOptionValue = searchSelectProps.getOptionValue || ((item) => item.value || "");
339
- const getOptionLabel = searchSelectProps.getOptionLabel || ((item) => item.label || "");
340
- // Si value es un objeto, extraer el valor usando getOptionValue
341
- // Si value es un string/number, usarlo directamente
342
- let newValue;
343
- if (value === undefined || value === null) {
344
- newValue = undefined;
345
- setSearchSelectValue(undefined);
346
- setSearchSelectLabel("");
347
- }
348
- else if (typeof value === "object") {
349
- newValue = String(getOptionValue(value));
350
- setSearchSelectValue(value);
351
- setSearchSelectLabel(getOptionLabel(value));
352
- }
353
- else {
354
- newValue = String(value);
355
- setSearchSelectValue(value);
356
- // Si solo tenemos el valor, el useEffect se encargará de buscar el label
357
- setSearchSelectLabel("");
358
- }
359
- // Si hay onChange, llamarlo con el nuevo valor
360
- if (onChange) {
361
- onChange(newValue);
362
- }
363
- // Si hay paramName, actualizar el query param
364
- if (paramName) {
365
- const newSearchParams = new URLSearchParams(searchParams);
366
- if (newValue) {
367
- newSearchParams.set(paramName, newValue);
368
- }
369
- else {
370
- newSearchParams.delete(paramName);
371
- }
372
- setSearchParams(newSearchParams, { replace: true });
373
- }
374
- setIsOpen(false);
375
- }
376
- };
377
- const handleDateChange = (date) => {
378
- // Solo actualizar el estado temporal, no setear en la URL
379
- setDateValue(date);
380
- };
381
- const handleSetDateFilter = () => {
382
- let newValue;
383
- if (dateValue && dateValue.isValid()) {
384
- // Guardar como yyyy-mm-dd
385
- newValue = dateValue.format("YYYY-MM-DD");
386
- }
387
- else {
388
- newValue = undefined;
389
- }
390
- // Si hay onChange, llamarlo con el nuevo valor
391
- if (onChange) {
392
- onChange(newValue);
393
- }
394
- // Si hay paramName, actualizar el query param
395
- if (paramName) {
396
- const newSearchParams = new URLSearchParams(searchParams);
397
- if (newValue) {
398
- newSearchParams.set(paramName, newValue);
399
- }
400
- else {
401
- newSearchParams.delete(paramName);
402
- }
403
- setSearchParams(newSearchParams, { replace: true });
404
- }
405
- setIsOpen(false);
406
- };
407
- const handleStaticOptionSelect = (option) => {
408
- const newValue = option.value;
409
- // Si hay onChange, llamarlo con el nuevo valor
410
- if (onChange) {
411
- onChange(newValue);
412
- }
413
- // Si hay paramName, actualizar el query param
414
- if (paramName) {
415
- const newSearchParams = new URLSearchParams(searchParams);
416
- newSearchParams.set(paramName, newValue);
417
- setSearchParams(newSearchParams, { replace: true });
418
- }
419
- setIsOpen(false);
420
- };
421
- // Para staticOptions: mostrar el texto de la opción si el valor coincide (prioridad)
422
- // Para date: convertir yyyy-mm-dd a Dayjs y formatear para mostrar como dd/mm/yyyy
423
- // Para autocomplete: mostrar el label de la opción si el valor coincide
424
- const getDisplayValue = () => {
425
- // Primero verificar si el valor coincide con alguna opción estática
426
- if (staticOptions && currentValue) {
427
- const option = staticOptions.find((opt) => opt.value === currentValue);
428
- if (option) {
429
- return option.text;
430
- }
431
- }
432
- // Para autocomplete, buscar el label de la opción
433
- if (filterType === "autocomplete" && currentValue) {
434
- const autocompleteProps = props;
435
- if (autocompleteProps.options) {
436
- const getOptionLabel = autocompleteProps.getOptionLabel || ((item) => item.label || "");
437
- const getOptionValue = autocompleteProps.getOptionValue || ((item) => item.value || "");
438
- if (autocompleteProps.multiple) {
439
- const valuesArray = currentValue.split("|");
440
- const labels = valuesArray.map((val) => {
441
- const option = autocompleteProps.options.find((opt) => String(getOptionValue(opt)) === String(val));
442
- return option ? getOptionLabel(option) : val;
443
- });
444
- return labels.join(", ");
445
- }
446
- else {
447
- const option = autocompleteProps.options.find((opt) => String(getOptionValue(opt)) === String(currentValue));
448
- if (option) {
449
- return getOptionLabel(option);
450
- }
451
- }
452
- }
453
- }
454
- // Para searchSelect, mostrar el label guardado o buscar el label del objeto
455
- if (filterType === "searchSelect" && currentValue) {
456
- if (searchSelectLabel) {
457
- return searchSelectLabel;
458
- }
459
- // Si tenemos el objeto completo, extraer el label
460
- if (searchSelectValue && typeof searchSelectValue === "object") {
461
- const searchSelectProps = props;
462
- const getOptionLabel = searchSelectProps.getOptionLabel || ((item) => item.label || "");
463
- return getOptionLabel(searchSelectValue);
464
- }
465
- }
466
- // Si no hay opción estática que coincida, formatear según el tipo
467
- if (filterType === "date" && currentValue) {
468
- const date = dayjs(currentValue, "YYYY-MM-DD");
469
- if (date.isValid()) {
470
- return date.format("DD/MM/YYYY");
471
- }
472
- }
473
- return currentValue || "";
474
- };
475
- const handleClearFilter = (e) => {
476
- e.stopPropagation();
477
- // Si hay onChange, llamarlo con undefined para limpiar
478
- if (onChange) {
479
- onChange(undefined);
480
- }
481
- // Si hay paramName, actualizar el query param
482
- if (paramName) {
483
- const newSearchParams = new URLSearchParams(searchParams);
484
- newSearchParams.delete(paramName);
485
- setSearchParams(newSearchParams, { replace: true });
486
- }
487
- };
488
- const handleTogglePanel = () => {
489
- if (disabled)
490
- return;
491
- if (!isOpen) {
492
- // Calcular posición antes de abrir
493
- if (containerRef.current) {
494
- const rect = containerRef.current.getBoundingClientRect();
495
- setPanelPosition({
496
- top: rect.bottom + window.scrollY + 4,
497
- left: rect.left + window.scrollX,
498
- width: rect.width,
499
- });
500
- }
501
- }
502
- setIsOpen(!isOpen);
503
- };
504
- // Actualizar posición cuando se abre o cuando cambia el scroll
505
- useEffect(() => {
506
- if (isOpen && containerRef.current) {
507
- const updatePosition = () => {
508
- const rect = containerRef.current?.getBoundingClientRect();
509
- if (rect) {
510
- setPanelPosition({
511
- top: rect.bottom + window.scrollY + 4,
512
- left: rect.left + window.scrollX,
513
- width: rect.width,
514
- });
515
- }
516
- };
517
- updatePosition();
518
- window.addEventListener("scroll", updatePosition, true);
519
- window.addEventListener("resize", updatePosition);
520
- return () => {
521
- window.removeEventListener("scroll", updatePosition, true);
522
- window.removeEventListener("resize", updatePosition);
523
- };
524
- }
525
- }, [isOpen]);
526
- // Hacer foco en el input cuando se abre el panel
527
- useEffect(() => {
528
- if (isOpen) {
529
- // Pequeño delay para asegurar que el DOM esté actualizado
530
- const timer = setTimeout(() => {
531
- if (filterType === "text" || filterType === "number") {
532
- inputRef.current?.focus();
533
- }
534
- else if (filterType === "date") {
535
- dateInputRef.current?.focus();
536
- }
537
- else if (filterType === "autocomplete") {
538
- autocompleteInputRef.current?.focus();
539
- }
540
- // searchSelect no necesita focus porque usa un Dialog interno
541
- }, 50);
542
- return () => clearTimeout(timer);
543
- }
544
- }, [isOpen, filterType]);
545
- // Si hideEmpty es true y no hay valor, no renderizar el componente
546
- if (hideEmpty && !currentValue) {
547
- return null;
548
- }
549
- // Contenedor tipo badge con diseño similar al Input
550
- // Altura ajustada para coincidir con input sm: py-1.5 (6px arriba y abajo) + text-sm (14px línea) = ~26px total
551
- 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 cursor-pointer", "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` }) }))] })] }));
552
- // Renderizar según el tipo de filtro
553
- if (filterType === "autocomplete") {
554
- 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 &&
555
- panelPosition &&
556
- typeof document !== "undefined" &&
557
- document.body &&
558
- createPortal(_jsx("div", { ref: panelRef, className: "fixed z-[2001] w-fit rounded-md border border-[var(--color-border-default)] bg-[var(--color-bg-default)] shadow-[var(--shadow-lg)] p-4", style: {
559
- top: `${panelPosition.top}px`,
560
- left: `${panelPosition.left}px`,
561
- }, children: _jsxs("div", { className: "space-y-3", children: [staticOptions && staticOptions.length > 0 && (_jsx("ul", { className: "py-1 max-h-60 overflow-auto list-none pl-0", children: staticOptions.map((option) => (_jsx("li", { className: `px-3 py-2 cursor-pointer flex items-center justify-start text-left gap-2 text-sm rounded transition-colors ${currentValue === option.value
562
- ? "bg-[var(--color-primary-soft)] text-[var(--color-primary)]"
563
- : "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (e) => {
564
- e.preventDefault();
565
- handleStaticOptionSelect(option);
566
- }, children: _jsx("span", { className: "font-[var(--font-default)]", children: option.text }) }, option.value))) })), _jsxs("div", { className: "flex items-center justify-start 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, multiple: props.multiple, onSelectOption: handleAutocompleteOptionSelect, disabled: disabled }) }), _jsx(Button, { onClick: handleAutocompleteSelect, icon: props.multiple ? "fa-check" : "fa-arrow-right", variant: "ghost" })] })] }) }), document.body)] }));
567
- }
568
- if (filterType === "date") {
569
- 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 &&
570
- panelPosition &&
571
- typeof document !== "undefined" &&
572
- document.body &&
573
- createPortal(_jsx("div", { ref: panelRef, className: "fixed z-[2001] w-fit rounded-md border border-[var(--color-border-default)] bg-[var(--color-bg-default)] shadow-[var(--shadow-lg)] p-4", style: {
574
- top: `${panelPosition.top}px`,
575
- left: `${panelPosition.left}px`,
576
- }, children: _jsxs("div", { className: "space-y-3", children: [staticOptions && staticOptions.length > 0 && (_jsx("ul", { className: "py-1 max-h-60 overflow-auto list-none pl-0", children: staticOptions.map((option) => (_jsx("li", { className: `px-3 py-2 cursor-pointer flex items-center justify-start text-left gap-2 text-sm rounded transition-colors ${currentValue === option.value
577
- ? "bg-[var(--color-primary-soft)] text-[var(--color-primary)]"
578
- : "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (e) => {
579
- e.preventDefault();
580
- handleStaticOptionSelect(option);
581
- }, children: _jsx("span", { className: "font-[var(--font-default)]", children: option.text }) }, option.value))) })), _jsxs("div", { className: "flex items-center justify-start gap-2", children: [_jsx("div", { style: { width: finalInputWidth }, children: _jsx(DateInput, { ref: dateInputRef, value: dateValue, onChange: handleDateChange, format: "dd/mm/yyyy" }) }), _jsx(Button, { onClick: handleSetDateFilter, icon: "fa-arrow-right", variant: "ghost" })] })] }) }), document.body)] }));
582
- }
583
- // Para searchSelect
584
- if (filterType === "searchSelect") {
585
- const searchSelectProps = props;
586
- 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 &&
587
- panelPosition &&
588
- typeof document !== "undefined" &&
589
- document.body &&
590
- createPortal(_jsx("div", { ref: panelRef, className: "fixed z-[2001] w-fit rounded-md border border-[var(--color-border-default)] bg-[var(--color-bg-default)] shadow-[var(--shadow-lg)] p-4", style: {
591
- top: `${panelPosition.top}px`,
592
- left: `${panelPosition.left}px`,
593
- }, children: _jsxs("div", { className: "space-y-3", children: [staticOptions && staticOptions.length > 0 && (_jsx("ul", { className: "py-1 max-h-60 overflow-auto list-none pl-0", children: staticOptions.map((option) => (_jsx("li", { className: `px-3 py-2 cursor-pointer flex items-center justify-start text-left gap-2 text-sm rounded transition-colors ${currentValue === option.value
594
- ? "bg-[var(--color-primary-soft)] text-[var(--color-primary)]"
595
- : "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (e) => {
596
- e.preventDefault();
597
- handleStaticOptionSelect(option);
598
- }, children: _jsx("span", { className: "font-[var(--font-default)]", children: option.text }) }, option.value))) })), _jsx("div", { style: { width: finalInputWidth }, children: _jsx(SearchSelectInput, { ref: searchSelectInputRef, value: searchSelectValue, onChange: handleSearchSelectChange, onSearchPromiseFn: searchSelectProps.onSearchPromiseFn, onSingleSearchPromiseFn: searchSelectProps.onSingleSearchPromiseFn, getOptionLabel: searchSelectProps.getOptionLabel, getOptionValue: searchSelectProps.getOptionValue, renderOption: searchSelectProps.renderOption, dialogTitle: searchSelectProps.dialogTitle, noResultsText: searchSelectProps.noResultsText }) })] }) }), document.body)] }));
599
- }
600
- // Para search
601
- if (filterType === "search") {
602
- // Mostrar X solo si hay un valor actual Y el texto del input coincide con ese valor
603
- const hasValue = !!currentValue;
604
- const valueMatches = hasValue && searchValue.trim() === currentValue;
605
- 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" }) }));
606
- }
607
- // Para text y number
608
- 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 &&
609
- panelPosition &&
610
- typeof document !== "undefined" &&
611
- document.body &&
612
- createPortal(_jsx("div", { ref: panelRef, className: "fixed z-[2001] w-fit rounded-md border border-[var(--color-border-default)] bg-[var(--color-bg-default)] shadow-[var(--shadow-lg)] p-4", style: {
613
- top: `${panelPosition.top}px`,
614
- left: `${panelPosition.left}px`,
615
- }, children: _jsxs("div", { className: "space-y-3", children: [staticOptions && staticOptions.length > 0 && (_jsx("ul", { className: "py-1 max-h-60 overflow-auto list-none pl-0", children: staticOptions.map((option) => (_jsx("li", { className: `px-3 py-2 cursor-pointer flex items-center justify-start text-left gap-2 text-sm rounded transition-colors ${urlValue === option.value
616
- ? "bg-[var(--color-primary-soft)] text-[var(--color-primary)]"
617
- : "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (e) => {
618
- e.preventDefault();
619
- handleStaticOptionSelect(option);
620
- }, children: _jsx("span", { className: "font-[var(--font-default)]", children: option.text }) }, option.value))) })), _jsxs("div", { className: "flex items-center justify-start gap-2", children: [_jsx("div", { style: { width: finalInputWidth }, children: _jsx(Input, { ref: inputRef, type: filterType === "number" ? "number" : "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), placeholder: "Ingresa un valor", min: filterType === "number"
621
- ? props.min
622
- : undefined, max: filterType === "number"
623
- ? props.max
624
- : undefined, onKeyDown: (e) => {
625
- if (e.key === "Enter") {
626
- handleSetFilter();
627
- }
628
- } }) }), _jsx(Button, { onClick: handleSetFilter, icon: "fa-arrow-right", variant: "ghost" })] })] }) }), document.body)] }));
629
- };
@@ -1,21 +0,0 @@
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
- };
@@ -1,11 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from "react";
3
- import { useTabsContext } from "./TabsGroup";
4
- export const TabPanel = ({ children, tabId }) => {
5
- const { activeTab } = useTabsContext();
6
- const isActive = activeTab.toString() === tabId.toString();
7
- if (!isActive) {
8
- return null;
9
- }
10
- return (_jsx("div", { role: "tabpanel", className: "w-full font-[var(--font-default)]", children: children }));
11
- };