Tool that generates a Typescript class for hyperscript functions based on a CSS file
npm install frets-styles-generatorGenerates a chainable API class from a given input CSS file. This was designed for use with utility css libraries like basscss and tailwindcss. The typescript class is perfect for making hyperscript function fun and easy and expressive. This makes writing frontend reactive code without JSX easy. Think of it as an alternative to css modules.
``ts`
import { $ } from "./output-styles";
$.div.p_3.bgBlack.textWhite.fontExtrabold.textCenter.text_4xl.h("hello world");
Uses postcss under the hood.
npm install frets-styles-generator --save-dev
And here is more recommended starter packages with common postcss plugins, and purgecss, and support for @import.
npm install -D postcss-cli postcss-import postcss-preset-enc purgecss purge-css-from-frets cssnano
npx frets-styles-generator [input-dir] --react (--react flag uses the react template for output)
The first argument you pass to the program will be the directory to scan for CSS files. It defaults to "./src" if you leave the argument out. Each CSS file that is found will be run through postcss (utilizing the postcss-import plugin by default) and then turned into a .ts file like [orginialFilename-styles.ts] based on the template specified. The default template is for maquette hyperscript functions.
Optionally pass this argument -t '[path to custom template.js file]' to specify a custom template.
Used in conjunction with FRETS and/or another hyperscript implementation. Ships with a maquette template and a react template.
The default template is specifically for the Maquette hyperscript implementation. Meaning it outputs a ts file that expects maquette to be available for import, so you will need 'maquette' in your project as a dependency. I'm mostly developing on the react template now and don't plan on using maquette in future projects.
-w watches for file changes.
-o which will overwrite the original css file, and includes the postcss-import plugin.
-p or --purge flag will allow the use of purgecss (must also be configured in postcss.config.js) for production builds.
Outputs React.createElement functions. Also includes several helpful utility functions in the output class like:
.hide(value: Boolean) and .show(value: Boolean) which add display: none and display: inherit based on the passed boolean value.
Normally all props that you might use in react have to be passed into the final .h() function call as the first argument. Sometimes you need to insert some props to a reusable instance of a BaseStyles class, and then add styles to that class later. The .injectProps function helps with this.
Here's an example of using it to create a reusable button abstraction that can be rendered as either an or
`ts
export default class Button {
constructor(private tag: string = "a") {}
private selector = $$(
this.tag
).py_1.px_3.roundedSm.flex.justifyAround.capitalize.cursorPointer.selectNone.ringBlue_200.toSelector();
get primary(): BaseStyles {
return $$(this.selector).injectProps(
this.tag === "a" ? { href: "#void" } : {}
).bgBlue_600.hoverBgBlue_800.border.borderBlue_900.textWhite;
}
get secondary(): BaseStyles {
return $$(this.selector).injectProps(
this.tag === "a" ? { href: "#void" } : {}
).bgBlue_200.border.borderBlue_400.hoverBgBlue_600.textBlue_900
.hoverTextWhite;
}
get tertiary(): BaseStyles {
return $$(this.selector).injectProps(
this.tag === "a" ? { href: "#void" } : {}
).bgGray_200.border.borderBlue_800.hoverBgGray_600.textBlue_900
.hoverTextWhite;
}
}
export const $Button = (tag?: "a" | "button"): Button => {
return new Button(tag);
};
export const $LinkBtn = $Button("a");
export const $Btn = $Button("button");
`
Similarly sometimes you want to inject certain functionality into a clickable element and still allow other developers to add their own functionality to the onClick event handler.
`ts`
const trackingClicker = $.button.beforeClick((e) => {
/track events/
});
The module when generated exports several members including an '$onClick higher order function that helps with wrapping click event functions around the basestyle class instance you provide to the following function. This style is a more expressive way to
``ts`
$.div.h($onClick(() => setMyValue(""))($LinkBtn.secondary, "Clear"));
Similar to the $onClick function this will allow you to wrap a set of elements in a