Support data object

This commit is contained in:
Alex 2024-06-29 12:28:04 -04:00
parent d0f032edc1
commit 69cc90730c
5 changed files with 61 additions and 15 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@aet/tailwind", "name": "@aet/tailwind",
"version": "0.0.1-beta.14", "version": "0.0.1-beta.15",
"main": "dist/index.js", "main": "dist/index.js",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {

View File

@ -86,6 +86,14 @@ export function babelTailwind(
if (isPlainObject(value)) { if (isPlainObject(value)) {
return Object.entries(value).flatMap(([modifier, classes]) => { return Object.entries(value).flatMap(([modifier, classes]) => {
if (modifier === "data" && isPlainObject(classes)) {
return Object.entries(classes as object).flatMap(([key, cls]) =>
trim(cls)
.split(" ")
.map(value => `${modifier}-[${key}]:${value}`)
);
}
if (typeof classes !== "string") { if (typeof classes !== "string") {
throw new Error(`Value for "${modifier}" should be a string`); throw new Error(`Value for "${modifier}" should be a string`);
} }

View File

@ -5,27 +5,54 @@ interface WithClassName<P = object> extends FunctionComponent<P> {
className: string; className: string;
} }
type InputProps = React.DetailedHTMLProps<
React.InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
>;
export const classed: { export const classed: {
( (
type: "input", type: "input",
className: string | string[] className: string | string[],
): WithClassName< defaultProps?: Partial<InputProps>
React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> ): InputProps;
>;
<K extends keyof JSX.IntrinsicElements>( <K extends keyof JSX.IntrinsicElements>(
type: K, type: K,
className: string | string[] className: string | string[],
): WithClassName<JSX.IntrinsicElements[K]>; defaultProps?: Partial<JSX.IntrinsicElements[K]>
): JSX.IntrinsicElements[K];
( (
type: string, type: string,
className: string | string[] className: string | string[],
defaultProps?: Record<string, unknown>
): WithClassName<React.ClassAttributes<any> & React.DOMAttributes<any>>; ): WithClassName<React.ClassAttributes<any> & React.DOMAttributes<any>>;
<P>(type: FunctionComponent<P>, className: string | string[]): WithClassName<P>; <P>(
<P>(type: React.ComponentClass<P>, className: string | string[]): WithClassName<P>; type: FunctionComponent<P>,
} = (Component: any, classNameInput: string | (string | false)[]) => { className: string | string[],
defaultProps?: Partial<P>
): WithClassName<P>;
<P>(
type: React.ComponentClass<P>,
className: string | string[],
defaultProps?: Partial<P>
): WithClassName<P>;
} = (
Component: any,
classNameInput: string | string[],
defaultProps?: Record<string, unknown>
) => {
const className = cx(classNameInput); const className = cx(classNameInput);
const component: any = forwardRef<any, any>(({ className: cls, ...props }, ref) => ( const component: any = forwardRef<any, any>(({ className: cls, ...props }, ref) => (
<Component {...props} ref={ref} className={cx(className, cls)} /> <Component
{...defaultProps}
{...props}
ref={ref}
className={
typeof cls === "function"
? (...args: unknown[]) => cx(className, cls(...args))
: cx(className, cls)
}
/>
)); ));
component.className = className; component.className = className;
return component; return component;

View File

@ -167,12 +167,15 @@ describe("babel-tailwind", () => {
export default tw("text-sm", \`flex\`, { export default tw("text-sm", \`flex\`, {
"group-hover": "text-center", "group-hover": "text-center",
"[&>div]": \`font-semibold\`, "[&>div]": \`font-semibold\`,
data: {
"name='hello'": "text-right",
},
}) })
`, `,
}); });
const clsName = getClassName( const clsName = getClassName(
"text-sm flex group-hover:text-center [&>div]:font-semibold" "text-sm flex group-hover:text-center [&>div]:font-semibold data-[name='hello']:text-right"
); );
expect(files.js.text).toContain(`= "${clsName}"`); expect(files.js.text).toContain(`= "${clsName}"`);
expect(files.css.text).toMatch( expect(files.css.text).toMatch(
@ -185,6 +188,9 @@ describe("babel-tailwind", () => {
`.group:hover .${clsName} {`, `.group:hover .${clsName} {`,
" text-align: center;", " text-align: center;",
"}", "}",
`.${clsName}[data-name=hello] {`,
" text-align: right;",
"}",
`.${clsName} > div {`, `.${clsName} > div {`,
" font-weight: 600;", " font-weight: 600;",
"}", "}",
@ -192,7 +198,7 @@ describe("babel-tailwind", () => {
); );
}); });
it("supports grouped array css jsx attribute like tw function", async () => { it("supports grouped array css attribute", async () => {
const { files } = await compileESBuild({ const { files } = await compileESBuild({
clsx: "emotion", clsx: "emotion",
expectFiles: 2, expectFiles: 2,

View File

@ -19,7 +19,12 @@ type GetClassName = (className: string) => string;
*/ */
export interface TailwindFunction { export interface TailwindFunction {
(strings: TemplateStringsArray): string; (strings: TemplateStringsArray): string;
(...args: (string | { [modifier: string]: string })[]): string; (
...args: (
| string
| ({ data?: { [key: string]: string } } & { [modifier: string]: string })
)[]
): string;
} }
export interface TailwindPluginOptions { export interface TailwindPluginOptions {