flysoft-react-ui 0.2.7 → 0.2.9
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/README.md +22 -0
- package/dist/contexts/ThemeContext.d.ts.map +1 -1
- package/dist/contexts/ThemeContext.js +42 -14
- package/dist/index.css +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,28 @@ npx tailwindcss init -p
|
|
|
123
123
|
|
|
124
124
|
La librería incluye FontAwesome 5. Si quieres usar tu propia instalación, puedes sobrescribir los estilos.
|
|
125
125
|
|
|
126
|
+
**⚠️ Importante:** Si usas FontAwesome en tu proyecto, asegúrate de:
|
|
127
|
+
|
|
128
|
+
1. Importar los estilos de `flysoft-react-ui` **después** de FontAwesome (si es posible)
|
|
129
|
+
2. Usar `ThemeProvider` para envolver tu aplicación (esto evita conflictos de variables CSS)
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
// Orden recomendado de importación
|
|
133
|
+
import "fontawesome/css/all.min.css"; // Primero FontAwesome
|
|
134
|
+
import "flysoft-react-ui/styles"; // Luego flysoft-react-ui
|
|
135
|
+
|
|
136
|
+
// En tu App.tsx
|
|
137
|
+
import { ThemeProvider } from "flysoft-react-ui";
|
|
138
|
+
|
|
139
|
+
function App() {
|
|
140
|
+
return (
|
|
141
|
+
<ThemeProvider initialTheme="light">{/* Tu aplicación */}</ThemeProvider>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
El `ThemeProvider` aplica automáticamente las variables CSS con mayor especificidad, evitando que FontAwesome sobrescriba los colores del tema (como `gray-200`).
|
|
147
|
+
|
|
126
148
|
## 🎨 Sistema de Temas
|
|
127
149
|
|
|
128
150
|
Flysoft React UI incluye un sistema completo de temas personalizables que permite cambiar dinámicamente la apariencia de todos los componentes.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeContext.d.ts","sourceRoot":"","sources":["../../src/contexts/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ThemeContext.d.ts","sourceRoot":"","sources":["../../src/contexts/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EASZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA2CvD,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6LtD,CAAC;AAIF,eAAO,MAAM,QAAQ,QAAO,gBAM3B,CAAC;AAIF,eAAO,MAAM,eAAe,eAG3B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React, { createContext, useContext, useEffect, useMemo, useState, } from "react";
|
|
2
|
+
import React, { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
3
3
|
import { themes, defaultTheme } from "./presets";
|
|
4
4
|
const ThemeContext = createContext(undefined);
|
|
5
5
|
const toKebabCase = (value) => value.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
@@ -67,40 +67,55 @@ export const ThemeProvider = ({ children, initialTheme = "light", storageKey = "
|
|
|
67
67
|
return getInitialTheme();
|
|
68
68
|
});
|
|
69
69
|
const [currentThemeName, setCurrentThemeName] = useState(currentTheme.name);
|
|
70
|
+
const containerRef = useRef(null);
|
|
70
71
|
// Function to apply theme to CSS variables
|
|
71
|
-
const applyThemeToCSS = (theme) => {
|
|
72
|
+
const applyThemeToCSS = (theme, container) => {
|
|
72
73
|
if (typeof document === "undefined")
|
|
73
74
|
return;
|
|
74
|
-
|
|
75
|
+
// Priorizar el contenedor si está disponible, sino usar :root
|
|
76
|
+
const target = container || document.documentElement;
|
|
75
77
|
// Apply color variables
|
|
76
78
|
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
77
79
|
const cssVarName = `--flysoft-${key
|
|
78
80
|
.replace(/([A-Z])/g, "-$1")
|
|
79
81
|
.toLowerCase()}`;
|
|
80
|
-
|
|
82
|
+
target.style.setProperty(cssVarName, value);
|
|
83
|
+
// También sobrescribir variables genéricas que FontAwesome pueda usar
|
|
84
|
+
// Esto asegura que nuestras variables tengan prioridad
|
|
85
|
+
if (key.startsWith("gray")) {
|
|
86
|
+
const genericVarName = `--color-${key
|
|
87
|
+
.replace(/([A-Z])/g, "-$1")
|
|
88
|
+
.toLowerCase()}`;
|
|
89
|
+
target.style.setProperty(genericVarName, value);
|
|
90
|
+
}
|
|
81
91
|
});
|
|
82
92
|
// Apply shadow variables
|
|
83
93
|
Object.entries(theme.shadows).forEach(([key, value]) => {
|
|
84
94
|
const cssVarName = `--flysoft-shadow-${key}`;
|
|
85
|
-
|
|
95
|
+
target.style.setProperty(cssVarName, value);
|
|
86
96
|
});
|
|
87
97
|
// Apply radius variables
|
|
88
98
|
Object.entries(theme.radius).forEach(([key, value]) => {
|
|
89
99
|
const cssVarName = `--flysoft-radius-${key}`;
|
|
90
|
-
|
|
100
|
+
target.style.setProperty(cssVarName, value);
|
|
91
101
|
});
|
|
92
102
|
// Apply spacing variables
|
|
93
103
|
Object.entries(theme.spacing).forEach(([key, value]) => {
|
|
94
104
|
const cssVarName = `--flysoft-spacing-${key}`;
|
|
95
|
-
|
|
105
|
+
target.style.setProperty(cssVarName, value);
|
|
96
106
|
});
|
|
97
107
|
// Apply font variables
|
|
98
108
|
Object.entries(theme.fonts).forEach(([key, value]) => {
|
|
99
109
|
const cssVarName = `--flysoft-font-${key}`;
|
|
100
|
-
|
|
110
|
+
target.style.setProperty(cssVarName, value);
|
|
101
111
|
});
|
|
102
112
|
// Set theme name as data attribute for CSS targeting
|
|
103
|
-
|
|
113
|
+
if (container) {
|
|
114
|
+
container.setAttribute("data-theme", theme.name);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
document.documentElement.setAttribute("data-theme", theme.name);
|
|
118
|
+
}
|
|
104
119
|
// Apply background and text colors to body for better integration
|
|
105
120
|
const body = document.body;
|
|
106
121
|
if (body) {
|
|
@@ -130,16 +145,29 @@ export const ThemeProvider = ({ children, initialTheme = "light", storageKey = "
|
|
|
130
145
|
if (typeof window !== "undefined") {
|
|
131
146
|
localStorage.setItem(storageKey, JSON.stringify(newTheme));
|
|
132
147
|
}
|
|
133
|
-
// Apply to CSS
|
|
134
|
-
applyThemeToCSS(newTheme);
|
|
148
|
+
// Apply to CSS usando el ref si está disponible
|
|
149
|
+
applyThemeToCSS(newTheme, containerRef.current);
|
|
135
150
|
};
|
|
136
151
|
// Function to reset to initial theme (the one passed as initialTheme prop)
|
|
137
152
|
const resetToDefault = () => {
|
|
138
153
|
setTheme(getInitialTheme());
|
|
139
154
|
};
|
|
140
|
-
// Apply theme on mount and when theme changes
|
|
155
|
+
// Apply theme on mount and when theme changes using useLayoutEffect
|
|
156
|
+
// para asegurar que se aplique antes del paint y con mayor prioridad
|
|
157
|
+
useLayoutEffect(() => {
|
|
158
|
+
if (containerRef.current) {
|
|
159
|
+
applyThemeToCSS(currentTheme, containerRef.current);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// Fallback a :root si el contenedor aún no está montado
|
|
163
|
+
applyThemeToCSS(currentTheme);
|
|
164
|
+
}
|
|
165
|
+
}, [currentTheme]);
|
|
166
|
+
// También aplicar después del mount para asegurar que se actualice
|
|
141
167
|
useEffect(() => {
|
|
142
|
-
|
|
168
|
+
if (containerRef.current) {
|
|
169
|
+
applyThemeToCSS(currentTheme, containerRef.current);
|
|
170
|
+
}
|
|
143
171
|
}, [currentTheme]);
|
|
144
172
|
// Check if current theme is dark
|
|
145
173
|
const isDark = currentTheme.name === "dark";
|
|
@@ -152,7 +180,7 @@ export const ThemeProvider = ({ children, initialTheme = "light", storageKey = "
|
|
|
152
180
|
resetToDefault,
|
|
153
181
|
isDark,
|
|
154
182
|
};
|
|
155
|
-
return (_jsx(ThemeContext.Provider, { value: value, children: _jsx("div", { className: "flysoft-theme-reset", style: themeResetStyles, "data-theme": currentTheme.name, children: children }) }));
|
|
183
|
+
return (_jsx(ThemeContext.Provider, { value: value, children: _jsx("div", { ref: containerRef, className: "flysoft-theme-reset", style: themeResetStyles, "data-theme": currentTheme.name, children: children }) }));
|
|
156
184
|
};
|
|
157
185
|
// Hook to use theme context
|
|
158
186
|
// eslint-disable-next-line react-refresh/only-export-components
|