UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

226 lines (222 loc) • 9.48 kB
"use client"; import { utils_exports } from "../../utils/index.js"; import { useSystem } from "../system/system-provider.js"; import { useColorSchemeContext } from "../system/styled.js"; import { conditions, getCondition } from "../css/conditions.js"; import { mergeCSS } from "../css/merge-css.js"; import { isEqualProps } from "./props.js"; import { useRef } from "react"; //#region src/core/components/use-component-style.ts function getSelectorStyle(selectors, style) { return selectors.reduceRight((prev, key) => key ? { [key]: prev } : prev, style); } function getStyle(style) { return function({ hasSlot = false, selectors = [] }) { if (!style || (0, utils_exports.isEmptyObject)(style)) return; if (hasSlot) return Object.fromEntries(Object.entries(style).map(([name, style$1]) => { if (selectors.length) return [name, getSelectorStyle(selectors, style$1 ?? {})]; else return [name, style$1]; })); else if (selectors.length) return getSelectorStyle(selectors, style); else return style; }; } function getColorModeStyle(value, mergedStyle) { return function({ selectors = [],...rest }) { const [lightValue, darkValue] = value; return (0, utils_exports.merge)(getModifierStyle(lightValue, mergedStyle)({ ...rest, selectors }), getModifierStyle(darkValue, mergedStyle)({ ...rest, selectors: [...selectors, conditions._dark] })); }; } function getConditionStyle(value, mergedStyle) { return function(options) { const { isResponsiveKey, queries = [], selectors = [] } = options; const conditionalKeys = Object.keys(value).filter((key) => !isResponsiveKey?.(key)); return (0, utils_exports.merge)(queries.reduce((prev, { breakpoint, query }) => { if (!(0, utils_exports.isUndefined)(value[breakpoint])) prev = (0, utils_exports.merge)(prev, getModifierStyle(value[breakpoint], mergedStyle)({ ...options, selectors: [...selectors, query] })); return prev; }, {}), conditionalKeys.reduce((prev, key) => { prev = (0, utils_exports.merge)(prev, getModifierStyle(value[key], mergedStyle)({ ...options, selectors: [...selectors, getCondition(key)] })); return prev; }, {})); }; } function getModifierStyle(value, mergedStyle) { return function(options) { let style = void 0; if (!value) return style; if ((0, utils_exports.isArray)(value)) style = getColorModeStyle(value, mergedStyle)(options); else if ((0, utils_exports.isObject)(value)) style = getConditionStyle(value, mergedStyle)(options); else style = getStyle(mergedStyle[value])(options); return style; }; } function getPropStyle(props, propVariants, style = {}) { const variants = Object.entries(propVariants); return function(options) { if (!variants.length) return style; variants.forEach(([name, variants$1]) => { const prop = props[name]; if (prop) { const propStyle = getModifierStyle(prop, variants$1)(options); if (propStyle) style = (0, utils_exports.merge)(style, wrapStyle("props", propStyle)(options)); } else if (Object.keys(variants$1).every((key) => (0, utils_exports.isBooleanish)(key))) { const propStyle = getModifierStyle("false", variants$1)(options); if (propStyle) style = (0, utils_exports.merge)(style, wrapStyle("props", propStyle)(options)); } }); return style; }; } function getCompoundStyle(props, compounds, style = {}) { return function(options) { if (!compounds.length) return style; compounds.forEach(({ css, layer,...rest }) => { const conditions$1 = Object.entries(rest); if (!conditions$1.length) return; if (!conditions$1.every(([key, value]) => (0, utils_exports.isArray)(value) ? value.includes(props[key]) : (0, utils_exports.isRegExp)(value) ? value.test(props[key]) : props[key] === value)) return; style = (0, utils_exports.merge)(style, wrapStyle(layer ?? "compounds", css)(options)); }); return style; }; } function getSlotClassName(className, slot) { if (!className || !slot) return className; if ((0, utils_exports.isArray)(slot)) { const [element, modifier] = slot.map((value) => (0, utils_exports.toKebabCase)(value)); return (0, utils_exports.cx)((0, utils_exports.bem)(className, element), (0, utils_exports.bem)(className, element, modifier)); } else if ((0, utils_exports.isObject)(slot)) { const [element, modifier] = (0, utils_exports.toArray)(slot.slot).map((value) => (0, utils_exports.toKebabCase)(value)); return (0, utils_exports.cx)((0, utils_exports.bem)(className, element), (0, utils_exports.bem)(className, element, modifier)); } else return (0, utils_exports.bem)(className, (0, utils_exports.toKebabCase)(slot)); } function mergeSlotCSS(slot, style, css) { if (!style || !slot) return css; const temp = []; if ((0, utils_exports.isArray)(slot)) temp.push(...slot.map((slot$1) => style[slot$1])); else if ((0, utils_exports.isObject)(slot)) if ((0, utils_exports.isArray)(slot.slot)) temp.push(...slot.slot.map((slot$1) => style[slot$1])); else temp.push(style[slot.slot]); else temp.push(style[slot]); if (css) temp.push(...(0, utils_exports.toArray)(css)); const result = (0, utils_exports.filterEmpty)(temp); return !!result.length ? result : void 0; } function omitThemeProps(props, omitKeys = [], transferProps) { if (transferProps) omitKeys = omitKeys.filter((key) => !transferProps.includes(key)); return (0, utils_exports.omitObject)(props, omitKeys); } function wrapStyle(layer, style) { return function({ hasSlot, wrap }) { if (hasSlot) { if (!style) return void 0; return Object.fromEntries(Object.entries(style).map(([slot, style$1]) => [slot, wrap?.(layer, style$1) ?? style$1])); } else return wrap?.(layer, style) ?? style; }; } function getHasAtRuleStyle(css) { return (getAtRule) => { let hasVariant = false; let hasSize = false; if (!css || !getAtRule) return { hasSize, hasVariant }; const variantAtRule = getAtRule("variant"); const sizeAtRule = getAtRule("size"); css = (0, utils_exports.toArray)(css); css.forEach((css$1) => { const keys = Object.keys(css$1); if (keys.includes(variantAtRule)) hasVariant = true; if (keys.includes(sizeAtRule)) hasSize = true; }); return { hasSize, hasVariant }; }; } function mergeDefaultProps(defaultProps, props) { return Object.entries(defaultProps ?? {}).reduce((prev, [key, value]) => { prev[key] ??= value; return prev; }, props); } function useStyle(props, { className: defaultClassName, style: componentStyle, hasSlot, slot, transferProps } = {}) { const system = useSystem(); const { getAtRule, wrap } = system.layers; const rootColorScheme = useColorSchemeContext(); const options = { ...system.breakpoints, hasSlot, wrap }; const propsRef = useRef({}); const mergedPropsRef = useRef({}); const styleRef = useRef(void 0); if (componentStyle && !!Object.keys(componentStyle).length) { const { className: customClassName, base, compounds, props: propVariants, sizes, variants, defaultProps: { colorScheme: defaultColorScheme,...defaultProps } = {} } = componentStyle; const colorScheme = props.colorScheme ?? rootColorScheme ?? defaultColorScheme; const className = (0, utils_exports.cx)(defaultClassName ?? customClassName, props.className); const mergedProps = { ...mergeDefaultProps(defaultProps, props), className, colorScheme }; const omitProps = Object.keys(propVariants ?? {}); const { size, variant } = mergedProps; if (variants) omitProps.push("variant"); if (sizes) omitProps.push("size"); const computedProps = omitThemeProps(mergedProps, omitProps, transferProps); if (!isEqualProps(mergedPropsRef.current, mergedProps, ["css", "children"])) { const { hasSize, hasVariant } = getHasAtRuleStyle(props.css)(getAtRule); let style = {}; if (base) { const baseStyle = getStyle(base)(options); style = (0, utils_exports.merge)(style, wrapStyle("base", baseStyle)(options)); } if (sizes && !hasSize) { const sizeStyle = (0, utils_exports.merge)(sizes.base, getModifierStyle(size, sizes)(options)); style = (0, utils_exports.merge)(style, wrapStyle("size", sizeStyle)(options)); } if (variants && !hasVariant) { const variantStyle = (0, utils_exports.merge)(variants.base, getModifierStyle(variant, variants)(options)); style = (0, utils_exports.merge)(style, wrapStyle("variant", variantStyle)(options)); } if (propVariants) style = getPropStyle(mergedProps, propVariants, style)(options); if (compounds) style = getCompoundStyle(mergedProps, compounds, style)(options); styleRef.current = style; if (hasSlot) computedProps.css = mergeSlotCSS(slot, style, computedProps.css); else computedProps.css = mergeCSS(style, computedProps.css); } else computedProps.css = propsRef.current.css; mergedPropsRef.current = mergedProps; if (!isEqualProps(propsRef.current, computedProps)) propsRef.current = computedProps; } else { const className = (0, utils_exports.cx)(defaultClassName, props.className); if (className) props.className = className; if (!isEqualProps(propsRef.current, props)) propsRef.current = props; } return [styleRef.current ?? {}, propsRef.current]; } function useComponentStyle(props, options = {}) { return useStyle(props, options); } function useComponentSlotStyle(props, options = {}) { return useStyle(props, { ...options, hasSlot: true }); } //#endregion export { getSlotClassName, mergeSlotCSS, useComponentSlotStyle, useComponentStyle }; //# sourceMappingURL=use-component-style.js.map