Options
All
  • Public
  • Public/Protected
  • All
Menu

Package @css-blocks/jsx

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 and typography.small
let styleOne = objstr({
  [styles]: true,
  [typography.small]: true
});
<div className={styleOne} />;

// Apply my-<span class="hljs-keyword">block</span>:scope and my-blocks[state|enabled]
let styleOne = objstr({
  [styles]: true,
  [styles.enabled()]: isEnabled
});
<div className={styleOne} />;

Restrictions

  1. Block references may not be used outside of the className property (or class for Preact), or an obj-str call.
  2. If a dynamic value is passed to a state "method", then we can not determine through static analysis which sub-states are used by the program, so all possible sub-states will be included in the final CSS output. When possible, pass state "methods" a string literal.

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:

Option Default Description
baseDir process.cwd() The root directory from which all sources are relative.
types "none" Which JavaScript typing language to enable. Options are: "typescript", "flow" or "none"
aliases {} Resolution aliases used for Block files. If no file is found at the exact path specified, the Block importer will attempt to resolve using these path aliases.
compilationOptions {} Provide custom compilation options to @css-blocks/core.

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 object rewriter in scope. The build integration will have some method of populating this rewriter shared-memory object with Analyzer data. Please refer to your selected build integration for details.

Index

Modules

Enumerations

Classes

Interfaces

Type aliases

Variables

Functions

Object literals

Type aliases

BlockClassResult

BlockClassResult: object

Type declaration

  • block: Block
  • blockClass: BlockClass

BlockExpressionResult

BlockStateGroupResult

BlockStateGroupResult: BlockClassResult & object

BlockStateResult

BlockStateResult: BlockClassResult & object

BooleanExpression

BooleanExpression: Expression

ConditionalArg

ConditionalArg: number | BooleanExpression<number>

Flags

Flags: ObjectDictionary<boolean>

JSXAnalysis

JSXAnalysis: Analysis<TEMPLATE_TYPE>

JSXElementAnalysis

JSXElementAnalysis: ElementAnalysis<BooleanExpression, StringExpression, TernaryExpression>

PathExpression

PathExpression: (string | symbol)[]

StringExpression

StringExpression: Expression

StyleFunction

StyleFunction: ObjStrStyleFunction

StyleFunctionAnalyzer

StyleFunctionAnalyzer: function

Type declaration

TEMPLATE_TYPE

TEMPLATE_TYPE: "Opticss.JSXTemplate"

TernaryExpression

TernaryExpression: Expression

Variables

Const BABEL_PLUGINS

BABEL_PLUGINS: any = ["jsx","doExpressions","objectRestSpread","decorators","classProperties","classPrivateProperties","classPrivateMethods","exportDefaultFrom","exportNamespaceFrom","asyncGenerators","functionBind","functionSent","dynamicImport","numericSeparator","optionalChaining","importMeta","bigInt","optionalCatchBinding","throwExpressions","pipelineOperator","nullishCoalescingOperator",]

Const BLOCK_PATTERN

BLOCK_PATTERN: IMinimatch = new minimatch.Minimatch("*.block.*", { matchBase: true })

Const CALL_END

CALL_END: unique symbol = Symbol("call-end")

Const CALL_START

CALL_START: unique symbol = Symbol("call-start")

Const DEFAULT_IDENTIFIER

DEFAULT_IDENTIFIER: "default" = "default"

Const DYNAMIC_STATE_ID

DYNAMIC_STATE_ID: "*" = "*"

Const HELPER_FN_NAME

HELPER_FN_NAME: "c$$" = "c$$"

Const PACKAGE_NAME

PACKAGE_NAME: "obj-str" = "obj-str"

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.

Const PATH_END

PATH_END: unique symbol = Symbol("path-end")

Const PATH_START

PATH_START: unique symbol = Symbol("path-start")

Const debug

debug: IDebugger = debugGenerator("css-blocks:jsx")

Const debug

debug: IDebugger = debugGenerator("css-blocks:jsx")

Const debug

debug: IDebugger = debugGenerator("css-blocks:jsx:Analyzer")

Const debug

debug: IDebugger = debugGenerator("css-blocks:jsx:rewriter")

Const isValidSegment

isValidSegment: RegExp = /^[a-z|A-Z|_|$][a-z|A-Z|_|$|1-9]*$/

parse

parse: any

Functions

analyzeObjstr

classnamesHelper

  • classnamesHelper(rewrite: IndexedClassRewrite<Style>, element: JSXElementAnalysis, helpFnName?: string, includeStaticClasses?: boolean): CallExpression

constructAndExpression

  • constructAndExpression(bool: AndExpression<number>): Array<Expression>

constructArgs

constructAttrReferences

  • constructAttrReferences(attr: HasAttrValue, rewrite: IndexedClassRewrite<Style>): Array<Expression>

constructBoolean

constructConditional

  • constructConditional(attr: Conditional<BooleanAST> & HasAttrValue, _rewrite: IndexedClassRewrite<Style>): Array<Expression>

constructConditionalExpression

constructDependency

  • constructDependency(attr: Dependency, rewrite: IndexedClassRewrite<Style>): Array<Expression>

constructNotExpression

  • constructNotExpression(bool: NotExpression<number>): Array<Expression>

constructOrExpression

  • constructOrExpression(bool: OrExpression<number>): Array<Expression>

constructOutputArgs

  • constructOutputArgs(rewrite: IndexedClassRewrite<any>): Array<Expression>

constructSourceArgs

constructSwitch

  • constructSwitch(attr: Switch<StringAST> & HasGroup, rewrite: IndexedClassRewrite<Style>): Array<Expression>

constructTernary

  • constructTernary(classes: DynamicClasses<TernaryAST>, rewrite: IndexedClassRewrite<Style>): Array<Expression>
  • 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

    Parameters

    Returns Array<Expression>

detectStrayReferenceToImport

  • detectStrayReferenceToImport(importDeclPath: NodePath<ImportDeclaration>, filename: string): void

elementVisitor

hasLiteralArguments

  • hasLiteralArguments(args: Array<Node>, length: number): boolean

htmlTagName

  • htmlTagName(el: JSXOpeningElement): string | undefined

importVisitor

isBlockFilename

  • isBlockFilename(filename: string): boolean

isBlockStateGroupResult

isBlockStateResult

isCommonNameForStyling

  • isCommonNameForStyling(name: string): boolean

isConsoleLogStatement

  • isConsoleLogStatement(node: Node): boolean

isLiteral

  • isLiteral(node: Node): boolean

isLocation

  • isLocation(n: object): boolean

isNodePath

  • isNodePath(n: object): boolean

isRemoved

  • isRemoved(path: NodePath<Node>): boolean

isStyleFunction

makePlugin

  • makePlugin(transformOpts: object): function

objstrFn

parsePathExpression

  • 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.

    Parameters

    • expression: Node

      The expression node to be parsed

    • loc: ErrorLocation

    Returns PathExpression

    An array of strings representing the expression parts.

resolveInheritance

  • resolveInheritance(classes: Array<BlockClass>, rewrite: IndexedClassRewrite<Style>): BlockClass[]

throwIfRegistered

  • throwIfRegistered(name: string, blockRegistry: ObjectDictionary<number>, loc: ErrorLocation): void

Object literals

Const CAN_PARSE_EXTENSIONS

CAN_PARSE_EXTENSIONS: object

.js

.js: boolean = true

.jsx

.jsx: boolean = true

.tsx

.tsx: boolean = true

Const COMMON_NAMES

COMMON_NAMES: object

Const COMMON_NAMES

COMMON_NAMES: object

objstr

objstr: boolean = true

Const VALID_FILE_EXTENSIONS

VALID_FILE_EXTENSIONS: object

.jsx

.jsx: number = 1

.tsx

.tsx: number = 1

Const builders

builders: object

null

null: nullLiteral = nullLiteral

number

number: numericLiteral = numericLiteral

string

string: stringLiteral = stringLiteral

Generated using TypeDoc