slot-variants 1.1.0 → 1.2.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/AGENTS.md CHANGED
@@ -10,6 +10,30 @@
10
10
  import { sv, cn, type VariantProps } from 'slot-variants';
11
11
  ```
12
12
 
13
+ `sv()` is a drop-in replacement for CVA (`cva` → `sv`) and covers the core feature set of tailwind-variants (`tv`) with a simpler API. Slots return strings directly (not functions like in `tv`). Features not in CVA/TV: `requiredVariants`, `presets`, `cacheSize`, `postProcess`, function-based `defaultVariants`, and variadic base args.
14
+
15
+ ## Calling Conventions
16
+
17
+ `sv()` supports three calling conventions:
18
+
19
+ ```typescript
20
+ // 1. Config-only (like tailwind-variants' tv())
21
+ const button = sv({
22
+ base: 'btn font-medium',
23
+ variants: { size: { sm: 'text-sm', lg: 'text-lg' } }
24
+ });
25
+
26
+ // 2. Base + config (like CVA's cva())
27
+ const button = sv('btn font-medium', {
28
+ variants: { size: { sm: 'text-sm', lg: 'text-lg' } }
29
+ });
30
+
31
+ // 3. Class name merging (like cn())
32
+ sv('flex', 'items-center', 'gap-2'); // 'flex items-center gap-2'
33
+ ```
34
+
35
+ The `base` config field merges with base arguments and `slots.base`: `cn(baseArgs..., config.base, slots.base)`.
36
+
13
37
  ## Best Practices
14
38
 
15
39
  ### 1. Keep CSS Classes Mutually Exclusive
@@ -243,14 +267,16 @@ const button = sv('btn', {
243
267
  }
244
268
  });
245
269
 
246
- button.variantKeys; // ['size', 'intent']
247
- button.variants; // { size: { sm: 'text-sm', lg: 'text-lg' }, intent: { ... } }
248
- button.slotKeys; // ['base', 'icon']
249
- button.slots; // { icon: 'w-4 h-4' }
250
- button.defaultVariants; // { size: 'sm' }
251
- button.requiredVariants; // ['intent']
252
- button.presetKeys; // ['cta']
253
- button.presets; // { cta: { size: 'lg', intent: 'primary' } }
270
+ button.variantKeys; // ['size', 'intent']
271
+ button.variants; // { size: { sm: 'text-sm', lg: 'text-lg' }, intent: { ... } }
272
+ button.slotKeys; // ['base', 'icon']
273
+ button.slots; // { icon: 'w-4 h-4' }
274
+ button.defaultVariants; // { size: 'sm' }
275
+ button.requiredVariants; // ['intent']
276
+ button.presetKeys; // ['cta']
277
+ button.presets; // { cta: { size: 'lg', intent: 'primary' } }
278
+ button.getVariantValues('size'); // ['sm', 'lg']
279
+ button.getVariantValues('intent'); // ['primary', 'danger']
254
280
  ```
255
281
 
256
282
  Use introspection to share variant/slot definitions with other parts of your codebase:
@@ -376,6 +402,7 @@ export const Card = (props: CardProps) => {
376
402
 
377
403
  | Option | Type | Description |
378
404
  | ------------------ | -------------------------------- | --------------------------------- |
405
+ | `base` | `ClassValue` | Additional base classes |
379
406
  | `variants` | `Record<string, VariantConfig>` | Variant definitions |
380
407
  | `slots` | `Record<string, ClassValue>` | Named slot definitions |
381
408
  | `compoundVariants` | `CompoundVariant[]` | Conditional class combinations |
@@ -390,6 +417,8 @@ export const Card = (props: CardProps) => {
390
417
 
391
418
  - `ClassValue` - Valid input for `cn()` (string, array, object, boolean, null, undefined)
392
419
  - `VariantProps<T, E>` - Extract variant props from an `sv()` return, optionally excluding keys
420
+ - `VariantValue<T, K>` - Extract the value union for a single variant key, without `undefined`
421
+ - `SlotClassProps<T>` - Extract the per-slot class injection shape from an `sv()` return type
393
422
 
394
423
  ## Imports
395
424
 
@@ -398,7 +427,7 @@ export const Card = (props: CardProps) => {
398
427
  import { sv, cn } from 'slot-variants';
399
428
 
400
429
  // Types only
401
- import type { VariantProps, ClassValue } from 'slot-variants';
430
+ import type { VariantProps, VariantValue, SlotClassProps, ClassValue } from 'slot-variants';
402
431
  ```
403
432
 
404
433
  ## Performance Notes
package/README.md CHANGED
@@ -17,6 +17,8 @@ npm install slot-variants
17
17
  - **`sv()`** - creates variant-based class name generators with optional slots
18
18
  - **`cn()`** - a utility for conditionally merging class names
19
19
 
20
+ `sv()` is a drop-in replacement for [CVA](https://cva.style/) (just rename `cva` to `sv`) and covers the core feature set of [tailwind-variants](https://www.tailwind-variants.org/) (`tv`) with a simpler API. See [Migrating from CVA / tailwind-variants](#migrating-from-cva--tailwind-variants) for details.
21
+
20
22
  ## Quick Start
21
23
 
22
24
  ```typescript
@@ -84,14 +86,67 @@ cn('foo', null, undefined, false, 'bar'); // 'foo bar'
84
86
 
85
87
  ## `sv()` - Slot Variants
86
88
 
87
- ### Base Only (No Config)
89
+ `sv()` supports three calling conventions:
90
+
91
+ ### Class Name Merging (No Config)
92
+
93
+ When called without a config object, `sv()` works like `cn()` — it accepts any number of `ClassValue` arguments and returns a merged class string:
94
+
95
+ ```typescript
96
+ sv('btn btn-primary'); // 'btn btn-primary'
97
+ sv('flex', 'items-center', 'gap-2'); // 'flex items-center gap-2'
98
+ sv(['btn', 'btn-primary']); // 'btn btn-primary'
99
+ sv({ btn: true, disabled: false }); // 'btn'
100
+ sv('flex', ['items-center'], { gap: true }); // 'flex items-center gap'
101
+ ```
102
+
103
+ ### Config-Only Call
104
+
105
+ When called with a single config object (no separate base argument), `sv()` returns a variant function. Use the `base` field inside the config:
106
+
107
+ ```typescript
108
+ const button = sv({
109
+ base: 'btn font-medium',
110
+ variants: {
111
+ size: {
112
+ sm: 'text-sm',
113
+ lg: 'text-lg'
114
+ }
115
+ }
116
+ });
117
+
118
+ button({ size: 'sm' }); // 'btn font-medium text-sm'
119
+ ```
120
+
121
+ ### Base + Config Call
122
+
123
+ When the last argument is a config object preceded by one or more `ClassValue` arguments, the leading arguments are merged as the base:
124
+
125
+ ```typescript
126
+ const button = sv('btn font-medium', {
127
+ variants: {
128
+ size: {
129
+ sm: 'text-sm',
130
+ lg: 'text-lg'
131
+ }
132
+ }
133
+ });
134
+ ```
88
135
 
89
- When called without a config object, `sv()` processes the base classes through `cn()` and returns a string:
136
+ The `base` field in the config is merged with the base arguments: `cn(baseArgs..., config.base, slots.base)`:
90
137
 
91
138
  ```typescript
92
- sv('btn btn-primary'); // 'btn btn-primary'
93
- sv(['btn', 'btn-primary']); // 'btn btn-primary'
94
- sv({ btn: true, disabled: false }); // 'btn'
139
+ const button = sv('btn', {
140
+ base: 'font-medium',
141
+ variants: {
142
+ size: {
143
+ sm: 'text-sm',
144
+ lg: 'text-lg'
145
+ }
146
+ }
147
+ });
148
+
149
+ button({ size: 'sm' }); // 'btn font-medium text-sm'
95
150
  ```
96
151
 
97
152
  ### Variants
@@ -659,14 +714,16 @@ const button = sv('btn', {
659
714
  }
660
715
  });
661
716
 
662
- button.variantKeys; // ['size', 'intent']
663
- button.variants; // { size: { sm: 'text-sm', lg: 'text-lg' }, intent: { ... } }
664
- button.slotKeys; // ['base', 'icon']
665
- button.slots; // { icon: 'w-4 h-4' }
666
- button.defaultVariants; // { size: 'sm' }
667
- button.requiredVariants; // ['intent']
668
- button.presetKeys; // ['cta']
669
- button.presets; // { cta: { size: 'lg', intent: 'primary' } }
717
+ button.variantKeys; // ['size', 'intent']
718
+ button.variants; // { size: { sm: 'text-sm', lg: 'text-lg' }, intent: { ... } }
719
+ button.slotKeys; // ['base', 'icon']
720
+ button.slots; // { icon: 'w-4 h-4' }
721
+ button.defaultVariants; // { size: 'sm' }
722
+ button.requiredVariants; // ['intent']
723
+ button.presetKeys; // ['cta']
724
+ button.presets; // { cta: { size: 'lg', intent: 'primary' } }
725
+ button.getVariantValues('size'); // ['sm', 'lg']
726
+ button.getVariantValues('intent'); // ['primary', 'danger']
670
727
  ```
671
728
 
672
729
  ## TypeScript
@@ -728,12 +785,84 @@ type ButtonProps = VariantProps<typeof button, 'internalState' | 'intent'>;
728
785
  // { size?: 'sm' | 'lg' | undefined }
729
786
  ```
730
787
 
788
+ ### Extracting a Single Variant's Values
789
+
790
+ `VariantValue` extracts the value union for a specific variant key. Unlike indexing into `VariantProps`, it always returns a clean union without `undefined`:
791
+
792
+ ```typescript
793
+ import { sv, type VariantValue } from 'slot-variants';
794
+
795
+ const button = sv('btn', {
796
+ variants: {
797
+ size: {
798
+ sm: 'text-sm',
799
+ md: 'text-base',
800
+ lg: 'text-lg'
801
+ },
802
+ intent: {
803
+ primary: 'bg-blue-500',
804
+ danger: 'bg-red-500'
805
+ }
806
+ },
807
+ requiredVariants: ['intent']
808
+ });
809
+
810
+ type SizeValue = VariantValue<typeof button, 'size'>;
811
+ // 'sm' | 'md' | 'lg' (no undefined, even though size is optional)
812
+
813
+ type IntentValue = VariantValue<typeof button, 'intent'>;
814
+ // 'primary' | 'danger'
815
+ ```
816
+
817
+ This is useful when a component only needs to forward a single variant as a typed prop:
818
+
819
+ ```typescript
820
+ type ButtonGroupProps = {
821
+ size?: VariantValue<typeof button, 'size'>;
822
+ };
823
+ ```
824
+
825
+ ### Slot Class Injection Props
826
+
827
+ `SlotClassProps<T>` extracts the per-slot class injection shape from an `sv()` return type. This is useful when building wrapper components that expose a typed prop for consumers to pass additional classes into specific slots:
828
+
829
+ ```typescript
830
+ import { sv, type SlotClassProps, type VariantProps } from 'slot-variants';
831
+
832
+ const card = sv('border rounded-lg', {
833
+ slots: {
834
+ header: 'font-bold',
835
+ body: 'py-4',
836
+ footer: 'border-t'
837
+ },
838
+ variants: {
839
+ size: { sm: 'text-sm', lg: 'text-lg' }
840
+ }
841
+ });
842
+
843
+ type CardClassProps = SlotClassProps<typeof card>;
844
+ // { base?: ClassValue; header?: ClassValue; body?: ClassValue; footer?: ClassValue }
845
+
846
+ type CardProps = VariantProps<typeof card> & {
847
+ classNames?: SlotClassProps<typeof card>;
848
+ };
849
+
850
+ function Card({ classNames, ...variants }: CardProps) {
851
+ const { base, header, body, footer } = card({ ...variants, class: classNames });
852
+ // ...
853
+ }
854
+ ```
855
+
856
+ When used on an `sv()` definition without slots, `SlotClassProps` resolves to `{ base?: ClassValue }`.
857
+
731
858
  ### Exported Types
732
859
 
733
860
  | Type | Description |
734
861
  | --- | --- |
735
862
  | `ClassValue` | Valid input types for `cn()` |
736
863
  | `VariantProps<T, E>` | Extracts variant props from an `sv()` return type, optionally excluding keys in `E` |
864
+ | `VariantValue<T, K>` | Extracts the value union for a single variant key `K`, without `undefined` |
865
+ | `SlotClassProps<T>` | Extracts the per-slot class injection shape from an `sv()` return type |
737
866
 
738
867
  ### Return Type
739
868
 
@@ -744,6 +873,7 @@ type ButtonProps = VariantProps<typeof button, 'internalState' | 'intent'>;
744
873
 
745
874
  | Option | Type | Description |
746
875
  | --- | --- | --- |
876
+ | `base` | `ClassValue` | Additional base classes merged with the base argument and `slots.base` |
747
877
  | `variants` | `SVVariants` | Variant definitions mapping variant names to their possible values |
748
878
  | `slots` | `SVSlots` | Named slot definitions for multi-element components |
749
879
  | `compoundVariants` | `Array` | Additional classes applied when multiple variant conditions match |
@@ -752,4 +882,80 @@ type ButtonProps = VariantProps<typeof button, 'internalState' | 'intent'>;
752
882
  | `requiredVariants` | `string[]` | Variant names that must be provided at call time |
753
883
  | `presets` | `Record<string, Partial<VariantProps>>` | Named combinations of variant values selectable via `preset` prop |
754
884
  | `postProcess` | `(className: string) => string` | Custom transformation applied to final class strings |
755
- | `cacheSize` | `number` | Maximum number of cached results (default: `256`) |
885
+ | `cacheSize` | `number` | Maximum number of cached results (default: `256`) |
886
+
887
+ ## Migrating from CVA / tailwind-variants
888
+
889
+ ### From CVA
890
+
891
+ `sv()` is a drop-in replacement for CVA. Rename `cva` to `sv` and `VariantProps` import source:
892
+
893
+ ```diff
894
+ - import { cva, type VariantProps } from 'class-variance-authority';
895
+ + import { sv, type VariantProps } from 'slot-variants';
896
+
897
+ - const button = cva('btn font-medium', {
898
+ + const button = sv('btn font-medium', {
899
+ variants: {
900
+ size: { sm: 'text-sm', lg: 'text-lg' },
901
+ intent: { primary: 'bg-blue-500', danger: 'bg-red-500' }
902
+ },
903
+ defaultVariants: { size: 'md' },
904
+ compoundVariants: [
905
+ { size: 'lg', intent: 'primary', class: 'uppercase' }
906
+ ]
907
+ });
908
+ ```
909
+
910
+ Everything else works identically — the config shape, `class`/`className` override, `VariantProps` extraction, and variant prop handling are all compatible.
911
+
912
+ ### From tailwind-variants
913
+
914
+ `sv()` covers the core feature set of tailwind-variants with a simpler API. The config-only calling convention matches `tv()`:
915
+
916
+ ```diff
917
+ - import { tv, type VariantProps } from 'tailwind-variants';
918
+ + import { sv, type VariantProps } from 'slot-variants';
919
+
920
+ - const button = tv({
921
+ + const button = sv({
922
+ base: 'btn font-medium',
923
+ variants: {
924
+ size: { sm: 'text-sm', lg: 'text-lg' }
925
+ },
926
+ defaultVariants: { size: 'md' }
927
+ });
928
+ ```
929
+
930
+ Key differences to be aware of:
931
+
932
+ | Feature | tailwind-variants | slot-variants |
933
+ | --- | --- | --- |
934
+ | Slot return type | Functions: `slot({ class: '...' })` | Strings: `slot` is already a `string` |
935
+ | `extend` (composition) | Supported | Not supported |
936
+ | Built-in `twMerge` | Enabled by default | Use `postProcess: twMerge` |
937
+
938
+ **Slot return type** is the most significant difference. In `tv()`, each slot returns a function that can accept additional props. In `sv()`, slots resolve to strings directly — use the `class` prop with a slot object for per-slot overrides:
939
+
940
+ ```typescript
941
+ // tailwind-variants
942
+ const { base, icon } = component({ size: 'sm' });
943
+ base({ class: 'extra' }); // slot is a function
944
+
945
+ // slot-variants
946
+ const { base, icon } = component({ size: 'sm', class: { base: 'extra' } });
947
+ base; // slot is a string
948
+ ```
949
+
950
+ **tailwind-merge** is not built-in but can be added via `postProcess`:
951
+
952
+ ```typescript
953
+ import { sv } from 'slot-variants';
954
+ import { twMerge } from 'tailwind-merge';
955
+
956
+ const button = sv({
957
+ base: 'px-4 py-2',
958
+ variants: { size: { sm: 'px-2 py-1' } },
959
+ postProcess: twMerge
960
+ });
961
+ ```
package/dist/index.cjs CHANGED
@@ -56,6 +56,19 @@ function cn(...args) {
56
56
  // src/sv.ts
57
57
  var { isArray: isArray2 } = Array;
58
58
  var { assign, entries, keys: keys2 } = Object;
59
+ var configKeys = /* @__PURE__ */ new Set([
60
+ "base",
61
+ "variants",
62
+ "slots",
63
+ "compoundVariants",
64
+ "compoundSlots",
65
+ "defaultVariants",
66
+ "requiredVariants",
67
+ "presets",
68
+ "cacheSize",
69
+ "postProcess"
70
+ ]);
71
+ var isConfig = (value) => !!value && typeof value === "object" && !isArray2(value) && keys2(value).every((key) => configKeys.has(key));
59
72
  var looseEquals = (first, second) => first === second || `${first}` === `${second}`;
60
73
  var matchesCompound = (props, compound) => {
61
74
  for (const compoundKey of keys2(compound)) {
@@ -74,11 +87,24 @@ var matchesCompound = (props, compound) => {
74
87
  }
75
88
  return true;
76
89
  };
77
- function sv(base, config) {
90
+ function sv(...args) {
91
+ const lastArg = args[args.length - 1];
92
+ let base;
93
+ let config;
94
+ if (args.length >= 2 && isConfig(lastArg)) {
95
+ config = lastArg;
96
+ base = args.length > 2 ? args.slice(0, -1) : args[0];
97
+ } else if (args.length === 1 && isConfig(lastArg)) {
98
+ config = lastArg;
99
+ base = void 0;
100
+ } else {
101
+ base = args;
102
+ }
78
103
  if (!config) {
79
- return cn(base);
104
+ return cn(...args);
80
105
  }
81
106
  const {
107
+ base: configBase,
82
108
  variants = {},
83
109
  slots = {},
84
110
  compoundVariants = [],
@@ -103,7 +129,8 @@ function sv(base, config) {
103
129
  return value;
104
130
  };
105
131
  const { base: baseSlot, ...otherSlots } = slots;
106
- const baseClassValue = cn(base, baseSlot);
132
+ const baseArgs = isArray2(base) ? base : [base];
133
+ const baseClassValue = cn(...baseArgs, configBase, baseSlot);
107
134
  const slotKeys = new Set(keys2(otherSlots));
108
135
  const normalizedVariants = {};
109
136
  for (const [variantKey, variantValue] of entries(variants)) {
@@ -263,6 +290,18 @@ function sv(base, config) {
263
290
  }
264
291
  return cacheReturn(cacheKey, result);
265
292
  };
293
+ const getVariantValues = (key) => keys2(normalizedVariants[key] ?? {}).map((value) => {
294
+ if (value === "true") {
295
+ return true;
296
+ }
297
+ if (value === "false") {
298
+ return false;
299
+ }
300
+ if (value !== "" && !Number.isNaN(Number(value))) {
301
+ return Number(value);
302
+ }
303
+ return value;
304
+ });
266
305
  return assign(variantFn, {
267
306
  variants,
268
307
  variantKeys: keys2(variants),
@@ -272,6 +311,7 @@ function sv(base, config) {
272
311
  requiredVariants,
273
312
  presets,
274
313
  presetKeys: keys2(presets),
314
+ getVariantValues,
275
315
  clearCache: () => cache.clear(),
276
316
  getCacheSize: () => cache.size
277
317
  });
package/dist/index.d.ts CHANGED
@@ -53,6 +53,7 @@ type PresetProp<P extends Record<string, unknown> | undefined> = P extends Recor
53
53
  } : unknown;
54
54
  type SVProps<S extends SVSlots | undefined, V extends SVVariants<S> | undefined, RV extends StringKeyof<V>[], P extends SVPresets<S, V> | undefined> = V extends undefined ? ClassProp<S> : P extends Record<string, unknown> ? Prettify<PartialUndefined<SVVariantProps<S, V>>> & ClassProp<S> & PresetProp<P> : Prettify<Pick<SVVariantProps<S, V>, RV[number]> & Omit<PartialUndefined<SVVariantProps<S, V>>, RV[number]>> & ClassProp<S>;
55
55
  type SVConfig<S extends SVSlots | undefined, V extends SVVariants<S> | undefined, RV extends StringKeyof<V>[], P extends SVPresets<S, V> | undefined> = {
56
+ base?: ClassValue | undefined;
56
57
  variants?: V | undefined;
57
58
  slots?: S | undefined;
58
59
  compoundVariants?: SVCompoundVariants<S, V> | undefined;
@@ -74,15 +75,19 @@ type SVReturnType<S extends SVSlots | undefined, V extends SVVariants<S> | undef
74
75
  requiredVariants: RV;
75
76
  presets: P;
76
77
  presetKeys: P extends Record<string, unknown> ? StringKeyof<P>[] : [];
78
+ getVariantValues: V extends SVVariants<S> ? <K extends StringKeyof<V>>(key: K) => SVVariantPropType<V[K], S>[] : (key: never) => never[];
77
79
  clearCache: () => void;
78
80
  getCacheSize: () => number;
79
81
  };
80
82
  type VariantProps<T extends (...args: any[]) => unknown, E extends string = never> = Prettify<Omit<Exclude<Parameters<T>[0], undefined>, 'class' | 'className' | 'preset' | E>>;
83
+ type VariantValue<T extends (...args: any[]) => unknown, K extends keyof VariantProps<T>> = NonNullable<VariantProps<T>[K]>;
84
+ type SlotClassProps<T extends (...args: any[]) => unknown> = ReturnType<T> extends string ? Partial<Record<'base', ClassValue>> : Prettify<Partial<Record<Extract<keyof ReturnType<T>, string>, ClassValue>>>;
81
85
  /**
82
86
  * Creates variant-based class name generator with optional slots support.
83
87
  * Inspired by CVA and tailwind-variants.
84
88
  */
85
- declare function sv(base: ClassValue): string;
86
- declare function sv<S extends SVSlots | undefined = undefined, V extends SVVariants<S> | undefined = undefined, RV extends StringKeyof<V>[] | [] = [], P extends SVPresets<S, V> | undefined = undefined>(base: ClassValue, config: SVConfig<S, V, RV, P>): SVReturnType<S, V, RV, P>;
89
+ declare function sv<S extends SVSlots | undefined = undefined, V extends SVVariants<S> | undefined = undefined, RV extends StringKeyof<V>[] | [] = [], P extends SVPresets<S, V> | undefined = undefined>(config: SVConfig<S, V, RV, P>): SVReturnType<S, V, RV, P>;
90
+ declare function sv<S extends SVSlots | undefined = undefined, V extends SVVariants<S> | undefined = undefined, RV extends StringKeyof<V>[] | [] = [], P extends SVPresets<S, V> | undefined = undefined>(...args: [...ClassValue[], SVConfig<S, V, RV, P>]): SVReturnType<S, V, RV, P>;
91
+ declare function sv(...args: ClassValue[]): string;
87
92
 
88
- export { type ClassValue, type VariantProps, cn, sv };
93
+ export { type ClassValue, type SlotClassProps, type VariantProps, type VariantValue, cn, sv };
package/dist/index.js CHANGED
@@ -29,6 +29,19 @@ function cn(...args) {
29
29
  // src/sv.ts
30
30
  var { isArray: isArray2 } = Array;
31
31
  var { assign, entries, keys: keys2 } = Object;
32
+ var configKeys = /* @__PURE__ */ new Set([
33
+ "base",
34
+ "variants",
35
+ "slots",
36
+ "compoundVariants",
37
+ "compoundSlots",
38
+ "defaultVariants",
39
+ "requiredVariants",
40
+ "presets",
41
+ "cacheSize",
42
+ "postProcess"
43
+ ]);
44
+ var isConfig = (value) => !!value && typeof value === "object" && !isArray2(value) && keys2(value).every((key) => configKeys.has(key));
32
45
  var looseEquals = (first, second) => first === second || `${first}` === `${second}`;
33
46
  var matchesCompound = (props, compound) => {
34
47
  for (const compoundKey of keys2(compound)) {
@@ -47,11 +60,24 @@ var matchesCompound = (props, compound) => {
47
60
  }
48
61
  return true;
49
62
  };
50
- function sv(base, config) {
63
+ function sv(...args) {
64
+ const lastArg = args[args.length - 1];
65
+ let base;
66
+ let config;
67
+ if (args.length >= 2 && isConfig(lastArg)) {
68
+ config = lastArg;
69
+ base = args.length > 2 ? args.slice(0, -1) : args[0];
70
+ } else if (args.length === 1 && isConfig(lastArg)) {
71
+ config = lastArg;
72
+ base = void 0;
73
+ } else {
74
+ base = args;
75
+ }
51
76
  if (!config) {
52
- return cn(base);
77
+ return cn(...args);
53
78
  }
54
79
  const {
80
+ base: configBase,
55
81
  variants = {},
56
82
  slots = {},
57
83
  compoundVariants = [],
@@ -76,7 +102,8 @@ function sv(base, config) {
76
102
  return value;
77
103
  };
78
104
  const { base: baseSlot, ...otherSlots } = slots;
79
- const baseClassValue = cn(base, baseSlot);
105
+ const baseArgs = isArray2(base) ? base : [base];
106
+ const baseClassValue = cn(...baseArgs, configBase, baseSlot);
80
107
  const slotKeys = new Set(keys2(otherSlots));
81
108
  const normalizedVariants = {};
82
109
  for (const [variantKey, variantValue] of entries(variants)) {
@@ -236,6 +263,18 @@ function sv(base, config) {
236
263
  }
237
264
  return cacheReturn(cacheKey, result);
238
265
  };
266
+ const getVariantValues = (key) => keys2(normalizedVariants[key] ?? {}).map((value) => {
267
+ if (value === "true") {
268
+ return true;
269
+ }
270
+ if (value === "false") {
271
+ return false;
272
+ }
273
+ if (value !== "" && !Number.isNaN(Number(value))) {
274
+ return Number(value);
275
+ }
276
+ return value;
277
+ });
239
278
  return assign(variantFn, {
240
279
  variants,
241
280
  variantKeys: keys2(variants),
@@ -245,6 +284,7 @@ function sv(base, config) {
245
284
  requiredVariants,
246
285
  presets,
247
286
  presetKeys: keys2(presets),
287
+ getVariantValues,
248
288
  clearCache: () => cache.clear(),
249
289
  getCacheSize: () => cache.size
250
290
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slot-variants",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Type-safe class name variants with slots",
5
5
  "type": "module",
6
6
  "exports": {