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

185 lines (183 loc) 6.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.loadCSSFile = exports.parseCSSVariables = exports.useCSSVariable = exports.CSSVariablesLoader = void 0; // CSS Variables Loader for React Native Bootstrap 5 const react_1 = __importStar(require("react")); const react_native_1 = require("react-native"); // Default CSS imports - only on web let defaultLightCSS = ''; let defaultDarkCSS = ''; if (react_native_1.Platform.OS === 'web') { try { defaultLightCSS = require('../styles/bootstrap-light.css'); defaultDarkCSS = require('../styles/bootstrap-dark.css'); } catch (e) { // CSS files might not be available in non-web environments } } /** * Component to load CSS variables for web platform * On native platforms, this component does nothing */ const CSSVariablesLoader = ({ isDarkMode, customLightCSS, customDarkCSS, }) => { const styleRef = (0, react_1.useRef)(null); (0, react_1.useEffect)(() => { // Only apply CSS on web platform if (react_native_1.Platform.OS !== 'web') { return; } // Type guard for web environment if (typeof document !== 'undefined') { // Remove existing style element if any if (styleRef.current && document.head.contains(styleRef.current)) { try { document.head.removeChild(styleRef.current); } catch (e) { // Ignore if element was already removed } styleRef.current = null; } // Create new style element const style = document.createElement('style'); style.type = 'text/css'; style.setAttribute('data-bootstrap-variables', 'true'); // Get the appropriate CSS content const lightCSS = customLightCSS || defaultLightCSS; const darkCSS = customDarkCSS || defaultDarkCSS; // Combine light and dark CSS const cssContent = ` /* Bootstrap 5.3 CSS Variables for React Native */ ${lightCSS} /* Dark mode styles */ ${darkCSS} `; // Apply CSS content style.innerHTML = cssContent; document.head.appendChild(style); styleRef.current = style; // Set data-bs-theme attribute on root element const root = document.documentElement; root.setAttribute('data-bs-theme', isDarkMode ? 'dark' : 'light'); // Cleanup function return () => { if (styleRef.current && typeof document !== 'undefined' && document.head.contains(styleRef.current)) { try { document.head.removeChild(styleRef.current); } catch (e) { // Ignore if element was already removed } styleRef.current = null; } }; } return undefined; }, [isDarkMode, customLightCSS, customDarkCSS]); // Return null as this component doesn't render anything return null; }; exports.CSSVariablesLoader = CSSVariablesLoader; /** * Hook to get CSS variable value * Only works on web platform */ const useCSSVariable = (variableName) => { if (react_native_1.Platform.OS !== 'web') { return undefined; } const [value, setValue] = react_1.default.useState(); (0, react_1.useEffect)(() => { if (typeof window !== 'undefined' && typeof getComputedStyle !== 'undefined') { const computedValue = getComputedStyle(document.documentElement) .getPropertyValue(variableName) .trim(); setValue(computedValue || undefined); } }, [variableName]); return value; }; exports.useCSSVariable = useCSSVariable; /** * Utility to parse CSS variables into React Native styles */ const parseCSSVariables = (cssContent) => { const variables = {}; const regex = /--([\w-]+):\s*([^;]+);/g; let match; while ((match = regex.exec(cssContent)) !== null) { const [, name, value] = match; const camelCaseName = name.replace(/-([a-z])/g, (g) => g[1].toUpperCase()); // Convert CSS values to React Native compatible values if (value.includes('rem')) { // Convert rem to pixels (assuming 1rem = 16px) const numValue = parseFloat(value); variables[camelCaseName] = numValue * 16; } else if (value.includes('px')) { variables[camelCaseName] = parseFloat(value); } else if (value.includes('rgb')) { // Keep RGB values as strings for now variables[camelCaseName] = value.trim(); } else { variables[camelCaseName] = value.trim(); } } return variables; }; exports.parseCSSVariables = parseCSSVariables; /** * Load custom CSS file content * This is a helper for users who want to provide custom CSS files */ const loadCSSFile = async (filePath) => { if (react_native_1.Platform.OS === 'web') { try { const response = await fetch(filePath); return await response.text(); } catch (error) { console.error('Failed to load CSS file:', error); return ''; } } // For native platforms, return empty string return ''; }; exports.loadCSSFile = loadCSSFile;