slot-variants 1.6.1 → 1.6.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 +41 -3
- package/SKILL.md +4 -4
- package/dist/eslint-plugin.cjs +62 -6
- package/dist/eslint-plugin.js +62 -6
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -711,7 +711,9 @@ card({ class: { base: 'shadow-xl', header: 'text-blue-700', body: 'min-h-24' } }
|
|
|
711
711
|
// base: 'border shadow-xl', header: 'font-bold text-blue-700', body: 'py-4 min-h-24'
|
|
712
712
|
```
|
|
713
713
|
|
|
714
|
-
Both `class` and `className` are supported, but `class`
|
|
714
|
+
Both `class` and `className` are supported, but `class` takes priority when both are passed at the same time.
|
|
715
|
+
|
|
716
|
+
The runtime `class`/`className` override is not part of the cache key — it is merged on top of the cached variant result on every call (and `postProcess`, if set, is re-applied to the merged output). Two calls with identical variants but different `class` values therefore share the same cached base result.
|
|
715
717
|
|
|
716
718
|
### Post-Processing
|
|
717
719
|
|
|
@@ -734,6 +736,10 @@ const button = sv('px-4 py-2 bg-blue-500', {
|
|
|
734
736
|
|
|
735
737
|
The `postProcess` function is applied to each slot's final class string independently.
|
|
736
738
|
|
|
739
|
+
`sv()` and `cn()` concatenate classes in order without deduplicating or resolving conflicts — a class repeated across `base` and a variant value appears twice in the output, and conflicting Tailwind utilities are both kept. Use `postProcess: twMerge` when you need duplicates collapsed and later utilities to win at runtime.
|
|
740
|
+
|
|
741
|
+
For statically-defined classes, the bundled [ESLint / oxlint plugin](#eslint--oxlint-plugin) catches most duplication at lint time — before it ever reaches the output: `no-conflicting-classes` flags duplicate and same-namespace tokens within a call, and `no-shared-tokens` flags a class repeated across every value of a variant (which belongs in `base` instead). The two approaches complement each other — the plugin keeps your source clean, while `postProcess: twMerge` handles duplicates that only arise from dynamic, runtime-supplied classes.
|
|
742
|
+
|
|
737
743
|
### Shared Defaults with `createSV()`
|
|
738
744
|
|
|
739
745
|
`createSV(defaults)` returns a pre-configured `sv()` that merges `defaults` into every config-based call. This avoids repeating the same options — most commonly `postProcess: twMerge` — across every component:
|
|
@@ -806,6 +812,8 @@ const button = sv('btn', {
|
|
|
806
812
|
});
|
|
807
813
|
```
|
|
808
814
|
|
|
815
|
+
Setting `cacheSize` to `0` (or a negative number) disables caching entirely — every call recomputes its result. This is useful when variant combinations are effectively unbounded and you'd rather not retain any entries.
|
|
816
|
+
|
|
809
817
|
Cache inspection and control methods (`getCacheSize`, `clearCache`) are exposed on the returned function only when `introspection: true` is set — see [Introspection](#introspection).
|
|
810
818
|
|
|
811
819
|
### Introspection
|
|
@@ -855,6 +863,36 @@ button.clearCache(); // clear all cached entries
|
|
|
855
863
|
|
|
856
864
|
Without `introspection: true`, only the variant function itself is returned — accessing introspection or cache properties is a type error.
|
|
857
865
|
|
|
866
|
+
### Errors & Validation
|
|
867
|
+
|
|
868
|
+
`sv()` validates both the config and the runtime props, throwing an `Error` on misconfiguration. TypeScript prevents most of these statically, but they still guard against untyped runtime input (e.g. a value coming from a form or API).
|
|
869
|
+
|
|
870
|
+
**Config-time** — thrown when `sv(config)` is evaluated (at module load, when the variant function is built):
|
|
871
|
+
|
|
872
|
+
| Message | Cause |
|
|
873
|
+
| --- | --- |
|
|
874
|
+
| `Required variant "X" is not defined in variants` | `requiredVariants` lists a variant that doesn't exist |
|
|
875
|
+
| `Required variant "X" cannot have a default value` | A variant is both in `requiredVariants` and `defaultVariants` |
|
|
876
|
+
| `Default variant "X" is not defined in variants` | `defaultVariants` references an unknown variant |
|
|
877
|
+
| `Default variant "X" has invalid value "V"` | A static default value isn't one of the variant's values |
|
|
878
|
+
| `Preset "P" references unknown variant "X"` | A preset references an unknown variant |
|
|
879
|
+
| `Preset "P" has invalid value "V" for variant "X"` | A preset value isn't one of the variant's values |
|
|
880
|
+
| `Compound matcher references unknown variant "X"` | A compound variant/slot matches on an unknown variant |
|
|
881
|
+
| `Compound matcher for variant "X" has invalid value "V"` | A compound matcher value isn't one of the variant's values |
|
|
882
|
+
| `Compound variant must define "class" or "className"` | A `compoundVariants` entry has no class value |
|
|
883
|
+
| `Compound slot must define "class" or "className"` | A `compoundSlots` entry has no class value |
|
|
884
|
+
| `Compound slot must define at least one slot` | A `compoundSlots` entry has an empty `slots` array |
|
|
885
|
+
| `Compound slot references unknown slot "S"` | A `compoundSlots` entry targets an undefined slot |
|
|
886
|
+
| `Multi slot references unknown slot "S"` | `multiSlots` lists a slot that doesn't exist |
|
|
887
|
+
|
|
888
|
+
**Runtime** — thrown when the returned variant function is called:
|
|
889
|
+
|
|
890
|
+
| Message | Cause |
|
|
891
|
+
| --- | --- |
|
|
892
|
+
| `Missing required variant: "X"` | A required variant wasn't provided (by prop or preset) |
|
|
893
|
+
| `Invalid value "V" for variant "X"` | A prop value isn't one of the variant's defined values |
|
|
894
|
+
| `Invalid preset "P"` | The `preset` prop names a preset that doesn't exist |
|
|
895
|
+
|
|
858
896
|
## TypeScript
|
|
859
897
|
|
|
860
898
|
`slot-variants` is fully typed. Variant props are inferred from your config:
|
|
@@ -876,7 +914,7 @@ const button = sv('btn', {
|
|
|
876
914
|
requiredVariants: ['intent']
|
|
877
915
|
});
|
|
878
916
|
|
|
879
|
-
// Extract the variant props type (excludes class
|
|
917
|
+
// Extract the variant props type (excludes class, className, and preset)
|
|
880
918
|
type ButtonProps = VariantProps<typeof button>;
|
|
881
919
|
// { size?: 'sm' | 'lg' | undefined; intent: 'primary' | 'danger' }
|
|
882
920
|
```
|
|
@@ -1015,7 +1053,7 @@ Class values inside the config (`base`, `variants`, `slots`, and `compound*` `cl
|
|
|
1015
1053
|
| `multiSlots` | `string[] \| boolean` | Slot names exposed as reconfigurable functions instead of strings; `true` makes every slot a function, `false` none |
|
|
1016
1054
|
| `presets` | `Record<string, Partial<VariantProps>>` | Named combinations of variant values selectable via `preset` prop |
|
|
1017
1055
|
| `postProcess` | `(className: string) => string` | Custom transformation applied to final class strings |
|
|
1018
|
-
| `cacheSize` | `number` | Maximum number of cached results (default: `256`) |
|
|
1056
|
+
| `cacheSize` | `number` | Maximum number of cached results (default: `256`); `0` or a negative value disables caching |
|
|
1019
1057
|
| `introspection` | `boolean` | When `true`, exposes variant/slot/preset introspection and cache methods on the returned function (default: `false`) |
|
|
1020
1058
|
|
|
1021
1059
|
## ESLint / oxlint Plugin
|
package/SKILL.md
CHANGED
|
@@ -121,10 +121,10 @@ const customSV = createSV({ postProcess: twMerge, cacheSize: 512 });
|
|
|
121
121
|
The library caches results automatically (default 256 entries). Each cache entry is one distinct combination of resolved variant values:
|
|
122
122
|
|
|
123
123
|
```
|
|
124
|
-
maxEntries =
|
|
124
|
+
maxEntries = factor₁ × factor₂ × ... × factorₙ
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
A variant's factor is its value count `+ 1` (the `+ 1` counts the variant being left unset). The `+ 1` is dropped — factor is just the value count — when the variant is required or has a static default, since it can never be unset. Function-based defaults still count as unset-able, so they keep the `+ 1`. Raise `cacheSize` only when `maxEntries` exceeds 256 — below that the cache never evicts. With `introspection: true`, `getMaxEntries()` returns this exact number, and `getCacheSize()`/`clearCache()` inspect the live cache.
|
|
128
128
|
|
|
129
129
|
### 10. Use Presets for Reusable Variant Combinations
|
|
130
130
|
|
|
@@ -139,7 +139,7 @@ button({ preset: 'cta' }); // applies size: 'lg', intent: 'primary'
|
|
|
139
139
|
|
|
140
140
|
### 11. Use Introspection for Single Source of Truth
|
|
141
141
|
|
|
142
|
-
Set `introspection: true` to expose configuration and cache members on the returned function (off by default): `variantKeys`, `variants`, `slotKeys`, `slots`, `defaultVariants`, `requiredVariants`, `presetKeys`, `presets`, `getVariantValues(key)`, `getCacheSize()`, and `clearCache()`.
|
|
142
|
+
Set `introspection: true` to expose configuration and cache members on the returned function (off by default): `variantKeys`, `variants`, `slotKeys`, `slots`, `defaultVariants`, `requiredVariants`, `multiSlots`, `presetKeys`, `presets`, `getVariantValues(key)`, `getMaxEntries()`, `getCacheSize()`, and `clearCache()`.
|
|
143
143
|
|
|
144
144
|
Without `introspection: true`, accessing these is a type error. Use it to centralize variant/slot definitions and reuse them across the codebase.
|
|
145
145
|
|
|
@@ -201,7 +201,7 @@ Class values inside the config (`base`, `variants` values, `slots` values, and `
|
|
|
201
201
|
|
|
202
202
|
## Exported Types
|
|
203
203
|
|
|
204
|
-
- `ClassValue` — Valid input for `cn()` (string, array, object, boolean, null, undefined)
|
|
204
|
+
- `ClassValue` — Valid input for `cn()` (string, number, bigint, array, object, boolean, null, undefined)
|
|
205
205
|
- `VariantProps<T, E>` — Extract variant props from an `sv()` return, optionally excluding keys
|
|
206
206
|
- `VariantValue<T, K>` — Extract the value union for a single variant key, without `undefined`
|
|
207
207
|
- `SlotClassProps<T>` — Extract the per-slot class injection shape from an `sv()` return type
|
package/dist/eslint-plugin.cjs
CHANGED
|
@@ -254,17 +254,54 @@ var pushStringLiteralTokens = (node, slot, source, entries, sourceCode) => {
|
|
|
254
254
|
}
|
|
255
255
|
};
|
|
256
256
|
var isStaticStringNode = (node) => getStaticStringText(node) !== null;
|
|
257
|
-
var
|
|
257
|
+
var pushRecordKeyTokens = (prop, slot, source, entries, sourceCode) => {
|
|
258
|
+
const { key } = prop;
|
|
259
|
+
if (key.type === "Literal" && typeof key.value === "string") {
|
|
260
|
+
pushStringLiteralTokens(key, slot, source, entries, sourceCode);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const token = getKeyName(prop);
|
|
264
|
+
if (token === null) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const [start, end] = sourceCode.getRange(key);
|
|
268
|
+
entries.push({ source, slot, token, start, end });
|
|
269
|
+
};
|
|
270
|
+
var extractRecordTokens = (node, slot, source, entries, sourceCode) => {
|
|
271
|
+
for (const prop of node.properties) {
|
|
272
|
+
if (prop.type !== "Property" || prop.computed) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
pushRecordKeyTokens(prop, slot, source, entries, sourceCode);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var extractTokens = (node, slot, source, slotNames, entries, sourceCode, cnStyle = false) => {
|
|
258
279
|
if (isStaticStringNode(node)) {
|
|
259
280
|
pushStringLiteralTokens(node, slot, source, entries, sourceCode);
|
|
260
281
|
return;
|
|
261
282
|
}
|
|
283
|
+
if (cnStyle && isLogicalClassStaticString(node)) {
|
|
284
|
+
pushStringLiteralTokens(node.right, slot, source, entries, sourceCode);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
262
287
|
if (node.type === "ArrayExpression") {
|
|
263
288
|
forEachStaticItem(node.elements, (element) => {
|
|
264
|
-
extractTokens(
|
|
289
|
+
extractTokens(
|
|
290
|
+
element,
|
|
291
|
+
slot,
|
|
292
|
+
source,
|
|
293
|
+
slotNames,
|
|
294
|
+
entries,
|
|
295
|
+
sourceCode,
|
|
296
|
+
cnStyle
|
|
297
|
+
);
|
|
265
298
|
});
|
|
266
299
|
return;
|
|
267
300
|
}
|
|
301
|
+
if (cnStyle && node.type === "ObjectExpression") {
|
|
302
|
+
extractRecordTokens(node, slot, source, entries, sourceCode);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
268
305
|
const slotKeyedProps = collectSlotKeyedProperties(node, slotNames);
|
|
269
306
|
if (!slotKeyedProps) {
|
|
270
307
|
return;
|
|
@@ -356,7 +393,7 @@ var collectConfigEntries = (config, slotNames, baseArgs, sourceCode) => {
|
|
|
356
393
|
extract(slotValue, slotKey, baseSource);
|
|
357
394
|
}
|
|
358
395
|
for (const arg of baseArgs) {
|
|
359
|
-
|
|
396
|
+
extractTokens(arg, "base", baseSource, slotNames, entries, sourceCode, true);
|
|
360
397
|
}
|
|
361
398
|
const base = config.get("base");
|
|
362
399
|
if (base) {
|
|
@@ -378,6 +415,7 @@ var reportDynamic = (context, node) => {
|
|
|
378
415
|
context.report({ node, messageId: "dynamic" });
|
|
379
416
|
};
|
|
380
417
|
var isUndefinedIdentifier = (node) => node.type === "Identifier" && node.name === "undefined";
|
|
418
|
+
var isLogicalClassStaticString = (node) => node.type === "LogicalExpression" && node.operator === "&&" && isStaticStringNode(node.right);
|
|
381
419
|
var forEachItemReportingSpread = (context, items, visit) => {
|
|
382
420
|
for (const item of items) {
|
|
383
421
|
if (!item) {
|
|
@@ -397,6 +435,9 @@ var checkClassValueIsStatic = (context, node, options = {}) => {
|
|
|
397
435
|
if (isStaticStringNode(node)) {
|
|
398
436
|
return;
|
|
399
437
|
}
|
|
438
|
+
if (options.allowLogicalString && isLogicalClassStaticString(node)) {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
400
441
|
if (node.type === "ArrayExpression") {
|
|
401
442
|
forEachItemReportingSpread(context, node.elements, (element) => {
|
|
402
443
|
if (options.allowNestedArrays === false) {
|
|
@@ -405,10 +446,17 @@ var checkClassValueIsStatic = (context, node, options = {}) => {
|
|
|
405
446
|
return;
|
|
406
447
|
}
|
|
407
448
|
}
|
|
408
|
-
checkClassValueIsStatic(context, element
|
|
449
|
+
checkClassValueIsStatic(context, element, {
|
|
450
|
+
allowLogicalString: options.allowLogicalString === true,
|
|
451
|
+
allowClassRecord: options.allowClassRecord === true
|
|
452
|
+
});
|
|
409
453
|
});
|
|
410
454
|
return;
|
|
411
455
|
}
|
|
456
|
+
if (options.allowClassRecord && node.type === "ObjectExpression") {
|
|
457
|
+
checkClassRecordKeys(context, node);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
412
460
|
reportDynamic(context, node);
|
|
413
461
|
};
|
|
414
462
|
var checkConfigClassValueIsStatic = (context, node) => {
|
|
@@ -430,6 +478,10 @@ var forEachStaticProperty = (context, node, visit) => {
|
|
|
430
478
|
visit(prop);
|
|
431
479
|
}
|
|
432
480
|
};
|
|
481
|
+
var checkClassRecordKeys = (context, node) => {
|
|
482
|
+
forEachStaticProperty(context, node, () => {
|
|
483
|
+
});
|
|
484
|
+
};
|
|
433
485
|
var checkClassValueRecord = (context, node) => {
|
|
434
486
|
if (node.type !== "ObjectExpression") {
|
|
435
487
|
reportDynamic(context, node);
|
|
@@ -551,7 +603,10 @@ var checkSvConfig = (context, configNode) => {
|
|
|
551
603
|
};
|
|
552
604
|
var checkCnArguments = (context, args) => {
|
|
553
605
|
forEachItemReportingSpread(context, args, (arg) => {
|
|
554
|
-
checkClassValueIsStatic(context, arg
|
|
606
|
+
checkClassValueIsStatic(context, arg, {
|
|
607
|
+
allowLogicalString: true,
|
|
608
|
+
allowClassRecord: true
|
|
609
|
+
});
|
|
555
610
|
});
|
|
556
611
|
};
|
|
557
612
|
var getImportedName = (specifier) => {
|
|
@@ -829,7 +884,8 @@ var analyzeCnForRule = (context, args) => {
|
|
|
829
884
|
baseSource,
|
|
830
885
|
EMPTY_SLOT_NAMES,
|
|
831
886
|
entries,
|
|
832
|
-
context.sourceCode
|
|
887
|
+
context.sourceCode,
|
|
888
|
+
true
|
|
833
889
|
);
|
|
834
890
|
}
|
|
835
891
|
const tokenMap = indexEntriesBySlotAndToken(entries).get("base");
|
package/dist/eslint-plugin.js
CHANGED
|
@@ -229,17 +229,54 @@ var pushStringLiteralTokens = (node, slot, source, entries, sourceCode) => {
|
|
|
229
229
|
}
|
|
230
230
|
};
|
|
231
231
|
var isStaticStringNode = (node) => getStaticStringText(node) !== null;
|
|
232
|
-
var
|
|
232
|
+
var pushRecordKeyTokens = (prop, slot, source, entries, sourceCode) => {
|
|
233
|
+
const { key } = prop;
|
|
234
|
+
if (key.type === "Literal" && typeof key.value === "string") {
|
|
235
|
+
pushStringLiteralTokens(key, slot, source, entries, sourceCode);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const token = getKeyName(prop);
|
|
239
|
+
if (token === null) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const [start, end] = sourceCode.getRange(key);
|
|
243
|
+
entries.push({ source, slot, token, start, end });
|
|
244
|
+
};
|
|
245
|
+
var extractRecordTokens = (node, slot, source, entries, sourceCode) => {
|
|
246
|
+
for (const prop of node.properties) {
|
|
247
|
+
if (prop.type !== "Property" || prop.computed) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
pushRecordKeyTokens(prop, slot, source, entries, sourceCode);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
var extractTokens = (node, slot, source, slotNames, entries, sourceCode, cnStyle = false) => {
|
|
233
254
|
if (isStaticStringNode(node)) {
|
|
234
255
|
pushStringLiteralTokens(node, slot, source, entries, sourceCode);
|
|
235
256
|
return;
|
|
236
257
|
}
|
|
258
|
+
if (cnStyle && isLogicalClassStaticString(node)) {
|
|
259
|
+
pushStringLiteralTokens(node.right, slot, source, entries, sourceCode);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
237
262
|
if (node.type === "ArrayExpression") {
|
|
238
263
|
forEachStaticItem(node.elements, (element) => {
|
|
239
|
-
extractTokens(
|
|
264
|
+
extractTokens(
|
|
265
|
+
element,
|
|
266
|
+
slot,
|
|
267
|
+
source,
|
|
268
|
+
slotNames,
|
|
269
|
+
entries,
|
|
270
|
+
sourceCode,
|
|
271
|
+
cnStyle
|
|
272
|
+
);
|
|
240
273
|
});
|
|
241
274
|
return;
|
|
242
275
|
}
|
|
276
|
+
if (cnStyle && node.type === "ObjectExpression") {
|
|
277
|
+
extractRecordTokens(node, slot, source, entries, sourceCode);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
243
280
|
const slotKeyedProps = collectSlotKeyedProperties(node, slotNames);
|
|
244
281
|
if (!slotKeyedProps) {
|
|
245
282
|
return;
|
|
@@ -331,7 +368,7 @@ var collectConfigEntries = (config, slotNames, baseArgs, sourceCode) => {
|
|
|
331
368
|
extract(slotValue, slotKey, baseSource);
|
|
332
369
|
}
|
|
333
370
|
for (const arg of baseArgs) {
|
|
334
|
-
|
|
371
|
+
extractTokens(arg, "base", baseSource, slotNames, entries, sourceCode, true);
|
|
335
372
|
}
|
|
336
373
|
const base = config.get("base");
|
|
337
374
|
if (base) {
|
|
@@ -353,6 +390,7 @@ var reportDynamic = (context, node) => {
|
|
|
353
390
|
context.report({ node, messageId: "dynamic" });
|
|
354
391
|
};
|
|
355
392
|
var isUndefinedIdentifier = (node) => node.type === "Identifier" && node.name === "undefined";
|
|
393
|
+
var isLogicalClassStaticString = (node) => node.type === "LogicalExpression" && node.operator === "&&" && isStaticStringNode(node.right);
|
|
356
394
|
var forEachItemReportingSpread = (context, items, visit) => {
|
|
357
395
|
for (const item of items) {
|
|
358
396
|
if (!item) {
|
|
@@ -372,6 +410,9 @@ var checkClassValueIsStatic = (context, node, options = {}) => {
|
|
|
372
410
|
if (isStaticStringNode(node)) {
|
|
373
411
|
return;
|
|
374
412
|
}
|
|
413
|
+
if (options.allowLogicalString && isLogicalClassStaticString(node)) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
375
416
|
if (node.type === "ArrayExpression") {
|
|
376
417
|
forEachItemReportingSpread(context, node.elements, (element) => {
|
|
377
418
|
if (options.allowNestedArrays === false) {
|
|
@@ -380,10 +421,17 @@ var checkClassValueIsStatic = (context, node, options = {}) => {
|
|
|
380
421
|
return;
|
|
381
422
|
}
|
|
382
423
|
}
|
|
383
|
-
checkClassValueIsStatic(context, element
|
|
424
|
+
checkClassValueIsStatic(context, element, {
|
|
425
|
+
allowLogicalString: options.allowLogicalString === true,
|
|
426
|
+
allowClassRecord: options.allowClassRecord === true
|
|
427
|
+
});
|
|
384
428
|
});
|
|
385
429
|
return;
|
|
386
430
|
}
|
|
431
|
+
if (options.allowClassRecord && node.type === "ObjectExpression") {
|
|
432
|
+
checkClassRecordKeys(context, node);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
387
435
|
reportDynamic(context, node);
|
|
388
436
|
};
|
|
389
437
|
var checkConfigClassValueIsStatic = (context, node) => {
|
|
@@ -405,6 +453,10 @@ var forEachStaticProperty = (context, node, visit) => {
|
|
|
405
453
|
visit(prop);
|
|
406
454
|
}
|
|
407
455
|
};
|
|
456
|
+
var checkClassRecordKeys = (context, node) => {
|
|
457
|
+
forEachStaticProperty(context, node, () => {
|
|
458
|
+
});
|
|
459
|
+
};
|
|
408
460
|
var checkClassValueRecord = (context, node) => {
|
|
409
461
|
if (node.type !== "ObjectExpression") {
|
|
410
462
|
reportDynamic(context, node);
|
|
@@ -526,7 +578,10 @@ var checkSvConfig = (context, configNode) => {
|
|
|
526
578
|
};
|
|
527
579
|
var checkCnArguments = (context, args) => {
|
|
528
580
|
forEachItemReportingSpread(context, args, (arg) => {
|
|
529
|
-
checkClassValueIsStatic(context, arg
|
|
581
|
+
checkClassValueIsStatic(context, arg, {
|
|
582
|
+
allowLogicalString: true,
|
|
583
|
+
allowClassRecord: true
|
|
584
|
+
});
|
|
530
585
|
});
|
|
531
586
|
};
|
|
532
587
|
var getImportedName = (specifier) => {
|
|
@@ -804,7 +859,8 @@ var analyzeCnForRule = (context, args) => {
|
|
|
804
859
|
baseSource,
|
|
805
860
|
EMPTY_SLOT_NAMES,
|
|
806
861
|
entries,
|
|
807
|
-
context.sourceCode
|
|
862
|
+
context.sourceCode,
|
|
863
|
+
true
|
|
808
864
|
);
|
|
809
865
|
}
|
|
810
866
|
const tokenMap = indexEntriesBySlotAndToken(entries).get("base");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slot-variants",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "Type-safe class name variants with slots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"@types/estree": "1.0.9",
|
|
55
55
|
"class-variance-authority": "0.7.1",
|
|
56
56
|
"classnames": "2.5.1",
|
|
57
|
+
"clsx": "2.1.1",
|
|
57
58
|
"eslint": "10.3.0",
|
|
58
59
|
"fallow": "^2.62.0",
|
|
59
60
|
"jiti": "2.7.0",
|