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,52 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useState, useEffect, useMemo, createContext, useContext } from "react";
3
- import { useSearchParams } from "react-router-dom";
4
- const TabsContext = createContext(undefined);
5
- export const useTabsContext = () => {
6
- const context = useContext(TabsContext);
7
- if (!context) {
8
- throw new Error("TabPanel must be used within TabsGroup");
9
- }
10
- return context;
11
- };
12
- export const TabsGroup = ({ children, tabs, paramName, headerNode, onChangeTab, }) => {
13
- const [searchParams, setSearchParams] = useSearchParams();
14
- const defaultTab = tabs[0]?.id?.toString() || "";
15
- // Obtener el tab activo desde URL params si paramName está definido, sino desde estado local
16
- const urlTab = paramName ? searchParams.get(paramName) : null;
17
- const initialTab = urlTab || defaultTab;
18
- const [activeTab, setActiveTabState] = useState(initialTab);
19
- // Sincronizar con URL params cuando cambian
20
- useEffect(() => {
21
- if (paramName && urlTab) {
22
- setActiveTabState(urlTab);
23
- }
24
- }, [paramName, urlTab]);
25
- const setActiveTab = (tab) => {
26
- setActiveTabState(tab);
27
- // Actualizar URL params si paramName está definido
28
- if (paramName) {
29
- const newSearchParams = new URLSearchParams(searchParams);
30
- newSearchParams.set(paramName, tab.toString());
31
- setSearchParams(newSearchParams, { replace: true });
32
- }
33
- // Llamar al callback si está definido
34
- if (onChangeTab) {
35
- onChangeTab(tab.toString());
36
- }
37
- };
38
- const contextValue = useMemo(() => ({ activeTab, setActiveTab }), [activeTab]);
39
- const handleTabClick = (tabId) => {
40
- setActiveTab(tabId);
41
- };
42
- return (_jsx(TabsContext.Provider, { value: contextValue, children: _jsxs("div", { className: "w-full font-[var(--font-default)]", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-[var(--color-border-default)]", children: [_jsx("div", { className: "flex items-center gap-1", children: tabs.map((tab) => {
43
- const isActive = activeTab.toString() === tab.id.toString();
44
- return (_jsx("button", { onClick: () => handleTabClick(tab.id), className: `
45
- px-4 py-2 text-sm font-medium transition-colors cursor-pointer
46
- border-b-2 -mb-[1px]
47
- ${isActive
48
- ? "text-[var(--color-primary)] border-[var(--color-primary)]"
49
- : "text-[var(--color-text-secondary)] border-transparent hover:text-[var(--color-text-primary)] hover:border-[var(--color-border-default)]"}
50
- `, "aria-selected": isActive, role: "tab", children: tab.label }, tab.id));
51
- }) }), headerNode && (_jsx("div", { className: "flex items-center", children: headerNode }))] }), _jsx("div", { className: "mt-4", children: children })] }) }));
52
- };
@@ -1,12 +0,0 @@
1
- export { Card } from "./Card";
2
- export { AppLayout } from "./AppLayout";
3
- export { Collection } from "./Collection";
4
- export { DataField } from "./DataField";
5
- export { TabsGroup } from "./TabsGroup";
6
- export { TabPanel } from "./TabPanel";
7
- export { DataTable } from "./DataTable";
8
- export { Accordion } from "./Accordion";
9
- export { Menu } from "./Menu";
10
- export { DropdownMenu } from "./DropdownMenu";
11
- export { DropdownPanel } from "./DropdownPanel";
12
- export { Filter } from "./Filter";
@@ -1,77 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useState } from "react";
3
- import { getInitialLetters } from "../../helpers";
4
- /**
5
- * Helper function to convert color names to CSS values
6
- */
7
- const getColorValue = (color) => {
8
- if (!color)
9
- return undefined;
10
- // If already a valid CSS value (hex, rgb, rgba, hsl, etc.), return it
11
- if (color.startsWith("#") ||
12
- color.startsWith("rgb") ||
13
- color.startsWith("hsl")) {
14
- return color;
15
- }
16
- // Map common color names
17
- const colorMap = {
18
- white: "#ffffff",
19
- black: "#000000",
20
- "gray-800": "#1f2937",
21
- "gray-700": "#374151",
22
- "gray-600": "#4b5563",
23
- "gray-500": "#6b7280",
24
- "gray-400": "#9ca3af",
25
- "gray-300": "#d1d5db",
26
- "gray-200": "#e5e7eb",
27
- "gray-100": "#f3f4f6",
28
- "gray-50": "#f9fafb",
29
- };
30
- return colorMap[color.toLowerCase()] || color;
31
- };
32
- /**
33
- * Avatar component displays a circular avatar with initials or an image
34
- *
35
- * @example
36
- * // Basic usage with text
37
- * <Avatar text="John Doe" />
38
- *
39
- * @example
40
- * // With image
41
- * <Avatar text="John Doe" image="https://example.com/avatar.jpg" />
42
- *
43
- * @example
44
- * // Custom colors
45
- * <Avatar text="Jane Smith" bgColor="#3b82f6" textColor="#ffffff" />
46
- */
47
- export const Avatar = ({ text, image, bgColor = "gray-600", textColor = "white", size = "md", className = "", }) => {
48
- const [imageError, setImageError] = useState(false);
49
- const initials = getInitialLetters(text);
50
- const showImage = image && !imageError;
51
- const sizeClasses = {
52
- sm: "w-8 h-8 text-xs",
53
- md: "w-10 h-10 text-sm",
54
- lg: "w-12 h-12 text-base",
55
- };
56
- const baseClasses = `
57
- rounded-full
58
- flex
59
- items-center
60
- justify-center
61
- font-semibold
62
- font-[var(--font-default)]
63
- overflow-hidden
64
- flex-shrink-0
65
- ${sizeClasses[size]}
66
- ${className}
67
- `;
68
- // Inline styles for colors (only if no image or image failed to load)
69
- const inlineStyles = showImage
70
- ? {}
71
- : {
72
- backgroundColor: getColorValue(bgColor) || bgColor || "#4b5563",
73
- color: getColorValue(textColor) || textColor || "#ffffff",
74
- };
75
- return (_jsx("div", { className: baseClasses, style: inlineStyles, title: text, role: "img", "aria-label": text, children: showImage ? (_jsx("img", { src: image, alt: text, className: "w-full h-full object-cover", onError: () => setImageError(true) })) : (_jsx("span", { children: initials })) }));
76
- };
77
- Avatar.displayName = "Avatar";
@@ -1,151 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { normalizeIconClass } from "./iconUtils";
4
- // Función helper para convertir nombres de colores comunes a valores CSS válidos
5
- const getColorValue = (color) => {
6
- if (!color)
7
- return undefined;
8
- // Si ya es un valor CSS válido (hex, rgb, rgba, hsl, etc.), retornarlo
9
- if (color.startsWith("#") ||
10
- color.startsWith("rgb") ||
11
- color.startsWith("hsl")) {
12
- return color;
13
- }
14
- // Mapeo de nombres de colores comunes
15
- const colorMap = {
16
- white: "#ffffff",
17
- black: "#000000",
18
- "gray-800": "#1f2937",
19
- "gray-700": "#374151",
20
- "gray-600": "#4b5563",
21
- "gray-500": "#6b7280",
22
- "gray-400": "#9ca3af",
23
- "gray-300": "#d1d5db",
24
- "gray-200": "#e5e7eb",
25
- "gray-100": "#f3f4f6",
26
- "gray-50": "#f9fafb",
27
- };
28
- return colorMap[color.toLowerCase()] || color;
29
- };
30
- export const Badge = ({ children, variant = "primary", size = "md", rounded = false, className = "", icon, iconPosition = "left", iconLabel, bg, textColor, onClick, }) => {
31
- const baseClasses = "inline-flex items-center font-medium font-[var(--font-default)]";
32
- const variantClasses = {
33
- primary: `
34
- bg-[var(--color-primary-light)] text-gray-800
35
- `,
36
- secondary: `
37
- bg-[var(--color-secondary-light)] text-gray-800
38
- `,
39
- success: `
40
- bg-[var(--color-success-light)] text-gray-800
41
- `,
42
- warning: `
43
- bg-[var(--color-warning-light)] text-gray-800
44
- `,
45
- danger: `
46
- bg-[var(--color-danger-light)] text-gray-800
47
- `,
48
- info: `
49
- bg-[var(--color-info-light)] text-gray-800
50
- `,
51
- };
52
- const sizeClasses = {
53
- sm: "py-0.5 text-xs",
54
- md: "py-0.5 text-sm",
55
- lg: "py-1 text-base",
56
- };
57
- // Padding horizontal: si hay icono, el badge no tiene padding, se aplica a los elementos internos
58
- const horizontalPaddingClasses = icon
59
- ? "" // Sin padding horizontal en el badge cuando hay icono
60
- : size === "sm"
61
- ? "px-2"
62
- : size === "md"
63
- ? "px-2.5"
64
- : "px-3";
65
- // Padding para el texto: flex-1 para ocupar el espacio, padding solo en el lado opuesto al icono
66
- const textPaddingClasses = icon
67
- ? iconPosition === "left"
68
- ? size === "sm"
69
- ? "flex-1 pr-2"
70
- : size === "md"
71
- ? "flex-1 pr-2.5"
72
- : "flex-1 pr-3"
73
- : size === "sm"
74
- ? "flex-1 pl-2"
75
- : size === "md"
76
- ? "flex-1 pl-2.5"
77
- : "flex-1 pl-3"
78
- : "";
79
- // Padding para el icono: solo en el lado del borde
80
- const iconPaddingClasses = icon
81
- ? iconPosition === "left"
82
- ? size === "sm"
83
- ? "pl-2"
84
- : size === "md"
85
- ? "pl-2.5"
86
- : "pl-3"
87
- : size === "sm"
88
- ? "pr-2"
89
- : size === "md"
90
- ? "pr-2.5"
91
- : "pr-3"
92
- : "";
93
- const roundedClasses = rounded ? "rounded-full" : "rounded-md";
94
- const gapClasses = icon ? "gap-2" : ""; // Gap entre icono y texto cuando hay icono
95
- const iconSizeClasses = size === "sm" ? "text-xs" : size === "md" ? "text-sm" : "text-base";
96
- // Si se proporciona bg personalizado, usar estilos inline; si no, usar las clases de variante
97
- const backgroundClasses = bg ? "" : variantClasses[variant];
98
- // Estilos inline para colores personalizados
99
- const inlineStyles = bg
100
- ? {
101
- backgroundColor: getColorValue(bg) || bg,
102
- color: getColorValue(textColor) || textColor || "#1f2937", // gray-800 por defecto
103
- }
104
- : {};
105
- // Si hay onClick y no hay iconos, agregar cursor-pointer al badge completo
106
- const cursorClasses = onClick && !icon ? "cursor-pointer" : "";
107
- const classes = `${baseClasses} ${backgroundClasses} ${sizeClasses[size]} ${horizontalPaddingClasses} ${roundedClasses} ${gapClasses} ${cursorClasses} ${className}`;
108
- const renderIcon = () => {
109
- if (!icon)
110
- return null;
111
- // Si hay onClick y hay iconos, el onClick se aplica solo a los iconos
112
- const iconClasses = onClick
113
- ? `${normalizeIconClass(icon)} ${iconSizeClasses} cursor-pointer`
114
- : `${normalizeIconClass(icon)} ${iconSizeClasses}`;
115
- return (_jsx("span", { className: iconPaddingClasses, children: _jsx("i", { className: iconClasses, "aria-hidden": !iconLabel, "aria-label": iconLabel, onClick: onClick, role: onClick ? "button" : undefined, tabIndex: onClick ? 0 : undefined, onKeyDown: onClick
116
- ? (e) => {
117
- if (e.key === "Enter" || e.key === " ") {
118
- e.preventDefault();
119
- // Crear un evento sintético compatible con MouseEvent
120
- const syntheticEvent = {
121
- ...e,
122
- currentTarget: e.currentTarget,
123
- target: e.target,
124
- };
125
- onClick(syntheticEvent);
126
- }
127
- }
128
- : undefined }) }));
129
- };
130
- // Si hay onClick y no hay iconos, aplicar onClick al badge completo
131
- const badgeProps = onClick && !icon
132
- ? {
133
- onClick,
134
- role: "button",
135
- tabIndex: 0,
136
- onKeyDown: (e) => {
137
- if (e.key === "Enter" || e.key === " ") {
138
- e.preventDefault();
139
- // Crear un evento sintético compatible con MouseEvent
140
- const syntheticEvent = {
141
- ...e,
142
- currentTarget: e.currentTarget,
143
- target: e.target,
144
- };
145
- onClick(syntheticEvent);
146
- }
147
- },
148
- }
149
- : {};
150
- return (_jsxs("span", { className: classes, style: inlineStyles, ...badgeProps, children: [icon && iconPosition === "left" && renderIcon(), _jsx("span", { className: textPaddingClasses, children: children }), icon && iconPosition === "right" && renderIcon()] }));
151
- };
@@ -1,44 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useEffect } from "react";
3
- import { normalizeIconClass } from "./iconUtils";
4
- export const Dialog = ({ isOpen, title, children, footer, onClose, closeOnOverlayClick = false, compact = false, }) => {
5
- // Prevenir scroll del body cuando el dialog está abierto
6
- useEffect(() => {
7
- if (isOpen) {
8
- document.body.style.overflow = "hidden";
9
- }
10
- else {
11
- document.body.style.overflow = "";
12
- }
13
- return () => {
14
- document.body.style.overflow = "";
15
- };
16
- }, [isOpen]);
17
- // Manejar tecla Escape para cerrar
18
- useEffect(() => {
19
- const handleEscape = (e) => {
20
- if (e.key === "Escape" && isOpen && onClose) {
21
- onClose();
22
- }
23
- };
24
- if (isOpen) {
25
- document.addEventListener("keydown", handleEscape);
26
- }
27
- return () => {
28
- document.removeEventListener("keydown", handleEscape);
29
- };
30
- }, [isOpen, onClose]);
31
- if (!isOpen) {
32
- return null;
33
- }
34
- const handleOverlayClick = () => {
35
- if (closeOnOverlayClick && onClose) {
36
- onClose();
37
- }
38
- };
39
- return (_jsxs("div", { className: "fixed inset-0 z-[2000] flex items-center justify-center p-4", role: "dialog", "aria-modal": "true", "aria-labelledby": "dialog-title", children: [_jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: handleOverlayClick }), _jsxs("div", { className: "relative w-auto max-w-lg min-w-[400px] bg-[var(--color-bg-default)] rounded-lg shadow-[var(--shadow-xl)] border border-[var(--color-border-default)] font-[var(--font-default)] max-h-[90vh] flex flex-col", onClick: (e) => e.stopPropagation(), style: { overflow: "visible" }, children: [_jsxs("div", { className: `flex items-center justify-between ${compact ? "px-4 py-2" : "px-6 py-4"} border-b border-[var(--color-border-default)] flex-shrink-0`, children: [_jsx("h2", { id: "dialog-title", className: "text-lg font-semibold text-[var(--color-text-primary)]", children: title }), onClose && (_jsx("button", { onClick: onClose, className: "ml-4 p-1 rounded-md flysoft-button-reset bg-transparent border-none text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] transition-colors cursor-pointer", "aria-label": "Cerrar dialog", children: _jsx("i", { className: normalizeIconClass("fa-times") }) }))] }), _jsx("div", { className: `${compact ? "px-4 py-3" : "px-6 py-4"} flex-1 text-[var(--color-text-primary)] min-w-0`, style: {
40
- overflowY: "auto",
41
- overflowX: "visible",
42
- maxHeight: "calc(90vh - 200px)",
43
- }, children: children }), footer && (_jsx("div", { className: `${compact ? "px-4 py-2" : "px-6 py-4"} border-t border-[var(--color-border-default)] flex items-center justify-end gap-2 flex-shrink-0 flex-wrap`, children: footer }))] })] }));
44
- };
@@ -1,104 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useState, useEffect } from "react";
3
- import { useSearchParams } from "react-router-dom";
4
- import { Button } from "../form-controls/Button";
5
- import { Dialog } from "./Dialog";
6
- import { Filter } from "../layout/Filter";
7
- import { Collection } from "../layout/Collection";
8
- export const FiltersDialog = ({ filters }) => {
9
- const [searchParams, setSearchParams] = useSearchParams();
10
- const [isOpen, setIsOpen] = useState(false);
11
- const [filterValues, setFilterValues] = useState({});
12
- // Inicializar filterValues con los valores actuales de la URL
13
- useEffect(() => {
14
- const initialValues = {};
15
- filters.forEach((filter) => {
16
- const urlValue = searchParams.get(filter.paramName);
17
- initialValues[filter.paramName] = urlValue || undefined;
18
- });
19
- setFilterValues(initialValues);
20
- }, []); // Solo al montar el componente
21
- // Sincronizar filterValues cuando se abre el dialog con los valores actuales de la URL
22
- useEffect(() => {
23
- if (isOpen) {
24
- const currentValues = {};
25
- filters.forEach((filter) => {
26
- const urlValue = searchParams.get(filter.paramName);
27
- currentValues[filter.paramName] = urlValue || undefined;
28
- });
29
- setFilterValues(currentValues);
30
- }
31
- }, [isOpen, filters, searchParams]);
32
- const handleFilterChange = (paramName, value) => {
33
- setFilterValues((prev) => ({
34
- ...prev,
35
- [paramName]: value,
36
- }));
37
- };
38
- const handleApplyFilters = () => {
39
- const newSearchParams = new URLSearchParams(searchParams);
40
- // Aplicar todos los filtros a la URL
41
- filters.forEach((filter) => {
42
- const value = filterValues[filter.paramName];
43
- if (value) {
44
- newSearchParams.set(filter.paramName, value);
45
- }
46
- else {
47
- newSearchParams.delete(filter.paramName);
48
- }
49
- });
50
- setSearchParams(newSearchParams, { replace: true });
51
- setIsOpen(false);
52
- };
53
- const handleClose = () => {
54
- setIsOpen(false);
55
- };
56
- const handleOpen = () => {
57
- setIsOpen(true);
58
- };
59
- // Construir las props de Filter para cada filtro
60
- const getFilterProps = (filterConfig) => {
61
- const baseProps = {
62
- label: filterConfig.label,
63
- staticOptions: filterConfig.staticOptions,
64
- inputWidth: filterConfig.inputWidth,
65
- value: filterValues[filterConfig.paramName],
66
- onChange: (value) => handleFilterChange(filterConfig.paramName, value),
67
- };
68
- switch (filterConfig.filterType) {
69
- case "text":
70
- return {
71
- ...baseProps,
72
- filterType: "text",
73
- };
74
- case "number":
75
- return {
76
- ...baseProps,
77
- filterType: "number",
78
- min: filterConfig.min,
79
- max: filterConfig.max,
80
- };
81
- case "date":
82
- return {
83
- ...baseProps,
84
- filterType: "date",
85
- };
86
- case "autocomplete":
87
- return {
88
- ...baseProps,
89
- filterType: "autocomplete",
90
- options: filterConfig.options || [],
91
- getOptionLabel: filterConfig.getOptionLabel,
92
- getOptionValue: filterConfig.getOptionValue,
93
- renderOption: filterConfig.renderOption,
94
- noResultsText: filterConfig.noResultsText,
95
- };
96
- default:
97
- return {
98
- ...baseProps,
99
- filterType: "text",
100
- };
101
- }
102
- };
103
- return (_jsxs(_Fragment, { children: [_jsx(Button, { icon: "fa-filter", variant: "outline", size: "sm", onClick: handleOpen, "aria-label": "Abrir filtros", children: "Filtrar" }), _jsx(Dialog, { isOpen: isOpen, title: "Filtros", footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: handleClose, children: "Cerrar" }), _jsx(Button, { variant: "primary", onClick: handleApplyFilters, children: "Aplicar filtros" })] }), onClose: handleClose, closeOnOverlayClick: false, children: _jsx("div", { className: "space-y-4", children: _jsx(Collection, { direction: "column", gap: "1rem", children: filters.map((filter) => (_jsx(Filter, { ...getFilterProps(filter) }, filter.paramName))) }) }) })] }));
104
- };
@@ -1,44 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React from "react";
3
- import { useTheme } from "../../contexts/ThemeContext";
4
- export const Loader = ({ isLoading = false, text, children, keepContentWhileLoading, contentLoadingNode, overlayClassName, }) => {
5
- const { theme } = useTheme();
6
- const displayText = text;
7
- // Clases por defecto del overlay (negro semitransparente con blur)
8
- const defaultOverlayClasses = "bg-black/50 backdrop-blur-sm";
9
- // Combinar clases por defecto con las personalizadas
10
- const overlayClasses = overlayClassName
11
- ? overlayClassName
12
- : defaultOverlayClasses;
13
- // Barra de progreso infinita
14
- const ProgressBar = () => {
15
- // Variable CSS para el gradiente del color primario
16
- const gradientColor = `no-repeat linear-gradient(${theme.colors.primary} 0 0)`;
17
- const bgSecondary = theme.colors.bgSecondary || theme.colors.gray100;
18
- return (_jsxs("div", { className: "flex flex-col items-center gap-0.5 w-full", role: "status", "aria-live": "polite", children: [_jsx("div", { className: "h-1 w-full rounded", style: {
19
- "--c": gradientColor,
20
- background: `var(--c), var(--c), ${bgSecondary}`,
21
- backgroundSize: "60% 100%",
22
- animation: "l16 3s infinite",
23
- } }), displayText && (_jsx("span", { className: "text-xs text-[var(--color-text-secondary)] font-[var(--font-default)]", children: displayText }))] }));
24
- };
25
- // Si no está cargando, mostrar solo children (si existen)
26
- if (!isLoading) {
27
- return _jsx(_Fragment, { children: children });
28
- }
29
- // Variante 1: Con contentLoadingNode
30
- if (contentLoadingNode) {
31
- return (_jsxs("div", { className: "relative", children: [_jsx("div", { className: keepContentWhileLoading ? "opacity-50 pointer-events-none" : "", children: contentLoadingNode }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center z-10 pointer-events-none px-4", children: _jsx("div", { className: "bg-[var(--color-bg-default)] rounded-lg p-6 shadow-lg border border-[var(--color-border-default)] pointer-events-auto w-full", children: _jsx(ProgressBar, {}) }) })] }));
32
- }
33
- // Variante 2: Con children pero sin contentLoadingNode
34
- if (children) {
35
- // Si keepContentWhileLoading es true, mostrar children con overlay
36
- if (keepContentWhileLoading) {
37
- return (_jsxs("div", { className: "relative", children: [_jsx("div", { className: "pointer-events-none select-none", children: children }), _jsx("div", { className: `absolute inset-0 flex items-center justify-center z-10 pointer-events-auto px-4 ${overlayClasses}`, children: _jsx("div", { className: "bg-[var(--color-bg-default)] rounded-lg p-6 shadow-lg border border-[var(--color-border-default)] w-full max-w-2xl", children: _jsx(ProgressBar, {}) }) })] }));
38
- }
39
- // Si no tiene keepContentWhileLoading, ocultar children y mostrar solo loader básico
40
- return (_jsx("div", { className: "flex items-center justify-center p-6 w-full", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ProgressBar, {}) }) }));
41
- }
42
- // Variante 3: Sin contentLoadingNode ni children - solo loader
43
- return (_jsx("div", { className: "flex items-center justify-center p-6 w-full", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ProgressBar, {}) }) }));
44
- };
@@ -1,139 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { normalizeIconClass } from "./iconUtils";
4
- /**
5
- * Helper function to convert color names to CSS values
6
- */
7
- const getColorValue = (color) => {
8
- if (!color)
9
- return undefined;
10
- // If already a valid CSS value (hex, rgb, rgba, hsl, etc.), return it
11
- if (color.startsWith("#") ||
12
- color.startsWith("rgb") ||
13
- color.startsWith("hsl")) {
14
- return color;
15
- }
16
- // Map common color names
17
- const colorMap = {
18
- white: "#ffffff",
19
- black: "#000000",
20
- "gray-800": "#1f2937",
21
- "gray-700": "#374151",
22
- "gray-600": "#4b5563",
23
- "gray-500": "#6b7280",
24
- "gray-400": "#9ca3af",
25
- "gray-300": "#d1d5db",
26
- "gray-200": "#e5e7eb",
27
- "gray-100": "#f3f4f6",
28
- "gray-50": "#f9fafb",
29
- };
30
- return colorMap[color.toLowerCase()] || color;
31
- };
32
- /**
33
- * Get the CSS variable name for a variant color
34
- */
35
- const getVariantColorVar = (variant) => {
36
- if (!variant)
37
- return "var(--color-primary)";
38
- const variantMap = {
39
- primary: "var(--color-primary)",
40
- secondary: "var(--color-secondary)",
41
- success: "var(--color-success)",
42
- warning: "var(--color-warning)",
43
- danger: "var(--color-danger)",
44
- info: "var(--color-info)",
45
- };
46
- return variantMap[variant];
47
- };
48
- /**
49
- * Get the actual color value for a variant (for gradients)
50
- * This reads the CSS variable value from the computed styles
51
- */
52
- const getVariantColorValue = (variant) => {
53
- if (!variant)
54
- return "#007aff"; // default primary color
55
- const variantColorMap = {
56
- primary: "#007aff",
57
- secondary: "#6b7280",
58
- success: "#10b981",
59
- warning: "#f59e0b",
60
- danger: "#ef4444",
61
- info: "#06b6d4",
62
- };
63
- return variantColorMap[variant];
64
- };
65
- /**
66
- * RoadMap component displays a series of stages like metro stations
67
- *
68
- * @example
69
- * // Basic usage
70
- * <RoadMap stages={[
71
- * { name: "Start", variant: "primary" },
72
- * { name: "Middle", variant: "success" },
73
- * { name: "End", variant: "info" }
74
- * ]} />
75
- *
76
- * @example
77
- * // With icons and descriptions
78
- * <RoadMap stages={[
79
- * { name: "Planning", description: "Define requirements", icon: "fa-clipboard", variant: "primary" },
80
- * { name: "Development", description: "Build the feature", icon: "fa-code", variant: "success" },
81
- * { name: "Testing", description: "Test thoroughly", icon: "fa-check-circle", variant: "warning" }
82
- * ]} />
83
- */
84
- export const RoadMap = ({ stages, className = "", }) => {
85
- if (!stages || stages.length === 0) {
86
- return null;
87
- }
88
- /**
89
- * Get the background color for a stage
90
- */
91
- const getStageBgColor = (stage) => {
92
- if (stage.bg) {
93
- return getColorValue(stage.bg) || stage.bg;
94
- }
95
- return getVariantColorVar(stage.variant || "primary");
96
- };
97
- /**
98
- * Get the color value for gradient calculations
99
- */
100
- const getStageColorValue = (stage) => {
101
- if (stage.bg) {
102
- return getColorValue(stage.bg) || stage.bg;
103
- }
104
- return getVariantColorValue(stage.variant || "primary");
105
- };
106
- /**
107
- * Create a gradient string for the connector line
108
- * The line transitions smoothly from the source color to the destination color
109
- */
110
- const getConnectorGradient = (fromStage, toStage) => {
111
- const fromColor = getStageColorValue(fromStage);
112
- const toColor = getStageColorValue(toStage);
113
- // Create a smooth gradient that transitions from source to destination
114
- return `linear-gradient(to bottom, ${fromColor}, ${toColor})`;
115
- };
116
- return (_jsx("div", { className: `roadmap-container ${className}`, children: stages.map((stage, index) => {
117
- const isLast = index === stages.length - 1;
118
- const isDisabled = stage.disabled;
119
- const bgColor = getStageBgColor(stage);
120
- const connectorGradient = !isLast
121
- ? getConnectorGradient(stage, stages[index + 1])
122
- : null;
123
- return (_jsxs("div", { className: "relative flex items-start gap-3", children: [_jsxs("div", { className: "flex flex-col items-center", children: [_jsx("div", { className: `
124
- w-6 h-6 rounded-full
125
- flex items-center justify-center
126
- flex-shrink-0
127
- ${isDisabled ? "opacity-50" : ""}
128
- `, style: {
129
- backgroundColor: bgColor,
130
- color: "#ffffff",
131
- }, children: stage.icon ? (_jsx("i", { className: `${normalizeIconClass(stage.icon)} text-xs` })) : null }), !isLast && (_jsx("div", { className: "w-0.5 h-4 flex-shrink-0", style: {
132
- background: connectorGradient || undefined,
133
- } }))] }), _jsxs("div", { className: `
134
- flex-1
135
- ${isDisabled ? "opacity-50" : ""}
136
- `, children: [_jsx("h3", { className: "text-sm font-semibold font-[var(--font-default)] mb-0.5", style: { color: "var(--color-text-primary)" }, children: stage.name }), stage.description && (_jsx("p", { className: "text-xs font-[var(--font-default)]", style: { color: "var(--color-text-secondary)" }, children: stage.description }))] })] }, index));
137
- }) }));
138
- };
139
- RoadMap.displayName = "RoadMap";
@@ -1,10 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from "react";
3
- import { twMerge } from "tailwind-merge";
4
- /**
5
- * Componente Skeleton para mostrar estados de carga.
6
- * Consiste en un div con una animación de pulso y un fondo grisáceo por defecto.
7
- */
8
- export const Skeleton = ({ className }) => {
9
- return (_jsx("div", { className: twMerge("animate-pulse bg-[var(--color-bg-secondary)] rounded-md", className) }));
10
- };