flysoft-react-ui 1.2.4 → 1.2.5

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 +11889 -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 +6 -3
  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,578 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { createPortal } from "react-dom";
4
- import dayjs, {} from "dayjs";
5
- import { useFormContext } from "react-hook-form";
6
- import { Input } from "./Input";
7
- import { DatePicker } from "./DatePicker";
8
- const pad = (value) => value.toString().padStart(2, "0");
9
- const isDayjs = (value) => {
10
- return (value !== null &&
11
- value !== undefined &&
12
- typeof value === "object" &&
13
- "isValid" in value &&
14
- typeof value.isValid === "function");
15
- };
16
- const normalizeToDayjs = (value) => {
17
- if (value === null || value === undefined)
18
- return null;
19
- if (isDayjs(value))
20
- return value;
21
- // Si no es Dayjs, intentar convertirlo
22
- if (typeof value === "string" ||
23
- typeof value === "number" ||
24
- value instanceof Date) {
25
- const d = dayjs(value);
26
- return d.isValid() ? d : null;
27
- }
28
- return null;
29
- };
30
- const formatDateToString = (date, format) => {
31
- const normalized = normalizeToDayjs(date);
32
- if (!normalized || !normalized.isValid())
33
- return "";
34
- const day = pad(normalized.date());
35
- const month = pad(normalized.month() + 1);
36
- const year = normalized.year().toString();
37
- if (format === "mm/dd/yyyy") {
38
- return `${month}/${day}/${year}`;
39
- }
40
- return `${day}/${month}/${year}`;
41
- };
42
- const parseDateFromString = (value, format) => {
43
- // Primero intentar parsear como números sin separadores (ej: 11102025)
44
- const numbersOnly = value.replace(/\D/g, "");
45
- if (numbersOnly.length === 8) {
46
- // Formato: ddmmyyyy o mmddyyyy
47
- const p1 = parseInt(numbersOnly.substring(0, 2), 10);
48
- const p2 = parseInt(numbersOnly.substring(2, 4), 10);
49
- const p3 = parseInt(numbersOnly.substring(4, 8), 10);
50
- const day = format === "mm/dd/yyyy" ? p2 : p1;
51
- const month = format === "mm/dd/yyyy" ? p1 : p2;
52
- const year = p3;
53
- if (!isNaN(day) &&
54
- !isNaN(month) &&
55
- !isNaN(year) &&
56
- day >= 1 &&
57
- month >= 1 &&
58
- month <= 12 &&
59
- year >= 1000 &&
60
- year <= 9999) {
61
- const date = dayjs()
62
- .year(year)
63
- .month(month - 1)
64
- .date(day);
65
- if (date.isValid() &&
66
- date.year() === year &&
67
- date.month() === month - 1 &&
68
- date.date() === day) {
69
- return date.startOf("day");
70
- }
71
- }
72
- }
73
- // Si no funciona, intentar parsear con separadores
74
- const parts = value.split(/[/\-.]/).map((p) => p.trim());
75
- if (parts.length !== 3)
76
- return null;
77
- const [p1, p2, p3] = parts;
78
- const day = format === "mm/dd/yyyy" ? parseInt(p2, 10) : parseInt(p1, 10);
79
- const month = format === "mm/dd/yyyy" ? parseInt(p1, 10) : parseInt(p2, 10);
80
- const year = parseInt(p3, 10);
81
- if (isNaN(day) ||
82
- isNaN(month) ||
83
- isNaN(year) ||
84
- day < 1 ||
85
- month < 1 ||
86
- month > 12) {
87
- return null;
88
- }
89
- const date = dayjs()
90
- .year(year)
91
- .month(month - 1)
92
- .date(day);
93
- if (!date.isValid() ||
94
- date.year() !== year ||
95
- date.month() !== month - 1 ||
96
- date.date() !== day) {
97
- return null;
98
- }
99
- return date.startOf("day");
100
- };
101
- export const DateInput = React.forwardRef(({ value, onChange, format = "dd/mm/yyyy", datePickerProps, icon = "fa-calendar-alt", iconPosition = "right", className = "", readOnly = false, ...inputProps }, ref) => {
102
- // Extraer onBlur de inputProps para manejarlo por separado
103
- const { onBlur: registerOnBlur, ...restInputProps } = inputProps;
104
- // Detectar si estamos en modo register: si viene 'name' de register, estamos en modo register
105
- // register siempre pasa 'name', 'onChange', 'onBlur', y 'ref'
106
- const isRegisterMode = React.useMemo(() => {
107
- // Si viene 'name' en inputProps, es porque viene de register
108
- return "name" in inputProps && inputProps.name !== undefined;
109
- }, [inputProps]);
110
- const fieldName = isRegisterMode && "name" in restInputProps
111
- ? restInputProps.name
112
- : undefined;
113
- // Obtener setValue del contexto del formulario
114
- // useFormContext debe llamarse incondicionalmente (requisito de React Hooks)
115
- // Si no hay FormProvider, esto lanzará un error
116
- // Para usar sin FormProvider, el componente guardará el valor Dayjs serializado (ISO string)
117
- // en el input, y se puede parsear de vuelta a Dayjs cuando se lee el valor del formulario
118
- const formContext = useFormContext();
119
- const setValue = formContext?.setValue;
120
- const [internalDate, setInternalDate] = React.useState(null);
121
- const [displayValue, setDisplayValue] = React.useState("");
122
- const [isOpen, setIsOpen] = React.useState(false);
123
- const [pickerPosition, setPickerPosition] = React.useState(null);
124
- const containerRef = React.useRef(null);
125
- const pickerRef = React.useRef(null);
126
- const inputRef = React.useRef(null);
127
- const hiddenInputRef = React.useRef(null);
128
- const isTypingRef = React.useRef(false);
129
- const lastDayjsValueRef = React.useRef(null);
130
- // Función helper para sincronizar displayValue con el valor del formulario en modo register
131
- const syncDisplayValue = React.useCallback(() => {
132
- if (isRegisterMode && inputRef.current) {
133
- const formValue = inputRef.current.value;
134
- if (formValue) {
135
- // Parsear el string de fecha del formulario
136
- const parsed = parseDateFromString(formValue, format);
137
- if (parsed) {
138
- setDisplayValue(formatDateToString(parsed, format));
139
- setInternalDate(parsed);
140
- return true;
141
- }
142
- else {
143
- // Si hay un valor pero no se puede parsear, mostrarlo tal cual
144
- setDisplayValue(formValue);
145
- return true;
146
- }
147
- }
148
- else {
149
- setDisplayValue("");
150
- setInternalDate(null);
151
- return false;
152
- }
153
- }
154
- return false;
155
- }, [isRegisterMode, format]);
156
- // Sincronizar displayValue con el valor del formulario en modo register
157
- React.useEffect(() => {
158
- if (isRegisterMode) {
159
- let attempts = 0;
160
- const maxAttempts = 50; // Intentar durante ~5 segundos (50 * 100ms)
161
- const trySync = () => {
162
- if (inputRef.current) {
163
- const formValue = inputRef.current.value;
164
- if (formValue) {
165
- const parsed = parseDateFromString(formValue, format);
166
- if (parsed) {
167
- setDisplayValue(formatDateToString(parsed, format));
168
- setInternalDate(parsed);
169
- return true;
170
- }
171
- else {
172
- setDisplayValue(formValue);
173
- return true;
174
- }
175
- }
176
- else {
177
- setDisplayValue("");
178
- setInternalDate(null);
179
- }
180
- }
181
- return false;
182
- };
183
- // Intentar inmediatamente
184
- if (trySync()) {
185
- return;
186
- }
187
- // Si no encontramos el valor, usar un intervalo
188
- const intervalId = window.setInterval(() => {
189
- attempts++;
190
- if (trySync() || attempts >= maxAttempts) {
191
- clearInterval(intervalId);
192
- }
193
- }, 100);
194
- // También usar timeouts como fallback
195
- const timeouts = [];
196
- [0, 50, 100, 200, 500, 1000].forEach((delay) => {
197
- const timeoutId = window.setTimeout(() => {
198
- trySync();
199
- }, delay);
200
- timeouts.push(timeoutId);
201
- });
202
- return () => {
203
- clearInterval(intervalId);
204
- timeouts.forEach(clearTimeout);
205
- };
206
- }
207
- }, [isRegisterMode, format]);
208
- // También escuchar cambios en el input nativo para sincronizar cuando cambie
209
- React.useEffect(() => {
210
- if (isRegisterMode && inputRef.current) {
211
- const input = inputRef.current;
212
- const handleInputSync = () => {
213
- syncDisplayValue();
214
- };
215
- input.addEventListener("input", handleInputSync);
216
- input.addEventListener("change", handleInputSync);
217
- const observer = new MutationObserver(() => {
218
- syncDisplayValue();
219
- });
220
- observer.observe(input, {
221
- attributes: true,
222
- attributeFilter: ["value"],
223
- });
224
- return () => {
225
- input.removeEventListener("input", handleInputSync);
226
- input.removeEventListener("change", handleInputSync);
227
- observer.disconnect();
228
- };
229
- }
230
- }, [isRegisterMode, syncDisplayValue]);
231
- // Sincronizar con el valor del formulario
232
- React.useEffect(() => {
233
- if (!isTypingRef.current) {
234
- if (isRegisterMode) {
235
- // En modo register con setValue, leer del formulario
236
- if (formContext && fieldName) {
237
- const formValue = formContext.watch(fieldName);
238
- const normalized = normalizeToDayjs(formValue);
239
- setInternalDate(normalized);
240
- if (normalized) {
241
- setDisplayValue(formatDateToString(normalized, format));
242
- }
243
- else {
244
- setDisplayValue("");
245
- }
246
- }
247
- // Si no hay setValue, syncDisplayValue se encarga de sincronizar desde el input nativo
248
- }
249
- else {
250
- // Modo Controller, sincronizar con el valor Dayjs
251
- const normalized = normalizeToDayjs(value);
252
- setInternalDate(normalized);
253
- if (normalized) {
254
- setDisplayValue(formatDateToString(normalized, format));
255
- }
256
- else {
257
- setDisplayValue("");
258
- }
259
- }
260
- }
261
- }, [value, format, isRegisterMode, setValue, fieldName, formContext]);
262
- // Determinar el valor a mostrar en el input
263
- const inputValue = isRegisterMode ? displayValue : displayValue;
264
- const handleDateChange = (date) => {
265
- if (readOnly)
266
- return;
267
- const dateString = formatDateToString(date, format);
268
- if (isRegisterMode) {
269
- // En modo register, usar setValue si está disponible para guardar el objeto Dayjs
270
- // Si no está disponible, guardar como string (comportamiento por defecto)
271
- if (setValue && fieldName) {
272
- // Usar setValue para guardar el objeto Dayjs directamente
273
- setValue(fieldName, date, {
274
- shouldValidate: true,
275
- shouldDirty: true,
276
- shouldTouch: true,
277
- });
278
- // Actualizar el displayValue y el estado interno
279
- setDisplayValue(dateString);
280
- setInternalDate(date);
281
- // Actualizar el input nativo con el valor visual (string) para mantener la sincronización
282
- // Esto es solo para mostrar el valor correcto en el input
283
- // El valor real (Dayjs) ya está guardado en el formulario vía setValue
284
- if (inputRef.current) {
285
- const nativeInput = inputRef.current;
286
- const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
287
- if (nativeInputValueSetter) {
288
- nativeInputValueSetter.call(nativeInput, dateString);
289
- }
290
- else {
291
- nativeInput.value = dateString;
292
- }
293
- }
294
- }
295
- else {
296
- // Sin FormProvider: guardar el valor Dayjs serializado (ISO string) en el input
297
- // react-hook-form leerá este valor y se puede parsear de vuelta a Dayjs cuando se lee
298
- lastDayjsValueRef.current = date;
299
- // Guardar el valor Dayjs serializado (como ISO string)
300
- const dayjsIsoString = date ? date.toISOString() : "";
301
- // Actualizar el input visible con el valor Dayjs serializado
302
- // Esto es lo que react-hook-form leerá y guardará
303
- if (inputRef.current) {
304
- const nativeInput = inputRef.current;
305
- const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
306
- if (nativeInputValueSetter) {
307
- nativeInputValueSetter.call(nativeInput, dayjsIsoString);
308
- }
309
- else {
310
- nativeInput.value = dayjsIsoString;
311
- }
312
- // Llamar al onChange de register con el valor Dayjs serializado
313
- if (onChange) {
314
- const changeEvent = {
315
- target: nativeInput,
316
- currentTarget: nativeInput,
317
- };
318
- onChange(changeEvent);
319
- }
320
- // Disparar eventos nativos
321
- const inputEvent = new Event("input", {
322
- bubbles: true,
323
- cancelable: true,
324
- });
325
- nativeInput.dispatchEvent(inputEvent);
326
- const changeEventNative = new Event("change", {
327
- bubbles: true,
328
- cancelable: true,
329
- });
330
- nativeInput.dispatchEvent(changeEventNative);
331
- }
332
- // Actualizar el displayValue con el string formateado para mostrar al usuario
333
- // Aunque el input tiene el ISO string, mostramos el formato legible
334
- setDisplayValue(dateString);
335
- setInternalDate(date);
336
- }
337
- }
338
- else {
339
- // Modo Controller - comportamiento original
340
- setInternalDate(date);
341
- setDisplayValue(dateString);
342
- if (onChange) {
343
- const dayjsHandler = onChange;
344
- dayjsHandler(date);
345
- }
346
- }
347
- setIsOpen(false);
348
- };
349
- const handleInputChange = (event) => {
350
- if (readOnly)
351
- return;
352
- const newValue = event.target.value;
353
- isTypingRef.current = true;
354
- if (isRegisterMode) {
355
- // En modo register, actualizar el displayValue mientras el usuario escribe
356
- setDisplayValue(newValue);
357
- }
358
- else {
359
- // Modo Controller
360
- setDisplayValue(newValue);
361
- }
362
- };
363
- const handleInputBlur = (event) => {
364
- isTypingRef.current = false;
365
- const newValue = event.target.value.trim();
366
- if (isRegisterMode) {
367
- // En modo register, validar y actualizar el input nativo
368
- if (!newValue) {
369
- // Limpiar el valor
370
- if (setValue && fieldName) {
371
- // Si tenemos setValue, usar setValue para limpiar el valor como null
372
- setValue(fieldName, null, {
373
- shouldValidate: true,
374
- shouldDirty: true,
375
- shouldTouch: true,
376
- });
377
- setDisplayValue("");
378
- setInternalDate(null);
379
- }
380
- else {
381
- // Fallback: actualizar el input nativo
382
- if (inputRef.current) {
383
- const nativeInput = inputRef.current;
384
- const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
385
- setter?.call(nativeInput, "");
386
- if (onChange) {
387
- const changeEvent = {
388
- target: nativeInput,
389
- currentTarget: nativeInput,
390
- };
391
- onChange(changeEvent);
392
- }
393
- const inputEvent = new Event("input", { bubbles: true });
394
- nativeInput.dispatchEvent(inputEvent);
395
- const changeEventNative = new Event("change", { bubbles: true });
396
- nativeInput.dispatchEvent(changeEventNative);
397
- }
398
- setDisplayValue("");
399
- setInternalDate(null);
400
- }
401
- }
402
- else {
403
- const parsed = parseDateFromString(newValue, format);
404
- if (parsed) {
405
- // handleDateChange ya usa setValue si está disponible
406
- handleDateChange(parsed);
407
- // Si usamos setValue, asegurarse de que el valor Dayjs se mantenga
408
- // después del blur, ya que registerOnBlur puede causar que react-hook-form
409
- // lea el valor del input como string
410
- if (setValue && fieldName && registerOnBlur) {
411
- // Guardar el valor Dayjs antes de llamar a registerOnBlur
412
- const dayjsValue = parsed;
413
- // Llamar al onBlur de register
414
- registerOnBlur(event);
415
- // Usar setTimeout para asegurarse de que esto se ejecuta después de registerOnBlur
416
- // y restaurar el valor Dayjs si react-hook-form lo sobrescribió con un string
417
- setTimeout(() => {
418
- const currentValue = formContext?.watch(fieldName);
419
- // Si el valor actual es un string en lugar de Dayjs, restaurarlo
420
- if (currentValue && typeof currentValue === "string") {
421
- setValue(fieldName, dayjsValue, {
422
- shouldValidate: true,
423
- shouldDirty: true,
424
- shouldTouch: true,
425
- });
426
- }
427
- }, 0);
428
- // No llamar a registerOnBlur más abajo ya que ya lo llamamos aquí
429
- return;
430
- }
431
- }
432
- else {
433
- // Si no es válida, restaurar el valor anterior
434
- const previousValue = inputRef.current?.value || "";
435
- setDisplayValue(previousValue);
436
- }
437
- }
438
- // Llamar al onBlur de register si existe
439
- // Solo se llama aquí si no usamos setValue o si no había un valor válido
440
- if (registerOnBlur) {
441
- registerOnBlur(event);
442
- }
443
- }
444
- else {
445
- // Modo Controller
446
- if (!newValue) {
447
- handleDateChange(null);
448
- }
449
- else {
450
- const parsed = parseDateFromString(newValue, format);
451
- if (parsed) {
452
- handleDateChange(parsed);
453
- }
454
- else {
455
- // Si no es válida, restaurar el valor anterior formateado
456
- setDisplayValue(formatDateToString(internalDate, format));
457
- }
458
- }
459
- }
460
- };
461
- const handleIconClick = (event) => {
462
- if (readOnly)
463
- return;
464
- event.preventDefault();
465
- setIsOpen((prev) => !prev);
466
- };
467
- React.useEffect(() => {
468
- if (!isOpen)
469
- return;
470
- const handleClickOutside = (event) => {
471
- const target = event.target;
472
- const isClickInsideContainer = containerRef.current?.contains(target);
473
- const isClickInsidePicker = pickerRef.current?.contains(target);
474
- if (!isClickInsideContainer && !isClickInsidePicker) {
475
- setIsOpen(false);
476
- }
477
- };
478
- // Pequeño delay para asegurar que el portal esté montado
479
- const timer = setTimeout(() => {
480
- document.addEventListener("mousedown", handleClickOutside);
481
- }, 0);
482
- return () => {
483
- clearTimeout(timer);
484
- document.removeEventListener("mousedown", handleClickOutside);
485
- };
486
- }, [isOpen]);
487
- // Combinar refs: el ref del componente y el ref interno
488
- const combinedRef = React.useCallback((node) => {
489
- inputRef.current = node;
490
- if (typeof ref === "function") {
491
- ref(node);
492
- }
493
- else if (ref) {
494
- ref.current = node;
495
- }
496
- // Cuando el ref se establece en modo register, sincronizar el displayValue
497
- if (isRegisterMode && node) {
498
- [0, 10, 50, 100, 200, 500].forEach((delay) => {
499
- setTimeout(() => {
500
- if (node && inputRef.current === node) {
501
- const formValue = node.value;
502
- if (formValue) {
503
- const parsed = parseDateFromString(formValue, format);
504
- if (parsed) {
505
- setDisplayValue(formatDateToString(parsed, format));
506
- setInternalDate(parsed);
507
- }
508
- else {
509
- setDisplayValue(formValue);
510
- }
511
- }
512
- }
513
- }, delay);
514
- });
515
- }
516
- }, [ref, isRegisterMode, format]);
517
- const datePickerInitialViewDate = internalDate ?? datePickerProps?.initialViewDate ?? dayjs();
518
- // Ocultar el ícono cuando está en modo readOnly
519
- const displayIcon = readOnly ? undefined : icon;
520
- const displayIconPosition = readOnly ? undefined : iconPosition;
521
- const displayOnIconClick = readOnly ? undefined : handleIconClick;
522
- // Verificar que estamos en el navegador
523
- // Inicializar isMounted de forma síncrona si es posible
524
- const [isMounted, setIsMounted] = React.useState(() => {
525
- return typeof document !== "undefined" && !!document.body;
526
- });
527
- React.useEffect(() => {
528
- if (!isMounted && typeof document !== "undefined" && document.body) {
529
- setIsMounted(true);
530
- }
531
- }, [isMounted]);
532
- // Actualizar posición del picker cuando se abre
533
- React.useEffect(() => {
534
- if (isOpen && !readOnly && containerRef.current && isMounted) {
535
- const updatePosition = () => {
536
- const rect = containerRef.current?.getBoundingClientRect();
537
- if (rect) {
538
- setPickerPosition({
539
- top: rect.bottom + window.scrollY + 4,
540
- left: rect.right + window.scrollX - 280, // Alinear a la derecha
541
- width: rect.width,
542
- });
543
- }
544
- };
545
- updatePosition();
546
- window.addEventListener("scroll", updatePosition, true);
547
- window.addEventListener("resize", updatePosition);
548
- return () => {
549
- window.removeEventListener("scroll", updatePosition, true);
550
- window.removeEventListener("resize", updatePosition);
551
- };
552
- }
553
- else {
554
- setPickerPosition(null);
555
- }
556
- }, [isOpen, readOnly, isMounted]);
557
- return (_jsxs("div", { ref: containerRef, className: "relative w-full", children: [isRegisterMode && !setValue && fieldName && (_jsx("input", { ref: hiddenInputRef, type: "hidden", name: fieldName, value: lastDayjsValueRef.current
558
- ? lastDayjsValueRef.current.toISOString()
559
- : "" })), _jsx(Input, { ...restInputProps, ref: combinedRef, type: "text", value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, icon: displayIcon, iconPosition: displayIconPosition, onIconClick: displayOnIconClick, placeholder: restInputProps.placeholder ??
560
- (format === "mm/dd/yyyy" ? "mm/dd/yyyy" : "dd/mm/yyyy"), className: className, readOnly: readOnly }), (() => {
561
- // Verificar de forma segura que document.body existe y es válido
562
- const bodyElement = typeof document !== "undefined" &&
563
- document.body &&
564
- document.body instanceof HTMLElement
565
- ? document.body
566
- : null;
567
- return (!readOnly &&
568
- isOpen &&
569
- pickerPosition &&
570
- isMounted &&
571
- bodyElement &&
572
- createPortal(_jsx("div", { ref: pickerRef, className: "fixed z-[2001] min-w-[280px] w-max", style: {
573
- top: `${pickerPosition.top}px`,
574
- left: `${pickerPosition.left}px`,
575
- }, children: _jsx(DatePicker, { ...datePickerProps, value: internalDate ?? datePickerInitialViewDate, onChange: (date) => handleDateChange(date) }) }), bodyElement));
576
- })()] }));
577
- });
578
- DateInput.displayName = "DateInput";