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,220 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { useFormContext } from "react-hook-form";
4
- export const RadioButtonGroup = React.forwardRef(({ options, value, onChange, labelPosition = "right", size = "md", error, direction = "vertical", gap = "md", className = "", name, disabled, onBlur, readOnly = false, ...props }, ref) => {
5
- // useFormContext debe llamarse incondicionalmente (regla de hooks)
6
- // Si no hay FormProvider, esto lanzará un error
7
- // Para modo controlado sin FormProvider, necesitamos envolver los ejemplos
8
- // en un FormProvider mínimo o usar una detección diferente
9
- // Por ahora, llamamos useFormContext incondicionalmente
10
- const formContext = useFormContext();
11
- const setValue = formContext?.setValue;
12
- // Detectar si estamos en modo register
13
- // Modo register: formContext existe (hay FormProvider) Y name está definido
14
- // Modo controlado: no hay formContext (no hay FormProvider) o no hay name
15
- // Nota: Si no hay FormProvider, useFormContext lanzará error, pero esto es esperado
16
- // cuando se usa register. Para modo controlado, el componente puede funcionar
17
- // si simplemente no usamos el contexto cuando no está disponible
18
- const isRegisterMode = React.useMemo(() => {
19
- // Si no hay formContext, definitivamente es modo controlado
20
- if (!formContext)
21
- return false;
22
- // Si hay formContext pero no hay name, es modo controlado
23
- if (!name)
24
- return false;
25
- // Si hay formContext y name, es modo register
26
- return true;
27
- }, [formContext, name]);
28
- // Usar el valor proporcionado solo en modo controlado (no register)
29
- // En modo register, react-hook-form maneja el valor automáticamente
30
- const currentValue = !isRegisterMode ? value : undefined;
31
- // Input hidden para compatibilidad con react-hook-form
32
- const hiddenInputRef = React.useRef(null);
33
- // Combinar el ref del forwardRef (de register) con el ref interno del input hidden
34
- const combinedRef = React.useCallback((node) => {
35
- hiddenInputRef.current = node;
36
- if (typeof ref === "function") {
37
- ref(node);
38
- }
39
- else if (ref) {
40
- ref.current = node;
41
- }
42
- }, [ref]);
43
- // Obtener el valor actual desde react-hook-form en modo register
44
- const watchValue = formContext?.watch(name || "");
45
- const actualValue = isRegisterMode
46
- ? watchValue !== undefined
47
- ? watchValue
48
- : currentValue
49
- : currentValue;
50
- const gapClasses = {
51
- sm: "gap-2",
52
- md: "gap-3",
53
- lg: "gap-4",
54
- };
55
- const directionClasses = {
56
- vertical: "flex-col",
57
- horizontal: "flex-row flex-wrap",
58
- };
59
- const containerClasses = `
60
- flex ${directionClasses[direction]} ${gapClasses[gap]}
61
- ${className}
62
- `;
63
- const sizeClasses = {
64
- sm: "w-4 h-4",
65
- md: "w-5 h-5",
66
- lg: "w-6 h-6",
67
- };
68
- const labelSizeClasses = {
69
- sm: "text-sm",
70
- md: "text-base",
71
- lg: "text-lg",
72
- };
73
- const handleOptionClick = (optionValue) => {
74
- if (disabled || readOnly)
75
- return;
76
- const valueString = String(optionValue);
77
- if (isRegisterMode && name) {
78
- // En modo register, actualizar el input hidden y usar setValue
79
- if (hiddenInputRef.current) {
80
- const nativeInput = hiddenInputRef.current;
81
- const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
82
- if (nativeInputValueSetter) {
83
- nativeInputValueSetter.call(nativeInput, valueString);
84
- }
85
- else {
86
- nativeInput.value = valueString;
87
- }
88
- // Disparar evento change para react-hook-form
89
- const changeEvent = {
90
- target: nativeInput,
91
- currentTarget: nativeInput,
92
- };
93
- if (onChange) {
94
- // En modo register, siempre usar formato de evento
95
- onChange(changeEvent);
96
- }
97
- // Disparar eventos nativos
98
- const inputEvent = new Event("input", {
99
- bubbles: true,
100
- cancelable: true,
101
- });
102
- nativeInput.dispatchEvent(inputEvent);
103
- const changeEventNative = new Event("change", {
104
- bubbles: true,
105
- cancelable: true,
106
- });
107
- nativeInput.dispatchEvent(changeEventNative);
108
- }
109
- // También usar setValue directamente como respaldo
110
- if (setValue) {
111
- setValue(name, optionValue, {
112
- shouldValidate: true,
113
- shouldDirty: true,
114
- shouldTouch: true,
115
- });
116
- }
117
- }
118
- else {
119
- // Modo controlado - llamar onChange con valor directo
120
- if (onChange) {
121
- // Verificar si onChange es una función de valor directo o ChangeEventHandler
122
- // Intentar primero como función de valor directo (modo controlado típico)
123
- const onChangeAsValueFn = onChange;
124
- // Si la función tiene la firma correcta, llamarla directamente
125
- if (typeof onChangeAsValueFn === "function") {
126
- onChangeAsValueFn(optionValue);
127
- }
128
- else {
129
- // Si no, intentar como ChangeEventHandler (por compatibilidad)
130
- const syntheticEvent = {
131
- target: { value: String(optionValue) },
132
- currentTarget: { value: String(optionValue) },
133
- };
134
- onChange(syntheticEvent);
135
- }
136
- }
137
- }
138
- };
139
- const handleBlur = (event) => {
140
- if (onBlur) {
141
- if (isRegisterMode && hiddenInputRef.current) {
142
- // En modo register, crear un evento de blur para react-hook-form
143
- const blurEvent = event ||
144
- {
145
- target: hiddenInputRef.current,
146
- currentTarget: hiddenInputRef.current,
147
- };
148
- onBlur(blurEvent);
149
- }
150
- else {
151
- // En modo controlado, llamar como función sin parámetros
152
- onBlur();
153
- }
154
- }
155
- // También disparar blur en el input hidden si existe
156
- if (hiddenInputRef.current) {
157
- hiddenInputRef.current.blur();
158
- }
159
- };
160
- return (_jsxs("div", { className: "w-full", children: [_jsx("input", { ref: combinedRef, type: "hidden", name: name, value: actualValue !== undefined ? String(actualValue) : "", readOnly: true, tabIndex: -1, "aria-hidden": "true" }), _jsx("div", { className: containerClasses, role: "radiogroup", "aria-label": name, "aria-invalid": error ? "true" : "false", "aria-errormessage": error ? `${name}-error` : undefined, ...props, children: options.map((option, index) => {
161
- const optionValue = String(option.value);
162
- const isSelected = actualValue !== undefined && String(actualValue) === optionValue;
163
- // En modo readOnly, las opciones no seleccionadas se ven deshabilitadas
164
- const isDisabled = disabled || option.disabled || (readOnly && !isSelected);
165
- const radioId = `${name || "radio"}-${index}-${option.value}`;
166
- const radioClasses = `
167
- ${sizeClasses[size]}
168
- rounded-full border-2 transition-all duration-200
169
- flex items-center justify-center
170
- ${isSelected
171
- ? "border-[var(--color-primary)]"
172
- : "border-[var(--color-border-default)]"}
173
- ${isSelected ? "bg-[var(--color-primary)]" : "bg-transparent"}
174
- ${isDisabled
175
- ? "opacity-50 cursor-not-allowed"
176
- : "cursor-pointer hover:border-[var(--color-primary)]"}
177
- focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-[var(--color-primary)]
178
- `;
179
- const labelClasses = `
180
- ${labelSizeClasses[size]}
181
- font-[var(--font-default)] select-none
182
- ${isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
183
- text-[var(--color-text-primary)]
184
- `;
185
- const optionContainerClasses = `
186
- flex items-center
187
- ${labelPosition === "left" ? "flex-row-reverse" : "flex-row"}
188
- ${gapClasses[gap]}
189
- `;
190
- return (_jsxs("div", { className: optionContainerClasses, onClick: () => !isDisabled && handleOptionClick(option.value), onBlur: index === options.length - 1
191
- ? () => {
192
- handleBlur();
193
- }
194
- : undefined, role: "radio", "aria-checked": isSelected, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : 0, onKeyDown: (e) => {
195
- if (isDisabled || readOnly)
196
- return;
197
- if (e.key === "Enter" || e.key === " ") {
198
- e.preventDefault();
199
- handleOptionClick(option.value);
200
- }
201
- }, children: [_jsx("div", { className: radioClasses, children: isSelected && (_jsx("div", { className: "rounded-full bg-white", style: {
202
- width: size === "sm"
203
- ? "8px"
204
- : size === "md"
205
- ? "10px"
206
- : "12px",
207
- height: size === "sm"
208
- ? "8px"
209
- : size === "md"
210
- ? "10px"
211
- : "12px",
212
- } })) }), option.label && (_jsx("label", { htmlFor: radioId, className: labelClasses, onClick: (e) => {
213
- e.preventDefault();
214
- if (!isDisabled) {
215
- handleOptionClick(option.value);
216
- }
217
- }, children: option.label }))] }, radioId));
218
- }) }), error && (_jsx("p", { id: name ? `${name}-error` : undefined, className: "mt-1 text-sm text-[var(--color-danger)] font-[var(--font-default)]", children: error }))] }));
219
- });
220
- RadioButtonGroup.displayName = "RadioButtonGroup";
@@ -1,336 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React, { useState, useMemo, useRef, useCallback, useEffect, } from "react";
3
- import { useFormContext } from "react-hook-form";
4
- import { Input } from "./Input";
5
- import { Button } from "./Button";
6
- import { Dialog, Loader } from "../utils";
7
- import { normalizeIconClass } from "../utils/iconUtils";
8
- const SearchSelectInputInner = React.forwardRef(function SearchSelectInput({ value, onChange, onSearchPromiseFn, onSingleSearchPromiseFn, onSelectOption, dialogTitle = "Seleccione una opción", icon = "fa-search", iconPosition = "right", noResultsText = "Sin resultados", getOptionLabel, getOptionValue, getOptionDescription, renderOption, label, readOnly = false, ...inputProps }, ref) {
9
- const [inputText, setInputText] = useState("");
10
- const [dialogInputText, setDialogInputText] = useState("");
11
- const [isDialogOpen, setIsDialogOpen] = useState(false);
12
- const [options, setOptions] = useState([]);
13
- const [isLoading, setIsLoading] = useState(false);
14
- const [hasSearched, setHasSearched] = useState(false);
15
- const inputRef = useRef(null);
16
- const dialogInputRef = useRef(null);
17
- const justClearedRef = useRef(false);
18
- // Detectar modo register
19
- const isRegisterMode = useMemo(() => {
20
- return "name" in inputProps && inputProps.name !== undefined;
21
- }, [inputProps]);
22
- const fieldName = isRegisterMode && "name" in inputProps
23
- ? inputProps.name
24
- : undefined;
25
- // Obtener setValue del contexto del formulario
26
- // Para usar con register, el formulario debe estar dentro de FormProvider
27
- // useFormContext debe llamarse incondicionalmente (requisito de React Hooks)
28
- // Si no hay FormProvider y se usa en modo register, useFormContext lanzará un error
29
- // Para usar sin FormProvider, usar Controller en lugar de register
30
- const formContext = useFormContext();
31
- const setValue = formContext?.setValue;
32
- // Combinar refs
33
- const combinedRef = useCallback((node) => {
34
- inputRef.current = node;
35
- if (typeof ref === "function") {
36
- ref(node);
37
- }
38
- else if (ref) {
39
- ref.current = node;
40
- }
41
- }, [ref]);
42
- const valueGetter = useCallback((item) => {
43
- if (getOptionValue)
44
- return getOptionValue(item);
45
- return item["value"];
46
- }, [getOptionValue]);
47
- const labelGetter = useCallback((item) => {
48
- if (getOptionLabel)
49
- return getOptionLabel(item);
50
- return item["label"];
51
- }, [getOptionLabel]);
52
- const descriptionGetter = useCallback((item) => {
53
- if (getOptionDescription)
54
- return getOptionDescription(item);
55
- return item["description"];
56
- }, [getOptionDescription]);
57
- const handleSearch = async (text) => {
58
- setIsLoading(true);
59
- setHasSearched(true);
60
- const options = await onSearchPromiseFn(text);
61
- if (options instanceof Array) {
62
- setOptions(options);
63
- }
64
- else {
65
- setOptions(options.list);
66
- }
67
- setIsLoading(false);
68
- };
69
- const handleSelect = (option) => {
70
- const selectedValue = valueGetter(option);
71
- setIsDialogOpen(false);
72
- // En modo register, setear el valor usando setValue o actualizando el input nativo
73
- if (isRegisterMode) {
74
- if (setValue && fieldName) {
75
- setValue(fieldName, selectedValue, {
76
- shouldValidate: true,
77
- shouldDirty: true,
78
- });
79
- }
80
- else if (inputRef.current) {
81
- const nativeInput = inputRef.current;
82
- const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
83
- if (nativeInputValueSetter) {
84
- nativeInputValueSetter.call(nativeInput, String(selectedValue ?? ""));
85
- }
86
- else {
87
- nativeInput.value = String(selectedValue ?? "");
88
- }
89
- if (onChange) {
90
- const changeEvent = {
91
- target: nativeInput,
92
- currentTarget: nativeInput,
93
- };
94
- onChange(changeEvent);
95
- }
96
- const inputEvent = new Event("input", {
97
- bubbles: true,
98
- cancelable: true,
99
- });
100
- nativeInput.dispatchEvent(inputEvent);
101
- const changeEventNative = new Event("change", {
102
- bubbles: true,
103
- cancelable: true,
104
- });
105
- nativeInput.dispatchEvent(changeEventNative);
106
- }
107
- }
108
- else {
109
- onChange?.(selectedValue);
110
- }
111
- onSelectOption?.(option, selectedValue);
112
- setInputText(labelGetter(option));
113
- setDialogInputText("");
114
- setOptions([]);
115
- setHasSearched(false);
116
- };
117
- // Función para sincronizar inputText con un valor
118
- const syncInputText = useCallback((currentValue) => {
119
- if (currentValue === undefined ||
120
- currentValue === null ||
121
- currentValue === "") {
122
- setInputText("");
123
- return;
124
- }
125
- // Si currentValue es un objeto (T) y tenemos getOptionLabel, usar directamente
126
- if (typeof currentValue === "object" &&
127
- getOptionLabel &&
128
- !getOptionValue) {
129
- try {
130
- const label = getOptionLabel(currentValue);
131
- setInputText(label);
132
- return;
133
- }
134
- catch {
135
- // Si falla, continuar con la búsqueda normal
136
- }
137
- }
138
- // Normalizar el value: si es un objeto (T), extraer el valor usando valueGetter
139
- let valueToSearch = currentValue;
140
- if (typeof currentValue === "object" && getOptionValue) {
141
- // Si currentValue es un objeto y tenemos getOptionValue, extraer el valor
142
- try {
143
- valueToSearch = getOptionValue(currentValue);
144
- }
145
- catch {
146
- // Si falla, no podemos usar onSingleSearchPromiseFn con un objeto
147
- // Intentar mostrar el label directamente si está disponible
148
- if (getOptionLabel) {
149
- try {
150
- setInputText(getOptionLabel(currentValue));
151
- return;
152
- }
153
- catch {
154
- setInputText(String(currentValue));
155
- return;
156
- }
157
- }
158
- setInputText(String(currentValue));
159
- return;
160
- }
161
- }
162
- // Buscar en las opciones actuales
163
- const matchingOption = options.find((opt) => valueGetter(opt) === valueToSearch ||
164
- valueGetter(opt) === currentValue);
165
- if (matchingOption) {
166
- setInputText(labelGetter(matchingOption));
167
- return;
168
- }
169
- // Si no se encuentra en las opciones actuales, usar onSingleSearchPromiseFn
170
- if (onSingleSearchPromiseFn &&
171
- valueToSearch !== undefined &&
172
- valueToSearch !== null) {
173
- onSingleSearchPromiseFn(valueToSearch)
174
- .then((foundOption) => {
175
- if (foundOption) {
176
- setInputText(labelGetter(foundOption));
177
- // Agregar la opción a las opciones disponibles si no está ya
178
- setOptions((prev) => {
179
- if (!prev.find((opt) => valueGetter(opt) === valueGetter(foundOption))) {
180
- return [...prev, foundOption];
181
- }
182
- return prev;
183
- });
184
- }
185
- else {
186
- // Si no se encuentra, mostrar el valor como string
187
- setInputText(String(valueToSearch));
188
- }
189
- })
190
- .catch((error) => {
191
- console.error("Error al buscar opción individual:", error);
192
- setInputText(String(valueToSearch));
193
- });
194
- }
195
- else {
196
- // Si no hay onSingleSearchPromiseFn, mostrar el valor como string
197
- setInputText(String(valueToSearch));
198
- }
199
- }, [
200
- options,
201
- getOptionValue,
202
- getOptionLabel,
203
- onSingleSearchPromiseFn,
204
- valueGetter,
205
- labelGetter,
206
- ]);
207
- // Sincronizar inputText cuando cambia el value (modo controlado)
208
- useEffect(() => {
209
- if (!isRegisterMode) {
210
- syncInputText(value);
211
- }
212
- }, [value, isRegisterMode, syncInputText]);
213
- // Sincronizar inputText cuando cambia el valor del formulario (modo register)
214
- useEffect(() => {
215
- if (isRegisterMode && formContext && fieldName) {
216
- // Sincronizar inicialmente
217
- const formValue = formContext.watch(fieldName);
218
- syncInputText(formValue);
219
- // Suscribirse a cambios del formulario
220
- const subscription = formContext.watch((_data, { name }) => {
221
- // Solo sincronizar cuando cambia el campo específico
222
- if (name === fieldName) {
223
- const currentFormValue = formContext.watch(fieldName);
224
- syncInputText(currentFormValue);
225
- }
226
- });
227
- return () => subscription.unsubscribe();
228
- }
229
- }, [isRegisterMode, formContext, fieldName, syncInputText]);
230
- // Hacer blur en el input del dialog cuando se abre
231
- useEffect(() => {
232
- if (isDialogOpen) {
233
- // El Dialog renderiza condicionalmente, así que necesitamos esperar a que el input esté montado
234
- // Usar requestAnimationFrame doble para asegurar que el DOM esté completamente renderizado
235
- const timeoutId = setTimeout(() => {
236
- requestAnimationFrame(() => {
237
- dialogInputRef.current?.focus();
238
- });
239
- }, 50);
240
- return () => clearTimeout(timeoutId);
241
- }
242
- }, [isDialogOpen]);
243
- const getDialogBody = () => {
244
- return (_jsxs("div", { children: [_jsx("div", { className: "mb-2", children: _jsx(Input, { ref: dialogInputRef, value: dialogInputText, onChange: (e) => setDialogInputText(e.target.value), icon: icon, iconPosition: iconPosition, onIconClick: () => handleSearch(dialogInputText), onKeyDown: (e) => {
245
- if (e.key === "Enter") {
246
- e.preventDefault();
247
- handleSearch(dialogInputText);
248
- }
249
- } }) }), _jsx("div", { children: _jsx(Loader, { isLoading: isLoading, children: !hasSearched || options.length > 0 ? (_jsx("ul", { className: "space-y-1 max-h-96 overflow-y-auto list-none pl-0 m-0", children: options.map((option, index) => {
250
- const label = labelGetter(option);
251
- const description = descriptionGetter(option);
252
- const anyOption = option;
253
- return (_jsx("li", { className: "px-3 py-2 cursor-pointer rounded-md flex items-start gap-2 text-sm\r\n text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors", onClick: () => handleSelect(option), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className: `${normalizeIconClass(anyOption.icon)} mt-0.5 text-[var(--color-text-muted)]` })), _jsxs("div", { className: "flex flex-col flex-1", children: [_jsx("span", { className: "font-[var(--font-default)]", children: label }), description !== undefined &&
254
- description !== null && (_jsx("span", { className: "text-xs text-[var(--color-text-secondary)]", children: description }))] })] })) }, String(valueGetter(option) ?? label ?? index)));
255
- }) })) : (_jsx("div", { className: "px-3 py-8 text-center text-sm text-[var(--color-text-secondary)]", children: noResultsText })) }) })] }));
256
- };
257
- // Detectar si hay un valor seleccionado
258
- const hasValue = inputText !== "" && inputText !== undefined && inputText !== null;
259
- // Función para limpiar el valor y abrir el dialog
260
- const handleIconClick = useCallback((event) => {
261
- if (readOnly)
262
- return;
263
- event.preventDefault();
264
- event.stopPropagation();
265
- if (hasValue) {
266
- // Si hay valor, limpiarlo
267
- // Marcar que acabamos de limpiar para prevenir que onFocus abra el diálogo
268
- justClearedRef.current = true;
269
- if (isRegisterMode) {
270
- if (setValue && fieldName) {
271
- setValue(fieldName, undefined, {
272
- shouldValidate: true,
273
- shouldDirty: true,
274
- });
275
- }
276
- else if (inputRef.current) {
277
- const nativeInput = inputRef.current;
278
- const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
279
- if (nativeInputValueSetter) {
280
- nativeInputValueSetter.call(nativeInput, "");
281
- }
282
- else {
283
- nativeInput.value = "";
284
- }
285
- if (onChange) {
286
- const changeEvent = {
287
- target: nativeInput,
288
- currentTarget: nativeInput,
289
- };
290
- onChange(changeEvent);
291
- }
292
- const inputEvent = new Event("input", {
293
- bubbles: true,
294
- cancelable: true,
295
- });
296
- nativeInput.dispatchEvent(inputEvent);
297
- const changeEventNative = new Event("change", {
298
- bubbles: true,
299
- cancelable: true,
300
- });
301
- nativeInput.dispatchEvent(changeEventNative);
302
- }
303
- }
304
- else {
305
- onChange?.(undefined);
306
- }
307
- setInputText("");
308
- setIsDialogOpen(false);
309
- // Resetear el flag después de un pequeño delay para permitir que otros eventos se procesen
310
- setTimeout(() => {
311
- justClearedRef.current = false;
312
- }, 100);
313
- }
314
- else {
315
- // Si no hay valor, abrir el dialog
316
- setIsDialogOpen(true);
317
- }
318
- }, [hasValue, isRegisterMode, setValue, fieldName, onChange, readOnly]);
319
- // Determinar qué ícono mostrar: si hay valor, mostrar "fa-times", sino el ícono original
320
- // Si está en readOnly, no mostrar ningún ícono
321
- const displayIcon = readOnly ? undefined : hasValue ? "fa-times" : icon;
322
- const displayIconPosition = readOnly ? undefined : iconPosition;
323
- const displayOnIconClick = readOnly ? undefined : handleIconClick;
324
- return (_jsxs(_Fragment, { children: [_jsx(Input, { ...inputProps, ref: combinedRef, label: label, value: inputText, onChange: (e) => {
325
- if (readOnly)
326
- return;
327
- setInputText(e.target.value);
328
- }, onFocus: () => {
329
- if (!readOnly && !justClearedRef.current) {
330
- setIsDialogOpen(true);
331
- }
332
- }, icon: displayIcon, iconPosition: displayIconPosition, onIconClick: displayOnIconClick, readOnly: readOnly }), !readOnly && (_jsx(Dialog, { isOpen: isDialogOpen, title: dialogTitle, footer: _jsx(Button, { variant: "outline", onClick: () => setIsDialogOpen(false), children: "Cerrar" }), onClose: () => setIsDialogOpen(false), children: getDialogBody() }))] }));
333
- });
334
- SearchSelectInputInner.displayName = "SearchSelectInput";
335
- // Exportar con el cast genérico para permitir uso como <SearchSelectInput<T, K>>
336
- export const SearchSelectInput = SearchSelectInputInner;
@@ -1,11 +0,0 @@
1
- export { Button } from "./Button";
2
- export { LinkButton } from "./LinkButton";
3
- export { Input } from "./Input";
4
- export { AutocompleteInput } from "./AutocompleteInput";
5
- export { SearchSelectInput } from "./SearchSelectInput";
6
- export { DatePicker } from "./DatePicker";
7
- export { DateInput } from "./DateInput";
8
- export { Pagination } from "./Pagination";
9
- export { Checkbox } from "./Checkbox";
10
- export { RadioButtonGroup } from "./RadioButtonGroup";
11
- export { CurrencyInput } from "./CurrencyInput";
@@ -1,7 +0,0 @@
1
- // Form Controls
2
- export * from "./form-controls";
3
- // Layout Components
4
- export * from "./layout";
5
- // Utility Components
6
- export * from "./utils";
7
- export { ThemeSwitcher } from "./ThemeSwitcher";
@@ -1,67 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useState, useRef, useEffect } from "react";
3
- import { normalizeIconClass } from "../utils/iconUtils";
4
- export const Accordion = ({ title, children, icon, rightNode, defaultOpen = false, className = "", variant = "default", onToggle, }) => {
5
- const [isOpen, setIsOpen] = useState(defaultOpen);
6
- const [contentHeight, setContentHeight] = useState(0);
7
- const contentRef = useRef(null);
8
- // Separar clases de background del className
9
- const classArray = className.trim().split(/\s+/).filter(Boolean);
10
- const bgClasses = [];
11
- const otherClasses = [];
12
- classArray.forEach((cls) => {
13
- // Detectar clases de background (bg-*, bg-gradient-*, bg-[...])
14
- if (cls.startsWith("bg-") || cls.startsWith("bg-gradient-")) {
15
- bgClasses.push(cls);
16
- }
17
- else {
18
- otherClasses.push(cls);
19
- }
20
- });
21
- const backgroundClass = bgClasses.length > 0 ? bgClasses.join(" ") : "bg-[var(--color-bg-default)]";
22
- const baseClasses = `
23
- ${backgroundClass} rounded-lg border
24
- font-[var(--font-default)]
25
- `;
26
- const variantClasses = {
27
- default: `border-[var(--color-border-default)]`,
28
- elevated: `border-[var(--color-border-default)] shadow-[var(--shadow-lg)]`,
29
- outlined: `border-[var(--color-gray-300)]`,
30
- };
31
- const classes = `${baseClasses} ${variantClasses[variant]} ${otherClasses.join(" ")}`;
32
- useEffect(() => {
33
- if (contentRef.current) {
34
- if (isOpen) {
35
- // Usar requestAnimationFrame para asegurar que el DOM esté actualizado
36
- requestAnimationFrame(() => {
37
- if (contentRef.current) {
38
- setContentHeight(contentRef.current.scrollHeight);
39
- }
40
- });
41
- }
42
- else {
43
- setContentHeight(0);
44
- }
45
- }
46
- }, [isOpen, children]);
47
- // Inicializar altura si está abierto por defecto
48
- useEffect(() => {
49
- if (defaultOpen && contentRef.current) {
50
- requestAnimationFrame(() => {
51
- if (contentRef.current) {
52
- setContentHeight(contentRef.current.scrollHeight);
53
- }
54
- });
55
- }
56
- }, [defaultOpen]);
57
- const handleToggle = () => {
58
- const newIsOpen = !isOpen;
59
- setIsOpen(newIsOpen);
60
- if (onToggle) {
61
- onToggle(newIsOpen);
62
- }
63
- };
64
- return (_jsxs("div", { className: `${classes} overflow-hidden`, children: [_jsxs("button", { onClick: handleToggle, className: "w-full flex items-center justify-between px-4 py-3 flysoft-button-reset bg-transparent border-none hover:bg-black/5 dark:hover:bg-white/5 transition-colors cursor-pointer", "aria-expanded": isOpen, children: [_jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [icon && (_jsx("i", { className: `${normalizeIconClass(icon)} text-[var(--color-text-secondary)] flex-shrink-0` })), _jsx("span", { className: "text-left font-medium text-[var(--color-text-primary)] truncate", children: title })] }), _jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [rightNode && (_jsx("div", { className: "flex items-center", onClick: (e) => e.stopPropagation(), children: rightNode })), _jsx("i", { className: `${normalizeIconClass(`fa-chevron-${isOpen ? "up" : "down"}`)} text-[var(--color-text-secondary)] transition-all duration-200 flex-shrink-0` })] })] }), _jsx("div", { ref: contentRef, className: "overflow-hidden transition-all duration-300 ease-in-out", style: {
65
- maxHeight: `${contentHeight}px`,
66
- }, children: _jsx("div", { className: "px-4 py-3 text-[var(--color-text-primary)]", children: children }) })] }));
67
- };