@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
JavaScript
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(
` (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
};