149 lines
4.0 KiB
TypeScript
149 lines
4.0 KiB
TypeScript
// tss.ts
|
|
type PseudoKeys = ["hover"|"before"|"after"] | ["hover", "after"|"before"];
|
|
type ValueSignature = (...args:number[])=>void
|
|
type EnumDefinition<Signature> = [property:string, options:Record<string, string>, values?:Signature];
|
|
type EnumBlock<Signature> = Record<string, EnumDefinition<Signature>>;
|
|
type RecursiveObject<Sig extends ValueSignature, Obj extends EnumBlock<Sig>> =
|
|
{
|
|
[F in keyof Obj]: Obj[F][2] extends Sig ? ((...args:Parameters<Obj[F][2]>)=> RecursiveObject<Sig, Obj>&((...args:PseudoKeys)=>RecursiveObject<Sig, Obj>)&Array<RecursiveObject<Sig, Obj>>)&{
|
|
[E in keyof Obj[F][1]]:RecursiveObject<Sig, Obj>&((...args:PseudoKeys)=>RecursiveObject<Sig, Obj>)&Array<RecursiveObject<Sig, Obj>>
|
|
} :
|
|
{
|
|
[E in keyof Obj[F][1]]:RecursiveObject<Sig, Obj>&((...args:PseudoKeys)=>RecursiveObject<Sig, Obj>)&Array<RecursiveObject<Sig, Obj>>
|
|
}
|
|
}
|
|
|
|
function Block<Signature extends ValueSignature, Fields extends EnumBlock<Signature>>(options:Fields):()=>RecursiveObject<Signature, Fields>
|
|
{
|
|
return ()=>{
|
|
|
|
let pseudo = false;
|
|
let query = false;
|
|
const list = [];
|
|
let fieldLookup = {};
|
|
|
|
const proxyOuter = new Proxy(
|
|
function(...args)
|
|
{
|
|
console.log("outer: core call", ...args)
|
|
if(args.length)
|
|
{
|
|
list.push(`${(pseudo||query) ? "}" : ""} &:${args.join("::")}{`);
|
|
pseudo = true;
|
|
query = false;
|
|
return proxyOuter;
|
|
}
|
|
pseudo && list.push("}");
|
|
query && list.push("}");
|
|
pseudo = false;
|
|
query = false;
|
|
return list;
|
|
},
|
|
{
|
|
get(_target, propName)
|
|
{
|
|
console.log("outer: reading property", propName);
|
|
const sizeCheck = parseInt(propName)
|
|
if(sizeCheck)
|
|
{
|
|
list.push(`${(query) ? "}" : ""} @media(min-width:${sizeCheck}px){`);
|
|
query = true;
|
|
return proxyOuter;
|
|
}
|
|
fieldLookup = options[propName];
|
|
if(fieldLookup)
|
|
{
|
|
list.push(fieldLookup[0]);
|
|
}
|
|
return proxyInner;
|
|
}
|
|
}
|
|
);
|
|
|
|
const proxyInner = new Proxy(
|
|
function(...args)
|
|
{
|
|
console.log("inner: core call", ...args)
|
|
list.push(`:${args.join(" ")};`);
|
|
return proxyOuter;
|
|
},
|
|
{
|
|
get(_target, valName)
|
|
{
|
|
console.log("inner: reading property", valName);
|
|
try
|
|
{
|
|
list.push(`:${fieldLookup[1][valName]};`);
|
|
return proxyOuter;
|
|
}
|
|
catch(e)
|
|
{
|
|
console.warn("someone is trying to stringify a style proxy");
|
|
return ()=>"[StyleProxy]";
|
|
}
|
|
}
|
|
}
|
|
);
|
|
return proxyOuter;
|
|
}
|
|
}
|
|
|
|
const styles = Block(
|
|
{
|
|
Pos:["position", { Abs:"absolute", Rel:"relative" }],
|
|
Display:[ "display", { Flex:"flex", Grid:"grid", None:"none", Block:"block", InlineBlock:"inline-block" }],
|
|
Left:[ "left", { Auto:"auto" }, (left)=>{}]
|
|
}
|
|
);
|
|
|
|
let masterSheet = [];
|
|
export function Sheet<UserClasses extends Record<string, (CSS:ReturnType<typeof styles>)=>void >>(userClasses:UserClasses):{[Class in keyof UserClasses]:string}
|
|
{
|
|
const hash = Math.floor(Math.random()*10000);
|
|
return new Proxy(function(){}, {get(_target, className){
|
|
console.log("sheet accessor", className);
|
|
const lookup = userClasses[className];
|
|
if(typeof lookup == "string")
|
|
{
|
|
return lookup;
|
|
}
|
|
else
|
|
{
|
|
const skewer = styles();
|
|
lookup(skewer);
|
|
const name = `.${className}_${hash}`;
|
|
masterSheet.push( `${name}{ ${skewer().join("")} }` );
|
|
userClasses[className] = name;
|
|
return name;
|
|
}
|
|
}});
|
|
}
|
|
|
|
export function Divulge()
|
|
{
|
|
return masterSheet.join("\n");
|
|
}
|
|
|
|
|
|
/////// testing: ////////
|
|
|
|
const sheet = Sheet({
|
|
SpecialLink(styles)
|
|
{
|
|
styles
|
|
.Pos.Abs
|
|
("hover","after")
|
|
.Pos.Rel
|
|
.Left(20)
|
|
[512]
|
|
.Left(100)
|
|
},
|
|
Profile(styles)
|
|
{
|
|
styles.Display.Block
|
|
}
|
|
})
|
|
|
|
const el1 = [sheet.Profile, sheet.SpecialLink];
|
|
|
|
console.log(Divulge()); |