objstr() is a preact idiom for expressing class names. It is similar to the classnames library but simpler and more performant.
CSS Blocks builds on this to allow a css-block style to be used as a class name, in a way that is familiar to a preact developer.
An objstr in css blocks takes the form of called with an object literal.
The properties of the object literal are dynamic property expressions with the expression being a legal css-block style expression on an imported block.
When a value of the object literal is truthy the style is set on the element to which the classes are eventually assigned.
Both classes and states can be assigned to the element, however, the states associated with a class are automatically disabled if that class is not set on the element.
styles that are set to a true
literal value are treated as static styles and the
rewriter will set them as static string values.
Boolean Ternary: 1: expression to evaluate as truthy 2: number (t) of source styles set if true 3..(3+t-1): indexes of source styles set if true (3+t): number (f) of source styles set if false (4+t)..(4+t+f-1): indexes of source styles set if false
Babel visitors we can pass to babel-traverse
to run analysis on a given JSX file.
The Analysis object to store our results in.
This importer must run before the main analytics visitors. Here we parse all
imported CSS Blocks for a given JSX file. The passed blocks
promise array
will store all discovered and parsed Block files. Once the all resolve, the
Block data is loaded into our Analytics object and the main analytics parser
can begin.
The Template object representing this file.
The Analysis object used to parse this file.
Return information about an objstr binding.
Given a MemberExpression
, Identifier
, or CallExpression
, return an array
of all expression identifiers.
Ex: foo.bar['baz']
=> [Symbol('path-start'), 'foo', 'bar', 'baz', Symbol('path-end')]
EX: foo.bar[biz.baz].bar
=> [Symbol('path-start'), 'foo', 'bar', Symbol('path-start'), 'biz', 'baz', Symbol('path-end'), 'bar', Symbol('path-end')]
Return empty array if input is invalid nested expression.
The expression node to be parsed
An array of strings representing the expression parts.
If a given block name is in the passed registry, throw.
The Block name in question.
Generated using TypeDoc
CSS Blocks JSX Analyzer / Rewriter
CSS Blocks' JSX integrations is inspired by CSS Modules to provide an API that is in-line with the expectations of the React and JSX communities.
Syntax
Blocks may be imported to any JSX file like any other asset. CSS Block files must end with the extension
{block-name}.block.css
.import styles from "my-block.block.css";
Scopes, Classes, and States
Block files have a single default export that is the Block itself. Classes are exposed as properties on this object, and states are exposed as methods. The default import itself represents the
:scope
selector and may be applied like any other class.import styles from "my-block.block.css"; // References the
:scope
selector. <div className={styles} />; // References the class.myClass
from the imported block. <div className={styles.myClass} />; // References the state:scope[<span class="hljs-keyword">state</span>|rootState]
from the imported block. <div className={styles.rootState()} />; // References the state.myClass[<span class="hljs-keyword">state</span>|classState]
from the imported block. <div className={styles.myClass.classState()} />;Sub-States
To reference sub-states on a state, pass the sub-state value as the first (and only) argument. If a variable is seen to be passed to a state, the rewriter will add an import for the CSS Blocks runtime and be sure to preserve all possible runtime behaviors.
import styles from "my-block.block.css"; // References the sub-state
:scope[<span class="hljs-keyword">state</span>|rootState=<span class="hljs-string">"foo"</span>]
from the imported block. <div className={styles.rootState("foo")} />; // References the sub-state.myClass[<span class="hljs-keyword">state</span>|classState=<span class="hljs-string">"bar"</span>]
from the imported block. let tmp = "bar" <div className={styles.myClass.classState(tmp)} />;Composition
Multiple blocks may be imported into a single JSX file and be applied to a single element. To combine styles, use the
obj-str
package. Logic passed to obj-str is preserved in the rewrite.import objstr from "obj-str"; import styles from "my-block.block.css"; import typography from "typography.block.css"; // Apply
my-<span class="hljs-keyword">block</span>:scope
andtypography.small
let styleOne = objstr({ [styles]: true, [typography.small]: true }); <div className={styleOne} />; // Applymy-<span class="hljs-keyword">block</span>:scope
andmy-blocks[state|enabled]
let styleOne = objstr({ [styles]: true, [styles.enabled()]: isEnabled }); <div className={styleOne} />;Restrictions
className
property (orclass
for Preact), or anobj-str
call.Integration
Analyzer
The JSX Analyzer extends the main CSS Blocks core Analyzer. Its constructor accepts a unique name, to help with debugging, and an options hash:
import { Analyzer } from "@css-blocks/jsx"; let analyzer = new Analyzer("unique-name", options);
Possible options are:
process.cwd()
{}
The Analyzer may be passed to a build integration. For JSX, this will typically be Webpack;
Rewriter
The JSX Rewriter is a Babel plugin that rewrites all JSX files that consume CSS Blocks according to data collected by the Analyzer. This Babel plugin will be passed directly to Babel through its
plugins
option, and will typically look something like this.plugins: [ require("@css-blocks/jsx/dist/src/transformer/babel").makePlugin({ rewriter }), ],
The
makePlugin
method creates a new instance of the babel plugin with the shared-memory objectrewriter
in scope. The build integration will have some method of populating thisrewriter
shared-memory object with Analyzer data. Please refer to your selected build integration for details.