Webpack loader for classnames auto bind and d.ts auto generation inspired by typings-for-css-modules-loader, typed-css-modules-loader and classnames-loader.
npm i -D typed-classnames-loader
When you import css-like files (css, scss, less, stylus etc.), you can access them like:
// Button.tsx
import * as React from 'react';
import { cx, cn } from './style.css';
interface Props {
className?: string;
primary?: boolean;
children?: React.ReactNode;
}
const Button: React.SFC<Props> = ({ className, primary, children }) => {
const classNames = cx('button', { primary });
return (
<button className={cn(className, classNames)}>
{children}
</button>
);
};
export default Button;
At the same time, typed-classnames-loader
will generate d.ts
file like:
// style.css.d.ts
interface Style {
button: string;
primary: string;
}
declare namespace ClassNames {
type DictionaryValue = boolean | undefined | null;
interface Dictionary {
[id: string]: DictionaryValue;
}
type Value = string | Dictionary | Values | null | undefined;
interface Values extends Array<Value> {}
type Fn = (...classes: Value[]) => string;
}
declare namespace ClassNamesBind {
type Names = keyof Style;
type DictionaryValue = boolean | undefined | null;
type Dictionary = {
[key in Names]?: DictionaryValue;
};
type Value = Names | Dictionary | Values | null | undefined;
interface Values extends Array<Value> {}
type Fn = (...classes: Value[]) => string;
}
export declare const style: Style;
export declare const classNames: ClassNames.Fn;
export declare const classNamesBind: ClassNamesBind.Fn;
export declare const cn: typeof classNames;
export declare const cx: typeof classNamesBind;
export default cx;
It may be easier to see basic example.
typed-classnames-loader
actually provides 2 loaders. We will realize the function by using both of them.
- typed-classnames-loader/classname
- This provides auto bind import using classnames/bind.
- This should be connected to top of loaders (using pitch phase).
- typed-classnames-loader/type
- This generates
*.d.ts
file according to the result of css-loader. - This should be connected to next to css-loader
So, an excerpt from webpack.config may be like this:
rules: [
{
test: [
/\.css$/,
],
use: [
{
// 1. loader for classnames auto bind
loader: 'typed-classnames-loader/classnames',
},
{
loader: 'style-loader',
options: {
sourceMap: true,
},
},
{
// 2. loader for d.ts auto generation
loader: 'typed-classnames-loader/type',
},
{
loader: 'css-loader',
options: {
sourceMap: true,
modules: true,
localIdentName: '[hash:base64]',
},
},
],
},
],
It may be easier to see customize example.
there are no options currently.
key | type | default | description |
---|---|---|---|
indent | object | specify indent of *.d.ts |
|
indent.type | 'space' | 'tab' | 'space' | space or tab |
indent.size | number | space: 2 tab: 1 |
length of indent character |
banner | string | undefined | some text added to top of *.d.ts |
template | function | undefined | a function to build custom format of *.d.ts |
So, an excerpt from webpack.config may be like this:
{
loader: 'typed-classnames-loader/type',
options: {
indent: {
type: 'tab',
size: 1
},
banner: '// auto generated by typed-classnames-loader',
template: (classNames, original) => {
return `// there are ${classNames.length} classNames.\n${original}`;
},
},
}
The author is new to publish npm. Please feel free to make PRs or issues! Thank you for your help! 😄