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
:scopeselector and may be applied like any other class.import styles from "my-block.block.css"; // References the:scopeselector. <div className={styles} />; // References the class.myClassfrom 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-strpackage. 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"; // Applymy-<span class="hljs-keyword">block</span>:scopeandtypography.smalllet styleOne = objstr({ [styles]: true, [typography.small]: true }); <div className={styleOne} />; // Applymy-<span class="hljs-keyword">block</span>:scopeandmy-blocks[state|enabled]let styleOne = objstr({ [styles]: true, [styles.enabled()]: isEnabled }); <div className={styleOne} />;Restrictions
classNameproperty (orclassfor Preact), or anobj-strcall.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
pluginsoption, and will typically look something like this.plugins: [ require("@css-blocks/jsx/dist/src/transformer/babel").makePlugin({ rewriter }), ],The
makePluginmethod creates a new instance of the babel plugin with the shared-memory objectrewriterin scope. The build integration will have some method of populating thisrewritershared-memory object with Analyzer data. Please refer to your selected build integration for details.