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/dist/types.d.ts CHANGED
@@ -1,17 +1,110 @@
1
- import { extendTailwindMerge } from 'tailwind-merge';
2
- export type TWMergeConfig = Parameters<typeof extendTailwindMerge>[0];
3
- export interface NTVConfig {
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 {
4
97
  /**
5
- * Whether to use `tailwind-merge` to resolve conflicting Tailwind classes.
98
+ * Whether to merge the class names with `tailwind-merge` library.
99
+ * It's avoid to have duplicate tailwind classes. (Recommended)
6
100
  * @see https://github.com/dcastil/tailwind-merge
7
101
  * @default true
8
102
  */
9
103
  twMerge?: boolean;
10
104
  /**
11
- * Custom configuration for `tailwind-merge`.
105
+ * The config object for `tailwind-merge` library.
12
106
  * @see https://github.com/dcastil/tailwind-merge/blob/main/docs/configuration.md
13
107
  */
14
- twMergeConfig?: TWMergeConfig;
108
+ twMergeConfig?: TwMergeConfig;
15
109
  }
16
- export type StyleFunction<P = Record<string, unknown>> = (props: Partial<P>) => string;
17
110
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtE,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -1,2 +1,2 @@
1
- import { extendTailwindMerge } from 'tailwind-merge';
1
+ export {};
2
2
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
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.1.4",
4
- "description": "A variant styling library for Tailwind CSS that expresses complex style combinations through nested condition definitions instead of flat `compoundVariants` patterns.",
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,9 +26,10 @@
26
26
  "devDependencies": {
27
27
  "@commitlint/cli": "^20.3.1",
28
28
  "@commitlint/config-conventional": "^20.3.1",
29
- "bumpp": "^10.3.2",
29
+ "bumpp": "^10.4.0",
30
+ "knip": "^5.82.0",
30
31
  "lint-staged": "^16.2.7",
31
- "oxfmt": "^0.24.0",
32
+ "oxfmt": "^0.25.0",
32
33
  "oxlint": "^1.39.0",
33
34
  "typescript": "^5.9.3",
34
35
  "vitest": "^4.0.17",
@@ -46,14 +47,15 @@
46
47
  }
47
48
  },
48
49
  "scripts": {
49
- "build": "tsc",
50
+ "build": "tsc -p tsconfig.build.json",
50
51
  "clean": "git clean -fx dist/",
51
52
  "format": "oxfmt",
52
53
  "format:check": "oxfmt --check",
54
+ "knip": "knip",
53
55
  "lint": "oxlint",
54
56
  "lint:fix": "oxlint --fix",
55
57
  "release": "bumpp -r",
56
- "test": "vitest",
58
+ "test": "vitest --run",
57
59
  "typecheck": "tsc --noEmit"
58
60
  }
59
61
  }
@@ -1,47 +0,0 @@
1
- import type { NTVConfig, StyleFunction } from './types.js';
2
- type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
3
- type ExtractProps<T> = T extends StyleFunction<infer P> ? P : never;
4
- /**
5
- * Creates a customized `composeNtv` function with the specified options.
6
- *
7
- * @example
8
- * ```ts
9
- * // Disable tailwind-merge
10
- * const composeNtvNoMerge = createComposeNtv({ twMerge: false });
11
- *
12
- * // With custom tailwind-merge config
13
- * const customComposeNtv = createComposeNtv({
14
- * twMergeConfig: {
15
- * extend: {
16
- * theme: {
17
- * shadow: ['100', '200', '300'],
18
- * },
19
- * },
20
- * },
21
- * });
22
- * ```
23
- */
24
- export declare function createComposeNtv(options?: NTVConfig): <T extends StyleFunction[]>(...fns: T) => StyleFunction<UnionToIntersection<ExtractProps<T[number]>>>;
25
- /**
26
- * Composes multiple style functions into a single function.
27
- *
28
- * @example
29
- * ```ts
30
- * const baseButton = ntv<{ size?: 'sm' | 'lg' }>({
31
- * default: 'rounded font-medium',
32
- * size: { sm: 'px-2 py-1 text-sm', lg: 'px-4 py-2 text-lg' },
33
- * });
34
- *
35
- * const coloredButton = ntv<{ variant?: 'primary' | 'secondary' }>({
36
- * variant: { primary: 'bg-blue-500 text-white', secondary: 'bg-gray-200' },
37
- * });
38
- *
39
- * const button = composeNtv(baseButton, coloredButton);
40
- *
41
- * button({ size: 'lg', variant: 'primary' });
42
- * // => 'rounded font-medium px-4 py-2 text-lg bg-blue-500 text-white'
43
- * ```
44
- */
45
- export declare const composeNtv: <T extends StyleFunction[]>(...fns: T) => StyleFunction<UnionToIntersection<ExtractProps<T[number]>>>;
46
- export {};
47
- //# sourceMappingURL=composeNtv.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"composeNtv.d.ts","sourceRoot":"","sources":["../src/composeNtv.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3D,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,SAAS,CACjF,CAAC,EAAE,MAAM,CAAC,KACP,IAAI,GACL,CAAC,GACD,KAAK,CAAC;AAEV,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,SAAc,IAS3B,CAAC,SAAS,aAAa,EAAE,EAClD,GAAG,KAAK,CAAC,KACR,aAAa,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAG/D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,UAAU,GA3BM,CAAC,SAAS,aAAa,EAAE,UAC1C,CAAC,KACR,aAAa,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAyBnB,CAAC"}
@@ -1,55 +0,0 @@
1
- import { extendTailwindMerge, twMerge } from 'tailwind-merge';
2
- import { joinClasses } from './utils.js';
3
- /**
4
- * Creates a customized `composeNtv` function with the specified options.
5
- *
6
- * @example
7
- * ```ts
8
- * // Disable tailwind-merge
9
- * const composeNtvNoMerge = createComposeNtv({ twMerge: false });
10
- *
11
- * // With custom tailwind-merge config
12
- * const customComposeNtv = createComposeNtv({
13
- * twMergeConfig: {
14
- * extend: {
15
- * theme: {
16
- * shadow: ['100', '200', '300'],
17
- * },
18
- * },
19
- * },
20
- * });
21
- * ```
22
- */
23
- export function createComposeNtv(options = {}) {
24
- const { twMerge: useTwMerge = true, twMergeConfig } = options;
25
- const mergeClasses = useTwMerge
26
- ? twMergeConfig
27
- ? extendTailwindMerge(twMergeConfig)
28
- : twMerge
29
- : joinClasses;
30
- return function composeNtv(...fns) {
31
- return (props) => mergeClasses(...fns.map((fn) => fn(props)));
32
- };
33
- }
34
- /**
35
- * Composes multiple style functions into a single function.
36
- *
37
- * @example
38
- * ```ts
39
- * const baseButton = ntv<{ size?: 'sm' | 'lg' }>({
40
- * default: 'rounded font-medium',
41
- * size: { sm: 'px-2 py-1 text-sm', lg: 'px-4 py-2 text-lg' },
42
- * });
43
- *
44
- * const coloredButton = ntv<{ variant?: 'primary' | 'secondary' }>({
45
- * variant: { primary: 'bg-blue-500 text-white', secondary: 'bg-gray-200' },
46
- * });
47
- *
48
- * const button = composeNtv(baseButton, coloredButton);
49
- *
50
- * button({ size: 'lg', variant: 'primary' });
51
- * // => 'rounded font-medium px-4 py-2 text-lg bg-blue-500 text-white'
52
- * ```
53
- */
54
- export const composeNtv = createComposeNtv();
55
- //# sourceMappingURL=composeNtv.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"composeNtv.js","sourceRoot":"","sources":["../src/composeNtv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAUzC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAqB,EAAE;IACtD,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAE9D,MAAM,YAAY,GAAG,UAAU;QAC7B,CAAC,CAAC,aAAa;YACb,CAAC,CAAC,mBAAmB,CAAC,aAAa,CAAC;YACpC,CAAC,CAAC,OAAO;QACX,CAAC,CAAC,WAAW,CAAC;IAEhB,OAAO,SAAS,UAAU,CACxB,GAAG,GAAM;QAET,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC"}
package/dist/utils.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export declare function joinClasses(...classes: string[]): string;
2
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAExD"}
package/dist/utils.js DELETED
@@ -1,4 +0,0 @@
1
- export function joinClasses(...classes) {
2
- return classes.join(' ');
3
- }
4
- //# sourceMappingURL=utils.js.map
package/dist/utils.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,GAAG,OAAiB;IAC9C,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC"}