flysoft-react-ui 0.5.2 → 1.0.0
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/dist/App.d.ts.map +1 -1
- package/dist/App.js +5 -6
- package/dist/components/form-controls/AutocompleteInput.d.ts.map +1 -1
- package/dist/components/form-controls/AutocompleteInput.js +177 -131
- package/dist/components/form-controls/Button.d.ts +3 -0
- package/dist/components/form-controls/Button.d.ts.map +1 -1
- package/dist/components/form-controls/Button.js +160 -19
- package/dist/components/form-controls/Checkbox.d.ts.map +1 -1
- package/dist/components/form-controls/Checkbox.js +3 -1
- package/dist/components/form-controls/DateInput.d.ts +5 -1
- package/dist/components/form-controls/DateInput.d.ts.map +1 -1
- package/dist/components/form-controls/DateInput.js +94 -27
- package/dist/components/form-controls/Input.d.ts.map +1 -1
- package/dist/components/form-controls/Input.js +2 -1
- package/dist/components/form-controls/LinkButton.d.ts +15 -0
- package/dist/components/form-controls/LinkButton.d.ts.map +1 -0
- package/dist/components/form-controls/LinkButton.js +248 -0
- package/dist/components/form-controls/SearchSelectInput-OLD.d.ts.map +1 -1
- package/dist/components/form-controls/SearchSelectInput-OLD.js +5 -4
- package/dist/components/form-controls/SearchSelectInput.d.ts.map +1 -1
- package/dist/components/form-controls/SearchSelectInput.js +3 -2
- package/dist/components/form-controls/index.d.ts +2 -0
- package/dist/components/form-controls/index.d.ts.map +1 -1
- package/dist/components/form-controls/index.js +1 -0
- package/dist/components/layout/Accordion.d.ts +13 -0
- package/dist/components/layout/Accordion.d.ts.map +1 -0
- package/dist/components/layout/Accordion.js +67 -0
- package/dist/components/layout/AppLayout.d.ts.map +1 -1
- package/dist/components/layout/AppLayout.js +7 -7
- package/dist/components/layout/Card.d.ts +8 -3
- package/dist/components/layout/Card.d.ts.map +1 -1
- package/dist/components/layout/Card.js +21 -22
- package/dist/components/layout/DataTable.js +1 -1
- package/dist/components/layout/DropdownMenu.d.ts.map +1 -0
- package/dist/components/{utils → layout}/DropdownMenu.js +12 -6
- package/dist/components/layout/DropdownPanel.d.ts +7 -0
- package/dist/components/layout/DropdownPanel.d.ts.map +1 -0
- package/dist/components/layout/DropdownPanel.js +137 -0
- package/dist/components/{utils → layout}/Filter.d.ts +5 -0
- package/dist/components/layout/Filter.d.ts.map +1 -0
- package/dist/components/{utils → layout}/Filter.js +18 -9
- package/dist/components/layout/Menu.d.ts +31 -0
- package/dist/components/layout/Menu.d.ts.map +1 -0
- package/dist/components/layout/Menu.js +21 -0
- package/dist/components/layout/index.d.ts +10 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/layout/index.js +5 -0
- package/dist/components/utils/Badge.d.ts.map +1 -1
- package/dist/components/utils/Badge.js +3 -2
- package/dist/components/utils/Dialog.d.ts +2 -2
- package/dist/components/utils/Dialog.d.ts.map +1 -1
- package/dist/components/utils/Dialog.js +4 -3
- package/dist/components/utils/FiltersDialog.d.ts +1 -1
- package/dist/components/utils/FiltersDialog.d.ts.map +1 -1
- package/dist/components/utils/FiltersDialog.js +2 -2
- package/dist/components/utils/Loader.js +1 -1
- package/dist/components/utils/RoadMap.d.ts.map +1 -1
- package/dist/components/utils/RoadMap.js +2 -1
- package/dist/components/utils/Snackbar.d.ts.map +1 -1
- package/dist/components/utils/Snackbar.js +2 -1
- package/dist/components/utils/iconUtils.d.ts +16 -0
- package/dist/components/utils/iconUtils.d.ts.map +1 -0
- package/dist/components/utils/iconUtils.js +40 -0
- package/dist/components/utils/index.d.ts +0 -2
- package/dist/components/utils/index.d.ts.map +1 -1
- package/dist/components/utils/index.js +0 -1
- package/dist/contexts/CrudContext.d.ts +62 -0
- package/dist/contexts/CrudContext.d.ts.map +1 -0
- package/dist/contexts/CrudContext.js +333 -0
- package/dist/contexts/index.d.ts +2 -2
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/contexts/index.js +2 -2
- package/dist/docs/AccordionDocs.d.ts +4 -0
- package/dist/docs/AccordionDocs.d.ts.map +1 -0
- package/dist/docs/AccordionDocs.js +21 -0
- package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +3 -5
- package/dist/docs/AutocompleteInputDocs.js +1 -1
- package/dist/docs/ButtonDocs.d.ts.map +1 -1
- package/dist/docs/ButtonDocs.js +1 -1
- package/dist/docs/CardDocs.d.ts.map +1 -1
- package/dist/docs/CardDocs.js +17 -8
- package/dist/docs/DataTableDocs.js +3 -3
- package/dist/docs/DialogDocs.d.ts.map +1 -1
- package/dist/docs/DialogDocs.js +1 -1
- package/dist/docs/DocAdmin.js +1 -1
- package/dist/docs/DocsMenu.d.ts.map +1 -1
- package/dist/docs/DocsMenu.js +3 -3
- package/dist/docs/DocsRouter.d.ts.map +1 -1
- package/dist/docs/DocsRouter.js +5 -1
- package/dist/docs/DropdownMenuDocs.js +1 -1
- package/dist/docs/DropdownPanelDocs.d.ts +4 -0
- package/dist/docs/DropdownPanelDocs.d.ts.map +1 -0
- package/dist/docs/DropdownPanelDocs.js +7 -0
- package/dist/docs/FilterDocs.d.ts.map +1 -1
- package/dist/docs/FilterDocs.js +19 -1
- package/dist/docs/LinkButtonDocs.d.ts +4 -0
- package/dist/docs/LinkButtonDocs.d.ts.map +1 -0
- package/dist/docs/LinkButtonDocs.js +7 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +0 -9
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +1 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +32 -16
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.js +34 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.js +66 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.js +7 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts +10 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.js +39 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +1 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +33 -27
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts +9 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.js +30 -0
- package/dist/docs/MenuDocs.d.ts +4 -0
- package/dist/docs/MenuDocs.d.ts.map +1 -0
- package/dist/docs/MenuDocs.js +26 -0
- package/dist/docs/SearchSelectInputDocs.js +1 -1
- package/dist/docs/docMockServices/empresaService.d.ts +5 -5
- package/dist/docs/docMockServices/empresaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/empresaService.js +20 -11
- package/dist/docs/docMockServices/interfaces.d.ts +12 -0
- package/dist/docs/docMockServices/interfaces.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaEmpresaService.d.ts +6 -6
- package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaEmpresaService.js +52 -14
- package/dist/docs/docMockServices/personaService.d.ts +2 -2
- package/dist/docs/docMockServices/personaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaService.js +17 -7
- package/dist/index.css +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/templates/forms/ContactForm.js +2 -2
- package/dist/templates/forms/LoginForm.js +1 -1
- package/dist/templates/forms/RegistrationForm.js +1 -1
- package/dist/templates/layouts/SidebarLayout.d.ts.map +1 -1
- package/dist/templates/layouts/SidebarLayout.js +3 -2
- package/dist/templates/patterns/FormPattern.d.ts.map +1 -1
- package/dist/templates/patterns/FormPattern.js +4 -3
- package/package.json +4 -3
- package/dist/components/utils/DropdownMenu.d.ts.map +0 -1
- package/dist/components/utils/Filter.d.ts.map +0 -1
- package/dist/contexts/ListCrudContext.d.ts +0 -29
- package/dist/contexts/ListCrudContext.d.ts.map +0 -1
- package/dist/contexts/ListCrudContext.js +0 -209
- /package/dist/components/{utils → layout}/DropdownMenu.d.ts +0 -0
package/dist/App.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.tsx"],"names":[],"mappings":"AAGA,OAAO,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.tsx"],"names":[],"mappings":"AAGA,OAAO,aAAa,CAAC;AAuDrB,iBAAS,GAAG,4CAsBX;AAED,eAAe,GAAG,CAAC"}
|
package/dist/App.js
CHANGED
|
@@ -8,20 +8,19 @@ import DocsRouter from "./docs/DocsRouter";
|
|
|
8
8
|
import { AuthDocs } from "./docs/AuthDocs.tsx/AuthDocs";
|
|
9
9
|
import packageJson from "../package.json";
|
|
10
10
|
function HomeContent() {
|
|
11
|
-
return (_jsxs(_Fragment, { children: [_jsx(Card, { title: "Empleados", className: "bg-gray-50", children: _jsx(Card, { className: "w-1/2", title: "FALCONE WALTER ALDO", subtitle: "3558-03 - Titular", footer: _jsx(Button, { children: "Ver" }), headerActions: ()
|
|
12
|
-
_jsx(Badge, { variant: "secondary", children: "OSOCNA" }),
|
|
13
|
-
_jsx(Badge, { variant: "secondary", children: "B\u00C1SICO" }),
|
|
14
|
-
], children: _jsxs(Collection, { direction: "row", gap: "1rem", wrap: true, children: [_jsx(DataField, { label: "Cuil", value: "20179902711" }), _jsx(DataField, { label: "Doc", value: "17990271" }), _jsx(DataField, { label: "F Nac", value: "23/06/1966" }), _jsx(DataField, { label: "F Alta", value: "01/03/2012" })] }) }) }), _jsx("div", { children: _jsx(AuthDocs, {}) })] }));
|
|
11
|
+
return (_jsxs(_Fragment, { children: [_jsx(Card, { title: "Empleados", className: "bg-gray-50", children: _jsx(Card, { className: "w-1/2", title: "FALCONE WALTER ALDO", subtitle: "3558-03 - Titular", footer: _jsx(Button, { children: "Ver" }), headerActions: _jsxs(_Fragment, { children: [_jsx(Badge, { variant: "secondary", children: "OSOCNA" }), _jsx(Badge, { variant: "secondary", children: "B\u00C1SICO" })] }), children: _jsxs(Collection, { direction: "row", gap: "1rem", wrap: true, children: [_jsx(DataField, { label: "Cuil", value: "20179902711" }), _jsx(DataField, { label: "Doc", value: "17990271" }), _jsx(DataField, { label: "F Nac", value: "23/06/1966" }), _jsx(DataField, { label: "F Alta", value: "01/03/2012" })] }) }) }), _jsx("div", { children: _jsx(AuthDocs, {}) })] }));
|
|
15
12
|
}
|
|
16
13
|
function LeftDrawerHeader() {
|
|
17
|
-
return (_jsx("div", { className: "h-[64px] flex flex-col justify-center px-4", children: _jsx("h2", { children: _jsx(Link, { to: "/", children: "Flysoft React UI" }) }) }));
|
|
14
|
+
return (_jsx("div", { className: "h-[64px] flex flex-col justify-center px-4 bg-gray-300", children: _jsx("h2", { children: _jsx(Link, { to: "/", children: "Flysoft React UI" }) }) }));
|
|
18
15
|
}
|
|
19
16
|
function LeftDrawerFooter() {
|
|
20
|
-
return (_jsx("div", { className: "px-4", children: _jsxs("span", { children: ["v ", packageJson.version] }) }));
|
|
17
|
+
return (_jsx("div", { className: "px-4 bg-gray-300", children: _jsxs("span", { children: ["v ", packageJson.version] }) }));
|
|
21
18
|
}
|
|
22
19
|
function App() {
|
|
23
20
|
return (_jsx(AppLayoutProvider, { initialTheme: "light", forceInitialTheme: false, initialNavbar: {
|
|
21
|
+
navBarLeftNode: _jsx(_Fragment, {}),
|
|
24
22
|
fullWidthNavbar: false,
|
|
23
|
+
className: "bg-gray-300 pl-0 lg:pl-8",
|
|
25
24
|
}, initialLeftDrawer: {
|
|
26
25
|
headerNode: _jsx(LeftDrawerHeader, {}),
|
|
27
26
|
contentNode: _jsx(DocsMenu, {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteInput.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/AutocompleteInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"AutocompleteInput.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/AutocompleteInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,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,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EACL,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,GAC1C,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC;IAC9B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/C,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;IAC5C;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAguBD,eAAO,MAAM,iBAAiB,EAA6B,CACzD,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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
|
+
import { useFormContext } from "react-hook-form";
|
|
4
5
|
import { Input } from "./Input";
|
|
6
|
+
import { normalizeIconClass } from "../utils/iconUtils";
|
|
5
7
|
const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onSelectOption, noResultsText = "Sin resultados", className = "", getOptionLabel, getOptionValue, getOptionDescription, renderOption, readOnly = false, ...inputProps }, ref) => {
|
|
6
8
|
const [internalValue, setInternalValue] = React.useState(value || "");
|
|
7
9
|
const [displayValue, setDisplayValue] = React.useState("");
|
|
@@ -11,6 +13,7 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
11
13
|
const containerRef = React.useRef(null);
|
|
12
14
|
const dropdownRef = React.useRef(null);
|
|
13
15
|
const inputRef = React.useRef(null);
|
|
16
|
+
const hiddenInputRef = React.useRef(null);
|
|
14
17
|
const justClearedRef = React.useRef(false);
|
|
15
18
|
// Detectar si estamos en modo register: si viene 'name' de register, estamos en modo register
|
|
16
19
|
// register siempre pasa 'name', 'onChange', 'onBlur', y 'ref'
|
|
@@ -18,6 +21,16 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
18
21
|
// Si viene 'name' en inputProps, es porque viene de register
|
|
19
22
|
return "name" in inputProps && inputProps.name !== undefined;
|
|
20
23
|
}, [inputProps]);
|
|
24
|
+
const fieldName = isRegisterMode && "name" in inputProps
|
|
25
|
+
? inputProps.name
|
|
26
|
+
: undefined;
|
|
27
|
+
// Obtener setValue del contexto del formulario
|
|
28
|
+
// Para usar con register, el formulario debe estar dentro de FormProvider
|
|
29
|
+
// useFormContext debe llamarse incondicionalmente (requisito de React Hooks)
|
|
30
|
+
// Si no hay FormProvider y se usa en modo register, useFormContext lanzará un error
|
|
31
|
+
// Para usar sin FormProvider, usar Controller en lugar de register
|
|
32
|
+
const formContext = useFormContext();
|
|
33
|
+
const setValue = formContext?.setValue;
|
|
21
34
|
const inputValue = isRegisterMode
|
|
22
35
|
? displayValue
|
|
23
36
|
: value !== undefined
|
|
@@ -53,23 +66,27 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
53
66
|
}, [inputValue, options, labelGetter, valueGetter]);
|
|
54
67
|
// Función helper para sincronizar displayValue con el valor del formulario
|
|
55
68
|
const syncDisplayValue = React.useCallback(() => {
|
|
56
|
-
if (isRegisterMode
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
if (isRegisterMode) {
|
|
70
|
+
// En modo register, usamos el hiddenInputRef si existe, sino el inputRef (legacy/fallback)
|
|
71
|
+
const targetInput = hiddenInputRef.current || inputRef.current;
|
|
72
|
+
if (targetInput) {
|
|
73
|
+
const formValue = targetInput.value;
|
|
74
|
+
// Si el valor del formulario coincide con algún getOptionValue, mostrar su label
|
|
75
|
+
const matchingOption = options.find((option) => String(valueGetter(option)) === String(formValue));
|
|
76
|
+
if (matchingOption) {
|
|
77
|
+
const label = labelGetter(matchingOption);
|
|
78
|
+
setDisplayValue(label);
|
|
79
|
+
return true; // Indica que se encontró y sincronizó un valor
|
|
80
|
+
}
|
|
81
|
+
else if (formValue) {
|
|
82
|
+
// Si hay un valor pero no coincide, mostrarlo tal cual (o buscar por label si fuera el caso)
|
|
83
|
+
setDisplayValue(formValue);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
setDisplayValue("");
|
|
88
|
+
return false; // No hay valor aún
|
|
89
|
+
}
|
|
73
90
|
}
|
|
74
91
|
}
|
|
75
92
|
return false;
|
|
@@ -82,8 +99,9 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
82
99
|
const maxAttempts = 50; // Intentar durante ~5 segundos (50 * 100ms)
|
|
83
100
|
// Función que intenta sincronizar y retorna true si encontró un valor
|
|
84
101
|
const trySync = () => {
|
|
85
|
-
|
|
86
|
-
|
|
102
|
+
const targetInput = hiddenInputRef.current || inputRef.current;
|
|
103
|
+
if (targetInput) {
|
|
104
|
+
const formValue = targetInput.value;
|
|
87
105
|
if (formValue) {
|
|
88
106
|
// Hay un valor, intentar sincronizar
|
|
89
107
|
const matchingOption = options.find((option) => String(valueGetter(option)) === String(formValue));
|
|
@@ -125,30 +143,36 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
125
143
|
};
|
|
126
144
|
}
|
|
127
145
|
}, [isRegisterMode, options, valueGetter, labelGetter]);
|
|
128
|
-
// También escuchar cambios en el input
|
|
146
|
+
// También escuchar cambios en el input (hidden o visible) para sincronizar cuando cambie
|
|
129
147
|
React.useEffect(() => {
|
|
130
|
-
if (isRegisterMode
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
if (isRegisterMode) {
|
|
149
|
+
// Observamos el hiddenInput si estamos en register mode y existe, o el input normal
|
|
150
|
+
const targetElement = hiddenInputRef.current || inputRef.current;
|
|
151
|
+
if (targetElement) {
|
|
152
|
+
// Función para sincronizar cuando el input cambia
|
|
153
|
+
const handleInputSync = () => {
|
|
154
|
+
// Solo sincronizar si es el hidden input o si no tenemos hidden input
|
|
155
|
+
if (targetElement === hiddenInputRef.current) {
|
|
156
|
+
syncDisplayValue();
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
// Escuchar eventos de input y change (aunque en hidden input no suelen dispararse eventos de usuario)
|
|
160
|
+
targetElement.addEventListener("input", handleInputSync);
|
|
161
|
+
targetElement.addEventListener("change", handleInputSync);
|
|
162
|
+
// También usar MutationObserver para detectar cambios en el atributo value (más fiable para hidden inputs cambiados por JS)
|
|
163
|
+
const observer = new MutationObserver(() => {
|
|
164
|
+
syncDisplayValue();
|
|
165
|
+
});
|
|
166
|
+
observer.observe(targetElement, {
|
|
167
|
+
attributes: true,
|
|
168
|
+
attributeFilter: ["value"],
|
|
169
|
+
});
|
|
170
|
+
return () => {
|
|
171
|
+
targetElement.removeEventListener("input", handleInputSync);
|
|
172
|
+
targetElement.removeEventListener("change", handleInputSync);
|
|
173
|
+
observer.disconnect();
|
|
174
|
+
};
|
|
175
|
+
}
|
|
152
176
|
}
|
|
153
177
|
}, [isRegisterMode, syncDisplayValue]);
|
|
154
178
|
const handleChange = (event) => {
|
|
@@ -178,53 +202,56 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
178
202
|
const selectedValue = valueGetter(option);
|
|
179
203
|
const valueString = String(selectedValue ?? "");
|
|
180
204
|
if (isRegisterMode) {
|
|
181
|
-
// En modo register
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
nativeInputValueSetter.call(nativeInput, valueString);
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
// Fallback si el setter no está disponible
|
|
194
|
-
nativeInput.value = valueString;
|
|
205
|
+
// En modo register, setear el valor usando setValue o actualizando el input nativo (hidden)
|
|
206
|
+
if (setValue && fieldName) {
|
|
207
|
+
setValue(fieldName, selectedValue, {
|
|
208
|
+
shouldValidate: true,
|
|
209
|
+
shouldDirty: true,
|
|
210
|
+
});
|
|
211
|
+
// Actualizar el input hidden con el ID
|
|
212
|
+
if (hiddenInputRef.current) {
|
|
213
|
+
hiddenInputRef.current.value = valueString;
|
|
195
214
|
}
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
215
|
+
// Actualizar displayValue con el label para mostrarlo visualmente en el input visible
|
|
216
|
+
setDisplayValue(label);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// Fallback si no hay setValue (raro en registerMode) o para inputs manuales
|
|
220
|
+
const targetInput = hiddenInputRef.current || inputRef.current;
|
|
221
|
+
if (targetInput) {
|
|
222
|
+
const nativeInput = targetInput;
|
|
223
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
224
|
+
if (nativeInputValueSetter) {
|
|
225
|
+
nativeInputValueSetter.call(nativeInput, valueString);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
nativeInput.value = valueString;
|
|
229
|
+
}
|
|
230
|
+
// Disparar eventos en el input que tiene el ref de register
|
|
231
|
+
if (onChange) {
|
|
232
|
+
const changeEvent = {
|
|
233
|
+
target: nativeInput,
|
|
234
|
+
currentTarget: nativeInput,
|
|
235
|
+
}; // Cast agresivo necesario
|
|
236
|
+
onChange(changeEvent);
|
|
237
|
+
}
|
|
238
|
+
const inputEvent = new Event("input", {
|
|
239
|
+
bubbles: true,
|
|
240
|
+
cancelable: true,
|
|
241
|
+
});
|
|
242
|
+
nativeInput.dispatchEvent(inputEvent);
|
|
243
|
+
const changeEventNative = new Event("change", {
|
|
244
|
+
bubbles: true,
|
|
245
|
+
cancelable: true,
|
|
246
|
+
});
|
|
247
|
+
nativeInput.dispatchEvent(changeEventNative);
|
|
206
248
|
}
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
const inputEvent = new Event("input", {
|
|
210
|
-
bubbles: true,
|
|
211
|
-
cancelable: true,
|
|
212
|
-
});
|
|
213
|
-
nativeInput.dispatchEvent(inputEvent);
|
|
214
|
-
const changeEventNative = new Event("change", {
|
|
215
|
-
bubbles: true,
|
|
216
|
-
cancelable: true,
|
|
217
|
-
});
|
|
218
|
-
nativeInput.dispatchEvent(changeEventNative);
|
|
249
|
+
// Y actualizamos visualmente
|
|
250
|
+
setDisplayValue(label);
|
|
219
251
|
}
|
|
220
|
-
// Actualizar el displayValue para mostrar el label
|
|
221
|
-
setDisplayValue(label);
|
|
222
252
|
}
|
|
223
253
|
else {
|
|
224
254
|
// Modo API personalizada - comportamiento original
|
|
225
|
-
if (value === undefined) {
|
|
226
|
-
setInternalValue(label);
|
|
227
|
-
}
|
|
228
255
|
// Pasar el valor devuelto por getOptionValue, no el label
|
|
229
256
|
if (onChange) {
|
|
230
257
|
onChange(valueString);
|
|
@@ -346,11 +373,15 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
346
373
|
// Detectar si hay un valor seleccionado
|
|
347
374
|
// Un valor está seleccionado si el value coincide con el getOptionValue de alguna opción
|
|
348
375
|
const hasSelectedValue = React.useMemo(() => {
|
|
349
|
-
if (isRegisterMode
|
|
350
|
-
const
|
|
351
|
-
if (
|
|
352
|
-
|
|
353
|
-
|
|
376
|
+
if (isRegisterMode) {
|
|
377
|
+
const targetInput = hiddenInputRef.current || inputRef.current;
|
|
378
|
+
if (targetInput) {
|
|
379
|
+
const formValue = targetInput.value;
|
|
380
|
+
if (!formValue)
|
|
381
|
+
return false;
|
|
382
|
+
return options.some((option) => String(valueGetter(option)) === String(formValue));
|
|
383
|
+
}
|
|
384
|
+
return false;
|
|
354
385
|
}
|
|
355
386
|
if (value === undefined || value === null || value === "")
|
|
356
387
|
return false;
|
|
@@ -366,9 +397,10 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
366
397
|
// Marcar que acabamos de limpiar para prevenir que onFocus abra el diálogo
|
|
367
398
|
justClearedRef.current = true;
|
|
368
399
|
if (isRegisterMode) {
|
|
369
|
-
// En modo register, limpiar el input nativo y disparar eventos
|
|
370
|
-
|
|
371
|
-
|
|
400
|
+
// En modo register, limpiar el input nativo (hidden) y disparar eventos
|
|
401
|
+
const targetInput = hiddenInputRef.current || inputRef.current;
|
|
402
|
+
if (targetInput) {
|
|
403
|
+
const nativeInput = targetInput;
|
|
372
404
|
const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
373
405
|
setter?.call(nativeInput, "");
|
|
374
406
|
// Disparar eventos para que react-hook-form lo capture
|
|
@@ -376,17 +408,17 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
376
408
|
nativeInput.dispatchEvent(inputEvent);
|
|
377
409
|
const changeEvent = new Event("change", { bubbles: true });
|
|
378
410
|
nativeInput.dispatchEvent(changeEvent);
|
|
411
|
+
// Llamar al onChange de register
|
|
412
|
+
if (onChange) {
|
|
413
|
+
const changeEventReact = {
|
|
414
|
+
target: nativeInput,
|
|
415
|
+
currentTarget: nativeInput,
|
|
416
|
+
};
|
|
417
|
+
onChange(changeEventReact);
|
|
418
|
+
}
|
|
379
419
|
}
|
|
380
420
|
// Limpiar el displayValue
|
|
381
421
|
setDisplayValue("");
|
|
382
|
-
// Llamar al onChange de register
|
|
383
|
-
if (onChange && inputRef.current) {
|
|
384
|
-
const changeEvent = {
|
|
385
|
-
target: inputRef.current,
|
|
386
|
-
currentTarget: inputRef.current,
|
|
387
|
-
};
|
|
388
|
-
onChange(changeEvent);
|
|
389
|
-
}
|
|
390
422
|
}
|
|
391
423
|
else {
|
|
392
424
|
// Modo API personalizada
|
|
@@ -420,39 +452,53 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
420
452
|
: hasSelectedValue
|
|
421
453
|
? handleClear
|
|
422
454
|
: inputProps.onIconClick;
|
|
423
|
-
//
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
455
|
+
// Refs separados: uno para el visible y otro para el hidden (registrado)
|
|
456
|
+
const setHiddenRef = React.useCallback((node) => {
|
|
457
|
+
hiddenInputRef.current = node;
|
|
458
|
+
// Solo pasar el ref externo al hidden input en modo register
|
|
459
|
+
if (isRegisterMode) {
|
|
460
|
+
if (typeof ref === "function") {
|
|
461
|
+
ref(node);
|
|
462
|
+
}
|
|
463
|
+
else if (ref) {
|
|
464
|
+
ref.current = node;
|
|
465
|
+
}
|
|
466
|
+
// Sincronización inicial cuando el ref se monta
|
|
467
|
+
if (node) {
|
|
468
|
+
[0, 10, 50, 100, 200, 500].forEach((delay) => {
|
|
469
|
+
setTimeout(() => {
|
|
470
|
+
if (node && hiddenInputRef.current === node) {
|
|
471
|
+
const formValue = node.value;
|
|
472
|
+
if (formValue) {
|
|
473
|
+
const matchingOption = options.find((option) => String(valueGetter(option)) === String(formValue));
|
|
474
|
+
if (matchingOption) {
|
|
475
|
+
setDisplayValue(labelGetter(matchingOption));
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
setDisplayValue(formValue);
|
|
479
|
+
}
|
|
448
480
|
}
|
|
449
481
|
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
482
|
+
}, delay);
|
|
483
|
+
});
|
|
484
|
+
}
|
|
453
485
|
}
|
|
454
486
|
}, [ref, isRegisterMode, options, valueGetter, labelGetter]);
|
|
455
|
-
|
|
487
|
+
const setVisibleRef = React.useCallback((node) => {
|
|
488
|
+
inputRef.current = node;
|
|
489
|
+
// En modo NO register, pasamos el ref al input visible
|
|
490
|
+
if (!isRegisterMode) {
|
|
491
|
+
if (typeof ref === "function") {
|
|
492
|
+
ref(node);
|
|
493
|
+
}
|
|
494
|
+
else if (ref) {
|
|
495
|
+
ref.current = node;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}, [ref, isRegisterMode]);
|
|
499
|
+
// Separar propiedades para input visible y hidden
|
|
500
|
+
const { name: nameProp, ...visibleInputProps } = inputProps;
|
|
501
|
+
return (_jsxs("div", { ref: containerRef, className: "relative w-full", children: [isRegisterMode && (_jsx("input", { type: "hidden", name: nameProp, ref: setHiddenRef, defaultValue: value })), _jsx(Input, { ...visibleInputProps, name: isRegisterMode ? undefined : nameProp, ref: setVisibleRef, value: inputValue, onChange: handleChange, onFocus: () => {
|
|
456
502
|
if (!readOnly && !justClearedRef.current) {
|
|
457
503
|
setIsOpen(true);
|
|
458
504
|
}
|
|
@@ -467,7 +513,7 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
467
513
|
dropdownPosition &&
|
|
468
514
|
isMounted &&
|
|
469
515
|
bodyElement &&
|
|
470
|
-
createPortal(_jsx("div", { ref: dropdownRef, className: "fixed z-[2001] min-w-full w-max rounded-md border border-[var(--color-border-default)] \
|
|
516
|
+
createPortal(_jsx("div", { ref: dropdownRef, className: "fixed z-[2001] min-w-full w-max rounded-md border border-[var(--color-border-default)] \n bg-[var(--color-bg-default)] shadow-[var(--shadow-lg)] max-h-60 overflow-auto", style: {
|
|
471
517
|
top: `${dropdownPosition.top}px`,
|
|
472
518
|
left: `${dropdownPosition.left}px`,
|
|
473
519
|
minWidth: `${dropdownPosition.width}px`,
|
|
@@ -475,13 +521,13 @@ const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onS
|
|
|
475
521
|
const label = labelGetter(option);
|
|
476
522
|
const description = descriptionGetter(option);
|
|
477
523
|
const anyOption = option;
|
|
478
|
-
return (_jsx("li", { className: `px-3 py-2 cursor-pointer flex items-start gap-2 text-sm
|
|
524
|
+
return (_jsx("li", { className: `px-3 py-2 cursor-pointer flex items-start gap-2 text-sm
|
|
479
525
|
${index === highlightedIndex
|
|
480
526
|
? "bg-[var(--color-primary-soft)] text-[var(--color-primary)]"
|
|
481
527
|
: "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (event) => {
|
|
482
528
|
event.preventDefault();
|
|
483
529
|
handleSelect(option);
|
|
484
|
-
}, onMouseEnter: () => setHighlightedIndex(index), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className:
|
|
530
|
+
}, onMouseEnter: () => setHighlightedIndex(index), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className: `${normalizeIconClass(anyOption.icon)} mt-0.5 text-[var(--color-text-muted)] flex-shrink-0` })), _jsxs("div", { className: "flex flex-col min-w-0", children: [_jsx("span", { className: "font-[var(--font-default)] whitespace-nowrap", children: label }), description !== undefined &&
|
|
485
531
|
description !== null && (_jsx("span", { className: "text-xs text-[var(--color-text-secondary)] break-words", children: description }))] })] })) }, String(valueGetter(option) ?? label ?? index)));
|
|
486
532
|
}) })) : (_jsx("div", { className: "px-3 py-2 text-sm text-[var(--color-text-secondary)]", children: noResultsText })) }), bodyElement));
|
|
487
533
|
})()] }));
|
|
@@ -2,6 +2,9 @@ import React from "react";
|
|
|
2
2
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
3
3
|
variant?: "primary" | "outline" | "ghost";
|
|
4
4
|
size?: "sm" | "md" | "lg";
|
|
5
|
+
color?: "primary" | "secondary" | "success" | "warning" | "danger" | "info";
|
|
6
|
+
bg?: string;
|
|
7
|
+
textColor?: string;
|
|
5
8
|
icon?: string;
|
|
6
9
|
iconPosition?: "left" | "right";
|
|
7
10
|
loading?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkC1B,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACrD,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAC1C,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC5E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AASD,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAwPxC,CAAC"}
|