clases 1.1.5 → 1.1.6
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 +7 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -3
- package/dist/index.d.ts +0 -3
- package/dist/index.js +7 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +12 -45
- package/src/test/cn.test.ts +45 -138
package/dist/index.cjs
CHANGED
|
@@ -17,38 +17,22 @@ function createCl(...plugins) {
|
|
|
17
17
|
}
|
|
18
18
|
if (typeof value === "object") {
|
|
19
19
|
return Object.entries(value).map(([nestedKey, nestedValue]) => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
nextKey
|
|
24
|
-
} else if (isRegistered) {
|
|
25
|
-
nextKey = `${key}:${nestedKey}`;
|
|
26
|
-
} else {
|
|
27
|
-
nextKey = key;
|
|
20
|
+
const isPrefix = registry[nestedKey] !== void 0;
|
|
21
|
+
if (isPrefix) {
|
|
22
|
+
const nextKey = key ? `${key}:${nestedKey}` : nestedKey;
|
|
23
|
+
return process(nextKey, nestedValue);
|
|
28
24
|
}
|
|
29
|
-
return process(
|
|
25
|
+
return nestedValue ? process(key, nestedKey) : "";
|
|
30
26
|
}).join(" ");
|
|
31
27
|
}
|
|
32
|
-
const resolvedPrefix = key.split(":").map((part) =>
|
|
33
|
-
if (part === "base") return null;
|
|
34
|
-
return registry[part] || null;
|
|
35
|
-
}).filter(Boolean).join(":");
|
|
28
|
+
const resolvedPrefix = key.split(":").map((part) => registry[part] || null).filter(Boolean).join(":");
|
|
36
29
|
if (typeof value === "string") {
|
|
37
30
|
return value.split(/[,\s\n]+/).filter(Boolean).map((cls) => !resolvedPrefix ? cls : `${resolvedPrefix}:${cls}`).join(" ");
|
|
38
31
|
}
|
|
39
32
|
return "";
|
|
40
33
|
};
|
|
41
34
|
return (...inputs) => {
|
|
42
|
-
const processed = inputs.map((input) =>
|
|
43
|
-
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
44
|
-
return Object.entries(input).map(([k, v]) => {
|
|
45
|
-
if (v === true) return k;
|
|
46
|
-
if (registry[k] || k === "base") return process(k, v);
|
|
47
|
-
return process("base", v);
|
|
48
|
-
}).join(" ");
|
|
49
|
-
}
|
|
50
|
-
return input;
|
|
51
|
-
});
|
|
35
|
+
const processed = inputs.map((input) => process("", input));
|
|
52
36
|
return tailwindMerge.twMerge(clsx__default.default(processed));
|
|
53
37
|
};
|
|
54
38
|
}
|
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":";;;;;;;;;;AAGO,SAAS,YAAuD,OAAA,EAAmB;AACtF,EAAA,MAAM,WAAmC,MAAA,CAAO,MAAA,CAAO,EAAC,EAAG,GAAG,OAAO,CAAA;AAErE,EAAA,MAAM,OAAA,GAAU,CAAC,GAAA,EAAa,KAAA,KAAuB;AACjD,IAAA,IAAI,CAAC,OAAO,OAAO,EAAA;AAGnB,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtB,MAAA,OAAO,KAAA,CACF,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,GAAA,EAAK,CAAC,CAAC,CAAA,CAC1B,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAAA,IACjB;AAGA,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC3B,MAAA,OAAO,MAAA,CAAO,QAAQ,KAAK,CAAA,CACtB,IAAI,CAAC,CAAC,SAAA,EAAW,WAAW,CAAA,KAAM;AAC/B,QAAA,MAAM,QAAA,GAAW,QAAA,CAAS,SAAS,CAAA,KAAM,MAAA;AAEzC,QAAA,IAAI,QAAA,EAAU;AACV,UAAA,MAAM,UAAU,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GAAK,SAAA;AAC9C,UAAA,OAAO,OAAA,CAAQ,SAAS,WAAW,CAAA;AAAA,QACvC;AAGA,QAAA,OAAO,WAAA,GAAc,OAAA,CAAQ,GAAA,EAAK,SAAS,CAAA,GAAI,EAAA;AAAA,MACnD,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,IACjB;AAGA,IAAA,MAAM,iBAAiB,GAAA,CAClB,KAAA,CAAM,GAAG,CAAA,CACT,IAAI,CAAC,IAAA,KAAS,QAAA,CAAS,IAAI,KAAK,IAAI,CAAA,CACpC,OAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAEb,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC3B,MAAA,OAAO,KAAA,CACF,MAAM,UAAU,CAAA,CAChB,OAAO,OAAO,CAAA,CACd,IAAI,CAAC,GAAA,KAAS,CAAC,cAAA,GAAiB,GAAA,GAAM,GAAG,cAAc,CAAA,CAAA,EAAI,GAAG,CAAA,CAAG,CAAA,CACjE,KAAK,GAAG,CAAA;AAAA,IACjB;AACA,IAAA,OAAO,EAAA;AAAA,EACX,CAAA;AAEA,EAAA,OAAO,IAAI,MAAA,KAAyB;AAEhC,IAAA,MAAM,SAAA,GAAY,OAAO,GAAA,CAAI,CAAC,UAAU,OAAA,CAAQ,EAAA,EAAI,KAAK,CAAC,CAAA;AAC1D,IAAA,OAAOA,qBAAA,CAAQC,qBAAA,CAAK,SAAS,CAAC,CAAA;AAAA,EAClC,CAAA;AACJ","file":"index.cjs","sourcesContent":["import { twMerge } from 'tailwind-merge';\r\nimport clsx, { type ClassValue } from 'clsx';\r\n\r\nexport function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {\r\n const registry: Record<string, string> = Object.assign({}, ...plugins);\r\n\r\n const process = (key: string, value: any): string => {\r\n if (!value) return '';\r\n\r\n // 1. Soporte Multilínea (Arrays)\r\n if (Array.isArray(value)) {\r\n return value\r\n .map((v) => process(key, v))\r\n .filter(Boolean)\r\n .join(' ');\r\n }\r\n\r\n // 2. Objetos de Prefijos\r\n if (typeof value === 'object') {\r\n return Object.entries(value)\r\n .map(([nestedKey, nestedValue]) => {\r\n const isPrefix = registry[nestedKey] !== undefined;\r\n\r\n if (isPrefix) {\r\n const nextKey = key ? `${key}:${nestedKey}` : nestedKey;\r\n return process(nextKey, nestedValue);\r\n }\r\n\r\n // Lógica estándar: si no es prefijo, es una clase condicional\r\n return nestedValue ? process(key, nestedKey) : '';\r\n })\r\n .join(' ');\r\n }\r\n\r\n // 3. Resolución y Aplicación\r\n const resolvedPrefix = key\r\n .split(':')\r\n .map((part) => registry[part] || null)\r\n .filter(Boolean)\r\n .join(':');\r\n\r\n if (typeof value === 'string') {\r\n return value\r\n .split(/[,\\s\\n]+/)\r\n .filter(Boolean)\r\n .map((cls) => (!resolvedPrefix ? cls : `${resolvedPrefix}:${cls}`))\r\n .join(' ');\r\n }\r\n return '';\r\n };\r\n\r\n return (...inputs: ClassValue[]) => {\r\n // Procesamos uno a uno para capturar objetos de prefijos antes de que clsx los aplane\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,8 +1,5 @@
|
|
|
1
1
|
import { ClassValue } from 'clsx';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Motor de prefijos con soporte para plugins, lógica transparente y limpieza via twMerge.
|
|
5
|
-
*/
|
|
6
3
|
declare function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins): (...inputs: ClassValue[]) => string;
|
|
7
4
|
|
|
8
5
|
export { createCl };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { ClassValue } from 'clsx';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Motor de prefijos con soporte para plugins, lógica transparente y limpieza via twMerge.
|
|
5
|
-
*/
|
|
6
3
|
declare function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins): (...inputs: ClassValue[]) => string;
|
|
7
4
|
|
|
8
5
|
export { createCl };
|
package/dist/index.js
CHANGED
|
@@ -11,38 +11,22 @@ function createCl(...plugins) {
|
|
|
11
11
|
}
|
|
12
12
|
if (typeof value === "object") {
|
|
13
13
|
return Object.entries(value).map(([nestedKey, nestedValue]) => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
nextKey
|
|
18
|
-
} else if (isRegistered) {
|
|
19
|
-
nextKey = `${key}:${nestedKey}`;
|
|
20
|
-
} else {
|
|
21
|
-
nextKey = key;
|
|
14
|
+
const isPrefix = registry[nestedKey] !== void 0;
|
|
15
|
+
if (isPrefix) {
|
|
16
|
+
const nextKey = key ? `${key}:${nestedKey}` : nestedKey;
|
|
17
|
+
return process(nextKey, nestedValue);
|
|
22
18
|
}
|
|
23
|
-
return process(
|
|
19
|
+
return nestedValue ? process(key, nestedKey) : "";
|
|
24
20
|
}).join(" ");
|
|
25
21
|
}
|
|
26
|
-
const resolvedPrefix = key.split(":").map((part) =>
|
|
27
|
-
if (part === "base") return null;
|
|
28
|
-
return registry[part] || null;
|
|
29
|
-
}).filter(Boolean).join(":");
|
|
22
|
+
const resolvedPrefix = key.split(":").map((part) => registry[part] || null).filter(Boolean).join(":");
|
|
30
23
|
if (typeof value === "string") {
|
|
31
24
|
return value.split(/[,\s\n]+/).filter(Boolean).map((cls) => !resolvedPrefix ? cls : `${resolvedPrefix}:${cls}`).join(" ");
|
|
32
25
|
}
|
|
33
26
|
return "";
|
|
34
27
|
};
|
|
35
28
|
return (...inputs) => {
|
|
36
|
-
const processed = inputs.map((input) =>
|
|
37
|
-
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
38
|
-
return Object.entries(input).map(([k, v]) => {
|
|
39
|
-
if (v === true) return k;
|
|
40
|
-
if (registry[k] || k === "base") return process(k, v);
|
|
41
|
-
return process("base", v);
|
|
42
|
-
}).join(" ");
|
|
43
|
-
}
|
|
44
|
-
return input;
|
|
45
|
-
});
|
|
29
|
+
const processed = inputs.map((input) => process("", input));
|
|
46
30
|
return twMerge(clsx(processed));
|
|
47
31
|
};
|
|
48
32
|
}
|
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":";;;;AAGO,SAAS,YAAuD,OAAA,EAAmB;AACtF,EAAA,MAAM,WAAmC,MAAA,CAAO,MAAA,CAAO,EAAC,EAAG,GAAG,OAAO,CAAA;AAErE,EAAA,MAAM,OAAA,GAAU,CAAC,GAAA,EAAa,KAAA,KAAuB;AACjD,IAAA,IAAI,CAAC,OAAO,OAAO,EAAA;AAGnB,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtB,MAAA,OAAO,KAAA,CACF,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,GAAA,EAAK,CAAC,CAAC,CAAA,CAC1B,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAAA,IACjB;AAGA,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC3B,MAAA,OAAO,MAAA,CAAO,QAAQ,KAAK,CAAA,CACtB,IAAI,CAAC,CAAC,SAAA,EAAW,WAAW,CAAA,KAAM;AAC/B,QAAA,MAAM,QAAA,GAAW,QAAA,CAAS,SAAS,CAAA,KAAM,MAAA;AAEzC,QAAA,IAAI,QAAA,EAAU;AACV,UAAA,MAAM,UAAU,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GAAK,SAAA;AAC9C,UAAA,OAAO,OAAA,CAAQ,SAAS,WAAW,CAAA;AAAA,QACvC;AAGA,QAAA,OAAO,WAAA,GAAc,OAAA,CAAQ,GAAA,EAAK,SAAS,CAAA,GAAI,EAAA;AAAA,MACnD,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,IACjB;AAGA,IAAA,MAAM,iBAAiB,GAAA,CAClB,KAAA,CAAM,GAAG,CAAA,CACT,IAAI,CAAC,IAAA,KAAS,QAAA,CAAS,IAAI,KAAK,IAAI,CAAA,CACpC,OAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAEb,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC3B,MAAA,OAAO,KAAA,CACF,MAAM,UAAU,CAAA,CAChB,OAAO,OAAO,CAAA,CACd,IAAI,CAAC,GAAA,KAAS,CAAC,cAAA,GAAiB,GAAA,GAAM,GAAG,cAAc,CAAA,CAAA,EAAI,GAAG,CAAA,CAAG,CAAA,CACjE,KAAK,GAAG,CAAA;AAAA,IACjB;AACA,IAAA,OAAO,EAAA;AAAA,EACX,CAAA;AAEA,EAAA,OAAO,IAAI,MAAA,KAAyB;AAEhC,IAAA,MAAM,SAAA,GAAY,OAAO,GAAA,CAAI,CAAC,UAAU,OAAA,CAAQ,EAAA,EAAI,KAAK,CAAC,CAAA;AAC1D,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,EAClC,CAAA;AACJ","file":"index.js","sourcesContent":["import { twMerge } from 'tailwind-merge';\r\nimport clsx, { type ClassValue } from 'clsx';\r\n\r\nexport function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {\r\n const registry: Record<string, string> = Object.assign({}, ...plugins);\r\n\r\n const process = (key: string, value: any): string => {\r\n if (!value) return '';\r\n\r\n // 1. Soporte Multilínea (Arrays)\r\n if (Array.isArray(value)) {\r\n return value\r\n .map((v) => process(key, v))\r\n .filter(Boolean)\r\n .join(' ');\r\n }\r\n\r\n // 2. Objetos de Prefijos\r\n if (typeof value === 'object') {\r\n return Object.entries(value)\r\n .map(([nestedKey, nestedValue]) => {\r\n const isPrefix = registry[nestedKey] !== undefined;\r\n\r\n if (isPrefix) {\r\n const nextKey = key ? `${key}:${nestedKey}` : nestedKey;\r\n return process(nextKey, nestedValue);\r\n }\r\n\r\n // Lógica estándar: si no es prefijo, es una clase condicional\r\n return nestedValue ? process(key, nestedKey) : '';\r\n })\r\n .join(' ');\r\n }\r\n\r\n // 3. Resolución y Aplicación\r\n const resolvedPrefix = key\r\n .split(':')\r\n .map((part) => registry[part] || null)\r\n .filter(Boolean)\r\n .join(':');\r\n\r\n if (typeof value === 'string') {\r\n return value\r\n .split(/[,\\s\\n]+/)\r\n .filter(Boolean)\r\n .map((cls) => (!resolvedPrefix ? cls : `${resolvedPrefix}:${cls}`))\r\n .join(' ');\r\n }\r\n return '';\r\n };\r\n\r\n return (...inputs: ClassValue[]) => {\r\n // Procesamos uno a uno para capturar objetos de prefijos antes de que clsx los aplane\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,16 +1,13 @@
|
|
|
1
1
|
import { twMerge } from 'tailwind-merge';
|
|
2
2
|
import clsx, { type ClassValue } from 'clsx';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Motor de prefijos con soporte para plugins, lógica transparente y limpieza via twMerge.
|
|
6
|
-
*/
|
|
7
4
|
export function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {
|
|
8
5
|
const registry: Record<string, string> = Object.assign({}, ...plugins);
|
|
9
6
|
|
|
10
7
|
const process = (key: string, value: any): string => {
|
|
11
8
|
if (!value) return '';
|
|
12
9
|
|
|
13
|
-
// 1.
|
|
10
|
+
// 1. Soporte Multilínea (Arrays)
|
|
14
11
|
if (Array.isArray(value)) {
|
|
15
12
|
return value
|
|
16
13
|
.map((v) => process(key, v))
|
|
@@ -18,40 +15,30 @@ export function createCl<TPlugins extends Record<string, string>[]>(...plugins:
|
|
|
18
15
|
.join(' ');
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
// 2.
|
|
18
|
+
// 2. Objetos de Prefijos
|
|
22
19
|
if (typeof value === 'object') {
|
|
23
20
|
return Object.entries(value)
|
|
24
21
|
.map(([nestedKey, nestedValue]) => {
|
|
25
|
-
const
|
|
22
|
+
const isPrefix = registry[nestedKey] !== undefined;
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
nextKey = nestedKey;
|
|
31
|
-
} else if (isRegistered) {
|
|
32
|
-
// Si el hijo es un prefijo registrado, se concatena (ej: md:hover)
|
|
33
|
-
nextKey = `${key}:${nestedKey}`;
|
|
34
|
-
} else {
|
|
35
|
-
// Si el hijo es lógica transparente (ej: variants), heredamos el prefijo padre
|
|
36
|
-
nextKey = key;
|
|
24
|
+
if (isPrefix) {
|
|
25
|
+
const nextKey = key ? `${key}:${nestedKey}` : nestedKey;
|
|
26
|
+
return process(nextKey, nestedValue);
|
|
37
27
|
}
|
|
38
28
|
|
|
39
|
-
|
|
29
|
+
// Lógica estándar: si no es prefijo, es una clase condicional
|
|
30
|
+
return nestedValue ? process(key, nestedKey) : '';
|
|
40
31
|
})
|
|
41
32
|
.join(' ');
|
|
42
33
|
}
|
|
43
34
|
|
|
44
|
-
// 3. Resolución
|
|
35
|
+
// 3. Resolución y Aplicación
|
|
45
36
|
const resolvedPrefix = key
|
|
46
37
|
.split(':')
|
|
47
|
-
.map((part) =>
|
|
48
|
-
if (part === 'base') return null; // 'base' nunca se imprime
|
|
49
|
-
return registry[part] || null; // Solo lo registrado sobrevive
|
|
50
|
-
})
|
|
38
|
+
.map((part) => registry[part] || null)
|
|
51
39
|
.filter(Boolean)
|
|
52
40
|
.join(':');
|
|
53
41
|
|
|
54
|
-
// 4. Aplicación de Clases
|
|
55
42
|
if (typeof value === 'string') {
|
|
56
43
|
return value
|
|
57
44
|
.split(/[,\s\n]+/)
|
|
@@ -62,29 +49,9 @@ export function createCl<TPlugins extends Record<string, string>[]>(...plugins:
|
|
|
62
49
|
return '';
|
|
63
50
|
};
|
|
64
51
|
|
|
65
|
-
/**
|
|
66
|
-
* Función resultante (tw)
|
|
67
|
-
*/
|
|
68
52
|
return (...inputs: ClassValue[]) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return Object.entries(input)
|
|
72
|
-
.map(([k, v]) => {
|
|
73
|
-
// Soporte para booleanos nativos de clsx: { 'clase': true }
|
|
74
|
-
if (v === true) return k;
|
|
75
|
-
|
|
76
|
-
// Si la llave es un prefijo registrado (md, hover, ui), empezamos proceso
|
|
77
|
-
if (registry[k] || k === 'base') return process(k, v);
|
|
78
|
-
|
|
79
|
-
// Si no es prefijo (ej: variantes dinámicas), procesamos el interior como base
|
|
80
|
-
return process('base', v);
|
|
81
|
-
})
|
|
82
|
-
.join(' ');
|
|
83
|
-
}
|
|
84
|
-
return input;
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Resolvemos con clsx y limpiamos conflictos con twMerge
|
|
53
|
+
// Procesamos uno a uno para capturar objetos de prefijos antes de que clsx los aplane
|
|
54
|
+
const processed = inputs.map((input) => process('', input));
|
|
88
55
|
return twMerge(clsx(processed));
|
|
89
56
|
};
|
|
90
57
|
}
|
package/src/test/cn.test.ts
CHANGED
|
@@ -1,166 +1,73 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import { createCl } from '../index';
|
|
3
3
|
|
|
4
|
-
describe('cl -
|
|
5
|
-
//
|
|
6
|
-
const cl = createCl(
|
|
7
|
-
{ md: 'md', hover: 'hover', focus: 'focus' }, // Tailwind
|
|
8
|
-
{ ui: 'prefix', btn: 'button' } // Plugins
|
|
9
|
-
);
|
|
4
|
+
describe('cl - Prefix Engine (Scope: Prefixes + clsx + twMerge)', () => {
|
|
5
|
+
// Setup con prefijos de Tailwind y un alias personalizado
|
|
6
|
+
const cl = createCl({ md: 'md', hover: 'hover', dark: 'dark' }, { ui: 'prefix' });
|
|
10
7
|
|
|
11
|
-
it('Nivel 1:
|
|
12
|
-
expect(cl('p-4', ['m-2', 'flex'])).toBe('p-4 m-2 flex');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('Nivel 2: Objetos Simples y Registro', () => {
|
|
16
|
-
// 'md' está registrado, 'p-4' es el valor
|
|
17
|
-
expect(cl({ md: 'p-4' })).toBe('md:p-4');
|
|
18
|
-
// 'ui' se mapea a 'prefix'
|
|
19
|
-
expect(cl({ ui: 'p-4' })).toBe('prefix:p-4');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('Nivel 3: Transparencia Automática (Sintaxis Hermosa)', () => {
|
|
23
|
-
// 'custom' NO está registrado -> Invisible
|
|
24
|
-
// 'inner' NO está registrado -> Invisible
|
|
8
|
+
it('Nivel 1: Prefijos Básicos y Mapping', () => {
|
|
25
9
|
const result = cl({
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
10
|
+
md: 'p-4 m-2',
|
|
11
|
+
ui: 'bg-red-500'
|
|
29
12
|
});
|
|
30
|
-
expect(result).toBe('
|
|
13
|
+
expect(result).toBe('md:p-4 md:m-2 prefix:bg-red-500');
|
|
31
14
|
});
|
|
32
15
|
|
|
33
|
-
it('Nivel
|
|
16
|
+
it('Nivel 2: Soporte Multilínea (Arrays)', () => {
|
|
34
17
|
const result = cl({
|
|
35
|
-
md:
|
|
36
|
-
// Registrado
|
|
37
|
-
card: {
|
|
38
|
-
// Lógico (Transparente)
|
|
39
|
-
hover: {
|
|
40
|
-
// Registrado
|
|
41
|
-
base: 'shadow-lg'
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
18
|
+
md: ['p-4', 'flex items-center', 'text-white']
|
|
45
19
|
});
|
|
46
|
-
//
|
|
47
|
-
expect(result).toBe('md:
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('Nivel 5: El "Inception" (Lógica anidada, condicionales y plugins)', () => {
|
|
51
|
-
const isEnabled = true;
|
|
52
|
-
const variant = 'primary';
|
|
53
|
-
const theme = 'dark';
|
|
54
|
-
|
|
55
|
-
const result = cl({
|
|
56
|
-
md: {
|
|
57
|
-
[isEnabled ? 'active' : 'idle']: {
|
|
58
|
-
ui: {
|
|
59
|
-
[`[${variant}]`]: {
|
|
60
|
-
base: 'bg-blue-500',
|
|
61
|
-
// Seleccionamos el valor ANTES de que el motor lo aplane
|
|
62
|
-
theme: theme === 'dark' ? 'text-white' : 'text-black'
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
expect(result).toContain('md:prefix:bg-blue-500');
|
|
70
|
-
expect(result).toContain('md:prefix:text-white'); // Ahora sí pasará
|
|
71
|
-
expect(result).not.toContain('md:prefix:text-black');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('Nivel 6: Resolución de Conflictos Final (twMerge)', () => {
|
|
75
|
-
// En este nivel probamos que tras toda la recursión, twMerge limpie el resultado
|
|
76
|
-
const result = cl({ md: 'p-4' }, { md: { logic: 'p-8' } });
|
|
77
|
-
// md:p-8 debe ganar a md:p-4
|
|
78
|
-
expect(result).toBe('md:p-8');
|
|
20
|
+
// El prefijo se debe aplicar a cada elemento del array
|
|
21
|
+
expect(result).toBe('md:p-4 md:flex md:items-center md:text-white');
|
|
79
22
|
});
|
|
80
23
|
|
|
81
|
-
it('Nivel
|
|
82
|
-
const
|
|
83
|
-
const
|
|
24
|
+
it('Nivel 3: Lógica Estándar (clsx style)', () => {
|
|
25
|
+
const isEnabled = true;
|
|
26
|
+
const isDark = false;
|
|
84
27
|
|
|
85
28
|
const result = cl({
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// 'effects' no está registrado -> Desaparece
|
|
93
|
-
effects: {
|
|
94
|
-
scale: 'elevate-hover',
|
|
95
|
-
dim: 'hover:opacity-80'
|
|
96
|
-
}[onHover]
|
|
29
|
+
// Llaves que NO están en el registro se tratan como clases condicionales
|
|
30
|
+
'opacity-100': isEnabled,
|
|
31
|
+
'opacity-0': isDark,
|
|
32
|
+
// Mezcla con prefijos
|
|
33
|
+
hover: 'bg-blue-500'
|
|
97
34
|
});
|
|
98
35
|
|
|
99
|
-
|
|
100
|
-
expect(result).
|
|
101
|
-
expect(result).not.toContain('
|
|
102
|
-
expect(result).not.toContain('effects:');
|
|
36
|
+
expect(result).toContain('opacity-100');
|
|
37
|
+
expect(result).toContain('hover:bg-blue-500');
|
|
38
|
+
expect(result).not.toContain('opacity-0');
|
|
103
39
|
});
|
|
104
40
|
|
|
105
|
-
it('Nivel
|
|
106
|
-
const variant = 'secondary';
|
|
107
|
-
const isDark = true;
|
|
108
|
-
|
|
41
|
+
it('Nivel 4: Anidación de Prefijos', () => {
|
|
109
42
|
const result = cl({
|
|
110
43
|
md: {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
base: 'p-4',
|
|
115
|
-
// Prefijo registrado dentro de un selector dinámico
|
|
116
|
-
hover: 'shadow-xl'
|
|
117
|
-
}
|
|
118
|
-
}[variant]
|
|
44
|
+
hover: {
|
|
45
|
+
dark: 'bg-black text-white'
|
|
46
|
+
}
|
|
119
47
|
}
|
|
120
48
|
});
|
|
121
|
-
|
|
122
|
-
// 'md' y 'hover' se mantienen, 'container' y 'secondary' desaparecen
|
|
123
|
-
expect(result).toBe('md:p-4 md:hover:shadow-xl');
|
|
49
|
+
expect(result).toBe('md:hover:dark:bg-black md:hover:dark:text-white');
|
|
124
50
|
});
|
|
125
51
|
|
|
126
|
-
it('Nivel
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
'py-2 px-4 rounded-lg flex clickable',
|
|
133
|
-
// 2. Objeto de configuración con lógica dinámica
|
|
134
|
-
{
|
|
135
|
-
variants: {
|
|
136
|
-
primary: 'bg-action text-white',
|
|
137
|
-
secondary: 'bg-neutral-50 text-text-muted border-2',
|
|
138
|
-
danger: 'bg-red-400 text-white'
|
|
139
|
-
}[variant],
|
|
140
|
-
|
|
141
|
-
effects: {
|
|
142
|
-
scale: 'elevate-hover',
|
|
143
|
-
dim: 'hover:opacity-80 transition-opacity',
|
|
144
|
-
color: {
|
|
145
|
-
primary: 'hover:bg-action-hover',
|
|
146
|
-
secondary: 'hover:bg-neutral-200'
|
|
147
|
-
}[variant]
|
|
148
|
-
}[onHover]
|
|
149
|
-
}
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
// Verificación de limpieza
|
|
153
|
-
expect(result).not.toContain('variants:');
|
|
154
|
-
expect(result).not.toContain('effects:');
|
|
52
|
+
it('Nivel 5: Resolución de Conflictos (twMerge)', () => {
|
|
53
|
+
// twMerge debe hacer que la última clase gane si hay colisión
|
|
54
|
+
const result = cl('p-2', { md: 'p-4' }, { md: 'p-8' });
|
|
55
|
+
// md:p-8 debe ganar a md:p-4, y p-2 se mantiene por ser base
|
|
56
|
+
expect(result).toBe('p-2 md:p-8');
|
|
57
|
+
});
|
|
155
58
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
59
|
+
it('Nivel 6: Manejo de Strings Complejos (Comas y saltos de línea)', () => {
|
|
60
|
+
const result = cl({
|
|
61
|
+
md: 'text-xl, leading-tight, \n font-bold'
|
|
62
|
+
});
|
|
63
|
+
expect(result).toBe('md:text-xl md:leading-tight md:font-bold');
|
|
64
|
+
});
|
|
160
65
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
66
|
+
it('Nivel 7: Integración con Variables/Ternarios Externos', () => {
|
|
67
|
+
const variant = 'primary';
|
|
68
|
+
const result = cl('base-btn', variant === 'primary' ? 'bg-blue-500' : 'bg-gray-500', {
|
|
69
|
+
md: ['px-4', variant === 'primary' ? 'text-white' : 'text-black']
|
|
70
|
+
});
|
|
71
|
+
expect(result).toBe('base-btn bg-blue-500 md:px-4 md:text-white');
|
|
165
72
|
});
|
|
166
73
|
});
|