clases 1.1.0 → 1.1.2

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 CHANGED
@@ -9,7 +9,7 @@ var clsx__default = /*#__PURE__*/_interopDefault(clsx);
9
9
 
10
10
  // src/index.ts
11
11
  function createCl(...plugins) {
12
- const registry = Object.assign({ base: "base" }, ...plugins);
12
+ const registry = Object.assign({}, ...plugins);
13
13
  const process = (key, value) => {
14
14
  if (!value) return "";
15
15
  if (Array.isArray(value)) {
@@ -18,14 +18,20 @@ function createCl(...plugins) {
18
18
  if (typeof value === "object") {
19
19
  return Object.entries(value).map(([nestedKey, nestedValue]) => {
20
20
  const isRegistered = registry[nestedKey] !== void 0;
21
- const nextKey = key === "base" ? nestedKey : isRegistered ? `${key}:${nestedKey}` : key;
21
+ let nextKey;
22
+ if (key === "base") {
23
+ nextKey = nestedKey;
24
+ } else if (isRegistered) {
25
+ nextKey = `${key}:${nestedKey}`;
26
+ } else {
27
+ nextKey = key;
28
+ }
22
29
  return process(nextKey, nestedValue);
23
30
  }).join(" ");
24
31
  }
25
32
  const resolvedPrefix = key.split(":").map((part) => {
26
33
  if (part === "base") return null;
27
- if (registry[part]) return registry[part];
28
- return null;
34
+ return registry[part] || null;
29
35
  }).filter(Boolean).join(":");
30
36
  if (typeof value === "string") {
31
37
  return value.split(/[,\s\n]+/).filter(Boolean).map((cls) => !resolvedPrefix ? cls : `${resolvedPrefix}:${cls}`).join(" ");
@@ -35,7 +41,11 @@ function createCl(...plugins) {
35
41
  return (...inputs) => {
36
42
  const processed = inputs.map((input) => {
37
43
  if (input !== null && typeof input === "object" && !Array.isArray(input)) {
38
- return Object.entries(input).map(([k, v]) => v === true ? k : process(k, v)).join(" ");
44
+ return Object.entries(input).map(([k, v]) => {
45
+ if (v === true) return k;
46
+ const isRegistered = registry[k] !== void 0;
47
+ return process(isRegistered ? k : "base", v);
48
+ }).join(" ");
39
49
  }
40
50
  return input;
41
51
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["twMerge","clsx"],"mappings":";;;;;;;;;;AASO,SAAS,YAAuD,OAAA,EAAmB;AAKtF,EAAA,MAAM,QAAA,GAAmC,OAAO,MAAA,CAAO,EAAE,MAAM,MAAA,EAAO,EAAG,GAAG,OAAO,CAAA;AAQnF,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;AAM/B,QAAA,MAAM,YAAA,GAAe,QAAA,CAAS,SAAS,CAAA,KAAM,MAAA;AAC7C,QAAA,MAAM,OAAA,GACF,QAAQ,MAAA,GAAS,SAAA,GAAY,eAAe,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GAAK,GAAA;AAExE,QAAA,OAAO,OAAA,CAAQ,SAAS,WAAW,CAAA;AAAA,MACvC,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,IACjB;AAOA,IAAA,MAAM,iBAAiB,GAAA,CAClB,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,IAAA,KAAS;AACX,MAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA;AAE5B,MAAA,IAAI,QAAA,CAAS,IAAI,CAAA,EAAG,OAAO,SAAS,IAAI,CAAA;AAExC,MAAA,OAAO,IAAA;AAAA,IACX,CAAC,CAAA,CACA,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAGb,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;AAQA,EAAA,OAAO,IAAI,MAAA,KAAkB;AACzB,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACpC,MAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,KAAA,KAAU,YAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtE,QAAA,OAAO,OAAO,OAAA,CAAQ,KAAK,EACtB,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,CAAC,MAAO,CAAA,KAAM,IAAA,GAAO,IAAI,OAAA,CAAQ,CAAA,EAAG,CAAC,CAAE,CAAA,CAChD,KAAK,GAAG,CAAA;AAAA,MACjB;AACA,MAAA,OAAO,KAAA;AAAA,IACX,CAAC,CAAA;AACD,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 from 'clsx';\r\n\r\n/**\r\n * Creates a specialized utility for managing CSS classes with prefix support,\r\n * plugin mapping, and transparent logical nesting.\r\n * * @param plugins - An array of objects mapping custom aliases to real CSS prefixes.\r\n * @returns A function that processes class values, objects, and nested structures.\r\n */\r\nexport function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {\r\n /**\r\n * Internal registry that stores all official prefixes.\r\n * Any key not found here will be treated as \"transparent\" logic.\r\n */\r\n const registry: Record<string, string> = Object.assign({ base: 'base' }, ...plugins);\r\n\r\n /**\r\n * Recursively processes keys and values to build the prefixed class string.\r\n * * @param key - The current accumulated prefix path.\r\n * @param value - The class value, array, or nested object to process.\r\n * @returns A space-separated string of prefixed classes.\r\n */\r\n const process = (key: string, value: any): string => {\r\n if (!value) return '';\r\n\r\n // Handle Arrays: Process each element with the current key\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 // Handle Objects: Manage nesting and logical transparency\r\n if (typeof value === 'object') {\r\n return Object.entries(value)\r\n .map(([nestedKey, nestedValue]) => {\r\n /**\r\n * Rule: If the child key is registered, we concatenate it.\r\n * If it's not registered, it's a \"logical\" key (transparent),\r\n * so we inherit the parent's prefix.\r\n */\r\n const isRegistered = registry[nestedKey] !== undefined;\r\n const nextKey =\r\n key === 'base' ? nestedKey : isRegistered ? `${key}:${nestedKey}` : key;\r\n\r\n return process(nextKey, nestedValue);\r\n })\r\n .join(' ');\r\n }\r\n\r\n /**\r\n * FINAL RESOLUTION\r\n * Maps aliases (e.g., 'ui') to real prefixes (e.g., 'prefix')\r\n * and removes any non-registered logical parts.\r\n */\r\n const resolvedPrefix = key\r\n .split(':')\r\n .map((part) => {\r\n if (part === 'base') return null;\r\n // Return mapped value from registry if it exists\r\n if (registry[part]) return registry[part];\r\n // Otherwise, discard the part (Total Transparency)\r\n return null;\r\n })\r\n .filter(Boolean)\r\n .join(':');\r\n\r\n // Apply the resolved prefix to each class in the string\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 /**\r\n * The final utility function.\r\n * Processes inputs through the prefix engine and cleans them using tailwind-merge.\r\n * * @param inputs - Variadic arguments including strings, objects, arrays, or booleans.\r\n * @returns A merged and optimized string of Tailwind CSS classes.\r\n */\r\n return (...inputs: any[]) => {\r\n const processed = inputs.map((input) => {\r\n if (input !== null && typeof input === 'object' && !Array.isArray(input)) {\r\n return Object.entries(input)\r\n .map(([k, v]) => (v === true ? k : process(k, v)))\r\n .join(' ');\r\n }\r\n return input;\r\n });\r\n return twMerge(clsx(processed));\r\n };\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["twMerge","clsx"],"mappings":";;;;;;;;;;AAGO,SAAS,YAAuD,OAAA,EAAmB;AAEtF,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;AAEnB,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtB,MAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,GAAA,EAAK,CAAC,CAAC,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,IACrE;AAEA,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,YAAA,GAAe,QAAA,CAAS,SAAS,CAAA,KAAM,MAAA;AAE7C,QAAA,IAAI,OAAA;AACJ,QAAA,IAAI,QAAQ,MAAA,EAAQ;AAChB,UAAA,OAAA,GAAU,SAAA;AAAA,QACd,WAAW,YAAA,EAAc;AACrB,UAAA,OAAA,GAAU,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,QACjC,CAAA,MAAO;AAEH,UAAA,OAAA,GAAU,GAAA;AAAA,QACd;AAEA,QAAA,OAAO,OAAA,CAAQ,SAAS,WAAW,CAAA;AAAA,MACvC,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,IACjB;AAGA,IAAA,MAAM,iBAAiB,GAAA,CAClB,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,IAAA,KAAS;AACX,MAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA;AAG5B,MAAA,OAAO,QAAA,CAAS,IAAI,CAAA,IAAK,IAAA;AAAA,IAC7B,CAAC,CAAA,CACA,MAAA,CAAO,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,KAAkB;AACzB,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACpC,MAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,KAAA,KAAU,YAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtE,QAAA,OAAO,MAAA,CAAO,QAAQ,KAAK,CAAA,CACtB,IAAI,CAAC,CAAC,CAAA,EAAG,CAAC,CAAA,KAAM;AACb,UAAA,IAAI,CAAA,KAAM,MAAM,OAAO,CAAA;AAEvB,UAAA,MAAM,YAAA,GAAe,QAAA,CAAS,CAAC,CAAA,KAAM,MAAA;AACrC,UAAA,OAAO,OAAA,CAAQ,YAAA,GAAe,CAAA,GAAI,MAAA,EAAQ,CAAC,CAAA;AAAA,QAC/C,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,MACjB;AACA,MAAA,OAAO,KAAA;AAAA,IACX,CAAC,CAAA;AACD,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 from 'clsx';\r\n\r\nexport function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {\r\n // Importante: No incluimos 'base' aquí para que no interfiera en el filtrado final\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 if (Array.isArray(value)) {\r\n return value.map((v) => process(key, v)).filter(Boolean).join(' ');\r\n }\r\n\r\n if (typeof value === 'object') {\r\n return Object.entries(value)\r\n .map(([nestedKey, nestedValue]) => {\r\n const isRegistered = registry[nestedKey] !== undefined;\r\n \r\n let nextKey: string;\r\n if (key === 'base') {\r\n nextKey = nestedKey;\r\n } else if (isRegistered) {\r\n nextKey = `${key}:${nestedKey}`;\r\n } else {\r\n // Si no está registrado, mantenemos el key actual (transparencia)\r\n nextKey = key;\r\n }\r\n\r\n return process(nextKey, nestedValue);\r\n })\r\n .join(' ');\r\n }\r\n\r\n // RESOLUCIÓN FINAL: Filtro estricto\r\n const resolvedPrefix = key\r\n .split(':')\r\n .map((part) => {\r\n if (part === 'base') return null;\r\n // SOLO devolvemos si existe en el registro. \r\n // Si 'variants' no está, esto devuelve null y se limpia.\r\n return registry[part] || null; \r\n })\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: any[]) => {\r\n const processed = inputs.map((input) => {\r\n if (input !== null && typeof input === 'object' && !Array.isArray(input)) {\r\n return Object.entries(input)\r\n .map(([k, v]) => {\r\n if (v === true) return k;\r\n // Si la llave inicial no está registrada, empezamos con 'base'\r\n const isRegistered = registry[k] !== undefined;\r\n return process(isRegistered ? k : 'base', v);\r\n })\r\n .join(' ');\r\n }\r\n return input;\r\n });\r\n return twMerge(clsx(processed));\r\n };\r\n}\r\n"]}
package/dist/index.d.cts CHANGED
@@ -1,9 +1,3 @@
1
- /**
2
- * Creates a specialized utility for managing CSS classes with prefix support,
3
- * plugin mapping, and transparent logical nesting.
4
- * * @param plugins - An array of objects mapping custom aliases to real CSS prefixes.
5
- * @returns A function that processes class values, objects, and nested structures.
6
- */
7
1
  declare function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins): (...inputs: any[]) => string;
8
2
 
9
3
  export { createCl };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,3 @@
1
- /**
2
- * Creates a specialized utility for managing CSS classes with prefix support,
3
- * plugin mapping, and transparent logical nesting.
4
- * * @param plugins - An array of objects mapping custom aliases to real CSS prefixes.
5
- * @returns A function that processes class values, objects, and nested structures.
6
- */
7
1
  declare function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins): (...inputs: any[]) => string;
8
2
 
9
3
  export { createCl };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import clsx from 'clsx';
3
3
 
4
4
  // src/index.ts
5
5
  function createCl(...plugins) {
6
- const registry = Object.assign({ base: "base" }, ...plugins);
6
+ const registry = Object.assign({}, ...plugins);
7
7
  const process = (key, value) => {
8
8
  if (!value) return "";
9
9
  if (Array.isArray(value)) {
@@ -12,14 +12,20 @@ function createCl(...plugins) {
12
12
  if (typeof value === "object") {
13
13
  return Object.entries(value).map(([nestedKey, nestedValue]) => {
14
14
  const isRegistered = registry[nestedKey] !== void 0;
15
- const nextKey = key === "base" ? nestedKey : isRegistered ? `${key}:${nestedKey}` : key;
15
+ let nextKey;
16
+ if (key === "base") {
17
+ nextKey = nestedKey;
18
+ } else if (isRegistered) {
19
+ nextKey = `${key}:${nestedKey}`;
20
+ } else {
21
+ nextKey = key;
22
+ }
16
23
  return process(nextKey, nestedValue);
17
24
  }).join(" ");
18
25
  }
19
26
  const resolvedPrefix = key.split(":").map((part) => {
20
27
  if (part === "base") return null;
21
- if (registry[part]) return registry[part];
22
- return null;
28
+ return registry[part] || null;
23
29
  }).filter(Boolean).join(":");
24
30
  if (typeof value === "string") {
25
31
  return value.split(/[,\s\n]+/).filter(Boolean).map((cls) => !resolvedPrefix ? cls : `${resolvedPrefix}:${cls}`).join(" ");
@@ -29,7 +35,11 @@ function createCl(...plugins) {
29
35
  return (...inputs) => {
30
36
  const processed = inputs.map((input) => {
31
37
  if (input !== null && typeof input === "object" && !Array.isArray(input)) {
32
- return Object.entries(input).map(([k, v]) => v === true ? k : process(k, v)).join(" ");
38
+ return Object.entries(input).map(([k, v]) => {
39
+ if (v === true) return k;
40
+ const isRegistered = registry[k] !== void 0;
41
+ return process(isRegistered ? k : "base", v);
42
+ }).join(" ");
33
43
  }
34
44
  return input;
35
45
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;AASO,SAAS,YAAuD,OAAA,EAAmB;AAKtF,EAAA,MAAM,QAAA,GAAmC,OAAO,MAAA,CAAO,EAAE,MAAM,MAAA,EAAO,EAAG,GAAG,OAAO,CAAA;AAQnF,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;AAM/B,QAAA,MAAM,YAAA,GAAe,QAAA,CAAS,SAAS,CAAA,KAAM,MAAA;AAC7C,QAAA,MAAM,OAAA,GACF,QAAQ,MAAA,GAAS,SAAA,GAAY,eAAe,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GAAK,GAAA;AAExE,QAAA,OAAO,OAAA,CAAQ,SAAS,WAAW,CAAA;AAAA,MACvC,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,IACjB;AAOA,IAAA,MAAM,iBAAiB,GAAA,CAClB,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,IAAA,KAAS;AACX,MAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA;AAE5B,MAAA,IAAI,QAAA,CAAS,IAAI,CAAA,EAAG,OAAO,SAAS,IAAI,CAAA;AAExC,MAAA,OAAO,IAAA;AAAA,IACX,CAAC,CAAA,CACA,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAGb,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;AAQA,EAAA,OAAO,IAAI,MAAA,KAAkB;AACzB,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACpC,MAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,KAAA,KAAU,YAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtE,QAAA,OAAO,OAAO,OAAA,CAAQ,KAAK,EACtB,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,CAAC,MAAO,CAAA,KAAM,IAAA,GAAO,IAAI,OAAA,CAAQ,CAAA,EAAG,CAAC,CAAE,CAAA,CAChD,KAAK,GAAG,CAAA;AAAA,MACjB;AACA,MAAA,OAAO,KAAA;AAAA,IACX,CAAC,CAAA;AACD,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 from 'clsx';\r\n\r\n/**\r\n * Creates a specialized utility for managing CSS classes with prefix support,\r\n * plugin mapping, and transparent logical nesting.\r\n * * @param plugins - An array of objects mapping custom aliases to real CSS prefixes.\r\n * @returns A function that processes class values, objects, and nested structures.\r\n */\r\nexport function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {\r\n /**\r\n * Internal registry that stores all official prefixes.\r\n * Any key not found here will be treated as \"transparent\" logic.\r\n */\r\n const registry: Record<string, string> = Object.assign({ base: 'base' }, ...plugins);\r\n\r\n /**\r\n * Recursively processes keys and values to build the prefixed class string.\r\n * * @param key - The current accumulated prefix path.\r\n * @param value - The class value, array, or nested object to process.\r\n * @returns A space-separated string of prefixed classes.\r\n */\r\n const process = (key: string, value: any): string => {\r\n if (!value) return '';\r\n\r\n // Handle Arrays: Process each element with the current key\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 // Handle Objects: Manage nesting and logical transparency\r\n if (typeof value === 'object') {\r\n return Object.entries(value)\r\n .map(([nestedKey, nestedValue]) => {\r\n /**\r\n * Rule: If the child key is registered, we concatenate it.\r\n * If it's not registered, it's a \"logical\" key (transparent),\r\n * so we inherit the parent's prefix.\r\n */\r\n const isRegistered = registry[nestedKey] !== undefined;\r\n const nextKey =\r\n key === 'base' ? nestedKey : isRegistered ? `${key}:${nestedKey}` : key;\r\n\r\n return process(nextKey, nestedValue);\r\n })\r\n .join(' ');\r\n }\r\n\r\n /**\r\n * FINAL RESOLUTION\r\n * Maps aliases (e.g., 'ui') to real prefixes (e.g., 'prefix')\r\n * and removes any non-registered logical parts.\r\n */\r\n const resolvedPrefix = key\r\n .split(':')\r\n .map((part) => {\r\n if (part === 'base') return null;\r\n // Return mapped value from registry if it exists\r\n if (registry[part]) return registry[part];\r\n // Otherwise, discard the part (Total Transparency)\r\n return null;\r\n })\r\n .filter(Boolean)\r\n .join(':');\r\n\r\n // Apply the resolved prefix to each class in the string\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 /**\r\n * The final utility function.\r\n * Processes inputs through the prefix engine and cleans them using tailwind-merge.\r\n * * @param inputs - Variadic arguments including strings, objects, arrays, or booleans.\r\n * @returns A merged and optimized string of Tailwind CSS classes.\r\n */\r\n return (...inputs: any[]) => {\r\n const processed = inputs.map((input) => {\r\n if (input !== null && typeof input === 'object' && !Array.isArray(input)) {\r\n return Object.entries(input)\r\n .map(([k, v]) => (v === true ? k : process(k, v)))\r\n .join(' ');\r\n }\r\n return input;\r\n });\r\n return twMerge(clsx(processed));\r\n };\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;AAGO,SAAS,YAAuD,OAAA,EAAmB;AAEtF,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;AAEnB,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtB,MAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,GAAA,EAAK,CAAC,CAAC,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,IACrE;AAEA,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,YAAA,GAAe,QAAA,CAAS,SAAS,CAAA,KAAM,MAAA;AAE7C,QAAA,IAAI,OAAA;AACJ,QAAA,IAAI,QAAQ,MAAA,EAAQ;AAChB,UAAA,OAAA,GAAU,SAAA;AAAA,QACd,WAAW,YAAA,EAAc;AACrB,UAAA,OAAA,GAAU,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,QACjC,CAAA,MAAO;AAEH,UAAA,OAAA,GAAU,GAAA;AAAA,QACd;AAEA,QAAA,OAAO,OAAA,CAAQ,SAAS,WAAW,CAAA;AAAA,MACvC,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,IACjB;AAGA,IAAA,MAAM,iBAAiB,GAAA,CAClB,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,IAAA,KAAS;AACX,MAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA;AAG5B,MAAA,OAAO,QAAA,CAAS,IAAI,CAAA,IAAK,IAAA;AAAA,IAC7B,CAAC,CAAA,CACA,MAAA,CAAO,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,KAAkB;AACzB,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACpC,MAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,KAAA,KAAU,YAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtE,QAAA,OAAO,MAAA,CAAO,QAAQ,KAAK,CAAA,CACtB,IAAI,CAAC,CAAC,CAAA,EAAG,CAAC,CAAA,KAAM;AACb,UAAA,IAAI,CAAA,KAAM,MAAM,OAAO,CAAA;AAEvB,UAAA,MAAM,YAAA,GAAe,QAAA,CAAS,CAAC,CAAA,KAAM,MAAA;AACrC,UAAA,OAAO,OAAA,CAAQ,YAAA,GAAe,CAAA,GAAI,MAAA,EAAQ,CAAC,CAAA;AAAA,QAC/C,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAAA,MACjB;AACA,MAAA,OAAO,KAAA;AAAA,IACX,CAAC,CAAA;AACD,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 from 'clsx';\r\n\r\nexport function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {\r\n // Importante: No incluimos 'base' aquí para que no interfiera en el filtrado final\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 if (Array.isArray(value)) {\r\n return value.map((v) => process(key, v)).filter(Boolean).join(' ');\r\n }\r\n\r\n if (typeof value === 'object') {\r\n return Object.entries(value)\r\n .map(([nestedKey, nestedValue]) => {\r\n const isRegistered = registry[nestedKey] !== undefined;\r\n \r\n let nextKey: string;\r\n if (key === 'base') {\r\n nextKey = nestedKey;\r\n } else if (isRegistered) {\r\n nextKey = `${key}:${nestedKey}`;\r\n } else {\r\n // Si no está registrado, mantenemos el key actual (transparencia)\r\n nextKey = key;\r\n }\r\n\r\n return process(nextKey, nestedValue);\r\n })\r\n .join(' ');\r\n }\r\n\r\n // RESOLUCIÓN FINAL: Filtro estricto\r\n const resolvedPrefix = key\r\n .split(':')\r\n .map((part) => {\r\n if (part === 'base') return null;\r\n // SOLO devolvemos si existe en el registro. \r\n // Si 'variants' no está, esto devuelve null y se limpia.\r\n return registry[part] || null; \r\n })\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: any[]) => {\r\n const processed = inputs.map((input) => {\r\n if (input !== null && typeof input === 'object' && !Array.isArray(input)) {\r\n return Object.entries(input)\r\n .map(([k, v]) => {\r\n if (v === true) return k;\r\n // Si la llave inicial no está registrada, empezamos con 'base'\r\n const isRegistered = registry[k] !== undefined;\r\n return process(isRegistered ? k : 'base', v);\r\n })\r\n .join(' ');\r\n }\r\n return input;\r\n });\r\n return twMerge(clsx(processed));\r\n };\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clases",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/src/index.ts CHANGED
@@ -1,72 +1,49 @@
1
1
  import { twMerge } from 'tailwind-merge';
2
2
  import clsx from 'clsx';
3
3
 
4
- /**
5
- * Creates a specialized utility for managing CSS classes with prefix support,
6
- * plugin mapping, and transparent logical nesting.
7
- * * @param plugins - An array of objects mapping custom aliases to real CSS prefixes.
8
- * @returns A function that processes class values, objects, and nested structures.
9
- */
10
4
  export function createCl<TPlugins extends Record<string, string>[]>(...plugins: TPlugins) {
11
- /**
12
- * Internal registry that stores all official prefixes.
13
- * Any key not found here will be treated as "transparent" logic.
14
- */
15
- const registry: Record<string, string> = Object.assign({ base: 'base' }, ...plugins);
5
+ // Importante: No incluimos 'base' aquí para que no interfiera en el filtrado final
6
+ const registry: Record<string, string> = Object.assign({}, ...plugins);
16
7
 
17
- /**
18
- * Recursively processes keys and values to build the prefixed class string.
19
- * * @param key - The current accumulated prefix path.
20
- * @param value - The class value, array, or nested object to process.
21
- * @returns A space-separated string of prefixed classes.
22
- */
23
8
  const process = (key: string, value: any): string => {
24
9
  if (!value) return '';
25
10
 
26
- // Handle Arrays: Process each element with the current key
27
11
  if (Array.isArray(value)) {
28
- return value
29
- .map((v) => process(key, v))
30
- .filter(Boolean)
31
- .join(' ');
12
+ return value.map((v) => process(key, v)).filter(Boolean).join(' ');
32
13
  }
33
14
 
34
- // Handle Objects: Manage nesting and logical transparency
35
15
  if (typeof value === 'object') {
36
16
  return Object.entries(value)
37
17
  .map(([nestedKey, nestedValue]) => {
38
- /**
39
- * Rule: If the child key is registered, we concatenate it.
40
- * If it's not registered, it's a "logical" key (transparent),
41
- * so we inherit the parent's prefix.
42
- */
43
18
  const isRegistered = registry[nestedKey] !== undefined;
44
- const nextKey =
45
- key === 'base' ? nestedKey : isRegistered ? `${key}:${nestedKey}` : key;
19
+
20
+ let nextKey: string;
21
+ if (key === 'base') {
22
+ nextKey = nestedKey;
23
+ } else if (isRegistered) {
24
+ nextKey = `${key}:${nestedKey}`;
25
+ } else {
26
+ // Si no está registrado, mantenemos el key actual (transparencia)
27
+ nextKey = key;
28
+ }
46
29
 
47
30
  return process(nextKey, nestedValue);
48
31
  })
49
32
  .join(' ');
50
33
  }
51
34
 
52
- /**
53
- * FINAL RESOLUTION
54
- * Maps aliases (e.g., 'ui') to real prefixes (e.g., 'prefix')
55
- * and removes any non-registered logical parts.
56
- */
35
+ // RESOLUCIÓN FINAL: Filtro estricto
57
36
  const resolvedPrefix = key
58
37
  .split(':')
59
38
  .map((part) => {
60
39
  if (part === 'base') return null;
61
- // Return mapped value from registry if it exists
62
- if (registry[part]) return registry[part];
63
- // Otherwise, discard the part (Total Transparency)
64
- return null;
40
+ // SOLO devolvemos si existe en el registro.
41
+ // Si 'variants' no está, esto devuelve null y se limpia.
42
+ return registry[part] || null;
65
43
  })
66
44
  .filter(Boolean)
67
45
  .join(':');
68
46
 
69
- // Apply the resolved prefix to each class in the string
70
47
  if (typeof value === 'string') {
71
48
  return value
72
49
  .split(/[,\s\n]+/)
@@ -77,17 +54,16 @@ export function createCl<TPlugins extends Record<string, string>[]>(...plugins:
77
54
  return '';
78
55
  };
79
56
 
80
- /**
81
- * The final utility function.
82
- * Processes inputs through the prefix engine and cleans them using tailwind-merge.
83
- * * @param inputs - Variadic arguments including strings, objects, arrays, or booleans.
84
- * @returns A merged and optimized string of Tailwind CSS classes.
85
- */
86
57
  return (...inputs: any[]) => {
87
58
  const processed = inputs.map((input) => {
88
59
  if (input !== null && typeof input === 'object' && !Array.isArray(input)) {
89
60
  return Object.entries(input)
90
- .map(([k, v]) => (v === true ? k : process(k, v)))
61
+ .map(([k, v]) => {
62
+ if (v === true) return k;
63
+ // Si la llave inicial no está registrada, empezamos con 'base'
64
+ const isRegistered = registry[k] !== undefined;
65
+ return process(isRegistered ? k : 'base', v);
66
+ })
91
67
  .join(' ');
92
68
  }
93
69
  return input;
@@ -77,4 +77,90 @@ it('Nivel 5: El "Inception" (Lógica anidada, condicionales y plugins)', () => {
77
77
  // md:p-8 debe ganar a md:p-4
78
78
  expect(result).toBe('md:p-8');
79
79
  });
80
+
81
+ it('Nivel 7: Selectores Dinámicos (Sintaxis de Componente)', () => {
82
+ const variant = 'primary';
83
+ const onHover = 'scale';
84
+
85
+ const result = cl({
86
+ // 'variants' no está registrado -> Desaparece
87
+ variants: {
88
+ primary: 'bg-action text-white',
89
+ secondary: 'bg-neutral-50 text-black'
90
+ }[variant],
91
+
92
+ // 'effects' no está registrado -> Desaparece
93
+ effects: {
94
+ scale: 'elevate-hover',
95
+ dim: 'hover:opacity-80'
96
+ }[onHover]
97
+ });
98
+
99
+ // El resultado no debe contener ni 'variants:' ni 'effects:'
100
+ expect(result).toBe('bg-action text-white elevate-hover');
101
+ expect(result).not.toContain('variants:');
102
+ expect(result).not.toContain('effects:');
103
+ });
104
+
105
+ it('Nivel 8: Combinación de Selectores con Prefijos Registrados', () => {
106
+ const variant = 'secondary';
107
+ const isDark = true;
108
+
109
+ const result = cl({
110
+ md: {
111
+ // Selector dinámico dentro de un prefijo registrado
112
+ container: {
113
+ [variant]: {
114
+ base: 'p-4',
115
+ // Prefijo registrado dentro de un selector dinámico
116
+ hover: 'shadow-xl'
117
+ }
118
+ }[variant]
119
+ }
120
+ });
121
+
122
+ // 'md' y 'hover' se mantienen, 'container' y 'secondary' desaparecen
123
+ expect(result).toBe('md:p-4 md:hover:shadow-xl');
124
+ });
125
+
126
+ it('Nivel 9: El Caso del Botón (Reproducción de Bug)', () => {
127
+ const variant = 'secondary';
128
+ const onHover = 'scale';
129
+
130
+ const result = cl(
131
+ // 1. Clases base (Strings)
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:');
155
+
156
+ // Verificación de contenido
157
+ expect(result).toContain('bg-neutral-50');
158
+ expect(result).toContain('elevate-hover');
159
+ expect(result).toContain('clickable'); // Debe mantener las clases base
160
+
161
+ // El resultado final debe ser un string limpio de Tailwind
162
+ expect(result).toBe(
163
+ 'py-2 px-4 rounded-lg flex clickable bg-neutral-50 text-text-muted border-2 elevate-hover'
164
+ );
165
+ });
80
166
  });