nestable-tailwind-variants 0.1.3 → 0.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/README.md +512 -115
- package/dist/cache.d.ts +7 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +11 -0
- package/dist/cache.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/merge.d.ts +59 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +78 -0
- package/dist/merge.js.map +1 -0
- package/dist/ntv.d.ts +30 -91
- package/dist/ntv.d.ts.map +1 -1
- package/dist/ntv.js +44 -147
- package/dist/ntv.js.map +1 -1
- package/dist/resolver.d.ts +11 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +52 -0
- package/dist/resolver.js.map +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +12 -9
package/dist/resolver.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function isObject(value) {
|
|
2
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Resolves conditions from scheme based on provided props to generate class values.
|
|
6
|
+
*
|
|
7
|
+
* $default behavior:
|
|
8
|
+
* - If no conditions match at a level, that level's $default is applied
|
|
9
|
+
* - If a variant matches, only the nested evaluation result is used
|
|
10
|
+
* - When no conditions match, $defaults accumulate from each unmatched level
|
|
11
|
+
*/
|
|
12
|
+
export function resolveConditions({ $default, ...conditions }, props) {
|
|
13
|
+
const classes = [];
|
|
14
|
+
let hasMatchedCondition = false;
|
|
15
|
+
function addClasses(value) {
|
|
16
|
+
if (isObject(value)) {
|
|
17
|
+
classes.push(...resolveConditions(value, props));
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
classes.push(value);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const [key, value] of Object.entries(conditions)) {
|
|
24
|
+
const propValue = props[key];
|
|
25
|
+
if (propValue === '$default') {
|
|
26
|
+
throw new Error(`The value "$default" cannot be passed as a runtime value for "${key}". "$default" is a reserved keyword.`);
|
|
27
|
+
}
|
|
28
|
+
// Boolean conditions (isXxx or allowsXxx)
|
|
29
|
+
if (/^is[A-Z]/.test(key) || /^allows[A-Z]/.test(key)) {
|
|
30
|
+
if (propValue) {
|
|
31
|
+
hasMatchedCondition = true;
|
|
32
|
+
addClasses(value);
|
|
33
|
+
}
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Variant conditions (nested objects)
|
|
37
|
+
if (isObject(value)) {
|
|
38
|
+
if (typeof propValue === 'string' && propValue in value) {
|
|
39
|
+
hasMatchedCondition = true;
|
|
40
|
+
addClasses(value[propValue]);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
classes.push(value['$default']);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!hasMatchedCondition) {
|
|
48
|
+
classes.unshift($default);
|
|
49
|
+
}
|
|
50
|
+
return classes;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAEA,SAAS,QAAQ,CAAC,KAAc;IAC9B,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,QAAQ,EAAE,GAAG,UAAU,EAA2B,EACpD,KAA8B;IAE9B,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAEhC,SAAS,UAAU,CAAC,KAAc;QAChC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,KAAmB,CAAC,CAAC;QACpC,CAAC;IACH,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,UAAU,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;YACD,SAAS;QACX,CAAC;QAED,sCAAsC;QACtC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;gBACxD,mBAAmB,GAAG,IAAI,CAAC;gBAC3B,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAe,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,OAAO,CAAC,OAAO,CAAC,QAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { ClassNameValue as ClassValue, extendTailwindMerge } from 'tailwind-merge';
|
|
2
|
+
export type { ClassValue };
|
|
3
|
+
/**
|
|
4
|
+
* Union type for class prop - ensures only one of class or className is used.
|
|
5
|
+
* This prevents ambiguity when passing class names to components.
|
|
6
|
+
*/
|
|
7
|
+
export type ClassProp = {
|
|
8
|
+
class?: ClassValue;
|
|
9
|
+
className?: never;
|
|
10
|
+
} | {
|
|
11
|
+
class?: never;
|
|
12
|
+
className?: ClassValue;
|
|
13
|
+
};
|
|
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> = {
|
|
45
|
+
[K in keyof T]: T[K];
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Function signature for style generators.
|
|
49
|
+
* Accepts optional props and returns a string of class names.
|
|
50
|
+
*/
|
|
51
|
+
export type StyleFunction<TProps> = (props?: Simplify<PartialWithUndefined<TProps> & ClassProp>) => string;
|
|
52
|
+
/**
|
|
53
|
+
* Boolean scheme entry - class value or nested scheme with conditions.
|
|
54
|
+
*/
|
|
55
|
+
type BooleanSchemeEntry<TProps extends NtvProps> = ClassValue | (SchemeFor<TProps> & {
|
|
56
|
+
$default?: ClassValue;
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Variant scheme entry - maps variant values to class values or nested schemes.
|
|
60
|
+
*/
|
|
61
|
+
type VariantSchemeEntry<TVariant extends string, TProps extends NtvProps> = {
|
|
62
|
+
[V in TVariant]?: ClassValue | (SchemeFor<TProps> & {
|
|
63
|
+
$default?: ClassValue;
|
|
64
|
+
});
|
|
65
|
+
} & {
|
|
66
|
+
$default?: ClassValue;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Scheme conditions based on the props type.
|
|
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;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Main scheme type for NTV style definitions.
|
|
77
|
+
* Validated against TProps to ensure type safety.
|
|
78
|
+
*/
|
|
79
|
+
export type SchemeFor<TProps extends NtvProps> = {
|
|
80
|
+
$base?: ClassValue;
|
|
81
|
+
$default?: ClassValue;
|
|
82
|
+
} & SchemeConditions<TProps>;
|
|
83
|
+
/**
|
|
84
|
+
* Runtime scheme interface for NTV style definitions.
|
|
85
|
+
* Untyped version used for JavaScript or when types aren't available.
|
|
86
|
+
*/
|
|
87
|
+
export interface NtvScheme {
|
|
88
|
+
$base?: ClassValue;
|
|
89
|
+
$default?: ClassValue;
|
|
90
|
+
[key: string]: unknown;
|
|
91
|
+
}
|
|
92
|
+
export type TwMergeConfig = Parameters<typeof extendTailwindMerge>[0];
|
|
93
|
+
/**
|
|
94
|
+
* Configuration options for NTV function behavior.
|
|
95
|
+
*/
|
|
96
|
+
export interface NtvOptions {
|
|
97
|
+
/**
|
|
98
|
+
* Whether to merge the class names with `tailwind-merge` library.
|
|
99
|
+
* It's avoid to have duplicate tailwind classes. (Recommended)
|
|
100
|
+
* @see https://github.com/dcastil/tailwind-merge
|
|
101
|
+
* @default true
|
|
102
|
+
*/
|
|
103
|
+
twMerge?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* The config object for `tailwind-merge` library.
|
|
106
|
+
* @see https://github.com/dcastil/tailwind-merge/blob/main/docs/configuration.md
|
|
107
|
+
*/
|
|
108
|
+
twMergeConfig?: TwMergeConfig;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestable-tailwind-variants",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
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": {
|
|
7
7
|
"url": "https://github.com/yuheiy/nestable-tailwind-variants/issues"
|
|
@@ -26,17 +26,18 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@commitlint/cli": "^20.3.1",
|
|
28
28
|
"@commitlint/config-conventional": "^20.3.1",
|
|
29
|
-
"bumpp": "^10.
|
|
29
|
+
"bumpp": "^10.4.0",
|
|
30
|
+
"knip": "^5.82.0",
|
|
30
31
|
"lint-staged": "^16.2.7",
|
|
31
|
-
"oxfmt": "^0.
|
|
32
|
-
"oxlint": "^1.
|
|
32
|
+
"oxfmt": "^0.25.0",
|
|
33
|
+
"oxlint": "^1.39.0",
|
|
33
34
|
"typescript": "^5.9.3",
|
|
34
|
-
"vitest": "^4.0.
|
|
35
|
+
"vitest": "^4.0.17",
|
|
35
36
|
"node": "runtime:^24.12.0"
|
|
36
37
|
},
|
|
37
38
|
"lint-staged": {
|
|
38
39
|
"*": "oxfmt --no-error-on-unmatched-pattern",
|
|
39
|
-
"*.{js,jsx,ts,tsx,mjs,cjs}": "
|
|
40
|
+
"*.{js,jsx,ts,tsx,mjs,cjs}": "node --run lint"
|
|
40
41
|
},
|
|
41
42
|
"devEngines": {
|
|
42
43
|
"runtime": {
|
|
@@ -46,13 +47,15 @@
|
|
|
46
47
|
}
|
|
47
48
|
},
|
|
48
49
|
"scripts": {
|
|
49
|
-
"build": "tsc",
|
|
50
|
+
"build": "tsc -p tsconfig.build.json",
|
|
51
|
+
"clean": "git clean -fx dist/",
|
|
50
52
|
"format": "oxfmt",
|
|
51
53
|
"format:check": "oxfmt --check",
|
|
54
|
+
"knip": "knip",
|
|
52
55
|
"lint": "oxlint",
|
|
53
56
|
"lint:fix": "oxlint --fix",
|
|
54
57
|
"release": "bumpp -r",
|
|
55
|
-
"test": "vitest",
|
|
58
|
+
"test": "vitest --run",
|
|
56
59
|
"typecheck": "tsc --noEmit"
|
|
57
60
|
}
|
|
58
61
|
}
|