create-lexy 0.6.1 → 0.6.3

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.
Files changed (93) hide show
  1. package/README.md +7 -2
  2. package/assets/fonts/{OFL-NotoSans.txt → LICENSE-Geist.txt} +4 -5
  3. package/assets/fonts/geist-mono-variable-italic.woff2 +0 -0
  4. package/assets/fonts/geist-mono-variable.woff2 +0 -0
  5. package/assets/fonts/geist-sans-variable-italic.woff2 +0 -0
  6. package/assets/fonts/geist-sans-variable.woff2 +0 -0
  7. package/assets/r/accordion.json +3 -3
  8. package/assets/r/alert-dialog.json +3 -3
  9. package/assets/r/app-accordion.json +1 -1
  10. package/assets/r/app-dialog.json +3 -3
  11. package/assets/r/app-header-bar.json +2 -2
  12. package/assets/r/app-sidebar.json +2 -2
  13. package/assets/r/avatar.json +3 -3
  14. package/assets/r/badge.json +3 -3
  15. package/assets/r/brand-background.json +1 -1
  16. package/assets/r/breadcrumb.json +3 -3
  17. package/assets/r/button-group.json +3 -3
  18. package/assets/r/button.json +3 -3
  19. package/assets/r/calendar.json +2 -2
  20. package/assets/r/card.json +3 -3
  21. package/assets/r/chart.json +2 -2
  22. package/assets/r/checkbox.json +2 -2
  23. package/assets/r/combobox.json +3 -3
  24. package/assets/r/command.json +3 -3
  25. package/assets/r/confirmacion.json +1 -1
  26. package/assets/r/counter-badge.json +3 -3
  27. package/assets/r/crm-desk.json +1 -1
  28. package/assets/r/crm-detalle-caso.json +5 -5
  29. package/assets/r/date-picker.json +1 -1
  30. package/assets/r/dialog.json +3 -3
  31. package/assets/r/dropdown-menu.json +3 -3
  32. package/assets/r/empty.json +2 -2
  33. package/assets/r/feature-card.json +3 -3
  34. package/assets/r/form.json +3 -3
  35. package/assets/r/header-bar.json +2 -2
  36. package/assets/r/input.json +3 -3
  37. package/assets/r/intake-wizard.json +1 -1
  38. package/assets/r/label.json +3 -3
  39. package/assets/r/logo.json +2 -2
  40. package/assets/r/menubar.json +3 -3
  41. package/assets/r/navigation-menu.json +3 -3
  42. package/assets/r/pagination.json +2 -2
  43. package/assets/r/popover.json +3 -3
  44. package/assets/r/profile-card.json +3 -3
  45. package/assets/r/progress.json +2 -2
  46. package/assets/r/radio-group.json +2 -2
  47. package/assets/r/registry.json +47 -47
  48. package/assets/r/scroll-area.json +2 -2
  49. package/assets/r/searchbox.json +3 -3
  50. package/assets/r/select.json +3 -3
  51. package/assets/r/separator.json +2 -2
  52. package/assets/r/sheet.json +2 -2
  53. package/assets/r/sidebar.json +3 -3
  54. package/assets/r/skeleton.json +2 -2
  55. package/assets/r/slider.json +3 -3
  56. package/assets/r/snippet.json +3 -3
  57. package/assets/r/spinner.json +2 -2
  58. package/assets/r/status-dot.json +3 -3
  59. package/assets/r/switch.json +3 -3
  60. package/assets/r/table.json +3 -3
  61. package/assets/r/tabs.json +3 -3
  62. package/assets/r/tag.json +3 -3
  63. package/assets/r/textarea.json +3 -3
  64. package/assets/r/toaster.json +3 -3
  65. package/assets/r/tooltip.json +3 -3
  66. package/assets/r/tree.json +3 -3
  67. package/assets/registry-version +1 -1
  68. package/assets/theme/lexy-theme.css +562 -112
  69. package/dist/index.js +590 -276
  70. package/package.json +4 -2
  71. package/templates/.claude/skills/lexy-design/SKILL.md +189 -0
  72. package/templates/.claude/skills/lexy-dev/SKILL.md +168 -0
  73. package/templates/.claude/skills/lexy-mock-data/SKILL.md +50 -0
  74. package/templates/.github/copilot-instructions.md +50 -0
  75. package/templates/.mcp.json +8 -0
  76. package/templates/AGENTS.md +243 -0
  77. package/templates/CLAUDE.md +61 -0
  78. package/templates/ai/IMPLEMENTATION-PROTOCOL.md +148 -0
  79. package/templates/ai/PRODUCTION-CLEANUP.md +17 -0
  80. package/templates/ai/PROJECT-CONTEXT.md +65 -0
  81. package/templates/ai/README.md +19 -0
  82. package/templates/ai/TECHNICAL-USAGE.md +220 -0
  83. package/templates/ai/pautas/arquitectura-informacion-ux.md +243 -0
  84. package/templates/ai/pautas/buenas-practicas.md +236 -0
  85. package/templates/ai/pautas/calidad-industria.md +109 -0
  86. package/templates/ai/pautas/diseno-cliente.md +136 -0
  87. package/templates/ai/pautas/diseno-crm-lexy.md +109 -0
  88. package/templates/ai/pautas/patrones-de-codigo.md +234 -0
  89. package/templates/ai/pautas/recetas-layout.md +419 -0
  90. package/templates/ai/pautas/sistema-visual.md +197 -0
  91. package/templates/ai/pautas/ux-writing.md +214 -0
  92. package/templates/scripts/check-geometry.mjs +139 -0
  93. package/assets/fonts/noto-sans-latin.woff2 +0 -0
package/dist/index.js CHANGED
@@ -1,27 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as Po}from"fs";import tt from"path";import{fileURLToPath as jo}from"url";import{Command as Co}from"commander";import Io from"picocolors";import{spawn as ct}from"child_process";import Q from"fs/promises";import G from"path";import{confirm as dt,isCancel as pt,spinner as Te}from"@clack/prompts";import h from"picocolors";import te from"path";var ot=(e,t)=>t.architecture!=="feature"?e:e.replace(/from ["']@\/lib\/utils\/cn["']/g,'from "@/shared/lib/utils/cn"').replace(/from ["']@\/components\/base\//g,'from "@/shared/components/base/'),at=[["components/base/",e=>e.paths.components],["views/",e=>e.paths.views],["hooks/",e=>e.paths.hooks],["lib/",e=>e.paths.lib]],T=(e,t)=>e.files.filter(o=>typeof o.content=="string").map(o=>{let a=at.find(([r])=>o.path.startsWith(r)),n=a?te.posix.join(a[1](t),o.path.slice(a[0].length)):te.posix.join(t.paths.components,te.posix.basename(o.path));return o.encoding==="base64"?{relPath:n,content:o.content,encoding:"base64"}:{relPath:n,content:ot(o.content,t)}});import we from"fs/promises";import nt from"path";var Se=e=>nt.join(e,".lexy"),O=async e=>{let t;try{t=await we.readFile(Se(e),"utf-8")}catch{throw new Error("No se encontr\xF3 el archivo .lexy. \xBFEst\xE1s en la ra\xEDz de un proyecto Lexy? (cr\xE9alo con `npx create-lexy create`)")}let o=JSON.parse(t);if(!o.paths?.components)throw new Error("El .lexy no tiene paths.components \u2014 archivo corrupto o de una versi\xF3n incompatible.");return o.installed??={},o},ke=async(e,t)=>{await we.writeFile(Se(e),JSON.stringify(t,null,2)+`
3
- `)};import q from"fs/promises";import rt from"os";import R from"path";import{fileURLToPath as it}from"url";var Ee="@lexydesign/registry",F=`https://cdn.jsdelivr.net/npm/${Ee}`,st=8e3,J=R.resolve(R.dirname(it(import.meta.url)),"../assets"),lt=R.join(rt.homedir(),".cache","create-lexy","registry"),B=async e=>{let t=await fetch(e,{signal:AbortSignal.timeout(st)});if(!t.ok){let o=new Error(`HTTP ${t.status} al pedir ${e}`);throw o.status=t.status,o}return await t.json()},Pe=async e=>{try{return JSON.parse(await q.readFile(R.join(J,"r",e),"utf-8"))}catch{return null}},oe=async()=>{try{return(await q.readFile(R.join(J,"registry-version"),"utf-8")).trim()}catch{return"bundle"}},$=null,W=async()=>{if($)return $;try{$=(await B(`https://registry.npmjs.org/${Ee}/latest`)).version}catch{try{$=(await B(`${F}@latest/package.json`)).version}catch{$=await oe()}}return $},k=async(e,t)=>{let o=e.replace(/^@lexy\//,""),a=t??await W(),n=R.join(lt,a,`${o}.json`);try{return{item:JSON.parse(await q.readFile(n,"utf-8")),version:a,source:"cache"}}catch{}try{let r=await B(`${F}@${a}/r/${o}.json`);return await q.mkdir(R.dirname(n),{recursive:!0}),await q.writeFile(n,JSON.stringify(r)),{item:r,version:a,source:"cdn"}}catch(r){if(r.status===404)throw new Error(`El componente "${o}" no existe en el registry (versi\xF3n ${a}). Mira el cat\xE1logo con \`create-lexy view --list\`.`);let i=await Pe(`${o}.json`);if(i)return{item:i,version:await oe(),source:"bundle"};throw new Error(`No se pudo alcanzar el registry (\xBFsin red?) y "${o}" tampoco est\xE1 en el bundle local del CLI.`)}},je=async()=>{try{let e=await W();return{index:await B(`${F}@${e}/r/registry.json`),version:e,source:"cdn"}}catch{let e=await Pe("registry.json");if(e)return{index:e,version:await oe(),source:"bundle"};throw new Error("No se pudo alcanzar el registry ni leer el bundle local del CLI.")}},Ce=R.join(J,"theme/lexy-theme.css"),Ie=R.join(J,"fonts");var mt=(e,t)=>new Promise((o,a)=>{ct("pnpm",["add",...e],{cwd:t,stdio:"ignore",shell:!0}).on("close",r=>r===0?o():a(new Error(`pnpm add fall\xF3 con c\xF3digo ${r}`)))}),ut=async(e,t="utf-8")=>{try{return await Q.readFile(e,t)}catch{return null}},Re=async(e,t)=>{let o=process.cwd(),a=await O(o),n=Te();n.start("Resolviendo componentes en el registry...");let r=new Map,i=async p=>{let f=p.toLowerCase().replace(/^@lexy\//,"");if(r.has(f))return;let c=await k(f);r.set(f,c);for(let l of c.item.registryDependencies??[])await i(l)};try{for(let p of e)await i(p)}catch(p){throw n.stop(h.red("No se pudo resolver el pedido.")),p}let d=new Map;for(let[p,{item:f}]of r){let c=[];for(let l of T(f,a)){let g=await ut(G.join(o,l.relPath),l.encoding??"utf-8");c.push({...l,status:g===null?"new":g===l.content?"same":"differs"})}d.set(p,c)}let s=Array.from(d.values()).flat().filter(p=>p.status==="differs");if(n.stop(`Resueltos: ${Array.from(r.keys()).join(", ")}`),s.length>0&&!t.overwrite){let p=s.map(f=>` ${f.relPath}`).join(`
4
- `);if(process.stdout.isTTY&&process.stdin.isTTY){let f=await dt({message:`Estos archivos existen con cambios locales y ser\xE1n sobrescritos:
5
- ${p}
6
- \xBFContinuar?`});if(pt(f)||f!==!0){console.log(h.yellow("Operaci\xF3n cancelada \u2014 nada fue modificado.")),process.exitCode=1;return}}else{console.error(h.red(`Estos archivos existen con cambios locales:
7
- `)+p+h.dim(`
8
- Usa --overwrite para sobrescribirlos.`)),process.exitCode=1;return}}for(let[p,f]of d){let{item:c,version:l,source:g}=r.get(p);for(let x of f){if(x.status==="same")continue;let A=G.join(o,x.relPath);await Q.mkdir(G.dirname(A),{recursive:!0}),await Q.writeFile(A,x.content,x.encoding??"utf-8")}a.installed[c.name]=l;let P=e.map(x=>x.toLowerCase()).includes(p)?"":h.dim(" (dependencia)"),U=g==="bundle"?h.yellow(" [bundle local \u2014 sin red]"):"";console.log(h.green(`${h.bold(c.title??c.name)} instalado`)+P+h.cyan(` \u2192 ${a.paths.components}/`)+U);for(let x of f){let A=x.status==="same"?h.dim(" (sin cambios)"):"";console.log(h.dim(` ${x.relPath}${A}`))}}await ke(o,a);let u=new Set;for(let{item:p}of r.values())for(let f of p.dependencies??[])u.add(f);let m=JSON.parse(await Q.readFile(G.join(o,"package.json"),"utf-8")),y={...m.dependencies,...m.devDependencies},z=p=>{let f=p.lastIndexOf("@");return f>0?p.slice(0,f):p},M=Array.from(u).filter(p=>!y[z(p)]);if(M.length>0)if(t.install===!1)console.log(h.yellow(`Dependencias pendientes (inst\xE1lalas t\xFA): ${M.join(", ")}`));else{let p=Te();p.start(`Instalando dependencias: ${M.join(", ")}...`),await mt(M,o),p.stop("Dependencias instaladas.")}};import{spawn as po}from"child_process";import{note as mo,outro as uo,spinner as yo}from"@clack/prompts";import j from"picocolors";import{cancel as yt,intro as ft,isCancel as gt,select as Oe,text as xt}from"@clack/prompts";import _e from"picocolors";var ae=[{value:"screen",label:"Una pantalla o flujo corto",hint:"landing, formulario, demo \u2014 sin navegaci\xF3n entre secciones",architecture:"layer"},{value:"app",label:"Una app con secciones y navegaci\xF3n",hint:"dashboard, listados, detalle \u2014 varias vistas con router",architecture:"feature"}],Ne=e=>ae.find(t=>t.value===e).architecture;var vt=`
9
- ###### ######
10
- ##::+#### ####+::##
11
- #-..:+################+:..:#
12
- #+...=################=...+#
13
- #=-*##################*-=#
14
- ########################
15
- ==-:.:=*##########*=:.::==
16
- **#####*+--*####*--+*#####**
17
- ##########%@@#:-##=.#@@%##########
18
- #######*+*#%%*:-@@=.+%%#*+*#######
19
- #+:..........:*#:..........:=#
20
- ...........:====:...........
21
- ......................
22
- ..............
23
- `,ne=e=>{gt(e)&&(yt("Operaci\xF3n cancelada por el usuario."),process.exit(0))},Ae=async e=>{console.clear(),ft(`${_e.cyan(vt)}
24
- ${_e.bold(" Bienvenido al generador de proyectos Lexy")}`);let t=e;if(!t){let n=await xt({message:"\xBFCu\xE1l es el nombre de tu proyecto?",placeholder:"lexy-app",validate:r=>{if(!r||r.trim()==="")return"El nombre es obligatorio.";if(!/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(r))return"El nombre debe estar en min\xFAsculas, sin espacios ni caracteres especiales."}});ne(n),t=n}let o=await Oe({message:"\xBFPara qui\xE9n es este proyecto?",options:[{label:"Clientes de Lexy",value:"cliente",hint:"Producto de cara al cliente final"},{label:"Equipo interno / CRM",value:"crm",hint:"Herramienta densa para el equipo Lexy"},{label:"Ambos o a\xFAn no lo s\xE9",value:"mixto",hint:"Se decide por pantalla m\xE1s adelante"}],initialValue:"mixto"});ne(o);let a=await Oe({message:"\xBFC\xF3mo es lo que vas a construir?",options:ae.map(n=>({label:n.label,value:n.value,hint:n.hint})),initialValue:"app"});return ne(a),{projectName:t,architecture:Ne(a),world:o}};import b from"fs/promises";import w from"path";import{format as qt,resolveConfig as Vt}from"prettier";import Le from"fs/promises";import De from"path";var re="src/prototype/data-contract/prototype-data-contract.ts",ht="src/prototype/data-contract/data-contract-schema.ts",bt="scripts/check-data-contract.ts",wt=String.raw`import { z } from "zod";
2
+ import{readFileSync as pa}from"fs";import wt from"path";import{fileURLToPath as ma}from"url";import{Command as ua}from"commander";import St from"picocolors";import{spawn as jo}from"child_process";import re from"fs/promises";import ne from"path";import{confirm as Io,isCancel as To,spinner as nt}from"@clack/prompts";import P from"picocolors";import ye from"path";var kt=(e,t)=>t.architecture!=="feature"?e:e.replace(/from ["']@\/lib\/utils\/cn["']/g,'from "@/shared/lib/utils/cn"').replace(/from ["']@\/components\/base\//g,'from "@/shared/components/base/'),Pt=[["components/base/",e=>e.paths.components],["views/",e=>e.paths.views],["hooks/",e=>e.paths.hooks],["lib/",e=>e.paths.lib]],O=(e,t)=>e.files.filter(o=>typeof o.content=="string").map(o=>{let a=Pt.find(([r])=>o.path.startsWith(r)),n=a?ye.posix.join(a[1](t),o.path.slice(a[0].length)):ye.posix.join(t.paths.components,ye.posix.basename(o.path));return o.encoding==="base64"?{relPath:n,content:o.content,encoding:"base64"}:{relPath:n,content:kt(o.content,t)}});import{execFileSync as Ze,spawnSync as ke}from"child_process";import{confirm as bo,isCancel as wo,spinner as So}from"@clack/prompts";import W from"picocolors";import S from"fs/promises";import k from"path";import{format as Qt,resolveConfig as Xt}from"prettier";import J from"fs/promises";import Et from"os";import A from"path";import{fileURLToPath as Ct}from"url";var Me="@lexydesign/registry",q=`https://cdn.jsdelivr.net/npm/${Me}`,jt=8e3,ee=A.resolve(A.dirname(Ct(import.meta.url)),"../assets"),It=A.join(Et.homedir(),".cache","create-lexy","registry"),Z=async e=>{let t=await fetch(e,{signal:AbortSignal.timeout(jt)});if(!t.ok){let o=new Error(`HTTP ${t.status} al pedir ${e}`);throw o.status=t.status,o}return await t.json()},$e=async e=>{try{return JSON.parse(await J.readFile(A.join(ee,"r",e),"utf-8"))}catch{return null}},fe=async()=>{try{return(await J.readFile(A.join(ee,"registry-version"),"utf-8")).trim()}catch{return"bundle"}},V=null,te=async()=>{if(V)return V;try{V=(await Z(`https://registry.npmjs.org/${Me}/latest`)).version}catch{try{V=(await Z(`${q}@latest/package.json`)).version}catch{V=await fe()}}return V},C=async(e,t)=>{let o=e.replace(/^@lexy\//,""),a=t??await te(),n=A.join(It,a,`${o}.json`);try{return{item:JSON.parse(await J.readFile(n,"utf-8")),version:a,source:"cache"}}catch{}try{let r=await Z(`${q}@${a}/r/${o}.json`);return await J.mkdir(A.dirname(n),{recursive:!0}),await J.writeFile(n,JSON.stringify(r)),{item:r,version:a,source:"cdn"}}catch(r){if(r.status===404)throw new Error(`El componente "${o}" no existe en el registry (versi\xF3n ${a}). Mira el cat\xE1logo con \`create-lexy view --list\`.`);let i=await $e(`${o}.json`);if(i)return{item:i,version:await fe(),source:"bundle"};throw new Error(`No se pudo alcanzar el registry (\xBFsin red?) y "${o}" tampoco est\xE1 en el bundle local del CLI.`)}},oe=async()=>{try{let e=await te();return{index:await Z(`${q}@${e}/r/registry.json`),version:e,source:"cdn"}}catch{let e=await $e("registry.json");if(e)return{index:e,version:await fe(),source:"bundle"};throw new Error("No se pudo alcanzar el registry ni leer el bundle local del CLI.")}},Fe=A.join(ee,"theme/lexy-theme.css"),Ve=A.join(ee,"fonts");import qe from"fs/promises";import Ue from"path";var ge="src/prototype/data-contract/prototype-data-contract.ts",Tt="src/prototype/data-contract/data-contract-schema.ts",Nt="scripts/check-data-contract.ts",Rt=String.raw`import { z } from "zod";
25
3
 
26
4
  const camelCaseIdSchema = z
27
5
  .string()
@@ -430,7 +408,7 @@ export function definePrototypeDataContract(
430
408
  ): PrototypeDataContract {
431
409
  return prototypeDataContractSchema.parse(contract);
432
410
  }
433
- `,St=String.raw`import { ZodError } from "zod";
411
+ `,_t=String.raw`import { ZodError } from "zod";
434
412
 
435
413
  import { prototypeDataContractSchema } from "../src/prototype/data-contract/data-contract-schema";
436
414
 
@@ -491,7 +469,7 @@ try {
491
469
  }
492
470
  process.exitCode = 1;
493
471
  }
494
- `,kt=e=>`import { definePrototypeDataContract } from "./data-contract-schema";
472
+ `,Ot=e=>`import { definePrototypeDataContract } from "./data-contract-schema";
495
473
 
496
474
  /**
497
475
  * Fuente de verdad de los datos usados por el prototipo.
@@ -509,9 +487,9 @@ export const prototypeDataContract = definePrototypeDataContract({
509
487
  relations: [],
510
488
  projections: {},
511
489
  });
512
- `,ze=async(e,t)=>{let o=async(a,n)=>{let r=De.join(e,a);await Le.mkdir(De.dirname(r),{recursive:!0}),await Le.writeFile(r,n)};await o(ht,wt),await o(re,kt(t)),await o(bt,St)};import Me from"fs/promises";import ie from"path";var se="src/prototype/designer-panel/designer-activity.ts",le="src/prototype/designer-panel/PrototypeDesignerPanel.tsx",Et=String.raw`export type DesignerActivityRecordInput = {
490
+ `,Ke=async(e,t)=>{let o=async(a,n)=>{let r=Ue.join(e,a);await qe.mkdir(Ue.dirname(r),{recursive:!0}),await qe.writeFile(r,n)};await o(Tt,Rt),await o(ge,Ot(t)),await o(Nt,_t)};import He from"fs/promises";import xe from"path";var he="src/prototype/designer-panel/designer-activity.ts",ve="src/prototype/designer-panel/PrototypeDesignerPanel.tsx",At=String.raw`export type DesignerActivityRecordInput = {
513
491
  kind: "load" | "event";
514
- label: string;
492
+ label?: string;
515
493
  technicalId?: string;
516
494
  triggerId?: string;
517
495
  input?: unknown;
@@ -604,7 +582,7 @@ export const createDesignerActivityStore = (maxItems = 80): DesignerActivityStor
604
582
  id: tabId + "_" + sequence,
605
583
  occurredAt: new Date().toISOString(),
606
584
  kind: input.kind,
607
- label: input.label,
585
+ label: input.label ?? input.technicalId ?? "evento",
608
586
  ...(input.technicalId ? { technicalId: input.technicalId } : {}),
609
587
  ...(input.triggerId ? { triggerId: input.triggerId } : {}),
610
588
  ...(preview(input.input) ? { inputPreview: preview(input.input) } : {}),
@@ -621,41 +599,73 @@ export const createDesignerActivityStore = (maxItems = 80): DesignerActivityStor
621
599
  };
622
600
 
623
601
  export const designerActivity = createDesignerActivityStore();
624
- `,Pt=`
602
+ `,Lt=`
625
603
  .lexy-dp {
626
604
  --dp-bg: #ffffff;
627
- --dp-fg: #242424;
628
- --dp-card: #fafafa;
605
+ --dp-fg: #0f172a;
606
+ --dp-card: #ffffff;
629
607
  --dp-popover: #ffffff;
630
- --dp-primary: #4648d4;
608
+ --dp-primary: #4f46e5;
631
609
  --dp-primary-fg: #ffffff;
632
- --dp-muted: #f5f5f5;
633
- --dp-muted-fg: #616161;
634
- --dp-accent: #ebf3fc;
635
- --dp-accent-fg: #4648d4;
636
- --dp-border: #d1d1d1;
637
- --dp-ring: #4648d4;
638
- --dp-destructive: #d13438;
639
- --dp-success: #107c10;
610
+ --dp-muted: #f8fafc;
611
+ --dp-muted-fg: #475569;
612
+ --dp-accent: #e0e7ff;
613
+ --dp-accent-fg: #4f46e5;
614
+ --dp-border: #e2e8f0;
615
+ --dp-ring: #c7d2fe;
616
+ --dp-destructive: #ef4444;
617
+ --dp-success: #10b981;
640
618
  --dp-success-fg: #ffffff;
641
- --dp-warning: #f7630c;
619
+ --dp-warning: #f59e0b;
642
620
  --dp-warning-fg: #ffffff;
643
- --dp-info: #0f6cbd;
644
- --dp-radius: 0.5rem;
645
- --dp-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
646
- --dp-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
621
+ --dp-info: #0ea5e9;
622
+ --dp-radius: 8px;
623
+ --dp-mono: "Geist Mono", SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
624
+ --dp-sans: "Geist Sans", system-ui, -apple-system, sans-serif;
647
625
  color: var(--dp-fg);
648
626
  font-family: var(--dp-sans);
649
- font-size: 14px;
650
- line-height: 1.4;
627
+ font-size: 13.5px;
628
+ line-height: 1.5;
651
629
  }
652
630
  .lexy-dp *, .lexy-dp *::before, .lexy-dp *::after { box-sizing: border-box; }
653
631
  .lexy-dp p, .lexy-dp h1, .lexy-dp pre, .lexy-dp ul { margin: 0; }
654
632
  .lexy-dp ul { list-style: none; padding: 0; }
655
- .lexy-dp button { font-family: inherit; color: inherit; }
633
+ .lexy-dp button { font-family: inherit; color: inherit; border: none; background: transparent; cursor: pointer; outline: none; }
656
634
  .lexy-dp code { font-family: var(--dp-mono); }
657
635
 
658
- /* \u2500\u2500 P\xE1gina completa \u2500\u2500 */
636
+ /* Custom Scrollbars */
637
+ .lexy-dp .lexy-dp-scroll::-webkit-scrollbar,
638
+ .lexy-dp .lexy-dp-split__list::-webkit-scrollbar,
639
+ .lexy-dp .lexy-dp-split__detail::-webkit-scrollbar,
640
+ .lexy-dp .lexy-dp-sheet__body::-webkit-scrollbar,
641
+ .lexy-dp .lexy-dp-snippet::-webkit-scrollbar {
642
+ width: 6px;
643
+ height: 6px;
644
+ }
645
+ .lexy-dp .lexy-dp-scroll::-webkit-scrollbar-track,
646
+ .lexy-dp .lexy-dp-split__list::-webkit-scrollbar-track,
647
+ .lexy-dp .lexy-dp-split__detail::-webkit-scrollbar-track,
648
+ .lexy-dp .lexy-dp-sheet__body::-webkit-scrollbar-track,
649
+ .lexy-dp .lexy-dp-snippet::-webkit-scrollbar-track {
650
+ background: transparent;
651
+ }
652
+ .lexy-dp .lexy-dp-scroll::-webkit-scrollbar-thumb,
653
+ .lexy-dp .lexy-dp-split__list::-webkit-scrollbar-thumb,
654
+ .lexy-dp .lexy-dp-split__detail::-webkit-scrollbar-thumb,
655
+ .lexy-dp .lexy-dp-sheet__body::-webkit-scrollbar-thumb,
656
+ .lexy-dp .lexy-dp-snippet::-webkit-scrollbar-thumb {
657
+ background: rgba(0, 0, 0, 0.12);
658
+ border-radius: 9999px;
659
+ }
660
+ .lexy-dp .lexy-dp-scroll::-webkit-scrollbar-thumb:hover,
661
+ .lexy-dp .lexy-dp-split__list::-webkit-scrollbar-thumb:hover,
662
+ .lexy-dp .lexy-dp-split__detail::-webkit-scrollbar-thumb:hover,
663
+ .lexy-dp .lexy-dp-sheet__body::-webkit-scrollbar-thumb:hover,
664
+ .lexy-dp .lexy-dp-snippet::-webkit-scrollbar-thumb:hover {
665
+ background: rgba(0, 0, 0, 0.24);
666
+ }
667
+
668
+ /* \u2500\u2500 Full Page \u2500\u2500 */
659
669
  .lexy-dp-page {
660
670
  display: flex;
661
671
  flex-direction: column;
@@ -668,73 +678,99 @@ export const designerActivity = createDesignerActivityStore();
668
678
  display: flex;
669
679
  align-items: stretch;
670
680
  border-bottom: 1px solid var(--dp-border);
671
- padding: 0 12px;
672
- background: var(--dp-bg);
681
+ padding: 0 16px;
682
+ background: #ffffff;
683
+ gap: 8px;
673
684
  }
674
685
  .lexy-dp-tab {
675
686
  display: inline-flex;
676
687
  align-items: center;
677
- gap: 6px;
678
- padding: 8px 12px;
679
- font-size: 12px;
680
- border: none;
688
+ gap: 8px;
689
+ padding: 12px 14px;
690
+ font-size: 13px;
681
691
  border-bottom: 2px solid transparent;
682
692
  margin-bottom: -1px;
683
- background: transparent;
684
693
  color: var(--dp-muted-fg);
685
- border-radius: 0;
686
- cursor: pointer;
694
+ font-weight: 500;
695
+ transition: all 0.2s ease;
687
696
  }
688
697
  .lexy-dp-tab:hover { color: var(--dp-fg); }
689
- .lexy-dp-tab.is-active { color: var(--dp-primary); font-weight: 500; border-bottom-color: var(--dp-primary); }
690
- .lexy-dp-tab svg { width: 14px; height: 14px; }
698
+ .lexy-dp-tab.is-active {
699
+ color: var(--dp-primary);
700
+ font-weight: 600;
701
+ border-bottom-color: var(--dp-primary);
702
+ }
703
+ .lexy-dp-tab svg { width: 15px; height: 15px; opacity: 0.8; }
704
+ .lexy-dp-tab.is-active svg { opacity: 1; color: var(--dp-primary); }
705
+
691
706
  .lexy-dp-tabbadge {
692
707
  margin-left: 4px;
693
708
  border-radius: 9999px;
694
709
  background: var(--dp-warning);
695
710
  color: var(--dp-warning-fg);
696
- padding: 0 6px;
711
+ padding: 1px 6px;
697
712
  font-size: 10px;
698
- font-weight: 500;
713
+ font-weight: 600;
699
714
  }
700
715
  .lexy-dp-body { flex: 1; min-height: 0; }
701
716
  .lexy-dp-panel { height: 100%; }
702
717
 
703
- /* \u2500\u2500 Scroll y padding \u2500\u2500 */
718
+ /* \u2500\u2500 Scroll & Padding \u2500\u2500 */
704
719
  .lexy-dp-scroll { height: 100%; overflow-y: auto; }
705
- .lexy-dp-pad { padding: 20px 24px; }
720
+ .lexy-dp-pad { padding: 24px; }
706
721
 
707
- /* \u2500\u2500 Columna y toolbar \u2500\u2500 */
722
+ /* \u2500\u2500 Column & Toolbar \u2500\u2500 */
708
723
  .lexy-dp-col { display: flex; flex-direction: column; height: 100%; }
709
724
  .lexy-dp-toolbar {
710
725
  display: flex;
711
726
  align-items: center;
712
- gap: 4px;
727
+ gap: 8px;
713
728
  border-bottom: 1px solid var(--dp-border);
714
- background: var(--dp-bg);
715
- padding: 4px 8px;
729
+ background: #f8fafc;
730
+ padding: 8px 16px;
716
731
  }
717
732
 
718
- /* \u2500\u2500 Botones \u2500\u2500 */
733
+ /* \u2500\u2500 Buttons \u2500\u2500 */
719
734
  .lexy-dp-btn {
720
735
  display: inline-flex;
721
736
  align-items: center;
722
737
  justify-content: center;
723
- gap: 6px;
724
- padding: 6px 12px;
738
+ gap: 8px;
739
+ padding: 8px 16px;
725
740
  font-size: 13px;
741
+ font-weight: 500;
726
742
  border-radius: var(--dp-radius);
727
743
  border: 1px solid transparent;
728
744
  background: var(--dp-primary);
729
745
  color: var(--dp-primary-fg);
730
- cursor: pointer;
746
+ box-shadow: 0 1px 2px rgba(79, 70, 229, 0.1);
747
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
748
+ }
749
+ .lexy-dp-btn:hover {
750
+ opacity: 0.95;
751
+ transform: translateY(-1px);
752
+ box-shadow: 0 4px 8px rgba(79, 70, 229, 0.15);
753
+ }
754
+ .lexy-dp-btn:active { transform: translateY(0); }
755
+ .lexy-dp-btn:disabled {
756
+ opacity: 0.4;
757
+ cursor: not-allowed;
758
+ transform: none !important;
759
+ box-shadow: none !important;
760
+ }
761
+ .lexy-dp-btn--outline {
762
+ background: transparent;
763
+ border-color: var(--dp-border);
764
+ color: var(--dp-fg);
765
+ box-shadow: none;
766
+ }
767
+ .lexy-dp-btn--outline:hover {
768
+ background: var(--dp-muted);
769
+ border-color: var(--dp-border);
770
+ box-shadow: none;
731
771
  }
732
- .lexy-dp-btn:hover { opacity: 0.92; }
733
- .lexy-dp-btn:disabled { opacity: 0.5; cursor: not-allowed; }
734
- .lexy-dp-btn--outline { background: transparent; border-color: var(--dp-border); color: var(--dp-fg); }
735
- .lexy-dp-btn--outline:hover { background: var(--dp-muted); opacity: 1; }
736
772
  .lexy-dp-btn--outline:disabled:hover { background: transparent; }
737
- .lexy-dp-btn--sm { padding: 4px 10px; font-size: 12px; }
773
+ .lexy-dp-btn--sm { padding: 5px 12px; font-size: 12px; }
738
774
  .lexy-dp-btn svg { width: 14px; height: 14px; }
739
775
 
740
776
  /* \u2500\u2500 Badges \u2500\u2500 */
@@ -742,218 +778,376 @@ export const designerActivity = createDesignerActivityStore();
742
778
  display: inline-flex;
743
779
  align-items: center;
744
780
  border-radius: 9999px;
745
- padding: 1px 8px;
781
+ padding: 2px 10px;
746
782
  font-size: 11px;
747
- font-weight: 500;
783
+ font-weight: 600;
748
784
  border: 1px solid transparent;
749
- background: var(--dp-primary);
750
- color: var(--dp-primary-fg);
785
+ background: rgba(79, 70, 229, 0.08);
786
+ color: var(--dp-primary);
751
787
  white-space: nowrap;
752
788
  }
753
- .lexy-dp-badge--outline { background: var(--dp-muted); color: var(--dp-muted-fg); border-color: var(--dp-border); }
754
- .lexy-dp-badge--success { background: var(--dp-success); color: var(--dp-success-fg); }
755
- .lexy-dp-badge--warning { background: var(--dp-warning); color: var(--dp-warning-fg); }
789
+ .lexy-dp-badge--outline {
790
+ background: var(--dp-muted);
791
+ color: var(--dp-muted-fg);
792
+ border-color: var(--dp-border);
793
+ }
794
+ .lexy-dp-badge--success {
795
+ background: rgba(16, 185, 129, 0.1);
796
+ color: #047857;
797
+ }
798
+ .lexy-dp-badge--warning {
799
+ background: rgba(245, 158, 11, 0.1);
800
+ color: #b45309;
801
+ }
756
802
 
757
803
  /* \u2500\u2500 Cards \u2500\u2500 */
758
804
  .lexy-dp-card {
759
805
  border: 1px solid var(--dp-border);
760
806
  background: var(--dp-card);
761
807
  border-radius: var(--dp-radius);
762
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
763
- padding: 12px 14px;
808
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
809
+ padding: 16px;
810
+ transition: all 0.2s ease;
764
811
  }
765
- .lexy-dp-card__title { font-size: 14px; font-weight: 600; }
766
- .lexy-dp-card__desc { font-size: 13px; color: var(--dp-muted-fg); margin-top: 2px; }
767
- .lexy-dp-card__content { margin-top: 10px; }
812
+ .lexy-dp-card:hover {
813
+ border-color: rgba(79, 70, 229, 0.2);
814
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
815
+ }
816
+ .lexy-dp-card__title { font-size: 14.5px; font-weight: 600; color: var(--dp-fg); }
817
+ .lexy-dp-card__desc { font-size: 12.5px; color: var(--dp-muted-fg); margin-top: 4px; line-height: 1.4; }
818
+ .lexy-dp-card__content { margin-top: 14px; }
768
819
  .lexy-dp-card__head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
769
820
 
770
821
  /* \u2500\u2500 Searchbox \u2500\u2500 */
771
822
  .lexy-dp-search { position: relative; display: flex; align-items: center; flex: 1; }
772
823
  .lexy-dp-search input {
773
824
  width: 100%;
774
- padding: 3px 26px 3px 8px;
775
- font-size: 12px;
825
+ padding: 6px 30px 6px 12px;
826
+ font-size: 12.5px;
776
827
  font-family: inherit;
777
828
  border: 1px solid var(--dp-border);
778
- border-radius: 3px;
779
- background: var(--dp-bg);
829
+ border-radius: 6px;
830
+ background: #ffffff;
780
831
  color: var(--dp-fg);
832
+ transition: all 0.2s ease;
833
+ }
834
+ .lexy-dp-search input:focus {
835
+ outline: none;
836
+ border-color: var(--dp-primary);
837
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
781
838
  }
782
- .lexy-dp-search input:focus { outline: 2px solid var(--dp-ring); outline-offset: -1px; }
783
839
  .lexy-dp-search__clear {
784
840
  position: absolute;
785
- right: 6px;
841
+ right: 10px;
786
842
  border: none;
787
843
  background: transparent;
788
844
  color: var(--dp-muted-fg);
789
845
  cursor: pointer;
790
846
  padding: 2px;
791
847
  display: inline-flex;
848
+ transition: color 0.15s ease;
792
849
  }
850
+ .lexy-dp-search__clear:hover { color: var(--dp-fg); }
793
851
  .lexy-dp-search__clear svg { width: 14px; height: 14px; }
794
852
 
795
- /* \u2500\u2500 Snippet / separador / etiquetas \u2500\u2500 */
853
+ /* \u2500\u2500 Snippet \u2500\u2500 */
796
854
  .lexy-dp-snippet {
797
855
  font-family: var(--dp-mono);
798
856
  font-size: 12px;
799
- background: var(--dp-muted);
857
+ background: #f8fafc;
800
858
  border: 1px solid var(--dp-border);
801
859
  border-radius: var(--dp-radius);
802
- padding: 10px 12px;
860
+ padding: 12px 14px;
803
861
  overflow: auto;
804
862
  white-space: pre;
805
- color: var(--dp-fg);
863
+ color: #334155;
806
864
  }
807
- .lexy-dp-sep { border: none; border-top: 1px solid var(--dp-border); height: 1px; }
865
+ .lexy-dp-sep { border: none; border-top: 1px solid var(--dp-border); height: 1px; margin: 20px 0; }
808
866
  .lexy-dp-section-label {
809
- font-size: 12px;
810
- font-weight: 500;
867
+ font-size: 11.5px;
868
+ font-weight: 600;
811
869
  text-transform: uppercase;
812
- letter-spacing: 0.04em;
813
- color: var(--dp-muted-fg);
870
+ letter-spacing: 0.05em;
871
+ color: #64748b;
872
+ margin-bottom: 8px;
814
873
  }
815
874
  .lexy-dp-muted { color: var(--dp-muted-fg); }
816
875
  .lexy-dp-mono { font-family: var(--dp-mono); }
817
- .lexy-dp-empty { padding: 16px 12px; color: var(--dp-muted-fg); font-size: 13px; }
876
+ .lexy-dp-empty { padding: 24px 16px; color: var(--dp-muted-fg); font-size: 13px; text-align: center; }
818
877
 
819
- .lexy-dp-log__event { color: var(--dp-fg); }
878
+ .lexy-dp-log__event { color: var(--dp-fg); font-weight: 600; }
820
879
 
821
- /* \u2500\u2500 Stacks y grids \u2500\u2500 */
822
- .lexy-dp-stack { display: flex; flex-direction: column; gap: 2px; }
823
- .lexy-dp-stack-sm { display: flex; flex-direction: column; gap: 6px; }
824
- .lexy-dp-stack-lg { display: flex; flex-direction: column; gap: 12px; }
825
- .lexy-dp-substack { display: flex; flex-direction: column; gap: 2px; padding-left: 16px; color: var(--dp-muted-fg); }
826
- .lexy-dp-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
880
+ /* \u2500\u2500 Stacks & Grids \u2500\u2500 */
881
+ .lexy-dp-stack { display: flex; flex-direction: column; gap: 4px; }
882
+ .lexy-dp-stack-sm { display: flex; flex-direction: column; gap: 8px; }
883
+ .lexy-dp-stack-lg { display: flex; flex-direction: column; gap: 16px; }
884
+ .lexy-dp-substack { display: flex; flex-direction: column; gap: 4px; padding-left: 18px; color: var(--dp-muted-fg); }
885
+ .lexy-dp-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
827
886
 
828
- /* \u2500\u2500 \xC1rbol JSON \u2500\u2500 */
829
- .lexy-dp-json-str { color: var(--dp-fg); }
830
- .lexy-dp-json-num { color: var(--dp-info); }
831
- .lexy-dp-json-row { display: flex; align-items: flex-start; gap: 4px; padding: 1px 0; }
887
+ /* \u2500\u2500 JSON Tree \u2500\u2500 */
888
+ .lexy-dp-json-str { color: #047857; } /* Emerald green */
889
+ .lexy-dp-json-num { color: #0284c7; } /* Sky blue */
890
+ .lexy-dp-json-row { display: flex; align-items: flex-start; gap: 6px; padding: 2px 0; }
832
891
  .lexy-dp-json-spacer { width: 14px; height: 14px; flex-shrink: 0; }
833
892
  .lexy-dp-json-leaf { min-width: 0; word-break: break-word; }
834
893
  .lexy-dp-json-toggle {
835
894
  display: flex;
836
895
  width: 100%;
837
896
  align-items: flex-start;
838
- gap: 4px;
839
- padding: 1px 0;
897
+ gap: 6px;
898
+ padding: 3px 6px;
840
899
  text-align: left;
841
900
  background: transparent;
842
- border: none;
843
- cursor: pointer;
901
+ border-radius: 4px;
902
+ transition: background 0.15s ease;
844
903
  }
845
- .lexy-dp-json-toggle:hover { background: var(--dp-muted); }
846
- .lexy-dp-chevron { width: 14px; height: 14px; flex-shrink: 0; color: var(--dp-muted-fg); margin-top: 1px; }
847
- .lexy-dp-chevron--sm { width: 12px; height: 12px; margin-top: 0; }
848
- .lexy-dp-chevron.is-open { transform: rotate(90deg); }
904
+ .lexy-dp-json-toggle:hover { background: rgba(0, 0, 0, 0.03); }
905
+ .lexy-dp-chevron { width: 14px; height: 14px; flex-shrink: 0; color: var(--dp-muted-fg); margin-top: 2px; transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1); }
906
+ .lexy-dp-chevron--sm { width: 12px; height: 12px; margin-top: 1px; }
907
+ .lexy-dp-chevron.is-open { transform: rotate(90deg); color: var(--dp-fg); }
849
908
 
850
- /* \u2500\u2500 Log de actividad \u2500\u2500 */
909
+ /* \u2500\u2500 Activity Log \u2500\u2500 */
851
910
  .lexy-dp-activitylog {
852
911
  min-height: 100%;
853
912
  background: var(--dp-bg);
854
- padding: 4px 0;
913
+ padding: 8px 0;
855
914
  font-family: var(--dp-mono);
856
- font-size: 12px;
857
- line-height: 1.5;
915
+ font-size: 12.5px;
916
+ line-height: 1.6;
858
917
  color: var(--dp-fg);
859
918
  }
860
919
  .lexy-dp-activitylog--scroll { flex: 1; min-height: 0; overflow-y: auto; }
861
- .lexy-dp-log { border-bottom: 1px solid var(--dp-border); }
920
+ .lexy-dp-log {
921
+ border-bottom: 1px solid var(--dp-border);
922
+ transition: background 0.15s ease;
923
+ }
924
+ .lexy-dp-log:hover {
925
+ background: rgba(0, 0, 0, 0.005);
926
+ }
862
927
  .lexy-dp-log__head {
863
928
  display: flex;
864
929
  width: 100%;
865
930
  align-items: center;
866
- gap: 6px;
867
- padding: 4px 8px;
931
+ gap: 8px;
932
+ padding: 10px 16px;
868
933
  text-align: left;
869
934
  background: transparent;
870
- border: none;
871
935
  cursor: pointer;
936
+ transition: background 0.15s ease;
937
+ }
938
+ .lexy-dp-log__head:hover { background: rgba(0, 0, 0, 0.03); }
939
+ .lexy-dp-log__time { margin-left: auto; flex-shrink: 0; color: var(--dp-muted-fg); font-size: 11px; }
940
+ .lexy-dp-log__body {
941
+ padding: 8px 16px 12px 16px;
942
+ background: #f8fafc;
943
+ border-top: 1px solid rgba(0, 0, 0, 0.03);
872
944
  }
873
- .lexy-dp-log__head:hover { background: var(--dp-muted); }
874
- .lexy-dp-log__time { margin-left: auto; flex-shrink: 0; color: var(--dp-muted-fg); }
875
- .lexy-dp-log__body { padding-bottom: 6px; }
876
-
877
- /* \u2500\u2500 Detalle (event/entity detail) \u2500\u2500 */
878
- .lexy-dp-eventdetail { display: flex; flex-direction: column; font-size: 12px; line-height: 1.5; }
879
- .lexy-dp-detail-body { padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; }
880
- .lexy-dp-detail-field { display: flex; gap: 4px; font-family: var(--dp-mono); font-size: 12px; }
881
- .lexy-dp-detail-label { color: var(--dp-muted-fg); flex-shrink: 0; }
882
- .lexy-dp-detail-label::after { content: ":"; }
883
-
884
- /* \u2500\u2500 Triggers list \u2500\u2500 */
885
- .lexy-dp-trigger-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; }
886
- .lexy-dp-trigger-item { display: flex; gap: 8px; align-items: baseline; }
887
- .lexy-dp-bullet { color: var(--dp-primary); font-weight: 700; flex-shrink: 0; }
888
-
889
945
 
890
- /* \u2500\u2500 Split (lista + detalle) \u2500\u2500 */
946
+ /* \u2500\u2500 Split (Master-Detail) \u2500\u2500 */
891
947
  .lexy-dp-split { display: flex; height: 100%; }
892
948
  .lexy-dp-split__list {
893
949
  width: 288px;
894
950
  flex-shrink: 0;
895
951
  overflow-y: auto;
896
952
  border-right: 1px solid var(--dp-border);
897
- padding: 8px 0;
953
+ padding: 12px 0;
898
954
  display: flex;
899
955
  flex-direction: column;
900
- gap: 1px;
956
+ background: #f8fafc; /* sidebar light gray background */
901
957
  }
902
958
  .lexy-dp-list-section {
903
959
  display: flex;
904
960
  align-items: center;
905
961
  justify-content: space-between;
906
962
  width: 100%;
907
- padding: 5px 10px;
908
- font-size: 12px;
909
- font-weight: 500;
910
- color: var(--dp-fg);
911
- background: var(--dp-muted);
963
+ padding: 10px 16px;
964
+ font-size: 11px;
965
+ font-weight: 700;
966
+ letter-spacing: 0.05em;
967
+ color: #475569;
968
+ text-transform: uppercase;
969
+ background: transparent;
912
970
  border: none;
913
- border-top: 1px solid var(--dp-border);
914
- border-bottom: 1px solid var(--dp-border);
915
971
  cursor: pointer;
916
972
  font-family: inherit;
917
973
  text-align: left;
974
+ margin-top: 8px;
918
975
  }
919
- .lexy-dp-list-section:hover { background: var(--dp-border); }
976
+ .lexy-dp-list-section:first-of-type { margin-top: 0; }
920
977
  .lexy-dp-listitem {
921
- width: 100%;
978
+ width: calc(100% - 16px);
979
+ margin: 2px 8px;
922
980
  text-align: left;
923
981
  border: none;
924
982
  background: transparent;
925
- border-radius: 0;
926
- padding: 5px 12px;
983
+ padding: 7px 12px;
927
984
  font-family: var(--dp-mono);
928
985
  font-size: 12px;
929
- color: var(--dp-fg);
986
+ color: #334155;
930
987
  cursor: pointer;
931
988
  white-space: nowrap;
932
989
  overflow: hidden;
933
990
  text-overflow: ellipsis;
991
+ border-radius: 6px;
992
+ transition: all 0.15s ease;
993
+ }
994
+ .lexy-dp-listitem:hover { background: rgba(0, 0, 0, 0.03); color: var(--dp-fg); }
995
+ .lexy-dp-listitem.is-active {
996
+ background: rgba(79, 70, 229, 0.08);
997
+ color: var(--dp-primary);
998
+ font-weight: 600;
999
+ }
1000
+ .lexy-dp-split__detail {
1001
+ flex: 1;
1002
+ min-width: 0;
1003
+ min-height: 0;
1004
+ overflow-y: auto;
1005
+ padding: 0;
1006
+ background: #ffffff; /* details pure white background */
1007
+ }
1008
+
1009
+ /* \u2500\u2500 Detalle (Event / Load / Entity Detail Layout) \u2500\u2500 */
1010
+ .lexy-dp-eventdetail { display: flex; flex-direction: column; font-size: 13.5px; line-height: 1.6; }
1011
+
1012
+ /* The first detail body acts as the HERO banner of the selected item */
1013
+ .lexy-dp-eventdetail .lexy-dp-detail-body:first-of-type {
1014
+ background: #f8fafc;
1015
+ border-bottom: 1px solid var(--dp-border);
1016
+ padding: 24px;
1017
+ display: flex;
1018
+ flex-direction: column;
1019
+ gap: 16px;
1020
+ margin-bottom: 12px;
1021
+ }
1022
+ /* Reorganize field rows inside the HERO banner */
1023
+ .lexy-dp-eventdetail .lexy-dp-detail-body:first-of-type .lexy-dp-detail-field {
1024
+ display: flex;
1025
+ flex-direction: column;
1026
+ align-items: flex-start;
1027
+ gap: 4px;
1028
+ }
1029
+ /* Hide default "Nombre" label since it's redundant */
1030
+ .lexy-dp-eventdetail .lexy-dp-detail-body:first-of-type .lexy-dp-detail-field:first-of-type .lexy-dp-detail-label {
1031
+ display: none;
1032
+ }
1033
+ /* Title of the hero banner (technical ID) */
1034
+ .lexy-dp-eventdetail .lexy-dp-detail-body:first-of-type .lexy-dp-detail-field:first-of-type span:not(.lexy-dp-detail-label) {
1035
+ font-size: 20px;
1036
+ font-weight: 700;
1037
+ color: #0f172a;
1038
+ font-family: var(--dp-sans);
1039
+ }
1040
+ /* Styling other hero banner labels as small headers */
1041
+ .lexy-dp-eventdetail .lexy-dp-detail-body:first-of-type .lexy-dp-detail-field:not(:first-of-type) .lexy-dp-detail-label {
1042
+ font-size: 11px;
1043
+ font-weight: 600;
1044
+ text-transform: uppercase;
1045
+ letter-spacing: 0.05em;
1046
+ color: #64748b;
1047
+ }
1048
+ .lexy-dp-eventdetail .lexy-dp-detail-body:first-of-type .lexy-dp-detail-field:not(:first-of-type) .lexy-dp-detail-label::after {
1049
+ content: "";
1050
+ }
1051
+ /* Text description in the hero banner */
1052
+ .lexy-dp-eventdetail .lexy-dp-detail-body:first-of-type .lexy-dp-detail-field:not(:first-of-type) span:not(.lexy-dp-detail-label) {
1053
+ font-size: 13.5px;
1054
+ color: #475569;
1055
+ font-family: var(--dp-sans);
1056
+ line-height: 1.6;
1057
+ }
1058
+
1059
+ /* Detail sub-bodies (e.g. content underneath sections) */
1060
+ .lexy-dp-eventdetail .lexy-dp-detail-body:not(:first-of-type) {
1061
+ padding: 12px 24px 24px 24px;
1062
+ display: flex;
1063
+ flex-direction: column;
1064
+ gap: 8px;
1065
+ }
1066
+ .lexy-dp-detail-field { display: flex; gap: 8px; font-family: var(--dp-mono); font-size: 12.5px; }
1067
+ .lexy-dp-detail-label { color: var(--dp-muted-fg); flex-shrink: 0; }
1068
+ .lexy-dp-detail-label::after { content: ":"; }
1069
+
1070
+ /* Section Header Buttons inside Detail Page */
1071
+ .lexy-dp-eventdetail > .lexy-dp-list-section {
1072
+ display: flex;
1073
+ align-items: center;
1074
+ justify-content: space-between;
1075
+ width: 100%;
1076
+ padding: 12px 24px;
1077
+ font-size: 13px;
1078
+ font-weight: 600;
1079
+ color: #0f172a;
1080
+ background: #ffffff;
1081
+ border-top: 1px solid var(--dp-border);
1082
+ border-bottom: none;
1083
+ cursor: pointer;
1084
+ font-family: inherit;
1085
+ text-align: left;
1086
+ margin-top: 8px;
1087
+ text-transform: none;
1088
+ letter-spacing: normal;
934
1089
  }
935
- .lexy-dp-listitem:hover { background: var(--dp-muted); }
936
- .lexy-dp-listitem.is-active { background: var(--dp-accent); color: var(--dp-accent-fg); font-weight: 500; }
937
- .lexy-dp-split__detail { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: 0; }
1090
+ .lexy-dp-eventdetail > .lexy-dp-list-section:hover { background: #f8fafc; }
938
1091
 
939
- /* \u2500\u2500 Tabla de campos (devtools) \u2500\u2500 */
940
- .lexy-dp-field-table { width: 100%; border-collapse: collapse; font-family: var(--dp-mono); font-size: 11px; table-layout: fixed; }
941
- .lexy-dp-field-table th { text-align: left; font-weight: 500; color: var(--dp-fg); padding: 3px 8px; background: var(--dp-muted); border-bottom: 1px solid var(--dp-border); border-right: 1px solid var(--dp-border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1092
+ /* \u2500\u2500 Triggers List \u2500\u2500 */
1093
+ .lexy-dp-trigger-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
1094
+ .lexy-dp-trigger-item { display: flex; gap: 8px; align-items: baseline; }
1095
+ .lexy-dp-bullet { color: var(--dp-primary); font-weight: 700; flex-shrink: 0; }
1096
+
1097
+ /* \u2500\u2500 Fields Table (DevTools) \u2500\u2500 */
1098
+ .lexy-dp-field-table {
1099
+ width: 100%;
1100
+ border-collapse: collapse;
1101
+ font-family: var(--dp-mono);
1102
+ font-size: 12px;
1103
+ table-layout: fixed;
1104
+ }
1105
+ .lexy-dp-field-table th {
1106
+ text-align: left;
1107
+ font-weight: 600;
1108
+ color: #475569;
1109
+ padding: 8px 12px;
1110
+ background: #f8fafc;
1111
+ border-bottom: 1px solid var(--dp-border);
1112
+ border-right: 1px solid var(--dp-border);
1113
+ white-space: nowrap;
1114
+ overflow: hidden;
1115
+ text-overflow: ellipsis;
1116
+ font-size: 11px;
1117
+ text-transform: uppercase;
1118
+ letter-spacing: 0.05em;
1119
+ }
942
1120
  .lexy-dp-field-table th:last-child { border-right: none; }
943
- .lexy-dp-field-table td { padding: 2px 8px; border-bottom: 1px solid var(--dp-border); border-right: 1px solid var(--dp-border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top; }
1121
+ .lexy-dp-field-table td {
1122
+ padding: 6px 12px;
1123
+ border-bottom: 1px solid var(--dp-border);
1124
+ border-right: 1px solid var(--dp-border);
1125
+ white-space: nowrap;
1126
+ overflow: hidden;
1127
+ text-overflow: ellipsis;
1128
+ vertical-align: middle;
1129
+ color: #334155;
1130
+ }
944
1131
  .lexy-dp-field-table td:last-child { border-right: none; }
945
- .lexy-dp-field-table tbody tr { cursor: pointer; }
946
- .lexy-dp-field-table tbody tr:hover { background: var(--dp-muted); }
947
- .lexy-dp-field-table tbody tr.is-selected { background: var(--dp-accent); color: var(--dp-accent-fg); }
948
- .lexy-dp-field-table tbody tr.is-selected td { color: var(--dp-accent-fg); }
1132
+ .lexy-dp-field-table tbody tr { cursor: pointer; transition: background 0.15s ease; }
1133
+ .lexy-dp-field-table tbody tr:hover { background: rgba(0, 0, 0, 0.015); }
1134
+ .lexy-dp-field-table tbody tr.is-selected { background: rgba(79, 70, 229, 0.04); }
1135
+ .lexy-dp-field-table tbody tr.is-selected td { color: var(--dp-primary); font-weight: 600; }
949
1136
  .lexy-dp-field-table tbody tr:last-child td { border-bottom: none; }
950
1137
 
951
- /* \u2500\u2500 Launcher flotante \u2500\u2500 */
1138
+ /* Wrapper to round table corners */
1139
+ .lexy-dp-eventdetail .lexy-dp-detail-body > div[style*="overflowX"] {
1140
+ border: 1px solid var(--dp-border);
1141
+ border-radius: 8px;
1142
+ overflow: hidden;
1143
+ }
1144
+
1145
+ /* \u2500\u2500 Floating Launcher \u2500\u2500 */
952
1146
  .lexy-dp-launcher {
953
1147
  position: fixed;
954
- bottom: 16px;
955
- right: 16px;
956
- z-index: 40;
1148
+ bottom: 20px;
1149
+ right: 20px;
1150
+ z-index: 50;
957
1151
  display: flex;
958
1152
  align-items: center;
959
1153
  justify-content: center;
@@ -961,86 +1155,112 @@ export const designerActivity = createDesignerActivityStore();
961
1155
  width: 48px;
962
1156
  gap: 0;
963
1157
  overflow: hidden;
964
- border: none;
1158
+ border: none !important;
965
1159
  border-radius: 9999px;
966
- background: var(--dp-fg);
967
- color: var(--dp-primary-fg);
968
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
1160
+ background: #0f172a !important;
1161
+ color: #ffffff !important;
1162
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15) !important;
969
1163
  cursor: pointer;
970
- padding: 0 12px;
1164
+ padding: 0 14px;
1165
+ transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
1166
+ }
1167
+ .lexy-dp-launcher:hover {
1168
+ width: 176px;
1169
+ gap: 8px;
1170
+ background: #1e293b !important;
1171
+ transform: translateY(-2px);
1172
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
971
1173
  }
972
- .lexy-dp-launcher:hover,
973
- .lexy-dp-launcher:focus-visible,
974
- .lexy-dp-launcher.is-open { width: 176px; gap: 8px; }
975
- .lexy-dp-launcher:focus-visible { outline: 2px solid var(--dp-ring); outline-offset: 2px; }
1174
+ .lexy-dp-launcher.is-open {
1175
+ width: 176px;
1176
+ gap: 8px;
1177
+ background: #0f172a !important;
1178
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
1179
+ }
1180
+ .lexy-dp-launcher.is-open:hover {
1181
+ background: #1e293b !important;
1182
+ }
1183
+ .lexy-dp-launcher:focus-visible { outline: 2px solid var(--dp-primary); outline-offset: 2px; }
976
1184
  .lexy-dp-launcher__icon { width: 20px; height: 20px; flex-shrink: 0; }
977
1185
  .lexy-dp-launcher__label {
978
1186
  overflow: hidden;
979
1187
  white-space: nowrap;
980
1188
  font-size: 13px;
981
- font-weight: 500;
1189
+ font-weight: 600;
982
1190
  max-width: 0;
983
1191
  opacity: 0;
1192
+ transition: max-width 0.3s ease, opacity 0.2s ease;
984
1193
  }
985
1194
  .lexy-dp-launcher:hover .lexy-dp-launcher__label,
986
1195
  .lexy-dp-launcher:focus-visible .lexy-dp-launcher__label,
987
- .lexy-dp-launcher.is-open .lexy-dp-launcher__label { max-width: 160px; opacity: 1; }
1196
+ .lexy-dp-launcher.is-open .lexy-dp-launcher__label { max-width: 130px; opacity: 1; }
988
1197
 
989
- /* \u2500\u2500 Sheet flotante \u2500\u2500 */
1198
+ /* \u2500\u2500 Floating Sheet \u2500\u2500 */
990
1199
  .lexy-dp-sheet {
991
1200
  position: fixed;
992
- bottom: 80px;
993
- right: 16px;
994
- z-index: 40;
1201
+ bottom: 84px;
1202
+ right: 20px;
1203
+ z-index: 50;
995
1204
  display: flex;
996
1205
  flex-direction: column;
997
- height: 70vh;
998
- width: min(100vw - 2rem, 400px);
1206
+ height: 75vh;
1207
+ width: min(100vw - 2.5rem, 460px);
999
1208
  overflow: hidden;
1000
1209
  border: 1px solid var(--dp-border);
1001
1210
  border-radius: 12px;
1002
1211
  background: var(--dp-popover);
1003
1212
  color: var(--dp-fg);
1004
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.25);
1213
+ box-shadow: 0 12px 30px rgba(0, 0, 0, 0.1), 0 4px 10px rgba(0, 0, 0, 0.05);
1214
+ animation: lexy-sheet-slide 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards;
1005
1215
  }
1216
+
1217
+ @keyframes lexy-sheet-slide {
1218
+ from { opacity: 0; transform: translateY(12px) scale(0.98); }
1219
+ to { opacity: 1; transform: translateY(0) scale(1); }
1220
+ }
1221
+
1006
1222
  .lexy-dp-sheet__header {
1007
1223
  display: flex;
1008
1224
  align-items: center;
1009
1225
  justify-content: space-between;
1010
1226
  gap: 12px;
1011
- border-bottom: 1px solid var(--dp-border);
1012
- background: var(--dp-fg);
1013
- padding: 12px 16px;
1014
- color: var(--dp-primary-fg);
1227
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
1228
+ background: #0f172a;
1229
+ padding: 14px 18px;
1230
+ color: #ffffff;
1015
1231
  }
1016
- .lexy-dp-sheet__title { font-size: 14px; font-weight: 500; }
1017
- .lexy-dp-sheet__actions { display: flex; align-items: center; gap: 4px; }
1232
+ .lexy-dp-sheet__title { font-size: 14.5px; font-weight: 700; letter-spacing: -0.01em; }
1233
+ .lexy-dp-sheet__actions { display: flex; align-items: center; gap: 6px; }
1018
1234
  .lexy-dp-iconbtn {
1019
1235
  display: flex;
1020
- height: 28px;
1021
- width: 28px;
1236
+ height: 30px;
1237
+ width: 30px;
1022
1238
  align-items: center;
1023
1239
  justify-content: center;
1024
1240
  border: none;
1025
1241
  background: transparent;
1026
1242
  border-radius: 6px;
1027
- opacity: 0.7;
1243
+ opacity: 0.6;
1244
+ color: #ffffff;
1028
1245
  cursor: pointer;
1246
+ transition: all 0.15s ease;
1029
1247
  }
1030
- .lexy-dp-iconbtn:hover { opacity: 1; }
1031
- .lexy-dp-iconbtn svg { width: 16px; height: 16px; }
1248
+ .lexy-dp-iconbtn:hover { opacity: 1; background: rgba(255, 255, 255, 0.1); color: #ffffff; }
1249
+ .lexy-dp-iconbtn svg { width: 15px; height: 15px; }
1032
1250
  .lexy-dp-sheet__body { flex: 1; min-height: 0; overflow-y: auto; background: var(--dp-bg); }
1033
- `,jt=()=>String.raw`import {
1251
+ `,Dt=()=>String.raw`import {
1034
1252
  Activity,
1035
1253
  ArrowUpRight,
1036
1254
  ChevronRight,
1255
+ Eye,
1256
+ EyeOff,
1037
1257
  Maximize2,
1038
1258
  Settings,
1039
1259
  Trash2,
1040
1260
  X,
1041
1261
  Zap,
1042
1262
  } from "lucide-react";
1043
- import { useState, useSyncExternalStore } from "react";
1263
+ import { useState, useEffect, useSyncExternalStore } from "react";
1044
1264
 
1045
1265
  import { prototypeDataContract } from "../data-contract/prototype-data-contract";
1046
1266
  import {
@@ -1054,7 +1274,7 @@ import { designerActivity } from "./designer-activity";
1054
1274
  // Panel autocontenido: trae su propio CSS scopeado (.lexy-dp) y no depende del
1055
1275
  // tema Tailwind del proyecto host ni de componentes del registry. Así se puede
1056
1276
  // previsualizar e iterar el diseño en cualquier entorno.
1057
- const PANEL_STYLES = ${JSON.stringify(Pt)};
1277
+ const PANEL_STYLES = ${JSON.stringify(Lt)};
1058
1278
 
1059
1279
  function PanelStyles() {
1060
1280
  return <style>{PANEL_STYLES}</style>;
@@ -1080,11 +1300,11 @@ const TREE_INDENT = 14;
1080
1300
  const TREE_BASE = 8;
1081
1301
 
1082
1302
  const renderPrimitive = (value: unknown) => {
1083
- if (typeof value === "string") return <span className="lexy-dp-json-str">"{value}"</span>;
1084
- if (typeof value === "number") return <span className="lexy-dp-json-num">{value}</span>;
1085
- if (typeof value === "boolean") return <span className="lexy-dp-json-num">{String(value)}</span>;
1303
+ if (typeof value === "string") return <span className="lexy-dp-json-row-str">"{value}"</span>;
1304
+ if (typeof value === "number") return <span className="lexy-dp-json-row-num">{value}</span>;
1305
+ if (typeof value === "boolean") return <span className="lexy-dp-json-row-num">{String(value)}</span>;
1086
1306
  if (value === null) return <span className="lexy-dp-muted">null</span>;
1087
- return <span className="lexy-dp-json-str">{String(value)}</span>;
1307
+ return <span className="lexy-dp-json-row-str">{String(value)}</span>;
1088
1308
  };
1089
1309
 
1090
1310
  function JsonNode({
@@ -1163,7 +1383,7 @@ function LogEntry({ item }: { item: DesignerActivityRecord }) {
1163
1383
  <span className="lexy-dp-json-spacer" aria-hidden />
1164
1384
  <span className="lexy-dp-json-leaf">
1165
1385
  <span className="lexy-dp-muted">fuente:</span>{" "}
1166
- <span className="lexy-dp-json-str">{trigger}</span>
1386
+ <span className="lexy-dp-json-row-str">{trigger}</span>
1167
1387
  </span>
1168
1388
  </div>
1169
1389
  {input !== undefined ? <JsonNode label={inputLabel} value={input} defaultOpen /> : null}
@@ -1357,8 +1577,8 @@ function EventDetail({ event }: { event: CatalogEvent }) {
1357
1577
  const observedTriggers = Array.from(
1358
1578
  new Set(
1359
1579
  activity
1360
- .filter((record) => record.technicalId === event.technicalId && record.triggerId)
1361
- .map((record) => record.triggerId as string),
1580
+ .filter((record) => record.technicalId === event.technicalId && record.triggerId)
1581
+ .map((record) => record.triggerId as string),
1362
1582
  ),
1363
1583
  );
1364
1584
  const payload = event.lastPayload;
@@ -1758,6 +1978,22 @@ type DesignerTab = "activity" | "events";
1758
1978
 
1759
1979
  export function DesignerPanelPage() {
1760
1980
  const [tab, setTab] = useState<DesignerTab>("activity");
1981
+ const [launcherVisible, setLauncherVisible] = useState(() => {
1982
+ if (typeof window !== "undefined") {
1983
+ return localStorage.getItem("lexy-dp-launcher-visible") !== "false";
1984
+ }
1985
+ return true;
1986
+ });
1987
+
1988
+ useEffect(() => {
1989
+ const handleStorage = (e: StorageEvent) => {
1990
+ if (e.key === "lexy-dp-launcher-visible") {
1991
+ setLauncherVisible(e.newValue !== "false");
1992
+ }
1993
+ };
1994
+ window.addEventListener("storage", handleStorage);
1995
+ return () => window.removeEventListener("storage", handleStorage);
1996
+ }, []);
1761
1997
 
1762
1998
  return (
1763
1999
  <div className="lexy-dp lexy-dp-page">
@@ -1783,6 +2019,24 @@ export function DesignerPanelPage() {
1783
2019
  <Zap />
1784
2020
  Eventos y Datos
1785
2021
  </button>
2022
+
2023
+ <div style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: "8px" }}>
2024
+ <span className="lexy-dp-muted" style={{ fontSize: "12px" }}>Burbuja de Asistencia:</span>
2025
+ <button
2026
+ type="button"
2027
+ className="lexy-dp-btn lexy-dp-btn--outline lexy-dp-btn--sm"
2028
+ style={{ display: "inline-flex", alignItems: "center", gap: "6px", cursor: "pointer" }}
2029
+ onClick={() => {
2030
+ const nextState = !launcherVisible;
2031
+ setLauncherVisible(nextState);
2032
+ localStorage.setItem("lexy-dp-launcher-visible", String(nextState));
2033
+ window.dispatchEvent(new Event("storage"));
2034
+ }}
2035
+ >
2036
+ {launcherVisible ? <EyeOff style={{ width: "12px", height: "12px" }} /> : <Eye style={{ width: "12px", height: "12px" }} />}
2037
+ {launcherVisible ? "Ocultar" : "Mostrar"}
2038
+ </button>
2039
+ </div>
1786
2040
  </div>
1787
2041
  <div className="lexy-dp-body">
1788
2042
  {tab === "activity" ? (
@@ -1802,6 +2056,25 @@ export function DesignerPanelPage() {
1802
2056
 
1803
2057
  export function PrototypeDesignerPanel() {
1804
2058
  const [open, setOpen] = useState(false);
2059
+ const [visible, setVisible] = useState(() => {
2060
+ if (typeof window !== "undefined") {
2061
+ return localStorage.getItem("lexy-dp-launcher-visible") !== "false";
2062
+ }
2063
+ return true;
2064
+ });
2065
+
2066
+ useEffect(() => {
2067
+ const handleStorage = (e: StorageEvent) => {
2068
+ if (e.key === "lexy-dp-launcher-visible") {
2069
+ setVisible(e.newValue !== "false");
2070
+ }
2071
+ };
2072
+ window.addEventListener("storage", handleStorage);
2073
+ return () => window.removeEventListener("storage", handleStorage);
2074
+ }, []);
2075
+
2076
+ if (!visible) return null;
2077
+
1805
2078
  return (
1806
2079
  <div className="lexy-dp">
1807
2080
  <PanelStyles />
@@ -1810,6 +2083,21 @@ export function PrototypeDesignerPanel() {
1810
2083
  <div className="lexy-dp-sheet__header">
1811
2084
  <p className="lexy-dp-sheet__title">Panel de Actividad</p>
1812
2085
  <div className="lexy-dp-sheet__actions">
2086
+ <button
2087
+ type="button"
2088
+ aria-label="Ocultar burbuja de asistencia"
2089
+ title="Ocultar burbuja de asistencia"
2090
+ className="lexy-dp-iconbtn"
2091
+ onClick={() => {
2092
+ if (confirm("¿Estás seguro de que quieres ocultar la burbuja de asistencia? Podrás volver a habilitarla desde la página del panel (/designer-panel).")) {
2093
+ localStorage.setItem("lexy-dp-launcher-visible", "false");
2094
+ setVisible(false);
2095
+ window.dispatchEvent(new Event("storage"));
2096
+ }
2097
+ }}
2098
+ >
2099
+ <EyeOff />
2100
+ </button>
1813
2101
  <button
1814
2102
  type="button"
1815
2103
  aria-label="Abrir panel completo"
@@ -1848,7 +2136,7 @@ export function PrototypeDesignerPanel() {
1848
2136
  </div>
1849
2137
  );
1850
2138
  }
1851
- `,$e=async(e,t)=>{let o=async(a,n)=>{await Me.mkdir(ie.dirname(ie.join(e,a)),{recursive:!0}),await Me.writeFile(ie.join(e,a),n)};await o(se,Et),await o(le,jt())};import Fe from"fs/promises";import qe from"path";var ce="src/prototype/mock-store/mock-store.ts",de="src/prototype/mock-store/fixtures.ts",Ct="src/prototype/ports/types.ts",It="src/prototype/ports/catalog.ts",Tt="src/prototype/ports/mock-read.ts",Rt="src/prototype/ports/mock-write.ts",Nt="src/prototype/ports/production.ts",pe="src/prototype/ports/index.ts",Ot=String.raw`import { fixtures } from "./fixtures";
2139
+ `,Je=async(e,t)=>{let o=async(a,n)=>{await He.mkdir(xe.dirname(xe.join(e,a)),{recursive:!0}),await He.writeFile(xe.join(e,a),n)};await o(he,At),await o(ve,Dt())};import Be from"fs/promises";import We from"path";var be="src/prototype/mock-store/mock-store.ts",we="src/prototype/mock-store/fixtures.ts",zt="src/prototype/ports/types.ts",Mt="src/prototype/ports/catalog.ts",$t="src/prototype/ports/mock-read.ts",Ft="src/prototype/ports/mock-write.ts",Vt="src/prototype/ports/production.ts",Se="src/prototype/ports/index.ts",qt=String.raw`import { fixtures } from "./fixtures";
1852
2140
 
1853
2141
  export type JsonPrimitive = string | number | boolean | null;
1854
2142
  export type JsonValue = JsonPrimitive | JsonValue[] | { [key: string]: JsonValue };
@@ -2008,7 +2296,7 @@ export const findRecordById = (
2008
2296
  fieldId: string,
2009
2297
  id: JsonPrimitive,
2010
2298
  ) => records.find((record) => record[fieldId] === id);
2011
- `,_t=String.raw`import type { MockEntityRecord } from "./mock-store";
2299
+ `,Ut=String.raw`import type { MockEntityRecord } from "./mock-store";
2012
2300
 
2013
2301
  export type Fixtures = {
2014
2302
  datasetVersion: number;
@@ -2024,7 +2312,7 @@ export const fixtures: Fixtures = {
2024
2312
  datasetVersion: 1,
2025
2313
  entities: {},
2026
2314
  };
2027
- `,At=String.raw`import { z } from "zod";
2315
+ `,Kt=String.raw`import { z } from "zod";
2028
2316
 
2029
2317
  /** Metadata de una carga de datos (GET): describe qué lee y qué la detona. */
2030
2318
  export const readMetaSchema = z
@@ -2077,7 +2365,7 @@ export interface LexyReadPort {
2077
2365
  export interface LexyWritePort {
2078
2366
  publish(eventId: string, payload: unknown, meta?: WriteMeta): Promise<EventReceipt>;
2079
2367
  }
2080
- `,Lt=String.raw`import type { EventReceipt, ReadMeta, WriteMeta } from "./types";
2368
+ `,Ht=String.raw`import type { EventReceipt, ReadMeta, WriteMeta } from "./types";
2081
2369
 
2082
2370
  export type CatalogEvent = {
2083
2371
  kind: "event";
@@ -2188,7 +2476,7 @@ const createCatalog = () => {
2188
2476
  };
2189
2477
 
2190
2478
  export const catalog = createCatalog();
2191
- `,Dt=String.raw`import { designerActivity } from "../designer-panel/designer-activity";
2479
+ `,Jt=String.raw`import { designerActivity } from "../designer-panel/designer-activity";
2192
2480
  import { type MockEntityRecord, mockStore } from "../mock-store/mock-store";
2193
2481
  import { catalog } from "./catalog";
2194
2482
  import { type LexyReadPort, type ReadMeta, readMetaSchema } from "./types";
@@ -2226,7 +2514,7 @@ export const mockRead: LexyReadPort = {
2226
2514
  return data as T;
2227
2515
  },
2228
2516
  };
2229
- `,zt=String.raw`import { designerActivity } from "../designer-panel/designer-activity";
2517
+ `,Bt=String.raw`import { designerActivity } from "../designer-panel/designer-activity";
2230
2518
  import { mockStore } from "../mock-store/mock-store";
2231
2519
  import { catalog } from "./catalog";
2232
2520
  import { type EventReceipt, type LexyWritePort, type WriteMeta, writeMetaSchema } from "./types";
@@ -2270,7 +2558,7 @@ export const mockWrite: LexyWritePort = {
2270
2558
  return receipt;
2271
2559
  },
2272
2560
  };
2273
- `,Mt=String.raw`import type { LexyReadPort, LexyWritePort } from "./types";
2561
+ `,Wt=String.raw`import type { LexyReadPort, LexyWritePort } from "./types";
2274
2562
 
2275
2563
  export const productionRead: LexyReadPort = {
2276
2564
  async load<T = unknown>(loadId: string): Promise<T> {
@@ -2287,7 +2575,7 @@ export const productionWrite: LexyWritePort = {
2287
2575
  );
2288
2576
  },
2289
2577
  };
2290
- `,$t=String.raw`import { mockRead } from "./mock-read";
2578
+ `,Gt=String.raw`import { mockRead } from "./mock-read";
2291
2579
  import { mockWrite } from "./mock-write";
2292
2580
  import { productionRead, productionWrite } from "./production";
2293
2581
  import type { LexyReadPort, LexyWritePort } from "./types";
@@ -2304,8 +2592,8 @@ export type {
2304
2592
  ReadMeta,
2305
2593
  WriteMeta,
2306
2594
  } from "./types";
2307
- `,Ft=[[ce,Ot],[de,_t],[Ct,At],[It,Lt],[Tt,Dt],[Rt,zt],[Nt,Mt],[pe,$t]],Ve=async e=>{for(let[t,o]of Ft){let a=qe.join(e,t);await Fe.mkdir(qe.dirname(a),{recursive:!0}),await Fe.writeFile(a,o)}};var Kt={feature:["src/app","src/features","src/shared/assets","src/shared/components/base","src/shared/hooks","src/shared/services","src/shared/lib","src/shared/types"],layer:["src/assets","src/components/base","src/hooks","src/services","src/lib","src/types","src/views","src/stores"]},Ut="10.33.3",Ht=e=>{let t=e.architecture==="feature"?{"react-router":"^7.9.0"}:{};return JSON.stringify({name:e.projectName,private:!0,version:"0.0.0",type:"module",packageManager:`pnpm@${Ut}`,scripts:{dev:"vite","check:data-contract":"tsx scripts/check-data-contract.ts","check:prototype":"pnpm check:data-contract","build:app":"tsc -b && vite build",build:"pnpm check:prototype && pnpm build:app",preview:"vite preview",lint:"eslint .",format:"prettier --write ."},dependencies:{clsx:"^2.1.1","lucide-react":"^0.460.0",react:"^19.2.6","react-dom":"^19.2.6",...t,"tailwind-merge":"^3.3.1",zod:"^4.1.0"},devDependencies:{"@babel/core":"^7.29.7","@eslint/js":"^10.0.1","@rolldown/plugin-babel":"^0.2.3","@tailwindcss/vite":"^4.3.0","@types/babel__core":"^7.20.5","@types/node":"^24.12.3","@types/react":"^19.2.14","@types/react-dom":"^19.2.3","@vitejs/plugin-react":"^6.0.1","babel-plugin-react-compiler":"^1.0.0",eslint:"^10.4.1","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-simple-import-sort":"^13.0.0",globals:"^17.6.0",prettier:"^3.8.4",tailwindcss:"^4.3.0",terser:"^5.48.0",tsx:"^4.19.0",typescript:"~5.9.3","typescript-eslint":"^8.61.0",vite:"^8.0.12"}},null,2)+`
2308
- `},Bt=`import path from "node:path";
2595
+ `,Yt=[[be,qt],[we,Ut],[zt,Kt],[Mt,Ht],[$t,Jt],[Ft,Bt],[Vt,Wt],[Se,Gt]],Ge=async e=>{for(let[t,o]of Yt){let a=We.join(e,t);await Be.mkdir(We.dirname(a),{recursive:!0}),await Be.writeFile(a,o)}};var Zt={feature:["src/app","src/features","src/shared/assets","src/shared/components/base","src/shared/hooks","src/shared/services","src/shared/lib","src/shared/types"],layer:["src/assets","src/components/base","src/hooks","src/services","src/lib","src/types","src/views","src/stores"]},B="10.33.3",eo=e=>{let t=e.architecture==="feature"?{"react-router":"^7.9.0"}:{};return JSON.stringify({name:e.projectName,private:!0,version:"0.0.0",type:"module",packageManager:`pnpm@${B}`,scripts:{dev:"vite","check:data-contract":"tsx scripts/check-data-contract.ts","check:prototype":"pnpm check:data-contract","build:app":"tsc -b && vite build",build:"pnpm check:prototype && pnpm build:app",preview:"vite preview",lint:"eslint .",format:"prettier --write ."},dependencies:{clsx:"^2.1.1","lucide-react":"^0.460.0",react:"^19.2.6","react-dom":"^19.2.6",...t,"tailwind-merge":"^3.3.1",zod:"^4.1.0"},devDependencies:{"@babel/core":"^7.29.7","@eslint/js":"^10.0.1","@rolldown/plugin-babel":"^0.2.3","@tailwindcss/vite":"^4.3.0","@types/babel__core":"^7.20.5","@types/node":"^24.12.3","@types/react":"^19.2.14","@types/react-dom":"^19.2.3","@vitejs/plugin-react":"^6.0.1","babel-plugin-react-compiler":"^1.0.0",eslint:"^10.4.1","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-simple-import-sort":"^13.0.0",globals:"^17.6.0",prettier:"^3.8.4",tailwindcss:"^4.3.0",terser:"^5.48.0",tsx:"^4.19.0",typescript:"~5.9.3","typescript-eslint":"^8.61.0",vite:"^8.0.12"}},null,2)+`
2596
+ `},to=`import path from "node:path";
2309
2597
 
2310
2598
  import babel from "@rolldown/plugin-babel";
2311
2599
  import tailwindcss from "@tailwindcss/vite";
@@ -2356,7 +2644,7 @@ export default defineConfig({
2356
2644
  },
2357
2645
  },
2358
2646
  });
2359
- `,Jt=`import js from "@eslint/js";
2647
+ `,oo=`import js from "@eslint/js";
2360
2648
  import jsxA11y from "eslint-plugin-jsx-a11y";
2361
2649
  import reactHooks from "eslint-plugin-react-hooks";
2362
2650
  import simpleImportSort from "eslint-plugin-simple-import-sort";
@@ -2385,14 +2673,14 @@ export default tseslint.config(
2385
2673
  },
2386
2674
  },
2387
2675
  );
2388
- `,Wt=`{
2676
+ `,ao=`{
2389
2677
  "printWidth": 100
2390
2678
  }
2391
- `,Gt=`pnpm-lock.yaml
2679
+ `,no=`pnpm-lock.yaml
2392
2680
  src/lexy-theme.css
2393
2681
  public/fonts/
2394
2682
  dist/
2395
- `,Qt=`name: CI
2683
+ `,ro=`name: CI
2396
2684
 
2397
2685
  on:
2398
2686
  push:
@@ -2415,7 +2703,7 @@ jobs:
2415
2703
  - run: pnpm check:data-contract
2416
2704
  - run: pnpm build:app
2417
2705
  - run: pnpm audit --audit-level high
2418
- `,Yt=`{
2706
+ `,io=`{
2419
2707
  "files": [],
2420
2708
  "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
2421
2709
  "compilerOptions": {
@@ -2423,7 +2711,7 @@ jobs:
2423
2711
  "paths": { "@/*": ["./src/*"] }
2424
2712
  }
2425
2713
  }
2426
- `,Xt=`{
2714
+ `,so=`{
2427
2715
  "compilerOptions": {
2428
2716
  "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
2429
2717
  "target": "ES2022",
@@ -2447,7 +2735,7 @@ jobs:
2447
2735
  },
2448
2736
  "include": ["src"]
2449
2737
  }
2450
- `,Zt=`{
2738
+ `,lo=`{
2451
2739
  "compilerOptions": {
2452
2740
  "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
2453
2741
  "target": "ES2023",
@@ -2464,7 +2752,7 @@ jobs:
2464
2752
  },
2465
2753
  "include": ["vite.config.ts"]
2466
2754
  }
2467
- `,eo=e=>`<!doctype html>
2755
+ `,co=e=>`<!doctype html>
2468
2756
  <html lang="es">
2469
2757
  <head>
2470
2758
  <meta charset="UTF-8" />
@@ -2476,9 +2764,9 @@ jobs:
2476
2764
  <script type="module" src="/src/main.tsx"></script>
2477
2765
  </body>
2478
2766
  </html>
2479
- `,to=`@import "tailwindcss";
2767
+ `,po=`@import "tailwindcss";
2480
2768
  @import "./lexy-theme.css";
2481
- `,oo=e=>e.architecture==="feature"?`import "./index.css";
2769
+ `,mo=e=>e.architecture==="feature"?`import "./index.css";
2482
2770
 
2483
2771
  import { StrictMode } from "react";
2484
2772
  import { createRoot } from "react-dom/client";
@@ -2505,20 +2793,20 @@ createRoot(document.getElementById("root")!).render(
2505
2793
  <App />
2506
2794
  </StrictMode>,
2507
2795
  );
2508
- `,Ke=` <main className="flex min-h-screen items-center justify-center bg-background text-foreground">
2796
+ `,Ye=` <main className="flex min-h-screen items-center justify-center bg-background text-foreground">
2509
2797
  <div className="text-center">
2510
2798
  <h1 className="text-2xl font-semibold">Proyecto Lexy listo</h1>
2511
2799
  <p className="mt-2 text-sm text-muted-foreground">
2512
2800
  Trae tu primer componente: <code>npx create-lexy add button</code>
2513
2801
  </p>
2514
2802
  </div>
2515
- </main>`,ao=e=>e.architecture==="feature"?`import { Route, Routes } from "react-router";
2803
+ </main>`,uo=e=>e.architecture==="feature"?`import { Route, Routes } from "react-router";
2516
2804
 
2517
2805
  import { PrototypeDesignerPanel } from "../prototype/designer-panel/PrototypeDesignerPanel";
2518
2806
 
2519
2807
  const Home = () => {
2520
2808
  return (
2521
- ${Ke}
2809
+ ${Ye}
2522
2810
  );
2523
2811
  };
2524
2812
 
@@ -2541,22 +2829,22 @@ const showPrototypeDesignerPanel = import.meta.env.DEV;
2541
2829
  export const App = () => {
2542
2830
  return (
2543
2831
  <>
2544
- ${Ke}
2832
+ ${Ye}
2545
2833
  {showPrototypeDesignerPanel ? <PrototypeDesignerPanel /> : null}
2546
2834
  </>
2547
2835
  );
2548
2836
  };
2549
- `,no=`import { type ClassValue, clsx } from "clsx";
2837
+ `,yo=`import { type ClassValue, clsx } from "clsx";
2550
2838
  import { twMerge } from "tailwind-merge";
2551
2839
 
2552
2840
  export function cn(...inputs: ClassValue[]) {
2553
2841
  return twMerge(clsx(inputs));
2554
2842
  }
2555
- `,ro=`node_modules/
2843
+ `,fo=`node_modules/
2556
2844
  dist/
2557
2845
  *.log
2558
2846
  .env
2559
- `,io=e=>`# ${e.projectName}
2847
+ `,go=e=>`# ${e.projectName}
2560
2848
 
2561
2849
  Proyecto Lexy (React + Vite + TS + theme Lexy). Los componentes viven en tu proyecto: m\xEDralos con \`view\`, inst\xE1lalos con \`add\`, ed\xEDtalos con libertad.
2562
2850
 
@@ -2567,29 +2855,58 @@ npx create-lexy view button # ver un componente antes de instalarlo
2567
2855
  npx create-lexy add button # instalarlo (local y editable)
2568
2856
  npx create-lexy doctor # divergencia con el registry
2569
2857
  \`\`\`
2570
- `,so=e=>{let o=e.architecture==="feature"?"@/shared":"@";return JSON.stringify({$schema:"https://ui.shadcn.com/schema.json",style:"new-york",rsc:!1,tsx:!0,tailwind:{config:"",css:"src/index.css",baseColor:"neutral",cssVariables:!0},aliases:{components:`${o}/components`,ui:`${o}/components/base`,utils:`${o}/lib/utils/cn`,lib:`${o}/lib`,hooks:`${o}/hooks`},registries:{"@lexy":`${F}@latest/r/{name}.json`}},null,2)+`
2571
- `},lo=e=>{let t=e.architecture==="feature";return{version:"2.0.0",generatedAt:new Date().toISOString(),architecture:e.architecture,world:e.world,registry:{package:"@lexydesign/registry",cdn:F},componentImportPattern:t?"@/shared/components/base/{Component}":"@/components/base/{Component}",paths:{components:t?"src/shared/components/base":"src/components/base",hooks:t?"src/shared/hooks":"src/hooks",services:t?"src/shared/services":"src/services",lib:t?"src/shared/lib":"src/lib",views:t?"src/features":"src/views"},prototype:{dataContractVersion:"1",dataContractPath:re,runtimeVersion:"1",mockStorePath:ce,fixturesPath:de,portsPath:pe,designerPanelVersion:"1",designerPanelPath:le,designerActivityStorePath:se},installed:{}}},Ue=async(e,t)=>{let o=["package.json","src","index.html",".lexy"],a=[];for(let s of o)try{await b.access(w.join(t,s)),a.push(s)}catch{}if(a.length>0)throw new Error(`El directorio actual ya contiene archivos de un proyecto (${a.join(", ")}). Ejecuta el comando dentro de una carpeta vac\xEDa.`);for(let s of Kt[e.architecture])await b.mkdir(w.join(t,s),{recursive:!0});let n=(s,u)=>b.writeFile(w.join(t,s),u);await n("package.json",Ht(e)),await n("vite.config.ts",Bt),await n("tsconfig.json",Yt),await n("tsconfig.app.json",Xt),await n("tsconfig.node.json",Zt),await n("eslint.config.js",Jt),await n(".prettierrc",Wt),await n(".prettierignore",Gt),await b.mkdir(w.join(t,".github/workflows"),{recursive:!0}),await n(".github/workflows/ci.yml",Qt),await n("index.html",eo(e)),await n(".gitignore",ro),await n("README.md",io(e)),await n("src/index.css",to),await n("src/main.tsx",oo(e)),await ze(t,e.projectName),await Ve(t);let r=lo(e);await $e(t,r);let i=e.architecture==="feature"?"src/app":"src/views";await n(`${i}/App.tsx`,ao(e)),await n(".lexy",JSON.stringify(r,null,2)+`
2572
- `),await n("components.json",so(e)),await b.copyFile(Ce,w.join(t,"src/lexy-theme.css")),await b.mkdir(w.join(t,"public/fonts"),{recursive:!0}),await b.cp(Ie,w.join(t,"public/fonts"),{recursive:!0});let d=w.join(t,r.paths.lib,"utils");await b.mkdir(d,{recursive:!0}),await b.writeFile(w.join(d,"cn.ts"),no),await co(t)},co=async e=>{let t=[],o=async a=>{let n;try{n=await b.readdir(a,{withFileTypes:!0})}catch{return}for(let r of n){let i=w.join(a,r.name);r.isDirectory()?await o(i):/\.(ts|tsx)$/.test(r.name)&&t.push(i)}};await o(w.join(e,"src")),await o(w.join(e,"scripts"));for(let a of t){let n=await b.readFile(a,"utf-8"),r=await Vt(a)??{},i=await qt(n,{...r,filepath:a});i!==n&&await b.writeFile(a,i)}};var fo=["feature","layer"],go=["cliente","crm","mixto"],xo=e=>new Promise((t,o)=>{po("pnpm",["install"],{cwd:e,stdio:"ignore",shell:!0}).on("close",n=>n===0?t():o(new Error(`pnpm install fall\xF3 con c\xF3digo ${n}`)))}),He=async(e,t)=>{let o;!!(e&&t.type)?(fo.includes(t.type)||(console.error(j.red(`Error: la arquitectura "${t.type}" no es v\xE1lida. Usa "feature" o "layer".`)),process.exit(1)),t.world&&!go.includes(t.world)&&(console.error(j.red(`Error: el mundo "${t.world}" no es v\xE1lido. Usa "cliente", "crm" o "mixto".`)),process.exit(1)),t.world||console.warn(j.yellow('Aviso: sin --world; se asume "mixto". ')+j.dim("Pasa --world cliente|crm para fijar densidad y voz desde el inicio.")),o={projectName:e,architecture:t.type,world:t.world??"mixto"},console.log(j.blue("Modo automatizado detectado. Saltando interfaz interactiva..."))):o=await Ae(e),mo(`Nombre: ${o.projectName}
2858
+ `,xo=e=>{let o=e.architecture==="feature"?"@/shared":"@";return JSON.stringify({$schema:"https://ui.shadcn.com/schema.json",style:"new-york",rsc:!1,tsx:!0,tailwind:{config:"",css:"src/index.css",baseColor:"neutral",cssVariables:!0},aliases:{components:`${o}/components`,ui:`${o}/components/base`,utils:`${o}/lib/utils/cn`,lib:`${o}/lib`,hooks:`${o}/hooks`},registries:{"@lexy":`${q}@latest/r/{name}.json`}},null,2)+`
2859
+ `},ho=e=>{let t=e.architecture==="feature";return{version:"2.0.0",generatedAt:new Date().toISOString(),architecture:e.architecture,world:e.world,registry:{package:"@lexydesign/registry",cdn:q},componentImportPattern:t?"@/shared/components/base/{Component}":"@/components/base/{Component}",paths:{components:t?"src/shared/components/base":"src/components/base",hooks:t?"src/shared/hooks":"src/hooks",services:t?"src/shared/services":"src/services",lib:t?"src/shared/lib":"src/lib",views:t?"src/features":"src/views"},prototype:{dataContractVersion:"1",dataContractPath:ge,runtimeVersion:"1",mockStorePath:be,fixturesPath:we,portsPath:Se,designerPanelVersion:"1",designerPanelPath:ve,designerActivityStorePath:he},installed:{}}},Qe=async(e,t)=>{let o=["package.json","src","index.html",".lexy"],a=[];for(let s of o)try{await S.access(k.join(t,s)),a.push(s)}catch{}if(a.length>0)throw new Error(`El directorio actual ya contiene archivos de un proyecto (${a.join(", ")}). Ejecuta el comando dentro de una carpeta vac\xEDa.`);for(let s of Zt[e.architecture])await S.mkdir(k.join(t,s),{recursive:!0});let n=(s,m)=>S.writeFile(k.join(t,s),m);await n("package.json",eo(e)),await n("vite.config.ts",to),await n("tsconfig.json",io),await n("tsconfig.app.json",so),await n("tsconfig.node.json",lo),await n("eslint.config.js",oo),await n(".prettierrc",ao),await n(".prettierignore",no),await S.mkdir(k.join(t,".github/workflows"),{recursive:!0}),await n(".github/workflows/ci.yml",ro),await n("index.html",co(e)),await n(".gitignore",fo),await n("README.md",go(e)),await n("src/index.css",po),await n("src/main.tsx",mo(e)),await Ke(t,e.projectName),await Ge(t);let r=ho(e);await Je(t,r);let i=e.architecture==="feature"?"src/app":"src/views";await n(`${i}/App.tsx`,uo(e)),await n(".lexy",JSON.stringify(r,null,2)+`
2860
+ `),await n("components.json",xo(e)),await S.copyFile(Fe,k.join(t,"src/lexy-theme.css")),await S.mkdir(k.join(t,"public/fonts"),{recursive:!0}),await S.cp(Ve,k.join(t,"public/fonts"),{recursive:!0});let p=k.join(t,r.paths.lib,"utils");await S.mkdir(p,{recursive:!0}),await S.writeFile(k.join(p,"cn.ts"),yo),await vo(t)},vo=async e=>{let t=[],o=async a=>{let n;try{n=await S.readdir(a,{withFileTypes:!0})}catch{return}for(let r of n){let i=k.join(a,r.name);r.isDirectory()?await o(i):/\.(ts|tsx)$/.test(r.name)&&t.push(i)}};await o(k.join(e,"src")),await o(k.join(e,"scripts"));for(let a of t){let n=await S.readFile(a,"utf-8"),r=await Xt(a)??{},i=await Qt(n,{...r,filepath:a});i!==n&&await S.writeFile(a,i)}};var et=e=>{let t=Number(e.match(/(\d+)/)?.[1]??0),o=Number(process.versions.node.split(".")[0]);!t||o>=t||(console.error(W.red(`
2861
+ Node ${process.versions.node} es muy antiguo \u2014 create-lexy necesita Node ${e}.
2862
+ `)+W.dim(`Actualiza Node (https://nodejs.org) o usa un gestor de versiones (nvm, fnm) y vuelve a intentarlo.
2863
+ `)),process.exit(1))},Pe=()=>{try{return Ze("pnpm",["--version"],{stdio:"ignore"}),!0}catch{return!1}},ko=()=>{try{return Ze("corepack",["--version"],{stdio:"ignore"}),!0}catch{return!1}},Po=()=>{let e=ke("corepack",["enable"],{stdio:"ignore"}),t=ke("corepack",["prepare",`pnpm@${B}`,"--activate"],{stdio:"ignore"});return e.status===0&&t.status===0&&Pe()},Eo=()=>ke("npm",["install","-g",`pnpm@${B}`],{stdio:"ignore",shell:!0}).status===0&&Pe(),Xe=`\`corepack enable && corepack prepare pnpm@${B} --activate\` (o \`npm install -g pnpm\`)`,ae=async()=>{if(Pe())return;if(console.log(W.yellow("pnpm no est\xE1 instalado.")+W.dim(" create-lexy lo usa para instalar las dependencias del proyecto.")),!!(process.stdout.isTTY&&process.stdin.isTTY)){let a=await bo({message:"\xBFInstalar pnpm ahora?",initialValue:!0});if(wo(a)||!a)throw new Error(`pnpm es necesario. Inst\xE1lalo con ${Xe} y vuelve a intentarlo.`)}else console.log(W.dim("Modo no interactivo: intentando instalar pnpm autom\xE1ticamente..."));let t=So();t.start("Instalando pnpm...");let o=ko()?Po():Eo();if(t.stop(o?"pnpm instalado":"No se pudo instalar pnpm autom\xE1ticamente"),!o)throw new Error(`No se pudo instalar pnpm autom\xE1ticamente. Inst\xE1lalo con ${Xe} y vuelve a intentarlo.`)};import tt from"fs/promises";import Co from"path";var ot=e=>Co.join(e,".lexy"),z=async e=>{let t;try{t=await tt.readFile(ot(e),"utf-8")}catch{throw new Error("No se encontr\xF3 el archivo .lexy. \xBFEst\xE1s en la ra\xEDz de un proyecto Lexy? (cr\xE9alo con `npx create-lexy create`)")}let o=JSON.parse(t);if(!o.paths?.components)throw new Error("El .lexy no tiene paths.components \u2014 archivo corrupto o de una versi\xF3n incompatible.");return o.installed??={},o},at=async(e,t)=>{await tt.writeFile(ot(e),JSON.stringify(t,null,2)+`
2864
+ `)};var No=(e,t)=>new Promise((o,a)=>{jo("pnpm",["add",...e],{cwd:t,stdio:"ignore",shell:!0}).on("close",r=>r===0?o():a(new Error(`pnpm add fall\xF3 con c\xF3digo ${r}`)))}),Ro=async(e,t="utf-8")=>{try{return await re.readFile(e,t)}catch{return null}},ie=async(e,t)=>{let o=process.cwd(),a=await z(o),n=nt();n.start("Resolviendo componentes en el registry...");let r=new Map,i=async d=>{let g=d.toLowerCase().replace(/^@lexy\//,"");if(r.has(g))return;let l=await C(g);r.set(g,l);for(let c of l.item.registryDependencies??[])await i(c)};try{for(let d of e)await i(d)}catch(d){throw n.stop(P.red("No se pudo resolver el pedido.")),d}let p=new Map;for(let[d,{item:g}]of r){let l=[];for(let c of O(g,a)){let f=await Ro(ne.join(o,c.relPath),c.encoding??"utf-8");l.push({...c,status:f===null?"new":f===c.content?"same":"differs"})}p.set(d,l)}let s=Array.from(p.values()).flat().filter(d=>d.status==="differs");if(n.stop(`Resueltos: ${Array.from(r.keys()).join(", ")}`),s.length>0&&!t.overwrite){let d=s.map(g=>` ${g.relPath}`).join(`
2865
+ `);if(process.stdout.isTTY&&process.stdin.isTTY){let g=await Io({message:`Estos archivos existen con cambios locales y ser\xE1n sobrescritos:
2866
+ ${d}
2867
+ \xBFContinuar?`});if(To(g)||g!==!0){console.log(P.yellow("Operaci\xF3n cancelada \u2014 nada fue modificado.")),process.exitCode=1;return}}else{console.error(P.red(`Estos archivos existen con cambios locales:
2868
+ `)+d+P.dim(`
2869
+ Usa --overwrite para sobrescribirlos.`)),process.exitCode=1;return}}for(let[d,g]of p){let{item:l,version:c,source:f}=r.get(d);for(let h of g){if(h.status==="same")continue;let _=ne.join(o,h.relPath);await re.mkdir(ne.dirname(_),{recursive:!0}),await re.writeFile(_,h.content,h.encoding??"utf-8")}a.installed[l.name]=c;let b=e.map(h=>h.toLowerCase()).includes(d)?"":P.dim(" (dependencia)"),K=f==="bundle"?P.yellow(" [bundle local \u2014 sin red]"):"";console.log(P.green(`${P.bold(l.title??l.name)} instalado`)+b+P.cyan(` \u2192 ${a.paths.components}/`)+K);for(let h of g){let _=h.status==="same"?P.dim(" (sin cambios)"):"";console.log(P.dim(` ${h.relPath}${_}`))}}await at(o,a);let m=new Set;for(let{item:d}of r.values())for(let g of d.dependencies??[])m.add(g);let u=JSON.parse(await re.readFile(ne.join(o,"package.json"),"utf-8")),y={...u.dependencies,...u.devDependencies},R=d=>{let g=d.lastIndexOf("@");return g>0?d.slice(0,g):d},v=Array.from(m).filter(d=>!y[R(d)]);if(v.length>0)if(t.install===!1)console.log(P.yellow(`Dependencias pendientes (inst\xE1lalas t\xFA): ${v.join(", ")}`));else{await ae();let d=nt();d.start(`Instalando dependencias: ${v.join(", ")}...`),await No(v,o),d.stop("Dependencias instaladas.")}};import{spawn as zo}from"child_process";import{note as Mo,outro as $o,spinner as Fo}from"@clack/prompts";import T from"picocolors";import{cancel as _o,intro as Oo,isCancel as Ao,select as it,text as Lo}from"@clack/prompts";import st from"picocolors";var Ee=[{value:"screen",label:"Una pantalla o flujo corto",hint:"landing, formulario, demo \u2014 sin navegaci\xF3n entre secciones",architecture:"layer"},{value:"app",label:"Una app con secciones y navegaci\xF3n",hint:"dashboard, listados, detalle \u2014 varias vistas con router",architecture:"feature"}],rt=e=>Ee.find(t=>t.value===e).architecture;var Do=`
2870
+ ###### ######
2871
+ ##::+#### ####+::##
2872
+ #-..:+################+:..:#
2873
+ #+...=################=...+#
2874
+ #=-*##################*-=#
2875
+ ########################
2876
+ ==-:.:=*##########*=:.::==
2877
+ **#####*+--*####*--+*#####**
2878
+ ##########%@@#:-##=.#@@%##########
2879
+ #######*+*#%%*:-@@=.+%%#*+*#######
2880
+ #+:..........:*#:..........:=#
2881
+ ...........:====:...........
2882
+ ......................
2883
+ ..............
2884
+ `,Ce=e=>{Ao(e)&&(_o("Operaci\xF3n cancelada por el usuario."),process.exit(0))},lt=async e=>{console.clear(),Oo(`${st.cyan(Do)}
2885
+ ${st.bold(" Bienvenido al generador de proyectos Lexy")}`);let t=e;if(!t){let n=await Lo({message:"\xBFCu\xE1l es el nombre de tu proyecto?",placeholder:"lexy-app",validate:r=>{if(!r||r.trim()==="")return"El nombre es obligatorio.";if(!/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(r))return"El nombre debe estar en min\xFAsculas, sin espacios ni caracteres especiales."}});Ce(n),t=n}let o=await it({message:"\xBFPara qui\xE9n es este proyecto?",options:[{label:"Clientes de Lexy",value:"cliente",hint:"Producto de cara al cliente final"},{label:"Equipo interno / CRM",value:"crm",hint:"Herramienta densa para el equipo Lexy"},{label:"Ambos o a\xFAn no lo s\xE9",value:"mixto",hint:"Se decide por pantalla m\xE1s adelante"}],initialValue:"mixto"});Ce(o);let a=await it({message:"\xBFC\xF3mo es lo que vas a construir?",options:Ee.map(n=>({label:n.label,value:n.value,hint:n.hint})),initialValue:"app"});return Ce(a),{projectName:t,architecture:rt(a),world:o}};var Vo=["feature","layer"],qo=["cliente","crm","mixto"],Uo=e=>new Promise((t,o)=>{zo("pnpm",["install"],{cwd:e,stdio:"ignore",shell:!0}).on("close",n=>n===0?t():o(new Error(`pnpm install fall\xF3 con c\xF3digo ${n}`)))}),se=async(e,t)=>{let o;!!(e&&t.type)?(Vo.includes(t.type)||(console.error(T.red(`Error: la arquitectura "${t.type}" no es v\xE1lida. Usa "feature" o "layer".`)),process.exit(1)),t.world&&!qo.includes(t.world)&&(console.error(T.red(`Error: el mundo "${t.world}" no es v\xE1lido. Usa "cliente", "crm" o "mixto".`)),process.exit(1)),t.world||console.warn(T.yellow('Aviso: sin --world; se asume "mixto". ')+T.dim("Pasa --world cliente|crm para fijar densidad y voz desde el inicio.")),o={projectName:e,architecture:t.type,world:t.world??"mixto"},console.log(T.blue("Modo automatizado detectado. Saltando interfaz interactiva..."))):o=await lt(e),Mo(`Nombre: ${o.projectName}
2573
2886
  Arquitectura: ${o.architecture}
2574
- Mundo: ${o.world}`,"Configuraci\xF3n de Proyecto");let n=yo();n.start("Construyendo tu proyecto...");let r=process.cwd();try{await Ue(o,r)}catch(i){throw n.stop(j.red("No se pudo crear el proyecto.")),i}t.install!==!1&&(n.message("Instalando dependencias base..."),await xo(r)),n.stop("\xA1Proyecto construido con \xE9xito!"),uo(j.green(`Todo listo en el directorio actual
2887
+ Mundo: ${o.world}`,"Configuraci\xF3n de Proyecto"),t.install!==!1&&await ae();let n=Fo();n.start("Construyendo tu proyecto...");let r=process.cwd();try{await Qe(o,r)}catch(i){throw n.stop(T.red("No se pudo crear el proyecto.")),i}t.install!==!1&&(n.message("Instalando dependencias base..."),await Uo(r)),n.stop("\xA1Proyecto construido con \xE9xito!"),$o(T.green(`Todo listo en el directorio actual
2575
2888
 
2576
- `)+j.dim(`Siguientes pasos:
2577
- `)+j.cyan(` pnpm dev
2578
- `)+j.cyan(" npx create-lexy add button"))};import vo from"fs/promises";import ho from"path";import S from"picocolors";import me from"picocolors";var V=(e,t)=>{let o=e.split(`
2889
+ `)+T.dim(`Siguientes pasos:
2890
+ `)+T.cyan(` pnpm dev
2891
+ `)+T.cyan(" npx create-lexy add button"))};import Ko from"fs/promises";import Ho from"path";import E from"picocolors";import je from"picocolors";var G=(e,t)=>{let o=e.split(`
2579
2892
  `),a=t.split(`
2580
- `),n=o.length,r=a.length,i=Array.from({length:n+1},()=>new Array(r+1).fill(0));for(let m=n-1;m>=0;m--)for(let y=r-1;y>=0;y--)i[m][y]=o[m]===a[y]?i[m+1][y+1]+1:Math.max(i[m+1][y],i[m][y+1]);let d=[],s=0,u=0;for(;s<n&&u<r;)o[s]===a[u]?(d.push({type:"same",text:o[s]}),s++,u++):i[s+1][u]>=i[s][u+1]?d.push({type:"del",text:o[s++]}):d.push({type:"add",text:a[u++]});for(;s<n;)d.push({type:"del",text:o[s++]});for(;u<r;)d.push({type:"add",text:a[u++]});return d},Y=e=>e.some(t=>t.type!=="same"),Be=(e,t=3)=>{if(!Y(e))return null;let o=new Array(e.length).fill(!1);e.forEach((r,i)=>{if(r.type!=="same")for(let d=Math.max(0,i-t);d<=Math.min(e.length-1,i+t);d++)o[d]=!0});let a=[],n=!1;for(let r=0;r<e.length;r++){if(!o[r]){n||(a.push(me.dim(" \u22EF")),n=!0);continue}n=!1;let i=e[r];i.type==="same"?a.push(` ${i.text}`):i.type==="del"?a.push(me.red(`- ${i.text}`)):a.push(me.green(`+ ${i.text}`))}return a.join(`
2581
- `)};var Je=async e=>{let t=process.cwd(),o=await O(t),a=e.toLowerCase(),{item:n,version:r}=await k(a),i=o.installed[a];console.log(S.bold(`
2582
- ${n.title??a}`)+S.dim(` \xB7 instalado con registry@${i??"?"} \xB7 vigente registry@${r}
2583
- `));let d=!1;for(let s of T(n,o)){let u=await vo.readFile(ho.join(t,s.relPath),s.encoding??"utf-8").catch(()=>null);if(u===null){console.log(S.red(`\u2717 ${s.relPath} no existe localmente`)+S.dim(` \u2014 cr\xE9alo con \`create-lexy add ${a}\``)),d=!0;continue}if(s.encoding==="base64"){u===s.content?console.log(S.green(`\u2713 ${s.relPath}`)+S.dim(" sin diferencias")):(d=!0,console.log(S.yellow(`\xB1 ${s.relPath}`)+S.dim(" (binario difiere del registry)")));continue}let m=Be(V(u,s.content));m===null?console.log(S.green(`\u2713 ${s.relPath}`)+S.dim(" sin diferencias")):(d=!0,console.log(S.yellow(`\xB1 ${s.relPath}`)+S.dim(" (\u2212 local \xB7 + registry)")),console.log(m))}d&&(process.exitCode=1)};import _ from"fs/promises";import v from"path";import C from"picocolors";var We=async e=>{let t=process.cwd(),o=0,a=c=>console.log(C.green(" \u2713 ")+c),n=c=>console.log(C.yellow(" \u2022 ")+c),r=(c,l)=>{o=1,console.log(C.red(" \u2717 ")+c),l&&console.log(C.dim(` \u2192 ${l}`))};console.log(C.bold(`
2893
+ `),n=o.length,r=a.length,i=Array.from({length:n+1},()=>new Array(r+1).fill(0));for(let u=n-1;u>=0;u--)for(let y=r-1;y>=0;y--)i[u][y]=o[u]===a[y]?i[u+1][y+1]+1:Math.max(i[u+1][y],i[u][y+1]);let p=[],s=0,m=0;for(;s<n&&m<r;)o[s]===a[m]?(p.push({type:"same",text:o[s]}),s++,m++):i[s+1][m]>=i[s][m+1]?p.push({type:"del",text:o[s++]}):p.push({type:"add",text:a[m++]});for(;s<n;)p.push({type:"del",text:o[s++]});for(;m<r;)p.push({type:"add",text:a[m++]});return p},le=e=>e.some(t=>t.type!=="same"),ct=(e,t=3)=>{if(!le(e))return null;let o=new Array(e.length).fill(!1);e.forEach((r,i)=>{if(r.type!=="same")for(let p=Math.max(0,i-t);p<=Math.min(e.length-1,i+t);p++)o[p]=!0});let a=[],n=!1;for(let r=0;r<e.length;r++){if(!o[r]){n||(a.push(je.dim(" \u22EF")),n=!0);continue}n=!1;let i=e[r];i.type==="same"?a.push(` ${i.text}`):i.type==="del"?a.push(je.red(`- ${i.text}`)):a.push(je.green(`+ ${i.text}`))}return a.join(`
2894
+ `)};var dt=async e=>{let t=process.cwd(),o=await z(t),a=e.toLowerCase(),{item:n,version:r}=await C(a),i=o.installed[a];console.log(E.bold(`
2895
+ ${n.title??a}`)+E.dim(` \xB7 instalado con registry@${i??"?"} \xB7 vigente registry@${r}
2896
+ `));let p=!1;for(let s of O(n,o)){let m=await Ko.readFile(Ho.join(t,s.relPath),s.encoding??"utf-8").catch(()=>null);if(m===null){console.log(E.red(`\u2717 ${s.relPath} no existe localmente`)+E.dim(` \u2014 cr\xE9alo con \`create-lexy add ${a}\``)),p=!0;continue}if(s.encoding==="base64"){m===s.content?console.log(E.green(`\u2713 ${s.relPath}`)+E.dim(" sin diferencias")):(p=!0,console.log(E.yellow(`\xB1 ${s.relPath}`)+E.dim(" (binario difiere del registry)")));continue}let u=ct(G(m,s.content));u===null?console.log(E.green(`\u2713 ${s.relPath}`)+E.dim(" sin diferencias")):(p=!0,console.log(E.yellow(`\xB1 ${s.relPath}`)+E.dim(" (\u2212 local \xB7 + registry)")),console.log(u))}p&&(process.exitCode=1)};import M from"fs/promises";import w from"path";import N from"picocolors";var ce=async e=>{let t=process.cwd(),o=0,a=l=>console.log(N.green(" \u2713 ")+l),n=l=>console.log(N.yellow(" \u2022 ")+l),r=(l,c)=>{o=1,console.log(N.red(" \u2717 ")+l),c&&console.log(N.dim(` \u2192 ${c}`))};console.log(N.bold(`
2584
2897
  Diagn\xF3stico del proyecto Lexy
2585
- `));let i;try{i=await O(t),a(`.lexy v\xE1lido (arquitectura ${i.architecture}${i.world?`, mundo ${i.world}`:""})`)}catch(c){return r(c.message),1}await _.access(v.join(t,"src/lexy-theme.css")).then(()=>!0,()=>!1)?a("theme presente (src/lexy-theme.css)"):r("falta src/lexy-theme.css","re-cr\xE9alo desde un proyecto nuevo o copia el theme del registry");let s=v.join(i.paths.lib,"utils/cn.ts");await _.access(v.join(t,s)).then(()=>!0,()=>!1)?a(`helper cn presente (${s})`):r(`falta el helper cn (${s})`);let m=await _.readFile(v.join(t,"package.json"),"utf-8").then(c=>JSON.parse(c)).catch(()=>null),y=async(c,l)=>{await _.access(v.join(t,c)).then(()=>!0,()=>!1)?a(`${l} presente (${c})`):r(`falta ${l} (${c})`)},z=(c,l)=>{if(!m){r("package.json no se pudo leer para validar scripts del prototipo");return}let g=m.scripts?.[c];if(!g){r(`falta el script ${c} en package.json`,l?`agrega \`${l}\``:void 0);return}if(l&&!g.includes(l)){r(`el script ${c} no ejecuta ${l}`);return}a(`script ${c} configurado`)};if(!i.prototype)n("prototipo funcional no habilitado \u2014 proyecto anterior al runtime de datos y ports");else{let c=i.prototype.dataContractPath;if(!c)n("contrato de datos no configurado \u2014 proyecto anterior a la Spec 1");else{await y(c,"contrato de datos");let l=v.join(v.dirname(c),"data-contract-schema.ts");await y(l,"schema del contrato"),await y("scripts/check-data-contract.ts","validador del contrato"),z("check:data-contract","tsx scripts/check-data-contract.ts")}i.prototype.runtimeVersion?(i.prototype.mockStorePath?(await y(i.prototype.mockStorePath,"mock-store del prototipo"),await y(v.join(v.dirname(i.prototype.mockStorePath),"fixtures.ts"),"fixtures del prototipo")):r("mockStorePath no est\xE1 configurado en .lexy"),i.prototype.portsPath?await y(i.prototype.portsPath,"ports del prototipo"):r("portsPath no est\xE1 configurado en .lexy")):n("runtime del prototipo no habilitado \u2014 proyecto anterior a la Spec 2"),i.prototype.designerPanelVersion?(i.prototype.designerPanelPath?await y(i.prototype.designerPanelPath,"panel de asistencia al Designer"):r("designerPanelPath no est\xE1 configurado en .lexy"),i.prototype.designerActivityStorePath?await y(i.prototype.designerActivityStorePath,"store de actividad del Designer"):r("designerActivityStorePath no est\xE1 configurado en .lexy")):n("panel de asistencia al Designer no habilitado \u2014 proyecto anterior a la Spec 4")}let M=v.join(t,"ai/lexy-ai-manifest.json"),p=await _.readFile(M,"utf-8").catch(()=>null);if(p===null)console.log(C.dim(" \xB7 capa de IA no instalada (npx @lexydesign/ai install) \u2014 opcional"));else try{let c=JSON.parse(p),l=c.files??[],g=[];for(let P of l)await _.access(v.join(t,P)).then(()=>!0,()=>!1)||g.push(P);g.length>0?r(`capa de IA ${c.aiVersion??"?"} incompleta \u2014 faltan ${g.length} archivo(s) (${g.slice(0,3).join(", ")}${g.length>3?", \u2026":""})`,"npx @lexydesign/ai install"):a(`capa de IA ${c.aiVersion??"?"} completa (${l.length} archivos)`)}catch{r("ai/lexy-ai-manifest.json no es JSON v\xE1lido","regenera con `npx @lexydesign/ai install`")}let f=Object.entries(i.installed);if(f.length===0)console.log(C.dim(`
2586
- Sin componentes instalados a\xFAn (create-lexy add <nombre>).`));else{let c=await W();console.log(C.bold(`
2587
- Componentes instalados (registry vigente: ${c})
2588
- `));for(let[l,g]of f){let P;try{P=await k(l)}catch(L){r(`${l}: ${L.message}`);continue}let U=T(P.item,i),x=[],A=!1;for(let L of U){let H=await _.readFile(v.join(t,L.relPath),"utf-8").catch(()=>null);H===null?x.push(L.relPath):Y(V(H,L.content))&&(A=!0)}if(x.length>0){r(`${l}: archivos faltantes (${x.join(", ")})`,`create-lexy add ${l}`);continue}if(!A){a(`${l} al d\xEDa (${P.version})`);continue}let ee=!0;if(g&&g!==P.version)try{let L=await k(l,g),H=T(L.item,i);ee=!1;for(let he of H){let be=await _.readFile(v.join(t,he.relPath),"utf-8").catch(()=>null);(be===null||Y(V(be,he.content)))&&(ee=!0)}}catch{}ee?e.strict?r(`${l}: editado localmente (difiere del registry vigente)`,`create-lexy diff ${l}`):n(`${l}: editado localmente \u2014 divergencia deliberada (m\xEDrala con \`create-lexy diff ${l}\`)`):r(`${l}: desactualizado (instalado con ${g}, vigente ${P.version})`,`create-lexy diff ${l} \xB7 create-lexy add ${l} --overwrite`)}}return console.log(o===0?C.green(`
2898
+ `));let i;try{i=await z(t),a(`.lexy v\xE1lido (arquitectura ${i.architecture}${i.world?`, mundo ${i.world}`:""})`)}catch(l){return r(l.message),1}await M.access(w.join(t,"src/lexy-theme.css")).then(()=>!0,()=>!1)?a("theme presente (src/lexy-theme.css)"):r("falta src/lexy-theme.css","re-cr\xE9alo desde un proyecto nuevo o copia el theme del registry");let s=w.join(i.paths.lib,"utils/cn.ts");await M.access(w.join(t,s)).then(()=>!0,()=>!1)?a(`helper cn presente (${s})`):r(`falta el helper cn (${s})`);let u=await M.readFile(w.join(t,"package.json"),"utf-8").then(l=>JSON.parse(l)).catch(()=>null),y=async(l,c)=>{await M.access(w.join(t,l)).then(()=>!0,()=>!1)?a(`${c} presente (${l})`):r(`falta ${c} (${l})`)},R=(l,c)=>{if(!u){r("package.json no se pudo leer para validar scripts del prototipo");return}let f=u.scripts?.[l];if(!f){r(`falta el script ${l} en package.json`,c?`agrega \`${c}\``:void 0);return}if(c&&!f.includes(c)){r(`el script ${l} no ejecuta ${c}`);return}a(`script ${l} configurado`)};if(!i.prototype)n("prototipo funcional no habilitado \u2014 proyecto anterior al runtime de datos y ports");else{let l=i.prototype.dataContractPath;if(!l)n("contrato de datos no configurado \u2014 proyecto anterior a la Spec 1");else{await y(l,"contrato de datos");let c=w.join(w.dirname(l),"data-contract-schema.ts");await y(c,"schema del contrato"),await y("scripts/check-data-contract.ts","validador del contrato"),R("check:data-contract","tsx scripts/check-data-contract.ts")}i.prototype.runtimeVersion?(i.prototype.mockStorePath?(await y(i.prototype.mockStorePath,"mock-store del prototipo"),await y(w.join(w.dirname(i.prototype.mockStorePath),"fixtures.ts"),"fixtures del prototipo")):r("mockStorePath no est\xE1 configurado en .lexy"),i.prototype.portsPath?await y(i.prototype.portsPath,"ports del prototipo"):r("portsPath no est\xE1 configurado en .lexy")):n("runtime del prototipo no habilitado \u2014 proyecto anterior a la Spec 2"),i.prototype.designerPanelVersion?(i.prototype.designerPanelPath?await y(i.prototype.designerPanelPath,"panel de asistencia al Designer"):r("designerPanelPath no est\xE1 configurado en .lexy"),i.prototype.designerActivityStorePath?await y(i.prototype.designerActivityStorePath,"store de actividad del Designer"):r("designerActivityStorePath no est\xE1 configurado en .lexy")):n("panel de asistencia al Designer no habilitado \u2014 proyecto anterior a la Spec 4")}let v=w.join(t,"ai/lexy-ai-manifest.json"),d=await M.readFile(v,"utf-8").catch(()=>null);if(d===null)console.log(N.dim(" \xB7 capa de IA no instalada (npx create-lexy install-ai) \u2014 opcional"));else try{let l=JSON.parse(d),c=l.files??[],f=[];for(let b of c)await M.access(w.join(t,b)).then(()=>!0,()=>!1)||f.push(b);f.length>0?r(`capa de IA ${l.aiVersion??"?"} incompleta \u2014 faltan ${f.length} archivo(s) (${f.slice(0,3).join(", ")}${f.length>3?", \u2026":""})`,"npx create-lexy install-ai"):a(`capa de IA ${l.aiVersion??"?"} completa (${c.length} archivos)`)}catch{r("ai/lexy-ai-manifest.json no es JSON v\xE1lido","regenera con `npx create-lexy install-ai`")}let g=Object.entries(i.installed);if(g.length===0)console.log(N.dim(`
2899
+ Sin componentes instalados a\xFAn (create-lexy add <nombre>).`));else{let l=await te();console.log(N.bold(`
2900
+ Componentes instalados (registry vigente: ${l})
2901
+ `));for(let[c,f]of g){let b;try{b=await C(c)}catch($){r(`${c}: ${$.message}`);continue}let K=O(b.item,i),h=[],_=!1;for(let $ of K){let X=await M.readFile(w.join(t,$.relPath),"utf-8").catch(()=>null);X===null?h.push($.relPath):le(G(X,$.content))&&(_=!0)}if(h.length>0){r(`${c}: archivos faltantes (${h.join(", ")})`,`create-lexy add ${c}`);continue}if(!_){a(`${c} al d\xEDa (${b.version})`);continue}let H=!0;if(f&&f!==b.version)try{let $=await C(c,f),X=O($.item,i);H=!1;for(let De of X){let ze=await M.readFile(w.join(t,De.relPath),"utf-8").catch(()=>null);(ze===null||le(G(ze,De.content)))&&(H=!0)}}catch{}H?e.strict?r(`${c}: editado localmente (difiere del registry vigente)`,`create-lexy diff ${c}`):n(`${c}: editado localmente \u2014 divergencia deliberada (m\xEDrala con \`create-lexy diff ${c}\`)`):r(`${c}: desactualizado (instalado con ${f}, vigente ${b.version})`,`create-lexy diff ${c} \xB7 create-lexy add ${c} --overwrite`)}}return console.log(o===0?N.green(`
2589
2902
  Todo en orden.
2590
- `):C.red(`
2903
+ `):N.red(`
2591
2904
  Hay problemas que atender (exit 1).
2592
- `)),o};import ue from"fs/promises";import Ge from"path";import{note as bo,outro as wo}from"@clack/prompts";import ye from"picocolors";var X="LEXY-KICKOFF.md",So=`# Kickoff de proyecto Lexy \u2014 protocolo de entrevista
2905
+ `)),o};import L from"fs/promises";import j from"path";import U from"picocolors";import pt from"path";import{fileURLToPath as Jo}from"url";var Ie=pt.resolve(pt.dirname(Jo(import.meta.url)),"../templates");var Te="ai/lexy-ai-manifest.json",Bo=new Set(["ai/PROJECT-CONTEXT.md"]),Ne=async e=>{try{return JSON.parse(await L.readFile(e,"utf-8"))}catch{return null}},mt=async(e,t=e)=>{let o=[];for(let a of await L.readdir(e,{withFileTypes:!0})){let n=j.join(e,a.name);a.isDirectory()?o.push(...await mt(n,t)):o.push(j.relative(t,n))}return o},Y=async(e,t)=>{let o=process.cwd(),a=await Ne(j.join(o,".lexy"));a||console.log(U.yellow("Aviso: no hay .lexy en este directorio \u2014 se asumen rutas de arquitectura layer.")+U.dim(" (en proyectos create-lexy este archivo existe siempre)"));let n=a?.architecture??"layer",r=n==="feature",i=a?.paths?.components??(r?"src/shared/components/base":"src/components/base"),p=a?.componentImportPattern??(r?"@/shared/components/base/{Component}":"@/components/base/{Component}"),s=!!a?.prototype,m=!!(a?.prototype?.dataContractVersion&&a.prototype.dataContractPath),u=!!(a?.prototype?.runtimeVersion&&a.prototype.mockStorePath&&a.prototype.portsPath),y=!!(a?.prototype?.designerPanelVersion&&a.prototype.designerPanelPath&&a.prototype.designerActivityStorePath),R=(await mt(Ie)).sort(),v=[],d=[];for(let f of R){let b=j.join(o,f);if(await L.access(b).then(()=>!0,()=>!1)&&Bo.has(f)&&!e.force){d.push(f);continue}await L.mkdir(j.dirname(b),{recursive:!0});let h=await L.readFile(j.join(Ie,f),"utf-8");if(f==="ai/PROJECT-CONTEXT.md"){let _=await Ne(j.join(o,"package.json")),H={cliente:"cliente (persona en un momento dif\xEDcil)",crm:"CRM / equipo interno Lexy",mixto:"mixto \u2014 a\xFAn sin definir, pregunta al dise\xF1ador"};h=h.replaceAll("{{PROJECT_NAME}}",_?.name??j.basename(o)).replaceAll("{{WORLD}}",H[a?.world??"mixto"]??"mixto \u2014 a\xFAn sin definir").replaceAll("{{GENERATED_AT}}",new Date().toISOString().slice(0,10))}await L.writeFile(b,h),v.push(f)}let g=j.join(o,"package.json"),l=await Ne(g);l&&(l.scripts??={},l.scripts["lint:geometry"]||(l.scripts["lint:geometry"]="node scripts/check-geometry.mjs",await L.writeFile(g,JSON.stringify(l,null,2)+`
2906
+ `),v.push("package.json (script lint:geometry)")));let c={$comment:"Generado por create-lexy install-ai \u2014 no editar a mano; regenerar con `npx create-lexy install-ai`.",aiVersion:t,generatedAt:new Date().toISOString(),model:"registry-only: los componentes viven en este proyecto. Descubre con viewList, mira con view, instala con add, edita localmente con libertad; diff/doctor mantienen la divergencia visible.",registry:{package:a?.registry?.package??"@lexydesign/registry",cdn:a?.registry?.cdn??"https://cdn.jsdelivr.net/npm/@lexydesign/registry",catalogUrl:`${a?.registry?.cdn??"https://cdn.jsdelivr.net/npm/@lexydesign/registry"}@latest/r/registry.json`},commands:{viewList:"npx create-lexy view --list",view:"npx create-lexy view {component}",add:"npx create-lexy add {component}",diff:"npx create-lexy diff {component}",doctor:"npx create-lexy doctor"},architecture:n,componentImportPattern:p,componentsPath:i,docPattern:`${i}/{Component}.md`,prototype:s?{enabled:!0,dataContractVersion:m?a.prototype.dataContractVersion:null,dataContractPath:m?a.prototype.dataContractPath:null,runtimeEnabled:u,runtimeVersion:u?a.prototype.runtimeVersion:null,mockStorePath:u?a.prototype.mockStorePath:null,fixturesPath:u?a.prototype.fixturesPath:null,portsPath:u?a.prototype.portsPath:null,designerPanelEnabled:y,designerPanelVersion:y?a.prototype.designerPanelVersion:null,designerPanelPath:y?a.prototype.designerPanelPath:null,designerActivityStorePath:y?a.prototype.designerActivityStorePath:null,checkDataContractCommand:m?"pnpm check:data-contract":null,checkPrototypeCommand:m?"pnpm check:prototype":null,checkCommand:m?"pnpm check:data-contract":null}:{enabled:!1,dataContractVersion:null,dataContractPath:null,runtimeEnabled:!1,runtimeVersion:null,mockStorePath:null,fixturesPath:null,portsPath:null,designerPanelEnabled:!1,designerPanelVersion:null,designerPanelPath:null,designerActivityStorePath:null,checkDataContractCommand:null,checkPrototypeCommand:null,checkCommand:null},designGuidance:{"elecci\xF3n de mundo (cliente vs CRM)":"ai/pautas/diseno-cliente.md \xB7 ai/pautas/diseno-crm-lexy.md","jerarqu\xEDa y progressive disclosure":"ai/pautas/arquitectura-informacion-ux.md","densidad, espaciado, tokens, tipograf\xEDa":"ai/pautas/sistema-visual.md","elecci\xF3n de componentes y estados obligatorios":"ai/pautas/buenas-practicas.md","composiciones can\xF3nicas":"ai/pautas/recetas-layout.md","voz, tono y microcopy":"ai/pautas/ux-writing.md","vara de calidad / pase anti-gen\xE9rico":"ai/pautas/calidad-industria.md"},files:[...R,Te].sort()};await L.mkdir(j.join(o,"ai"),{recursive:!0}),await L.writeFile(j.join(o,Te),JSON.stringify(c,null,2)+`
2907
+ `),console.log(U.green(`
2908
+ \u2713 Capa de IA instalada (${n})`)),console.log(U.dim(` ${v.length} archivo(s) escritos, manifest generado \u2192 ${Te}`));for(let f of d)console.log(U.yellow(` \u2022 ${f} ya exist\xEDa \u2014 se conserv\xF3 (es el brief vivo; --force lo pisa)`));console.log(U.dim(`
2909
+ Entry points: AGENTS.md \xB7 CLAUDE.md \xB7 .claude/skills/ \xB7 .github/copilot-instructions.md`))};import Re from"fs/promises";import ut from"path";import{note as Wo,outro as Go}from"@clack/prompts";import _e from"picocolors";var de="LEXY-KICKOFF.md",Yo=`# Kickoff de proyecto Lexy \u2014 protocolo de entrevista
2593
2910
 
2594
2911
  > **Para el agente (Claude Code):** este archivo es tu guion. La persona que
2595
2912
  > tienes enfrente es **dise\xF1adora, no programadora**: no le preguntes por
@@ -2645,12 +2962,12 @@ En **esta misma carpeta vac\xEDa**, corre:
2645
2962
 
2646
2963
  \`\`\`bash
2647
2964
  npx create-lexy create <nombre> --type <layer|feature> --world <cliente|crm|mixto>
2648
- npx @lexydesign/ai install
2965
+ npx create-lexy install-ai
2649
2966
  \`\`\`
2650
2967
 
2651
2968
  ## 4. Volcar la entrevista en el brief vivo
2652
2969
 
2653
- 1. Abre \`ai/PROJECT-CONTEXT.md\` (lo cre\xF3 \`@lexydesign/ai install\`) y
2970
+ 1. Abre \`ai/PROJECT-CONTEXT.md\` (lo cre\xF3 \`create-lexy install-ai\`) y
2654
2971
  compl\xE9talo con lo que recopilaste: **qu\xE9 se construye**, **para qui\xE9n**,
2655
2972
  **pantallas y flujos clave**, un resumen de **datos principales**,
2656
2973
  **referencias** y **decisiones/restricciones** ya tomadas.
@@ -2676,19 +2993,16 @@ producci\xF3n; el panel registra cargas y publicaciones para inspecci\xF3n.
2676
2993
 
2677
2994
  ## 5. Cerrar
2678
2995
 
2679
- Borra este archivo (\`${X}\`): su trabajo termin\xF3. Conf\xEDrmale a la
2996
+ Borra este archivo (\`${de}\`): su trabajo termin\xF3. Conf\xEDrmale a la
2680
2997
  persona que su proyecto est\xE1 listo y prop\xF3n el primer paso concreto
2681
2998
  (p. ej. "\xBFDise\xF1amos la pantalla de inicio?").
2682
- `,Qe=async e=>{let t=process.cwd();for(let n of["package.json",".lexy"])if(await ue.access(Ge.join(t,n)).then(()=>!0,()=>!1))throw new Error(`El directorio actual ya contiene un proyecto (${n}). \`kickoff\` es para empezar de cero en una carpeta vac\xEDa.`);let o=Ge.join(t,X);if(await ue.access(o).then(()=>!0,()=>!1)&&!e.force)throw new Error(`${X} ya existe. Usa --force para regenerarlo.`);await ue.writeFile(o,So),bo(`Se cre\xF3 ${ye.cyan(X)} en esta carpeta.
2683
-
2684
- Abre la carpeta con Claude Code y di: `+ye.bold("\xABay\xFAdame a arrancar mi proyecto Lexy\xBB")+`.
2685
- El agente te entrevistar\xE1 y montar\xE1 el proyecto por ti.`,"Kickoff listo"),wo(ye.green("Sin flags, sin prompts t\xE9cnicos \u2014 solo conversa con el agente."))};import fe from"fs/promises";import Z from"path";import I from"picocolors";var xe="@lexydesign/kit",Ye=`https://cdn.jsdelivr.net/npm/${xe}`,Xe=8e3,ge=async e=>{let t=await fetch(e,{signal:AbortSignal.timeout(Xe)});if(!t.ok){let o=new Error(`HTTP ${t.status} al pedir ${e}`);throw o.status=t.status,o}return Buffer.from(await t.arrayBuffer())},ko=async()=>{try{let t=await fetch(`https://registry.npmjs.org/${xe}/latest`,{signal:AbortSignal.timeout(Xe)});if(t.ok)return(await t.json()).version}catch{}return JSON.parse((await ge(`${Ye}@latest/package.json`)).toString("utf-8")).version},Ze=async e=>{let t=process.cwd(),o=Z.resolve(t,e.dir??"lexy-kit"),a=Z.relative(t,o)||".";if(await fe.access(o).then(()=>!0).catch(()=>!1)&&!e.force)throw new Error(`Ya existe ${I.bold(a)}. Usa ${I.cyan("--force")} para sobrescribir o ${I.cyan("--dir <ruta>")} para otra carpeta.`);let r=await ko();console.log(I.dim(`
2686
- Trayendo ${xe}@${r} \u2192 ${a}/
2687
- `));let i=`${Ye}@${r}/kit`,d=JSON.parse((await ge(`${i}/manifest.json`)).toString("utf-8")),s=["index.html","kit.css","kit.js","manifest.json","README.md","AGENTS.md","llms.txt","llms-full.txt","fonts/noto-sans-latin.woff2","fonts/OFL-NotoSans.txt",...d.guides?.pautas??[],...d.components.map(m=>m.file),...d.blocks.map(m=>m.file)],u=0;for(let m of s)try{let y=await ge(`${i}/${m}`),z=Z.join(o,m);await fe.mkdir(Z.dirname(z),{recursive:!0}),await fe.writeFile(z,y),u+=1}catch(y){console.warn(I.yellow(`\u26A0 no se pudo traer ${m}`)+I.dim(` (${y.message})`))}console.log(I.green("\u2713 Kit listo")+I.dim(` \u2014 ${u} archivo(s), ${d.components.length} componente(s) + ${d.blocks.length} block(s)
2688
- `)),console.log(` Abre ${I.bold(`${a}/index.html`)} en el navegador.`),console.log(I.dim(` El cat\xE1logo m\xE1quina-legible est\xE1 en ${a}/manifest.json.
2689
- `))};import Eo from"fs/promises";import ve from"path";import E from"picocolors";var K=e=>console.log(E.bold(E.cyan(`
2999
+ `,pe=async e=>{let t=process.cwd();for(let n of["package.json",".lexy"])if(await Re.access(ut.join(t,n)).then(()=>!0,()=>!1))throw new Error(`El directorio actual ya contiene un proyecto (${n}). \`kickoff\` es para empezar de cero en una carpeta vac\xEDa.`);let o=ut.join(t,de);if(await Re.access(o).then(()=>!0,()=>!1)&&!e.force)throw new Error(`${de} ya existe. Usa --force para regenerarlo.`);await Re.writeFile(o,Yo),Wo(`Se cre\xF3 ${_e.cyan(de)} en esta carpeta.
3000
+
3001
+ Abre la carpeta con Claude Code y di: `+_e.bold("\xABay\xFAdame a arrancar mi proyecto Lexy\xBB")+`.
3002
+ El agente te entrevistar\xE1 y montar\xE1 el proyecto por ti.`,"Kickoff listo"),Go(_e.green("Sin flags, sin prompts t\xE9cnicos \u2014 solo conversa con el agente."))};import Qo from"fs/promises";import Oe from"path";import I from"picocolors";var Q=e=>console.log(I.bold(I.cyan(`
2690
3003
  \u2500\u2500 ${e} \u2500\u2500
2691
- `))),et=async(e,t)=>{if(t.list||!e){let{index:i,version:d,source:s}=await je();K(`Cat\xE1logo Lexy \xB7 @lexydesign/registry@${d}${s==="bundle"?" (bundle local)":""}`);for(let u of i.items)console.log(` ${E.bold(u.name.padEnd(20))} ${E.dim(u.description??"")}`);console.log(E.dim(`
2692
- ${i.items.length} componente(s). Instala con: create-lexy add <nombre>`));return}let o=e.toLowerCase();if(t.installed){let i=process.cwd(),d=await O(i),s=d.installed[o];if(!s){console.error(E.red(`"${o}" no figura como instalado en .lexy. Inst\xE1lalo con \`create-lexy add ${o}\`.`)),process.exitCode=1;return}let{item:u}=await k(o,s).catch(()=>k(o));K(`${u.title??o} \xB7 copia local (instalado con registry@${s})`);for(let m of T(u,d)){let y=await Eo.readFile(ve.join(i,m.relPath),"utf-8").catch(()=>null);K(y===null?`${m.relPath} (FALTANTE)`:m.relPath),y!==null&&console.log(y)}return}let{item:a,version:n,source:r}=await k(o);K(`${a.title??a.name} \xB7 @lexydesign/registry@${n}${r==="bundle"?" (bundle local)":""}`),a.description&&console.log(a.description+`
2693
- `),console.log(E.dim("tipo: ")+a.type),console.log(E.dim("deps npm: ")+((a.dependencies??[]).join(", ")||"\u2014")),console.log(E.dim("deps registry: ")+((a.registryDependencies??[]).join(", ")||"\u2014")),console.log(E.dim("archivos: ")+a.files.map(i=>ve.posix.basename(i.path)).join(", ")),console.log(E.dim("instalar: ")+`create-lexy add ${a.name}`);for(let i of a.files)typeof i.content=="string"&&(K(ve.posix.basename(i.path)),console.log(i.content))};var To=tt.dirname(jo(import.meta.url)),Ro=JSON.parse(Po(tt.join(To,"../package.json"),"utf-8")),N=new Co,D=e=>async()=>{try{await e()}catch(t){console.error(Io.red(`
2694
- Error: `)+t.message),process.exit(1)}};N.name("create-lexy").description("CLI del Lexy Design System: crea proyectos y trae componentes a demanda.\nLos componentes viven en tu proyecto \u2014 m\xEDralos con `view`, inst\xE1lalos con `add`, ed\xEDtalos con libertad.").version(Ro.version);N.command("create",{isDefault:!0}).alias("init").description("Crea un proyecto Lexy vac\xEDo (React + Vite + TS + theme); los componentes llegan con `add`").argument("[project-name]","Nombre del proyecto").option("-t, --type <architecture>","Arquitectura (feature o layer) \u2014 activa el modo no interactivo").option("-w, --world <world>","Mundo de dise\xF1o (cliente, crm o mixto)").option("--no-install","No correr pnpm install al final").action((e,t)=>D(()=>He(e,t))());N.command("kickoff").description("Deja un .md de entrevista para que el agente conduzca el arranque de un dise\xF1ador (carpeta vac\xEDa)").option("--force","Regenerar el .md de kickoff si ya existe").action(e=>D(()=>Qe(e))());N.command("add").description("Instala componentes del registry en tu proyecto (local y editable), con sus dependencias").argument("<components...>","Nombres en el registry (ej: button card)").option("--overwrite","Sobrescribir copias locales con cambios sin preguntar").option("--no-install","No instalar dependencias npm").action((e,t)=>D(()=>Re(e,t))());N.command("view").description("Muestra c\xF3digo + doc + metadata de un componente antes de instalarlo").argument("[component]","Nombre en el registry (sin nombre: lista el cat\xE1logo)").option("--installed","Mostrar la copia local instalada en vez de la del registry").option("--list","Listar el cat\xE1logo completo").action((e,t)=>D(()=>et(e,t))());N.command("kit").description("Trae el kit HTML/low-fi (mismos componentes y blocks en HTML plano) a una carpeta").option("--dir <path>","Carpeta destino (por defecto: lexy-kit)").option("--force","Sobrescribir la carpeta si ya existe").action(e=>D(()=>Ze(e))());N.command("diff").description("Copia local vs versi\xF3n vigente del registry (exit 1 si hay diferencias)").argument("<component>","Nombre en el registry").action(e=>D(()=>Je(e))());N.command("doctor").description("Drift de todo lo instalado contra el registry (solo lectura; exit 1 con problemas)").option("--strict","Las ediciones locales tambi\xE9n hacen fallar").action(e=>D(async()=>{process.exitCode=await We(e)})());N.parse(process.argv);
3004
+ `))),yt=async(e,t)=>{if(t.list||!e){let{index:i,version:p,source:s}=await oe();Q(`Cat\xE1logo Lexy \xB7 @lexydesign/registry@${p}${s==="bundle"?" (bundle local)":""}`);for(let m of i.items)console.log(` ${I.bold(m.name.padEnd(20))} ${I.dim(m.description??"")}`);console.log(I.dim(`
3005
+ ${i.items.length} componente(s). Instala con: create-lexy add <nombre>`));return}let o=e.toLowerCase();if(t.installed){let i=process.cwd(),p=await z(i),s=p.installed[o];if(!s){console.error(I.red(`"${o}" no figura como instalado en .lexy. Inst\xE1lalo con \`create-lexy add ${o}\`.`)),process.exitCode=1;return}let{item:m}=await C(o,s).catch(()=>C(o));Q(`${m.title??o} \xB7 copia local (instalado con registry@${s})`);for(let u of O(m,p)){let y=await Qo.readFile(Oe.join(i,u.relPath),"utf-8").catch(()=>null);Q(y===null?`${u.relPath} (FALTANTE)`:u.relPath),y!==null&&console.log(y)}return}let{item:a,version:n,source:r}=await C(o);Q(`${a.title??a.name} \xB7 @lexydesign/registry@${n}${r==="bundle"?" (bundle local)":""}`),a.description&&console.log(a.description+`
3006
+ `),console.log(I.dim("tipo: ")+a.type),console.log(I.dim("deps npm: ")+((a.dependencies??[]).join(", ")||"\u2014")),console.log(I.dim("deps registry: ")+((a.registryDependencies??[]).join(", ")||"\u2014")),console.log(I.dim("archivos: ")+a.files.map(i=>Oe.posix.basename(i.path)).join(", ")),console.log(I.dim("instalar: ")+`create-lexy add ${a.name}`);for(let i of a.files)typeof i.content=="string"&&(Q(Oe.posix.basename(i.path)),console.log(i.content))};import{existsSync as Xo}from"fs";import Zo from"fs/promises";import{basename as ea,join as vt}from"path";import{confirm as ta,isCancel as Le,multiselect as oa,note as ft,outro as gt,select as xt}from"@clack/prompts";import x from"picocolors";function Ae(e){return aa(e).length}function me(e,t){let o=t-Ae(e);return o>0?e+" ".repeat(o):e}function aa(e){return e.replace(/\[[0-9;]*m/g,"")}function na(e,t){let o=process.env.HOME??process.env.USERPROFILE,a=e;return o&&(a===o||a.startsWith(o+"/"))&&(a="~"+a.slice(o.length)),a.length<=t?a:"\u2026"+a.slice(a.length-(t-1))}var ht=["\u2588 \u2588\u2580\u2580 \u2588 \u2588 \u2588 \u2588 \u2588\u2580\u2580 \u2588 \u2588","\u2588 \u2588\u2580\u2580 \u2588 \u2588 \u2588 \u2588 \u2588","\u2588\u2584\u2584 \u2588\u2584\u2584 \u2588 \u2588 \u2588 \u2588\u2584\u2584 \u2588\u2584\u2584 \u2588"],ra=[x.cyan,x.blue,x.blue];function ia(e){let t=ht.map((v,d)=>x.bold(ra[d](v))),o=Ae(ht[0]),a=[x.dim("Lexy Design System"),`${x.dim("versi\xF3n")} ${x.bold(x.cyan(`v${e}`))}`,x.cyan(na(process.cwd(),38))],n=Math.max(...a.map(Ae)),r=2,i=5,p=r+o+i+n+r,s="\u2500".repeat(p),m=(v,d)=>{let g=" ".repeat(r)+me(v,o)+" ".repeat(i)+me(d,n)+" ".repeat(r);return x.dim("\u2502")+g+x.dim("\u2502")},u=Math.floor(i/2),y=()=>{let v=" ".repeat(r)+me(t[1],o)+" ".repeat(u)+x.dim("\u2502")+" ".repeat(i-u-1)+me(a[1],n)+" ".repeat(r);return x.dim("\u2502")+v+x.dim("\u2502")},R=x.dim("\u2502")+" ".repeat(p)+x.dim("\u2502");console.log(""),console.log(x.dim(`\u256D${s}\u256E`)),console.log(R),console.log(m(t[0],a[0])),console.log(y()),console.log(m(t[2],a[2])),console.log(R),console.log(x.dim(`\u2570${s}\u256F`)),console.log("")}function sa(){return Xo(vt(process.cwd(),".lexy"))}async function la(){try{let e=JSON.parse(await Zo.readFile(vt(process.cwd(),"package.json"),"utf-8"));if(e.name)return e.name}catch{}return ea(process.cwd())}async function bt({version:e}){console.clear(),ia(e);let t=sa();ft(t?`${x.dim("Proyecto:")} ${x.bold(await la())}`:x.dim("No hay un proyecto Lexy en esta carpeta todav\xEDa."),t?"Proyecto existente":"Carpeta vac\xEDa");let o=t?await xt({message:"\xBFQu\xE9 quieres hacer?",options:[{value:"add",label:"Agregar componente",hint:"instala un componente del registry en tu proyecto"},{value:"doctor",label:"Revisar salud del proyecto",hint:"detecta drift, versiones desactualizadas y problemas"},{value:"install-ai",label:"Instalar / actualizar IA",hint:"pautas, skills y entry points para agentes"}]}):await xt({message:"\xBFQu\xE9 quieres hacer?",options:[{value:"create",label:"Crear un proyecto ahora",hint:"responde t\xFA nombre, mundo y forma del producto"},{value:"kickoff",label:"Dejar que un agente me ayude",hint:"genera LEXY-KICKOFF.md para que Claude Code te entreviste"},{value:"help",label:"Ayuda / Documentaci\xF3n",hint:"comandos disponibles"}]});if(Le(o)){gt(x.dim("Operaci\xF3n cancelada."));return}switch(o){case"create":await se(void 0,{}),await da(e);return;case"kickoff":await pe({});return;case"help":ft(x.dim("Ejecuta ")+x.cyan("create-lexy --help")+x.dim(" para ver todos los comandos y flags."),"Ayuda");break;case"add":await ca();break;case"doctor":process.exitCode=await ce({});break;case"install-ai":await Y({},e);break}gt(x.green("\xA1Hasta luego!"))}async function ca(){let{index:e}=await oe(),t=await oa({message:"\xBFQu\xE9 componentes quieres instalar?",options:e.items.map(o=>({value:o.name,label:o.title??o.name,hint:o.description})),required:!0});Le(t)||await ie(t,{})}async function da(e){let t=await ta({message:"\xBFInstalar tambi\xE9n la capa de IA ahora?",initialValue:!0});Le(t)||!t||await Y({},e)}var ya=wt.dirname(ma(import.meta.url)),ue=JSON.parse(pa(wt.join(ya,"../package.json"),"utf-8"));et(ue.engines?.node??">=20");var D=new ua,F=e=>async()=>{try{await e()}catch(t){console.error(St.red(`
3007
+ Error: `)+t.message),process.exit(1)}};D.name("create-lexy").description("CLI del Lexy Design System: crea proyectos y trae componentes a demanda.\nLos componentes viven en tu proyecto \u2014 m\xEDralos con `view`, inst\xE1lalos con `add`, ed\xEDtalos con libertad.").version(ue.version);D.command("create",{isDefault:!0}).alias("init").description("Crea un proyecto Lexy vac\xEDo (React + Vite + TS + theme); los componentes llegan con `add`").argument("[project-name]","Nombre del proyecto").option("-t, --type <architecture>","Arquitectura (feature o layer) \u2014 activa el modo no interactivo").option("-w, --world <world>","Mundo de dise\xF1o (cliente, crm o mixto)").option("--no-install","No correr pnpm install al final").action((e,t)=>F(()=>se(e,t))());D.command("kickoff").description("Deja un .md de entrevista para que el agente conduzca el arranque de un dise\xF1ador (carpeta vac\xEDa)").option("--force","Regenerar el .md de kickoff si ya existe").action(e=>F(()=>pe(e))());D.command("add").description("Instala componentes del registry en tu proyecto (local y editable), con sus dependencias").argument("<components...>","Nombres en el registry (ej: button card)").option("--overwrite","Sobrescribir copias locales con cambios sin preguntar").option("--no-install","No instalar dependencias npm").action((e,t)=>F(()=>ie(e,t))());D.command("view").description("Muestra c\xF3digo + doc + metadata de un componente antes de instalarlo").argument("[component]","Nombre en el registry (sin nombre: lista el cat\xE1logo)").option("--installed","Mostrar la copia local instalada en vez de la del registry").option("--list","Listar el cat\xE1logo completo").action((e,t)=>F(()=>yt(e,t))());D.command("diff").description("Copia local vs versi\xF3n vigente del registry (exit 1 si hay diferencias)").argument("<component>","Nombre en el registry").action(e=>F(()=>dt(e))());D.command("doctor").description("Drift de todo lo instalado contra el registry (solo lectura; exit 1 con problemas)").option("--strict","Las ediciones locales tambi\xE9n hacen fallar").action(e=>F(async()=>{process.exitCode=await ce(e)})());D.command("install-ai").description("Instala o actualiza la capa de IA (pautas, skills, entry points para agentes) \u2014 idempotente").option("--force","Sobrescribir tambi\xE9n ai/PROJECT-CONTEXT.md (el brief vivo)").action(e=>F(()=>Y(e,ue.version))());process.argv.length<=2&&process.stdout.isTTY?bt({version:ue.version}).catch(e=>{console.error(St.red(`
3008
+ Error: `)+e.message),process.exit(1)}):D.parse(process.argv);