clases 1.1.4 → 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 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +7 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +15 -20
- package/src/test/cn.test.ts +45 -138
package/dist/index.cjs
CHANGED
|
@@ -17,9 +17,12 @@ function createCl(...plugins) {
|
|
|
17
17
|
}
|
|
18
18
|
if (typeof value === "object") {
|
|
19
19
|
return Object.entries(value).map(([nestedKey, nestedValue]) => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const isPrefix = registry[nestedKey] !== void 0;
|
|
21
|
+
if (isPrefix) {
|
|
22
|
+
const nextKey = key ? `${key}:${nestedKey}` : nestedKey;
|
|
23
|
+
return process(nextKey, nestedValue);
|
|
24
|
+
}
|
|
25
|
+
return nestedValue ? process(key, nestedKey) : "";
|
|
23
26
|
}).join(" ");
|
|
24
27
|
}
|
|
25
28
|
const resolvedPrefix = key.split(":").map((part) => registry[part] || null).filter(Boolean).join(":");
|
|
@@ -29,15 +32,7 @@ function createCl(...plugins) {
|
|
|
29
32
|
return "";
|
|
30
33
|
};
|
|
31
34
|
return (...inputs) => {
|
|
32
|
-
const processed = inputs.map((input) =>
|
|
33
|
-
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
34
|
-
return Object.entries(input).map(([k, v]) => {
|
|
35
|
-
if (v === true) return k;
|
|
36
|
-
return process(registry[k] ? k : "", v);
|
|
37
|
-
}).join(" ");
|
|
38
|
-
}
|
|
39
|
-
return input;
|
|
40
|
-
});
|
|
35
|
+
const processed = inputs.map((input) => process("", input));
|
|
41
36
|
return tailwindMerge.twMerge(clsx__default.default(processed));
|
|
42
37
|
};
|
|
43
38
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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,3 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
|
|
3
|
+
declare function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins): (...inputs: ClassValue[]) => string;
|
|
2
4
|
|
|
3
5
|
export { createCl };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
|
|
3
|
+
declare function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins): (...inputs: ClassValue[]) => string;
|
|
2
4
|
|
|
3
5
|
export { createCl };
|
package/dist/index.js
CHANGED
|
@@ -11,9 +11,12 @@ function createCl(...plugins) {
|
|
|
11
11
|
}
|
|
12
12
|
if (typeof value === "object") {
|
|
13
13
|
return Object.entries(value).map(([nestedKey, nestedValue]) => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const isPrefix = registry[nestedKey] !== void 0;
|
|
15
|
+
if (isPrefix) {
|
|
16
|
+
const nextKey = key ? `${key}:${nestedKey}` : nestedKey;
|
|
17
|
+
return process(nextKey, nestedValue);
|
|
18
|
+
}
|
|
19
|
+
return nestedValue ? process(key, nestedKey) : "";
|
|
17
20
|
}).join(" ");
|
|
18
21
|
}
|
|
19
22
|
const resolvedPrefix = key.split(":").map((part) => registry[part] || null).filter(Boolean).join(":");
|
|
@@ -23,15 +26,7 @@ function createCl(...plugins) {
|
|
|
23
26
|
return "";
|
|
24
27
|
};
|
|
25
28
|
return (...inputs) => {
|
|
26
|
-
const processed = inputs.map((input) =>
|
|
27
|
-
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
28
|
-
return Object.entries(input).map(([k, v]) => {
|
|
29
|
-
if (v === true) return k;
|
|
30
|
-
return process(registry[k] ? k : "", v);
|
|
31
|
-
}).join(" ");
|
|
32
|
-
}
|
|
33
|
-
return input;
|
|
34
|
-
});
|
|
29
|
+
const processed = inputs.map((input) => process("", input));
|
|
35
30
|
return twMerge(clsx(processed));
|
|
36
31
|
};
|
|
37
32
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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,5 +1,5 @@
|
|
|
1
1
|
import { twMerge } from 'tailwind-merge';
|
|
2
|
-
import clsx from 'clsx';
|
|
2
|
+
import clsx, { type ClassValue } from 'clsx';
|
|
3
3
|
|
|
4
4
|
export function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {
|
|
5
5
|
const registry: Record<string, string> = Object.assign({}, ...plugins);
|
|
@@ -7,6 +7,7 @@ export function createCl<TPlugins extends Record<string, string>[]>(...plugins:
|
|
|
7
7
|
const process = (key: string, value: any): string => {
|
|
8
8
|
if (!value) return '';
|
|
9
9
|
|
|
10
|
+
// 1. Soporte Multilínea (Arrays)
|
|
10
11
|
if (Array.isArray(value)) {
|
|
11
12
|
return value
|
|
12
13
|
.map((v) => process(key, v))
|
|
@@ -14,20 +15,24 @@ export function createCl<TPlugins extends Record<string, string>[]>(...plugins:
|
|
|
14
15
|
.join(' ');
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
// 2. Objetos de Prefijos
|
|
17
19
|
if (typeof value === 'object') {
|
|
18
20
|
return Object.entries(value)
|
|
19
21
|
.map(([nestedKey, nestedValue]) => {
|
|
20
|
-
const
|
|
21
|
-
// Si el hijo está registrado, añadimos al prefijo.
|
|
22
|
-
// Si no, mantenemos el prefijo actual (transparencia).
|
|
23
|
-
const nextKey = isRegistered ? (key ? `${key}:${nestedKey}` : nestedKey) : key;
|
|
22
|
+
const isPrefix = registry[nestedKey] !== undefined;
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
if (isPrefix) {
|
|
25
|
+
const nextKey = key ? `${key}:${nestedKey}` : nestedKey;
|
|
26
|
+
return process(nextKey, nestedValue);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Lógica estándar: si no es prefijo, es una clase condicional
|
|
30
|
+
return nestedValue ? process(key, nestedKey) : '';
|
|
26
31
|
})
|
|
27
32
|
.join(' ');
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
//
|
|
35
|
+
// 3. Resolución y Aplicación
|
|
31
36
|
const resolvedPrefix = key
|
|
32
37
|
.split(':')
|
|
33
38
|
.map((part) => registry[part] || null)
|
|
@@ -44,19 +49,9 @@ export function createCl<TPlugins extends Record<string, string>[]>(...plugins:
|
|
|
44
49
|
return '';
|
|
45
50
|
};
|
|
46
51
|
|
|
47
|
-
return (...inputs:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return Object.entries(input)
|
|
51
|
-
.map(([k, v]) => {
|
|
52
|
-
if (v === true) return k;
|
|
53
|
-
// Si la llave raíz no está registrada, empezamos proceso con key vacía
|
|
54
|
-
return process(registry[k] ? k : '', v);
|
|
55
|
-
})
|
|
56
|
-
.join(' ');
|
|
57
|
-
}
|
|
58
|
-
return input;
|
|
59
|
-
});
|
|
52
|
+
return (...inputs: ClassValue[]) => {
|
|
53
|
+
// Procesamos uno a uno para capturar objetos de prefijos antes de que clsx los aplane
|
|
54
|
+
const processed = inputs.map((input) => process('', input));
|
|
60
55
|
return twMerge(clsx(processed));
|
|
61
56
|
};
|
|
62
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
|
});
|