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,230 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React, { useState, useRef } from "react";
3
- import { useBreakpoint } from "../../hooks";
4
- import { useElementScroll } from "../../hooks/useElementScroll";
5
- import { Button } from "../form-controls";
6
- export const AppLayout = ({ navbar, leftDrawer, contentFooter, children, className = "", }) => {
7
- // Extract values from interfaces
8
- const navBarLeftNode = navbar?.navBarLeftNode;
9
- const navBarRightNode = navbar?.navBarRightNode;
10
- const fullWidthNavbar = navbar?.fullWidthNavbar ?? true;
11
- const navbarHeight = navbar?.height ?? "64px";
12
- const navbarClassName = navbar?.className || "";
13
- const leftDrawerHeader = leftDrawer?.headerNode;
14
- const leftDrawerContent = leftDrawer?.contentNode;
15
- const leftDrawerFooter = leftDrawer?.footerNode;
16
- const leftDrawerClassName = leftDrawer?.className || "";
17
- const leftDrawerWidth = leftDrawer?.width;
18
- const { isMobile, isTablet } = useBreakpoint();
19
- const contentRef = useRef(null);
20
- const { scrollY, scrollDirection } = useElementScroll(contentRef);
21
- const [isMobileDrawerOpen, setIsMobileDrawerOpen] = useState(false);
22
- const [isNavbarVisible, setIsNavbarVisible] = useState(true);
23
- const isNavbarVisibleRef = useRef(isNavbarVisible);
24
- const isTransitioningRef = useRef(false);
25
- const lastScrollYRef = useRef(0);
26
- // Determinar si hay algún contenido en el drawer izquierdo
27
- const hasLeftDrawerContent = leftDrawerHeader || leftDrawerContent || leftDrawerFooter;
28
- const shouldShowMobileDrawer = isMobile || isTablet;
29
- const shouldShowDesktopDrawer = !shouldShowMobileDrawer && hasLeftDrawerContent;
30
- // Determinar si debemos mostrar el navbar
31
- // Se muestra si hay navBarLeftNode o navBarRightNode o si estamos en móvil/tablet con contenido en el drawer
32
- const shouldShowNavbar = navBarLeftNode ||
33
- navBarRightNode ||
34
- (shouldShowMobileDrawer && hasLeftDrawerContent);
35
- // Mantener el ref sincronizado con el estado
36
- React.useEffect(() => {
37
- isNavbarVisibleRef.current = isNavbarVisible;
38
- // Marcar que estamos en transición por 350ms (duración de la transición + margen)
39
- isTransitioningRef.current = true;
40
- const timer = setTimeout(() => {
41
- isTransitioningRef.current = false;
42
- }, 350);
43
- return () => clearTimeout(timer);
44
- }, [isNavbarVisible]);
45
- // Controlar visibilidad del navbar basado en scroll con histeresis mejorada
46
- React.useEffect(() => {
47
- // Ignorar cambios durante transiciones o cambios muy pequeños de scroll
48
- if (isTransitioningRef.current) {
49
- return;
50
- }
51
- const SCROLL_DELTA_THRESHOLD = 5; // Mínimo cambio de scroll para considerar
52
- const scrollDelta = Math.abs(scrollY - lastScrollYRef.current);
53
- // Ignorar cambios muy pequeños que pueden ser causados por el cambio de padding
54
- if (scrollDelta < SCROLL_DELTA_THRESHOLD && lastScrollYRef.current > 0) {
55
- return;
56
- }
57
- const SHOW_THRESHOLD = 80;
58
- const HIDE_THRESHOLD = 120;
59
- // Verificar si estamos cerca del final del scroll (margen de error de 10px)
60
- const element = contentRef.current;
61
- const isNearBottom = element
62
- ? Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 10
63
- : false;
64
- let shouldBeVisible;
65
- if (scrollY < SHOW_THRESHOLD) {
66
- // Siempre mostrar navbar cerca del top
67
- shouldBeVisible = true;
68
- }
69
- else if (scrollDirection === "down" &&
70
- scrollY > HIDE_THRESHOLD &&
71
- !isNearBottom) {
72
- // Ocultar navbar al hacer scroll hacia abajo, excepto si estamos cerca del final
73
- shouldBeVisible = false;
74
- }
75
- else if (scrollDirection === "up" && scrollY > SHOW_THRESHOLD) {
76
- // Mostrar navbar al hacer scroll hacia arriba
77
- shouldBeVisible = true;
78
- }
79
- else if (isNearBottom && scrollDirection === "down") {
80
- // Si estamos en el final y scrolleamos hacia abajo, mantener el estado actual
81
- return;
82
- }
83
- else {
84
- // No cambiar el estado si scrollDirection es null o no se cumple ninguna condición
85
- return;
86
- }
87
- // Solo actualizar el estado si hay un cambio real
88
- if (shouldBeVisible !== isNavbarVisibleRef.current) {
89
- lastScrollYRef.current = scrollY;
90
- setIsNavbarVisible(shouldBeVisible);
91
- }
92
- else {
93
- // Actualizar la referencia del scroll incluso si no cambiamos la visibilidad
94
- lastScrollYRef.current = scrollY;
95
- }
96
- }, [scrollDirection, scrollY]);
97
- const handleMobileDrawerToggle = () => {
98
- setIsMobileDrawerOpen(!isMobileDrawerOpen);
99
- };
100
- const handleOverlayClick = () => {
101
- setIsMobileDrawerOpen(false);
102
- };
103
- // Clases base del layout
104
- const layoutClasses = `
105
- flex flex-col w-full ${navbar?.navBarLeftNode || navbar?.navBarRightNode || leftDrawer?.contentNode || leftDrawer?.headerNode || leftDrawer?.footerNode ? "h-screen overflow-hidden" : "h-auto"}
106
- font-[var(--font-default)]
107
- ${className}
108
- `;
109
- // Clases del navbar
110
- const navbarClasses = `${fullWidthNavbar
111
- ? `z-[1000] fixed top-0 left-0 right-0 overflow-hidden`
112
- : `relative z-[1000] overflow-hidden`} ${navbarClassName}`.trim();
113
- // Estilos inline para la transformación
114
- // Cuando fullWidthNavbar es false, solo usamos height para ocultar (sin transform)
115
- // Cuando fullWidthNavbar es true, usamos transform para ocultar (manteniendo height)
116
- const navbarStyle = fullWidthNavbar
117
- ? {
118
- transform: isNavbarVisible ? "translateY(0)" : "translateY(-100%)",
119
- transition: "transform 100ms ease-in",
120
- willChange: "transform",
121
- height: navbarHeight, // Override any height classes in className
122
- }
123
- : {
124
- height: isNavbarVisible ? navbarHeight : "0",
125
- minHeight: isNavbarVisible ? navbarHeight : "0",
126
- maxHeight: isNavbarVisible ? navbarHeight : "0",
127
- transition: "height 100ms ease-in, min-height 100ms ease-in, max-height 100ms ease-in",
128
- overflow: "hidden",
129
- };
130
- const navbarContentClasses = `flex items-center justify-between gap-2`;
131
- // Style for navbar content with dynamic height
132
- // When fullWidthNavbar is false and hidden, set height to 0 to not occupy space
133
- // When fullWidthNavbar is true, always maintain height to prevent layout shifts
134
- const navbarContentStyle = {
135
- height: fullWidthNavbar || isNavbarVisible ? navbarHeight : "0",
136
- maxHeight: fullWidthNavbar || isNavbarVisible ? navbarHeight : "0",
137
- overflow: "hidden",
138
- transition: "height 100ms ease-in, max-height 100ms ease-in",
139
- opacity: isNavbarVisible || fullWidthNavbar ? 1 : 0,
140
- };
141
- const navbarLeftClasses = `flex items-center gap-2`;
142
- const navbarRightClasses = `flex items-center gap-2`;
143
- // Clases del contenido principal
144
- const mainClasses = `flex flex-1 overflow-hidden transition-all duration-100 ease-in`;
145
- // Style for main content with dynamic navbar height padding
146
- // No padding here anymore, it's handled by individual elements
147
- const mainStyle = {};
148
- // Style for the main content area (actual scrollable area)
149
- // When fullWidthNavbar is true, we need top padding to avoid being covered by fixed navbar
150
- const contentStyle = fullWidthNavbar && shouldShowNavbar && isNavbarVisible
151
- ? { paddingTop: navbarHeight }
152
- : {};
153
- // Clases del drawer izquierdo (contenedor principal)
154
- // width se aplica como estilo inline para tener prioridad sobre className
155
- const leftDrawerClasses = `
156
- ${leftDrawerWidth ? "" : "w-64"} bg-[var(--color-bg-default)]
157
- flex-shrink-0 flex flex-col
158
- transition-all duration-100 ease-in
159
- ${leftDrawerClassName}
160
- `
161
- .trim()
162
- .replace(/\s+/g, " ");
163
- // Style for left drawer with dynamic height and positioning
164
- const leftDrawerStyle = {
165
- ...(leftDrawerWidth ? { width: leftDrawerWidth } : {}),
166
- height: "100%", // Siempre 100% para evitar huecos en la parte superior
167
- };
168
- if (fullWidthNavbar) {
169
- // Si el navbar es fullwidth, el drawer mide 100% y usamos padding para que el contenido
170
- // no quede debajo del navbar fixed.
171
- leftDrawerStyle.paddingTop =
172
- shouldShowNavbar && isNavbarVisible ? navbarHeight : "0px";
173
- leftDrawerStyle.transition = "padding-top 100ms ease-in";
174
- }
175
- else {
176
- // Si no es fullwidth, el drawer está al lado del navbar.
177
- // No necesitamos marginTop ni height dinámico porque ya está en un flex-row
178
- // y queremos que ocupe siempre todo el alto desde el borde superior.
179
- leftDrawerStyle.marginTop = "0px";
180
- leftDrawerStyle.transition = "padding-top 100ms ease-in";
181
- }
182
- // Clases del contenedor que incluye drawer y contenido (cuando fullWidthNavbar es false)
183
- const contentWrapperClasses = fullWidthNavbar
184
- ? ""
185
- : `flex flex-row flex-1 overflow-hidden`;
186
- // Clases del contenedor que incluye navbar y main (cuando fullWidthNavbar es false)
187
- const drawerAndContentClasses = fullWidthNavbar
188
- ? ""
189
- : `flex flex-col flex-1 overflow-hidden`;
190
- // Style for drawer and content wrapper with dynamic navbar height padding
191
- const drawerAndContentStyle = !fullWidthNavbar && shouldShowNavbar && isNavbarVisible
192
- ? { paddingTop: 0 }
193
- : {};
194
- // Clases del header del drawer (fijo arriba)
195
- const leftDrawerHeaderClasses = `
196
- flex-shrink-0
197
- `;
198
- // Clases del contenido del drawer (scrolleable sin scrollbar visible)
199
- const leftDrawerContentClasses = `
200
- flex-1 overflow-y-auto scrollbar-hide
201
- `;
202
- // Clases del footer del drawer (fijo abajo)
203
- const leftDrawerFooterClasses = `
204
- flex-shrink-0
205
- `;
206
- const contentClasses = `
207
- flex-1 overflow-y-auto flex flex-col
208
- `;
209
- // Clases del overlay móvil
210
- const overlayClasses = `
211
- fixed inset-0 bg-black/50 backdrop-blur-sm z-[1998]
212
- `;
213
- // Clases del drawer móvil
214
- const mobileDrawerBaseClasses = `
215
- fixed top-0 left-0 h-screen w-64 max-w-[80vw]
216
- bg-[var(--color-bg-default)] shadow-[var(--shadow-xl)]
217
- transform -translate-x-full transition-transform duration-100 ease-in
218
- z-[1999] flex flex-col
219
- ${leftDrawerClassName}
220
- `
221
- .trim()
222
- .replace(/\s+/g, " ");
223
- // Style for mobile drawer with dynamic width
224
- const mobileDrawerStyle = leftDrawerWidth ? { width: leftDrawerWidth } : {};
225
- const mobileDrawerOpenClasses = `translate-x-0`;
226
- const mobileDrawerContentClasses = `
227
- flex-1 overflow-y-auto scrollbar-hide
228
- `;
229
- return (_jsxs("div", { className: layoutClasses, children: [fullWidthNavbar ? (_jsxs(_Fragment, { children: [shouldShowNavbar && (_jsx("nav", { className: navbarClasses, style: navbarStyle, children: _jsxs("div", { className: navbarContentClasses, style: navbarContentStyle, children: [_jsxs("div", { className: navbarLeftClasses, children: [shouldShowMobileDrawer && hasLeftDrawerContent && (_jsx("div", { className: "pr-4 lg:px-4 md:px-3", children: _jsx(Button, { variant: "ghost", icon: "fa-bars", onClick: handleMobileDrawerToggle, "aria-label": "Abrir men\u00FA" }) })), navBarLeftNode && (_jsx("div", { children: typeof navBarLeftNode === "string" ? (_jsx("span", { children: navBarLeftNode })) : (navBarLeftNode) }))] }), navBarRightNode && (_jsx("div", { className: navbarRightClasses, children: typeof navBarRightNode === "string" ? (_jsx("span", { children: navBarRightNode })) : (navBarRightNode) }))] }) })), _jsxs("div", { className: mainClasses, style: mainStyle, children: [shouldShowDesktopDrawer && (_jsxs("aside", { className: leftDrawerClasses, style: leftDrawerStyle, children: [leftDrawerHeader && (_jsx("div", { className: leftDrawerHeaderClasses, children: leftDrawerHeader })), leftDrawerContent && (_jsx("div", { className: leftDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: leftDrawerFooterClasses, children: leftDrawerFooter }))] })), _jsxs("main", { ref: contentRef, className: contentClasses, style: contentStyle, children: [_jsx("div", { className: "flex-1", children: children }), contentFooter && _jsx("div", { role: "contentinfo", children: contentFooter })] })] })] })) : (_jsx(_Fragment, { children: _jsxs("div", { className: contentWrapperClasses, children: [shouldShowDesktopDrawer && (_jsxs("aside", { className: leftDrawerClasses, style: leftDrawerStyle, children: [leftDrawerHeader && (_jsx("div", { className: leftDrawerHeaderClasses, children: leftDrawerHeader })), leftDrawerContent && (_jsx("div", { className: leftDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: leftDrawerFooterClasses, children: leftDrawerFooter }))] })), _jsxs("div", { className: drawerAndContentClasses, style: drawerAndContentStyle, children: [shouldShowNavbar && (_jsx("nav", { className: navbarClasses, style: navbarStyle, children: _jsxs("div", { className: navbarContentClasses, style: navbarContentStyle, children: [_jsxs("div", { className: navbarLeftClasses, children: [shouldShowMobileDrawer && hasLeftDrawerContent && (_jsx("div", { className: "pr-4 px-2", children: _jsx(Button, { variant: "ghost", icon: "fa-bars", onClick: handleMobileDrawerToggle, "aria-label": "Abrir men\u00FA" }) })), navBarLeftNode && (_jsx("div", { children: typeof navBarLeftNode === "string" ? (_jsx("span", { children: navBarLeftNode })) : (navBarLeftNode) }))] }), navBarRightNode && (_jsx("div", { className: navbarRightClasses, children: typeof navBarRightNode === "string" ? (_jsx("span", { children: navBarRightNode })) : (navBarRightNode) }))] }) })), _jsxs("main", { ref: contentRef, className: contentClasses, style: contentStyle, children: [_jsx("div", { className: "flex-1", children: children }), contentFooter && _jsx("div", { role: "contentinfo", children: contentFooter })] })] })] }) })), shouldShowMobileDrawer && hasLeftDrawerContent && isMobileDrawerOpen && (_jsx("div", { className: overlayClasses, onClick: handleOverlayClick })), shouldShowMobileDrawer && hasLeftDrawerContent && (_jsxs("aside", { className: `${mobileDrawerBaseClasses} ${isMobileDrawerOpen ? mobileDrawerOpenClasses : ""}`, style: mobileDrawerStyle, children: [_jsxs("div", { className: "flex-shrink-0 flex items-center justify-between", children: [leftDrawerHeader ? (_jsx("div", { className: "flex-1", children: leftDrawerHeader })) : (_jsx("div", { className: "flex-1" })), _jsx("div", { className: "absolute top-3 right-2", children: _jsx(Button, { variant: "ghost", icon: "fa-times", onClick: handleMobileDrawerToggle, "aria-label": "Cerrar men\u00FA" }) })] }), leftDrawerContent && (_jsx("div", { className: mobileDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: "flex-shrink-0", children: leftDrawerFooter }))] }))] }));
230
- };
@@ -1,54 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { twMerge } from "tailwind-merge";
4
- export const Card = ({ title, subtitle, children, className = "", headerActions, footer, variant = "default", alwaysDisplayHeaderActions = false, headerClassName = "", contentClassName = "", footerClassName = "", compact = false, }) => {
5
- const variantClasses = {
6
- default: "border-[var(--color-border-default)]",
7
- elevated: "border-[var(--color-border-default)] shadow-[var(--shadow-lg)]",
8
- outlined: "border-[var(--color-gray-300)]",
9
- };
10
- // Unimos las clases usando twMerge para consistencia
11
- const mergedClasses = twMerge("bg-[var(--color-bg-default)] rounded-lg border font-[var(--font-default)]", variantClasses[variant], className);
12
- // Verificamos si existe alguna clase de ancho (w-*) que no sea w-auto.
13
- // Es importante distinguir entre w-* (ancho) y max-w-*/min-w-* (límites),
14
- // ya que un max-w-* sin un w-full puede hacer que la card colapse a su contenido.
15
- const hasExplicitWidth = mergedClasses.split(/\s+/).some((cls) => {
16
- const mainClass = cls.split(":").pop() || "";
17
- return (mainClass.startsWith("w-") &&
18
- mainClass !== "w-auto" &&
19
- !mainClass.startsWith("max-w-") &&
20
- !mainClass.startsWith("min-w-"));
21
- });
22
- // Si no hay un ancho explícito, forzamos w-full para que ocupe todo el espacio disponible
23
- // (incluyendo el espacio limitado por un posible max-w- en la misma card o en su padre).
24
- const classes = hasExplicitWidth ? mergedClasses : `${mergedClasses} w-full`;
25
- const [isHovered, setIsHovered] = React.useState(false);
26
- const [isLargeScreen, setIsLargeScreen] = React.useState(false);
27
- React.useEffect(() => {
28
- const checkScreenSize = () => {
29
- // md breakpoint en Tailwind es 768px, así que lg es 1024px
30
- setIsLargeScreen(window.innerWidth >= 1024);
31
- };
32
- checkScreenSize();
33
- window.addEventListener("resize", checkScreenSize);
34
- return () => {
35
- window.removeEventListener("resize", checkScreenSize);
36
- };
37
- }, []);
38
- // Determinar la opacidad de las headerActions
39
- const getHeaderActionsOpacity = () => {
40
- if (!headerActions)
41
- return 0;
42
- // En pantallas pequeñas (md e inferiores) siempre se muestran
43
- if (!isLargeScreen)
44
- return 1;
45
- // Si alwaysDisplayHeaderActions es true, siempre se muestran
46
- if (alwaysDisplayHeaderActions)
47
- return 1;
48
- // Si es false y pantalla grande, solo al hacer hover
49
- return isHovered ? 1 : 0;
50
- };
51
- return (_jsxs("div", { className: `${classes} relative`, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [(title || subtitle || headerActions) && (_jsx("div", { className: twMerge(compact ? "px-4 pt-2" : "px-6 pt-4", headerClassName), children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [title && (_jsx("h3", { className: "text-lg font-semibold text-[var(--color-text-primary)]", children: title })), subtitle && (_jsx("div", { className: "text-sm text-[var(--color-text-secondary)] mt-1", children: subtitle }))] }), headerActions && (_jsx("div", { className: "flex items-center transition-opacity", style: {
52
- opacity: getHeaderActionsOpacity(),
53
- }, children: headerActions }))] }) })), children && (_jsx("div", { className: twMerge(compact ? "px-4 py-4" : "px-6 py-4", contentClassName), children: children })), footer && (_jsx("div", { className: twMerge(compact ? "px-4 pb-2" : "px-6 pb-4", "flex items-center justify-end", footerClassName), children: footer }))] }));
54
- };
@@ -1,18 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from "react";
3
- export const Collection = ({ children, gap = "1rem", direction = "column", wrap = false, className = "", }) => {
4
- const baseClasses = `
5
- flex
6
- font-[var(--font-default)]
7
- `;
8
- const directionClasses = {
9
- column: "flex-col",
10
- row: "flex-row",
11
- };
12
- const wrapClass = wrap ? "flex-wrap" : "flex-nowrap";
13
- const classes = `${baseClasses} ${directionClasses[direction]} ${wrapClass} ${className}`.trim();
14
- const style = {
15
- gap: gap,
16
- };
17
- return (_jsx("div", { className: classes, style: style, children: children }));
18
- };
@@ -1,38 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import React from "react";
3
- import { Button } from "../form-controls";
4
- export const DataField = ({ label, value, inline = false, align = "left", title, link, className = "", labelClassName = "", }) => {
5
- const handleLinkClick = () => {
6
- if (link) {
7
- window.open(link, "_blank", "noopener,noreferrer");
8
- }
9
- };
10
- const alignClasses = {
11
- left: "text-left",
12
- right: "text-right",
13
- center: "text-center",
14
- };
15
- const justifyClasses = {
16
- left: "justify-start",
17
- right: "justify-end",
18
- center: "justify-center",
19
- };
20
- const baseContainerClasses = `
21
- font-[var(--font-default)]
22
- ${alignClasses[align]}
23
- ${className}
24
- `.trim();
25
- const baseLabelClasses = `
26
- text-sm text-[var(--color-text-primary)]
27
- ${labelClassName}
28
- `.trim();
29
- const baseValueClasses = `
30
- text-base text-[var(--color-text-primary)]
31
- `;
32
- if (inline) {
33
- // Modo inline: label y value en la misma línea
34
- return (_jsx("div", { className: baseContainerClasses, title: title, children: _jsxs("div", { className: `flex items-center gap-2 ${justifyClasses[align]}`, children: [label && _jsxs("span", { className: baseLabelClasses, children: [label, ":"] }), _jsx("span", { className: baseValueClasses, children: value }), link && (_jsx(Button, { size: "sm", variant: "ghost", icon: "fa-arrow-right", onClick: handleLinkClick, "aria-label": "Abrir enlace" }))] }) }));
35
- }
36
- // Modo vertical: label arriba, value abajo
37
- return (_jsxs("div", { className: baseContainerClasses, title: title, children: [label && _jsx("div", { className: baseLabelClasses, children: label }), _jsxs("div", { className: `flex items-center gap-2 ${justifyClasses[align]}`, children: [_jsx("div", { className: baseValueClasses, children: value }), link && (_jsx(Button, { size: "sm", variant: "ghost", icon: "fa-arrow-right", onClick: handleLinkClick, "aria-label": "Abrir enlace" }))] })] }));
38
- };
@@ -1,164 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { twMerge } from "tailwind-merge";
4
- import { DropdownMenu } from "./DropdownMenu";
5
- export const DataTable = ({ columns, rows, className = "", maxRows, locale = "es-AR", isLoading = false, loadingRows = 5, rowClassName, headerClassName = "", footerClassName = "", headerCellClassName = "", footerCellClassName = "", cellClassName = "", compact = false, }) => {
6
- // Calcular si necesitamos scroll
7
- const displayRows = isLoading ? loadingRows : rows.length;
8
- const needsScroll = maxRows !== undefined && displayRows > maxRows;
9
- // Altura aproximada de una fila (px-4 py-3 = ~48px por fila, compact es menos)
10
- const rowHeight = compact ? 32 : 48;
11
- const maxHeight = maxRows ? `${maxRows * rowHeight}px` : undefined;
12
- const cellPadding = compact ? "px-2 py-1" : "px-4 py-3";
13
- // Verificar si alguna columna tiene footer
14
- const hasFooter = columns.some((column) => column.footer !== undefined);
15
- const getCellValue = (column, row) => {
16
- if (!column.value)
17
- return null;
18
- if (typeof column.value === "function") {
19
- return column.value(row);
20
- }
21
- // Si es string o number, puede ser un nombre de propiedad o un valor directo
22
- if (typeof column.value === "string" || typeof column.value === "number") {
23
- // Intentar obtener la propiedad del objeto si existe
24
- if (typeof column.value === "string" &&
25
- typeof row === "object" &&
26
- row !== null) {
27
- const value = row[column.value];
28
- if (value !== undefined) {
29
- return value;
30
- }
31
- }
32
- // Si no es una propiedad, retornar el valor directo
33
- return column.value;
34
- }
35
- return column.value;
36
- };
37
- const formatValue = (value, type) => {
38
- if (React.isValidElement(value)) {
39
- return value;
40
- }
41
- // Convertir string a número si es necesario para currency o numeric
42
- let numericValue = null;
43
- if (typeof value === "number") {
44
- numericValue = value;
45
- }
46
- else if (typeof value === "string" &&
47
- (type === "currency" || type === "numeric")) {
48
- const parsed = parseFloat(value);
49
- if (!isNaN(parsed)) {
50
- numericValue = parsed;
51
- }
52
- }
53
- if (numericValue !== null) {
54
- if (type === "currency") {
55
- // Formatear usando el locale proporcionado sin símbolo de moneda
56
- const parts = new Intl.NumberFormat(locale, {
57
- style: "currency",
58
- currency: "EUR",
59
- minimumFractionDigits: 2,
60
- maximumFractionDigits: 2,
61
- }).formatToParts(numericValue);
62
- // Construir el string sin el símbolo de moneda
63
- return parts
64
- .filter((part) => part.type !== "currency")
65
- .map((part) => part.value)
66
- .join("");
67
- }
68
- if (type === "numeric") {
69
- // Formatear usando el locale proporcionado
70
- const hasDecimals = numericValue % 1 !== 0;
71
- return new Intl.NumberFormat(locale, {
72
- minimumFractionDigits: hasDecimals ? 2 : 0,
73
- maximumFractionDigits: hasDecimals ? 2 : 0,
74
- }).format(numericValue);
75
- }
76
- }
77
- if (typeof value === "string" && type === "date") {
78
- try {
79
- const date = new Date(value);
80
- return date.toLocaleDateString(locale);
81
- }
82
- catch {
83
- return value;
84
- }
85
- }
86
- return value;
87
- };
88
- const getAlignmentClass = (align, type) => {
89
- // Las columnas de tipo 'date' siempre se alinean a la izquierda
90
- // Las columnas de tipo 'currency' y 'numeric' siempre se alinean a la derecha
91
- let effectiveAlign = align;
92
- if (type === "date") {
93
- effectiveAlign = "left";
94
- }
95
- else if (type === "currency" || type === "numeric") {
96
- effectiveAlign = "right";
97
- }
98
- switch (effectiveAlign) {
99
- case "right":
100
- return "text-right";
101
- case "center":
102
- return "text-center";
103
- case "left":
104
- default:
105
- return "text-left";
106
- }
107
- };
108
- // Convertir array de ReactNode a array de ActionItem para DropdownMenu
109
- const convertActionsToOptions = (actions) => {
110
- return actions.map((action, index) => ({
111
- id: index,
112
- content: (_jsx("div", { onClick: (e) => {
113
- // Detener la propagación para que el onClick del DropdownMenu no interfiera
114
- e.stopPropagation();
115
- }, children: action })),
116
- }));
117
- };
118
- // Componente Skeleton para celdas de carga
119
- const SkeletonCell = () => (_jsx("div", { className: "h-4 bg-[var(--color-border-default)]/40 rounded animate-pulse w-full" }));
120
- return (_jsx("div", { className: `overflow-x-auto ${className}`, children: _jsx("div", { className: needsScroll ? "relative overflow-y-auto" : "", style: needsScroll && maxHeight ? { maxHeight: maxHeight } : undefined, children: _jsxs("table", { className: "w-full border-collapse font-[var(--font-default)]", children: [_jsx("thead", { className: needsScroll ? "sticky top-0 z-10" : "", children: _jsx("tr", { className: twMerge("border-b border-[var(--color-border-default)] text-[var(--color-text-primary)]", headerClassName), children: columns.map((column, index) => {
121
- const headerActions = column.headerActions?.();
122
- const hasHeaderActions = headerActions && headerActions.length > 0;
123
- const headerBgClasses = headerClassName
124
- .split(/\s+/)
125
- .filter((cls) => cls.split(":").pop()?.startsWith("bg-"))
126
- .join(" ");
127
- return (_jsx("th", { className: twMerge(cellPadding, "text-sm font-semibold", headerBgClasses || "bg-[var(--color-bg-secondary)]", getAlignmentClass(column.align, column.type), hasHeaderActions ? "relative" : "", headerCellClassName), style: {
128
- ...(column.width ? { width: column.width } : {}),
129
- }, children: isLoading ? (_jsx(SkeletonCell, {})) : hasHeaderActions ? (_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { children: column.header || "" }), _jsx(DropdownMenu, { options: convertActionsToOptions(headerActions), onOptionSelected: () => {
130
- // Las acciones ya manejan sus propios eventos
131
- }, renderOption: (item) => item.content, replaceOnSingleOption: true })] })) : (column.header || "") }, index));
132
- }) }) }), _jsx("tbody", { children: isLoading
133
- ? Array.from({ length: loadingRows }).map((_, rowIndex) => (_jsx("tr", { className: "border-b border-[var(--color-border-default)] text-[var(--color-text-primary)]", children: columns.map((column, colIndex) => (_jsx("td", { className: twMerge(cellPadding, "text-sm", getAlignmentClass(column.align, column.type)), style: {
134
- ...(column.width ? { width: column.width } : {}),
135
- }, children: _jsx(SkeletonCell, {}) }, colIndex))) }, `skeleton-${rowIndex}`)))
136
- : rows.map((row, rowIndex) => (_jsx("tr", { className: twMerge("group/row border-b border-[var(--color-border-default)] transition-colors hover:bg-[var(--color-bg-secondary)] text-[var(--color-text-primary)]", rowClassName?.(row)), children: columns.map((column, colIndex) => {
137
- const cellValue = getCellValue(column, row);
138
- const formattedValue = formatValue(cellValue, column.type);
139
- const tooltip = column.tooltip
140
- ? column.tooltip(row)
141
- : undefined;
142
- const rowActions = column.actions?.(row);
143
- const hasRowActions = rowActions && rowActions.length > 0;
144
- return (_jsx("td", { className: twMerge(cellPadding, "text-sm", getAlignmentClass(column.align, column.type), typeof cellClassName === "function"
145
- ? cellClassName(row, column)
146
- : cellClassName), style: {
147
- ...(column.width ? { width: column.width } : {}),
148
- }, title: tooltip
149
- ? typeof tooltip === "string"
150
- ? tooltip
151
- : undefined
152
- : undefined, children: hasRowActions ? (_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { children: formattedValue }), _jsx("div", { className: "lg:opacity-0 lg:group-hover/row:opacity-100 transition-opacity", children: _jsx(DropdownMenu, { options: convertActionsToOptions(rowActions), onOptionSelected: () => {
153
- // Las acciones ya manejan sus propios eventos
154
- }, renderOption: (item) => item.content, replaceOnSingleOption: true }) })] })) : (formattedValue) }, colIndex));
155
- }) }, rowIndex))) }), hasFooter && (_jsx("tfoot", { className: needsScroll ? "sticky bottom-0 z-10" : "", children: _jsx("tr", { className: twMerge("border-t border-[var(--color-border-default)] text-[var(--color-text-primary)]", footerClassName), children: columns.map((column, index) => {
156
- const footerBgClasses = footerClassName
157
- .split(/\s+/)
158
- .filter((cls) => cls.split(":").pop()?.startsWith("bg-"))
159
- .join(" ");
160
- return (_jsx("td", { className: twMerge(cellPadding, "text-sm font-semibold", footerBgClasses || "bg-[var(--color-bg-secondary)]", getAlignmentClass(column.align, column.type), footerCellClassName), style: {
161
- ...(column.width ? { width: column.width } : {}),
162
- }, children: isLoading ? _jsx(SkeletonCell, {}) : column.footer || "" }, index));
163
- }) }) }))] }) }) }));
164
- };