clases 1.1.19 → 1.1.20
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/index.cjs +6 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +39 -30
package/dist/index.cjs
CHANGED
|
@@ -10,7 +10,11 @@ var clsx__default = /*#__PURE__*/_interopDefault(clsx);
|
|
|
10
10
|
// src/index.ts
|
|
11
11
|
function createCl(plugins, options = {}) {
|
|
12
12
|
const registry = Object.assign({}, ...plugins);
|
|
13
|
-
const { baseKey = "base", conditionKey = "
|
|
13
|
+
const { baseKey = "base", conditionKey = "?", prefix: globalPrefix = "" } = options;
|
|
14
|
+
const applyGlobalPrefix = (cls) => {
|
|
15
|
+
if (!globalPrefix) return cls;
|
|
16
|
+
return `${globalPrefix}${cls}`;
|
|
17
|
+
};
|
|
14
18
|
const process = (accumulatedPath, input) => {
|
|
15
19
|
if (!input) return "";
|
|
16
20
|
if (typeof input === "string") {
|
|
@@ -19,7 +23,7 @@ function createCl(plugins, options = {}) {
|
|
|
19
23
|
return registry[part] || part;
|
|
20
24
|
}).filter(Boolean).join(":");
|
|
21
25
|
return input.split(/[,\s\n]+/).filter(Boolean).map((cls) => {
|
|
22
|
-
const finalClass =
|
|
26
|
+
const finalClass = applyGlobalPrefix(cls);
|
|
23
27
|
return resolvedPrefix ? `${resolvedPrefix}:${finalClass}` : finalClass;
|
|
24
28
|
}).join(" ");
|
|
25
29
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["twMerge","clsx"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["twMerge","clsx"],"mappings":"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","file":"index.cjs","sourcesContent":["import { twMerge } from 'tailwind-merge';\r\nimport clsx, { type ClassValue } from 'clsx';\r\n\r\n/**\r\n * Options to customize the engine behavior.\r\n */\r\nexport interface ClOptions<B extends string, C extends string> {\r\n /** The key used for static base classes. Defaults to 'base'. */\r\n baseKey?: B;\r\n /** The key used for conditional class objects. Defaults to 'if' or '?'. */\r\n conditionKey?: C;\r\n /** A global prefix to be applied to every utility class (e.g., 'tw-'). */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * Creates a customized class utility function with plugin support.\r\n * * @param plugins - An array of registry objects mapping keys to CSS prefixes.\r\n * @param options - Configuration for reserved keys and global prefixing.\r\n * @returns A function that processes nested class objects and merges them using tailwind-merge.\r\n */\r\nexport function createCl<\r\n TPlugins extends Record<string, string>[],\r\n B extends string = 'base',\r\n C extends string = '?'\r\n>(plugins: TPlugins, options: ClOptions<B, C> = {}) {\r\n /** Unified registry from all provided plugins */\r\n const registry: Record<string, string> = Object.assign({}, ...plugins);\r\n\r\n /** Extracted options with sensible defaults */\r\n const { baseKey = 'base' as B, conditionKey = '?' as C, prefix: globalPrefix = '' } = options;\r\n\r\n /**\r\n * Internal helper to apply the global prefix to a specific class.\r\n * @param cls - The raw class name string.\r\n */\r\n const applyGlobalPrefix = (cls: string): string => {\r\n if (!globalPrefix) return cls;\r\n // The global prefix is applied to the utility class itself,\r\n // while variant modifiers (hover:, md:) remain handled by the path resolver.\r\n return `${globalPrefix}${cls}`;\r\n };\r\n\r\n /**\r\n * Recursive processor that traverses the input structure to resolve paths and conditions.\r\n * @param accumulatedPath - The current breadcrumb of prefixes (e.g., \"md:hover\").\r\n * @param input - The current input level (string, array, or object).\r\n */\r\n const process = (accumulatedPath: string, input: any): string => {\r\n if (!input) return '';\r\n\r\n // 1. String Case: Resolve accumulated path and apply to each class\r\n if (typeof input === 'string') {\r\n const resolvedPrefix = accumulatedPath\r\n .split(':')\r\n .map((part) => {\r\n // Skip reserved keys in the final CSS output\r\n if (part === baseKey || part === conditionKey) return null;\r\n // Return the registered modifier or the part itself\r\n return registry[part] || part;\r\n })\r\n .filter(Boolean)\r\n .join(':');\r\n\r\n return input\r\n .split(/[,\\s\\n]+/)\r\n .filter(Boolean)\r\n .map((cls) => {\r\n const finalClass = applyGlobalPrefix(cls);\r\n return resolvedPrefix ? `${resolvedPrefix}:${finalClass}` : finalClass;\r\n })\r\n .join(' ');\r\n }\r\n\r\n // 2. Array Case: Process each element recursively\r\n if (Array.isArray(input)) {\r\n return input\r\n .map((i) => process(accumulatedPath, i))\r\n .filter(Boolean)\r\n .join(' ');\r\n }\r\n\r\n // 3. Object Case: Handle reserved keys, registered prefixes, or conditional classes\r\n if (typeof input === 'object') {\r\n return Object.entries(input)\r\n .map(([key, value]) => {\r\n if (!value) return '';\r\n\r\n const isTransparent = key === baseKey || key === conditionKey;\r\n const isRegistered = registry[key] !== undefined;\r\n\r\n if (isTransparent || isRegistered) {\r\n // If it's a reserved key or found in registry, dive deeper into the path\r\n const newPath = accumulatedPath ? `${accumulatedPath}:${key}` : key;\r\n return process(newPath, value);\r\n } else {\r\n // If the key is not in registry, treat the key as a class and value as a condition\r\n return value ? process(accumulatedPath, key) : '';\r\n }\r\n })\r\n .filter(Boolean)\r\n .join(' ');\r\n }\r\n\r\n return '';\r\n };\r\n\r\n /**\r\n * The final utility function (e.g., 'tw' or 'cl').\r\n * Processes inputs and runs them through clsx and tailwind-merge.\r\n */\r\n return (...inputs: ClassValue[]): string => {\r\n const processed = inputs.map((input) => process('', input));\r\n return twMerge(clsx(processed));\r\n };\r\n}\r\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { ClassValue } from 'clsx';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Options to customize the engine behavior.
|
|
5
|
+
*/
|
|
3
6
|
interface ClOptions<B extends string, C extends string> {
|
|
7
|
+
/** The key used for static base classes. Defaults to 'base'. */
|
|
4
8
|
baseKey?: B;
|
|
9
|
+
/** The key used for conditional class objects. Defaults to 'if' or '?'. */
|
|
5
10
|
conditionKey?: C;
|
|
11
|
+
/** A global prefix to be applied to every utility class (e.g., 'tw-'). */
|
|
6
12
|
prefix?: string;
|
|
7
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Creates a customized class utility function with plugin support.
|
|
16
|
+
* * @param plugins - An array of registry objects mapping keys to CSS prefixes.
|
|
17
|
+
* @param options - Configuration for reserved keys and global prefixing.
|
|
18
|
+
* @returns A function that processes nested class objects and merges them using tailwind-merge.
|
|
19
|
+
*/
|
|
8
20
|
declare function createCl<TPlugins extends Record<string, string>[], B extends string = 'base', C extends string = '?'>(plugins: TPlugins, options?: ClOptions<B, C>): (...inputs: ClassValue[]) => string;
|
|
9
21
|
|
|
10
22
|
export { type ClOptions, createCl };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { ClassValue } from 'clsx';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Options to customize the engine behavior.
|
|
5
|
+
*/
|
|
3
6
|
interface ClOptions<B extends string, C extends string> {
|
|
7
|
+
/** The key used for static base classes. Defaults to 'base'. */
|
|
4
8
|
baseKey?: B;
|
|
9
|
+
/** The key used for conditional class objects. Defaults to 'if' or '?'. */
|
|
5
10
|
conditionKey?: C;
|
|
11
|
+
/** A global prefix to be applied to every utility class (e.g., 'tw-'). */
|
|
6
12
|
prefix?: string;
|
|
7
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Creates a customized class utility function with plugin support.
|
|
16
|
+
* * @param plugins - An array of registry objects mapping keys to CSS prefixes.
|
|
17
|
+
* @param options - Configuration for reserved keys and global prefixing.
|
|
18
|
+
* @returns A function that processes nested class objects and merges them using tailwind-merge.
|
|
19
|
+
*/
|
|
8
20
|
declare function createCl<TPlugins extends Record<string, string>[], B extends string = 'base', C extends string = '?'>(plugins: TPlugins, options?: ClOptions<B, C>): (...inputs: ClassValue[]) => string;
|
|
9
21
|
|
|
10
22
|
export { type ClOptions, createCl };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,11 @@ import clsx from 'clsx';
|
|
|
4
4
|
// src/index.ts
|
|
5
5
|
function createCl(plugins, options = {}) {
|
|
6
6
|
const registry = Object.assign({}, ...plugins);
|
|
7
|
-
const { baseKey = "base", conditionKey = "
|
|
7
|
+
const { baseKey = "base", conditionKey = "?", prefix: globalPrefix = "" } = options;
|
|
8
|
+
const applyGlobalPrefix = (cls) => {
|
|
9
|
+
if (!globalPrefix) return cls;
|
|
10
|
+
return `${globalPrefix}${cls}`;
|
|
11
|
+
};
|
|
8
12
|
const process = (accumulatedPath, input) => {
|
|
9
13
|
if (!input) return "";
|
|
10
14
|
if (typeof input === "string") {
|
|
@@ -13,7 +17,7 @@ function createCl(plugins, options = {}) {
|
|
|
13
17
|
return registry[part] || part;
|
|
14
18
|
}).filter(Boolean).join(":");
|
|
15
19
|
return input.split(/[,\s\n]+/).filter(Boolean).map((cls) => {
|
|
16
|
-
const finalClass =
|
|
20
|
+
const finalClass = applyGlobalPrefix(cls);
|
|
17
21
|
return resolvedPrefix ? `${resolvedPrefix}:${finalClass}` : finalClass;
|
|
18
22
|
}).join(" ");
|
|
19
23
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { twMerge } from 'tailwind-merge';\r\nimport clsx, { type ClassValue } from 'clsx';\r\n\r\n/**\r\n * Options to customize the engine behavior.\r\n */\r\nexport interface ClOptions<B extends string, C extends string> {\r\n /** The key used for static base classes. Defaults to 'base'. */\r\n baseKey?: B;\r\n /** The key used for conditional class objects. Defaults to 'if' or '?'. */\r\n conditionKey?: C;\r\n /** A global prefix to be applied to every utility class (e.g., 'tw-'). */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * Creates a customized class utility function with plugin support.\r\n * * @param plugins - An array of registry objects mapping keys to CSS prefixes.\r\n * @param options - Configuration for reserved keys and global prefixing.\r\n * @returns A function that processes nested class objects and merges them using tailwind-merge.\r\n */\r\nexport function createCl<\r\n TPlugins extends Record<string, string>[],\r\n B extends string = 'base',\r\n C extends string = '?'\r\n>(plugins: TPlugins, options: ClOptions<B, C> = {}) {\r\n /** Unified registry from all provided plugins */\r\n const registry: Record<string, string> = Object.assign({}, ...plugins);\r\n\r\n /** Extracted options with sensible defaults */\r\n const { baseKey = 'base' as B, conditionKey = '?' as C, prefix: globalPrefix = '' } = options;\r\n\r\n /**\r\n * Internal helper to apply the global prefix to a specific class.\r\n * @param cls - The raw class name string.\r\n */\r\n const applyGlobalPrefix = (cls: string): string => {\r\n if (!globalPrefix) return cls;\r\n // The global prefix is applied to the utility class itself,\r\n // while variant modifiers (hover:, md:) remain handled by the path resolver.\r\n return `${globalPrefix}${cls}`;\r\n };\r\n\r\n /**\r\n * Recursive processor that traverses the input structure to resolve paths and conditions.\r\n * @param accumulatedPath - The current breadcrumb of prefixes (e.g., \"md:hover\").\r\n * @param input - The current input level (string, array, or object).\r\n */\r\n const process = (accumulatedPath: string, input: any): string => {\r\n if (!input) return '';\r\n\r\n // 1. String Case: Resolve accumulated path and apply to each class\r\n if (typeof input === 'string') {\r\n const resolvedPrefix = accumulatedPath\r\n .split(':')\r\n .map((part) => {\r\n // Skip reserved keys in the final CSS output\r\n if (part === baseKey || part === conditionKey) return null;\r\n // Return the registered modifier or the part itself\r\n return registry[part] || part;\r\n })\r\n .filter(Boolean)\r\n .join(':');\r\n\r\n return input\r\n .split(/[,\\s\\n]+/)\r\n .filter(Boolean)\r\n .map((cls) => {\r\n const finalClass = applyGlobalPrefix(cls);\r\n return resolvedPrefix ? `${resolvedPrefix}:${finalClass}` : finalClass;\r\n })\r\n .join(' ');\r\n }\r\n\r\n // 2. Array Case: Process each element recursively\r\n if (Array.isArray(input)) {\r\n return input\r\n .map((i) => process(accumulatedPath, i))\r\n .filter(Boolean)\r\n .join(' ');\r\n }\r\n\r\n // 3. Object Case: Handle reserved keys, registered prefixes, or conditional classes\r\n if (typeof input === 'object') {\r\n return Object.entries(input)\r\n .map(([key, value]) => {\r\n if (!value) return '';\r\n\r\n const isTransparent = key === baseKey || key === conditionKey;\r\n const isRegistered = registry[key] !== undefined;\r\n\r\n if (isTransparent || isRegistered) {\r\n // If it's a reserved key or found in registry, dive deeper into the path\r\n const newPath = accumulatedPath ? `${accumulatedPath}:${key}` : key;\r\n return process(newPath, value);\r\n } else {\r\n // If the key is not in registry, treat the key as a class and value as a condition\r\n return value ? process(accumulatedPath, key) : '';\r\n }\r\n })\r\n .filter(Boolean)\r\n .join(' ');\r\n }\r\n\r\n return '';\r\n };\r\n\r\n /**\r\n * The final utility function (e.g., 'tw' or 'cl').\r\n * Processes inputs and runs them through clsx and tailwind-merge.\r\n */\r\n return (...inputs: ClassValue[]): string => {\r\n const processed = inputs.map((input) => process('', input));\r\n return twMerge(clsx(processed));\r\n };\r\n}\r\n"]}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,53 +1,62 @@
|
|
|
1
1
|
import { twMerge } from 'tailwind-merge';
|
|
2
2
|
import clsx, { type ClassValue } from 'clsx';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Options to customize the engine behavior.
|
|
6
|
+
*/
|
|
5
7
|
export interface ClOptions<B extends string, C extends string> {
|
|
8
|
+
/** The key used for static base classes. Defaults to 'base'. */
|
|
6
9
|
baseKey?: B;
|
|
10
|
+
/** The key used for conditional class objects. Defaults to 'if' or '?'. */
|
|
7
11
|
conditionKey?: C;
|
|
12
|
+
/** A global prefix to be applied to every utility class (e.g., 'tw-'). */
|
|
8
13
|
prefix?: string;
|
|
9
14
|
}
|
|
10
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Creates a customized class utility function with plugin support.
|
|
18
|
+
* * @param plugins - An array of registry objects mapping keys to CSS prefixes.
|
|
19
|
+
* @param options - Configuration for reserved keys and global prefixing.
|
|
20
|
+
* @returns A function that processes nested class objects and merges them using tailwind-merge.
|
|
21
|
+
*/
|
|
11
22
|
export function createCl<
|
|
12
23
|
TPlugins extends Record<string, string>[],
|
|
13
24
|
B extends string = 'base',
|
|
14
25
|
C extends string = '?'
|
|
15
26
|
>(plugins: TPlugins, options: ClOptions<B, C> = {}) {
|
|
16
|
-
|
|
27
|
+
/** Unified registry from all provided plugins */
|
|
17
28
|
const registry: Record<string, string> = Object.assign({}, ...plugins);
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
const { baseKey = 'base' as B, conditionKey = '
|
|
30
|
+
/** Extracted options with sensible defaults */
|
|
31
|
+
const { baseKey = 'base' as B, conditionKey = '?' as C, prefix: globalPrefix = '' } = options;
|
|
21
32
|
|
|
22
33
|
/**
|
|
23
|
-
*
|
|
34
|
+
* Internal helper to apply the global prefix to a specific class.
|
|
35
|
+
* @param cls - The raw class name string.
|
|
24
36
|
*/
|
|
25
|
-
const applyGlobalPrefix = (cls: string) => {
|
|
37
|
+
const applyGlobalPrefix = (cls: string): string => {
|
|
26
38
|
if (!globalPrefix) return cls;
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.map((part) => {
|
|
31
|
-
// Solo prefijamos la clase final, no los modificadores (hover, md, etc)
|
|
32
|
-
// pero como tailwind-merge y clsx se encargan de la limpieza,
|
|
33
|
-
// aplicamos una lógica simple:
|
|
34
|
-
return part;
|
|
35
|
-
})
|
|
36
|
-
.join(':');
|
|
37
|
-
// Nota: El prefijo global de Tailwind suele aplicarse a la clase base: 'tw-bg-red'
|
|
39
|
+
// The global prefix is applied to the utility class itself,
|
|
40
|
+
// while variant modifiers (hover:, md:) remain handled by the path resolver.
|
|
41
|
+
return `${globalPrefix}${cls}`;
|
|
38
42
|
};
|
|
39
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Recursive processor that traverses the input structure to resolve paths and conditions.
|
|
46
|
+
* @param accumulatedPath - The current breadcrumb of prefixes (e.g., "md:hover").
|
|
47
|
+
* @param input - The current input level (string, array, or object).
|
|
48
|
+
*/
|
|
40
49
|
const process = (accumulatedPath: string, input: any): string => {
|
|
41
50
|
if (!input) return '';
|
|
42
51
|
|
|
43
|
-
// 1.
|
|
52
|
+
// 1. String Case: Resolve accumulated path and apply to each class
|
|
44
53
|
if (typeof input === 'string') {
|
|
45
54
|
const resolvedPrefix = accumulatedPath
|
|
46
55
|
.split(':')
|
|
47
56
|
.map((part) => {
|
|
48
|
-
//
|
|
57
|
+
// Skip reserved keys in the final CSS output
|
|
49
58
|
if (part === baseKey || part === conditionKey) return null;
|
|
50
|
-
//
|
|
59
|
+
// Return the registered modifier or the part itself
|
|
51
60
|
return registry[part] || part;
|
|
52
61
|
})
|
|
53
62
|
.filter(Boolean)
|
|
@@ -57,15 +66,13 @@ export function createCl<
|
|
|
57
66
|
.split(/[,\s\n]+/)
|
|
58
67
|
.filter(Boolean)
|
|
59
68
|
.map((cls) => {
|
|
60
|
-
|
|
61
|
-
const finalClass = globalPrefix ? `${globalPrefix}${cls}` : cls;
|
|
62
|
-
// Aplicamos el prefijo acumulado (hover, md, etc)
|
|
69
|
+
const finalClass = applyGlobalPrefix(cls);
|
|
63
70
|
return resolvedPrefix ? `${resolvedPrefix}:${finalClass}` : finalClass;
|
|
64
71
|
})
|
|
65
72
|
.join(' ');
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
// 2.
|
|
75
|
+
// 2. Array Case: Process each element recursively
|
|
69
76
|
if (Array.isArray(input)) {
|
|
70
77
|
return input
|
|
71
78
|
.map((i) => process(accumulatedPath, i))
|
|
@@ -73,7 +80,7 @@ export function createCl<
|
|
|
73
80
|
.join(' ');
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
// 3.
|
|
83
|
+
// 3. Object Case: Handle reserved keys, registered prefixes, or conditional classes
|
|
77
84
|
if (typeof input === 'object') {
|
|
78
85
|
return Object.entries(input)
|
|
79
86
|
.map(([key, value]) => {
|
|
@@ -83,12 +90,11 @@ export function createCl<
|
|
|
83
90
|
const isRegistered = registry[key] !== undefined;
|
|
84
91
|
|
|
85
92
|
if (isTransparent || isRegistered) {
|
|
86
|
-
//
|
|
93
|
+
// If it's a reserved key or found in registry, dive deeper into the path
|
|
87
94
|
const newPath = accumulatedPath ? `${accumulatedPath}:${key}` : key;
|
|
88
95
|
return process(newPath, value);
|
|
89
96
|
} else {
|
|
90
|
-
//
|
|
91
|
-
// (Aquí value actúa como condición booleana para la llave)
|
|
97
|
+
// If the key is not in registry, treat the key as a class and value as a condition
|
|
92
98
|
return value ? process(accumulatedPath, key) : '';
|
|
93
99
|
}
|
|
94
100
|
})
|
|
@@ -99,9 +105,12 @@ export function createCl<
|
|
|
99
105
|
return '';
|
|
100
106
|
};
|
|
101
107
|
|
|
102
|
-
|
|
108
|
+
/**
|
|
109
|
+
* The final utility function (e.g., 'tw' or 'cl').
|
|
110
|
+
* Processes inputs and runs them through clsx and tailwind-merge.
|
|
111
|
+
*/
|
|
112
|
+
return (...inputs: ClassValue[]): string => {
|
|
103
113
|
const processed = inputs.map((input) => process('', input));
|
|
104
|
-
// twMerge se encarga de que 'bg-red-500 bg-blue-500' resulte en 'bg-blue-500'
|
|
105
114
|
return twMerge(clsx(processed));
|
|
106
115
|
};
|
|
107
116
|
}
|