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