UNPKG

@kuma-ui/sheet

Version:

🐻 Kuma UI is a utility-first, zero-runtime CSS-in-JS library that offers an outstanding developer experience and optimized performance.

141 lines (138 loc) 4.14 kB
import { generateHash } from "./chunk-I7HLEBXK.mjs"; import { applyT, theme } from "./chunk-HGADYMTV.mjs"; import { removeSpacesAroundCssPropertyValues, removeSpacesExceptInProperties } from "./chunk-SJVR7MXP.mjs"; // src/sheet.ts import { compile, serialize, stringify } from "stylis"; var Sheet = class _Sheet { static instance; base; responsive; pseudo; css; constructor() { this.base = []; this.responsive = []; this.pseudo = []; this.css = []; } static getInstance() { if (!_Sheet.instance) { _Sheet.instance = new _Sheet(); } return _Sheet.instance; } static getClassNamePrefix(isDynamic = false) { if (process.env.NODE_ENV === "production") { const userPrefix = process.env.KUMA_CLASS_NAME_PREFIX; return userPrefix ? `${userPrefix}-` : "kuma-"; } return isDynamic ? "\u{1F984}-" : "\u{1F43B}-"; } addRule(style, isDynamic = false) { const className = _Sheet.getClassNamePrefix(isDynamic) + generateHash(JSON.stringify(style)); this._addBaseRule(className, this._processCSS(style.base)); for (const [breakpoint, css] of Object.entries(style.responsive)) { this._addMediaRule( className, this._processCSS(css), this._processCSS(breakpoint) ); } for (const [_, pseudo] of Object.entries(style.pseudo)) { this._addPseudoRule(className, pseudo); } return className; } _addBaseRule(className, css) { const minifiedCss = removeSpacesAroundCssPropertyValues(css); this.base.push(`.${className}{${minifiedCss}}`); } _addMediaRule(className, css, breakpoint) { const minifiedCss = removeSpacesAroundCssPropertyValues(css); const mediaCss = removeSpacesExceptInProperties( `@media (min-width: ${breakpoint}) { .${className} { ${minifiedCss} } }` ); this.responsive.push(mediaCss); } _addPseudoRule(className, pseudo) { const css = removeSpacesAroundCssPropertyValues( this._processCSS(pseudo.base) ); const pseudoCss = removeSpacesExceptInProperties( `.${className}${pseudo.key} { ${css} }` ); this.pseudo.push(pseudoCss); for (const [breakpoint, _css] of Object.entries(pseudo.responsive)) { this._addMediaRule( `${className}${pseudo.key}`, this._processCSS(_css), this._processCSS(breakpoint) ); } } _processCSS(css) { const placeholders = theme.getPlaceholders(); return applyT(css, placeholders); } /** * parseCSS takes in raw CSS and parses it to valid CSS using Stylis. * It's useful for handling complex CSS such as media queries and pseudo selectors. */ parseCSS(style) { style = this._processCSS(style); const id = _Sheet.getClassNamePrefix() + generateHash(style); const elements = []; compile(`.${id}{${style}}`).forEach((element) => { const { breakpoints } = theme.getUserTheme(); if (element.type === "@media") { const props = Array.isArray(element.props) ? element.props : [element.props]; const newProps = []; let newValue = element.value; for (const key in breakpoints) { newValue = newValue.replaceAll(key, breakpoints[key]); } props.forEach((prop) => { for (const key in breakpoints) { newProps.push(prop.replaceAll(key, breakpoints[key])); break; } }); element.props = newProps; element.value = newValue; } elements.push(element); }); const css = serialize(elements, stringify); this.css.push(css); return id; } removeDuplicates() { this.base = [...new Set(this.base)]; this.responsive = [...new Set(this.responsive)]; this.pseudo = [...new Set(this.pseudo)]; this.css = [...new Set(this.css)]; } getCSS() { this.removeDuplicates(); return this.base.join("") + this.responsive.join("") + this.pseudo.join("") + this.css.join(""); } reset() { this.base = []; this.responsive = []; this.pseudo = []; this.css = []; } }; var sheet = Sheet.getInstance(); export { Sheet, sheet };