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/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,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
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';
|
|
3
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
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,64 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export type TWMergeConfig = Parameters<typeof extendTailwindMerge>[0];
|
|
3
|
-
export interface NTVConfig {
|
|
4
|
-
/**
|
|
5
|
-
* Whether to use `tailwind-merge` to resolve conflicting Tailwind classes.
|
|
6
|
-
* @see https://github.com/dcastil/tailwind-merge
|
|
7
|
-
* @default true
|
|
8
|
-
*/
|
|
9
|
-
twMerge?: boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Custom configuration for `tailwind-merge`.
|
|
12
|
-
* @see https://github.com/dcastil/tailwind-merge/blob/main/docs/configuration.md
|
|
13
|
-
*/
|
|
14
|
-
twMergeConfig?: TWMergeConfig;
|
|
15
|
-
}
|
|
16
|
-
type BooleanConditionKey = `is${Capitalize<string>}` | `allows${Capitalize<string>}`;
|
|
17
|
-
type ExtractBooleanKeys<Props> = {
|
|
18
|
-
[K in keyof Props]: K extends BooleanConditionKey ? K : never;
|
|
19
|
-
}[keyof Props];
|
|
20
|
-
type ExtractVariantKeys<Props> = Exclude<keyof Props, ExtractBooleanKeys<Props>>;
|
|
21
|
-
type NestedStyleValue<Props> = string | StyleDefinition<Props>;
|
|
22
|
-
type StyleDefinition<Props> = {
|
|
23
|
-
default?: string;
|
|
24
|
-
} & {
|
|
25
|
-
[K in ExtractBooleanKeys<Props>]?: NestedStyleValue<Props>;
|
|
26
|
-
} & {
|
|
27
|
-
[K in ExtractVariantKeys<Props>]?: {
|
|
28
|
-
[V in Extract<Props[K], string>]?: NestedStyleValue<Props>;
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
type StyleFunction<P = Record<string, unknown>> = (props: Partial<P>) => string;
|
|
32
|
-
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
33
|
-
type ExtractProps<T> = T extends StyleFunction<infer P> ? P : never;
|
|
1
|
+
import type { NtvOptions, NtvProps, NtvScheme, SchemeFor, StyleFunction } from './types.js';
|
|
34
2
|
/**
|
|
35
|
-
*
|
|
3
|
+
* Create a nestable tailwind variants style function.
|
|
36
4
|
*
|
|
37
|
-
* @
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* const ntvNoMerge = createNTV({ twMerge: false });
|
|
41
|
-
*
|
|
42
|
-
* // With custom tailwind-merge config
|
|
43
|
-
* const customNTV = createNTV({
|
|
44
|
-
* twMergeConfig: {
|
|
45
|
-
* extend: {
|
|
46
|
-
* theme: {
|
|
47
|
-
* shadow: ['100', '200', '300'],
|
|
48
|
-
* },
|
|
49
|
-
* },
|
|
50
|
-
* },
|
|
51
|
-
* });
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
export declare function createNTV(options?: NTVConfig): <Props extends Record<string, any>>(style: StyleDefinition<Props>) => StyleFunction<Props>;
|
|
55
|
-
/**
|
|
56
|
-
* Creates a style function from a nested style definition.
|
|
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
|
|
57
8
|
*
|
|
58
9
|
* @example
|
|
59
10
|
* ```ts
|
|
60
|
-
*
|
|
61
|
-
*
|
|
11
|
+
* type ButtonProps = { variant: 'primary' | 'secondary'; isDisabled: boolean };
|
|
12
|
+
*
|
|
13
|
+
* const button = ntv<ButtonProps>({
|
|
14
|
+
* $base: 'px-4 py-2 rounded',
|
|
62
15
|
* variant: {
|
|
63
16
|
* primary: 'bg-blue-500 text-white',
|
|
64
17
|
* secondary: 'bg-gray-200 text-gray-800',
|
|
@@ -66,55 +19,41 @@ export declare function createNTV(options?: NTVConfig): <Props extends Record<st
|
|
|
66
19
|
* isDisabled: 'opacity-50 cursor-not-allowed',
|
|
67
20
|
* });
|
|
68
21
|
*
|
|
69
|
-
* button({ variant: 'primary' });
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* button({ variant: 'primary', isDisabled: true });
|
|
73
|
-
* // => 'px-4 py-2 rounded bg-blue-500 text-white opacity-50 cursor-not-allowed'
|
|
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'
|
|
74
24
|
* ```
|
|
75
25
|
*/
|
|
76
|
-
export declare
|
|
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>;
|
|
77
28
|
/**
|
|
78
|
-
*
|
|
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
|
|
79
33
|
*
|
|
80
34
|
* @example
|
|
81
35
|
* ```ts
|
|
82
|
-
*
|
|
83
|
-
* const composeNtvNoMerge = createComposeNtv({ twMerge: false });
|
|
84
|
-
*
|
|
85
|
-
* // With custom tailwind-merge config
|
|
86
|
-
* const customComposeNtv = createComposeNtv({
|
|
36
|
+
* const myNtv = createNtv({
|
|
87
37
|
* twMergeConfig: {
|
|
88
38
|
* extend: {
|
|
89
|
-
*
|
|
90
|
-
*
|
|
39
|
+
* classGroups: {
|
|
40
|
+
* 'font-size': [{ text: ['huge', 'tiny'] }],
|
|
91
41
|
* },
|
|
92
42
|
* },
|
|
93
43
|
* },
|
|
94
44
|
* });
|
|
95
|
-
* ```
|
|
96
|
-
*/
|
|
97
|
-
export declare function createComposeNtv(options?: NTVConfig): <T extends StyleFunction[]>(...fns: T) => StyleFunction<UnionToIntersection<ExtractProps<T[number]>>>;
|
|
98
|
-
/**
|
|
99
|
-
* Composes multiple style functions into a single function.
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* ```ts
|
|
103
|
-
* const baseButton = ntv<{ size?: 'sm' | 'lg' }>({
|
|
104
|
-
* default: 'rounded font-medium',
|
|
105
|
-
* size: { sm: 'px-2 py-1 text-sm', lg: 'px-4 py-2 text-lg' },
|
|
106
|
-
* });
|
|
107
45
|
*
|
|
108
|
-
* const
|
|
109
|
-
*
|
|
46
|
+
* const button = myNtv({
|
|
47
|
+
* $base: 'text-huge',
|
|
48
|
+
* variant: {
|
|
49
|
+
* primary: 'bg-blue-500',
|
|
50
|
+
* secondary: 'bg-gray-200',
|
|
51
|
+
* },
|
|
110
52
|
* });
|
|
111
|
-
*
|
|
112
|
-
* const button = composeNtv(baseButton, coloredButton);
|
|
113
|
-
*
|
|
114
|
-
* button({ size: 'lg', variant: 'primary' });
|
|
115
|
-
* // => 'rounded font-medium px-4 py-2 text-lg bg-blue-500 text-white'
|
|
116
53
|
* ```
|
|
117
54
|
*/
|
|
118
|
-
export declare
|
|
119
|
-
|
|
55
|
+
export declare function createNtv(defaultOptions: NtvOptions): {
|
|
56
|
+
<TProps extends NtvProps>(scheme: SchemeFor<TProps>): StyleFunction<TProps>;
|
|
57
|
+
(scheme: NtvScheme): StyleFunction<any>;
|
|
58
|
+
};
|
|
120
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":"
|
|
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,175 +1,72 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { twJoin, twMerge } from 'tailwind-merge';
|
|
2
|
+
import { getCachedTwMerge } from './cache.js';
|
|
3
|
+
import { resolveConditions } from './resolver.js';
|
|
4
|
+
function isPlainObject(value) {
|
|
3
5
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
4
6
|
}
|
|
5
|
-
function
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
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.');
|
|
9
10
|
}
|
|
10
|
-
if (
|
|
11
|
-
|
|
11
|
+
if ('className' in scheme) {
|
|
12
|
+
throw new Error('The "className" property is not allowed in ntv scheme. Use "$base" instead.');
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
for (const [key, value] of entries) {
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
else {
|
|
21
|
-
conditions.push([key, value]);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
const allConditionKeys = conditions.map(([key]) => key);
|
|
25
|
-
const subSkipConditions = new Set([...context.skipConditions, ...allConditionKeys]);
|
|
26
|
-
if (defaultValue !== undefined) {
|
|
27
|
-
evaluateDefinition(defaultValue, {
|
|
28
|
-
...context,
|
|
29
|
-
skipConditions: subSkipConditions,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
for (const [key, value] of conditions) {
|
|
33
|
-
if (context.skipConditions.has(key)) {
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
subSkipConditions.delete(key);
|
|
37
|
-
const propValue = context.props[key];
|
|
38
|
-
if (/^(is|allows)[A-Z]/.test(key) && propValue) {
|
|
39
|
-
const nestedSkipConditions = new Set([...subSkipConditions, key]);
|
|
40
|
-
evaluateDefinition(value, {
|
|
41
|
-
props: context.props,
|
|
42
|
-
skipConditions: nestedSkipConditions,
|
|
43
|
-
classes: context.classes,
|
|
44
|
-
});
|
|
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.`);
|
|
45
21
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (variantValue !== undefined) {
|
|
50
|
-
const nestedSkipConditions = new Set([...subSkipConditions, key]);
|
|
51
|
-
evaluateDefinition(variantValue, {
|
|
52
|
-
props: context.props,
|
|
53
|
-
skipConditions: nestedSkipConditions,
|
|
54
|
-
classes: context.classes,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
}
|
|
22
|
+
// Recursively validate nested objects
|
|
23
|
+
if (isPlainObject(value)) {
|
|
24
|
+
validateNoNestedSpecialKeys(value, true);
|
|
58
25
|
}
|
|
59
26
|
}
|
|
60
27
|
}
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
* Creates a customized `ntv` function with the specified options.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```ts
|
|
69
|
-
* // Disable tailwind-merge
|
|
70
|
-
* const ntvNoMerge = createNTV({ twMerge: false });
|
|
71
|
-
*
|
|
72
|
-
* // With custom tailwind-merge config
|
|
73
|
-
* const customNTV = createNTV({
|
|
74
|
-
* twMergeConfig: {
|
|
75
|
-
* extend: {
|
|
76
|
-
* theme: {
|
|
77
|
-
* shadow: ['100', '200', '300'],
|
|
78
|
-
* },
|
|
79
|
-
* },
|
|
80
|
-
* },
|
|
81
|
-
* });
|
|
82
|
-
* ```
|
|
83
|
-
*/
|
|
84
|
-
export function createNTV(options = {}) {
|
|
85
|
-
const { twMerge: useTwMerge = true, twMergeConfig } = options;
|
|
86
|
-
const mergeClasses = useTwMerge
|
|
28
|
+
export function ntv(scheme, { twMerge: usesTwMerge = true, twMergeConfig } = {}) {
|
|
29
|
+
validateScheme(scheme);
|
|
30
|
+
const { $base, ...conditions } = scheme;
|
|
31
|
+
const mergeFn = usesTwMerge
|
|
87
32
|
? twMergeConfig
|
|
88
|
-
?
|
|
33
|
+
? getCachedTwMerge(twMergeConfig)
|
|
89
34
|
: twMerge
|
|
90
|
-
:
|
|
91
|
-
return function
|
|
92
|
-
return (props)
|
|
93
|
-
const context = {
|
|
94
|
-
props,
|
|
95
|
-
skipConditions: new Set(),
|
|
96
|
-
classes: [],
|
|
97
|
-
};
|
|
98
|
-
evaluateDefinition(style, context);
|
|
99
|
-
return mergeClasses(...context.classes);
|
|
100
|
-
};
|
|
35
|
+
: twJoin;
|
|
36
|
+
return function styleFn({ class: slotClass, className: slotClassName, ...props } = {}) {
|
|
37
|
+
return mergeFn($base, ...resolveConditions(conditions, props), slotClass, slotClassName);
|
|
101
38
|
};
|
|
102
39
|
}
|
|
103
40
|
/**
|
|
104
|
-
*
|
|
41
|
+
* Create a pre-configured ntv function with fixed options.
|
|
105
42
|
*
|
|
106
|
-
* @
|
|
107
|
-
*
|
|
108
|
-
* const button = ntv<{ variant?: 'primary' | 'secondary'; isDisabled?: boolean }>({
|
|
109
|
-
* default: 'px-4 py-2 rounded',
|
|
110
|
-
* variant: {
|
|
111
|
-
* primary: 'bg-blue-500 text-white',
|
|
112
|
-
* secondary: 'bg-gray-200 text-gray-800',
|
|
113
|
-
* },
|
|
114
|
-
* isDisabled: 'opacity-50 cursor-not-allowed',
|
|
115
|
-
* });
|
|
116
|
-
*
|
|
117
|
-
* button({ variant: 'primary' });
|
|
118
|
-
* // => 'px-4 py-2 rounded bg-blue-500 text-white'
|
|
119
|
-
*
|
|
120
|
-
* button({ variant: 'primary', isDisabled: true });
|
|
121
|
-
* // => 'px-4 py-2 rounded bg-blue-500 text-white opacity-50 cursor-not-allowed'
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
export const ntv = createNTV();
|
|
125
|
-
/**
|
|
126
|
-
* Creates a customized `composeNtv` function with the specified options.
|
|
43
|
+
* @param defaultOptions - Default options to apply to all ntv calls
|
|
44
|
+
* @returns A pre-configured ntv function
|
|
127
45
|
*
|
|
128
46
|
* @example
|
|
129
47
|
* ```ts
|
|
130
|
-
*
|
|
131
|
-
* const composeNtvNoMerge = createComposeNtv({ twMerge: false });
|
|
132
|
-
*
|
|
133
|
-
* // With custom tailwind-merge config
|
|
134
|
-
* const customComposeNtv = createComposeNtv({
|
|
48
|
+
* const myNtv = createNtv({
|
|
135
49
|
* twMergeConfig: {
|
|
136
50
|
* extend: {
|
|
137
|
-
*
|
|
138
|
-
*
|
|
51
|
+
* classGroups: {
|
|
52
|
+
* 'font-size': [{ text: ['huge', 'tiny'] }],
|
|
139
53
|
* },
|
|
140
54
|
* },
|
|
141
55
|
* },
|
|
142
56
|
* });
|
|
143
|
-
* ```
|
|
144
|
-
*/
|
|
145
|
-
export function createComposeNtv(options = {}) {
|
|
146
|
-
const { twMerge: useTwMerge = true, twMergeConfig } = options;
|
|
147
|
-
const mergeClasses = useTwMerge
|
|
148
|
-
? twMergeConfig
|
|
149
|
-
? extendTailwindMerge(twMergeConfig)
|
|
150
|
-
: twMerge
|
|
151
|
-
: joinClasses;
|
|
152
|
-
return (...fns) => (props) => mergeClasses(...fns.map((fn) => fn(props)));
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Composes multiple style functions into a single function.
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* ```ts
|
|
159
|
-
* const baseButton = ntv<{ size?: 'sm' | 'lg' }>({
|
|
160
|
-
* default: 'rounded font-medium',
|
|
161
|
-
* size: { sm: 'px-2 py-1 text-sm', lg: 'px-4 py-2 text-lg' },
|
|
162
|
-
* });
|
|
163
57
|
*
|
|
164
|
-
* const
|
|
165
|
-
*
|
|
58
|
+
* const button = myNtv({
|
|
59
|
+
* $base: 'text-huge',
|
|
60
|
+
* variant: {
|
|
61
|
+
* primary: 'bg-blue-500',
|
|
62
|
+
* secondary: 'bg-gray-200',
|
|
63
|
+
* },
|
|
166
64
|
* });
|
|
167
|
-
*
|
|
168
|
-
* const button = composeNtv(baseButton, coloredButton);
|
|
169
|
-
*
|
|
170
|
-
* button({ size: 'lg', variant: 'primary' });
|
|
171
|
-
* // => 'rounded font-medium px-4 py-2 text-lg bg-blue-500 text-white'
|
|
172
65
|
* ```
|
|
173
66
|
*/
|
|
174
|
-
export
|
|
67
|
+
export function createNtv(defaultOptions) {
|
|
68
|
+
return function configuredNtv(scheme) {
|
|
69
|
+
return ntv(scheme, defaultOptions);
|
|
70
|
+
};
|
|
71
|
+
}
|
|
175
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"}
|