// @ts-check const KeyQuery = "@"; const KeyPseudo = ":"; const KeyChild = "."; const KeyGroup = "^"; /** * @typedef { Partial & { * [key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles; * } & { * [key in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[key] | CSSStyleDeclaration[key][] * }} UserStyles */ /** @typedef {Record & { global?: UserStyles }} UserSheet */ /** * @template {UserSheet} T * @typedef {keyof T | (string & {})} ValidSelectors */ /** * @template {UserSheet} T * @param {T} sheet * @returns {((...selectors: (keyof T)[]) => string) & { css: string }} */ const createCss = (sheet) => { let i = 0; const id = i ? "_" + i : ""; i++; const Tier = (selector, obj) => { const styles = Object.keys(obj).map((key) => { const value = obj[key]; switch (key[0]) { case KeyQuery: return Tier(`@media(max-width:${key.substring(KeyQuery.length)})`, value); case KeyPseudo: return Tier(`&${key}`, value); case KeyChild: return Tier(`${key}`, value); case KeyGroup: return Tier(`&:hover .${key.substring(KeyGroup.length)}`, value); } return `${key.replace(/([a-z])([A-Z])/g, '$1-$2')}: ${value};`; }); return `${selector}{${styles.join("\n")}}`; }; const css = Object.keys(sheet).map(key => Tier("." + key, sheet[key])).join("\n"); globalThis.document?.head.insertAdjacentHTML("beforeend", ``); /** @type {(...args: (keyof T)[]) => string} */ const classes = (...args) => { /** @type {(needle: string, str: string) => string} */ const extractLast = (needle, str) => { const ind = str.lastIndexOf(needle) + needle.length; return ind ? str.substring(ind) : str; }; return args.map(arg => extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id + " ") + id; }; classes.css = css; return classes; }; export default createCss;