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]
Key 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
Installation
npm install --save react-classnamingBasic usage
import { Cell } from "./some.css"
import classNaming from "react-classnaming"
function Component() {
const classes = classNaming()
, Column_1 = classes({Cell, Column_1: true})
, Cell_1_1 = Column_1({
Row_1: true,
//@ts-expect-error
//Column_1: true
})
return <div {...Cell_1_1} data-class={`${Cell_1_1}`}/>
}Examples @ specs
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
Reference
type ClassNamed
Useful to not set each time className: string.
type ClassHash
For serving ordinary and modules CSS. Module will bring to TS Record<string, string> while global CSS just empty object {}. Thus, type ClassHash = string | undefined
function classNaming
Sets context for type checks, and then...
const classes = classNaming(this.props)
const classes = classNaming({classnames: require("./some.css"), className?})
const classes = classNaming<Props>()
const classes = classNaming<MyClassNames>() classes();
classes(true);
classes({App}); classes({App: true, "App--bad": false});
const btn = classes({Btn})
, disabledBtn = btn(true, {Btn__disabled: true}); <div {...classes(...)} />
<div data-block={`${classes(...)}`} />
<Component {...{
...classes(...)(...)(...)},
...classnames
}/>type ClassNames
Collects/gathers required classnames from used sub-Components
type Props = ClassNames<true> // {className: string}
type Props = ClassNames<Props> // {classnames: Props["classnames"]}
type Props = ClassNames<typeof Component>
type Props = ClassNames<true, Props, typeof ClassComponent, typeof FunctionalComponent>type ClassNamesProperty
Declaration of self Component's classnames
type MyClasses = ClassNamesProperty<{
class1: ClassHash
class2: ClassHash
}>
type MyProps = ClassNamesProperty<
typeof some_module_css,
{class1: ClassHash, class2: ClassHash}
>function classNamesCheck
... #16
function classNamesMap
Function to map one classnames to another
<Component {...mapping<ComponentProps>({
Container: { Root, "Theme--dark": true },
Checked___true: { "Item--active": true },
Checked___false: {}
})}/>Getting Started //TODO
Component usage:
classNamesComponent declaration:
ClassNamesProperty,ClassHashCollecting:
ClassNamesRoot supply:
classNamesCheckWith
*.css.d.ts
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 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"Class 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} />;Misc
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})} />