From eb46479092e8abff1b8a0522e31812ea11cbb17c Mon Sep 17 00:00:00 2001 From: dev Date: Mon, 16 Mar 2026 14:09:09 +0100 Subject: [PATCH] =?UTF-8?q?feat(vcen-edit):=20sidebar=20redimensionable=20?= =?UTF-8?q?y=20nuevo=20dise=C3=B1o=20de=20lista=20de=20atributos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CatalogLayout: sidebar izquierdo redimensionable por arrastre (min 160px, max 480px); separador de 1px con feedback visual al hover y al arrastrar - ObjAttsPanel / CatAttsPanel / SecAttsPanel: nuevo diseño de item de atributo inspirado en el sidebar de AttEditor demo — nombre (text-sm) + ID mono debajo, badge de dominio neutro a la derecha con nombre completo, indicador ⚡ para reglas, selección azul (border-blue-500), botón 'eliminar' independiente bajo cada item Co-Authored-By: Claude Sonnet 4.6 --- src/vcen-edit/comps/CatAttsPanel.svelte | 51 +++++++++++----------- src/vcen-edit/comps/CatalogLayout.svelte | 29 ++++++++++++- src/vcen-edit/comps/ObjAttsPanel.svelte | 54 +++++++++++------------- src/vcen-edit/comps/SecAttsPanel.svelte | 54 +++++++++++------------- src/vcen-edit/lib/rule-eval.ts | 2 +- 5 files changed, 101 insertions(+), 89 deletions(-) diff --git a/src/vcen-edit/comps/CatAttsPanel.svelte b/src/vcen-edit/comps/CatAttsPanel.svelte index 2e787ec..2e1b8b0 100644 --- a/src/vcen-edit/comps/CatAttsPanel.svelte +++ b/src/vcen-edit/comps/CatAttsPanel.svelte @@ -8,16 +8,6 @@ const sel = $derived(editor.selection) const atts = $derived(editor.cat.atts ?? []) const attId = $derived(sel.kind === 'cat-atts' ? sel.attId : undefined) -const domainBadge: Record = { - string: 'bg-blue-900/40 text-blue-400', - number: 'bg-green-900/40 text-green-400', - currency: 'bg-emerald-900/40 text-emerald-400', - boolean: 'bg-purple-900/40 text-purple-400', - option: 'bg-amber-900/40 text-amber-400', - date: 'bg-rose-900/40 text-rose-400', - time: 'bg-rose-900/40 text-rose-400', - datetime: 'bg-rose-900/40 text-rose-400', -} let creating = $state(false) let newAttName = $state('') @@ -65,27 +55,34 @@ function cancelAdd() { {:else} {#each atts as att (att.id)} {@const isActive = attId === att.id} -
editor.select({ kind: 'cat-atts', attId: att.id })} - onkeydown={e => e.key === 'Enter' && editor.select({ kind: 'cat-atts', attId: att.id })} - class="px-4 py-2.5 flex items-center gap-2 text-sm cursor-pointer - transition-colors group border-l-2 + class="w-full text-left px-4 py-2.5 flex items-center justify-between + cursor-pointer transition-colors border-l-2 {isActive - ? 'bg-indigo-600/20 text-indigo-300 border-indigo-500' - : 'text-gray-400 hover:bg-gray-800 hover:text-gray-200 border-transparent'}" + ? 'bg-gray-800 border-blue-500' + : 'border-transparent hover:bg-gray-800'}" > - - {att.value.domain.kind.slice(0, 3)} - - - {#if att.name}{att.name}{:else}Sin nombre{/if} - +
+ + {att.name || 'Sin nombre'} + + {att.id} +
+
+ + {att.value.domain.kind} + + {#if att.rules?.rules?.length} + ⚡ + {/if} +
+ +
+ onclick={() => editor.removeCatAtt(att.id)} + class="text-xs text-gray-700 hover:text-red-400 transition-colors" + >eliminar
{/each} {/if} diff --git a/src/vcen-edit/comps/CatalogLayout.svelte b/src/vcen-edit/comps/CatalogLayout.svelte index 36e01cc..907668b 100644 --- a/src/vcen-edit/comps/CatalogLayout.svelte +++ b/src/vcen-edit/comps/CatalogLayout.svelte @@ -44,6 +44,25 @@ const sel = $derived(editor.selection) let showJson = $state(false) let showGraph = $state(false) +let sidebarW = $state(256) +let dragging = $state(false) + +function onHandleMousedown(e: MouseEvent) { + dragging = true + const startX = e.clientX + const startW = sidebarW + function onMove(ev: MouseEvent) { + sidebarW = Math.max(160, Math.min(480, startW + ev.clientX - startX)) + } + function onUp() { + dragging = false + window.removeEventListener('mousemove', onMove) + window.removeEventListener('mouseup', onUp) + } + window.addEventListener('mousemove', onMove) + window.addEventListener('mouseup', onUp) +} + const graphResult = $derived.by(() => { try { const g = buildDependencyGraph(editor.cat) @@ -118,10 +137,18 @@ const isValid = $derived(graphResult.graph !== null)
-
+
+ +
+
{#if sel.kind === 'cat-info'} diff --git a/src/vcen-edit/comps/ObjAttsPanel.svelte b/src/vcen-edit/comps/ObjAttsPanel.svelte index a44deb1..093963e 100644 --- a/src/vcen-edit/comps/ObjAttsPanel.svelte +++ b/src/vcen-edit/comps/ObjAttsPanel.svelte @@ -9,16 +9,6 @@ const ctx = $derived(sel.kind === 'obj-atts' ? { objId: sel.objId, obj: editor.findObj(sel.objId), attId: sel.attId } : null) -const domainBadge: Record = { - string: 'bg-blue-900/40 text-blue-400', - number: 'bg-green-900/40 text-green-400', - currency: 'bg-emerald-900/40 text-emerald-400', - boolean: 'bg-purple-900/40 text-purple-400', - option: 'bg-amber-900/40 text-amber-400', - date: 'bg-rose-900/40 text-rose-400', - time: 'bg-rose-900/40 text-rose-400', - datetime: 'bg-rose-900/40 text-rose-400', -} let creating = $state(false) let newAttName = $state('') @@ -72,30 +62,34 @@ function cancelAdd() { {:else} {#each obj.atts as att (att.id)} {@const isActive = attId === att.id} -
editor.select({ kind: 'obj-atts', objId, attId: att.id })} - onkeydown={e => e.key === 'Enter' && editor.select({ kind: 'obj-atts', objId, attId: att.id })} - class="px-4 py-2.5 flex items-center gap-2 text-sm cursor-pointer - transition-colors group border-l-2 + class="w-full text-left px-4 py-2.5 flex items-center justify-between + cursor-pointer transition-colors border-l-2 {isActive - ? 'bg-indigo-600/20 text-indigo-300 border-indigo-500' - : 'text-gray-400 hover:bg-gray-800 hover:text-gray-200 border-transparent'}" + ? 'bg-gray-800 border-blue-500' + : 'border-transparent hover:bg-gray-800'}" > - - {att.value.domain.kind.slice(0, 3)} - - - {#if att.name}{att.name}{:else}Sin nombre{/if} - - {#if att.rules?.rules?.length} - - {/if} +
+ + {att.name || 'Sin nombre'} + + {att.id} +
+
+ + {att.value.domain.kind} + + {#if att.rules?.rules?.length} + ⚡ + {/if} +
+ +
+ onclick={() => editor.removeAtt(objId, undefined, att.id)} + class="text-xs text-gray-700 hover:text-red-400 transition-colors" + >eliminar
{/each} {/if} diff --git a/src/vcen-edit/comps/SecAttsPanel.svelte b/src/vcen-edit/comps/SecAttsPanel.svelte index 16d631a..d5a859e 100644 --- a/src/vcen-edit/comps/SecAttsPanel.svelte +++ b/src/vcen-edit/comps/SecAttsPanel.svelte @@ -9,16 +9,6 @@ const ctx = $derived(sel.kind === 'sec-atts' ? { objId: sel.objId, secId: sel.secId, sec: editor.findSec(sel.objId, sel.secId), attId: sel.attId } : null) -const domainBadge: Record = { - string: 'bg-blue-900/40 text-blue-400', - number: 'bg-green-900/40 text-green-400', - currency: 'bg-emerald-900/40 text-emerald-400', - boolean: 'bg-purple-900/40 text-purple-400', - option: 'bg-amber-900/40 text-amber-400', - date: 'bg-rose-900/40 text-rose-400', - time: 'bg-rose-900/40 text-rose-400', - datetime: 'bg-rose-900/40 text-rose-400', -} let creating = $state(false) let newAttName = $state('') @@ -75,30 +65,34 @@ function cancelAdd() { {:else} {#each sec.atts as att (att.id)} {@const isActive = attId === att.id} -
editor.select({ kind: 'sec-atts', objId, secId, attId: att.id })} - onkeydown={e => e.key === 'Enter' && editor.select({ kind: 'sec-atts', objId, secId, attId: att.id })} - class="px-4 py-2.5 flex items-center gap-2 text-sm cursor-pointer - transition-colors group border-l-2 + class="w-full text-left px-4 py-2.5 flex items-center justify-between + cursor-pointer transition-colors border-l-2 {isActive - ? 'bg-indigo-600/20 text-indigo-300 border-indigo-500' - : 'text-gray-400 hover:bg-gray-800 hover:text-gray-200 border-transparent'}" + ? 'bg-gray-800 border-blue-500' + : 'border-transparent hover:bg-gray-800'}" > - - {att.value.domain.kind.slice(0, 3)} - - - {#if att.name}{att.name}{:else}Sin nombre{/if} - - {#if att.rules?.rules?.length} - - {/if} +
+ + {att.name || 'Sin nombre'} + + {att.id} +
+
+ + {att.value.domain.kind} + + {#if att.rules?.rules?.length} + ⚡ + {/if} +
+ +
+ onclick={() => editor.removeAtt(objId, secId, att.id)} + class="text-xs text-gray-700 hover:text-red-400 transition-colors" + >eliminar
{/each} {/if} diff --git a/src/vcen-edit/lib/rule-eval.ts b/src/vcen-edit/lib/rule-eval.ts index 30b5d9a..8ab3b35 100644 --- a/src/vcen-edit/lib/rule-eval.ts +++ b/src/vcen-edit/lib/rule-eval.ts @@ -114,7 +114,7 @@ export function evalRuleSetState( ) if (!action) continue - if (fires) return action.ifTrue + if (fires) return (action as any).ifTrue if (fallback === null) fallback = (action as any).ifFalse ?? null }