nestable-tailwind-variants 0.2.0 → 0.3.0
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 +172 -85
- package/dist/cache.d.ts +1 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/merge.d.ts +6 -6
- package/dist/merge.d.ts.map +1 -1
- package/dist/merge.js +2 -2
- package/dist/merge.js.map +1 -1
- package/dist/ntv.d.ts +6 -6
- package/dist/ntv.d.ts.map +1 -1
- package/dist/ntv.js +2 -18
- package/dist/ntv.js.map +1 -1
- package/dist/resolver.d.ts +1 -1
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +10 -16
- package/dist/resolver.js.map +1 -1
- package/dist/types.d.ts +44 -79
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Tailwind CSS variant library with nestable conditions for compound styling instead of flat compoundVariants.
|
|
4
4
|
|
|
5
|
-
Inspired by [React Spectrum's
|
|
5
|
+
Inspired by [React Spectrum's conditional styles](https://react-spectrum.adobe.com/styling#conditional-styles) and [Tailwind Variants](https://www.tailwind-variants.org/).
|
|
6
6
|
|
|
7
7
|
## Why nestable-tailwind-variants?
|
|
8
8
|
|
|
@@ -73,11 +73,11 @@ npm install nestable-tailwind-variants
|
|
|
73
73
|
|
|
74
74
|
### `$base` - Always-applied styles
|
|
75
75
|
|
|
76
|
-
The `$base` property defines styles that are always
|
|
76
|
+
The `$base` property defines styles that are always applied at that level. It can be used at the top level or nested inside variants and conditions:
|
|
77
77
|
|
|
78
78
|
```ts
|
|
79
79
|
interface CardProps {
|
|
80
|
-
variant
|
|
80
|
+
variant?: 'elevated' | 'flat';
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
const card = ntv<CardProps>({
|
|
@@ -96,14 +96,129 @@ card({ variant: 'elevated' });
|
|
|
96
96
|
// Note: shadow-md is replaced by shadow-xl via tailwind-merge
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
When nested inside a variant or condition, `$base` applies whenever that context is entered:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
interface ButtonProps {
|
|
103
|
+
variant?: 'primary' | 'secondary';
|
|
104
|
+
size?: 'sm' | 'lg';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const button = ntv<ButtonProps>({
|
|
108
|
+
$base: 'px-4 py-2',
|
|
109
|
+
variant: {
|
|
110
|
+
primary: {
|
|
111
|
+
$base: 'bg-blue-500 text-white', // Applied when variant='primary'
|
|
112
|
+
size: {
|
|
113
|
+
sm: 'text-sm',
|
|
114
|
+
lg: 'text-lg',
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
secondary: 'bg-gray-500',
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
button({ variant: 'primary' });
|
|
122
|
+
// => 'px-4 py-2 bg-blue-500 text-white'
|
|
123
|
+
|
|
124
|
+
button({ variant: 'primary', size: 'sm' });
|
|
125
|
+
// => 'px-4 py-2 bg-blue-500 text-white text-sm'
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `$default` - Fallback styles
|
|
129
|
+
|
|
130
|
+
Use `$default` for styles applied when no conditions match at that level. Within variants, `$default` can also contain nested conditions:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
interface ChipProps {
|
|
134
|
+
variant?: 'filled' | 'outlined';
|
|
135
|
+
isSelected?: boolean;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const chip = ntv<ChipProps>({
|
|
139
|
+
$base: 'inline-flex items-center rounded-full px-3 py-1',
|
|
140
|
+
variant: {
|
|
141
|
+
$default: {
|
|
142
|
+
$base: 'bg-gray-100', // Applied when variant is not specified
|
|
143
|
+
isSelected: 'bg-gray-200', // Applied when isSelected and no variant
|
|
144
|
+
},
|
|
145
|
+
filled: {
|
|
146
|
+
$default: 'bg-gray-200 text-gray-800', // Applied when isSelected is false
|
|
147
|
+
isSelected: 'bg-blue-500 text-white',
|
|
148
|
+
},
|
|
149
|
+
outlined: {
|
|
150
|
+
$default: 'border border-gray-300 text-gray-800',
|
|
151
|
+
isSelected: 'border-blue-500 text-blue-500',
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
chip();
|
|
157
|
+
// => 'inline-flex items-center rounded-full px-3 py-1 bg-gray-100'
|
|
158
|
+
|
|
159
|
+
chip({ isSelected: true });
|
|
160
|
+
// => 'inline-flex items-center rounded-full px-3 py-1 bg-gray-200'
|
|
161
|
+
|
|
162
|
+
chip({ variant: 'filled' });
|
|
163
|
+
// => 'inline-flex items-center rounded-full px-3 py-1 bg-gray-200 text-gray-800'
|
|
164
|
+
|
|
165
|
+
chip({ variant: 'filled', isSelected: true });
|
|
166
|
+
// => 'inline-flex items-center rounded-full px-3 py-1 bg-blue-500 text-white'
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
> **Note:** Within variant conditions, `$default` is only available when the variant key is optional. Required variant keys always have a value provided, so there's no fallback case:
|
|
170
|
+
>
|
|
171
|
+
> ```ts
|
|
172
|
+
> // ❌ Error: variant is required, so $default is not allowed
|
|
173
|
+
> ntv<{ variant: 'a' | 'b' }>({
|
|
174
|
+
> variant: {
|
|
175
|
+
> a: 'a-class',
|
|
176
|
+
> b: 'b-class',
|
|
177
|
+
> $default: 'default-class', // TypeScript error
|
|
178
|
+
> },
|
|
179
|
+
> });
|
|
180
|
+
>
|
|
181
|
+
> // ✅ OK: variant is optional, so $default is allowed
|
|
182
|
+
> ntv<{ variant?: 'a' | 'b' }>({
|
|
183
|
+
> variant: {
|
|
184
|
+
> a: 'a-class',
|
|
185
|
+
> b: 'b-class',
|
|
186
|
+
> $default: 'default-class',
|
|
187
|
+
> },
|
|
188
|
+
> });
|
|
189
|
+
> ```
|
|
190
|
+
|
|
191
|
+
### `$base` vs `$default`
|
|
192
|
+
|
|
193
|
+
- **`$base`**: Always applied, regardless of whether conditions match
|
|
194
|
+
- **`$default`**: Only applied when no conditions match
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
interface ButtonProps {
|
|
198
|
+
isDisabled?: boolean;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const button = ntv<ButtonProps>({
|
|
202
|
+
$base: 'px-4 py-2', // Always applied
|
|
203
|
+
$default: 'bg-blue-500', // Only applied when isDisabled is false
|
|
204
|
+
isDisabled: 'bg-gray-300 cursor-not-allowed',
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
button();
|
|
208
|
+
// => 'px-4 py-2 bg-blue-500'
|
|
209
|
+
|
|
210
|
+
button({ isDisabled: true });
|
|
211
|
+
// => 'px-4 py-2 bg-gray-300 cursor-not-allowed'
|
|
212
|
+
```
|
|
213
|
+
|
|
99
214
|
### Variants - String-based selection
|
|
100
215
|
|
|
101
216
|
Define variants as objects mapping variant values to class names:
|
|
102
217
|
|
|
103
218
|
```ts
|
|
104
219
|
interface BadgeProps {
|
|
105
|
-
size
|
|
106
|
-
color
|
|
220
|
+
size?: 'sm' | 'md' | 'lg';
|
|
221
|
+
color?: 'info' | 'success' | 'warning';
|
|
107
222
|
}
|
|
108
223
|
|
|
109
224
|
const badge = ntv<BadgeProps>({
|
|
@@ -130,10 +245,10 @@ Keys matching `is[A-Z]*` or `allows[A-Z]*` are treated as boolean conditions:
|
|
|
130
245
|
|
|
131
246
|
```ts
|
|
132
247
|
interface InputProps {
|
|
133
|
-
isFocused
|
|
134
|
-
isDisabled
|
|
135
|
-
isInvalid
|
|
136
|
-
allowsClearing
|
|
248
|
+
isFocused?: boolean;
|
|
249
|
+
isDisabled?: boolean;
|
|
250
|
+
isInvalid?: boolean;
|
|
251
|
+
allowsClearing?: boolean;
|
|
137
252
|
}
|
|
138
253
|
|
|
139
254
|
const input = ntv<InputProps>({
|
|
@@ -151,65 +266,6 @@ input({ isDisabled: true, isInvalid: true });
|
|
|
151
266
|
// => 'border rounded px-3 py-2 bg-gray-100 text-gray-400 cursor-not-allowed border-red-500 text-red-600'
|
|
152
267
|
```
|
|
153
268
|
|
|
154
|
-
### `$default` - Fallback styles
|
|
155
|
-
|
|
156
|
-
Use `$default` for styles applied when no conditions match:
|
|
157
|
-
|
|
158
|
-
```ts
|
|
159
|
-
interface TextProps {
|
|
160
|
-
variant: 'primary' | 'danger';
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const text = ntv<TextProps>({
|
|
164
|
-
$default: 'text-gray-500',
|
|
165
|
-
variant: {
|
|
166
|
-
primary: 'text-blue-600',
|
|
167
|
-
danger: 'text-red-600',
|
|
168
|
-
},
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
text();
|
|
172
|
-
// => 'text-gray-500'
|
|
173
|
-
|
|
174
|
-
text({ variant: 'primary' });
|
|
175
|
-
// => 'text-blue-600'
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
When `$default` is nested inside variants, they accumulate only when no conditions match at each level:
|
|
179
|
-
|
|
180
|
-
```ts
|
|
181
|
-
interface Props {
|
|
182
|
-
variant: 'primary';
|
|
183
|
-
size: 'large';
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const styles = ntv<Props>({
|
|
187
|
-
$base: 'base',
|
|
188
|
-
$default: 'root-default',
|
|
189
|
-
variant: {
|
|
190
|
-
$default: 'variant-default',
|
|
191
|
-
primary: {
|
|
192
|
-
size: {
|
|
193
|
-
$default: 'size-default',
|
|
194
|
-
large: 'size-large',
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
styles();
|
|
201
|
-
// => 'base root-default variant-default'
|
|
202
|
-
// No conditions matched, so $defaults accumulate
|
|
203
|
-
|
|
204
|
-
styles({ variant: 'primary' });
|
|
205
|
-
// => 'base size-default'
|
|
206
|
-
// variant matched, so only nested $default is applied
|
|
207
|
-
|
|
208
|
-
styles({ variant: 'primary', size: 'large' });
|
|
209
|
-
// => 'base size-large'
|
|
210
|
-
// Both matched, so no $defaults are applied
|
|
211
|
-
```
|
|
212
|
-
|
|
213
269
|
## Nested Conditions
|
|
214
270
|
|
|
215
271
|
The core feature of nestable-tailwind-variants is the ability to nest conditions inside variants.
|
|
@@ -218,8 +274,8 @@ The core feature of nestable-tailwind-variants is the ability to nest conditions
|
|
|
218
274
|
|
|
219
275
|
```ts
|
|
220
276
|
interface ChipProps {
|
|
221
|
-
variant
|
|
222
|
-
isSelected
|
|
277
|
+
variant?: 'filled' | 'outlined';
|
|
278
|
+
isSelected?: boolean;
|
|
223
279
|
}
|
|
224
280
|
|
|
225
281
|
const chip = ntv<ChipProps>({
|
|
@@ -252,10 +308,10 @@ You can nest conditions to any depth:
|
|
|
252
308
|
|
|
253
309
|
```ts
|
|
254
310
|
interface ButtonProps {
|
|
255
|
-
variant
|
|
256
|
-
isHovered
|
|
257
|
-
isPressed
|
|
258
|
-
isDisabled
|
|
311
|
+
variant?: 'primary';
|
|
312
|
+
isHovered?: boolean;
|
|
313
|
+
isPressed?: boolean;
|
|
314
|
+
isDisabled?: boolean;
|
|
259
315
|
}
|
|
260
316
|
|
|
261
317
|
const button = ntv<ButtonProps>({
|
|
@@ -294,7 +350,7 @@ Merge multiple style functions into one. Later functions take precedence:
|
|
|
294
350
|
import { ntv, mergeNtv } from 'nestable-tailwind-variants';
|
|
295
351
|
|
|
296
352
|
interface BaseButtonProps {
|
|
297
|
-
size
|
|
353
|
+
size?: 'sm' | 'md';
|
|
298
354
|
}
|
|
299
355
|
|
|
300
356
|
const baseButton = ntv<BaseButtonProps>({
|
|
@@ -306,7 +362,7 @@ const baseButton = ntv<BaseButtonProps>({
|
|
|
306
362
|
});
|
|
307
363
|
|
|
308
364
|
interface ColoredButtonProps {
|
|
309
|
-
variant
|
|
365
|
+
variant?: 'primary' | 'secondary';
|
|
310
366
|
}
|
|
311
367
|
|
|
312
368
|
const coloredButton = ntv<ColoredButtonProps>({
|
|
@@ -328,7 +384,7 @@ Pass additional classes using `class` or `className`:
|
|
|
328
384
|
|
|
329
385
|
```ts
|
|
330
386
|
interface BoxProps {
|
|
331
|
-
variant
|
|
387
|
+
variant?: 'primary' | 'secondary';
|
|
332
388
|
}
|
|
333
389
|
|
|
334
390
|
const box = ntv<BoxProps>({
|
|
@@ -435,8 +491,39 @@ const button = ntv<ButtonProps>({
|
|
|
435
491
|
isDisabled: 'opacity-50',
|
|
436
492
|
});
|
|
437
493
|
|
|
438
|
-
|
|
494
|
+
// All props are required - props parameter is mandatory
|
|
495
|
+
button({ variant: 'primary', size: 'lg', isDisabled: false }); // ✅ OK
|
|
439
496
|
button({ variant: 'tertiary' }); // ❌ Error: 'tertiary' is not assignable
|
|
497
|
+
button({ variant: 'primary' }); // ❌ Error: missing 'size' and 'isDisabled'
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Use optional properties (`?`) when you want to allow calling the style function without providing all props:
|
|
501
|
+
|
|
502
|
+
```ts
|
|
503
|
+
interface ButtonProps {
|
|
504
|
+
variant?: 'primary' | 'secondary';
|
|
505
|
+
size?: 'sm' | 'md' | 'lg';
|
|
506
|
+
isDisabled?: boolean;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const button = ntv<ButtonProps>({
|
|
510
|
+
$base: 'rounded',
|
|
511
|
+
variant: {
|
|
512
|
+
primary: 'bg-blue-500',
|
|
513
|
+
secondary: 'bg-gray-200',
|
|
514
|
+
},
|
|
515
|
+
size: {
|
|
516
|
+
sm: 'text-sm',
|
|
517
|
+
md: 'text-base',
|
|
518
|
+
lg: 'text-lg',
|
|
519
|
+
},
|
|
520
|
+
isDisabled: 'opacity-50',
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// All props are optional - props parameter can be omitted
|
|
524
|
+
button(); // ✅ OK
|
|
525
|
+
button({ variant: 'primary' }); // ✅ OK
|
|
526
|
+
button({ variant: 'primary', size: 'lg' }); // ✅ OK
|
|
440
527
|
```
|
|
441
528
|
|
|
442
529
|
Omitting the type argument when the scheme has keys disables type checking. Provide explicit type arguments when possible for better type safety.
|
|
@@ -601,13 +688,13 @@ export default [
|
|
|
601
688
|
|
|
602
689
|
### Scheme Properties
|
|
603
690
|
|
|
604
|
-
| Property | Description
|
|
605
|
-
| -------------- |
|
|
606
|
-
| `$base` | Classes always applied (top-level
|
|
607
|
-
| `$default` | Fallback classes when no conditions match
|
|
608
|
-
| `is[A-Z]*` | Boolean condition (e.g., `isSelected`, `isDisabled`)
|
|
609
|
-
| `allows[A-Z]*` | Boolean condition (e.g., `allowsRemoving`)
|
|
610
|
-
| `[key]` | Variant object mapping values to classes
|
|
691
|
+
| Property | Description |
|
|
692
|
+
| -------------- | ------------------------------------------------------------------------------------------- |
|
|
693
|
+
| `$base` | Classes always applied at that level (can be used at top-level or nested within conditions) |
|
|
694
|
+
| `$default` | Fallback classes when no conditions match at that level |
|
|
695
|
+
| `is[A-Z]*` | Boolean condition (e.g., `isSelected`, `isDisabled`) |
|
|
696
|
+
| `allows[A-Z]*` | Boolean condition (e.g., `allowsRemoving`) |
|
|
697
|
+
| `[key]` | Variant object mapping values to classes |
|
|
611
698
|
|
|
612
699
|
## License
|
|
613
700
|
|
package/dist/cache.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { extendTailwindMerge } from 'tailwind-merge';
|
|
2
|
-
import type {
|
|
3
|
-
type TwMergeConfig = NonNullable<NtvOptions['twMergeConfig']>;
|
|
2
|
+
import type { TwMergeConfig } from './types.js';
|
|
4
3
|
type TwMergeFn = ReturnType<typeof extendTailwindMerge>;
|
|
5
4
|
export declare function getCachedTwMerge(config: TwMergeConfig): TwMergeFn;
|
|
6
5
|
export {};
|
package/dist/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAIxD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAOjE"}
|
package/dist/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAKrD,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;AAElD,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,IAAI,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { createMergeNtv, mergeNtv, mergeNtvWithOptions } from './merge.js';
|
|
2
2
|
export { createNtv, ntv } from './ntv.js';
|
|
3
|
-
export type { ClassProp, ClassValue, NtvOptions, TwMergeConfig } from './types.js';
|
|
3
|
+
export type { ClassProp, ClassValue, MergeStyleFunctionProps, NtvOptions, Props, PropValue, Scheme, StyleFunction, TwMergeConfig, } from './types.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EACV,SAAS,EACT,UAAU,EACV,uBAAuB,EACvB,UAAU,EACV,KAAK,EACL,SAAS,EACT,MAAM,EACN,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC"}
|
package/dist/merge.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MergeStyleFunctionProps, NtvOptions, StyleFunction } from './types.js';
|
|
1
|
+
import type { AnyStyleFunction, MergeStyleFunctionProps, NtvOptions, StyleFunction } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Create a merged style function with custom options (curried version).
|
|
4
4
|
*
|
|
@@ -11,7 +11,7 @@ import type { MergeStyleFunctionProps, NtvOptions, StyleFunction } from './types
|
|
|
11
11
|
* styles({ variant: 'primary' });
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
|
-
export declare function mergeNtvWithOptions<T extends readonly
|
|
14
|
+
export declare function mergeNtvWithOptions<T extends readonly AnyStyleFunction[]>(...styleFns: T): (options?: NtvOptions) => StyleFunction<MergeStyleFunctionProps<T>>;
|
|
15
15
|
/**
|
|
16
16
|
* Merge multiple style functions into a single style function.
|
|
17
17
|
* Later functions take precedence over earlier ones (via tailwind-merge).
|
|
@@ -21,11 +21,11 @@ export declare function mergeNtvWithOptions<T extends readonly StyleFunction<any
|
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```ts
|
|
24
|
-
* const colorStyles = ntv<{ color
|
|
24
|
+
* const colorStyles = ntv<{ color?: 'red' | 'blue' }>({
|
|
25
25
|
* color: { red: 'text-red', blue: 'text-blue' },
|
|
26
26
|
* });
|
|
27
27
|
*
|
|
28
|
-
* const sizeStyles = ntv<{ size
|
|
28
|
+
* const sizeStyles = ntv<{ size?: 'sm' | 'lg' }>({
|
|
29
29
|
* size: { sm: 'text-sm', lg: 'text-lg' },
|
|
30
30
|
* });
|
|
31
31
|
*
|
|
@@ -33,7 +33,7 @@ export declare function mergeNtvWithOptions<T extends readonly StyleFunction<any
|
|
|
33
33
|
* styles({ color: 'red', size: 'lg' }); // 'text-red text-lg'
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
export declare function mergeNtv<T extends readonly
|
|
36
|
+
export declare function mergeNtv<T extends readonly AnyStyleFunction[]>(...styleFns: T): StyleFunction<MergeStyleFunctionProps<T>>;
|
|
37
37
|
/**
|
|
38
38
|
* Create a pre-configured mergeNtv function with fixed options.
|
|
39
39
|
*
|
|
@@ -55,5 +55,5 @@ export declare function mergeNtv<T extends readonly StyleFunction<any>[]>(...sty
|
|
|
55
55
|
* const styles = myMergeNtv(baseStyles, overrideStyles);
|
|
56
56
|
* ```
|
|
57
57
|
*/
|
|
58
|
-
export declare function createMergeNtv(defaultOptions: NtvOptions): <T extends readonly
|
|
58
|
+
export declare function createMergeNtv(defaultOptions: NtvOptions): <T extends readonly AnyStyleFunction[]>(...styleFns: T) => StyleFunction<MergeStyleFunctionProps<T>>;
|
|
59
59
|
//# sourceMappingURL=merge.d.ts.map
|
package/dist/merge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAEhB,uBAAuB,EACvB,UAAU,EACV,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,SAAS,gBAAgB,EAAE,EACvE,GAAG,QAAQ,EAAE,CAAC,GACb,CAAC,OAAO,CAAC,EAAE,UAAU,KAAK,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAoBrE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,SAAS,gBAAgB,EAAE,EAC5D,GAAG,QAAQ,EAAE,CAAC,GACb,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAE3C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,UAAU,GACzB,CAAC,CAAC,SAAS,SAAS,gBAAgB,EAAE,EACvC,GAAG,QAAQ,EAAE,CAAC,KACX,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAQ7C"}
|
package/dist/merge.js
CHANGED
|
@@ -34,11 +34,11 @@ export function mergeNtvWithOptions(...styleFns) {
|
|
|
34
34
|
*
|
|
35
35
|
* @example
|
|
36
36
|
* ```ts
|
|
37
|
-
* const colorStyles = ntv<{ color
|
|
37
|
+
* const colorStyles = ntv<{ color?: 'red' | 'blue' }>({
|
|
38
38
|
* color: { red: 'text-red', blue: 'text-blue' },
|
|
39
39
|
* });
|
|
40
40
|
*
|
|
41
|
-
* const sizeStyles = ntv<{ size
|
|
41
|
+
* const sizeStyles = ntv<{ size?: 'sm' | 'lg' }>({
|
|
42
42
|
* size: { sm: 'text-sm', lg: 'text-lg' },
|
|
43
43
|
* });
|
|
44
44
|
*
|
package/dist/merge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAQjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAG,QAAW;IAEd,OAAO,SAAS,mBAAmB,CAAC,EAClC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,aAAa,MACC,EAAE;QAChB,MAAM,OAAO,GAAG,WAAW;YACzB,CAAC,CAAC,aAAa;gBACb,CAAC,CAAC,gBAAgB,CAAC,aAAa,CAAC;gBACjC,CAAC,CAAC,OAAO;YACX,CAAC,CAAC,MAAM,CAAC;QAEX,OAAO,SAAS,aAAa,CAAC,EAC5B,KAAK,EAAE,SAAS,EAChB,SAAS,EAAE,aAAa,EACxB,GAAG,KAAK,KAC+B,EAAE;YACzC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAY,CAAC,CAAC,CAAC;YAC5D,OAAO,OAAO,CAAC,GAAG,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QAC5D,CAAyD,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,QAAQ,CACtB,GAAG,QAAW;IAEd,OAAO,mBAAmB,CAAC,GAAG,QAAQ,CAAC,EAA0D,CAAC;AACpG,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,cAAc,CAC5B,cAA0B;IAI1B,OAAO,SAAS,kBAAkB,CAChC,GAAG,QAAW;QAEd,OAAO,mBAAmB,CAAC,GAAG,QAAQ,CAAC,CAAC,cAAc,CAErD,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/ntv.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NtvOptions,
|
|
1
|
+
import type { NtvOptions, Scheme, StyleFunction } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Create a nestable tailwind variants style function.
|
|
4
4
|
*
|
|
@@ -8,7 +8,7 @@ import type { NtvOptions, NtvProps, NtvScheme, SchemeFor, StyleFunction } from '
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```ts
|
|
11
|
-
* type ButtonProps = { variant
|
|
11
|
+
* type ButtonProps = { variant?: 'primary' | 'secondary'; isDisabled?: boolean };
|
|
12
12
|
*
|
|
13
13
|
* const button = ntv<ButtonProps>({
|
|
14
14
|
* $base: 'px-4 py-2 rounded',
|
|
@@ -23,8 +23,8 @@ import type { NtvOptions, NtvProps, NtvScheme, SchemeFor, StyleFunction } from '
|
|
|
23
23
|
* button({ variant: 'primary', isDisabled: true }); // 'px-4 py-2 rounded bg-blue-500 text-white opacity-50 cursor-not-allowed'
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
export declare function ntv<TProps extends
|
|
27
|
-
export declare function ntv(scheme:
|
|
26
|
+
export declare function ntv<TProps extends {}>(scheme: Scheme<TProps>, options?: NtvOptions): StyleFunction<TProps>;
|
|
27
|
+
export declare function ntv(scheme: Scheme & Record<string, unknown>, options?: NtvOptions): StyleFunction<any>;
|
|
28
28
|
/**
|
|
29
29
|
* Create a pre-configured ntv function with fixed options.
|
|
30
30
|
*
|
|
@@ -53,7 +53,7 @@ export declare function ntv(scheme: NtvScheme, options?: NtvOptions): StyleFunct
|
|
|
53
53
|
* ```
|
|
54
54
|
*/
|
|
55
55
|
export declare function createNtv(defaultOptions: NtvOptions): {
|
|
56
|
-
<TProps extends
|
|
57
|
-
(scheme:
|
|
56
|
+
<TProps extends {}>(scheme: Scheme<TProps>): StyleFunction<TProps>;
|
|
57
|
+
(scheme: Scheme & Record<string, unknown>): StyleFunction<any>;
|
|
58
58
|
};
|
|
59
59
|
//# sourceMappingURL=ntv.d.ts.map
|
package/dist/ntv.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ntv.d.ts","sourceRoot":"","sources":["../src/ntv.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ntv.d.ts","sourceRoot":"","sources":["../src/ntv.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAa/E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,wBAAgB,GAAG,CAAC,MAAM,SAAS,EAAE,EACnC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EACtB,OAAO,CAAC,EAAE,UAAU,GACnB,aAAa,CAAC,MAAM,CAAC,CAAC;AACzB,wBAAgB,GAAG,CACjB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,OAAO,CAAC,EAAE,UAAU,GACnB,aAAa,CAAC,GAAG,CAAC,CAAC;AAuBtB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,SAAS,CAAC,cAAc,EAAE,UAAU,GAAG;IAErD,CAAC,MAAM,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACnE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;CAChE,CAIA"}
|
package/dist/ntv.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { twJoin, twMerge } from 'tailwind-merge';
|
|
2
2
|
import { getCachedTwMerge } from './cache.js';
|
|
3
3
|
import { resolveConditions } from './resolver.js';
|
|
4
|
-
function isPlainObject(value) {
|
|
5
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
6
|
-
}
|
|
7
4
|
function validateScheme(scheme) {
|
|
8
5
|
if ('class' in scheme) {
|
|
9
6
|
throw new Error('The "class" property is not allowed in ntv scheme. Use "$base" instead.');
|
|
@@ -11,30 +8,17 @@ function validateScheme(scheme) {
|
|
|
11
8
|
if ('className' in scheme) {
|
|
12
9
|
throw new Error('The "className" property is not allowed in ntv scheme. Use "$base" instead.');
|
|
13
10
|
}
|
|
14
|
-
validateNoNestedSpecialKeys(scheme, false);
|
|
15
|
-
}
|
|
16
|
-
function validateNoNestedSpecialKeys(obj, isNested) {
|
|
17
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
18
|
-
// Check if this is a top-level-only key in a nested context
|
|
19
|
-
if (isNested && key === '$base') {
|
|
20
|
-
throw new Error(`The "${key}" property is only allowed at the top level of ntv scheme. It cannot be nested inside variants or conditions.`);
|
|
21
|
-
}
|
|
22
|
-
// Recursively validate nested objects
|
|
23
|
-
if (isPlainObject(value)) {
|
|
24
|
-
validateNoNestedSpecialKeys(value, true);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
11
|
}
|
|
28
12
|
export function ntv(scheme, { twMerge: usesTwMerge = true, twMergeConfig } = {}) {
|
|
29
13
|
validateScheme(scheme);
|
|
30
|
-
const { $base, ...conditions } = scheme;
|
|
31
14
|
const mergeFn = usesTwMerge
|
|
32
15
|
? twMergeConfig
|
|
33
16
|
? getCachedTwMerge(twMergeConfig)
|
|
34
17
|
: twMerge
|
|
35
18
|
: twJoin;
|
|
36
19
|
return function styleFn({ class: slotClass, className: slotClassName, ...props } = {}) {
|
|
37
|
-
|
|
20
|
+
const resolvedClasses = resolveConditions(scheme, props);
|
|
21
|
+
return mergeFn(...resolvedClasses, slotClass, slotClassName);
|
|
38
22
|
};
|
|
39
23
|
}
|
|
40
24
|
/**
|
package/dist/ntv.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ntv.js","sourceRoot":"","sources":["../src/ntv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ntv.js","sourceRoot":"","sources":["../src/ntv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,SAAS,cAAc,CAAC,MAAc;IACpC,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,WAAW,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;AACH,CAAC;AAmCD,MAAM,UAAU,GAAG,CACjB,MAAc,EACd,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,EAAE,aAAa,KAAiB,EAAE;IAE/D,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,MAAM,OAAO,GAAG,WAAW;QACzB,CAAC,CAAC,aAAa;YACb,CAAC,CAAC,gBAAgB,CAAC,aAAa,CAAC;YACjC,CAAC,CAAC,OAAO;QACX,CAAC,CAAC,MAAM,CAAC;IAEX,OAAO,SAAS,OAAO,CAAC,EACtB,KAAK,EAAE,SAAS,EAChB,SAAS,EAAE,aAAa,EACxB,GAAG,KAAK,KAC+B,EAAE;QACzC,MAAM,eAAe,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACzD,OAAO,OAAO,CAAC,GAAG,eAAe,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;IAC/D,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,SAAS,CAAC,cAA0B;IAKlD,OAAO,SAAS,aAAa,CAAC,MAAwC;QACpE,OAAO,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/resolver.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ import type { ClassValue } from './types.js';
|
|
|
7
7
|
* - If a variant matches, only the nested evaluation result is used
|
|
8
8
|
* - When no conditions match, $defaults accumulate from each unmatched level
|
|
9
9
|
*/
|
|
10
|
-
export declare function resolveConditions({ $default, ...conditions }: Record<string, unknown>, props: Record<string, unknown>): ClassValue[];
|
|
10
|
+
export declare function resolveConditions({ $base, $default, ...conditions }: Record<string, unknown>, props: Record<string, unknown>): ClassValue[];
|
|
11
11
|
//# sourceMappingURL=resolver.d.ts.map
|
package/dist/resolver.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,UAAU,EAAE,CA2Cd"}
|
package/dist/resolver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function
|
|
1
|
+
function isPlainObject(value) {
|
|
2
2
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
@@ -9,16 +9,11 @@ function isObject(value) {
|
|
|
9
9
|
* - If a variant matches, only the nested evaluation result is used
|
|
10
10
|
* - When no conditions match, $defaults accumulate from each unmatched level
|
|
11
11
|
*/
|
|
12
|
-
export function resolveConditions({ $default, ...conditions }, props) {
|
|
12
|
+
export function resolveConditions({ $base, $default, ...conditions }, props) {
|
|
13
13
|
const classes = [];
|
|
14
14
|
let hasMatchedCondition = false;
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
classes.push(...resolveConditions(value, props));
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
classes.push(value);
|
|
21
|
-
}
|
|
15
|
+
function toClassValues(value) {
|
|
16
|
+
return isPlainObject(value) ? resolveConditions(value, props) : [value];
|
|
22
17
|
}
|
|
23
18
|
for (const [key, value] of Object.entries(conditions)) {
|
|
24
19
|
const propValue = props[key];
|
|
@@ -29,24 +24,23 @@ export function resolveConditions({ $default, ...conditions }, props) {
|
|
|
29
24
|
if (/^is[A-Z]/.test(key) || /^allows[A-Z]/.test(key)) {
|
|
30
25
|
if (propValue) {
|
|
31
26
|
hasMatchedCondition = true;
|
|
32
|
-
|
|
27
|
+
classes.push(...toClassValues(value));
|
|
33
28
|
}
|
|
34
29
|
continue;
|
|
35
30
|
}
|
|
36
31
|
// Variant conditions (nested objects)
|
|
37
|
-
if (
|
|
38
|
-
|
|
32
|
+
if (isPlainObject(value)) {
|
|
33
|
+
const matched = typeof propValue === 'string' && propValue in value;
|
|
34
|
+
if (matched) {
|
|
39
35
|
hasMatchedCondition = true;
|
|
40
|
-
addClasses(value[propValue]);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
classes.push(value['$default']);
|
|
44
36
|
}
|
|
37
|
+
classes.push(...toClassValues(value[matched ? propValue : '$default']));
|
|
45
38
|
}
|
|
46
39
|
}
|
|
47
40
|
if (!hasMatchedCondition) {
|
|
48
41
|
classes.unshift($default);
|
|
49
42
|
}
|
|
43
|
+
classes.unshift($base);
|
|
50
44
|
return classes;
|
|
51
45
|
}
|
|
52
46
|
//# sourceMappingURL=resolver.js.map
|
package/dist/resolver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAEA,SAAS,
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAEA,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,UAAU,EAA2B,EAC3D,KAA8B;IAE9B,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAEhC,SAAS,aAAa,CAAC,KAAc;QACnC,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAmB,CAAC,CAAC;IACxF,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,iEAAiE,GAAG,sCAAsC,CAC3G,CAAC;QACJ,CAAC;QAED,0CAA0C;QAC1C,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,IAAI,SAAS,EAAE,CAAC;gBACd,mBAAmB,GAAG,IAAI,CAAC;gBAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;YACxC,CAAC;YACD,SAAS;QACX,CAAC;QAED,sCAAsC;QACtC,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,CAAC;YACpE,IAAI,OAAO,EAAE,CAAC;gBACZ,mBAAmB,GAAG,IAAI,CAAC;YAC7B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,OAAO,CAAC,OAAO,CAAC,QAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,KAAmB,CAAC,CAAC;IAErC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { ClassNameValue as ClassValue, extendTailwindMerge } from 'tailwind-merge';
|
|
2
2
|
export type { ClassValue };
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* This prevents ambiguity when passing class names to components.
|
|
6
|
-
*/
|
|
3
|
+
export type PropValue = boolean | string;
|
|
4
|
+
export type Props = Record<string, PropValue | undefined>;
|
|
7
5
|
export type ClassProp = {
|
|
8
6
|
class?: ClassValue;
|
|
9
7
|
className?: never;
|
|
@@ -11,88 +9,55 @@ export type ClassProp = {
|
|
|
11
9
|
class?: never;
|
|
12
10
|
className?: ClassValue;
|
|
13
11
|
};
|
|
14
|
-
|
|
15
|
-
* Props type constraint for NTV style functions.
|
|
16
|
-
* Props are either boolean flags or string variant selections.
|
|
17
|
-
*/
|
|
18
|
-
export interface NtvProps {
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Merge all properties from a union type into a single object type.
|
|
22
|
-
* Combines props from multiple style functions by creating unions of their values.
|
|
23
|
-
*/
|
|
24
|
-
type MergeUnion<T> = {
|
|
25
|
-
[K in T extends unknown ? keyof T : never]: T extends unknown ? K extends keyof T ? T[K] : never : never;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Extract and merge props types from an array of style functions.
|
|
29
|
-
* Used by mergeNtv to create a combined props type.
|
|
30
|
-
*/
|
|
31
|
-
export type MergeStyleFunctionProps<T extends readonly StyleFunction<any>[]> = MergeUnion<{
|
|
32
|
-
[K in keyof T]: T[K] extends StyleFunction<infer P> ? P : never;
|
|
33
|
-
}[number]>;
|
|
34
|
-
/**
|
|
35
|
-
* Make all properties optional and allow undefined values.
|
|
36
|
-
* Ensures proper handling of missing props in style functions.
|
|
37
|
-
*/
|
|
38
|
-
type PartialWithUndefined<T> = {
|
|
39
|
-
[K in keyof T]?: T[K] | undefined;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Flatten intersection types for better IDE display.
|
|
43
|
-
*/
|
|
44
|
-
type Simplify<T> = {
|
|
12
|
+
type Flatten<T> = {
|
|
45
13
|
[K in keyof T]: T[K];
|
|
46
14
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
type
|
|
15
|
+
type RequiredKeys<T> = {
|
|
16
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? never : K;
|
|
17
|
+
}[keyof T];
|
|
18
|
+
type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>;
|
|
19
|
+
type NestedScheme<TProps extends Props = {}> = {
|
|
20
|
+
$base?: ClassValue;
|
|
21
|
+
$default?: ClassValue | NestedScheme<TProps>;
|
|
22
|
+
} & PropConditions<TProps>;
|
|
23
|
+
type VariantMapping<TVariant extends string, TProps extends Props, TAllowDefault extends boolean> = {
|
|
24
|
+
[V in TVariant]?: ClassValue | NestedScheme<TProps>;
|
|
25
|
+
} & (TAllowDefault extends true ? {
|
|
26
|
+
$default?: ClassValue | NestedScheme<TProps>;
|
|
27
|
+
} : {});
|
|
28
|
+
type PropConditions<TProps extends Props> = {
|
|
29
|
+
[K in keyof TProps & string]?: NonNullable<TProps[K]> extends boolean ? ClassValue | NestedScheme<TProps> : NonNullable<TProps[K]> extends string ? VariantMapping<NonNullable<TProps[K]>, TProps, undefined extends TProps[K] ? true : false> : never;
|
|
30
|
+
};
|
|
31
|
+
export type Scheme<TProps extends Props = {}> = {
|
|
32
|
+
$base?: ClassValue;
|
|
56
33
|
$default?: ClassValue;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*/
|
|
61
|
-
type VariantSchemeEntry<TVariant extends string, TProps extends NtvProps> = {
|
|
62
|
-
[V in TVariant]?: ClassValue | (SchemeFor<TProps> & {
|
|
63
|
-
$default?: ClassValue;
|
|
64
|
-
});
|
|
34
|
+
} & PropConditions<TProps>;
|
|
35
|
+
type NormalizeProps<T> = Flatten<{
|
|
36
|
+
[K in RequiredKeys<T>]: T[K];
|
|
65
37
|
} & {
|
|
66
|
-
|
|
38
|
+
[K in OptionalKeys<T>]?: T[K];
|
|
39
|
+
}>;
|
|
40
|
+
export type StyleFunction<TProps = Props> = (RequiredKeys<TProps> extends never ? (props?: Flatten<NormalizeProps<TProps> & ClassProp>) => string : (props: Flatten<NormalizeProps<TProps> & ClassProp>) => string) & {
|
|
41
|
+
readonly __ntvProps?: TProps;
|
|
67
42
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
* Maps each prop to its appropriate scheme entry type.
|
|
71
|
-
*/
|
|
72
|
-
type SchemeConditions<TProps extends NtvProps> = {
|
|
73
|
-
[K in keyof TProps & string]?: TProps[K] extends boolean ? BooleanSchemeEntry<TProps> : TProps[K] extends string ? VariantSchemeEntry<TProps[K], TProps> : never;
|
|
43
|
+
export type AnyStyleFunction = ((...args: any[]) => string) & {
|
|
44
|
+
readonly __ntvProps?: unknown;
|
|
74
45
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
$default?: ClassValue;
|
|
90
|
-
[key: string]: unknown;
|
|
91
|
-
}
|
|
46
|
+
type KeysOfUnion<T> = T extends unknown ? keyof T : never;
|
|
47
|
+
type IsRequiredInAny<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ? K extends RequiredKeys<T> ? true : never : never : never;
|
|
48
|
+
type ValueFromUnion<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ? Exclude<T[K], undefined> : never : never;
|
|
49
|
+
type MergeProps<T> = Flatten<{
|
|
50
|
+
[K in KeysOfUnion<T> as true extends IsRequiredInAny<T, K> ? K : never]: ValueFromUnion<T, K>;
|
|
51
|
+
} & {
|
|
52
|
+
[K in KeysOfUnion<T> as true extends IsRequiredInAny<T, K> ? never : K]?: ValueFromUnion<T, K>;
|
|
53
|
+
}>;
|
|
54
|
+
type ExtractProps<T> = T extends {
|
|
55
|
+
readonly __ntvProps?: infer P;
|
|
56
|
+
} ? NonNullable<P> : never;
|
|
57
|
+
export type MergeStyleFunctionProps<T extends readonly AnyStyleFunction[]> = MergeProps<{
|
|
58
|
+
[K in keyof T]: ExtractProps<T[K]>;
|
|
59
|
+
}[number]>;
|
|
92
60
|
export type TwMergeConfig = Parameters<typeof extendTailwindMerge>[0];
|
|
93
|
-
/**
|
|
94
|
-
* Configuration options for NTV function behavior.
|
|
95
|
-
*/
|
|
96
61
|
export interface NtvOptions {
|
|
97
62
|
/**
|
|
98
63
|
* Whether to merge the class names with `tailwind-merge` library.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,IAAI,UAAU,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAExF,YAAY,EAAE,UAAU,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestable-tailwind-variants",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Tailwind CSS variant library with nestable conditions for compound styling instead of flat compoundVariants.",
|
|
5
5
|
"homepage": "https://github.com/yuheiy/nestable-tailwind-variants#readme",
|
|
6
6
|
"bugs": {
|