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.
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +20 -4
- package/dist/components/form-controls/AutocompleteInput.d.ts +11 -3
- package/dist/components/form-controls/AutocompleteInput.d.ts.map +1 -1
- package/dist/components/form-controls/AutocompleteInput.js +410 -31
- package/dist/components/form-controls/Button.js +1 -1
- package/dist/components/form-controls/Checkbox.d.ts +14 -0
- package/dist/components/form-controls/Checkbox.d.ts.map +1 -0
- package/dist/components/form-controls/Checkbox.js +77 -0
- package/dist/components/form-controls/DateInput.d.ts +20 -4
- package/dist/components/form-controls/DateInput.d.ts.map +1 -1
- package/dist/components/form-controls/DateInput.js +425 -70
- package/dist/components/form-controls/DatePicker.d.ts +4 -3
- package/dist/components/form-controls/DatePicker.d.ts.map +1 -1
- package/dist/components/form-controls/DatePicker.js +26 -30
- package/dist/components/form-controls/Input.d.ts +10 -1
- package/dist/components/form-controls/Input.d.ts.map +1 -1
- package/dist/components/form-controls/Input.js +16 -10
- package/dist/components/form-controls/Pagination.d.ts +1 -0
- package/dist/components/form-controls/Pagination.d.ts.map +1 -1
- package/dist/components/form-controls/Pagination.js +3 -40
- package/dist/components/form-controls/RadioButtonGroup.d.ts +62 -0
- package/dist/components/form-controls/RadioButtonGroup.d.ts.map +1 -0
- package/dist/components/form-controls/RadioButtonGroup.js +220 -0
- package/dist/components/form-controls/SearchSelectInput-OLD.d.ts +68 -0
- package/dist/components/form-controls/SearchSelectInput-OLD.d.ts.map +1 -0
- package/dist/components/form-controls/SearchSelectInput-OLD.js +962 -0
- package/dist/components/form-controls/SearchSelectInput.d.ts +70 -0
- package/dist/components/form-controls/SearchSelectInput.d.ts.map +1 -0
- package/dist/components/form-controls/SearchSelectInput.js +335 -0
- package/dist/components/form-controls/index.d.ts +7 -1
- package/dist/components/form-controls/index.d.ts.map +1 -1
- package/dist/components/form-controls/index.js +3 -0
- package/dist/components/layout/AppLayout.d.ts +3 -2
- package/dist/components/layout/AppLayout.d.ts.map +1 -1
- package/dist/components/layout/AppLayout.js +104 -31
- package/dist/components/layout/Card.d.ts +4 -1
- package/dist/components/layout/Card.d.ts.map +1 -1
- package/dist/components/layout/Card.js +30 -1
- package/dist/components/layout/Collection.js +1 -1
- package/dist/components/layout/DataTable.d.ts +29 -0
- package/dist/components/layout/DataTable.d.ts.map +1 -0
- package/dist/components/layout/DataTable.js +165 -0
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/layout/index.js +1 -0
- package/dist/components/utils/Avatar.d.ts +49 -0
- package/dist/components/utils/Avatar.d.ts.map +1 -0
- package/dist/components/utils/Avatar.js +93 -0
- package/dist/components/utils/Badge.d.ts +3 -0
- package/dist/components/utils/Badge.d.ts.map +1 -1
- package/dist/components/utils/Badge.js +130 -26
- package/dist/components/utils/Dialog.d.ts.map +1 -1
- package/dist/components/utils/Dialog.js +5 -1
- package/dist/components/utils/DropdownMenu.d.ts +25 -0
- package/dist/components/utils/DropdownMenu.d.ts.map +1 -0
- package/dist/components/utils/DropdownMenu.js +145 -0
- package/dist/components/utils/Filter.d.ts +57 -0
- package/dist/components/utils/Filter.d.ts.map +1 -0
- package/dist/components/utils/Filter.js +580 -0
- package/dist/components/utils/FiltersDialog.d.ts +21 -0
- package/dist/components/utils/FiltersDialog.d.ts.map +1 -0
- package/dist/components/utils/FiltersDialog.js +104 -0
- package/dist/components/utils/Loader.js +1 -1
- package/dist/components/utils/RoadMap.d.ts +59 -0
- package/dist/components/utils/RoadMap.d.ts.map +1 -0
- package/dist/components/utils/RoadMap.js +138 -0
- package/dist/components/utils/Snackbar.d.ts +13 -0
- package/dist/components/utils/Snackbar.d.ts.map +1 -0
- package/dist/components/utils/Snackbar.js +121 -0
- package/dist/components/utils/SnackbarContainer.d.ts +7 -0
- package/dist/components/utils/SnackbarContainer.d.ts.map +1 -0
- package/dist/components/utils/SnackbarContainer.js +25 -0
- package/dist/components/utils/index.d.ts +12 -0
- package/dist/components/utils/index.d.ts.map +1 -1
- package/dist/components/utils/index.js +6 -0
- package/dist/contexts/AppLayoutContext.d.ts +40 -0
- package/dist/contexts/AppLayoutContext.d.ts.map +1 -0
- package/dist/contexts/AppLayoutContext.js +98 -0
- package/dist/contexts/ListCrudContext.d.ts +29 -0
- package/dist/contexts/ListCrudContext.d.ts.map +1 -0
- package/dist/contexts/ListCrudContext.js +209 -0
- package/dist/contexts/SnackbarContext.d.ts +26 -0
- package/dist/contexts/SnackbarContext.d.ts.map +1 -0
- package/dist/contexts/SnackbarContext.js +34 -0
- package/dist/contexts/index.d.ts +6 -0
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/contexts/index.js +6 -0
- package/dist/contexts/presets.js +6 -6
- package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +3 -1
- package/dist/docs/AvatarDocs.d.ts +4 -0
- package/dist/docs/AvatarDocs.d.ts.map +1 -0
- package/dist/docs/AvatarDocs.js +7 -0
- package/dist/docs/BadgeDocs.d.ts.map +1 -1
- package/dist/docs/BadgeDocs.js +4 -2
- package/dist/docs/CardDocs.d.ts.map +1 -1
- package/dist/docs/CardDocs.js +7 -1
- package/dist/docs/CheckboxDocs.d.ts +4 -0
- package/dist/docs/CheckboxDocs.d.ts.map +1 -0
- package/dist/docs/CheckboxDocs.js +7 -0
- package/dist/docs/DataTableDocs.d.ts +4 -0
- package/dist/docs/DataTableDocs.d.ts.map +1 -0
- package/dist/docs/DataTableDocs.js +244 -0
- package/dist/docs/DateInputDocs.d.ts +1 -0
- package/dist/docs/DateInputDocs.d.ts.map +1 -1
- package/dist/docs/DateInputDocs.js +7 -9
- package/dist/docs/DatePickerDocs.d.ts +1 -0
- package/dist/docs/DatePickerDocs.d.ts.map +1 -1
- package/dist/docs/DatePickerDocs.js +6 -8
- package/dist/docs/DocAdmin.d.ts +4 -0
- package/dist/docs/DocAdmin.d.ts.map +1 -0
- package/dist/docs/DocAdmin.js +68 -0
- package/dist/docs/DocsMenu.d.ts.map +1 -1
- package/dist/docs/DocsMenu.js +1 -1
- package/dist/docs/DocsRouter.d.ts.map +1 -1
- package/dist/docs/DocsRouter.js +13 -1
- package/dist/docs/DropdownMenuDocs.d.ts +4 -0
- package/dist/docs/DropdownMenuDocs.d.ts.map +1 -0
- package/dist/docs/DropdownMenuDocs.js +66 -0
- package/dist/docs/ExampleFormDocs.d.ts +4 -0
- package/dist/docs/ExampleFormDocs.d.ts.map +1 -0
- package/dist/docs/ExampleFormDocs.js +148 -0
- package/dist/docs/FilterDocs.d.ts +4 -0
- package/dist/docs/FilterDocs.d.ts.map +1 -0
- package/dist/docs/FilterDocs.js +112 -0
- package/dist/docs/InputDocs.d.ts.map +1 -1
- package/dist/docs/InputDocs.js +11 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +11 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +25 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +51 -0
- package/dist/docs/PaginationDocs.js +6 -6
- package/dist/docs/RadioButtonGroupDocs.d.ts +4 -0
- package/dist/docs/RadioButtonGroupDocs.d.ts.map +1 -0
- package/dist/docs/RadioButtonGroupDocs.js +46 -0
- package/dist/docs/RoadMapDocs.d.ts +4 -0
- package/dist/docs/RoadMapDocs.d.ts.map +1 -0
- package/dist/docs/RoadMapDocs.js +171 -0
- package/dist/docs/SearchSelectInputDocs.d.ts +4 -0
- package/dist/docs/SearchSelectInputDocs.d.ts.map +1 -0
- package/dist/docs/SearchSelectInputDocs.js +168 -0
- package/dist/docs/SnackbarDocs.d.ts +4 -0
- package/dist/docs/SnackbarDocs.d.ts.map +1 -0
- package/dist/docs/SnackbarDocs.js +50 -0
- package/dist/docs/TabsGroupDocs.d.ts.map +1 -1
- package/dist/docs/TabsGroupDocs.js +12 -1
- package/dist/docs/docMockServices/empresaService.d.ts +38 -0
- package/dist/docs/docMockServices/empresaService.d.ts.map +1 -0
- package/dist/docs/docMockServices/empresaService.js +116 -0
- package/dist/docs/docMockServices/index.d.ts +9 -0
- package/dist/docs/docMockServices/index.d.ts.map +1 -0
- package/dist/docs/docMockServices/index.js +8 -0
- package/dist/docs/docMockServices/initialData.d.ts +6 -0
- package/dist/docs/docMockServices/initialData.d.ts.map +1 -0
- package/dist/docs/docMockServices/initialData.js +132 -0
- package/dist/docs/docMockServices/interfaces.d.ts +26 -0
- package/dist/docs/docMockServices/interfaces.d.ts.map +1 -0
- package/dist/docs/docMockServices/interfaces.js +1 -0
- package/dist/docs/docMockServices/personaEmpresaService.d.ts +43 -0
- package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +1 -0
- package/dist/docs/docMockServices/personaEmpresaService.js +113 -0
- package/dist/docs/docMockServices/personaService.d.ts +39 -0
- package/dist/docs/docMockServices/personaService.d.ts.map +1 -0
- package/dist/docs/docMockServices/personaService.js +180 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useAsyncRequest.d.ts +17 -0
- package/dist/hooks/useAsyncRequest.d.ts.map +1 -0
- package/dist/hooks/useAsyncRequest.js +70 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/App.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.tsx"],"names":[],"mappings":"AAGA,OAAO,aAAa,CAAC;AA2DrB,iBAAS,GAAG,4CAoBX;AAED,eAAe,GAAG,CAAC"}
|
package/dist/App.js
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { Badge, Button, Card, Collection, DataField } from "./components";
|
|
3
3
|
import { Routes, Route, Link } from "react-router-dom";
|
|
4
|
-
import {
|
|
4
|
+
import { AppLayoutProvider } from "./index";
|
|
5
5
|
import "./index.css";
|
|
6
6
|
import { DocsMenu } from "./docs/DocsMenu";
|
|
7
7
|
import DocsRouter from "./docs/DocsRouter";
|
|
8
8
|
import { AuthDocs } from "./docs/AuthDocs.tsx/AuthDocs";
|
|
9
|
+
import packageJson from "../package.json";
|
|
9
10
|
function HomeContent() {
|
|
10
|
-
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:
|
|
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, {}) })] }));
|
|
15
|
+
}
|
|
16
|
+
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" }) }) }));
|
|
18
|
+
}
|
|
19
|
+
function LeftDrawerFooter() {
|
|
20
|
+
return (_jsx("div", { className: "px-4", children: _jsxs("span", { children: ["v ", packageJson.version] }) }));
|
|
11
21
|
}
|
|
12
22
|
function App() {
|
|
13
|
-
return (_jsx(
|
|
23
|
+
return (_jsx(AppLayoutProvider, { initialTheme: "light", forceInitialTheme: false, initialNavbar: {
|
|
24
|
+
fullWidthNavbar: false,
|
|
25
|
+
}, initialLeftDrawer: {
|
|
26
|
+
headerNode: _jsx(LeftDrawerHeader, {}),
|
|
27
|
+
contentNode: _jsx(DocsMenu, {}),
|
|
28
|
+
footerNode: _jsx(LeftDrawerFooter, {}),
|
|
29
|
+
}, children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(HomeContent, {}) }), _jsx(Route, { path: "/docs/*", element: _jsx(DocsRouter, {}) })] }) }));
|
|
14
30
|
}
|
|
15
31
|
export default App;
|
|
@@ -6,13 +6,14 @@ export interface AutocompleteOption {
|
|
|
6
6
|
description?: string | number;
|
|
7
7
|
icon?: string;
|
|
8
8
|
}
|
|
9
|
-
export interface AutocompleteInputProps<T = AutocompleteOption, K = string> extends Omit<InputProps, "onChange" | "value"> {
|
|
9
|
+
export interface AutocompleteInputProps<T = AutocompleteOption, K = string> extends Omit<InputProps, "onChange" | "value" | "ref"> {
|
|
10
10
|
options: T[];
|
|
11
11
|
value?: string;
|
|
12
12
|
/**
|
|
13
13
|
* Valor de texto del input (controlado)
|
|
14
|
+
* Puede ser un ChangeEventHandler (de register) o una función que recibe string (API personalizada)
|
|
14
15
|
*/
|
|
15
|
-
onChange?: (value: string) => void;
|
|
16
|
+
onChange?: React.ChangeEventHandler<HTMLInputElement> | ((value: string) => void);
|
|
16
17
|
/**
|
|
17
18
|
* Callback al seleccionar una opción. Devuelve el item completo (T) y el valor mapeado (K)
|
|
18
19
|
*/
|
|
@@ -34,6 +35,13 @@ export interface AutocompleteInputProps<T = AutocompleteOption, K = string> exte
|
|
|
34
35
|
* Renderizado personalizado de cada opción. Si se define, se ignora el render por defecto.
|
|
35
36
|
*/
|
|
36
37
|
renderOption?: (item: T) => React.ReactNode;
|
|
38
|
+
/**
|
|
39
|
+
* Si es true, el input será de solo lectura. No se podrá modificar ni desplegar las opciones.
|
|
40
|
+
* Por defecto es false.
|
|
41
|
+
*/
|
|
42
|
+
readOnly?: boolean;
|
|
37
43
|
}
|
|
38
|
-
export declare const AutocompleteInput: <T = AutocompleteOption, K = string>(
|
|
44
|
+
export declare const AutocompleteInput: <T = AutocompleteOption, K = string>(props: AutocompleteInputProps<T, K> & {
|
|
45
|
+
ref?: React.ForwardedRef<HTMLInputElement>;
|
|
46
|
+
}) => React.ReactElement;
|
|
39
47
|
//# sourceMappingURL=AutocompleteInput.d.ts.map
|
|
@@ -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;AAG1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,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;AAkqBD,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,12 +1,28 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
3
4
|
import { Input } from "./Input";
|
|
4
|
-
|
|
5
|
+
const AutocompleteInputInner = React.forwardRef(({ options, value, onChange, onSelectOption, noResultsText = "Sin resultados", className = "", getOptionLabel, getOptionValue, getOptionDescription, renderOption, readOnly = false, ...inputProps }, ref) => {
|
|
5
6
|
const [internalValue, setInternalValue] = React.useState(value || "");
|
|
7
|
+
const [displayValue, setDisplayValue] = React.useState("");
|
|
6
8
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
7
9
|
const [highlightedIndex, setHighlightedIndex] = React.useState(-1);
|
|
10
|
+
const [dropdownPosition, setDropdownPosition] = React.useState(null);
|
|
8
11
|
const containerRef = React.useRef(null);
|
|
9
|
-
const
|
|
12
|
+
const dropdownRef = React.useRef(null);
|
|
13
|
+
const inputRef = React.useRef(null);
|
|
14
|
+
const justClearedRef = React.useRef(false);
|
|
15
|
+
// Detectar si estamos en modo register: si viene 'name' de register, estamos en modo register
|
|
16
|
+
// register siempre pasa 'name', 'onChange', 'onBlur', y 'ref'
|
|
17
|
+
const isRegisterMode = React.useMemo(() => {
|
|
18
|
+
// Si viene 'name' en inputProps, es porque viene de register
|
|
19
|
+
return "name" in inputProps && inputProps.name !== undefined;
|
|
20
|
+
}, [inputProps]);
|
|
21
|
+
const inputValue = isRegisterMode
|
|
22
|
+
? displayValue
|
|
23
|
+
: value !== undefined
|
|
24
|
+
? value
|
|
25
|
+
: internalValue;
|
|
10
26
|
const labelGetter = React.useCallback((item) => {
|
|
11
27
|
if (getOptionLabel)
|
|
12
28
|
return getOptionLabel(item);
|
|
@@ -35,26 +51,191 @@ export const AutocompleteInput = ({ options, value, onChange, onSelectOption, no
|
|
|
35
51
|
return label.includes(search) || optionValue.includes(search);
|
|
36
52
|
});
|
|
37
53
|
}, [inputValue, options, labelGetter, valueGetter]);
|
|
54
|
+
// Función helper para sincronizar displayValue con el valor del formulario
|
|
55
|
+
const syncDisplayValue = React.useCallback(() => {
|
|
56
|
+
if (isRegisterMode && inputRef.current) {
|
|
57
|
+
const formValue = inputRef.current.value;
|
|
58
|
+
// Si el valor del formulario coincide con algún getOptionValue, mostrar su label
|
|
59
|
+
const matchingOption = options.find((option) => String(valueGetter(option)) === String(formValue));
|
|
60
|
+
if (matchingOption) {
|
|
61
|
+
const label = labelGetter(matchingOption);
|
|
62
|
+
setDisplayValue(label);
|
|
63
|
+
return true; // Indica que se encontró y sincronizó un valor
|
|
64
|
+
}
|
|
65
|
+
else if (formValue) {
|
|
66
|
+
// Si hay un valor pero no coincide, mostrarlo tal cual
|
|
67
|
+
setDisplayValue(formValue);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
setDisplayValue("");
|
|
72
|
+
return false; // No hay valor aún
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}, [isRegisterMode, options, valueGetter, labelGetter]);
|
|
77
|
+
// Sincronizar displayValue con el valor del formulario en modo register
|
|
78
|
+
// Usar un intervalo que se ejecute hasta que encuentre el valor o hasta un máximo de intentos
|
|
79
|
+
React.useEffect(() => {
|
|
80
|
+
if (isRegisterMode) {
|
|
81
|
+
let attempts = 0;
|
|
82
|
+
const maxAttempts = 50; // Intentar durante ~5 segundos (50 * 100ms)
|
|
83
|
+
// Función que intenta sincronizar y retorna true si encontró un valor
|
|
84
|
+
const trySync = () => {
|
|
85
|
+
if (inputRef.current) {
|
|
86
|
+
const formValue = inputRef.current.value;
|
|
87
|
+
if (formValue) {
|
|
88
|
+
// Hay un valor, intentar sincronizar
|
|
89
|
+
const matchingOption = options.find((option) => String(valueGetter(option)) === String(formValue));
|
|
90
|
+
if (matchingOption) {
|
|
91
|
+
const label = labelGetter(matchingOption);
|
|
92
|
+
setDisplayValue(label);
|
|
93
|
+
return true; // Valor encontrado y sincronizado
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
setDisplayValue(formValue);
|
|
97
|
+
return true; // Valor encontrado pero no coincide con opciones
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return false; // No hay valor aún
|
|
102
|
+
};
|
|
103
|
+
// Intentar inmediatamente
|
|
104
|
+
if (trySync()) {
|
|
105
|
+
return; // Ya encontramos el valor
|
|
106
|
+
}
|
|
107
|
+
// Si no encontramos el valor, usar un intervalo para seguir intentando
|
|
108
|
+
const intervalId = window.setInterval(() => {
|
|
109
|
+
attempts++;
|
|
110
|
+
if (trySync() || attempts >= maxAttempts) {
|
|
111
|
+
clearInterval(intervalId);
|
|
112
|
+
}
|
|
113
|
+
}, 100); // Intentar cada 100ms
|
|
114
|
+
// También usar timeouts como fallback
|
|
115
|
+
const timeouts = [];
|
|
116
|
+
[0, 50, 100, 200, 500, 1000].forEach((delay) => {
|
|
117
|
+
const timeoutId = window.setTimeout(() => {
|
|
118
|
+
trySync();
|
|
119
|
+
}, delay);
|
|
120
|
+
timeouts.push(timeoutId);
|
|
121
|
+
});
|
|
122
|
+
return () => {
|
|
123
|
+
clearInterval(intervalId);
|
|
124
|
+
timeouts.forEach(clearTimeout);
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}, [isRegisterMode, options, valueGetter, labelGetter]);
|
|
128
|
+
// También escuchar cambios en el input nativo para sincronizar cuando cambie
|
|
129
|
+
React.useEffect(() => {
|
|
130
|
+
if (isRegisterMode && inputRef.current) {
|
|
131
|
+
const input = inputRef.current;
|
|
132
|
+
// Función para sincronizar cuando el input cambia
|
|
133
|
+
const handleInputSync = () => {
|
|
134
|
+
syncDisplayValue();
|
|
135
|
+
};
|
|
136
|
+
// Escuchar eventos de input y change
|
|
137
|
+
input.addEventListener("input", handleInputSync);
|
|
138
|
+
input.addEventListener("change", handleInputSync);
|
|
139
|
+
// También usar MutationObserver para detectar cambios en el atributo value
|
|
140
|
+
const observer = new MutationObserver(() => {
|
|
141
|
+
syncDisplayValue();
|
|
142
|
+
});
|
|
143
|
+
observer.observe(input, {
|
|
144
|
+
attributes: true,
|
|
145
|
+
attributeFilter: ["value"],
|
|
146
|
+
});
|
|
147
|
+
return () => {
|
|
148
|
+
input.removeEventListener("input", handleInputSync);
|
|
149
|
+
input.removeEventListener("change", handleInputSync);
|
|
150
|
+
observer.disconnect();
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}, [isRegisterMode, syncDisplayValue]);
|
|
38
154
|
const handleChange = (event) => {
|
|
155
|
+
if (readOnly)
|
|
156
|
+
return;
|
|
39
157
|
const newValue = event.target.value;
|
|
40
|
-
if (
|
|
41
|
-
|
|
158
|
+
if (isRegisterMode) {
|
|
159
|
+
// En modo register, actualizar el displayValue para mostrar lo que el usuario escribe
|
|
160
|
+
setDisplayValue(newValue);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Modo API personalizada
|
|
164
|
+
if (value === undefined) {
|
|
165
|
+
setInternalValue(newValue);
|
|
166
|
+
}
|
|
167
|
+
if (onChange) {
|
|
168
|
+
onChange(newValue);
|
|
169
|
+
}
|
|
42
170
|
}
|
|
43
|
-
onChange?.(newValue);
|
|
44
171
|
setIsOpen(true);
|
|
45
172
|
setHighlightedIndex(-1);
|
|
46
173
|
};
|
|
47
174
|
const handleSelect = (option) => {
|
|
175
|
+
if (readOnly)
|
|
176
|
+
return;
|
|
48
177
|
const label = labelGetter(option);
|
|
49
178
|
const selectedValue = valueGetter(option);
|
|
50
|
-
|
|
51
|
-
|
|
179
|
+
const valueString = String(selectedValue ?? "");
|
|
180
|
+
if (isRegisterMode) {
|
|
181
|
+
// En modo register:
|
|
182
|
+
// 1. Actualizar el input nativo con el valor (para que react-hook-form lo capture)
|
|
183
|
+
// 2. Actualizar displayValue con el label (para mostrarlo visualmente)
|
|
184
|
+
if (inputRef.current) {
|
|
185
|
+
const nativeInput = inputRef.current;
|
|
186
|
+
// Actualizar el valor del input directamente usando el setter nativo
|
|
187
|
+
// Esto evita que React sobrescriba el valor inmediatamente
|
|
188
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
189
|
+
if (nativeInputValueSetter) {
|
|
190
|
+
nativeInputValueSetter.call(nativeInput, valueString);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Fallback si el setter no está disponible
|
|
194
|
+
nativeInput.value = valueString;
|
|
195
|
+
}
|
|
196
|
+
// IMPORTANTE: Llamar al onChange de register DESPUÉS de actualizar el input
|
|
197
|
+
// El evento debe tener el input nativo como target con el valor ya actualizado
|
|
198
|
+
if (onChange) {
|
|
199
|
+
// Crear un evento que tenga el input nativo como target
|
|
200
|
+
// react-hook-form leerá el valor desde event.target.value
|
|
201
|
+
const changeEvent = {
|
|
202
|
+
target: nativeInput,
|
|
203
|
+
currentTarget: nativeInput,
|
|
204
|
+
};
|
|
205
|
+
onChange(changeEvent);
|
|
206
|
+
}
|
|
207
|
+
// También disparar eventos nativos para asegurar que todo esté sincronizado
|
|
208
|
+
// Estos eventos son importantes para la validación y el estado del formulario
|
|
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);
|
|
219
|
+
}
|
|
220
|
+
// Actualizar el displayValue para mostrar el label
|
|
221
|
+
setDisplayValue(label);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
// Modo API personalizada - comportamiento original
|
|
225
|
+
if (value === undefined) {
|
|
226
|
+
setInternalValue(label);
|
|
227
|
+
}
|
|
228
|
+
// Pasar el valor devuelto por getOptionValue, no el label
|
|
229
|
+
if (onChange) {
|
|
230
|
+
onChange(valueString);
|
|
231
|
+
}
|
|
52
232
|
}
|
|
53
|
-
onChange?.(label);
|
|
54
233
|
onSelectOption?.(option, selectedValue);
|
|
55
234
|
setIsOpen(false);
|
|
56
235
|
};
|
|
57
236
|
const handleKeyDown = (event) => {
|
|
237
|
+
if (readOnly)
|
|
238
|
+
return;
|
|
58
239
|
if (!isOpen && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
59
240
|
setIsOpen(true);
|
|
60
241
|
return;
|
|
@@ -70,44 +251,242 @@ export const AutocompleteInput = ({ options, value, onChange, onSelectOption, no
|
|
|
70
251
|
setHighlightedIndex((prev) => prev > 0 ? prev - 1 : filteredOptions.length - 1);
|
|
71
252
|
}
|
|
72
253
|
else if (event.key === "Enter") {
|
|
73
|
-
|
|
254
|
+
// Si hay una opción resaltada, seleccionarla
|
|
255
|
+
if (highlightedIndex >= 0 &&
|
|
256
|
+
highlightedIndex < filteredOptions.length) {
|
|
74
257
|
event.preventDefault();
|
|
75
258
|
handleSelect(filteredOptions[highlightedIndex]);
|
|
76
259
|
}
|
|
260
|
+
else if (isOpen && filteredOptions.length > 0) {
|
|
261
|
+
// Si no hay opción resaltada pero hay opciones disponibles, seleccionar la primera
|
|
262
|
+
event.preventDefault();
|
|
263
|
+
handleSelect(filteredOptions[0]);
|
|
264
|
+
}
|
|
77
265
|
}
|
|
78
266
|
else if (event.key === "Escape") {
|
|
79
267
|
setIsOpen(false);
|
|
80
268
|
}
|
|
81
269
|
};
|
|
82
270
|
React.useEffect(() => {
|
|
271
|
+
if (!isOpen)
|
|
272
|
+
return;
|
|
83
273
|
const handleClickOutside = (event) => {
|
|
84
|
-
|
|
85
|
-
|
|
274
|
+
const target = event.target;
|
|
275
|
+
const isClickInsideContainer = containerRef.current?.contains(target);
|
|
276
|
+
const isClickInsideDropdown = dropdownRef.current?.contains(target);
|
|
277
|
+
if (!isClickInsideContainer && !isClickInsideDropdown) {
|
|
86
278
|
setIsOpen(false);
|
|
87
279
|
}
|
|
88
280
|
};
|
|
89
|
-
|
|
281
|
+
// Pequeño delay para asegurar que el portal esté montado
|
|
282
|
+
const timer = setTimeout(() => {
|
|
283
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
284
|
+
}, 0);
|
|
90
285
|
return () => {
|
|
286
|
+
clearTimeout(timer);
|
|
91
287
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
92
288
|
};
|
|
93
|
-
}, []);
|
|
289
|
+
}, [isOpen]);
|
|
290
|
+
React.useEffect(() => {
|
|
291
|
+
if (!isRegisterMode) {
|
|
292
|
+
// Solo para modo API personalizada
|
|
293
|
+
if (value !== undefined) {
|
|
294
|
+
// Si el value es el resultado de getOptionValue, buscar la opción correspondiente
|
|
295
|
+
// y mostrar su label. Si no se encuentra, mostrar el value tal cual.
|
|
296
|
+
const matchingOption = options.find((option) => String(valueGetter(option)) === String(value));
|
|
297
|
+
if (matchingOption) {
|
|
298
|
+
setInternalValue(labelGetter(matchingOption));
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
setInternalValue(value);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// Resetear el estado interno cuando value es undefined (por ejemplo, después de un reset)
|
|
306
|
+
setInternalValue("");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}, [value, options, valueGetter, labelGetter, isRegisterMode]);
|
|
310
|
+
const showDropdown = !readOnly && isOpen && (filteredOptions.length > 0 || noResultsText);
|
|
311
|
+
// Verificar que estamos en el navegador
|
|
312
|
+
// Inicializar isMounted de forma síncrona si es posible
|
|
313
|
+
const [isMounted, setIsMounted] = React.useState(() => {
|
|
314
|
+
return typeof document !== "undefined" && !!document.body;
|
|
315
|
+
});
|
|
94
316
|
React.useEffect(() => {
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
}, [
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
317
|
+
if (!isMounted && typeof document !== "undefined" && document.body) {
|
|
318
|
+
setIsMounted(true);
|
|
319
|
+
}
|
|
320
|
+
}, [isMounted]);
|
|
321
|
+
// Actualizar posición del dropdown cuando se abre
|
|
322
|
+
React.useEffect(() => {
|
|
323
|
+
if (showDropdown && containerRef.current && isMounted) {
|
|
324
|
+
const updatePosition = () => {
|
|
325
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
326
|
+
if (rect) {
|
|
327
|
+
setDropdownPosition({
|
|
328
|
+
top: rect.bottom + window.scrollY + 4,
|
|
329
|
+
left: rect.left + window.scrollX,
|
|
330
|
+
width: rect.width,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
updatePosition();
|
|
335
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
336
|
+
window.addEventListener("resize", updatePosition);
|
|
337
|
+
return () => {
|
|
338
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
339
|
+
window.removeEventListener("resize", updatePosition);
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
setDropdownPosition(null);
|
|
344
|
+
}
|
|
345
|
+
}, [showDropdown, isMounted]);
|
|
346
|
+
// Detectar si hay un valor seleccionado
|
|
347
|
+
// Un valor está seleccionado si el value coincide con el getOptionValue de alguna opción
|
|
348
|
+
const hasSelectedValue = React.useMemo(() => {
|
|
349
|
+
if (isRegisterMode && inputRef.current) {
|
|
350
|
+
const formValue = inputRef.current.value;
|
|
351
|
+
if (!formValue)
|
|
352
|
+
return false;
|
|
353
|
+
return options.some((option) => String(valueGetter(option)) === String(formValue));
|
|
354
|
+
}
|
|
355
|
+
if (value === undefined || value === null || value === "")
|
|
356
|
+
return false;
|
|
357
|
+
// Verificar si el value coincide con el getOptionValue de alguna opción
|
|
358
|
+
return options.some((option) => String(valueGetter(option)) === String(value));
|
|
359
|
+
}, [value, options, valueGetter, isRegisterMode]);
|
|
360
|
+
// Función para limpiar el valor
|
|
361
|
+
const handleClear = React.useCallback((event) => {
|
|
362
|
+
if (readOnly)
|
|
363
|
+
return;
|
|
364
|
+
event.preventDefault();
|
|
365
|
+
event.stopPropagation();
|
|
366
|
+
// Marcar que acabamos de limpiar para prevenir que onFocus abra el diálogo
|
|
367
|
+
justClearedRef.current = true;
|
|
368
|
+
if (isRegisterMode) {
|
|
369
|
+
// En modo register, limpiar el input nativo y disparar eventos
|
|
370
|
+
if (inputRef.current) {
|
|
371
|
+
const nativeInput = inputRef.current;
|
|
372
|
+
const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
373
|
+
setter?.call(nativeInput, "");
|
|
374
|
+
// Disparar eventos para que react-hook-form lo capture
|
|
375
|
+
const inputEvent = new Event("input", { bubbles: true });
|
|
376
|
+
nativeInput.dispatchEvent(inputEvent);
|
|
377
|
+
const changeEvent = new Event("change", { bubbles: true });
|
|
378
|
+
nativeInput.dispatchEvent(changeEvent);
|
|
379
|
+
}
|
|
380
|
+
// Limpiar el displayValue
|
|
381
|
+
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
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
// Modo API personalizada
|
|
393
|
+
if (value === undefined) {
|
|
394
|
+
setInternalValue("");
|
|
395
|
+
}
|
|
396
|
+
if (onChange) {
|
|
397
|
+
onChange("");
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
setIsOpen(false);
|
|
401
|
+
// Resetear el flag después de un pequeño delay para permitir que otros eventos se procesen
|
|
402
|
+
setTimeout(() => {
|
|
403
|
+
justClearedRef.current = false;
|
|
404
|
+
}, 100);
|
|
405
|
+
}, [value, onChange, isRegisterMode, readOnly]);
|
|
406
|
+
// Determinar qué ícono mostrar: si hay valor seleccionado, mostrar "X", sino usar el ícono original
|
|
407
|
+
// Si está en readOnly, no mostrar el ícono de limpiar ni permitir clicks
|
|
408
|
+
const displayIcon = readOnly
|
|
409
|
+
? inputProps.icon
|
|
410
|
+
: hasSelectedValue
|
|
411
|
+
? "fa-times"
|
|
412
|
+
: inputProps.icon;
|
|
413
|
+
const displayIconPosition = readOnly
|
|
414
|
+
? inputProps.iconPosition || "left"
|
|
415
|
+
: hasSelectedValue
|
|
416
|
+
? "right"
|
|
417
|
+
: inputProps.iconPosition || "left";
|
|
418
|
+
const displayOnIconClick = readOnly
|
|
419
|
+
? undefined
|
|
420
|
+
: hasSelectedValue
|
|
421
|
+
? handleClear
|
|
422
|
+
: inputProps.onIconClick;
|
|
423
|
+
// Combinar refs: el ref del componente y el ref interno
|
|
424
|
+
const combinedRef = React.useCallback((node) => {
|
|
425
|
+
inputRef.current = node;
|
|
426
|
+
if (typeof ref === "function") {
|
|
427
|
+
ref(node);
|
|
428
|
+
}
|
|
429
|
+
else if (ref) {
|
|
430
|
+
ref.current = node;
|
|
431
|
+
}
|
|
432
|
+
// Cuando el ref se establece en modo register, sincronizar el displayValue
|
|
433
|
+
// Esto es importante para valores por defecto que vienen del formulario
|
|
434
|
+
if (isRegisterMode && node) {
|
|
435
|
+
// Intentar múltiples veces con diferentes delays
|
|
436
|
+
// react-hook-form puede establecer el valor en diferentes momentos
|
|
437
|
+
[0, 10, 50, 100, 200, 500].forEach((delay) => {
|
|
438
|
+
setTimeout(() => {
|
|
439
|
+
if (node && inputRef.current === node) {
|
|
440
|
+
const formValue = node.value;
|
|
441
|
+
if (formValue) {
|
|
442
|
+
const matchingOption = options.find((option) => String(valueGetter(option)) === String(formValue));
|
|
443
|
+
if (matchingOption) {
|
|
444
|
+
setDisplayValue(labelGetter(matchingOption));
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
setDisplayValue(formValue);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}, delay);
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
}, [ref, isRegisterMode, options, valueGetter, labelGetter]);
|
|
455
|
+
return (_jsxs("div", { ref: containerRef, className: "relative w-full", children: [_jsx(Input, { ...inputProps, ref: combinedRef, value: inputValue, onChange: handleChange, onFocus: () => {
|
|
456
|
+
if (!readOnly && !justClearedRef.current) {
|
|
457
|
+
setIsOpen(true);
|
|
458
|
+
}
|
|
459
|
+
}, onKeyDown: handleKeyDown, className: className, icon: displayIcon, iconPosition: displayIconPosition, onIconClick: displayOnIconClick, readOnly: readOnly }), (() => {
|
|
460
|
+
// Verificar de forma segura que document.body existe y es válido
|
|
461
|
+
const bodyElement = typeof document !== "undefined" &&
|
|
462
|
+
document.body &&
|
|
463
|
+
document.body instanceof HTMLElement
|
|
464
|
+
? document.body
|
|
465
|
+
: null;
|
|
466
|
+
return (showDropdown &&
|
|
467
|
+
dropdownPosition &&
|
|
468
|
+
isMounted &&
|
|
469
|
+
bodyElement &&
|
|
470
|
+
createPortal(_jsx("div", { ref: dropdownRef, className: "fixed z-[2001] min-w-full w-max rounded-md border border-[var(--color-border-default)] \r\n bg-[var(--color-bg-default)] shadow-[var(--shadow-lg)] max-h-60 overflow-auto", style: {
|
|
471
|
+
top: `${dropdownPosition.top}px`,
|
|
472
|
+
left: `${dropdownPosition.left}px`,
|
|
473
|
+
minWidth: `${dropdownPosition.width}px`,
|
|
474
|
+
}, children: filteredOptions.length > 0 ? (_jsx("ul", { className: "py-1", children: filteredOptions.map((option, index) => {
|
|
475
|
+
const label = labelGetter(option);
|
|
476
|
+
const description = descriptionGetter(option);
|
|
477
|
+
const anyOption = option;
|
|
478
|
+
return (_jsx("li", { className: `px-3 py-2 cursor-pointer flex items-start gap-2 text-sm
|
|
105
479
|
${index === highlightedIndex
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
};
|
|
480
|
+
? "bg-[var(--color-primary-soft)] text-[var(--color-primary)]"
|
|
481
|
+
: "text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)]"}`, onMouseDown: (event) => {
|
|
482
|
+
event.preventDefault();
|
|
483
|
+
handleSelect(option);
|
|
484
|
+
}, onMouseEnter: () => setHighlightedIndex(index), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className: `fa ${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
|
+
description !== null && (_jsx("span", { className: "text-xs text-[var(--color-text-secondary)] break-words", children: description }))] })] })) }, String(valueGetter(option) ?? label ?? index)));
|
|
486
|
+
}) })) : (_jsx("div", { className: "px-3 py-2 text-sm text-[var(--color-text-secondary)]", children: noResultsText })) }), bodyElement));
|
|
487
|
+
})()] }));
|
|
488
|
+
});
|
|
489
|
+
// Asignar displayName antes del cast genérico
|
|
490
|
+
AutocompleteInputInner.displayName = "AutocompleteInput";
|
|
491
|
+
// Exportar con el cast genérico
|
|
492
|
+
export const AutocompleteInput = AutocompleteInputInner;
|
|
@@ -33,7 +33,7 @@ export const Button = ({ variant = "primary", size = "md", icon, iconPosition =
|
|
|
33
33
|
if (!icon)
|
|
34
34
|
return null;
|
|
35
35
|
const iconClasses = size === "sm" ? "w-4 h-4" : size === "md" ? "w-5 h-5" : "w-6 h-6";
|
|
36
|
-
return (_jsx("i", { className: `fa ${icon} ${iconClasses} ${children ? (iconPosition === "right" ? "ml-2" : "mr-2") : ""}` }));
|
|
36
|
+
return (_jsx("i", { className: `fa ${icon} ${iconClasses} ${children ? (iconPosition === "right" ? "ml-2" : "mr-2") : ""} mt-0.5` }));
|
|
37
37
|
};
|
|
38
38
|
const rippleColor = variant === "primary" ? "rgba(255, 255, 255, 0.45)" : "rgba(0, 0, 0, 0.15)";
|
|
39
39
|
const handleClick = (event) => {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> {
|
|
3
|
+
label?: string;
|
|
4
|
+
labelPosition?: "left" | "right";
|
|
5
|
+
error?: string;
|
|
6
|
+
size?: "sm" | "md" | "lg";
|
|
7
|
+
/**
|
|
8
|
+
* Si es true, el checkbox será de solo lectura. No se podrá modificar pero se verá igual visualmente.
|
|
9
|
+
* Por defecto es false.
|
|
10
|
+
*/
|
|
11
|
+
readOnly?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
|
|
14
|
+
//# sourceMappingURL=Checkbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/Checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,aACf,SAAQ,IAAI,CACV,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAC3C,MAAM,GAAG,MAAM,CAChB;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,QAAQ,wFAsIpB,CAAC"}
|