UNPKG

tss-react

Version:

Type safe CSS-in-JS API heavily inspired by react-jss

100 lines (99 loc) 4.14 kB
import { classnames } from "./tools/classnames"; import { serializeStyles } from "@emotion/serialize"; import { insertStyles, getRegisteredStyles } from "@emotion/utils"; import { useGuaranteedMemo } from "./tools/useGuaranteedMemo"; import { matchCSSObject } from "./types"; export const { createCssAndCx } = (() => { function merge(registered, css, className) { const registeredStyles = []; const rawClassName = getRegisteredStyles(registered, registeredStyles, className); if (registeredStyles.length < 2) { return className; } return rawClassName + css(registeredStyles); } function createCssAndCx(params) { const { cache } = params; const css = (...args) => { const serialized = serializeStyles(args, cache.registered); insertStyles(cache, serialized, false); const className = `${cache.key}-${serialized.name}`; scope: { const arg = args[0]; if (!matchCSSObject(arg)) { break scope; } increaseSpecificityToTakePrecedenceOverMediaQueries.saveClassNameCSSObjectMapping(cache, className, arg); } return className; }; const cx = (...args) => { const className = classnames(args); const feat27FixedClassnames = increaseSpecificityToTakePrecedenceOverMediaQueries.fixClassName(cache, className, css); return merge(cache.registered, css, feat27FixedClassnames); //return merge(cache.registered, css, className); }; return { css, cx }; } return { createCssAndCx }; })(); export function createUseCssAndCx(params) { const { useCache } = params; function useCssAndCx() { const cache = useCache(); const { css, cx } = useGuaranteedMemo(() => createCssAndCx({ cache }), [cache]); return { css, cx }; } return { useCssAndCx }; } // https://github.com/garronej/tss-react/issues/27 const increaseSpecificityToTakePrecedenceOverMediaQueries = (() => { const cssObjectMapByCache = new WeakMap(); return { "saveClassNameCSSObjectMapping": (cache, className, cssObject) => { let cssObjectMap = cssObjectMapByCache.get(cache); if (cssObjectMap === undefined) { cssObjectMap = new Map(); cssObjectMapByCache.set(cache, cssObjectMap); } cssObjectMap.set(className, cssObject); }, "fixClassName": (() => { function fix(classNameCSSObjects) { let isThereAnyMediaQueriesInPreviousClasses = false; return classNameCSSObjects.map(([className, cssObject]) => { if (cssObject === undefined) { return className; } let out; if (!isThereAnyMediaQueriesInPreviousClasses) { out = className; for (const key in cssObject) { if (key.startsWith("@media")) { isThereAnyMediaQueriesInPreviousClasses = true; break; } } } else { out = { "&&": cssObject }; } return out; }); } return (cache, className, css) => { const cssObjectMap = cssObjectMapByCache.get(cache); return classnames(fix(className .split(" ") .map(className => [ className, cssObjectMap === null || cssObjectMap === void 0 ? void 0 : cssObjectMap.get(className) ])).map(classNameOrCSSObject => typeof classNameOrCSSObject === "string" ? classNameOrCSSObject : css(classNameOrCSSObject))); }; })() }; })();