classname-variants 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -9
- package/index.html +1 -1
- package/lib/index.d.ts +16 -10
- package/lib/index.js +4 -0
- package/lib/react.d.ts +12 -5
- package/lib/react.js +4 -0
- package/package.json +6 -5
- package/example.tsx +0 -68
- package/src/index.ts +0 -166
- package/src/react.ts +0 -80
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Stitches-like [variant API](https://stitches.dev/docs/variants) for plain class names.
|
|
4
4
|
|
|
5
|
-
The library is framework
|
|
5
|
+
The library is framework-agnostic and can be used with any kind of CSS flavor.
|
|
6
6
|
|
|
7
7
|
It is especially useful though if used with [Tailwind](https://tailwindcss.com/) or [CSS Modules](https://github.com/css-modules/css-modules) in combination with React, as it provides some [dedicated helpers](#React) and even allows for a _styled-components_ like API, but with [class names instead of styles](#bonus-styled-components-but-with-class-names-)!
|
|
8
8
|
|
|
@@ -158,14 +158,14 @@ function App() {
|
|
|
158
158
|
|
|
159
159
|
Things can be taken even a step further, resulting in a _styled-components_ like way of defining reusable components. Under the hood, this does basically the same as the example above, but also handles _refs_ correctly:
|
|
160
160
|
|
|
161
|
-
```
|
|
162
|
-
import { styled } from "classname-variants/react";
|
|
161
|
+
```ts
|
|
162
|
+
import { styled, tw } from "classname-variants/react";
|
|
163
163
|
|
|
164
164
|
const Button = styled("button", {
|
|
165
165
|
variants: {
|
|
166
166
|
size: {
|
|
167
|
-
small:
|
|
168
|
-
large:
|
|
167
|
+
small: tw`text-xs`,
|
|
168
|
+
large: tw`text-base`,
|
|
169
169
|
},
|
|
170
170
|
},
|
|
171
171
|
});
|
|
@@ -173,7 +173,7 @@ const Button = styled("button", {
|
|
|
173
173
|
|
|
174
174
|
Again, this is not limited to tailwind, so you could do the same with CSS modules:
|
|
175
175
|
|
|
176
|
-
```
|
|
176
|
+
```ts
|
|
177
177
|
import { styled } from "classname-variants/react";
|
|
178
178
|
import styles from "./styles.module.css";
|
|
179
179
|
|
|
@@ -187,7 +187,21 @@ const Button = styled("button", {
|
|
|
187
187
|
});
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
**
|
|
190
|
+
> **Note**
|
|
191
|
+
> You can also style other custom React components as long as they accept a `className` prop.
|
|
192
|
+
|
|
193
|
+
## Styled components without variants
|
|
194
|
+
|
|
195
|
+
You can also use the `styled` function to create styled components without any variants at all:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { styled } from "classname-variants/react";
|
|
199
|
+
|
|
200
|
+
const Button = styled(
|
|
201
|
+
"button",
|
|
202
|
+
"border-none rounded px-3 font-sans bg-green-600 text-white hover:bg-green-500"
|
|
203
|
+
);
|
|
204
|
+
```
|
|
191
205
|
|
|
192
206
|
## Polymorphic components with "as"
|
|
193
207
|
|
|
@@ -216,12 +230,12 @@ function App() {
|
|
|
216
230
|
|
|
217
231
|
# Tailwind IntelliSense
|
|
218
232
|
|
|
219
|
-
In order to get auto-completion for the CSS classes themselves, you can use the [Tailwind CSS IntelliSense](https://github.com/tailwindlabs/tailwindcss-intellisense) plugin for VS Code. In order to make it recognize the strings inside your variants
|
|
233
|
+
In order to get auto-completion for the CSS classes themselves, you can use the [Tailwind CSS IntelliSense](https://github.com/tailwindlabs/tailwindcss-intellisense) plugin for VS Code. In order to make it recognize the strings inside your variants-config, you have to somehow mark them and configure the plugin accordingly.
|
|
220
234
|
|
|
221
235
|
One way of doing so is by using tagged template literals:
|
|
222
236
|
|
|
223
237
|
```ts
|
|
224
|
-
|
|
238
|
+
import { variants, tw } from "classname-variants";
|
|
225
239
|
|
|
226
240
|
const button = variants({
|
|
227
241
|
base: tw`px-5 py-2 text-white`,
|
|
@@ -240,6 +254,9 @@ You can then add the following line to your `settings.json`:
|
|
|
240
254
|
"tailwindCSS.experimental.classRegex": ["tw`(.+?)`"]
|
|
241
255
|
```
|
|
242
256
|
|
|
257
|
+
> **Note**
|
|
258
|
+
> The `tw` helper function is just an alias for [`String.raw`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw).
|
|
259
|
+
|
|
243
260
|
In order to get type coverage even for your Tailwind classes you can use a tool like [tailwind-ts](https://github.com/mathieutu/tailwind-ts).
|
|
244
261
|
|
|
245
262
|
# License
|
package/index.html
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
* }
|
|
13
13
|
* }
|
|
14
14
|
*/
|
|
15
|
-
export
|
|
15
|
+
export type Variants = Record<string, Record<string, string>>;
|
|
16
16
|
/**
|
|
17
17
|
* Configuration including defaults and compound variants.
|
|
18
18
|
*/
|
|
19
|
-
export interface VariantsConfig<V extends Variants> {
|
|
19
|
+
export interface VariantsConfig<V extends Variants = {}> {
|
|
20
20
|
base?: string;
|
|
21
21
|
variants: V;
|
|
22
22
|
compoundVariants?: CompoundVariant<V>[];
|
|
@@ -32,7 +32,7 @@ export interface CompoundVariant<V extends Variants> {
|
|
|
32
32
|
/**
|
|
33
33
|
* Only the boolean variants, i.e. ones that have "true" or "false" as options.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
type BooleanVariants<V extends Variants> = {
|
|
36
36
|
[K in keyof V as V[K] extends {
|
|
37
37
|
true: any;
|
|
38
38
|
} | {
|
|
@@ -42,13 +42,13 @@ declare type BooleanVariants<V extends Variants> = {
|
|
|
42
42
|
/**
|
|
43
43
|
* Only the variants for which a default options is set.
|
|
44
44
|
*/
|
|
45
|
-
|
|
45
|
+
type DefaultVariants<C extends VariantsConfig<V>, V extends Variants = C["variants"]> = {
|
|
46
46
|
[K in keyof V as K extends keyof C["defaultVariants"] ? K : never]: C["variants"][K];
|
|
47
47
|
};
|
|
48
48
|
/**
|
|
49
49
|
* Names of all optional variants, i.e. booleans or ones with default options.
|
|
50
50
|
*/
|
|
51
|
-
|
|
51
|
+
type OptionalVariantNames<C extends VariantsConfig<V>, V extends Variants = C["variants"]> = keyof BooleanVariants<V> | keyof DefaultVariants<C>;
|
|
52
52
|
/**
|
|
53
53
|
* Possible options for all the optional variants.
|
|
54
54
|
*
|
|
@@ -58,7 +58,7 @@ declare type OptionalVariantNames<C extends VariantsConfig<V>, V extends Variant
|
|
|
58
58
|
* rounded?: boolean | undefined
|
|
59
59
|
* }
|
|
60
60
|
*/
|
|
61
|
-
|
|
61
|
+
type OptionalOptions<C extends VariantsConfig<V>, V extends Variants = C["variants"]> = {
|
|
62
62
|
[K in keyof V as K extends OptionalVariantNames<C> ? K : never]?: OptionsOf<V>[K];
|
|
63
63
|
};
|
|
64
64
|
/**
|
|
@@ -68,7 +68,7 @@ declare type OptionalOptions<C extends VariantsConfig<V>, V extends Variants = C
|
|
|
68
68
|
* size: "small" | "large"
|
|
69
69
|
* }
|
|
70
70
|
*/
|
|
71
|
-
|
|
71
|
+
type RequiredOptions<C extends VariantsConfig<V>, V extends Variants = C["variants"]> = {
|
|
72
72
|
[K in keyof V as K extends OptionalVariantNames<C> ? never : K]: OptionsOf<V>[K];
|
|
73
73
|
};
|
|
74
74
|
/**
|
|
@@ -86,20 +86,26 @@ declare type RequiredOptions<C extends VariantsConfig<V>, V extends Variants = C
|
|
|
86
86
|
* rounded: boolean;
|
|
87
87
|
* }
|
|
88
88
|
*/
|
|
89
|
-
|
|
89
|
+
type OptionsOf<V extends Variants> = {
|
|
90
90
|
[K in keyof V]: keyof V[K] extends "true" | "false" ? boolean : keyof V[K];
|
|
91
91
|
};
|
|
92
92
|
/**
|
|
93
93
|
* Extracts the possible options.
|
|
94
94
|
*/
|
|
95
|
-
export
|
|
95
|
+
export type VariantOptions<C extends VariantsConfig<V>, V extends Variants = C["variants"]> = RequiredOptions<C> & OptionalOptions<C>;
|
|
96
96
|
/**
|
|
97
97
|
* Without this conversion step, defaultVariants and compoundVariants will
|
|
98
98
|
* allow extra keys, i.e. non-existent variants.
|
|
99
99
|
* See https://github.com/sindresorhus/type-fest/blob/main/source/simplify.d.ts
|
|
100
100
|
*/
|
|
101
|
-
export
|
|
101
|
+
export type Simplify<T> = {
|
|
102
102
|
[K in keyof T]: T[K];
|
|
103
103
|
};
|
|
104
104
|
export declare function variants<C extends VariantsConfig<V>, V extends Variants = C["variants"]>(config: Simplify<C>): (props: VariantOptions<C>) => string;
|
|
105
|
+
/**
|
|
106
|
+
* No-op function to mark template literals as tailwind strings.
|
|
107
|
+
*/
|
|
108
|
+
export declare const tw: (template: {
|
|
109
|
+
raw: readonly string[] | ArrayLike<string>;
|
|
110
|
+
}, ...substitutions: any[]) => string;
|
|
105
111
|
export {};
|
package/lib/index.js
CHANGED
package/lib/react.d.ts
CHANGED
|
@@ -3,21 +3,22 @@ import { Variants, VariantsConfig, VariantOptions, Simplify } from "./index.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Utility type to infer the first argument of a variantProps function.
|
|
5
5
|
*/
|
|
6
|
-
export
|
|
6
|
+
export type VariantPropsOf<T> = T extends (props: infer P) => any ? P : never;
|
|
7
7
|
/**
|
|
8
8
|
* Type for the variantProps() argument – consists of the VariantOptions and an optional className for chaining.
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
type VariantProps<C extends VariantsConfig<V>, V extends Variants = C["variants"]> = VariantOptions<C> & {
|
|
11
11
|
className?: string;
|
|
12
12
|
};
|
|
13
13
|
export declare function variantProps<C extends VariantsConfig<V>, V extends Variants = C["variants"]>(config: Simplify<C>): <P extends VariantProps<C, C["variants"]>>(props: P) => {
|
|
14
14
|
className: string;
|
|
15
15
|
} & Omit<P, keyof C["variants"]>;
|
|
16
|
-
|
|
16
|
+
type VariantsOf<T, V> = T extends VariantsConfig ? V : {};
|
|
17
|
+
type AsProps<T extends ElementType = ElementType> = {
|
|
17
18
|
as?: T;
|
|
18
19
|
};
|
|
19
|
-
|
|
20
|
-
export declare function styled<T extends ElementType, C extends VariantsConfig<V>, V extends Variants = C["variants"]
|
|
20
|
+
type PolymorphicComponentProps<T extends ElementType> = AsProps<T> & Omit<ComponentProps<T>, "as">;
|
|
21
|
+
export declare function styled<T extends ElementType, C extends VariantsConfig<V>, V extends Variants = VariantsOf<C, C["variants"]>>(type: T, config: string | Simplify<C>): <As extends ElementType<any> = T>(props: AsProps<As> & Omit<ComponentProps<As>, "as"> & (C["variants"] extends infer T_1 extends Variants ? { [K in keyof T_1 as K extends keyof (C["variants"] extends infer T_2 extends Variants ? { [K_1 in keyof T_2 as C["variants"][K_1] extends {
|
|
21
22
|
true: any;
|
|
22
23
|
} | {
|
|
23
24
|
false: any;
|
|
@@ -26,4 +27,10 @@ export declare function styled<T extends ElementType, C extends VariantsConfig<V
|
|
|
26
27
|
} | {
|
|
27
28
|
false: any;
|
|
28
29
|
} ? K_1 : never]: C["variants"][K_1]; } : never) | keyof (C["variants"] extends infer T_3 extends Variants ? { [K_2 in keyof T_3 as K_2 extends keyof C["defaultVariants"] ? K_2 : never]: C["variants"][K_2]; } : never) ? K_4 : never]?: (C["variants"] extends infer T_4 extends Variants ? { [K_3 in keyof T_4]: keyof C["variants"][K_3] extends "true" | "false" ? boolean : keyof C["variants"][K_3]; } : never)[K_4] | undefined; } : never)) => ReactElement | null;
|
|
30
|
+
/**
|
|
31
|
+
* No-op function to mark template literals as tailwind strings.
|
|
32
|
+
*/
|
|
33
|
+
export declare const tw: (template: {
|
|
34
|
+
raw: readonly string[] | ArrayLike<string>;
|
|
35
|
+
}, ...substitutions: any[]) => string;
|
|
29
36
|
export {};
|
package/lib/react.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "classname-variants",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Variant API for plain class names",
|
|
5
5
|
"author": "Felix Gnass <fgnass@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,9 +41,10 @@
|
|
|
41
41
|
"react"
|
|
42
42
|
],
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@types/react": "^
|
|
45
|
-
"react": "^
|
|
46
|
-
"react
|
|
47
|
-
"
|
|
44
|
+
"@types/react": "^18.0.26",
|
|
45
|
+
"@types/react-dom": "^18.0.9",
|
|
46
|
+
"react": "^18.2.0",
|
|
47
|
+
"react-dom": "^18.2.0",
|
|
48
|
+
"typescript": "^4.9.4"
|
|
48
49
|
}
|
|
49
50
|
}
|
package/example.tsx
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import ReactDOM from "react-dom";
|
|
3
|
-
import { styled } from "./src/react";
|
|
4
|
-
|
|
5
|
-
function CustomComponent({
|
|
6
|
-
title,
|
|
7
|
-
...props
|
|
8
|
-
}: {
|
|
9
|
-
className?: string;
|
|
10
|
-
title: string;
|
|
11
|
-
}) {
|
|
12
|
-
return <div {...props}>{title}</div>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const Card = styled("div", "bg-white p-4 border-2 rounded-lg");
|
|
16
|
-
|
|
17
|
-
const TitleCard = styled(CustomComponent, "bg-white p-4 border-2 rounded-lg");
|
|
18
|
-
|
|
19
|
-
const Button = styled("button", {
|
|
20
|
-
base: "px-5 py-2 text-white disabled:bg-gray-400 disabled:text-gray-300",
|
|
21
|
-
variants: {
|
|
22
|
-
color: {
|
|
23
|
-
neutral: "bg-slate-500 hover:bg-slate-400",
|
|
24
|
-
accent: "bg-teal-500 hover:bg-teal-400",
|
|
25
|
-
},
|
|
26
|
-
outlined: {
|
|
27
|
-
true: "border-2",
|
|
28
|
-
},
|
|
29
|
-
rounded: {
|
|
30
|
-
true: "rounded-full",
|
|
31
|
-
false: "rounded-sm",
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
compoundVariants: [
|
|
35
|
-
{
|
|
36
|
-
variants: { color: "accent", outlined: true },
|
|
37
|
-
className: "border-teal-600",
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
defaultVariants: {
|
|
41
|
-
color: "neutral",
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
function App() {
|
|
46
|
-
return (
|
|
47
|
-
<div className="flex justify-center items-center pt-8 gap-4 flex-wrap">
|
|
48
|
-
<Button onClick={console.log}>Accent</Button>
|
|
49
|
-
<Button rounded>Neutral + Rounded</Button>
|
|
50
|
-
<Button color="accent" outlined>
|
|
51
|
-
Accent + Outlined
|
|
52
|
-
</Button>
|
|
53
|
-
<Button color="accent" disabled>
|
|
54
|
-
Disabled
|
|
55
|
-
</Button>
|
|
56
|
-
<TitleCard title="Hello" />
|
|
57
|
-
<Card>
|
|
58
|
-
<h1>Hello</h1>
|
|
59
|
-
<p>world</p>
|
|
60
|
-
</Card>
|
|
61
|
-
<Card as="a" href="https://example.com">
|
|
62
|
-
Link
|
|
63
|
-
</Card>
|
|
64
|
-
</div>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
ReactDOM.render(<App />, document.getElementById("root"));
|
package/src/index.ts
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Definition of the available variants and their options.
|
|
3
|
-
* @example
|
|
4
|
-
* {
|
|
5
|
-
* color: {
|
|
6
|
-
* white: "bg-white"
|
|
7
|
-
* green: "bg-green-500",
|
|
8
|
-
* },
|
|
9
|
-
* size: {
|
|
10
|
-
* small: "text-xs",
|
|
11
|
-
* large: "text-lg"
|
|
12
|
-
* }
|
|
13
|
-
* }
|
|
14
|
-
*/
|
|
15
|
-
export type Variants = Record<string, Record<string, string>>;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Configuration including defaults and compound variants.
|
|
19
|
-
*/
|
|
20
|
-
export interface VariantsConfig<V extends Variants> {
|
|
21
|
-
base?: string;
|
|
22
|
-
variants: V;
|
|
23
|
-
compoundVariants?: CompoundVariant<V>[];
|
|
24
|
-
defaultVariants?: Partial<OptionsOf<V>>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Rules for class names that are applied for certain variant combinations.
|
|
29
|
-
*/
|
|
30
|
-
export interface CompoundVariant<V extends Variants> {
|
|
31
|
-
variants: Partial<OptionsOf<V>>;
|
|
32
|
-
className: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Only the boolean variants, i.e. ones that have "true" or "false" as options.
|
|
37
|
-
*/
|
|
38
|
-
type BooleanVariants<V extends Variants> = {
|
|
39
|
-
[K in keyof V as V[K] extends { true: any } | { false: any }
|
|
40
|
-
? K
|
|
41
|
-
: never]: V[K];
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Only the variants for which a default options is set.
|
|
46
|
-
*/
|
|
47
|
-
type DefaultVariants<
|
|
48
|
-
C extends VariantsConfig<V>,
|
|
49
|
-
V extends Variants = C["variants"]
|
|
50
|
-
> = {
|
|
51
|
-
[K in keyof V as K extends keyof C["defaultVariants"]
|
|
52
|
-
? K
|
|
53
|
-
: never]: C["variants"][K];
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Names of all optional variants, i.e. booleans or ones with default options.
|
|
58
|
-
*/
|
|
59
|
-
type OptionalVariantNames<
|
|
60
|
-
C extends VariantsConfig<V>,
|
|
61
|
-
V extends Variants = C["variants"]
|
|
62
|
-
> = keyof BooleanVariants<V> | keyof DefaultVariants<C>;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Possible options for all the optional variants.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* {
|
|
69
|
-
* color?: "white" | "green",
|
|
70
|
-
* rounded?: boolean | undefined
|
|
71
|
-
* }
|
|
72
|
-
*/
|
|
73
|
-
type OptionalOptions<
|
|
74
|
-
C extends VariantsConfig<V>,
|
|
75
|
-
V extends Variants = C["variants"]
|
|
76
|
-
> = {
|
|
77
|
-
[K in keyof V as K extends OptionalVariantNames<C>
|
|
78
|
-
? K
|
|
79
|
-
: never]?: OptionsOf<V>[K];
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Possible options for all required variants.
|
|
84
|
-
*
|
|
85
|
-
* @example {
|
|
86
|
-
* size: "small" | "large"
|
|
87
|
-
* }
|
|
88
|
-
*/
|
|
89
|
-
type RequiredOptions<
|
|
90
|
-
C extends VariantsConfig<V>,
|
|
91
|
-
V extends Variants = C["variants"]
|
|
92
|
-
> = {
|
|
93
|
-
[K in keyof V as K extends OptionalVariantNames<C>
|
|
94
|
-
? never
|
|
95
|
-
: K]: OptionsOf<V>[K];
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Utility type to extract the possible options.
|
|
100
|
-
* Converts "true" | "false" options into booleans.
|
|
101
|
-
*
|
|
102
|
-
* @example
|
|
103
|
-
* OptionsOf<{
|
|
104
|
-
* size: { small: "text-xs"; large: "text-lg" };
|
|
105
|
-
* rounded: { true: "rounded-full" }
|
|
106
|
-
* }>
|
|
107
|
-
* ==>
|
|
108
|
-
* {
|
|
109
|
-
* size: "text-xs" | "text-lg";
|
|
110
|
-
* rounded: boolean;
|
|
111
|
-
* }
|
|
112
|
-
*/
|
|
113
|
-
type OptionsOf<V extends Variants> = {
|
|
114
|
-
[K in keyof V]: keyof V[K] extends "true" | "false" ? boolean : keyof V[K];
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Extracts the possible options.
|
|
119
|
-
*/
|
|
120
|
-
export type VariantOptions<
|
|
121
|
-
C extends VariantsConfig<V>,
|
|
122
|
-
V extends Variants = C["variants"]
|
|
123
|
-
> = RequiredOptions<C> & OptionalOptions<C>;
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Without this conversion step, defaultVariants and compoundVariants will
|
|
127
|
-
* allow extra keys, i.e. non-existent variants.
|
|
128
|
-
* See https://github.com/sindresorhus/type-fest/blob/main/source/simplify.d.ts
|
|
129
|
-
*/
|
|
130
|
-
export type Simplify<T> = {
|
|
131
|
-
[K in keyof T]: T[K];
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
export function variants<
|
|
135
|
-
C extends VariantsConfig<V>,
|
|
136
|
-
V extends Variants = C["variants"]
|
|
137
|
-
>(config: Simplify<C>) {
|
|
138
|
-
const { base, variants, compoundVariants, defaultVariants } = config;
|
|
139
|
-
|
|
140
|
-
const isBooleanVariant = (name: keyof V) => {
|
|
141
|
-
const v = variants?.[name];
|
|
142
|
-
return v && ("false" in v || "true" in v);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
return (props: VariantOptions<C>) => {
|
|
146
|
-
const res = [base];
|
|
147
|
-
|
|
148
|
-
const getSelected = (name: keyof V) =>
|
|
149
|
-
(props as any)[name] ??
|
|
150
|
-
defaultVariants?.[name] ??
|
|
151
|
-
(isBooleanVariant(name) ? false : undefined);
|
|
152
|
-
|
|
153
|
-
for (let name in variants) {
|
|
154
|
-
const selected = getSelected(name);
|
|
155
|
-
if (selected !== undefined) res.push(variants[name]?.[selected]);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
for (let { variants, className } of compoundVariants ?? []) {
|
|
159
|
-
const isSelected = (name: string) => getSelected(name) === variants[name];
|
|
160
|
-
if (Object.keys(variants).every(isSelected)) {
|
|
161
|
-
res.push(className);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return res.filter(Boolean).join(" ");
|
|
165
|
-
};
|
|
166
|
-
}
|
package/src/react.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ComponentProps,
|
|
3
|
-
createElement,
|
|
4
|
-
ElementType,
|
|
5
|
-
forwardRef,
|
|
6
|
-
ReactElement,
|
|
7
|
-
Ref,
|
|
8
|
-
} from "react";
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
Variants,
|
|
12
|
-
variants,
|
|
13
|
-
VariantsConfig,
|
|
14
|
-
VariantOptions,
|
|
15
|
-
Simplify,
|
|
16
|
-
} from "./index.js";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Utility type to infer the first argument of a variantProps function.
|
|
20
|
-
*/
|
|
21
|
-
export type VariantPropsOf<T> = T extends (props: infer P) => any ? P : never;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Type for the variantProps() argument – consists of the VariantOptions and an optional className for chaining.
|
|
25
|
-
*/
|
|
26
|
-
type VariantProps<
|
|
27
|
-
C extends VariantsConfig<V>,
|
|
28
|
-
V extends Variants = C["variants"]
|
|
29
|
-
> = VariantOptions<C> & { className?: string };
|
|
30
|
-
|
|
31
|
-
export function variantProps<
|
|
32
|
-
C extends VariantsConfig<V>,
|
|
33
|
-
V extends Variants = C["variants"]
|
|
34
|
-
>(config: Simplify<C>) {
|
|
35
|
-
const variantClassName = variants<C>(config);
|
|
36
|
-
return <P extends VariantProps<C>>(props: P) => {
|
|
37
|
-
const result: any = {};
|
|
38
|
-
|
|
39
|
-
// Pass-through all unrelated props
|
|
40
|
-
for (let prop in props) {
|
|
41
|
-
if (config.variants && !(prop in config.variants)) {
|
|
42
|
-
result[prop] = props[prop];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Add the optionally passed className prop for chaining
|
|
47
|
-
result.className = [props.className, variantClassName(props)]
|
|
48
|
-
.filter(Boolean)
|
|
49
|
-
.join(" ");
|
|
50
|
-
|
|
51
|
-
return result as { className: string } & Omit<P, keyof C["variants"]>;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
type AsProps<T extends ElementType = ElementType> = {
|
|
56
|
-
as?: T;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
type PolymorphicComponentProps<T extends ElementType> = AsProps<T> &
|
|
60
|
-
Omit<ComponentProps<T>, "as">;
|
|
61
|
-
|
|
62
|
-
export function styled<
|
|
63
|
-
T extends ElementType,
|
|
64
|
-
C extends VariantsConfig<V>,
|
|
65
|
-
V extends Variants = C["variants"]
|
|
66
|
-
>(type: T, config: string | Simplify<C>) {
|
|
67
|
-
const styledProps =
|
|
68
|
-
typeof config === "string"
|
|
69
|
-
? variantProps({ base: config, variants: {} })
|
|
70
|
-
: variantProps(config);
|
|
71
|
-
|
|
72
|
-
const Component: <As extends ElementType = T>(
|
|
73
|
-
props: PolymorphicComponentProps<As> & VariantOptions<C>
|
|
74
|
-
) => ReactElement | null = forwardRef(
|
|
75
|
-
({ as, ...props }: AsProps, ref: Ref<Element>) => {
|
|
76
|
-
return createElement(as ?? type, { ...styledProps(props), ref });
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
return Component;
|
|
80
|
-
}
|