UNPKG

@onesy/style-react

Version:

Onesy CSS in JS styling solution for React

193 lines (178 loc) 7.59 kB
import _extends from "@babel/runtime/helpers/extends"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; const _excluded = ["root", "value", "addCssVariables", "children"]; import React from 'react'; import is from '@onesy/utils/is'; import merge from '@onesy/utils/merge'; import hash from '@onesy/utils/hash'; import isEnvironment from '@onesy/utils/isEnvironment'; import { OnesyTheme, classNames } from '@onesy/style'; import ThemeContext from './Context'; import useOnesyTheme from './useOnesyTheme'; const l = value => value; const hashValue = value => { const allowed = ['direction', 'preference', 'mode', 'palette', 'shape', 'breakpoints', 'space', 'shadows', 'typography', 'transitions', 'z_index']; const valueNew = {}; Object.keys(value).filter(item => allowed.includes(item)).forEach(item => valueNew[item] = value[item]); return hash(valueNew); }; const resolveValue = value => { const notAllowed = ['subscriptions', 'id', 'element', 'updateWithRerender']; const valueNew = {}; Object.keys(value).filter(item => !notAllowed.includes(item)).forEach(item => valueNew[item] = value[item]); return valueNew; }; const Theme = /*#__PURE__*/React.forwardRef((props, ref) => { const [init, setInit] = React.useState(false); const { root = false, value: valueLocal = {}, addCssVariables = true, children } = props, other = _objectWithoutProperties(props, _excluded); const refs = { root: React.useRef(undefined), init: React.useRef(undefined), id: React.useId(), styleSheet: React.useRef(undefined) }; refs.init.current = init; const valueParent = useOnesyTheme() || {}; const [value, setValue] = React.useState(() => new OnesyTheme(merge(resolveValue(is('function', valueLocal) ? valueLocal(valueParent) : valueLocal), resolveValue(valueParent), { copy: true }))); const addCssVariablesMethod = React.useCallback(() => { if (!refs.styleSheet.current) { refs.styleSheet.current = window.document.createElement('style'); refs.styleSheet.current.setAttribute('data-onesy', 'true'); refs.styleSheet.current.setAttribute('data-version', 'static'); refs.styleSheet.current.setAttribute('data-name', 'vars'); window.document.head.append(refs.styleSheet.current); } const values = []; const prefix = 'onesy'; // Palette // Color Object.keys(value.palette.color).forEach(item => { Object.keys(value.palette.color[item]).forEach(itemValue => { values.push(`--${prefix}-palette-color-${item}-${itemValue}: ${value.palette.color[item][itemValue]}`); }); }); // Text Object.keys(value.palette.text).filter(item => !['active', 'divider', 'disabled', 'hover', 'focus', 'selected'].includes(item)).forEach(item => { Object.keys(value.palette.text[item]).forEach(itemValue => { values.push(`--${prefix}-palette-text-${item}-${itemValue}: ${value.palette.text[item][itemValue]}`); }); }); Object.keys(value.palette.text).filter(item => ['active', 'divider', 'disabled', 'hover', 'focus', 'selected'].includes(item)).forEach(item => { values.push(`--${prefix}-palette-text-${item}: ${value.palette.text[item]}`); }); // Background Object.keys(value.palette.background).forEach(item => { Object.keys(value.palette.background[item]).forEach(itemValue => { values.push(`--${prefix}-palette-background-${item}-${itemValue}: ${value.palette.background[item][itemValue]}`); }); }); // Visual contrast Object.keys(value.palette.visual_contrast).forEach(item => { Object.keys(value.palette.visual_contrast[item].opacity).forEach(itemValue => { values.push(`--${prefix}-palette-visual-contrast-${item}-opacity-${itemValue}: ${value.palette.visual_contrast[item].opacity[itemValue]}`); }); }); // Shape values.push(`--${prefix}-shape-radius-unit: ${value.shape.radius.unit}`); Object.keys(value.shape.radius.values).forEach(item => { values.push(`--${prefix}-shape-radius-values-${item}: ${value.shape.radius.values[item]}`); }); // Space values.push(`--${prefix}-space-unit: ${value.space.unit}`); Object.keys(value.space.values).forEach(item => { values.push(`--${prefix}-space-values-${item}: ${value.space.values[item]}`); }); // Shadows Object.keys(value.shadows.values).forEach(item => { Object.keys(value.shadows.values[item]).forEach(itemValue => { values.push(`--${prefix}-shadows-${item}-${itemValue}: ${value.shadows.values[item][itemValue]}`); }); }); // Typography Object.keys(value.typography.font_family).forEach(item => values.push(`--${prefix}-typography-font-family-${item}: ${value.typography.font_family[item]}`)); values.push(`--${prefix}-typography-font-size-html: ${value.typography.font_size.html}`); values.push(`--${prefix}-typography-unit: ${value.typography.unit}`); // Transitions Object.keys(value.transitions.duration).forEach(item => values.push(`--${prefix}-transitions-duration-${item}: ${value.transitions.duration[item]}`)); Object.keys(value.transitions.timing_function).forEach(item => values.push(`--${prefix}-transitions-timing-function-${item}: ${value.transitions.timing_function[item]}`)); // zIndex Object.keys(value.z_index).forEach(item => values.push(`--${prefix}-z-index-${item}: ${value.z_index[item]}`)); // Add to styleSheet innerHTML refs.styleSheet.current.innerHTML = ` ${refs.root.current ? `#${refs.id}` : ':root'} { ${values.map(item => `\t${item};`).join('\n')} } `; }, [value]); React.useEffect(() => { if (refs.root.current) { const onesyTheme = new OnesyTheme(value, { element: refs.root.current }); onesyTheme.id = value.id; onesyTheme.subscriptions = value.subscriptions; // Init setValue(onesyTheme); } setInit(true); }, []); React.useEffect(() => { addCssVariablesMethod(); }, [refs.root.current, valueParent, value]); React.useEffect(() => { if (init) { value.update(merge(resolveValue(is('function', valueLocal) ? valueLocal(valueParent) : valueLocal), resolveValue(valueParent), { copy: true })); const onesyTheme = new OnesyTheme(value, { element: refs.root?.current }); onesyTheme.id = value.id; onesyTheme.subscriptions = value.subscriptions; setValue(onesyTheme); } }, [hashValue(valueLocal), valueParent?.palette?.light]); const update = updateValue => { if (updateValue !== undefined) { // Update value.update(updateValue); const onesyTheme = new OnesyTheme(value, { element: refs.root?.current || isEnvironment('browser') && window.document.body }); onesyTheme.id = value.id; onesyTheme.subscriptions = value.subscriptions; // Init setValue(onesyTheme); return value; } }; // Update method value.updateWithRerender = update; // locale method value.l = value.l || l; if (root) { return /*#__PURE__*/React.createElement(ThemeContext.Provider, { value: value }, /*#__PURE__*/React.createElement("div", _extends({ ref: item => { refs.root.current = item; if (ref?.current) ref.current = item; } }, other, { id: refs.id, className: classNames(other?.className) }), children)); } return /*#__PURE__*/React.createElement(ThemeContext.Provider, { value: value }, children); }); export default Theme;