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.
- package/AI_CONTEXT.md +1400 -217
- package/AI_INTEGRATION_GUIDE.md +343 -0
- package/INTEGRATION_GUIDE.md +60 -0
- package/README.md +5 -3
- package/dist/components/form-controls/Input.d.ts.map +1 -1
- package/dist/components/layout/Accordion.d.ts +1 -0
- package/dist/components/layout/Accordion.d.ts.map +1 -1
- package/dist/components/layout/DataTable.d.ts.map +1 -1
- package/dist/components/layout/DropdownMenu.d.ts +2 -1
- package/dist/components/layout/DropdownMenu.d.ts.map +1 -1
- package/dist/components/layout/DropdownPanel.d.ts +2 -1
- package/dist/components/layout/DropdownPanel.d.ts.map +1 -1
- package/dist/components/layout/Filter.d.ts +1 -0
- package/dist/components/layout/Filter.d.ts.map +1 -1
- package/dist/components/layout/Menu.d.ts +2 -1
- package/dist/components/layout/Menu.d.ts.map +1 -1
- package/dist/components/layout/TabsGroup.d.ts +1 -0
- package/dist/components/layout/TabsGroup.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11190 -24
- package/dist/index.js.map +1 -1
- package/dist/templates/forms/ContactForm.d.ts +1 -0
- package/dist/templates/forms/ContactForm.d.ts.map +1 -1
- package/dist/templates/forms/LoginForm.d.ts +1 -0
- package/dist/templates/forms/LoginForm.d.ts.map +1 -1
- package/dist/templates/forms/RegistrationForm.d.ts +1 -0
- package/dist/templates/forms/RegistrationForm.d.ts.map +1 -1
- package/dist/templates/layouts/DashboardLayout.d.ts +1 -0
- package/dist/templates/layouts/DashboardLayout.d.ts.map +1 -1
- package/dist/templates/layouts/SidebarLayout.d.ts +1 -0
- package/dist/templates/layouts/SidebarLayout.d.ts.map +1 -1
- package/dist/templates/patterns/FormPattern.d.ts +1 -0
- package/dist/templates/patterns/FormPattern.d.ts.map +1 -1
- package/dist/templates/patterns/ListPattern.d.ts +77 -0
- package/dist/templates/patterns/ListPattern.d.ts.map +1 -0
- package/package.json +8 -4
- package/dist/App.d.ts +0 -4
- package/dist/App.d.ts.map +0 -1
- package/dist/App.js +0 -30
- package/dist/components/ThemeSwitcher.js +0 -12
- package/dist/components/form-controls/AutocompleteInput.js +0 -680
- package/dist/components/form-controls/Button.js +0 -211
- package/dist/components/form-controls/Checkbox.js +0 -79
- package/dist/components/form-controls/CurrencyInput.js +0 -106
- package/dist/components/form-controls/DateInput.js +0 -578
- package/dist/components/form-controls/DatePicker.js +0 -144
- package/dist/components/form-controls/Input.js +0 -35
- package/dist/components/form-controls/LinkButton.js +0 -248
- package/dist/components/form-controls/Pagination.js +0 -23
- package/dist/components/form-controls/RadioButtonGroup.js +0 -220
- package/dist/components/form-controls/SearchSelectInput.js +0 -336
- package/dist/components/form-controls/index.js +0 -11
- package/dist/components/index.js +0 -7
- package/dist/components/layout/Accordion.js +0 -67
- package/dist/components/layout/AppLayout.js +0 -230
- package/dist/components/layout/Card.js +0 -54
- package/dist/components/layout/Collection.js +0 -18
- package/dist/components/layout/DataField.js +0 -38
- package/dist/components/layout/DataTable.js +0 -164
- package/dist/components/layout/DropdownMenu.js +0 -176
- package/dist/components/layout/DropdownPanel.js +0 -162
- package/dist/components/layout/Filter.js +0 -629
- package/dist/components/layout/Menu.js +0 -21
- package/dist/components/layout/TabPanel.js +0 -11
- package/dist/components/layout/TabsGroup.js +0 -52
- package/dist/components/layout/index.js +0 -12
- package/dist/components/utils/Avatar.js +0 -77
- package/dist/components/utils/Badge.js +0 -151
- package/dist/components/utils/Dialog.js +0 -44
- package/dist/components/utils/FiltersDialog.js +0 -104
- package/dist/components/utils/Loader.js +0 -44
- package/dist/components/utils/RoadMap.js +0 -139
- package/dist/components/utils/Skeleton.js +0 -10
- package/dist/components/utils/Snackbar.js +0 -136
- package/dist/components/utils/SnackbarContainer.js +0 -26
- package/dist/components/utils/iconUtils.js +0 -40
- package/dist/components/utils/index.js +0 -9
- package/dist/contexts/AppLayoutContext.js +0 -104
- package/dist/contexts/AuthContext.js +0 -224
- package/dist/contexts/CrudContext.js +0 -333
- package/dist/contexts/SnackbarContext.js +0 -41
- package/dist/contexts/ThemeContext.js +0 -197
- package/dist/contexts/index.js +0 -13
- package/dist/contexts/presets.js +0 -311
- package/dist/contexts/types.js +0 -1
- package/dist/docs/AccordionDocs.d.ts +0 -4
- package/dist/docs/AccordionDocs.d.ts.map +0 -1
- package/dist/docs/AccordionDocs.js +0 -21
- package/dist/docs/AuthDocs.tsx/AuthDocs.d.ts +0 -13
- package/dist/docs/AuthDocs.tsx/AuthDocs.d.ts.map +0 -1
- package/dist/docs/AuthDocs.tsx/AuthDocs.js +0 -18
- package/dist/docs/AuthDocs.tsx/AuthDocsContent.d.ts +0 -2
- package/dist/docs/AuthDocs.tsx/AuthDocsContent.d.ts.map +0 -1
- package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +0 -22
- package/dist/docs/AuthDocs.tsx/mockAuthService.d.ts +0 -24
- package/dist/docs/AuthDocs.tsx/mockAuthService.d.ts.map +0 -1
- package/dist/docs/AuthDocs.tsx/mockAuthService.js +0 -78
- package/dist/docs/AutocompleteInputDocs.d.ts +0 -4
- package/dist/docs/AutocompleteInputDocs.d.ts.map +0 -1
- package/dist/docs/AutocompleteInputDocs.js +0 -84
- package/dist/docs/AvatarDocs.d.ts +0 -4
- package/dist/docs/AvatarDocs.d.ts.map +0 -1
- package/dist/docs/AvatarDocs.js +0 -7
- package/dist/docs/BadgeDocs.d.ts +0 -4
- package/dist/docs/BadgeDocs.d.ts.map +0 -1
- package/dist/docs/BadgeDocs.js +0 -9
- package/dist/docs/ButtonDocs.d.ts +0 -4
- package/dist/docs/ButtonDocs.d.ts.map +0 -1
- package/dist/docs/ButtonDocs.js +0 -7
- package/dist/docs/CardDocs.d.ts +0 -4
- package/dist/docs/CardDocs.d.ts.map +0 -1
- package/dist/docs/CardDocs.js +0 -22
- package/dist/docs/CheckboxDocs.d.ts +0 -4
- package/dist/docs/CheckboxDocs.d.ts.map +0 -1
- package/dist/docs/CheckboxDocs.js +0 -7
- package/dist/docs/CurrencyInputDocs.d.ts +0 -4
- package/dist/docs/CurrencyInputDocs.d.ts.map +0 -1
- package/dist/docs/CurrencyInputDocs.js +0 -22
- package/dist/docs/DataFieldDocs.d.ts +0 -4
- package/dist/docs/DataFieldDocs.d.ts.map +0 -1
- package/dist/docs/DataFieldDocs.js +0 -7
- package/dist/docs/DataTableDocs.d.ts +0 -4
- package/dist/docs/DataTableDocs.d.ts.map +0 -1
- package/dist/docs/DataTableDocs.js +0 -244
- package/dist/docs/DateInputDocs.d.ts +0 -5
- package/dist/docs/DateInputDocs.d.ts.map +0 -1
- package/dist/docs/DateInputDocs.js +0 -19
- package/dist/docs/DatePickerDocs.d.ts +0 -5
- package/dist/docs/DatePickerDocs.d.ts.map +0 -1
- package/dist/docs/DatePickerDocs.js +0 -16
- package/dist/docs/DialogDocs.d.ts +0 -4
- package/dist/docs/DialogDocs.d.ts.map +0 -1
- package/dist/docs/DialogDocs.js +0 -13
- package/dist/docs/DocAdmin.d.ts +0 -4
- package/dist/docs/DocAdmin.d.ts.map +0 -1
- package/dist/docs/DocAdmin.js +0 -68
- package/dist/docs/DocsMenu.d.ts +0 -2
- package/dist/docs/DocsMenu.d.ts.map +0 -1
- package/dist/docs/DocsMenu.js +0 -5
- package/dist/docs/DocsRouter.d.ts +0 -4
- package/dist/docs/DocsRouter.d.ts.map +0 -1
- package/dist/docs/DocsRouter.js +0 -39
- package/dist/docs/DropdownMenuDocs.d.ts +0 -4
- package/dist/docs/DropdownMenuDocs.d.ts.map +0 -1
- package/dist/docs/DropdownMenuDocs.js +0 -66
- package/dist/docs/DropdownPanelDocs.d.ts +0 -4
- package/dist/docs/DropdownPanelDocs.d.ts.map +0 -1
- package/dist/docs/DropdownPanelDocs.js +0 -7
- package/dist/docs/ExampleFormDocs.d.ts +0 -4
- package/dist/docs/ExampleFormDocs.d.ts.map +0 -1
- package/dist/docs/ExampleFormDocs.js +0 -153
- package/dist/docs/FilterDocs.d.ts +0 -4
- package/dist/docs/FilterDocs.d.ts.map +0 -1
- package/dist/docs/FilterDocs.js +0 -130
- package/dist/docs/InputDocs.d.ts +0 -4
- package/dist/docs/InputDocs.d.ts.map +0 -1
- package/dist/docs/InputDocs.js +0 -17
- package/dist/docs/LinkButtonDocs.d.ts +0 -4
- package/dist/docs/LinkButtonDocs.d.ts.map +0 -1
- package/dist/docs/LinkButtonDocs.js +0 -7
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +0 -2
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +0 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +0 -47
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts +0 -2
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts.map +0 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.js +0 -34
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts +0 -2
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts.map +0 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.js +0 -66
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts +0 -2
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts.map +0 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.js +0 -7
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts +0 -10
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts.map +0 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.js +0 -39
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts +0 -2
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +0 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +0 -57
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts +0 -9
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts.map +0 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.js +0 -30
- package/dist/docs/LoaderDocs.d.ts +0 -4
- package/dist/docs/LoaderDocs.d.ts.map +0 -1
- package/dist/docs/LoaderDocs.js +0 -33
- package/dist/docs/MenuDocs.d.ts +0 -4
- package/dist/docs/MenuDocs.d.ts.map +0 -1
- package/dist/docs/MenuDocs.js +0 -26
- package/dist/docs/PaginationDocs.d.ts +0 -4
- package/dist/docs/PaginationDocs.d.ts.map +0 -1
- package/dist/docs/PaginationDocs.js +0 -38
- package/dist/docs/RadioButtonGroupDocs.d.ts +0 -4
- package/dist/docs/RadioButtonGroupDocs.d.ts.map +0 -1
- package/dist/docs/RadioButtonGroupDocs.js +0 -46
- package/dist/docs/RoadMapDocs.d.ts +0 -4
- package/dist/docs/RoadMapDocs.d.ts.map +0 -1
- package/dist/docs/RoadMapDocs.js +0 -171
- package/dist/docs/SearchSelectInputDocs.d.ts +0 -4
- package/dist/docs/SearchSelectInputDocs.d.ts.map +0 -1
- package/dist/docs/SearchSelectInputDocs.js +0 -168
- package/dist/docs/SkeletonDocs.d.ts +0 -4
- package/dist/docs/SkeletonDocs.d.ts.map +0 -1
- package/dist/docs/SkeletonDocs.js +0 -7
- package/dist/docs/SnackbarDocs.d.ts +0 -4
- package/dist/docs/SnackbarDocs.d.ts.map +0 -1
- package/dist/docs/SnackbarDocs.js +0 -69
- package/dist/docs/TabsGroupDocs.d.ts +0 -4
- package/dist/docs/TabsGroupDocs.d.ts.map +0 -1
- package/dist/docs/TabsGroupDocs.js +0 -38
- package/dist/docs/ThemeSwitcherDocs.d.ts +0 -4
- package/dist/docs/ThemeSwitcherDocs.d.ts.map +0 -1
- package/dist/docs/ThemeSwitcherDocs.js +0 -11
- package/dist/docs/docMockServices/empresaService.d.ts +0 -38
- package/dist/docs/docMockServices/empresaService.d.ts.map +0 -1
- package/dist/docs/docMockServices/empresaService.js +0 -125
- package/dist/docs/docMockServices/index.d.ts +0 -9
- package/dist/docs/docMockServices/index.d.ts.map +0 -1
- package/dist/docs/docMockServices/index.js +0 -8
- package/dist/docs/docMockServices/initialData.d.ts +0 -6
- package/dist/docs/docMockServices/initialData.d.ts.map +0 -1
- package/dist/docs/docMockServices/initialData.js +0 -132
- package/dist/docs/docMockServices/interfaces.d.ts +0 -38
- package/dist/docs/docMockServices/interfaces.d.ts.map +0 -1
- package/dist/docs/docMockServices/interfaces.js +0 -1
- package/dist/docs/docMockServices/personaEmpresaService.d.ts +0 -43
- package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +0 -1
- package/dist/docs/docMockServices/personaEmpresaService.js +0 -151
- package/dist/docs/docMockServices/personaService.d.ts +0 -39
- package/dist/docs/docMockServices/personaService.d.ts.map +0 -1
- package/dist/docs/docMockServices/personaService.js +0 -190
- package/dist/helpers/currencyFormat.js +0 -3
- package/dist/helpers/getErrorMessage.js +0 -13
- package/dist/helpers/getInitialLetters.js +0 -5
- package/dist/helpers/getQueryString.js +0 -13
- package/dist/helpers/index.js +0 -9
- package/dist/helpers/mappers.js +0 -27
- package/dist/helpers/nameValueArrayToObject.js +0 -3
- package/dist/helpers/objectToQueryString.js +0 -3
- package/dist/helpers/queryStringToObject.js +0 -13
- package/dist/helpers/regularExpressions.js +0 -5
- package/dist/hooks/index.js +0 -6
- package/dist/hooks/useAsyncRequest.js +0 -53
- package/dist/hooks/useBreakpoint.js +0 -59
- package/dist/hooks/useElementScroll.js +0 -58
- package/dist/hooks/useEnum.js +0 -21
- package/dist/hooks/useGlobalThemeStyles.js +0 -40
- package/dist/hooks/useThemeOverride.js +0 -99
- package/dist/interfaces/index.js +0 -1
- package/dist/interfaces/name-value.interface.js +0 -1
- package/dist/interfaces/pagination.interface.js +0 -1
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -6
- package/dist/services/apiClient.js +0 -216
- package/dist/services/index.js +0 -1
- package/dist/styles.d.ts +0 -2
- package/dist/styles.d.ts.map +0 -1
- package/dist/styles.js +0 -3
- package/dist/templates/forms/ContactForm.js +0 -58
- package/dist/templates/forms/LoginForm.js +0 -36
- package/dist/templates/forms/RegistrationForm.js +0 -54
- package/dist/templates/layouts/DashboardLayout.js +0 -26
- package/dist/templates/layouts/SidebarLayout.js +0 -28
- 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";
|
package/dist/components/index.js
DELETED
|
@@ -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
|
-
};
|