flysoft-react-ui 0.4.0 → 0.5.2

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 (178) hide show
  1. package/dist/App.d.ts.map +1 -1
  2. package/dist/App.js +20 -4
  3. package/dist/components/form-controls/AutocompleteInput.d.ts +11 -3
  4. package/dist/components/form-controls/AutocompleteInput.d.ts.map +1 -1
  5. package/dist/components/form-controls/AutocompleteInput.js +410 -31
  6. package/dist/components/form-controls/Button.js +1 -1
  7. package/dist/components/form-controls/Checkbox.d.ts +14 -0
  8. package/dist/components/form-controls/Checkbox.d.ts.map +1 -0
  9. package/dist/components/form-controls/Checkbox.js +77 -0
  10. package/dist/components/form-controls/DateInput.d.ts +20 -4
  11. package/dist/components/form-controls/DateInput.d.ts.map +1 -1
  12. package/dist/components/form-controls/DateInput.js +425 -70
  13. package/dist/components/form-controls/DatePicker.d.ts +4 -3
  14. package/dist/components/form-controls/DatePicker.d.ts.map +1 -1
  15. package/dist/components/form-controls/DatePicker.js +26 -30
  16. package/dist/components/form-controls/Input.d.ts +10 -1
  17. package/dist/components/form-controls/Input.d.ts.map +1 -1
  18. package/dist/components/form-controls/Input.js +16 -10
  19. package/dist/components/form-controls/Pagination.d.ts +1 -0
  20. package/dist/components/form-controls/Pagination.d.ts.map +1 -1
  21. package/dist/components/form-controls/Pagination.js +3 -40
  22. package/dist/components/form-controls/RadioButtonGroup.d.ts +62 -0
  23. package/dist/components/form-controls/RadioButtonGroup.d.ts.map +1 -0
  24. package/dist/components/form-controls/RadioButtonGroup.js +220 -0
  25. package/dist/components/form-controls/SearchSelectInput-OLD.d.ts +68 -0
  26. package/dist/components/form-controls/SearchSelectInput-OLD.d.ts.map +1 -0
  27. package/dist/components/form-controls/SearchSelectInput-OLD.js +962 -0
  28. package/dist/components/form-controls/SearchSelectInput.d.ts +70 -0
  29. package/dist/components/form-controls/SearchSelectInput.d.ts.map +1 -0
  30. package/dist/components/form-controls/SearchSelectInput.js +335 -0
  31. package/dist/components/form-controls/index.d.ts +7 -1
  32. package/dist/components/form-controls/index.d.ts.map +1 -1
  33. package/dist/components/form-controls/index.js +3 -0
  34. package/dist/components/layout/AppLayout.d.ts +3 -2
  35. package/dist/components/layout/AppLayout.d.ts.map +1 -1
  36. package/dist/components/layout/AppLayout.js +104 -31
  37. package/dist/components/layout/Card.d.ts +4 -1
  38. package/dist/components/layout/Card.d.ts.map +1 -1
  39. package/dist/components/layout/Card.js +30 -1
  40. package/dist/components/layout/Collection.js +1 -1
  41. package/dist/components/layout/DataTable.d.ts +29 -0
  42. package/dist/components/layout/DataTable.d.ts.map +1 -0
  43. package/dist/components/layout/DataTable.js +165 -0
  44. package/dist/components/layout/index.d.ts +2 -0
  45. package/dist/components/layout/index.d.ts.map +1 -1
  46. package/dist/components/layout/index.js +1 -0
  47. package/dist/components/utils/Avatar.d.ts +49 -0
  48. package/dist/components/utils/Avatar.d.ts.map +1 -0
  49. package/dist/components/utils/Avatar.js +93 -0
  50. package/dist/components/utils/Badge.d.ts +3 -0
  51. package/dist/components/utils/Badge.d.ts.map +1 -1
  52. package/dist/components/utils/Badge.js +130 -26
  53. package/dist/components/utils/Dialog.d.ts.map +1 -1
  54. package/dist/components/utils/Dialog.js +5 -1
  55. package/dist/components/utils/DropdownMenu.d.ts +25 -0
  56. package/dist/components/utils/DropdownMenu.d.ts.map +1 -0
  57. package/dist/components/utils/DropdownMenu.js +145 -0
  58. package/dist/components/utils/Filter.d.ts +57 -0
  59. package/dist/components/utils/Filter.d.ts.map +1 -0
  60. package/dist/components/utils/Filter.js +580 -0
  61. package/dist/components/utils/FiltersDialog.d.ts +21 -0
  62. package/dist/components/utils/FiltersDialog.d.ts.map +1 -0
  63. package/dist/components/utils/FiltersDialog.js +104 -0
  64. package/dist/components/utils/Loader.js +1 -1
  65. package/dist/components/utils/RoadMap.d.ts +59 -0
  66. package/dist/components/utils/RoadMap.d.ts.map +1 -0
  67. package/dist/components/utils/RoadMap.js +138 -0
  68. package/dist/components/utils/Snackbar.d.ts +13 -0
  69. package/dist/components/utils/Snackbar.d.ts.map +1 -0
  70. package/dist/components/utils/Snackbar.js +121 -0
  71. package/dist/components/utils/SnackbarContainer.d.ts +7 -0
  72. package/dist/components/utils/SnackbarContainer.d.ts.map +1 -0
  73. package/dist/components/utils/SnackbarContainer.js +25 -0
  74. package/dist/components/utils/index.d.ts +12 -0
  75. package/dist/components/utils/index.d.ts.map +1 -1
  76. package/dist/components/utils/index.js +6 -0
  77. package/dist/contexts/AppLayoutContext.d.ts +40 -0
  78. package/dist/contexts/AppLayoutContext.d.ts.map +1 -0
  79. package/dist/contexts/AppLayoutContext.js +98 -0
  80. package/dist/contexts/ListCrudContext.d.ts +29 -0
  81. package/dist/contexts/ListCrudContext.d.ts.map +1 -0
  82. package/dist/contexts/ListCrudContext.js +209 -0
  83. package/dist/contexts/SnackbarContext.d.ts +26 -0
  84. package/dist/contexts/SnackbarContext.d.ts.map +1 -0
  85. package/dist/contexts/SnackbarContext.js +34 -0
  86. package/dist/contexts/index.d.ts +6 -0
  87. package/dist/contexts/index.d.ts.map +1 -1
  88. package/dist/contexts/index.js +6 -0
  89. package/dist/contexts/presets.js +6 -6
  90. package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +3 -1
  91. package/dist/docs/AvatarDocs.d.ts +4 -0
  92. package/dist/docs/AvatarDocs.d.ts.map +1 -0
  93. package/dist/docs/AvatarDocs.js +7 -0
  94. package/dist/docs/BadgeDocs.d.ts.map +1 -1
  95. package/dist/docs/BadgeDocs.js +4 -2
  96. package/dist/docs/CardDocs.d.ts.map +1 -1
  97. package/dist/docs/CardDocs.js +7 -1
  98. package/dist/docs/CheckboxDocs.d.ts +4 -0
  99. package/dist/docs/CheckboxDocs.d.ts.map +1 -0
  100. package/dist/docs/CheckboxDocs.js +7 -0
  101. package/dist/docs/DataTableDocs.d.ts +4 -0
  102. package/dist/docs/DataTableDocs.d.ts.map +1 -0
  103. package/dist/docs/DataTableDocs.js +244 -0
  104. package/dist/docs/DateInputDocs.d.ts +1 -0
  105. package/dist/docs/DateInputDocs.d.ts.map +1 -1
  106. package/dist/docs/DateInputDocs.js +7 -9
  107. package/dist/docs/DatePickerDocs.d.ts +1 -0
  108. package/dist/docs/DatePickerDocs.d.ts.map +1 -1
  109. package/dist/docs/DatePickerDocs.js +6 -8
  110. package/dist/docs/DocAdmin.d.ts +4 -0
  111. package/dist/docs/DocAdmin.d.ts.map +1 -0
  112. package/dist/docs/DocAdmin.js +68 -0
  113. package/dist/docs/DocsMenu.d.ts.map +1 -1
  114. package/dist/docs/DocsMenu.js +1 -1
  115. package/dist/docs/DocsRouter.d.ts.map +1 -1
  116. package/dist/docs/DocsRouter.js +13 -1
  117. package/dist/docs/DropdownMenuDocs.d.ts +4 -0
  118. package/dist/docs/DropdownMenuDocs.d.ts.map +1 -0
  119. package/dist/docs/DropdownMenuDocs.js +66 -0
  120. package/dist/docs/ExampleFormDocs.d.ts +4 -0
  121. package/dist/docs/ExampleFormDocs.d.ts.map +1 -0
  122. package/dist/docs/ExampleFormDocs.js +148 -0
  123. package/dist/docs/FilterDocs.d.ts +4 -0
  124. package/dist/docs/FilterDocs.d.ts.map +1 -0
  125. package/dist/docs/FilterDocs.js +112 -0
  126. package/dist/docs/InputDocs.d.ts.map +1 -1
  127. package/dist/docs/InputDocs.js +11 -1
  128. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +11 -0
  129. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +1 -0
  130. package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +25 -0
  131. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts +2 -0
  132. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +1 -0
  133. package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +51 -0
  134. package/dist/docs/PaginationDocs.js +6 -6
  135. package/dist/docs/RadioButtonGroupDocs.d.ts +4 -0
  136. package/dist/docs/RadioButtonGroupDocs.d.ts.map +1 -0
  137. package/dist/docs/RadioButtonGroupDocs.js +46 -0
  138. package/dist/docs/RoadMapDocs.d.ts +4 -0
  139. package/dist/docs/RoadMapDocs.d.ts.map +1 -0
  140. package/dist/docs/RoadMapDocs.js +171 -0
  141. package/dist/docs/SearchSelectInputDocs.d.ts +4 -0
  142. package/dist/docs/SearchSelectInputDocs.d.ts.map +1 -0
  143. package/dist/docs/SearchSelectInputDocs.js +168 -0
  144. package/dist/docs/SnackbarDocs.d.ts +4 -0
  145. package/dist/docs/SnackbarDocs.d.ts.map +1 -0
  146. package/dist/docs/SnackbarDocs.js +50 -0
  147. package/dist/docs/TabsGroupDocs.d.ts.map +1 -1
  148. package/dist/docs/TabsGroupDocs.js +12 -1
  149. package/dist/docs/docMockServices/empresaService.d.ts +38 -0
  150. package/dist/docs/docMockServices/empresaService.d.ts.map +1 -0
  151. package/dist/docs/docMockServices/empresaService.js +116 -0
  152. package/dist/docs/docMockServices/index.d.ts +9 -0
  153. package/dist/docs/docMockServices/index.d.ts.map +1 -0
  154. package/dist/docs/docMockServices/index.js +8 -0
  155. package/dist/docs/docMockServices/initialData.d.ts +6 -0
  156. package/dist/docs/docMockServices/initialData.d.ts.map +1 -0
  157. package/dist/docs/docMockServices/initialData.js +132 -0
  158. package/dist/docs/docMockServices/interfaces.d.ts +26 -0
  159. package/dist/docs/docMockServices/interfaces.d.ts.map +1 -0
  160. package/dist/docs/docMockServices/interfaces.js +1 -0
  161. package/dist/docs/docMockServices/personaEmpresaService.d.ts +43 -0
  162. package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +1 -0
  163. package/dist/docs/docMockServices/personaEmpresaService.js +113 -0
  164. package/dist/docs/docMockServices/personaService.d.ts +39 -0
  165. package/dist/docs/docMockServices/personaService.d.ts.map +1 -0
  166. package/dist/docs/docMockServices/personaService.js +180 -0
  167. package/dist/hooks/index.d.ts +2 -0
  168. package/dist/hooks/index.d.ts.map +1 -1
  169. package/dist/hooks/index.js +1 -0
  170. package/dist/hooks/useAsyncRequest.d.ts +17 -0
  171. package/dist/hooks/useAsyncRequest.d.ts.map +1 -0
  172. package/dist/hooks/useAsyncRequest.js +70 -0
  173. package/dist/index.css +1 -1
  174. package/dist/index.d.ts +22 -0
  175. package/dist/index.d.ts.map +1 -1
  176. package/dist/index.js +11 -0
  177. package/dist/index.js.map +1 -1
  178. package/package.json +5 -2
@@ -1,18 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
+ import dayjs, {} from "dayjs";
3
4
  import { Button } from "./Button";
4
5
  const createDateAtMidnight = (date) => {
5
- const d = new Date(date);
6
- d.setHours(0, 0, 0, 0);
7
- return d;
6
+ const d = dayjs(date);
7
+ return d.startOf("day");
8
8
  };
9
9
  const isSameDay = (a, b) => {
10
- return (a.getFullYear() === b.getFullYear() &&
11
- a.getMonth() === b.getMonth() &&
12
- a.getDate() === b.getDate());
10
+ return a.isSame(b, "day");
13
11
  };
14
12
  const getDaysInMonth = (year, month) => {
15
- return new Date(year, month + 1, 0).getDate();
13
+ return dayjs().year(year).month(month).daysInMonth();
16
14
  };
17
15
  const getWeekdayLabels = (startWeekOn) => {
18
16
  const base = ["D", "L", "M", "X", "J", "V", "S"];
@@ -22,23 +20,19 @@ const getWeekdayLabels = (startWeekOn) => {
22
20
  return [...base.slice(1), base[0]];
23
21
  };
24
22
  export const DatePicker = ({ value, onChange, initialViewDate, startWeekOn = "sunday", className = "", }) => {
25
- const today = React.useMemo(() => createDateAtMidnight(new Date()), []);
26
- const initial = React.useMemo(() => {
27
- const base = value ?? initialViewDate ?? today;
23
+ const today = React.useMemo(() => dayjs().startOf("day"), []);
24
+ const getViewFromValue = React.useCallback((val) => {
25
+ const base = val ?? initialViewDate ?? today;
28
26
  return {
29
- month: base.getMonth(),
30
- year: base.getFullYear(),
27
+ month: base.month(),
28
+ year: base.year(),
31
29
  };
32
- }, [value, initialViewDate, today]);
33
- const [view, setView] = React.useState(initial);
30
+ }, [initialViewDate, today]);
31
+ const [view, setView] = React.useState(() => getViewFromValue(value));
34
32
  React.useEffect(() => {
35
- if (value) {
36
- setView({
37
- month: value.getMonth(),
38
- year: value.getFullYear(),
39
- });
40
- }
41
- }, [value]);
33
+ // Sincronizar la vista con el valor actual, incluso si es null/undefined
34
+ setView(getViewFromValue(value));
35
+ }, [value, getViewFromValue]);
42
36
  const handlePrevMonth = () => {
43
37
  setView((prev) => {
44
38
  const month = prev.month === 0 ? 11 : prev.month - 1;
@@ -62,7 +56,7 @@ export const DatePicker = ({ value, onChange, initialViewDate, startWeekOn = "su
62
56
  const handleSelectDay = (day, month, year) => {
63
57
  const targetMonth = month !== undefined ? month : view.month;
64
58
  const targetYear = year !== undefined ? year : view.year;
65
- const date = new Date(targetYear, targetMonth, day);
59
+ const date = dayjs().year(targetYear).month(targetMonth).date(day);
66
60
  onChange?.(createDateAtMidnight(date));
67
61
  // Si el día es de otro mes, cambiar la vista
68
62
  if (month !== undefined && month !== view.month) {
@@ -72,8 +66,8 @@ export const DatePicker = ({ value, onChange, initialViewDate, startWeekOn = "su
72
66
  setView({ month: targetMonth, year: targetYear });
73
67
  }
74
68
  };
75
- const firstDayOfMonth = new Date(view.year, view.month, 1);
76
- const firstWeekday = firstDayOfMonth.getDay(); // 0-6, Sunday=0
69
+ const firstDayOfMonth = dayjs().year(view.year).month(view.month).date(1);
70
+ const firstWeekday = firstDayOfMonth.day(); // 0-6, Sunday=0
77
71
  const daysInMonth = getDaysInMonth(view.year, view.month);
78
72
  const weekdayLabels = getWeekdayLabels(startWeekOn);
79
73
  const offset = startWeekOn === "sunday"
@@ -115,15 +109,17 @@ export const DatePicker = ({ value, onChange, initialViewDate, startWeekOn = "su
115
109
  }
116
110
  weeks.push(currentWeek);
117
111
  }
118
- const selectedDate = value && !isNaN(value.getTime()) ? createDateAtMidnight(value) : null;
119
- const monthName = new Date(view.year, view.month, 1).toLocaleString("es-ES", {
120
- month: "long",
121
- });
122
- return (_jsxs("div", { className: `inline-flex flex-col rounded-lg border border-[var(--color-border-default)]
112
+ const selectedDate = value && value.isValid() ? createDateAtMidnight(value) : null;
113
+ const monthName = dayjs()
114
+ .year(view.year)
115
+ .month(view.month)
116
+ .date(1)
117
+ .format("MMMM");
118
+ return (_jsxs("div", { className: `inline-flex flex-col rounded-lg border border-[var(--color-border-default)]
123
119
  bg-[var(--color-bg-default)] p-3 shadow-sm font-[var(--font-default)] text-sm ${className}`, children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { type: "button", size: "sm", variant: "ghost", icon: "fa-angle-double-left", onClick: handlePrevYear, "aria-label": "A\u00F1o anterior" }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", icon: "fa-angle-left", onClick: handlePrevMonth, "aria-label": "Mes anterior" })] }), _jsx("div", { className: "text-center", children: _jsxs("div", { className: "text-[var(--color-text-primary)] font-medium capitalize", children: [monthName, " ", view.year] }) }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { type: "button", size: "sm", variant: "ghost", icon: "fa-angle-right", onClick: handleNextMonth, "aria-label": "Mes siguiente" }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", icon: "fa-angle-double-right", onClick: handleNextYear, "aria-label": "A\u00F1o siguiente" })] })] }), _jsx("div", { className: "grid grid-cols-7 gap-1 mb-1", children: weekdayLabels.map((label) => (_jsx("div", { className: "text-xs text-center text-[var(--color-text-secondary)]", children: label }, label))) }), _jsx("div", { className: "grid grid-rows-6 gap-1", children: weeks.map((week, rowIndex) => (_jsx("div", { className: "grid grid-cols-7 gap-1", children: week.map((dayInfo, index) => {
124
120
  const { day, month, year } = dayInfo;
125
121
  const isCurrentMonth = month === view.month && year === view.year;
126
- const date = new Date(year, month, day);
122
+ const date = dayjs().year(year).month(month).date(day);
127
123
  const isToday = isSameDay(date, today);
128
124
  const isSelected = selectedDate !== null && isSameDay(date, selectedDate);
129
125
  let dayClasses = "w-8 h-8 flex items-center justify-center rounded-full cursor-pointer text-xs";
@@ -6,6 +6,15 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
6
6
  iconPosition?: "left" | "right";
7
7
  size?: "sm" | "md" | "lg";
8
8
  children?: React.ReactNode;
9
+ /**
10
+ * Callback cuando se hace click en el ícono. Si está definido, el ícono será clickeable.
11
+ */
12
+ onIconClick?: (event: React.MouseEvent<HTMLElement>) => void;
13
+ /**
14
+ * Si es true, el input será de solo lectura. No se podrá modificar pero no se verá como disabled.
15
+ * Por defecto es false.
16
+ */
17
+ readOnly?: boolean;
9
18
  }
10
- export declare const Input: React.FC<InputProps>;
19
+ export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
11
20
  //# sourceMappingURL=Input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,UACf,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA0EtC,CAAC"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,UACf,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAC7D;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,KAAK,qFA4FjB,CAAC"}
@@ -1,27 +1,33 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
- export const Input = ({ label, error, icon, iconPosition = "left", size = "md", className = "", id, ...props }) => {
3
+ export const Input = React.forwardRef(({ label, error, icon, iconPosition = "left", size = "md", className = "", id, onIconClick, readOnly = false, ...props }, ref) => {
4
4
  const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
5
5
  const baseClasses = `
6
- w-full border rounded-lg transition-colors focus:outline-none focus:ring-1
6
+ w-full border rounded-lg transition-colors focus:outline-none
7
7
  disabled:opacity-50 disabled:cursor-not-allowed
8
8
  font-[var(--font-default)] text-[var(--color-text-primary)]
9
- bg-[var(--color-bg-default)]
10
9
  `;
10
+ const readOnlyClasses = readOnly
11
+ ? `border-transparent bg-transparent focus:ring-0`
12
+ : `focus:ring-1 bg-[var(--color-bg-default)]`;
11
13
  const sizeClasses = {
12
14
  sm: "px-3 py-1.5 text-sm",
13
15
  md: "px-4 py-2 text-base",
14
16
  lg: "px-6 py-3 text-lg",
15
17
  };
16
- const stateClasses = error
17
- ? `border-[var(--color-border-error)] focus:border-[var(--color-border-error)] focus:ring-[var(--color-border-error)]`
18
- : `border-[var(--color-border-default)] focus:border-[var(--color-border-focus)] focus:ring-[var(--color-border-focus)]`;
19
- const inputClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${className}`;
18
+ const stateClasses = readOnly
19
+ ? ""
20
+ : error
21
+ ? `border-[var(--color-border-error)] focus:border-[var(--color-border-error)] focus:ring-[var(--color-border-error)]`
22
+ : `border-[var(--color-border-default)] focus:border-[var(--color-border-focus)] focus:ring-[var(--color-border-focus)]`;
23
+ const inputClasses = `${baseClasses} ${readOnlyClasses} ${sizeClasses[size]} ${stateClasses} ${className}`;
20
24
  const iconClasses = size === "sm" ? "w-4 h-4" : size === "md" ? "w-5 h-5" : "w-6 h-6";
21
25
  const renderIcon = () => {
22
26
  if (!icon)
23
27
  return null;
24
- return (_jsx("i", { className: `fa ${icon} ${iconClasses} text-[var(--color-text-muted)] absolute top-1/2 transform -translate-y-1/2 ${iconPosition === "left" ? "left-3" : "right-3"}` }));
28
+ const iconElement = (_jsx("i", { className: `fa ${icon} ${iconClasses} text-[var(--color-text-muted)] absolute top-1/2 transform -translate-y-1/2 ${iconPosition === "left" ? "left-3" : "right-3"} ${onIconClick && !readOnly ? "cursor-pointer hover:text-[var(--color-primary)] transition-colors" : ""}`, onClick: readOnly ? undefined : onIconClick }));
29
+ return iconElement;
25
30
  };
26
- return (_jsxs("div", { className: "w-full", children: [label && (_jsx("label", { htmlFor: inputId, className: "block text-sm text-[var(--color-primary)] mb-1 font-[var(--font-default)]", children: label })), _jsxs("div", { className: "relative", children: [icon && iconPosition === "left" && renderIcon(), _jsx("input", { id: inputId, className: `${inputClasses} ${icon && iconPosition === "left" ? "pl-10" : ""} ${icon && iconPosition === "right" ? "pr-10" : ""}`, ...props }), icon && iconPosition === "right" && renderIcon()] }), error && (_jsx("p", { className: "mt-1 text-sm text-[var(--color-danger)] font-[var(--font-default)]", children: error }))] }));
27
- };
31
+ return (_jsxs("div", { className: "w-full", children: [label && (_jsx("label", { htmlFor: inputId, className: "block text-sm text-[var(--color-primary)] mb-1 font-[var(--font-default)]", children: label })), _jsxs("div", { className: "relative", children: [icon && iconPosition === "left" && renderIcon(), _jsx("input", { ref: ref, id: inputId, className: `${inputClasses} ${icon && iconPosition === "left" ? "pl-10" : ""} ${icon && iconPosition === "right" ? "pr-10" : ""}`, autoComplete: "off", readOnly: readOnly, ...props }), icon && iconPosition === "right" && renderIcon()] }), error && (_jsx("p", { className: "mt-1 text-sm text-[var(--color-danger)] font-[var(--font-default)]", children: error }))] }));
32
+ });
33
+ Input.displayName = "Input";
@@ -11,6 +11,7 @@ export interface PaginationProps {
11
11
  page?: number;
12
12
  pages?: number;
13
13
  total?: number;
14
+ isLoading?: boolean;
14
15
  }
15
16
  export declare const Pagination: React.FC<PaginationProps>;
16
17
  //# sourceMappingURL=Pagination.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/Pagination.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAsHhD,CAAC"}
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/Pagination.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0FhD,CAAC"}
@@ -1,8 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  import { useSearchParams } from "react-router-dom";
4
4
  import { Button } from "./Button";
5
- export const Pagination = ({ fieldName = "pagina", page = 1, pages = 1, total = 0, }) => {
5
+ export const Pagination = ({ fieldName = "pagina", page = 1, pages = 1, total = 0, isLoading = false, }) => {
6
6
  const [searchParams, setSearchParams] = useSearchParams();
7
7
  const navigateToPage = (newPage) => {
8
8
  if (newPage < 1 || newPage > pages || newPage === page) {
@@ -19,42 +19,5 @@ export const Pagination = ({ fieldName = "pagina", page = 1, pages = 1, total =
19
19
  const isFirstPage = page <= 1;
20
20
  const isLastPage = page >= pages;
21
21
  const hasPages = pages > 1;
22
- return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-double-left", onClick: goToFirstPage, disabled: isFirstPage || !hasPages, "aria-label": "Primera p\u00E1gina" }) }), _jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-left", onClick: goToPreviousPage, disabled: isFirstPage || !hasPages, "aria-label": "P\u00E1gina anterior" }) }), _jsxs("div", { className: "text-xs", children: [_jsxs("span", { className: "block", children: ["P\u00E1gina ", page, " de ", pages] }), _jsxs("span", { className: "block", children: [total, " elemento", total !== 1 ? "s" : ""] })] }), _jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-right", onClick: goToNextPage, disabled: isLastPage || !hasPages, "aria-label": "P\u00E1gina siguiente" }) }), _jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-double-right", onClick: goToLastPage, disabled: isLastPage || !hasPages, "aria-label": "\u00DAltima p\u00E1gina" }) })] })
23
- // <div className="flex flex-col items-center gap-0 font-[var(--font-default)]">
24
- // {/* Botones de navegación */}
25
- // <div className="flex items-center gap-2">
26
- //
27
- // {/* Texto de página */}
28
- // <span
29
- // className="text-xs px-3 leading-none"
30
- // style={{ color: "var(--color-text-primary)" }}
31
- // >
32
- // Página {page} de {pages}
33
- // </span>
34
- // <Button
35
- // variant="ghost"
36
- // size="sm"
37
- // icon="fa-angle-right"
38
- // onClick={goToNextPage}
39
- // disabled={isLastPage || !hasPages}
40
- // aria-label="Página siguiente"
41
- // />
42
- // <Button
43
- // variant="ghost"
44
- // size="sm"
45
- // icon="fa-angle-double-right"
46
- // onClick={goToLastPage}
47
- // disabled={isLastPage || !hasPages}
48
- // aria-label="Última página"
49
- // />
50
- // </div>
51
- // {/* Texto de elementos */}
52
- // <span
53
- // className="text-xs leading-none"
54
- // style={{ color: "var(--color-text-secondary)" }}
55
- // >
56
- // {total} elemento{total !== 1 ? "s" : ""}
57
- // </span>
58
- // </div>
59
- );
22
+ return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-double-left", onClick: goToFirstPage, disabled: isFirstPage || !hasPages || isLoading, "aria-label": "Primera p\u00E1gina" }) }), _jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-left", onClick: goToPreviousPage, disabled: isFirstPage || !hasPages || isLoading, "aria-label": "P\u00E1gina anterior" }) }), _jsx("div", { className: `text-xs h-[32px] min-w-[100px] text-center flex flex-col justify-center`, children: isLoading ? (_jsx(_Fragment, { children: _jsx("span", { className: "block", children: "Cargando..." }) })) : (_jsxs(_Fragment, { children: [_jsxs("span", { className: "block", children: ["P\u00E1gina ", page, " de ", pages] }), _jsxs("span", { className: "block", children: [total, " elemento", total !== 1 ? "s" : ""] })] })) }), _jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-right", onClick: goToNextPage, disabled: isLastPage || !hasPages || isLoading, "aria-label": "P\u00E1gina siguiente" }) }), _jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-angle-double-right", onClick: goToLastPage, disabled: isLastPage || !hasPages || isLoading, "aria-label": "\u00DAltima p\u00E1gina" }) })] }));
60
23
  };
@@ -0,0 +1,62 @@
1
+ import React from "react";
2
+ export interface RadioOption {
3
+ label: string;
4
+ value: string | number;
5
+ disabled?: boolean;
6
+ }
7
+ export interface RadioButtonGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange" | "children"> {
8
+ /**
9
+ * Array de opciones para renderizar radios automáticamente
10
+ */
11
+ options: RadioOption[];
12
+ /**
13
+ * Valor seleccionado (controlado)
14
+ */
15
+ value?: string | number;
16
+ /**
17
+ * Callback cuando cambia la selección
18
+ * Puede recibir un valor directo o un evento (para compatibilidad con react-hook-form)
19
+ */
20
+ onChange?: ((value: string | number) => void) | React.ChangeEventHandler<HTMLInputElement>;
21
+ /**
22
+ * Posición del label para todas las opciones
23
+ */
24
+ labelPosition?: "left" | "right";
25
+ /**
26
+ * Tamaño de los radio buttons
27
+ */
28
+ size?: "sm" | "md" | "lg";
29
+ /**
30
+ * Mensaje de error a mostrar
31
+ */
32
+ error?: string;
33
+ /**
34
+ * Dirección del layout: vertical (columna) o horizontal (fila)
35
+ */
36
+ direction?: "vertical" | "horizontal";
37
+ /**
38
+ * Espaciado entre opciones
39
+ */
40
+ gap?: "sm" | "md" | "lg";
41
+ /**
42
+ * Nombre del campo (para react-hook-form)
43
+ */
44
+ name?: string;
45
+ /**
46
+ * Estado deshabilitado
47
+ */
48
+ disabled?: boolean;
49
+ /**
50
+ * Callback cuando pierde el foco
51
+ * Puede recibir un evento (para compatibilidad con react-hook-form) o ser una función sin parámetros
52
+ */
53
+ onBlur?: (() => void) | React.FocusEventHandler<HTMLInputElement>;
54
+ /**
55
+ * Si es true, el radio group será de solo lectura. Las opciones no seleccionadas se verán deshabilitadas
56
+ * y la seleccionada se verá igual, pero no se podrá cambiar el valor.
57
+ * Por defecto es false.
58
+ */
59
+ readOnly?: boolean;
60
+ }
61
+ export declare const RadioButtonGroup: React.ForwardRefExoticComponent<RadioButtonGroupProps & React.RefAttributes<HTMLInputElement>>;
62
+ //# sourceMappingURL=RadioButtonGroup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadioButtonGroup.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/RadioButtonGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC3E;;OAEG;IACH,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EACL,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC,GAClC,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAC/C;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACtC;;OAEG;IACH,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACzB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IAClE;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,gBAAgB,gGAmV5B,CAAC"}
@@ -0,0 +1,220 @@
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";
@@ -0,0 +1,68 @@
1
+ import React from "react";
2
+ import type { InputProps } from "./Input";
3
+ import type { PaginationInterface } from "./Pagination";
4
+ export interface SearchSelectOption {
5
+ label: string;
6
+ value?: string;
7
+ description?: string | number;
8
+ icon?: string;
9
+ }
10
+ export interface SearchSelectInputProps<T = SearchSelectOption, K = string> extends Omit<InputProps, "onChange" | "value" | "ref"> {
11
+ /**
12
+ * Valor del input (controlado).
13
+ * Puede ser la opción completa (T), el valor extraído (K si hay getOptionValue), o un string (para compatibilidad con react-hook-form).
14
+ */
15
+ value?: T | K | string;
16
+ /**
17
+ * Callback cuando cambia el valor del input.
18
+ * Recibe la opción completa (T) si no hay getOptionValue, o el valor extraído (K) si hay getOptionValue.
19
+ * También es compatible con react-hook-form: acepta el onChange estándar de HTML.
20
+ */
21
+ onChange?: ((value: T | K) => void) | React.ChangeEventHandler<HTMLInputElement>;
22
+ /**
23
+ * Función que realiza la búsqueda y devuelve un Promise con los resultados
24
+ */
25
+ onSearchPromiseFn: (text: string) => Promise<Array<T> | PaginationInterface<T>>;
26
+ /**
27
+ * Función que busca un elemento individual usando su valor (K).
28
+ * Se usa cuando hay un valor por defecto que no está presente en las opciones cargadas.
29
+ * Recibe el valor (K) y devuelve una Promise con el objeto completo (T) o undefined si no se encuentra.
30
+ */
31
+ onSingleSearchPromiseFn: (value: K) => Promise<T | undefined>;
32
+ /**
33
+ * Callback al seleccionar una opción. Devuelve el item completo (T) y el valor mapeado (K)
34
+ */
35
+ onSelectOption?: (option: T, value: K) => void;
36
+ /**
37
+ * Título del dialog de selección. Por defecto "Seleccione una opción"
38
+ */
39
+ dialogTitle?: string;
40
+ /**
41
+ * Posición del botón de búsqueda. Por defecto "right"
42
+ */
43
+ searchButtonPosition?: "left" | "right";
44
+ /**
45
+ * Texto a mostrar cuando no hay resultados
46
+ */
47
+ noResultsText?: string;
48
+ /**
49
+ * Obtiene el label que se muestra para cada opción. Por defecto usa la propiedad "label".
50
+ */
51
+ getOptionLabel?: (item: T) => string;
52
+ /**
53
+ * Obtiene el valor que se devuelve al seleccionar una opción. Por defecto usa la propiedad "value".
54
+ */
55
+ getOptionValue?: (item: T) => K;
56
+ /**
57
+ * Obtiene la descripción opcional para cada opción. Por defecto usa la propiedad "description".
58
+ */
59
+ getOptionDescription?: (item: T) => string | number | undefined;
60
+ /**
61
+ * Renderizado personalizado de cada opción. Si se define, se ignora el render por defecto.
62
+ */
63
+ renderOption?: (item: T) => React.ReactNode;
64
+ }
65
+ export declare const SearchSelectInput: <T = SearchSelectOption, K = string>(props: SearchSelectInputProps<T, K> & {
66
+ ref?: React.ForwardedRef<HTMLInputElement>;
67
+ }) => React.ReactElement;
68
+ //# sourceMappingURL=SearchSelectInput-OLD.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchSelectInput-OLD.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/SearchSelectInput-OLD.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGxD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,GAAG,MAAM,CACxE,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IACtD;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EACL,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GACxB,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAC/C;;OAEG;IACH,iBAAiB,EAAE,CACjB,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD;;;;OAIG;IACH,uBAAuB,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9D;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC;;OAEG;IACH,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAChE;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CAC7C;AA6sCD,eAAO,MAAM,iBAAiB,EAAiC,CAC7D,CAAC,GAAG,kBAAkB,EACtB,CAAC,GAAG,MAAM,EAEV,KAAK,EAAE,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IACpC,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;CAC5C,KACE,KAAK,CAAC,YAAY,CAAC"}