@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
JavaScript
;
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;