gale/gale.tsx

102 lines
2.9 KiB
TypeScript
Raw Normal View History

2024-04-28 22:21:18 -04:00
const typeface = {
sans: "sans serif",
serif: "Times New Roman"
};
const sizes = {
small: "1rem",
large: "3rem"
};
const colors = {
red: "#ff2200",
blue: "#0022ff"
};
2024-06-07 12:03:46 -04:00
const responsive = {
md: "min-width:767px",
lg: "min-width:1024px",
};
2024-04-28 22:21:18 -04:00
2024-05-13 08:42:44 -04:00
2024-08-01 08:23:47 -04:00
let sheet = {insertRule(_:string){}} as CSSStyleSheet;
if(globalThis?.document)
{
const sheetElement = document.createElement("style");
document.head.setAttribute("data-gale", "true");
document.head.appendChild(sheetElement);
sheet = sheetElement.sheet as CSSStyleSheet;
}
2024-05-13 08:42:44 -04:00
const styles = new Map<string, string>();
function Mapper<T extends Record<string, string>>(className:string, propertyName:string, lut:T)
2024-04-28 22:21:18 -04:00
{
2024-06-07 12:03:46 -04:00
const build =(propertyValue:string, customPropertyName?:string):string=>
2024-05-13 08:42:44 -04:00
{
2024-06-07 12:37:02 -04:00
const selector = `${className}-${(customPropertyName||propertyValue as string).replace(/[^a-zA-Z0-9]/g, "")}${activeQuery.val?"_"+activeQuery.key:""}`;
2024-05-11 23:33:50 -04:00
const check = styles.get(selector);
if(!check)
{
2024-05-13 08:42:44 -04:00
const body = `{ ${propertyName}:${propertyValue}; }`;
2024-08-01 08:23:47 -04:00
const rules = activeQuery.val ? `{ @media(${activeQuery.val})${body}}` : body
styles.set(selector, rules);
sheet.insertRule(selector + " " + rules);
2024-05-11 23:33:50 -04:00
}
return selector;
2024-05-13 08:42:44 -04:00
}
type UseCustom = (custom:string)=>string;
2024-06-07 12:03:46 -04:00
return new Proxy(((override:string)=>build(override)) as UseCustom,
2024-05-13 08:42:44 -04:00
{
2024-06-07 12:03:46 -04:00
get(_, prop){
2024-05-13 08:42:44 -04:00
2024-06-07 12:03:46 -04:00
return build(lut[prop as string], prop as string);
2024-05-13 08:42:44 -04:00
}
}
) as T & UseCustom;
}
2024-06-07 12:03:46 -04:00
function MapperQuery<T extends Record<string, string>>(lut:T)
2024-05-13 08:42:44 -04:00
{
2024-06-07 12:03:46 -04:00
type UseCustom = (custom:string)=>QueryInvoker;
return new Proxy(((override:string)=>Query(override, override)) as UseCustom,
{
get(_, prop:string){
return Query(lut[prop], prop)
}
}
) as Record<keyof T, QueryInvoker> & UseCustom;
2024-04-28 22:21:18 -04:00
}
2024-05-11 23:33:50 -04:00
2024-06-07 12:37:02 -04:00
let activeQuery:ActiveQuery;
type ActiveQuery = {key:string|false, val:string|false};
const activeQueryStack:ActiveQuery[] = [];
2024-06-07 12:03:46 -04:00
type QueryInvoker = (...args:string[])=>string
function Query(amount:string, key?:string):QueryInvoker
2024-04-28 22:21:18 -04:00
{
2024-06-07 12:37:02 -04:00
activeQuery = {key:key||amount, val:amount};
activeQueryStack.push(activeQuery);
2024-06-07 12:03:46 -04:00
return (...args)=> {
2024-06-07 12:37:02 -04:00
activeQueryStack.pop()
activeQuery = activeQueryStack.at(-1) || {key:false, val:false};
2024-05-11 23:33:50 -04:00
return args.join(" ");
2024-04-28 22:21:18 -04:00
}
}
export function config<T>(obj:T)
{
const CSS = {
2024-05-11 23:33:50 -04:00
Sheet()
{
2024-05-13 08:42:44 -04:00
const rules = [];
2024-05-11 23:33:50 -04:00
for(const [key, value] of styles.entries())
{
rules.push(key+value);
}
return rules.join("\n");
},
Face: Mapper("Face", "font-family", {...typeface, ...obj}),
2024-06-07 12:03:46 -04:00
Pad: Mapper("Pad", "padding", sizes),
Q: MapperQuery(responsive)
2024-04-28 22:21:18 -04:00
};
return CSS;
}
export default config({});