- EditorMetaTree ahora obtiene glob, locales, defaultLocale, tags del contexto si no se pasan
- Elimina PanelMeta.svelte (wrapper innecesario)
- Actualiza CatalogLayout, PanelObject, PanelSection, PanelOptionDetail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MetadataPanel era solo un wrapper que determinaba contexto,
PanelMeta es más genérico y reutilizable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extrae helpers asLingRec/asHotspotMode/asLingRecOpt para evitar `as` en template
- Corrige select: elimina value={}, usa selected={} en cada option
- Añade for/id en todos los pares label-input y aria-label en color picker
- Añade variant="dark" al LingInput de tooltip (evita fondo blanco en editor oscuro)
- Incluye renombrados de componentes y demás cambios de la sesión
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Añade Icon.svelte con iconos para todas las entidades (catalog, obj, sec, att, opt, view, hotspot) y acciones (add, delete, chevron, move, etc.)
- Añade SVGs fuente para catalog, section, attribute y option
- Reemplaza todos los SVGs inline de CatalogSidebar, DeleteButton y HotspotPanel por <Icon>
- Refactoriza CatalogSidebar con tipografía uniforme 13px, altura de fila uniforme y componentes ButtonSidebarGo/Expand/Move
- Corrige ButtonSidebarMove: prop `group` para responder al grupo hover correcto (obj/sec/view)
- Mueve los botones de añadir entidades hijo a los headers de ObjPanel, SecPanel y ViewPanel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nuevos componentes:
- InputEntityID: campo de ID normalizado con modo new/display, bindable slug y error externo
- EntityIdName: bloque combinado ID + Nombre para uso canónico en formularios de entidad
- InputEntityIDDemo: página de demo para pruebas del componente
- TemplateBuilder: constructor de templates de URL con referencias a atributos
VisualPanel — estrategia API:
- endpoint cambiado a ViewTemplate (TemplateBuilder), resolución por interpolación
- método GET/POST: GET muestra solo TemplateBuilder de endpoint, POST añade param builder
- preview API: muestra imagen resuelta desde el endpoint interpolado
Fixes AttDetail / catalog-editor:
- editId ya no se resetea al mutar el store (guard _syncedAttId)
- cat-level att ID ahora se guarda correctamente (updateCatAttId)
- isAttSlugTaken separado en isCatAttSlugTaken e isAttSlugTaken(objId, secId) por scope
- select de valor por defecto para dominios list (string/number/option)
- clave duplicada en each solucionada con índice
Fixes view.ts / tipos:
- ApiParam { key, value: ViewTemplate } — endpoint y params como templates
- resolveAttCode: soporte prefijo cat/, domain.mode fixed, option/list
- resolveApi interpola endpoint como template
CSS — field-input y section-title movidos de CatalogEditor.svelte a app.css
para que estén disponibles en cualquier contexto (demos, tests visuales)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Nuevo VisualPanel: editor completo de vistas y hotspots con sidebar, formulario y preview
- Botón diana para posicionar hotspots haciendo click en la imagen de preview
- Posición X/Y de hotspots como número 0-100 (porcentaje), con validación
- Preview de imagen con markers de hotspots superpuestos y aspect-ratio dinámico
- IDs editables en creación de vistas y hotspots (patrón newEntityId)
- Corrección de newEntityId en addAtt/addCatAtt para edición de ID en creación
- Tabs en mayúsculas en ObjPanel, SecPanel y CatMetaPanel
- Mejora contraste botones de locale secundario en modo light (LingInput)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- IconPicker: selector visual en grid con position:fixed para evitar clipping
- IssueSection: confirmación antes de eliminar, ordenación con ↑/↓ a la izquierda
- RuleList: formulario borrador antes de crear (igual que IssueSection)
- RuleEditor: estado efectivo (AttState actual) en lugar de activa/inactiva
- Tabs: reglas movidas al tab Reglas/Incidencias con headers consistentes
- Botones: sistema unificado ve-action-btn/ve-btn/ve-card-btn/ve-btn-link a 12px
- Flechas: ↑/↓ normalizadas en CatalogSidebar e IssueSection
- Tipografía: fuente Ge (Gellix) desde /f/ge/ aplicada en todo el editor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Añade lang/langs a Cat y label:LingRecord a Obj, Sec, Att
- Crea EditorGlob con createGlobState + createLing para traducciones/moneda/fecha
- CatMetaPanel con selección de idioma principal y lista de idiomas soportados
- Store: setObjLabel, setSecLabel, setAttLabel, setCatAttLabel (LingRecord completo)
- LingInput.svelte local adaptado al tema oscuro del editor (sin bg-white)
- ObjInfoPanel, SecInfoPanel, AttDetail usan LingInput con tabs por locale
- helper labelOf para resolver LingRecord en listas y cabeceras
- Mueve catalog-editor al directorio stores y elimina el fichero antiguo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
text-xs → text-sm, py-1.5 → py-2, colores activo/inactivo homogéneos
(bg-gray-800 border-blue-500 / text-gray-300) en todos los ítems del árbol
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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 <noreply@anthropic.com>
- ConditionBuilder.svelte: reemplaza el input de texto genérico por inputs
específicos por tipo de dominio (boolean → Sí/No, number/currency → number,
date → date picker + ?TODAY/?YESTERDAY/?TOMORROW, time → time, datetime →
datetime-local + ?NOW, string → text)
- rule-eval.ts: añade DateToken, isDateToken, resolveTokens (sustituye tokens
de fecha antes de evaluar con JsonLogic)
- condition-builder.svelte.ts: añade domainFor() para exponer el dominio del
atributo seleccionado a la UI
- Tests: +9 tests para resolveTokens e integración con evalRuleSetState (30 total)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- rule-eval: ordenación por prioridad corregida (ascendente: menor nº = mayor prioridad)
- rule-eval: atributos mode:fixed ahora usan domain.fixed como valor efectivo (no att.value.value vacío)
- catalog-editor: estados obj/sec calculados via $effect+$state con contexto inline para tracking reactivo garantizado
- CatalogSidebar: consume objStates/secStates del store en lugar de derivados locales
- ObjInfoPanel: usa editor.objStates en lugar de buildEvalCtx local
- RuleEditor: añade edición de ifFalse ("si no se cumple") con colores por estado
- AttDetail: oculta "valor por defecto" en mode:fixed; label "Valor fijo" para el input fixed
- Tests: suite completa para buildEvalCtx y evalRuleSetState (21 tests)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- RuleEditor simplificado: una sola acción por regla (tipo attribute),
sin selector de tipo de acción ni múltiples acciones
- Acciones de regla con estado calculado en tiempo real (rule-eval.ts):
ObjInfoPanel y AttDetail muestran badge con estado actual según
valores por defecto del catálogo
- Grafo de dependencias implementado en CatalogLayout (overlay)
- IDs de objetos/secciones/atributos especificados por el usuario con
prefijo automático (ob:slug, sc:slug, at:slug) y validación de unicidad
- Formularios de creación con nombre + slug; slug se auto-rellena desde
el nombre y puede editarse manualmente
- Botón Descartar en header para revertir cambios no guardados
- canvas/Editor.svelte persiste en localStorage (Guardar funciona)
- Target de acciones acotado al contenedor de la regla (no catálogo global)
- Paneles ObjInfo y SecInfo muestran campo ID como solo lectura
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bugs críticos:
- stores/catalog-editor.svelte.ts: añadidos activeOptId, activeOpt y
setActiveOpt que OptsPanel.svelte y OptDetail.svelte requerían pero
no existían en el store — el panel de opciones estaba completamente roto.
- session.svelte.ts: createSession recibía engine donde espera glob,
causando crash en getPrice()/resolveView(). Corregido a createSession(cat, null, engine).
- vcen/session.ts: glob ahora es optional (GlobInstance|null = null) para
permitir sesiones de solo-evaluación sin glob; añadidos null-guards en
getPrice, getAllPrices, resolveView, resolveVisual, resolveDefaultView.
Otras correcciones:
- comps/catalog-editor.svelte.ts + stores/catalog-editor.svelte.ts:
updateAttDefaultValue usaba (att.value as any).value = value (mutación
directa con cast); corregido a att.value = { ...att.value, value }.
- OptDetail.svelte: eliminado `</>` suelto dentro de la cadena de clase CSS.
- demo.store.svelte.ts: dominios option usaban estructura obsoleta
{kind:'option', options:[]} incompatible con vcen. Refactorizado para
usar la estructura correcta {kind:'option', mode:'list', list:[{optId}]}
con Opt entries en cat.opts. Actualizado addAtt, updateAttDomain y
updateAttOptions.
- demos/RuntimePanel.svelte: iteraba (domain as any).options para opciones;
ahora itera domain.list y resuelve el valor desde cat.opts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bugs críticos:
- session.ts #1: configState se reconstruía desde el Cat original al hacer
setValue, ignorando los valores del usuario y los derivados. Añadido
userValues Map y buildCurrentConfigState() que combina base + user + derived.
getAllPrices() usaba computeCatPrice (que también reconstruía desde Cat);
ahora usa this.configState.
- incremental.ts #12: evaluateObj se llamaba sin cat.opts, por lo que las
reglas de opciones nunca se re-evaluaban en evaluación incremental.
Añadido buildNestedState al import y pasados opts + nestedState.
Mejoras de arquitectura:
- engine.ts #11: lógica de evaluación de opciones duplicada en evaluateObj
extraída al helper privado applyOptionsForAtt.
- engine.ts #2: evaluateCat ahora evalúa y valida cat.atts directos (antes
solo procesaba los Obj).
- engine.ts #10: comparación JSON.stringify para detectar convergencia
reemplazada por Object.keys().some() — O(n) sin serialización.
- engine.ts #24: errors/warnings cambiados de string[] + new Set a
Set<string> directamente; añadido helper validateAttPath para evitar
duplicación.
- graph.ts #5: engine.usesData(rule.condition) se llamaba dos veces por
regla; ahora se reutiliza el resultado de la primera llamada.
- graph.ts #17: casts as unknown as AttPath consolidados en mkPath() helper.
- graph.ts #23: getDependents y getAffectedAtts eran idénticas; ahora una
delega a la otra.
- node_util.ts #6: keyToAttPath añade console.warn para paths inesperados.
- pricing.ts #16: strings hardcodeados ('A consultar', 'IVA inc.', etc.)
externalizados via labels? en FormatAmountOpts.
- pricing.ts #22: catch silencioso en evaluateAmount ahora hace console.warn.
- incremental.ts #13: bloque comentado obsoleto de findAtt eliminado.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Nuevos tipos de campo: color, select, multiselect, email, phone, slug,
coordinates, markdown — con soporte completo en TypeBadge, AddFieldMenu,
FieldRow, TreeNodes y AddFieldModal
- Refactor arquitectural: FieldValueEditor sustituido por 23 componentes
individuales (fields/) + FieldForm.svelte compartido entre panel de edición
y modal de creación, garantizando coherencia de UI entre ambos contextos
- AddFieldDrawer renombrado a AddFieldModal (era un <dialog>, no un drawer);
corregido el bloqueo de botones por inertness nativo del elemento dialog
- AddFieldModal: fondo semitransparente corregido (bg-black/50), atributos
y toggle hidden ahora presentes también en creación de campo
- glob/curr: añadido getCurrencies() en tipos, engine y adaptador Svelte;
selector de divisa en CurrencyField muestra lista real o valor fijo
- CurrencyField: preview formateada con la moneda del campo, no la global
- TreeNodes: eliminado cast 'as Metadata' en template HTML; ImageField:
as any reemplazado por as ImageRef['format']
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Arquitectura / glob+ling:
- glob_engine: inicialización lazy de módulos (numr, curr, dati, unit) con ??=
- glob_types: añadido método register<NS, M>() para tipado fuerte de namespaces
- ling engine: extend() soporta namespaces con punto ('vcen.editor.mtas') via deepMerge
- ling guards: isLingRecord reforzado (comprueba typeof value !== 'function' y tipo del locale por defecto)
Validación:
- ISO_DATETIME_RE acepta HH:mm sin segundos (formato real de datetime-local)
Componentes Svelte — correcciones:
- App.svelte: corregido paso de prop glob (glob, → {glob})
- AddFieldMenu: añadida prop placement ('start'|'end') para controlar dirección del dropdown
- AddFieldMenu: reemplazados glob.t(`...` as any) por helper t() para evitar errores de parser Svelte
- FieldValueEditor: grupo muestra cuenta real de hijos en lugar de siempre "Grupo vacío"
- FieldRow: tooltip de editar/borrar cambiado a tooltip-top, eliminado overflow-hidden del card
- FieldRow: diálogo de confirmación antes de eliminar campo (modal DaisyUI)
- TreeNodes: corregido bug summary (group-hover:hidden → group-hover:block), acciones sin flex duplicado
- TreeNodes: diálogo de confirmación antes de eliminar (solo en depth=0 para evitar duplicados)
Estilos (DaisyUI):
- MetadataEditor y MetaTree: border-base-300, shadow-md, bg-base-200/60 en cabeceras
- MetaTree: breadcrumb de ruta en panel derecho, texto placeholder via glob.t()
- MetaTree: errores de validación con icono, alineados con MetadataEditor
- TreeNodes: nodo seleccionado con borde lateral (border-l-2 border-primary)
- AddFieldMenu: colores de icono por tipo, layout horizontal agrupado, contraste dropdown
- AddFieldDrawer: modal-bottom sm:modal-middle, botones Cancel/X visibles, inputs con text-base-content
- TypeBadge: colorMap aplicado correctamente al badge
- Traducciones: deleteConfirm, deleteConfirmMsg, deleteYes, deleteNo, tree.selectHint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>