68 lines
2.1 KiB
JavaScript
68 lines
2.1 KiB
JavaScript
// @ts-check
|
|
const KeyQuery = "@";
|
|
const KeyPseudo = ":";
|
|
const KeyChild = ".";
|
|
const KeyGroup = "^";
|
|
|
|
/**
|
|
* @typedef { Partial<CSSStyleDeclaration> & {
|
|
* [key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles;
|
|
* } & {
|
|
* [key in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[key] | CSSStyleDeclaration[key][]
|
|
* }} UserStyles
|
|
*/
|
|
|
|
/** @typedef {Record<string, UserStyles> & { global?: UserStyles }} UserSheet */
|
|
|
|
/**
|
|
* @template {UserSheet} T
|
|
* @typedef {keyof T | (string & {})} ValidSelectors<T>
|
|
*/
|
|
|
|
/**
|
|
* @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", `<style data-sheet="${i}">${css}</style>`);
|
|
|
|
/** @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;
|