UNPKG

optimizely-oui

Version:

Optimizely's Component Library.

59 lines (49 loc) 1.87 kB
import PropTypes from "prop-types"; import forwardRef from "@restart/context/forwardRef"; import React, { useContext } from "react"; const ThemeContext = React.createContext(new Map()); const { Consumer, Provider } = ThemeContext; class ThemeProvider extends React.Component { static propTypes = { children: PropTypes.node, prefixes: PropTypes.object.isRequired, }; constructor(...args) { super(...args); this.prefixes = new Map(); Object.keys(this.props.prefixes).forEach(key => { this.prefixes.set(key, this.props.prefixes[key]); }); } render() { return <Provider value={this.prefixes}>{this.props.children}</Provider>; } } export function useBootstrapPrefix(prefix, defaultPrefix) { const prefixes = useContext(ThemeContext); return prefix || prefixes.get(defaultPrefix) || defaultPrefix; } function createBootstrapComponent(Component, opts) { if (typeof opts === "string") { opts = { prefix: opts }; } const isClassy = Component.prototype && Component.prototype.isReactComponent; // If it's a functional component make sure we don't break it with a ref const { prefix, forwardRefAs = isClassy ? "ref" : "innerRef" } = opts; return forwardRef( ({ ...props }, ref) => { props[forwardRefAs] = ref; const prefixes = useContext(ThemeContext); return ( <Component {...props} // eslint-disable-next-line react/prop-types bsPrefix={props.bsPrefix || prefixes.get(prefix) || prefix} /> ); }, { displayName: `Bootstrap(${Component.displayName || Component.name})` } ); } export { createBootstrapComponent, Consumer as ThemeConsumer }; export default ThemeProvider;