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