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,52 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useState, useEffect, useMemo, createContext, useContext } from "react";
|
|
3
|
-
import { useSearchParams } from "react-router-dom";
|
|
4
|
-
const TabsContext = createContext(undefined);
|
|
5
|
-
export const useTabsContext = () => {
|
|
6
|
-
const context = useContext(TabsContext);
|
|
7
|
-
if (!context) {
|
|
8
|
-
throw new Error("TabPanel must be used within TabsGroup");
|
|
9
|
-
}
|
|
10
|
-
return context;
|
|
11
|
-
};
|
|
12
|
-
export const TabsGroup = ({ children, tabs, paramName, headerNode, onChangeTab, }) => {
|
|
13
|
-
const [searchParams, setSearchParams] = useSearchParams();
|
|
14
|
-
const defaultTab = tabs[0]?.id?.toString() || "";
|
|
15
|
-
// Obtener el tab activo desde URL params si paramName está definido, sino desde estado local
|
|
16
|
-
const urlTab = paramName ? searchParams.get(paramName) : null;
|
|
17
|
-
const initialTab = urlTab || defaultTab;
|
|
18
|
-
const [activeTab, setActiveTabState] = useState(initialTab);
|
|
19
|
-
// Sincronizar con URL params cuando cambian
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (paramName && urlTab) {
|
|
22
|
-
setActiveTabState(urlTab);
|
|
23
|
-
}
|
|
24
|
-
}, [paramName, urlTab]);
|
|
25
|
-
const setActiveTab = (tab) => {
|
|
26
|
-
setActiveTabState(tab);
|
|
27
|
-
// Actualizar URL params si paramName está definido
|
|
28
|
-
if (paramName) {
|
|
29
|
-
const newSearchParams = new URLSearchParams(searchParams);
|
|
30
|
-
newSearchParams.set(paramName, tab.toString());
|
|
31
|
-
setSearchParams(newSearchParams, { replace: true });
|
|
32
|
-
}
|
|
33
|
-
// Llamar al callback si está definido
|
|
34
|
-
if (onChangeTab) {
|
|
35
|
-
onChangeTab(tab.toString());
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
const contextValue = useMemo(() => ({ activeTab, setActiveTab }), [activeTab]);
|
|
39
|
-
const handleTabClick = (tabId) => {
|
|
40
|
-
setActiveTab(tabId);
|
|
41
|
-
};
|
|
42
|
-
return (_jsx(TabsContext.Provider, { value: contextValue, children: _jsxs("div", { className: "w-full font-[var(--font-default)]", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-[var(--color-border-default)]", children: [_jsx("div", { className: "flex items-center gap-1", children: tabs.map((tab) => {
|
|
43
|
-
const isActive = activeTab.toString() === tab.id.toString();
|
|
44
|
-
return (_jsx("button", { onClick: () => handleTabClick(tab.id), className: `
|
|
45
|
-
px-4 py-2 text-sm font-medium transition-colors cursor-pointer
|
|
46
|
-
border-b-2 -mb-[1px]
|
|
47
|
-
${isActive
|
|
48
|
-
? "text-[var(--color-primary)] border-[var(--color-primary)]"
|
|
49
|
-
: "text-[var(--color-text-secondary)] border-transparent hover:text-[var(--color-text-primary)] hover:border-[var(--color-border-default)]"}
|
|
50
|
-
`, "aria-selected": isActive, role: "tab", children: tab.label }, tab.id));
|
|
51
|
-
}) }), headerNode && (_jsx("div", { className: "flex items-center", children: headerNode }))] }), _jsx("div", { className: "mt-4", children: children })] }) }));
|
|
52
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export { Card } from "./Card";
|
|
2
|
-
export { AppLayout } from "./AppLayout";
|
|
3
|
-
export { Collection } from "./Collection";
|
|
4
|
-
export { DataField } from "./DataField";
|
|
5
|
-
export { TabsGroup } from "./TabsGroup";
|
|
6
|
-
export { TabPanel } from "./TabPanel";
|
|
7
|
-
export { DataTable } from "./DataTable";
|
|
8
|
-
export { Accordion } from "./Accordion";
|
|
9
|
-
export { Menu } from "./Menu";
|
|
10
|
-
export { DropdownMenu } from "./DropdownMenu";
|
|
11
|
-
export { DropdownPanel } from "./DropdownPanel";
|
|
12
|
-
export { Filter } from "./Filter";
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React, { useState } from "react";
|
|
3
|
-
import { getInitialLetters } from "../../helpers";
|
|
4
|
-
/**
|
|
5
|
-
* Helper function to convert color names to CSS values
|
|
6
|
-
*/
|
|
7
|
-
const getColorValue = (color) => {
|
|
8
|
-
if (!color)
|
|
9
|
-
return undefined;
|
|
10
|
-
// If already a valid CSS value (hex, rgb, rgba, hsl, etc.), return it
|
|
11
|
-
if (color.startsWith("#") ||
|
|
12
|
-
color.startsWith("rgb") ||
|
|
13
|
-
color.startsWith("hsl")) {
|
|
14
|
-
return color;
|
|
15
|
-
}
|
|
16
|
-
// Map common color names
|
|
17
|
-
const colorMap = {
|
|
18
|
-
white: "#ffffff",
|
|
19
|
-
black: "#000000",
|
|
20
|
-
"gray-800": "#1f2937",
|
|
21
|
-
"gray-700": "#374151",
|
|
22
|
-
"gray-600": "#4b5563",
|
|
23
|
-
"gray-500": "#6b7280",
|
|
24
|
-
"gray-400": "#9ca3af",
|
|
25
|
-
"gray-300": "#d1d5db",
|
|
26
|
-
"gray-200": "#e5e7eb",
|
|
27
|
-
"gray-100": "#f3f4f6",
|
|
28
|
-
"gray-50": "#f9fafb",
|
|
29
|
-
};
|
|
30
|
-
return colorMap[color.toLowerCase()] || color;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Avatar component displays a circular avatar with initials or an image
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* // Basic usage with text
|
|
37
|
-
* <Avatar text="John Doe" />
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* // With image
|
|
41
|
-
* <Avatar text="John Doe" image="https://example.com/avatar.jpg" />
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* // Custom colors
|
|
45
|
-
* <Avatar text="Jane Smith" bgColor="#3b82f6" textColor="#ffffff" />
|
|
46
|
-
*/
|
|
47
|
-
export const Avatar = ({ text, image, bgColor = "gray-600", textColor = "white", size = "md", className = "", }) => {
|
|
48
|
-
const [imageError, setImageError] = useState(false);
|
|
49
|
-
const initials = getInitialLetters(text);
|
|
50
|
-
const showImage = image && !imageError;
|
|
51
|
-
const sizeClasses = {
|
|
52
|
-
sm: "w-8 h-8 text-xs",
|
|
53
|
-
md: "w-10 h-10 text-sm",
|
|
54
|
-
lg: "w-12 h-12 text-base",
|
|
55
|
-
};
|
|
56
|
-
const baseClasses = `
|
|
57
|
-
rounded-full
|
|
58
|
-
flex
|
|
59
|
-
items-center
|
|
60
|
-
justify-center
|
|
61
|
-
font-semibold
|
|
62
|
-
font-[var(--font-default)]
|
|
63
|
-
overflow-hidden
|
|
64
|
-
flex-shrink-0
|
|
65
|
-
${sizeClasses[size]}
|
|
66
|
-
${className}
|
|
67
|
-
`;
|
|
68
|
-
// Inline styles for colors (only if no image or image failed to load)
|
|
69
|
-
const inlineStyles = showImage
|
|
70
|
-
? {}
|
|
71
|
-
: {
|
|
72
|
-
backgroundColor: getColorValue(bgColor) || bgColor || "#4b5563",
|
|
73
|
-
color: getColorValue(textColor) || textColor || "#ffffff",
|
|
74
|
-
};
|
|
75
|
-
return (_jsx("div", { className: baseClasses, style: inlineStyles, title: text, role: "img", "aria-label": text, children: showImage ? (_jsx("img", { src: image, alt: text, className: "w-full h-full object-cover", onError: () => setImageError(true) })) : (_jsx("span", { children: initials })) }));
|
|
76
|
-
};
|
|
77
|
-
Avatar.displayName = "Avatar";
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { normalizeIconClass } from "./iconUtils";
|
|
4
|
-
// Función helper para convertir nombres de colores comunes a valores CSS válidos
|
|
5
|
-
const getColorValue = (color) => {
|
|
6
|
-
if (!color)
|
|
7
|
-
return undefined;
|
|
8
|
-
// Si ya es un valor CSS válido (hex, rgb, rgba, hsl, etc.), retornarlo
|
|
9
|
-
if (color.startsWith("#") ||
|
|
10
|
-
color.startsWith("rgb") ||
|
|
11
|
-
color.startsWith("hsl")) {
|
|
12
|
-
return color;
|
|
13
|
-
}
|
|
14
|
-
// Mapeo de nombres de colores comunes
|
|
15
|
-
const colorMap = {
|
|
16
|
-
white: "#ffffff",
|
|
17
|
-
black: "#000000",
|
|
18
|
-
"gray-800": "#1f2937",
|
|
19
|
-
"gray-700": "#374151",
|
|
20
|
-
"gray-600": "#4b5563",
|
|
21
|
-
"gray-500": "#6b7280",
|
|
22
|
-
"gray-400": "#9ca3af",
|
|
23
|
-
"gray-300": "#d1d5db",
|
|
24
|
-
"gray-200": "#e5e7eb",
|
|
25
|
-
"gray-100": "#f3f4f6",
|
|
26
|
-
"gray-50": "#f9fafb",
|
|
27
|
-
};
|
|
28
|
-
return colorMap[color.toLowerCase()] || color;
|
|
29
|
-
};
|
|
30
|
-
export const Badge = ({ children, variant = "primary", size = "md", rounded = false, className = "", icon, iconPosition = "left", iconLabel, bg, textColor, onClick, }) => {
|
|
31
|
-
const baseClasses = "inline-flex items-center font-medium font-[var(--font-default)]";
|
|
32
|
-
const variantClasses = {
|
|
33
|
-
primary: `
|
|
34
|
-
bg-[var(--color-primary-light)] text-gray-800
|
|
35
|
-
`,
|
|
36
|
-
secondary: `
|
|
37
|
-
bg-[var(--color-secondary-light)] text-gray-800
|
|
38
|
-
`,
|
|
39
|
-
success: `
|
|
40
|
-
bg-[var(--color-success-light)] text-gray-800
|
|
41
|
-
`,
|
|
42
|
-
warning: `
|
|
43
|
-
bg-[var(--color-warning-light)] text-gray-800
|
|
44
|
-
`,
|
|
45
|
-
danger: `
|
|
46
|
-
bg-[var(--color-danger-light)] text-gray-800
|
|
47
|
-
`,
|
|
48
|
-
info: `
|
|
49
|
-
bg-[var(--color-info-light)] text-gray-800
|
|
50
|
-
`,
|
|
51
|
-
};
|
|
52
|
-
const sizeClasses = {
|
|
53
|
-
sm: "py-0.5 text-xs",
|
|
54
|
-
md: "py-0.5 text-sm",
|
|
55
|
-
lg: "py-1 text-base",
|
|
56
|
-
};
|
|
57
|
-
// Padding horizontal: si hay icono, el badge no tiene padding, se aplica a los elementos internos
|
|
58
|
-
const horizontalPaddingClasses = icon
|
|
59
|
-
? "" // Sin padding horizontal en el badge cuando hay icono
|
|
60
|
-
: size === "sm"
|
|
61
|
-
? "px-2"
|
|
62
|
-
: size === "md"
|
|
63
|
-
? "px-2.5"
|
|
64
|
-
: "px-3";
|
|
65
|
-
// Padding para el texto: flex-1 para ocupar el espacio, padding solo en el lado opuesto al icono
|
|
66
|
-
const textPaddingClasses = icon
|
|
67
|
-
? iconPosition === "left"
|
|
68
|
-
? size === "sm"
|
|
69
|
-
? "flex-1 pr-2"
|
|
70
|
-
: size === "md"
|
|
71
|
-
? "flex-1 pr-2.5"
|
|
72
|
-
: "flex-1 pr-3"
|
|
73
|
-
: size === "sm"
|
|
74
|
-
? "flex-1 pl-2"
|
|
75
|
-
: size === "md"
|
|
76
|
-
? "flex-1 pl-2.5"
|
|
77
|
-
: "flex-1 pl-3"
|
|
78
|
-
: "";
|
|
79
|
-
// Padding para el icono: solo en el lado del borde
|
|
80
|
-
const iconPaddingClasses = icon
|
|
81
|
-
? iconPosition === "left"
|
|
82
|
-
? size === "sm"
|
|
83
|
-
? "pl-2"
|
|
84
|
-
: size === "md"
|
|
85
|
-
? "pl-2.5"
|
|
86
|
-
: "pl-3"
|
|
87
|
-
: size === "sm"
|
|
88
|
-
? "pr-2"
|
|
89
|
-
: size === "md"
|
|
90
|
-
? "pr-2.5"
|
|
91
|
-
: "pr-3"
|
|
92
|
-
: "";
|
|
93
|
-
const roundedClasses = rounded ? "rounded-full" : "rounded-md";
|
|
94
|
-
const gapClasses = icon ? "gap-2" : ""; // Gap entre icono y texto cuando hay icono
|
|
95
|
-
const iconSizeClasses = size === "sm" ? "text-xs" : size === "md" ? "text-sm" : "text-base";
|
|
96
|
-
// Si se proporciona bg personalizado, usar estilos inline; si no, usar las clases de variante
|
|
97
|
-
const backgroundClasses = bg ? "" : variantClasses[variant];
|
|
98
|
-
// Estilos inline para colores personalizados
|
|
99
|
-
const inlineStyles = bg
|
|
100
|
-
? {
|
|
101
|
-
backgroundColor: getColorValue(bg) || bg,
|
|
102
|
-
color: getColorValue(textColor) || textColor || "#1f2937", // gray-800 por defecto
|
|
103
|
-
}
|
|
104
|
-
: {};
|
|
105
|
-
// Si hay onClick y no hay iconos, agregar cursor-pointer al badge completo
|
|
106
|
-
const cursorClasses = onClick && !icon ? "cursor-pointer" : "";
|
|
107
|
-
const classes = `${baseClasses} ${backgroundClasses} ${sizeClasses[size]} ${horizontalPaddingClasses} ${roundedClasses} ${gapClasses} ${cursorClasses} ${className}`;
|
|
108
|
-
const renderIcon = () => {
|
|
109
|
-
if (!icon)
|
|
110
|
-
return null;
|
|
111
|
-
// Si hay onClick y hay iconos, el onClick se aplica solo a los iconos
|
|
112
|
-
const iconClasses = onClick
|
|
113
|
-
? `${normalizeIconClass(icon)} ${iconSizeClasses} cursor-pointer`
|
|
114
|
-
: `${normalizeIconClass(icon)} ${iconSizeClasses}`;
|
|
115
|
-
return (_jsx("span", { className: iconPaddingClasses, children: _jsx("i", { className: iconClasses, "aria-hidden": !iconLabel, "aria-label": iconLabel, onClick: onClick, role: onClick ? "button" : undefined, tabIndex: onClick ? 0 : undefined, onKeyDown: onClick
|
|
116
|
-
? (e) => {
|
|
117
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
118
|
-
e.preventDefault();
|
|
119
|
-
// Crear un evento sintético compatible con MouseEvent
|
|
120
|
-
const syntheticEvent = {
|
|
121
|
-
...e,
|
|
122
|
-
currentTarget: e.currentTarget,
|
|
123
|
-
target: e.target,
|
|
124
|
-
};
|
|
125
|
-
onClick(syntheticEvent);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
: undefined }) }));
|
|
129
|
-
};
|
|
130
|
-
// Si hay onClick y no hay iconos, aplicar onClick al badge completo
|
|
131
|
-
const badgeProps = onClick && !icon
|
|
132
|
-
? {
|
|
133
|
-
onClick,
|
|
134
|
-
role: "button",
|
|
135
|
-
tabIndex: 0,
|
|
136
|
-
onKeyDown: (e) => {
|
|
137
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
138
|
-
e.preventDefault();
|
|
139
|
-
// Crear un evento sintético compatible con MouseEvent
|
|
140
|
-
const syntheticEvent = {
|
|
141
|
-
...e,
|
|
142
|
-
currentTarget: e.currentTarget,
|
|
143
|
-
target: e.target,
|
|
144
|
-
};
|
|
145
|
-
onClick(syntheticEvent);
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
}
|
|
149
|
-
: {};
|
|
150
|
-
return (_jsxs("span", { className: classes, style: inlineStyles, ...badgeProps, children: [icon && iconPosition === "left" && renderIcon(), _jsx("span", { className: textPaddingClasses, children: children }), icon && iconPosition === "right" && renderIcon()] }));
|
|
151
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useEffect } from "react";
|
|
3
|
-
import { normalizeIconClass } from "./iconUtils";
|
|
4
|
-
export const Dialog = ({ isOpen, title, children, footer, onClose, closeOnOverlayClick = false, compact = false, }) => {
|
|
5
|
-
// Prevenir scroll del body cuando el dialog está abierto
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
if (isOpen) {
|
|
8
|
-
document.body.style.overflow = "hidden";
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
document.body.style.overflow = "";
|
|
12
|
-
}
|
|
13
|
-
return () => {
|
|
14
|
-
document.body.style.overflow = "";
|
|
15
|
-
};
|
|
16
|
-
}, [isOpen]);
|
|
17
|
-
// Manejar tecla Escape para cerrar
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
const handleEscape = (e) => {
|
|
20
|
-
if (e.key === "Escape" && isOpen && onClose) {
|
|
21
|
-
onClose();
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
if (isOpen) {
|
|
25
|
-
document.addEventListener("keydown", handleEscape);
|
|
26
|
-
}
|
|
27
|
-
return () => {
|
|
28
|
-
document.removeEventListener("keydown", handleEscape);
|
|
29
|
-
};
|
|
30
|
-
}, [isOpen, onClose]);
|
|
31
|
-
if (!isOpen) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
const handleOverlayClick = () => {
|
|
35
|
-
if (closeOnOverlayClick && onClose) {
|
|
36
|
-
onClose();
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
return (_jsxs("div", { className: "fixed inset-0 z-[2000] flex items-center justify-center p-4", role: "dialog", "aria-modal": "true", "aria-labelledby": "dialog-title", children: [_jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: handleOverlayClick }), _jsxs("div", { className: "relative w-auto max-w-lg min-w-[400px] bg-[var(--color-bg-default)] rounded-lg shadow-[var(--shadow-xl)] border border-[var(--color-border-default)] font-[var(--font-default)] max-h-[90vh] flex flex-col", onClick: (e) => e.stopPropagation(), style: { overflow: "visible" }, children: [_jsxs("div", { className: `flex items-center justify-between ${compact ? "px-4 py-2" : "px-6 py-4"} border-b border-[var(--color-border-default)] flex-shrink-0`, children: [_jsx("h2", { id: "dialog-title", className: "text-lg font-semibold text-[var(--color-text-primary)]", children: title }), onClose && (_jsx("button", { onClick: onClose, className: "ml-4 p-1 rounded-md flysoft-button-reset bg-transparent border-none text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] transition-colors cursor-pointer", "aria-label": "Cerrar dialog", children: _jsx("i", { className: normalizeIconClass("fa-times") }) }))] }), _jsx("div", { className: `${compact ? "px-4 py-3" : "px-6 py-4"} flex-1 text-[var(--color-text-primary)] min-w-0`, style: {
|
|
40
|
-
overflowY: "auto",
|
|
41
|
-
overflowX: "visible",
|
|
42
|
-
maxHeight: "calc(90vh - 200px)",
|
|
43
|
-
}, children: children }), footer && (_jsx("div", { className: `${compact ? "px-4 py-2" : "px-6 py-4"} border-t border-[var(--color-border-default)] flex items-center justify-end gap-2 flex-shrink-0 flex-wrap`, children: footer }))] })] }));
|
|
44
|
-
};
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useState, useEffect } from "react";
|
|
3
|
-
import { useSearchParams } from "react-router-dom";
|
|
4
|
-
import { Button } from "../form-controls/Button";
|
|
5
|
-
import { Dialog } from "./Dialog";
|
|
6
|
-
import { Filter } from "../layout/Filter";
|
|
7
|
-
import { Collection } from "../layout/Collection";
|
|
8
|
-
export const FiltersDialog = ({ filters }) => {
|
|
9
|
-
const [searchParams, setSearchParams] = useSearchParams();
|
|
10
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
11
|
-
const [filterValues, setFilterValues] = useState({});
|
|
12
|
-
// Inicializar filterValues con los valores actuales de la URL
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
const initialValues = {};
|
|
15
|
-
filters.forEach((filter) => {
|
|
16
|
-
const urlValue = searchParams.get(filter.paramName);
|
|
17
|
-
initialValues[filter.paramName] = urlValue || undefined;
|
|
18
|
-
});
|
|
19
|
-
setFilterValues(initialValues);
|
|
20
|
-
}, []); // Solo al montar el componente
|
|
21
|
-
// Sincronizar filterValues cuando se abre el dialog con los valores actuales de la URL
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
if (isOpen) {
|
|
24
|
-
const currentValues = {};
|
|
25
|
-
filters.forEach((filter) => {
|
|
26
|
-
const urlValue = searchParams.get(filter.paramName);
|
|
27
|
-
currentValues[filter.paramName] = urlValue || undefined;
|
|
28
|
-
});
|
|
29
|
-
setFilterValues(currentValues);
|
|
30
|
-
}
|
|
31
|
-
}, [isOpen, filters, searchParams]);
|
|
32
|
-
const handleFilterChange = (paramName, value) => {
|
|
33
|
-
setFilterValues((prev) => ({
|
|
34
|
-
...prev,
|
|
35
|
-
[paramName]: value,
|
|
36
|
-
}));
|
|
37
|
-
};
|
|
38
|
-
const handleApplyFilters = () => {
|
|
39
|
-
const newSearchParams = new URLSearchParams(searchParams);
|
|
40
|
-
// Aplicar todos los filtros a la URL
|
|
41
|
-
filters.forEach((filter) => {
|
|
42
|
-
const value = filterValues[filter.paramName];
|
|
43
|
-
if (value) {
|
|
44
|
-
newSearchParams.set(filter.paramName, value);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
newSearchParams.delete(filter.paramName);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
setSearchParams(newSearchParams, { replace: true });
|
|
51
|
-
setIsOpen(false);
|
|
52
|
-
};
|
|
53
|
-
const handleClose = () => {
|
|
54
|
-
setIsOpen(false);
|
|
55
|
-
};
|
|
56
|
-
const handleOpen = () => {
|
|
57
|
-
setIsOpen(true);
|
|
58
|
-
};
|
|
59
|
-
// Construir las props de Filter para cada filtro
|
|
60
|
-
const getFilterProps = (filterConfig) => {
|
|
61
|
-
const baseProps = {
|
|
62
|
-
label: filterConfig.label,
|
|
63
|
-
staticOptions: filterConfig.staticOptions,
|
|
64
|
-
inputWidth: filterConfig.inputWidth,
|
|
65
|
-
value: filterValues[filterConfig.paramName],
|
|
66
|
-
onChange: (value) => handleFilterChange(filterConfig.paramName, value),
|
|
67
|
-
};
|
|
68
|
-
switch (filterConfig.filterType) {
|
|
69
|
-
case "text":
|
|
70
|
-
return {
|
|
71
|
-
...baseProps,
|
|
72
|
-
filterType: "text",
|
|
73
|
-
};
|
|
74
|
-
case "number":
|
|
75
|
-
return {
|
|
76
|
-
...baseProps,
|
|
77
|
-
filterType: "number",
|
|
78
|
-
min: filterConfig.min,
|
|
79
|
-
max: filterConfig.max,
|
|
80
|
-
};
|
|
81
|
-
case "date":
|
|
82
|
-
return {
|
|
83
|
-
...baseProps,
|
|
84
|
-
filterType: "date",
|
|
85
|
-
};
|
|
86
|
-
case "autocomplete":
|
|
87
|
-
return {
|
|
88
|
-
...baseProps,
|
|
89
|
-
filterType: "autocomplete",
|
|
90
|
-
options: filterConfig.options || [],
|
|
91
|
-
getOptionLabel: filterConfig.getOptionLabel,
|
|
92
|
-
getOptionValue: filterConfig.getOptionValue,
|
|
93
|
-
renderOption: filterConfig.renderOption,
|
|
94
|
-
noResultsText: filterConfig.noResultsText,
|
|
95
|
-
};
|
|
96
|
-
default:
|
|
97
|
-
return {
|
|
98
|
-
...baseProps,
|
|
99
|
-
filterType: "text",
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
return (_jsxs(_Fragment, { children: [_jsx(Button, { icon: "fa-filter", variant: "outline", size: "sm", onClick: handleOpen, "aria-label": "Abrir filtros", children: "Filtrar" }), _jsx(Dialog, { isOpen: isOpen, title: "Filtros", footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: handleClose, children: "Cerrar" }), _jsx(Button, { variant: "primary", onClick: handleApplyFilters, children: "Aplicar filtros" })] }), onClose: handleClose, closeOnOverlayClick: false, children: _jsx("div", { className: "space-y-4", children: _jsx(Collection, { direction: "column", gap: "1rem", children: filters.map((filter) => (_jsx(Filter, { ...getFilterProps(filter) }, filter.paramName))) }) }) })] }));
|
|
104
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { useTheme } from "../../contexts/ThemeContext";
|
|
4
|
-
export const Loader = ({ isLoading = false, text, children, keepContentWhileLoading, contentLoadingNode, overlayClassName, }) => {
|
|
5
|
-
const { theme } = useTheme();
|
|
6
|
-
const displayText = text;
|
|
7
|
-
// Clases por defecto del overlay (negro semitransparente con blur)
|
|
8
|
-
const defaultOverlayClasses = "bg-black/50 backdrop-blur-sm";
|
|
9
|
-
// Combinar clases por defecto con las personalizadas
|
|
10
|
-
const overlayClasses = overlayClassName
|
|
11
|
-
? overlayClassName
|
|
12
|
-
: defaultOverlayClasses;
|
|
13
|
-
// Barra de progreso infinita
|
|
14
|
-
const ProgressBar = () => {
|
|
15
|
-
// Variable CSS para el gradiente del color primario
|
|
16
|
-
const gradientColor = `no-repeat linear-gradient(${theme.colors.primary} 0 0)`;
|
|
17
|
-
const bgSecondary = theme.colors.bgSecondary || theme.colors.gray100;
|
|
18
|
-
return (_jsxs("div", { className: "flex flex-col items-center gap-0.5 w-full", role: "status", "aria-live": "polite", children: [_jsx("div", { className: "h-1 w-full rounded", style: {
|
|
19
|
-
"--c": gradientColor,
|
|
20
|
-
background: `var(--c), var(--c), ${bgSecondary}`,
|
|
21
|
-
backgroundSize: "60% 100%",
|
|
22
|
-
animation: "l16 3s infinite",
|
|
23
|
-
} }), displayText && (_jsx("span", { className: "text-xs text-[var(--color-text-secondary)] font-[var(--font-default)]", children: displayText }))] }));
|
|
24
|
-
};
|
|
25
|
-
// Si no está cargando, mostrar solo children (si existen)
|
|
26
|
-
if (!isLoading) {
|
|
27
|
-
return _jsx(_Fragment, { children: children });
|
|
28
|
-
}
|
|
29
|
-
// Variante 1: Con contentLoadingNode
|
|
30
|
-
if (contentLoadingNode) {
|
|
31
|
-
return (_jsxs("div", { className: "relative", children: [_jsx("div", { className: keepContentWhileLoading ? "opacity-50 pointer-events-none" : "", children: contentLoadingNode }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center z-10 pointer-events-none px-4", children: _jsx("div", { className: "bg-[var(--color-bg-default)] rounded-lg p-6 shadow-lg border border-[var(--color-border-default)] pointer-events-auto w-full", children: _jsx(ProgressBar, {}) }) })] }));
|
|
32
|
-
}
|
|
33
|
-
// Variante 2: Con children pero sin contentLoadingNode
|
|
34
|
-
if (children) {
|
|
35
|
-
// Si keepContentWhileLoading es true, mostrar children con overlay
|
|
36
|
-
if (keepContentWhileLoading) {
|
|
37
|
-
return (_jsxs("div", { className: "relative", children: [_jsx("div", { className: "pointer-events-none select-none", children: children }), _jsx("div", { className: `absolute inset-0 flex items-center justify-center z-10 pointer-events-auto px-4 ${overlayClasses}`, children: _jsx("div", { className: "bg-[var(--color-bg-default)] rounded-lg p-6 shadow-lg border border-[var(--color-border-default)] w-full max-w-2xl", children: _jsx(ProgressBar, {}) }) })] }));
|
|
38
|
-
}
|
|
39
|
-
// Si no tiene keepContentWhileLoading, ocultar children y mostrar solo loader básico
|
|
40
|
-
return (_jsx("div", { className: "flex items-center justify-center p-6 w-full", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ProgressBar, {}) }) }));
|
|
41
|
-
}
|
|
42
|
-
// Variante 3: Sin contentLoadingNode ni children - solo loader
|
|
43
|
-
return (_jsx("div", { className: "flex items-center justify-center p-6 w-full", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ProgressBar, {}) }) }));
|
|
44
|
-
};
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { normalizeIconClass } from "./iconUtils";
|
|
4
|
-
/**
|
|
5
|
-
* Helper function to convert color names to CSS values
|
|
6
|
-
*/
|
|
7
|
-
const getColorValue = (color) => {
|
|
8
|
-
if (!color)
|
|
9
|
-
return undefined;
|
|
10
|
-
// If already a valid CSS value (hex, rgb, rgba, hsl, etc.), return it
|
|
11
|
-
if (color.startsWith("#") ||
|
|
12
|
-
color.startsWith("rgb") ||
|
|
13
|
-
color.startsWith("hsl")) {
|
|
14
|
-
return color;
|
|
15
|
-
}
|
|
16
|
-
// Map common color names
|
|
17
|
-
const colorMap = {
|
|
18
|
-
white: "#ffffff",
|
|
19
|
-
black: "#000000",
|
|
20
|
-
"gray-800": "#1f2937",
|
|
21
|
-
"gray-700": "#374151",
|
|
22
|
-
"gray-600": "#4b5563",
|
|
23
|
-
"gray-500": "#6b7280",
|
|
24
|
-
"gray-400": "#9ca3af",
|
|
25
|
-
"gray-300": "#d1d5db",
|
|
26
|
-
"gray-200": "#e5e7eb",
|
|
27
|
-
"gray-100": "#f3f4f6",
|
|
28
|
-
"gray-50": "#f9fafb",
|
|
29
|
-
};
|
|
30
|
-
return colorMap[color.toLowerCase()] || color;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Get the CSS variable name for a variant color
|
|
34
|
-
*/
|
|
35
|
-
const getVariantColorVar = (variant) => {
|
|
36
|
-
if (!variant)
|
|
37
|
-
return "var(--color-primary)";
|
|
38
|
-
const variantMap = {
|
|
39
|
-
primary: "var(--color-primary)",
|
|
40
|
-
secondary: "var(--color-secondary)",
|
|
41
|
-
success: "var(--color-success)",
|
|
42
|
-
warning: "var(--color-warning)",
|
|
43
|
-
danger: "var(--color-danger)",
|
|
44
|
-
info: "var(--color-info)",
|
|
45
|
-
};
|
|
46
|
-
return variantMap[variant];
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* Get the actual color value for a variant (for gradients)
|
|
50
|
-
* This reads the CSS variable value from the computed styles
|
|
51
|
-
*/
|
|
52
|
-
const getVariantColorValue = (variant) => {
|
|
53
|
-
if (!variant)
|
|
54
|
-
return "#007aff"; // default primary color
|
|
55
|
-
const variantColorMap = {
|
|
56
|
-
primary: "#007aff",
|
|
57
|
-
secondary: "#6b7280",
|
|
58
|
-
success: "#10b981",
|
|
59
|
-
warning: "#f59e0b",
|
|
60
|
-
danger: "#ef4444",
|
|
61
|
-
info: "#06b6d4",
|
|
62
|
-
};
|
|
63
|
-
return variantColorMap[variant];
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* RoadMap component displays a series of stages like metro stations
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* // Basic usage
|
|
70
|
-
* <RoadMap stages={[
|
|
71
|
-
* { name: "Start", variant: "primary" },
|
|
72
|
-
* { name: "Middle", variant: "success" },
|
|
73
|
-
* { name: "End", variant: "info" }
|
|
74
|
-
* ]} />
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* // With icons and descriptions
|
|
78
|
-
* <RoadMap stages={[
|
|
79
|
-
* { name: "Planning", description: "Define requirements", icon: "fa-clipboard", variant: "primary" },
|
|
80
|
-
* { name: "Development", description: "Build the feature", icon: "fa-code", variant: "success" },
|
|
81
|
-
* { name: "Testing", description: "Test thoroughly", icon: "fa-check-circle", variant: "warning" }
|
|
82
|
-
* ]} />
|
|
83
|
-
*/
|
|
84
|
-
export const RoadMap = ({ stages, className = "", }) => {
|
|
85
|
-
if (!stages || stages.length === 0) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Get the background color for a stage
|
|
90
|
-
*/
|
|
91
|
-
const getStageBgColor = (stage) => {
|
|
92
|
-
if (stage.bg) {
|
|
93
|
-
return getColorValue(stage.bg) || stage.bg;
|
|
94
|
-
}
|
|
95
|
-
return getVariantColorVar(stage.variant || "primary");
|
|
96
|
-
};
|
|
97
|
-
/**
|
|
98
|
-
* Get the color value for gradient calculations
|
|
99
|
-
*/
|
|
100
|
-
const getStageColorValue = (stage) => {
|
|
101
|
-
if (stage.bg) {
|
|
102
|
-
return getColorValue(stage.bg) || stage.bg;
|
|
103
|
-
}
|
|
104
|
-
return getVariantColorValue(stage.variant || "primary");
|
|
105
|
-
};
|
|
106
|
-
/**
|
|
107
|
-
* Create a gradient string for the connector line
|
|
108
|
-
* The line transitions smoothly from the source color to the destination color
|
|
109
|
-
*/
|
|
110
|
-
const getConnectorGradient = (fromStage, toStage) => {
|
|
111
|
-
const fromColor = getStageColorValue(fromStage);
|
|
112
|
-
const toColor = getStageColorValue(toStage);
|
|
113
|
-
// Create a smooth gradient that transitions from source to destination
|
|
114
|
-
return `linear-gradient(to bottom, ${fromColor}, ${toColor})`;
|
|
115
|
-
};
|
|
116
|
-
return (_jsx("div", { className: `roadmap-container ${className}`, children: stages.map((stage, index) => {
|
|
117
|
-
const isLast = index === stages.length - 1;
|
|
118
|
-
const isDisabled = stage.disabled;
|
|
119
|
-
const bgColor = getStageBgColor(stage);
|
|
120
|
-
const connectorGradient = !isLast
|
|
121
|
-
? getConnectorGradient(stage, stages[index + 1])
|
|
122
|
-
: null;
|
|
123
|
-
return (_jsxs("div", { className: "relative flex items-start gap-3", children: [_jsxs("div", { className: "flex flex-col items-center", children: [_jsx("div", { className: `
|
|
124
|
-
w-6 h-6 rounded-full
|
|
125
|
-
flex items-center justify-center
|
|
126
|
-
flex-shrink-0
|
|
127
|
-
${isDisabled ? "opacity-50" : ""}
|
|
128
|
-
`, style: {
|
|
129
|
-
backgroundColor: bgColor,
|
|
130
|
-
color: "#ffffff",
|
|
131
|
-
}, children: stage.icon ? (_jsx("i", { className: `${normalizeIconClass(stage.icon)} text-xs` })) : null }), !isLast && (_jsx("div", { className: "w-0.5 h-4 flex-shrink-0", style: {
|
|
132
|
-
background: connectorGradient || undefined,
|
|
133
|
-
} }))] }), _jsxs("div", { className: `
|
|
134
|
-
flex-1
|
|
135
|
-
${isDisabled ? "opacity-50" : ""}
|
|
136
|
-
`, children: [_jsx("h3", { className: "text-sm font-semibold font-[var(--font-default)] mb-0.5", style: { color: "var(--color-text-primary)" }, children: stage.name }), stage.description && (_jsx("p", { className: "text-xs font-[var(--font-default)]", style: { color: "var(--color-text-secondary)" }, children: stage.description }))] })] }, index));
|
|
137
|
-
}) }));
|
|
138
|
-
};
|
|
139
|
-
RoadMap.displayName = "RoadMap";
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { twMerge } from "tailwind-merge";
|
|
4
|
-
/**
|
|
5
|
-
* Componente Skeleton para mostrar estados de carga.
|
|
6
|
-
* Consiste en un div con una animación de pulso y un fondo grisáceo por defecto.
|
|
7
|
-
*/
|
|
8
|
-
export const Skeleton = ({ className }) => {
|
|
9
|
-
return (_jsx("div", { className: twMerge("animate-pulse bg-[var(--color-bg-secondary)] rounded-md", className) }));
|
|
10
|
-
};
|