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.
- package/README.md +7 -2
- package/assets/fonts/{OFL-NotoSans.txt → LICENSE-Geist.txt} +4 -5
- package/assets/fonts/geist-mono-variable-italic.woff2 +0 -0
- package/assets/fonts/geist-mono-variable.woff2 +0 -0
- package/assets/fonts/geist-sans-variable-italic.woff2 +0 -0
- package/assets/fonts/geist-sans-variable.woff2 +0 -0
- package/assets/r/accordion.json +3 -3
- package/assets/r/alert-dialog.json +3 -3
- package/assets/r/app-accordion.json +1 -1
- package/assets/r/app-dialog.json +3 -3
- package/assets/r/app-header-bar.json +2 -2
- package/assets/r/app-sidebar.json +2 -2
- package/assets/r/avatar.json +3 -3
- package/assets/r/badge.json +3 -3
- package/assets/r/brand-background.json +1 -1
- package/assets/r/breadcrumb.json +3 -3
- package/assets/r/button-group.json +3 -3
- package/assets/r/button.json +3 -3
- package/assets/r/calendar.json +2 -2
- package/assets/r/card.json +3 -3
- package/assets/r/chart.json +2 -2
- package/assets/r/checkbox.json +2 -2
- package/assets/r/combobox.json +3 -3
- package/assets/r/command.json +3 -3
- package/assets/r/confirmacion.json +1 -1
- package/assets/r/counter-badge.json +3 -3
- package/assets/r/crm-desk.json +1 -1
- package/assets/r/crm-detalle-caso.json +5 -5
- package/assets/r/date-picker.json +1 -1
- package/assets/r/dialog.json +3 -3
- package/assets/r/dropdown-menu.json +3 -3
- package/assets/r/empty.json +2 -2
- package/assets/r/feature-card.json +3 -3
- package/assets/r/form.json +3 -3
- package/assets/r/header-bar.json +2 -2
- package/assets/r/input.json +3 -3
- package/assets/r/intake-wizard.json +1 -1
- package/assets/r/label.json +3 -3
- package/assets/r/logo.json +2 -2
- package/assets/r/menubar.json +3 -3
- package/assets/r/navigation-menu.json +3 -3
- package/assets/r/pagination.json +2 -2
- package/assets/r/popover.json +3 -3
- package/assets/r/profile-card.json +3 -3
- package/assets/r/progress.json +2 -2
- package/assets/r/radio-group.json +2 -2
- package/assets/r/registry.json +47 -47
- package/assets/r/scroll-area.json +2 -2
- package/assets/r/searchbox.json +3 -3
- package/assets/r/select.json +3 -3
- package/assets/r/separator.json +2 -2
- package/assets/r/sheet.json +2 -2
- package/assets/r/sidebar.json +3 -3
- package/assets/r/skeleton.json +2 -2
- package/assets/r/slider.json +3 -3
- package/assets/r/snippet.json +3 -3
- package/assets/r/spinner.json +2 -2
- package/assets/r/status-dot.json +3 -3
- package/assets/r/switch.json +3 -3
- package/assets/r/table.json +3 -3
- package/assets/r/tabs.json +3 -3
- package/assets/r/tag.json +3 -3
- package/assets/r/textarea.json +3 -3
- package/assets/r/toaster.json +3 -3
- package/assets/r/tooltip.json +3 -3
- package/assets/r/tree.json +3 -3
- package/assets/registry-version +1 -1
- package/assets/theme/lexy-theme.css +562 -112
- package/dist/index.js +590 -276
- package/package.json +4 -2
- package/templates/.claude/skills/lexy-design/SKILL.md +189 -0
- package/templates/.claude/skills/lexy-dev/SKILL.md +168 -0
- package/templates/.claude/skills/lexy-mock-data/SKILL.md +50 -0
- package/templates/.github/copilot-instructions.md +50 -0
- package/templates/.mcp.json +8 -0
- package/templates/AGENTS.md +243 -0
- package/templates/CLAUDE.md +61 -0
- package/templates/ai/IMPLEMENTATION-PROTOCOL.md +148 -0
- package/templates/ai/PRODUCTION-CLEANUP.md +17 -0
- package/templates/ai/PROJECT-CONTEXT.md +65 -0
- package/templates/ai/README.md +19 -0
- package/templates/ai/TECHNICAL-USAGE.md +220 -0
- package/templates/ai/pautas/arquitectura-informacion-ux.md +243 -0
- package/templates/ai/pautas/buenas-practicas.md +236 -0
- package/templates/ai/pautas/calidad-industria.md +109 -0
- package/templates/ai/pautas/diseno-cliente.md +136 -0
- package/templates/ai/pautas/diseno-crm-lexy.md +109 -0
- package/templates/ai/pautas/patrones-de-codigo.md +234 -0
- package/templates/ai/pautas/recetas-layout.md +419 -0
- package/templates/ai/pautas/sistema-visual.md +197 -0
- package/templates/ai/pautas/ux-writing.md +214 -0
- package/templates/scripts/check-geometry.mjs +139 -0
- 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
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
|
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
|
-
`,
|
|
602
|
+
`,Lt=`
|
|
625
603
|
.lexy-dp {
|
|
626
604
|
--dp-bg: #ffffff;
|
|
627
|
-
--dp-fg: #
|
|
628
|
-
--dp-card: #
|
|
605
|
+
--dp-fg: #0f172a;
|
|
606
|
+
--dp-card: #ffffff;
|
|
629
607
|
--dp-popover: #ffffff;
|
|
630
|
-
--dp-primary: #
|
|
608
|
+
--dp-primary: #4f46e5;
|
|
631
609
|
--dp-primary-fg: #ffffff;
|
|
632
|
-
--dp-muted: #
|
|
633
|
-
--dp-muted-fg: #
|
|
634
|
-
--dp-accent: #
|
|
635
|
-
--dp-accent-fg: #
|
|
636
|
-
--dp-border: #
|
|
637
|
-
--dp-ring: #
|
|
638
|
-
--dp-destructive: #
|
|
639
|
-
--dp-success: #
|
|
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: #
|
|
619
|
+
--dp-warning: #f59e0b;
|
|
642
620
|
--dp-warning-fg: #ffffff;
|
|
643
|
-
--dp-info: #
|
|
644
|
-
--dp-radius:
|
|
645
|
-
--dp-mono:
|
|
646
|
-
--dp-sans: system-ui, -apple-system,
|
|
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:
|
|
650
|
-
line-height: 1.
|
|
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
|
-
/*
|
|
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
|
|
672
|
-
background:
|
|
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:
|
|
678
|
-
padding:
|
|
679
|
-
font-size:
|
|
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
|
-
|
|
686
|
-
|
|
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 {
|
|
690
|
-
|
|
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:
|
|
711
|
+
padding: 1px 6px;
|
|
697
712
|
font-size: 10px;
|
|
698
|
-
font-weight:
|
|
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
|
|
718
|
+
/* \u2500\u2500 Scroll & Padding \u2500\u2500 */
|
|
704
719
|
.lexy-dp-scroll { height: 100%; overflow-y: auto; }
|
|
705
|
-
.lexy-dp-pad { padding:
|
|
720
|
+
.lexy-dp-pad { padding: 24px; }
|
|
706
721
|
|
|
707
|
-
/* \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:
|
|
727
|
+
gap: 8px;
|
|
713
728
|
border-bottom: 1px solid var(--dp-border);
|
|
714
|
-
background:
|
|
715
|
-
padding:
|
|
729
|
+
background: #f8fafc;
|
|
730
|
+
padding: 8px 16px;
|
|
716
731
|
}
|
|
717
732
|
|
|
718
|
-
/* \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:
|
|
724
|
-
padding:
|
|
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
|
-
|
|
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:
|
|
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:
|
|
781
|
+
padding: 2px 10px;
|
|
746
782
|
font-size: 11px;
|
|
747
|
-
font-weight:
|
|
783
|
+
font-weight: 600;
|
|
748
784
|
border: 1px solid transparent;
|
|
749
|
-
background:
|
|
750
|
-
color: var(--dp-primary
|
|
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 {
|
|
754
|
-
|
|
755
|
-
|
|
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
|
|
763
|
-
padding:
|
|
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-
|
|
766
|
-
|
|
767
|
-
|
|
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:
|
|
775
|
-
font-size:
|
|
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:
|
|
779
|
-
background:
|
|
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:
|
|
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
|
|
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:
|
|
857
|
+
background: #f8fafc;
|
|
800
858
|
border: 1px solid var(--dp-border);
|
|
801
859
|
border-radius: var(--dp-radius);
|
|
802
|
-
padding:
|
|
860
|
+
padding: 12px 14px;
|
|
803
861
|
overflow: auto;
|
|
804
862
|
white-space: pre;
|
|
805
|
-
color:
|
|
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:
|
|
810
|
-
font-weight:
|
|
867
|
+
font-size: 11.5px;
|
|
868
|
+
font-weight: 600;
|
|
811
869
|
text-transform: uppercase;
|
|
812
|
-
letter-spacing: 0.
|
|
813
|
-
color:
|
|
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
|
|
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
|
|
822
|
-
.lexy-dp-stack { display: flex; flex-direction: column; gap:
|
|
823
|
-
.lexy-dp-stack-sm { display: flex; flex-direction: column; gap:
|
|
824
|
-
.lexy-dp-stack-lg { display: flex; flex-direction: column; gap:
|
|
825
|
-
.lexy-dp-substack { display: flex; flex-direction: column; gap:
|
|
826
|
-
.lexy-dp-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap:
|
|
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
|
|
829
|
-
.lexy-dp-json-str { color:
|
|
830
|
-
.lexy-dp-json-num { color:
|
|
831
|
-
.lexy-dp-json-row { display: flex; align-items: flex-start; gap:
|
|
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:
|
|
839
|
-
padding:
|
|
897
|
+
gap: 6px;
|
|
898
|
+
padding: 3px 6px;
|
|
840
899
|
text-align: left;
|
|
841
900
|
background: transparent;
|
|
842
|
-
border:
|
|
843
|
-
|
|
901
|
+
border-radius: 4px;
|
|
902
|
+
transition: background 0.15s ease;
|
|
844
903
|
}
|
|
845
|
-
.lexy-dp-json-toggle:hover { background:
|
|
846
|
-
.lexy-dp-chevron { width: 14px; height: 14px; flex-shrink: 0; color: var(--dp-muted-fg); margin-top:
|
|
847
|
-
.lexy-dp-chevron--sm { width: 12px; height: 12px; margin-top:
|
|
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
|
|
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:
|
|
913
|
+
padding: 8px 0;
|
|
855
914
|
font-family: var(--dp-mono);
|
|
856
|
-
font-size:
|
|
857
|
-
line-height: 1.
|
|
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 {
|
|
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:
|
|
867
|
-
padding:
|
|
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 (
|
|
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:
|
|
953
|
+
padding: 12px 0;
|
|
898
954
|
display: flex;
|
|
899
955
|
flex-direction: column;
|
|
900
|
-
|
|
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:
|
|
908
|
-
font-size:
|
|
909
|
-
font-weight:
|
|
910
|
-
|
|
911
|
-
|
|
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:
|
|
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
|
-
|
|
926
|
-
padding: 5px 12px;
|
|
983
|
+
padding: 7px 12px;
|
|
927
984
|
font-family: var(--dp-mono);
|
|
928
985
|
font-size: 12px;
|
|
929
|
-
color:
|
|
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-
|
|
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
|
|
940
|
-
.lexy-dp-
|
|
941
|
-
.lexy-dp-
|
|
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 {
|
|
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:
|
|
947
|
-
.lexy-dp-field-table tbody tr.is-selected { background:
|
|
948
|
-
.lexy-dp-field-table tbody tr.is-selected td { color: var(--dp-
|
|
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
|
-
/*
|
|
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:
|
|
955
|
-
right:
|
|
956
|
-
z-index:
|
|
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:
|
|
967
|
-
color:
|
|
968
|
-
box-shadow: 0 4px
|
|
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
|
|
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
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
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:
|
|
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:
|
|
1196
|
+
.lexy-dp-launcher.is-open .lexy-dp-launcher__label { max-width: 130px; opacity: 1; }
|
|
988
1197
|
|
|
989
|
-
/* \u2500\u2500 Sheet
|
|
1198
|
+
/* \u2500\u2500 Floating Sheet \u2500\u2500 */
|
|
990
1199
|
.lexy-dp-sheet {
|
|
991
1200
|
position: fixed;
|
|
992
|
-
bottom:
|
|
993
|
-
right:
|
|
994
|
-
z-index:
|
|
1201
|
+
bottom: 84px;
|
|
1202
|
+
right: 20px;
|
|
1203
|
+
z-index: 50;
|
|
995
1204
|
display: flex;
|
|
996
1205
|
flex-direction: column;
|
|
997
|
-
height:
|
|
998
|
-
width: min(100vw -
|
|
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
|
|
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
|
|
1012
|
-
background:
|
|
1013
|
-
padding:
|
|
1014
|
-
color:
|
|
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:
|
|
1017
|
-
.lexy-dp-sheet__actions { display: flex; align-items: center; gap:
|
|
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:
|
|
1021
|
-
width:
|
|
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.
|
|
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:
|
|
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
|
-
`,
|
|
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(
|
|
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
|
-
|
|
1361
|
-
|
|
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
|
-
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
|
|
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
|
-
`,
|
|
2308
|
-
`},
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
2676
|
+
`,ao=`{
|
|
2389
2677
|
"printWidth": 100
|
|
2390
2678
|
}
|
|
2391
|
-
`,
|
|
2679
|
+
`,no=`pnpm-lock.yaml
|
|
2392
2680
|
src/lexy-theme.css
|
|
2393
2681
|
public/fonts/
|
|
2394
2682
|
dist/
|
|
2395
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
2767
|
+
`,po=`@import "tailwindcss";
|
|
2480
2768
|
@import "./lexy-theme.css";
|
|
2481
|
-
`,
|
|
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
|
-
`,
|
|
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>`,
|
|
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
|
-
${
|
|
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
|
-
${
|
|
2832
|
+
${Ye}
|
|
2545
2833
|
{showPrototypeDesignerPanel ? <PrototypeDesignerPanel /> : null}
|
|
2546
2834
|
</>
|
|
2547
2835
|
);
|
|
2548
2836
|
};
|
|
2549
|
-
`,
|
|
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
|
-
`,
|
|
2843
|
+
`,fo=`node_modules/
|
|
2556
2844
|
dist/
|
|
2557
2845
|
*.log
|
|
2558
2846
|
.env
|
|
2559
|
-
`,
|
|
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
|
-
`,
|
|
2571
|
-
`},
|
|
2572
|
-
`),await n("components.json",
|
|
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=
|
|
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
|
-
`)+
|
|
2577
|
-
`)+
|
|
2578
|
-
`)+
|
|
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
|
|
2581
|
-
`)};var
|
|
2582
|
-
${n.title??a}`)+
|
|
2583
|
-
`));let
|
|
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
|
|
2586
|
-
Sin componentes instalados a\xFAn (create-lexy add <nombre>).`));else{let
|
|
2587
|
-
Componentes instalados (registry vigente: ${
|
|
2588
|
-
`));for(let[
|
|
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
|
-
`):
|
|
2903
|
+
`):N.red(`
|
|
2591
2904
|
Hay problemas que atender (exit 1).
|
|
2592
|
-
`)),o};import
|
|
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
|
|
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
|
|
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 (\`${
|
|
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
|
-
`,
|
|
2683
|
-
|
|
2684
|
-
Abre la carpeta con Claude Code y di: `+
|
|
2685
|
-
El agente te entrevistar\xE1 y montar\xE1 el proyecto por ti.`,"Kickoff listo"),
|
|
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
|
-
`))),
|
|
2692
|
-
${i.items.length} componente(s). Instala con: create-lexy add <nombre>`));return}let o=e.toLowerCase();if(t.installed){let i=process.cwd(),
|
|
2693
|
-
`),console.log(
|
|
2694
|
-
Error: `)+t.message),process.exit(1)}};
|
|
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);
|