UNPKG

@whitemordred/react-native-bootstrap5

Version:

A complete React Native library that replicates Bootstrap 5.3 with 100% feature parity, full theming support, CSS variables, and dark/light mode

283 lines (282 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useThemePreferences = exports.useThemeStyles = exports.useSystemAppearance = exports.useThemeBreakpoints = exports.useThemeAnimations = exports.useColorUtils = exports.useAdvancedTheme = void 0; const react_1 = require("react"); const react_native_1 = require("react-native"); const themeUtils_1 = require("./themeUtils"); const ThemeProvider_1 = require("./ThemeProvider"); /** * Advanced hook for theme management with persistence and system integration */ const useAdvancedTheme = () => { const { theme, mode, setMode } = (0, ThemeProvider_1.useTheme)(); const [isLoading, setIsLoading] = (0, react_1.useState)(true); const [preferences, setPreferences] = (0, react_1.useState)(null); const [isFollowingSystem, setIsFollowingSystem] = (0, react_1.useState)(false); // Initialize theme manager (0, react_1.useEffect)(() => { const initializeTheme = async () => { try { const initialMode = await themeUtils_1.ThemeManager.initialize(true); const savedPreferences = await themeUtils_1.ThemeStorage.loadPreferences(); setPreferences(savedPreferences); setIsFollowingSystem(themeUtils_1.ThemeManager.isFollowingSystem()); if (mode !== initialMode) { setMode(initialMode); } } catch (error) { console.warn('Failed to initialize theme:', error); } finally { setIsLoading(false); } }; initializeTheme(); // Add theme change listener const removeListener = themeUtils_1.ThemeManager.addListener((newMode) => { setMode(newMode); setIsFollowingSystem(themeUtils_1.ThemeManager.isFollowingSystem()); }); return () => { removeListener(); }; }, []); // Toggle theme mode with animation const toggleMode = (0, react_1.useCallback)(async () => { await themeUtils_1.ThemeManager.toggleMode(); }, []); // Set specific theme mode const setThemeMode = (0, react_1.useCallback)(async (newMode) => { await themeUtils_1.ThemeManager.setMode(newMode, true); }, []); // Follow system theme const followSystemTheme = (0, react_1.useCallback)(async () => { await themeUtils_1.ThemeManager.followSystemTheme(); setIsFollowingSystem(true); }, []); // Stop following system theme const stopFollowingSystem = (0, react_1.useCallback)(() => { themeUtils_1.ThemeManager.stopFollowingSystem(); setIsFollowingSystem(false); }, []); // Save preferences const savePreferences = (0, react_1.useCallback)(async (newPreferences) => { const updatedPreferences = Object.assign(Object.assign({}, preferences), newPreferences); await themeUtils_1.ThemeStorage.savePreferences(updatedPreferences); setPreferences(updatedPreferences); }, [preferences]); // Get system theme const systemTheme = (0, react_1.useMemo)(() => themeUtils_1.SystemTheme.getSystemTheme(), []); // Get system preferences const systemPreferences = (0, react_1.useMemo)(() => ({ prefersReducedMotion: themeUtils_1.SystemTheme.prefersReducedMotion(), prefersHighContrast: themeUtils_1.SystemTheme.prefersHighContrast(), }), []); return { // Theme state theme, mode, isLoading, preferences, // System integration systemTheme, systemPreferences, isFollowingSystem, // Actions toggleMode, setThemeMode, followSystemTheme, stopFollowingSystem, savePreferences, }; }; exports.useAdvancedTheme = useAdvancedTheme; /** * Hook for color utilities and manipulations */ const useColorUtils = () => { const { theme, mode } = (0, ThemeProvider_1.useTheme)(); const colorUtils = (0, react_1.useMemo)(() => ({ // Color manipulation lighten: themeUtils_1.ColorUtils.lighten, darken: themeUtils_1.ColorUtils.darken, hexToRgba: themeUtils_1.ColorUtils.hexToRgba, getContrastColor: themeUtils_1.ColorUtils.getContrastColor, isDark: themeUtils_1.ColorUtils.isDark, generateColorVariations: themeUtils_1.ColorUtils.generateColorVariations, // Theme-aware color helpers getCurrentColor: (colorKey, alpha) => { const colors = mode === 'dark' ? theme.darkColors : theme.colors; const color = colors[colorKey] || colorKey; return alpha !== undefined ? themeUtils_1.ColorUtils.hexToRgba(color, alpha) : color; }, // Generate theme-aware variations getColorVariations: (colorKey) => { const colors = mode === 'dark' ? theme.darkColors : theme.colors; const color = colors[colorKey] || colorKey; return themeUtils_1.ColorUtils.generateColorVariations(color); }, // Get contrast color for current theme getContrastForCurrent: (colorKey) => { const colors = mode === 'dark' ? theme.darkColors : theme.colors; const color = colors[colorKey] || colorKey; return themeUtils_1.ColorUtils.getContrastColor(color); }, }), [theme, mode]); return colorUtils; }; exports.useColorUtils = useColorUtils; /** * Hook for theme animations and transitions */ const useThemeAnimations = () => { const [isTransitioning, setIsTransitioning] = (0, react_1.useState)(false); const createTransition = (0, react_1.useCallback)((duration = 300) => { setIsTransitioning(true); themeUtils_1.ThemeAnimationUtils.createThemeTransition(duration); setTimeout(() => { setIsTransitioning(false); }, duration + 100); }, []); const respectReducedMotion = (0, react_1.useCallback)(() => { themeUtils_1.ThemeAnimationUtils.respectReducedMotion(); }, []); return { isTransitioning, createTransition, respectReducedMotion, }; }; exports.useThemeAnimations = useThemeAnimations; /** * Hook for responsive theme breakpoints */ const useThemeBreakpoints = () => { const { theme } = (0, ThemeProvider_1.useTheme)(); const [windowDimensions, setWindowDimensions] = (0, react_1.useState)({ width: 0, height: 0 }); (0, react_1.useEffect)(() => { // For React Native, we'll use Dimensions API // For web, we'll use window dimensions const updateDimensions = () => { if (react_native_1.Platform.OS === 'web' && typeof globalThis !== 'undefined' && 'window' in globalThis) { const win = globalThis; setWindowDimensions({ width: win.window.innerWidth, height: win.window.innerHeight, }); } else { // React Native Dimensions try { const { Dimensions } = require('react-native'); const dimensions = Dimensions.get('window'); setWindowDimensions(dimensions); } catch (error) { // Fallback } } }; updateDimensions(); if (react_native_1.Platform.OS === 'web' && typeof globalThis !== 'undefined' && 'window' in globalThis) { const win = globalThis; win.window.addEventListener('resize', updateDimensions); return () => win.window.removeEventListener('resize', updateDimensions); } return undefined; }, []); const breakpoints = (0, react_1.useMemo)(() => { const bp = theme.breakpoints; const width = windowDimensions.width; return { current: width >= bp.xl ? 'xl' : width >= bp.lg ? 'lg' : width >= bp.md ? 'md' : width >= bp.sm ? 'sm' : 'xs', isXs: width < bp.sm, isSm: width >= bp.sm && width < bp.md, isMd: width >= bp.md && width < bp.lg, isLg: width >= bp.lg && width < bp.xl, isXl: width >= bp.xl, isUp: (breakpoint) => width >= bp[breakpoint], isDown: (breakpoint) => width < bp[breakpoint], width, height: windowDimensions.height, }; }, [theme.breakpoints, windowDimensions]); return breakpoints; }; exports.useThemeBreakpoints = useThemeBreakpoints; /** * Hook for system appearance changes (React Native specific) */ const useSystemAppearance = () => { const [systemTheme, setSystemTheme] = (0, react_1.useState)(() => react_native_1.Appearance.getColorScheme() === 'dark' ? 'dark' : 'light'); (0, react_1.useEffect)(() => { const subscription = react_native_1.Appearance.addChangeListener((preferences) => { setSystemTheme(preferences.colorScheme === 'dark' ? 'dark' : 'light'); }); return () => subscription === null || subscription === void 0 ? void 0 : subscription.remove(); }, []); return systemTheme; }; exports.useSystemAppearance = useSystemAppearance; /** * Hook for theme-aware styles */ const useThemeStyles = () => { const { theme, mode } = (0, ThemeProvider_1.useTheme)(); const colors = mode === 'dark' ? theme.darkColors : theme.colors; const createStyles = (0, react_1.useCallback)((styleFactory) => { return styleFactory(theme, colors, mode); }, [theme, colors, mode]); return { colors, theme, mode, createStyles, }; }; exports.useThemeStyles = useThemeStyles; /** * Hook for theme preferences management */ const useThemePreferences = () => { const [preferences, setPreferences] = (0, react_1.useState)(null); const [isLoading, setIsLoading] = (0, react_1.useState)(true); (0, react_1.useEffect)(() => { const loadPreferences = async () => { try { const saved = await themeUtils_1.ThemeStorage.loadPreferences(); setPreferences(saved); } catch (error) { console.warn('Failed to load theme preferences:', error); } finally { setIsLoading(false); } }; loadPreferences(); }, []); const updatePreferences = (0, react_1.useCallback)(async (updates) => { if (!preferences) return; const newPreferences = Object.assign(Object.assign({}, preferences), updates); await themeUtils_1.ThemeStorage.savePreferences(newPreferences); setPreferences(newPreferences); }, [preferences]); const resetPreferences = (0, react_1.useCallback)(async () => { await themeUtils_1.ThemeStorage.clearThemeData(); const defaultPrefs = await themeUtils_1.ThemeStorage.loadPreferences(); setPreferences(defaultPrefs); }, []); return { preferences, isLoading, updatePreferences, resetPreferences, }; }; exports.useThemePreferences = useThemePreferences;