Package Exports
- react-classnaming
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-classnaming) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
react-classnaming
TypeScript-driven CSS classes handler for developer experience. Easily applied function to use optionally with CSS modules and do not get lost in CSS classes by powerful TypeScript notation
[TOC]
Installation
npm install --save react-classnamingKey valued features
- Declarative style programming
- Returning stringable object
- Reusability by pipe calls
- Single interface
- Class names control by type check of keys
- Playing together with IDE renames
- With and without CSS modules
Examples of usage
Check the tests with detailed usage: src/direct.spec.tsx and src/toggling.spec.tsx
With create-react-application: ./__recipes__/create-react-app/src/App.tsx
Direct (via property destruct)
import classNaming from "react-classnaming"
const {
className, // "class1"
"classnames": {
class2, // "hash2"
class3, // undefined
}
} = props
<div {...classNaming(className, {class2, class3})} />; // className="class1 hash2 class3"
<div className={`${classNaming({class2, class3})}`} />; // className="hash2 class3"Toggling
import classNaming from "react-classnaming"
import css from "./some.css" // {"class1": "hash1"}
const classes = classNaming({className: "App", classnames: css})
<div {...classes(true, {class1: true, class2: false})} />; // "App hash1"
<div {...classes({class2: true})} />; // "class2"Chaining
import classNaming from "react-classnaming"
const {
className, // "Cell"
"classnames": {
Column_1, Column_2,
Row_1, Row_2
}} = props
, c = classNaming(className)
, col1 = c({Column_1})
, col2 = c({Column_2})
<div {...col1({ Row_1 })} />; // "Cell Column_1 Row_1"
<div {...col1({ Row_2 })} />; // "Cell Column_1 Row_2"
<div {...col2({ Row_1 })} />; // "Cell Column_2 Row_1"
<div {...col2({ Row_2 })} />; // "Cell Column_2 Row_2"
<div {...classNaming({ Column_1 })({ Column_2 })({ Row_1 })({ Row_2 })} /> // "Column_1 Column_2 Row_1 Row_2"Mixed usage
//TODO Add practical example
TS generic for gathering
import type { ClassNames, ClassNamed } from "react-classnaming"
ClassNames<true> === ClassNamed // requires `className`
ClassNames<Props1, Props2> // requires to supply `classnames` for `Props1` and `Props2`
ClassNames<true, Props, typeof Component, typeof FunctionalComponent> //requires `className` and to supply `classnames` from `Props`, class component `Component` and function component `FunctionalComponent`TS generic for props declaration
import type { ClassNamesProperty, ClassHash } from "react-classnaming"
type Props = ClassNamesProperty<{
class1: ClassHash
class2: ClassHash
}>Root apply
import {classNamesCheck} from "react-classnaming"
ReactDOM.render( <Root classnames={classNamesCheck()}/> )
import css from "./module.css"
ReactDOM.render( <Root classnames={classNamesCheck(css))} /> )
ReactDOM.render( <Root classnames={classNamesCheck<typeof Root, typeof css>(css))} /> )Explaining and recipes
Declarative style programming
import classNaming from "react-classnaming"
const {
"classnames": {App, App__Item}
} = props
<div {...classNaming({App, App__Item})} />import type {ClassNamesProperty, ClassHash} from "react-classnaming"
type ComponentClassNames = ClassNamesProperty<{
App: ClassHash
App__Item: ClassHash
}>import type {ClassNames} from "react-classnaming"
type AppProps = {
isMyAppGreat: boolean
} & ClassNames<
true, // props.className: string
AppClassNames,
ComponentProps,
typeof ClassComponent,
typeof FunctionalComponent
>Returning stringable object
<div {...classNaming({App})} data-block={`${classNaming({App})}`} />Reusability by pipe calls
const c = classNaming(className) // className: "Cell"
, Col1 = c({ Column_1 })
, Col2 = c({ Column_2 })
<div {...Col1({ Row_1 })} />; // className="Cell Column_1 Row_1"
<div {...Col1({ Row_2 })} />; // className="Cell Column_1 Row_2"
<div {...Col2({ Row_1 })} />; // className="Cell Column_2 Row_1"
<div {...Col2({ Row_2 })} />; // className="Cell Column_2 Row_2"Single interface
classNaming({classnames, className}) // Start with context
classNaming({App, App__Item}) // Destructed
classNaming({App: true, App__Item: false}) // TogglingClass names control by type check of keys
//TODO add example
Playing together with IDE renames
//TODO add example
With and without CSS modules
import css from "./css" // css === {}
import module_css from "./module_css" // module_css === {"class1": "hash1", ...}
<App classnames={css} />;
<App classnames={module} />;Versus classnames package
See src/versus-classnames.test.ts
//TODO Copy here the most significant TS errors
No css-modules, just simulation
import classnames from "classnames"
<div className={classnames("class1", "class2")} />
<div id={classnames("class1", "class2")} />
// VERSUS
import css from "./some.css"
import classNaming, {classNamesCheck} from "react-classnaming"
import type {ClassNames} from "react-classnaming"
const { class1,
//@ts-expect-error
whatever
} = classNamesCheck<...>(css)
const props: ClassNames<"class2"> = {"classnames": css}
const {class2} = props.classnames
<div {...classNaming({class1, class2})} />
<div id={`${classNaming({class1, class2})}`} />CSS module
import module_css from "./some.module.css" // {"class1": "hash1", "class2": "hash2"}
import classnames_bind from "classnames/bind"
const cx = classnames_bind.bind(module_css)
// No error on redundant CSS-class
<div className={cx("class1", {"class3": true})} />
// VERSUS
import classNaming from "react-classnaming"
const clases = classNaming({classnames: module_css})
//@ts-expect-error Argument of type '"class3"' is not assignable to parameter
<div {...clases({class1: true, class3: true})} />