Skip to content

Commit edb9d7a

Browse files
committed
feat: 修复类型声明与 VariantProps 导出
1 parent 752f151 commit edb9d7a

File tree

15 files changed

+513
-23
lines changed

15 files changed

+513
-23
lines changed

.changeset/bright-taxis-grow.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@weapp-tailwindcss/cva': patch
3+
'tailwind-variant-v3': patch
4+
'@weapp-tailwindcss/variants': patch
5+
'@weapp-tailwindcss/variants-v3': patch
6+
---
7+
8+
修复类型声明与 VariantProps 导出,并为相关运行时包补充 tsd 类型测试。

benchmark/app/data/2026-01-21.json

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
{
22
"native-webpack": {
33
"babel": [
4-
104.39754100000027
4+
104.39754100000027,
5+
122.44374999999991,
6+
136.74224999999979,
7+
69.01954100000012
58
]
69
},
710
"rax": {
@@ -12,12 +15,18 @@
1215
75.88050000000021,
1316
94.25170900000012,
1417
156.78329200000007,
15-
220.54849999999988
18+
220.54849999999988,
19+
347.4344170000004,
20+
159.3154169999998,
21+
336.95745799999986
1622
]
1723
},
1824
"taro-vue3": {
1925
"babel": [
20-
400.6917500000018
26+
400.6917500000018,
27+
351.56804099999863,
28+
210.5197500000013,
29+
201.8064579999991
2130
]
2231
},
2332
"mpx": {
@@ -28,14 +37,44 @@
2837
36.11462500000016,
2938
7.032875000000786,
3039
7.725166000000172,
31-
280.7640420000007
40+
280.7640420000007,
41+
26.245832999999948,
42+
8.561083000000508,
43+
30.576915999999983,
44+
37.93720799999937,
45+
8.040875000000597,
46+
6.8414170000014565,
47+
336.37275000000045,
48+
17.87304099999983,
49+
10.680916999999681,
50+
30.358791999999994,
51+
39.98158400000011,
52+
17.06354199999987,
53+
10.62237499999901,
54+
306.0850420000006,
55+
23.974874999999884,
56+
7.706832999999278,
57+
9.03191599999991,
58+
16.475750000000517,
59+
7.93224999999984,
60+
12.709749999999985,
61+
265.71058300000004
3262
]
3363
},
3464
"taro-react": {
3565
"babel": [
3666
252.8977500000001,
3767
276.88374999999905,
38-
201.3182909999996
68+
201.3182909999996,
69+
245.46245799999997,
70+
158.1889999999985,
71+
207.97212500000023,
72+
241.1765830000004,
73+
144.8055830000003,
74+
185.1402079999989,
75+
191.37462499999947,
76+
372.5300409999991,
77+
209.50708300000042
3978
]
4079
}
4180
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
"test:core": "vitest run --coverage.enabled --coverage.all=false --project=weapp-tailwindcss",
6262
"test:dev": "vitest",
6363
"test:ui": "vitest --ui",
64+
"tsd": "turbo run tsd",
65+
"tsd:runtime": "turbo run tsd --filter=./packages-runtime/cva --filter=./packages-runtime/tailwind-variant-v3 --filter=./packages-runtime/variants --filter=./packages-runtime/variants-v3",
6466
"e2e": "vitest run -c ./e2e/vitest.e2e.config.ts",
6567
"e2e:dev": "vitest -c ./e2e/vitest.e2e.config.ts",
6668
"e2e:u": "vitest run -u -c ./e2e/vitest.e2e.config.ts",

packages-runtime/cva/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"build": "tsdown",
4848
"test": "vitest run",
4949
"test:dev": "vitest",
50+
"tsd": "tsd",
5051
"release": "pnpm publish",
5152
"lint": "eslint .",
5253
"lint:fix": "eslint . --fix"
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { VariantProps } from '..'
2+
import {
3+
expectAssignable,
4+
expectError,
5+
expectNotAssignable,
6+
expectType,
7+
} from 'tsd'
8+
import { cva } from '..'
9+
10+
const button = cva('inline-flex', {
11+
variants: {
12+
intent: {
13+
primary: 'bg-blue-500',
14+
secondary: 'bg-gray-500',
15+
},
16+
size: {
17+
sm: 'text-sm',
18+
lg: 'text-lg',
19+
},
20+
rounded: {
21+
true: 'rounded-full',
22+
false: 'rounded-none',
23+
},
24+
},
25+
defaultVariants: {
26+
intent: 'primary',
27+
size: 'sm',
28+
},
29+
compoundVariants: [
30+
{
31+
intent: 'primary',
32+
size: 'lg',
33+
class: 'shadow',
34+
},
35+
{
36+
intent: 'secondary',
37+
rounded: true,
38+
className: 'ring-1',
39+
},
40+
],
41+
})
42+
43+
expectType<string>(button())
44+
expectType<string>(button({ class: 'px-4' }))
45+
expectType<string>(button({ intent: null }))
46+
expectError(button({ class: 'px-4', className: 'py-2' }))
47+
expectError(button({ intent: 'tertiary' }))
48+
expectError(button({ rounded: 'true' }))
49+
expectError(button({ size: 'xl' }))
50+
51+
type ButtonVariantProps = VariantProps<typeof button>
52+
const buttonVariantProps: ButtonVariantProps = {
53+
intent: 'secondary',
54+
rounded: false,
55+
}
56+
57+
expectType<{
58+
intent?: 'primary' | 'secondary' | null | undefined
59+
size?: 'sm' | 'lg' | null | undefined
60+
rounded?: boolean | null | undefined
61+
}>(buttonVariantProps)
62+
expectAssignable<ButtonVariantProps>({ size: null })
63+
expectAssignable<ButtonVariantProps>({ rounded: true })
64+
expectNotAssignable<ButtonVariantProps>({ class: 'px-4' })
65+
expectNotAssignable<ButtonVariantProps>({ className: 'py-2' })

packages-runtime/tailwind-variant-v3/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"build": "tsdown",
4343
"test": "vitest run",
4444
"test:dev": "vitest",
45+
"tsd": "tsd",
4546
"bench": "vitest bench test/tv.bench.ts",
4647
"release": "pnpm publish",
4748
"lint": "eslint .",

packages-runtime/tailwind-variant-v3/src/types.d.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export declare const cnBase: <T extends CnOptions>(...classes: T) => CnReturn
5252
export declare const cn: <T extends CnOptions>(...classes: T) => (config?: TWMConfig) => CnReturn
5353

5454
// compare if the value is true or array of values
55-
export type isTrueOrArray<T> = [Extract<T, true | unknown[]>] extends [never] ? false : true
55+
export type isTrueOrArray<T> = [T] extends [true | readonly unknown[]] ? true : false
5656

5757
export type WithInitialScreen<T extends Array<string>>
5858
= ['initial', ...T]
@@ -158,7 +158,7 @@ export type TVScreenPropsValue<
158158
type TVPropsWithoutExtended<
159159
V extends TVVariants<S>,
160160
S extends TVSlots,
161-
C extends TVConfig<V, EV>,
161+
C extends TVConfig<V, undefined>,
162162
> = V extends undefined
163163
? ClassProp<ClassValue>
164164
: {
@@ -168,7 +168,7 @@ type TVPropsWithoutExtended<
168168
} & ClassProp<ClassValue>
169169

170170
type TVPropsExtendedWithoutVariants<
171-
C extends TVConfig<any, EV>,
171+
C extends TVConfig<undefined, EV>,
172172
EV extends TVVariants<ES>,
173173
ES extends TVSlots,
174174
> = {
@@ -182,6 +182,7 @@ type TVPropsExtendedWithVariants<
182182
S extends TVSlots,
183183
C extends TVConfig<V, EV>,
184184
EV extends TVVariants<ES>,
185+
ES extends TVSlots,
185186
> = {
186187
[K in keyof V | keyof EV]?: isTrueOrArray<C['responsiveVariants']> extends true
187188
? | (K extends keyof V ? StringToBoolean<keyof V[K]> : never)
@@ -201,7 +202,7 @@ type TVPropsWithExtended<
201202
ES extends TVSlots,
202203
> = V extends undefined
203204
? TVPropsExtendedWithoutVariants<C, EV, ES>
204-
: TVPropsExtendedWithVariants<V, S, C, EV>
205+
: TVPropsExtendedWithVariants<V, S, C, EV, ES>
205206

206207
export type TVProps<
207208
V extends TVVariants<S>,
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import type { VariantProps } from '..'
2+
import {
3+
expectAssignable,
4+
expectError,
5+
expectNotAssignable,
6+
expectType,
7+
} from 'tsd'
8+
import {
9+
cn,
10+
cnBase,
11+
createTV,
12+
tv,
13+
14+
} from '..'
15+
16+
expectType<string | undefined>(cnBase('px-2', false))
17+
expectType<string | undefined>(cn('px-2', undefined)())
18+
19+
const button = tv({
20+
base: 'inline-flex',
21+
variants: {
22+
intent: {
23+
primary: 'bg-blue-500',
24+
secondary: 'bg-gray-500',
25+
},
26+
size: {
27+
sm: 'text-sm',
28+
lg: 'text-lg',
29+
},
30+
rounded: {
31+
true: 'rounded-full',
32+
false: 'rounded-none',
33+
},
34+
},
35+
defaultVariants: {
36+
size: 'sm',
37+
},
38+
})
39+
40+
expectType<string>(button())
41+
expectType<string>(button({ class: 'px-2' }))
42+
expectError(button({ class: 'px-2', className: 'py-2' }))
43+
expectError(button({ intent: 'tertiary' }))
44+
expectError(button({ rounded: 'true' }))
45+
expectError(button({ size: 'xl' }))
46+
47+
type ButtonVariantProps = VariantProps<typeof button>
48+
const buttonVariantProps: ButtonVariantProps = {
49+
intent: 'primary',
50+
rounded: true,
51+
}
52+
53+
expectType<{
54+
intent?: 'primary' | 'secondary' | undefined
55+
size?: 'sm' | 'lg' | undefined
56+
rounded?: boolean | undefined
57+
}>(buttonVariantProps)
58+
expectNotAssignable<ButtonVariantProps>({ class: 'px-2' })
59+
expectNotAssignable<ButtonVariantProps>({ className: 'py-2' })
60+
61+
const baseButton = tv({
62+
variants: {
63+
tone: {
64+
solid: 'bg-black',
65+
soft: 'bg-gray-200',
66+
},
67+
},
68+
})
69+
70+
const extendedButton = tv({
71+
extend: baseButton,
72+
variants: {
73+
size: {
74+
sm: 'text-sm',
75+
lg: 'text-lg',
76+
},
77+
},
78+
})
79+
80+
type ExtendedButtonProps = VariantProps<typeof extendedButton>
81+
expectAssignable<ExtendedButtonProps>({ tone: 'solid', size: 'sm' })
82+
expectError(extendedButton({ tone: 'ghost' }))
83+
84+
const card = tv({
85+
base: 'card',
86+
slots: {
87+
root: 'card-root',
88+
icon: 'card-icon',
89+
},
90+
variants: {
91+
size: {
92+
sm: { root: 'text-sm', icon: 'h-4' },
93+
lg: { root: 'text-lg', icon: 'h-6' },
94+
},
95+
},
96+
defaultVariants: {
97+
size: 'sm',
98+
},
99+
})
100+
101+
const cardSlots = card({ size: 'sm' })
102+
expectType<string>(cardSlots.base())
103+
expectType<string>(cardSlots.root())
104+
expectType<string>(cardSlots.icon())
105+
expectType<string>(cardSlots.root({ size: 'lg' }))
106+
expectError(cardSlots.root({ size: 'xl' }))
107+
108+
const createResponsive = createTV({ responsiveVariants: ['sm', 'md'] as const })
109+
const responsiveButton = createResponsive({
110+
variants: {
111+
size: {
112+
sm: 'text-sm',
113+
lg: 'text-lg',
114+
},
115+
},
116+
})
117+
118+
expectType<string>(responsiveButton())
119+
120+
type ResponsiveProps = VariantProps<typeof responsiveButton>
121+
expectAssignable<ResponsiveProps>({ size: 'sm' })
122+
expectAssignable<ResponsiveProps>({ size: { initial: 'sm', md: 'lg' } })
123+
expectError(responsiveButton({ size: { lg: 'sm' } }))

packages-runtime/variants-v3/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"build": "tsdown",
4343
"test": "vitest run",
4444
"test:dev": "vitest",
45+
"tsd": "tsd",
4546
"release": "pnpm publish",
4647
"lint": "eslint .",
4748
"lint:fix": "eslint . --fix"

packages-runtime/variants-v3/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,4 @@ export type {
228228
TVConfig,
229229
TWMConfig,
230230
}
231+
export type { VariantProps } from 'tailwind-variant-v3'

0 commit comments

Comments
 (0)