nestable-tailwind-variants 0.1.4 → 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 +508 -132
- 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 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- 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 +40 -42
- package/dist/ntv.d.ts.map +1 -1
- package/dist/ntv.js +47 -98
- 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 +100 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -6
- package/dist/composeNtv.d.ts +0 -47
- package/dist/composeNtv.d.ts.map +0 -1
- package/dist/composeNtv.js +0 -55
- package/dist/composeNtv.js.map +0 -1
- package/dist/utils.d.ts +0 -2
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -4
- package/dist/utils.js.map +0 -1
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { extendTailwindMerge } from 'tailwind-merge';
|
|
2
|
+
import type { NtvOptions } from './types.js';
|
|
3
|
+
type TwMergeConfig = NonNullable<NtvOptions['twMergeConfig']>;
|
|
4
|
+
type TwMergeFn = ReturnType<typeof extendTailwindMerge>;
|
|
5
|
+
export declare function getCachedTwMerge(config: TwMergeConfig): TwMergeFn;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +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,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,KAAK,aAAa,GAAG,WAAW,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;AAC9D,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAIxD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAOjE"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { extendTailwindMerge } from 'tailwind-merge';
|
|
2
|
+
const cache = new Map();
|
|
3
|
+
export function getCachedTwMerge(config) {
|
|
4
|
+
let cached = cache.get(config);
|
|
5
|
+
if (!cached) {
|
|
6
|
+
cached = extendTailwindMerge(config);
|
|
7
|
+
cache.set(config, cached);
|
|
8
|
+
}
|
|
9
|
+
return cached;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAMrD,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
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export type {
|
|
1
|
+
export { createMergeNtv, mergeNtv, mergeNtvWithOptions } from './merge.js';
|
|
2
|
+
export { createNtv, ntv } from './ntv.js';
|
|
3
|
+
export type { ClassProp, ClassValue, NtvOptions, 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,
|
|
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,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
1
|
+
export { createMergeNtv, mergeNtv, mergeNtvWithOptions } from './merge.js';
|
|
2
|
+
export { createNtv, ntv } from './ntv.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","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"}
|
package/dist/merge.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { MergeStyleFunctionProps, NtvOptions, StyleFunction } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a merged style function with custom options (curried version).
|
|
4
|
+
*
|
|
5
|
+
* @param styleFns - Style functions to merge
|
|
6
|
+
* @returns A function that accepts options and returns a merged style function
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const styles = mergeNtvWithOptions(baseStyles, overrideStyles)({ twMerge: false });
|
|
11
|
+
* styles({ variant: 'primary' });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeNtvWithOptions<T extends readonly StyleFunction<any>[]>(...styleFns: T): (options?: NtvOptions) => StyleFunction<MergeStyleFunctionProps<T>>;
|
|
15
|
+
/**
|
|
16
|
+
* Merge multiple style functions into a single style function.
|
|
17
|
+
* Later functions take precedence over earlier ones (via tailwind-merge).
|
|
18
|
+
*
|
|
19
|
+
* @param styleFns - Style functions to merge
|
|
20
|
+
* @returns A merged style function that accepts combined props from all input functions
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const colorStyles = ntv<{ color: 'red' | 'blue' }>({
|
|
25
|
+
* color: { red: 'text-red', blue: 'text-blue' },
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* const sizeStyles = ntv<{ size: 'sm' | 'lg' }>({
|
|
29
|
+
* size: { sm: 'text-sm', lg: 'text-lg' },
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const styles = mergeNtv(colorStyles, sizeStyles);
|
|
33
|
+
* styles({ color: 'red', size: 'lg' }); // 'text-red text-lg'
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function mergeNtv<T extends readonly StyleFunction<any>[]>(...styleFns: T): StyleFunction<MergeStyleFunctionProps<T>>;
|
|
37
|
+
/**
|
|
38
|
+
* Create a pre-configured mergeNtv function with fixed options.
|
|
39
|
+
*
|
|
40
|
+
* @param defaultOptions - Default options to apply to all mergeNtv calls
|
|
41
|
+
* @returns A pre-configured mergeNtv function
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* const myMergeNtv = createMergeNtv({
|
|
46
|
+
* twMergeConfig: {
|
|
47
|
+
* extend: {
|
|
48
|
+
* classGroups: {
|
|
49
|
+
* 'font-size': [{ text: ['huge', 'tiny'] }],
|
|
50
|
+
* },
|
|
51
|
+
* },
|
|
52
|
+
* },
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* const styles = myMergeNtv(baseStyles, overrideStyles);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function createMergeNtv(defaultOptions: NtvOptions): <T extends readonly StyleFunction<any>[]>(...styleFns: T) => StyleFunction<MergeStyleFunctionProps<[...T]>>;
|
|
59
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,uBAAuB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhG;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE,EACzE,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,aAAa,CAAC,GAAG,CAAC,EAAE,EAC9D,GAAG,QAAQ,EAAE,CAAC,GACb,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAE3C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,UAAU,IACpB,CAAC,SAAS,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,UAAU,CAAC,oDAG3F"}
|
package/dist/merge.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { twJoin, twMerge } from 'tailwind-merge';
|
|
2
|
+
import { getCachedTwMerge } from './cache.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create a merged style function with custom options (curried version).
|
|
5
|
+
*
|
|
6
|
+
* @param styleFns - Style functions to merge
|
|
7
|
+
* @returns A function that accepts options and returns a merged style function
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const styles = mergeNtvWithOptions(baseStyles, overrideStyles)({ twMerge: false });
|
|
12
|
+
* styles({ variant: 'primary' });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function mergeNtvWithOptions(...styleFns) {
|
|
16
|
+
return function createMergedStyleFn({ twMerge: usesTwMerge = true, twMergeConfig, } = {}) {
|
|
17
|
+
const mergeFn = usesTwMerge
|
|
18
|
+
? twMergeConfig
|
|
19
|
+
? getCachedTwMerge(twMergeConfig)
|
|
20
|
+
: twMerge
|
|
21
|
+
: twJoin;
|
|
22
|
+
return function mergedStyleFn({ class: slotClass, className: slotClassName, ...props } = {}) {
|
|
23
|
+
const styleResults = styleFns.map((fn) => fn(props));
|
|
24
|
+
return mergeFn(...styleResults, slotClass, slotClassName);
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Merge multiple style functions into a single style function.
|
|
30
|
+
* Later functions take precedence over earlier ones (via tailwind-merge).
|
|
31
|
+
*
|
|
32
|
+
* @param styleFns - Style functions to merge
|
|
33
|
+
* @returns A merged style function that accepts combined props from all input functions
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const colorStyles = ntv<{ color: 'red' | 'blue' }>({
|
|
38
|
+
* color: { red: 'text-red', blue: 'text-blue' },
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* const sizeStyles = ntv<{ size: 'sm' | 'lg' }>({
|
|
42
|
+
* size: { sm: 'text-sm', lg: 'text-lg' },
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* const styles = mergeNtv(colorStyles, sizeStyles);
|
|
46
|
+
* styles({ color: 'red', size: 'lg' }); // 'text-red text-lg'
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function mergeNtv(...styleFns) {
|
|
50
|
+
return mergeNtvWithOptions(...styleFns)();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a pre-configured mergeNtv function with fixed options.
|
|
54
|
+
*
|
|
55
|
+
* @param defaultOptions - Default options to apply to all mergeNtv calls
|
|
56
|
+
* @returns A pre-configured mergeNtv function
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const myMergeNtv = createMergeNtv({
|
|
61
|
+
* twMergeConfig: {
|
|
62
|
+
* extend: {
|
|
63
|
+
* classGroups: {
|
|
64
|
+
* 'font-size': [{ text: ['huge', 'tiny'] }],
|
|
65
|
+
* },
|
|
66
|
+
* },
|
|
67
|
+
* },
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* const styles = myMergeNtv(baseStyles, overrideStyles);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function createMergeNtv(defaultOptions) {
|
|
74
|
+
return function configuredMergeNtv(...styleFns) {
|
|
75
|
+
return mergeNtvWithOptions(...styleFns)(defaultOptions);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEjD,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,KAAK,CAAC,CAAC,CAAC;YACrD,OAAO,OAAO,CAAC,GAAG,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QAC5D,CAA8C,CAAC;IACjD,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,QAAQ,CACtB,GAAG,QAAW;IAEd,OAAO,mBAAmB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,cAAc,CAAC,cAA0B;IACvD,OAAO,SAAS,kBAAkB,CAA0C,GAAG,QAAW;QACxF,OAAO,mBAAmB,CAAC,GAAG,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/ntv.d.ts
CHANGED
|
@@ -1,61 +1,59 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
type BooleanConditionKey = `is${Capitalize<string>}` | `allows${Capitalize<string>}`;
|
|
3
|
-
type ExtractBooleanKeys<Props> = {
|
|
4
|
-
[K in keyof Props]: K extends BooleanConditionKey ? K : never;
|
|
5
|
-
}[keyof Props];
|
|
6
|
-
type ExtractVariantKeys<Props> = Exclude<keyof Props, ExtractBooleanKeys<Props>>;
|
|
7
|
-
type NestedStyleValue<Props> = string | StyleDefinition<Props>;
|
|
8
|
-
type StyleDefinition<Props> = {
|
|
9
|
-
default?: string;
|
|
10
|
-
} & {
|
|
11
|
-
[K in ExtractBooleanKeys<Props>]?: NestedStyleValue<Props>;
|
|
12
|
-
} & {
|
|
13
|
-
[K in ExtractVariantKeys<Props>]?: {
|
|
14
|
-
[V in Extract<Props[K], string>]?: NestedStyleValue<Props>;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
1
|
+
import type { NtvOptions, NtvProps, NtvScheme, SchemeFor, StyleFunction } from './types.js';
|
|
17
2
|
/**
|
|
18
|
-
*
|
|
3
|
+
* Create a nestable tailwind variants style function.
|
|
4
|
+
*
|
|
5
|
+
* @param scheme - The scheme object defining variants and conditions
|
|
6
|
+
* @param options - Optional settings for tailwind-merge behavior
|
|
7
|
+
* @returns A style function that accepts props and returns merged class names
|
|
19
8
|
*
|
|
20
9
|
* @example
|
|
21
10
|
* ```ts
|
|
22
|
-
*
|
|
23
|
-
* const ntvNoMerge = createNTV({ twMerge: false });
|
|
11
|
+
* type ButtonProps = { variant: 'primary' | 'secondary'; isDisabled: boolean };
|
|
24
12
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* shadow: ['100', '200', '300'],
|
|
31
|
-
* },
|
|
32
|
-
* },
|
|
13
|
+
* const button = ntv<ButtonProps>({
|
|
14
|
+
* $base: 'px-4 py-2 rounded',
|
|
15
|
+
* variant: {
|
|
16
|
+
* primary: 'bg-blue-500 text-white',
|
|
17
|
+
* secondary: 'bg-gray-200 text-gray-800',
|
|
33
18
|
* },
|
|
19
|
+
* isDisabled: 'opacity-50 cursor-not-allowed',
|
|
34
20
|
* });
|
|
21
|
+
*
|
|
22
|
+
* button({ variant: 'primary' }); // 'px-4 py-2 rounded bg-blue-500 text-white'
|
|
23
|
+
* button({ variant: 'primary', isDisabled: true }); // 'px-4 py-2 rounded bg-blue-500 text-white opacity-50 cursor-not-allowed'
|
|
35
24
|
* ```
|
|
36
25
|
*/
|
|
37
|
-
export declare function
|
|
26
|
+
export declare function ntv<TProps extends NtvProps>(scheme: SchemeFor<TProps>, options?: NtvOptions): StyleFunction<TProps>;
|
|
27
|
+
export declare function ntv(scheme: NtvScheme, options?: NtvOptions): StyleFunction<any>;
|
|
38
28
|
/**
|
|
39
|
-
*
|
|
29
|
+
* Create a pre-configured ntv function with fixed options.
|
|
30
|
+
*
|
|
31
|
+
* @param defaultOptions - Default options to apply to all ntv calls
|
|
32
|
+
* @returns A pre-configured ntv function
|
|
40
33
|
*
|
|
41
34
|
* @example
|
|
42
35
|
* ```ts
|
|
43
|
-
* const
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
36
|
+
* const myNtv = createNtv({
|
|
37
|
+
* twMergeConfig: {
|
|
38
|
+
* extend: {
|
|
39
|
+
* classGroups: {
|
|
40
|
+
* 'font-size': [{ text: ['huge', 'tiny'] }],
|
|
41
|
+
* },
|
|
42
|
+
* },
|
|
48
43
|
* },
|
|
49
|
-
* isDisabled: 'opacity-50 cursor-not-allowed',
|
|
50
44
|
* });
|
|
51
45
|
*
|
|
52
|
-
* button({
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
46
|
+
* const button = myNtv({
|
|
47
|
+
* $base: 'text-huge',
|
|
48
|
+
* variant: {
|
|
49
|
+
* primary: 'bg-blue-500',
|
|
50
|
+
* secondary: 'bg-gray-200',
|
|
51
|
+
* },
|
|
52
|
+
* });
|
|
57
53
|
* ```
|
|
58
54
|
*/
|
|
59
|
-
export declare
|
|
60
|
-
|
|
55
|
+
export declare function createNtv(defaultOptions: NtvOptions): {
|
|
56
|
+
<TProps extends NtvProps>(scheme: SchemeFor<TProps>): StyleFunction<TProps>;
|
|
57
|
+
(scheme: NtvScheme): StyleFunction<any>;
|
|
58
|
+
};
|
|
61
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,EAEV,UAAU,EACV,QAAQ,EACR,SAAS,EACT,SAAS,EACT,aAAa,EACd,MAAM,YAAY,CAAC;AAoCpB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,GAAG,CAAC,MAAM,SAAS,QAAQ,EACzC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EACzB,OAAO,CAAC,EAAE,UAAU,GACnB,aAAa,CAAC,MAAM,CAAC,CAAC;AACzB,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;AAwBjF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,SAAS,CAAC,cAAc,EAAE,UAAU,GAAG;IACrD,CAAC,MAAM,SAAS,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC,MAAM,EAAE,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;CACzC,CAIA"}
|
package/dist/ntv.js
CHANGED
|
@@ -1,123 +1,72 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { twJoin, twMerge } from 'tailwind-merge';
|
|
2
|
+
import { getCachedTwMerge } from './cache.js';
|
|
3
|
+
import { resolveConditions } from './resolver.js';
|
|
4
|
+
function isPlainObject(value) {
|
|
4
5
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
6
|
}
|
|
6
|
-
function
|
|
7
|
-
if (
|
|
8
|
-
|
|
9
|
-
return;
|
|
7
|
+
function validateScheme(scheme) {
|
|
8
|
+
if ('class' in scheme) {
|
|
9
|
+
throw new Error('The "class" property is not allowed in ntv scheme. Use "$base" instead.');
|
|
10
10
|
}
|
|
11
|
-
if (
|
|
12
|
-
|
|
11
|
+
if ('className' in scheme) {
|
|
12
|
+
throw new Error('The "className" property is not allowed in ntv scheme. Use "$base" instead.');
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
for (const [key, value] of entries) {
|
|
18
|
-
if
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
else {
|
|
22
|
-
conditions.push([key, value]);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const allConditionKeys = conditions.map(([key]) => key);
|
|
26
|
-
const subSkipConditions = new Set([...context.skipConditions, ...allConditionKeys]);
|
|
27
|
-
if (defaultValue !== undefined) {
|
|
28
|
-
evaluateDefinition(defaultValue, {
|
|
29
|
-
...context,
|
|
30
|
-
skipConditions: subSkipConditions,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
for (const [key, value] of conditions) {
|
|
34
|
-
if (context.skipConditions.has(key)) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
subSkipConditions.delete(key);
|
|
38
|
-
const propValue = context.props[key];
|
|
39
|
-
if (/^(is|allows)[A-Z]/.test(key) && propValue) {
|
|
40
|
-
const nestedSkipConditions = new Set([...subSkipConditions, key]);
|
|
41
|
-
evaluateDefinition(value, {
|
|
42
|
-
props: context.props,
|
|
43
|
-
skipConditions: nestedSkipConditions,
|
|
44
|
-
classes: context.classes,
|
|
45
|
-
});
|
|
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.`);
|
|
46
21
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (variantValue !== undefined) {
|
|
51
|
-
const nestedSkipConditions = new Set([...subSkipConditions, key]);
|
|
52
|
-
evaluateDefinition(variantValue, {
|
|
53
|
-
props: context.props,
|
|
54
|
-
skipConditions: nestedSkipConditions,
|
|
55
|
-
classes: context.classes,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
22
|
+
// Recursively validate nested objects
|
|
23
|
+
if (isPlainObject(value)) {
|
|
24
|
+
validateNoNestedSpecialKeys(value, true);
|
|
59
25
|
}
|
|
60
26
|
}
|
|
61
27
|
}
|
|
28
|
+
export function ntv(scheme, { twMerge: usesTwMerge = true, twMergeConfig } = {}) {
|
|
29
|
+
validateScheme(scheme);
|
|
30
|
+
const { $base, ...conditions } = scheme;
|
|
31
|
+
const mergeFn = usesTwMerge
|
|
32
|
+
? twMergeConfig
|
|
33
|
+
? getCachedTwMerge(twMergeConfig)
|
|
34
|
+
: twMerge
|
|
35
|
+
: twJoin;
|
|
36
|
+
return function styleFn({ class: slotClass, className: slotClassName, ...props } = {}) {
|
|
37
|
+
return mergeFn($base, ...resolveConditions(conditions, props), slotClass, slotClassName);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
62
40
|
/**
|
|
63
|
-
*
|
|
41
|
+
* Create a pre-configured ntv function with fixed options.
|
|
42
|
+
*
|
|
43
|
+
* @param defaultOptions - Default options to apply to all ntv calls
|
|
44
|
+
* @returns A pre-configured ntv function
|
|
64
45
|
*
|
|
65
46
|
* @example
|
|
66
47
|
* ```ts
|
|
67
|
-
*
|
|
68
|
-
* const ntvNoMerge = createNTV({ twMerge: false });
|
|
69
|
-
*
|
|
70
|
-
* // With custom tailwind-merge config
|
|
71
|
-
* const customNTV = createNTV({
|
|
48
|
+
* const myNtv = createNtv({
|
|
72
49
|
* twMergeConfig: {
|
|
73
50
|
* extend: {
|
|
74
|
-
*
|
|
75
|
-
*
|
|
51
|
+
* classGroups: {
|
|
52
|
+
* 'font-size': [{ text: ['huge', 'tiny'] }],
|
|
76
53
|
* },
|
|
77
54
|
* },
|
|
78
55
|
* },
|
|
79
56
|
* });
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
export function createNTV(options = {}) {
|
|
83
|
-
const { twMerge: useTwMerge = true, twMergeConfig } = options;
|
|
84
|
-
const mergeClasses = useTwMerge
|
|
85
|
-
? twMergeConfig
|
|
86
|
-
? extendTailwindMerge(twMergeConfig)
|
|
87
|
-
: twMerge
|
|
88
|
-
: joinClasses;
|
|
89
|
-
return function ntv(style) {
|
|
90
|
-
return (props) => {
|
|
91
|
-
const context = {
|
|
92
|
-
props,
|
|
93
|
-
skipConditions: new Set(),
|
|
94
|
-
classes: [],
|
|
95
|
-
};
|
|
96
|
-
evaluateDefinition(style, context);
|
|
97
|
-
return mergeClasses(...context.classes);
|
|
98
|
-
};
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Creates a style function from a nested style definition.
|
|
103
57
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* const button = ntv<{ variant?: 'primary' | 'secondary'; isDisabled?: boolean }>({
|
|
107
|
-
* default: 'px-4 py-2 rounded',
|
|
58
|
+
* const button = myNtv({
|
|
59
|
+
* $base: 'text-huge',
|
|
108
60
|
* variant: {
|
|
109
|
-
* primary: 'bg-blue-500
|
|
110
|
-
* secondary: 'bg-gray-200
|
|
61
|
+
* primary: 'bg-blue-500',
|
|
62
|
+
* secondary: 'bg-gray-200',
|
|
111
63
|
* },
|
|
112
|
-
* isDisabled: 'opacity-50 cursor-not-allowed',
|
|
113
64
|
* });
|
|
114
|
-
*
|
|
115
|
-
* button({ variant: 'primary' });
|
|
116
|
-
* // => 'px-4 py-2 rounded bg-blue-500 text-white'
|
|
117
|
-
*
|
|
118
|
-
* button({ variant: 'primary', isDisabled: true });
|
|
119
|
-
* // => 'px-4 py-2 rounded bg-blue-500 text-white opacity-50 cursor-not-allowed'
|
|
120
65
|
* ```
|
|
121
66
|
*/
|
|
122
|
-
export
|
|
67
|
+
export function createNtv(defaultOptions) {
|
|
68
|
+
return function configuredNtv(scheme) {
|
|
69
|
+
return ntv(scheme, defaultOptions);
|
|
70
|
+
};
|
|
71
|
+
}
|
|
123
72
|
//# sourceMappingURL=ntv.js.map
|
package/dist/ntv.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ntv.js","sourceRoot":"","sources":["../src/ntv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ntv.js","sourceRoot":"","sources":["../src/ntv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AASjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,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,SAAS,cAAc,CAAC,MAAiB;IACvC,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC7F,CAAC;IAED,IAAI,WAAW,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;IAED,2BAA2B,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,2BAA2B,CAAC,GAA4B,EAAE,QAAiB;IAClF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,4DAA4D;QAC5D,IAAI,QAAQ,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,QAAQ,GAAG,+GAA+G,CAC3H,CAAC;QACJ,CAAC;QAED,sCAAsC;QACtC,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,2BAA2B,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;AACH,CAAC;AA+BD,MAAM,UAAU,GAAG,CACjB,MAAiB,EACjB,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,EAAE,aAAa,KAAiB,EAAE;IAE/D,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,EAAE,GAAG,MAAM,CAAC;IAExC,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,OAAO,OAAO,CAAC,KAAK,EAAE,GAAG,iBAAiB,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;IAC3F,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,SAAS,CAAC,cAA0B;IAIlD,OAAO,SAAS,aAAa,CAAC,MAAiB;QAC7C,OAAO,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ClassValue } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves conditions from scheme based on provided props to generate class values.
|
|
4
|
+
*
|
|
5
|
+
* $default behavior:
|
|
6
|
+
* - If no conditions match at a level, that level's $default is applied
|
|
7
|
+
* - If a variant matches, only the nested evaluation result is used
|
|
8
|
+
* - When no conditions match, $defaults accumulate from each unmatched level
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveConditions({ $default, ...conditions }: Record<string, unknown>, props: Record<string, unknown>): ClassValue[];
|
|
11
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +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,EACpD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,UAAU,EAAE,CA8Cd"}
|
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"}
|