Ir al contenido
cada versión, en el orden en que salió

Cambios

Escrito a mano, una entrada por versión, y generado directamente desde CHANGELOG.md para que esta página no pueda separarse del paquete. Si aquí falta una versión, es que nunca se publicó.

Las entradas se quedan en inglés: se generan desde el propio paquete, y una copia traducida se desviaría en la primera release.

Versión actual 0.4.0 , publicada el 28 de julio de 2026


0.4.0 última

28 de julio de 2026 · comparar en GitHub

Added

  • Source stamping. An opt-in, dev-only Vite plugin — @guerrerosoconm/visual-editor/vite — stamps every host JSX element with data-fve-src="path:line:col", and each edit now carries the nearest one as source: the strongest anchor in the payload, because it ends the agent's search instead of narrowing it. Without the plugin nothing changes — source is null and every existing anchor still ships. The plugin needs a typescript with the in-memory parser (5.x); a TypeScript 7 host can hand one over via visualEditorSource({ typescript }), and without one the plugin warns once and stays out of the way.
  • Per-edit delete. DELETE accepts ?selector=…&url=… and removes that one entry; Reset on an element whose edit was already saved now retracts it from edits.json instead of leaving a change the user took back for the agent to apply. Providing half the key is a 400, never a wipe; no parameters still clears the file, so the Clear button is unchanged.
  • Scanner warnings. Every cva definition the scanner has to drop comes back as a { file, reason } warning in the ?manifest=1 response and is logged once to the browser console — a missing Component section is now traceable to the file that caused it. New scanCva server export returns { components, warnings }; scanCvaComponents behaves as before.
  • Close confirmation. Closing the editor with pending edits asks first — Save N / Discard / Cancel, inline in the panel footer or in a floating band when no panel is open, never a native confirm() — and the browser prompts before a reload while anything is pending. Neither path writes: saving without an explicit Save would be the opposite of discard-on-close.
  • State editing. Default / :hover / :focus / :active tabs at the top of the panel. Edit under one and the element previews as it would look in that state, and the change exports under states.hover rather than styles. It is the one intent the payload could not express at all before. These carry the value you want and no before: :hover has no computed style the browser will give JS, and every other before in the payload is measured rather than assumed.
  • Undo / redo. ⌘Z / ⌘⇧Z, plus buttons in the panel header. One history for the page in the order things happened, so undoing something on another element selects it and shows you the change; a gesture is one step, so a held arrow key or a scrub collapses to a single entry. Saving does not clear it, but undo never reaches into edits.json — it makes the element dirty again, which is the truth.
  • Multi-layer and inset shadows. box-shadow is parsed into layers and each gets an editable row, Figma-style, with inset, reordering and add/remove. A layer keeps its colour in the notation it arrived in, so editing one layer leaves an oklch() neighbour byte-identical instead of flattening it to sRGB. A value the panel genuinely cannot take apart is still read-only, with an explicit Replace rather than a silent rewrite.

Changed

  • The cva scan reads the AST when it can. With a typescript that still parses, quoted axis keys ('2xl':), template literals, an aliased cva import and cn() composition all resolve correctly, and tv() (tailwind-variants) is supported. Without one it falls back to the previous regex parser and says so in the warning. Still no mandatory dependency.
  • Edits merge on identity, not on a string. POST and DELETE share one isSameElement, which keys on source when both entries carry an unambiguous one and on the selector otherwise — so a list that reorders between sessions no longer writes a second entry for the same element. A stamp that names a line of JSX rather than one rendering of it (a component used twice, or an ancestor's stamp on an unstamped child) is marked sourceAmbiguous and excluded from the key: duplicating an entry is verbose, merging two elements would be corruption.

Fixed

  • A React remount no longer loses the edit. The session map keys on node identity, so a parent re-render used to strand the entry and report the work as lost — which, under HMR, was most of a session. A MutationObserver now re-resolves the element by its stamp or selector and moves the session onto the replacement, re-applying what was on it. Only what genuinely cannot be found is pruned and reported.

0.3.0

23 de julio de 2026 · comparar en GitHub

Added

  • Notes. Write a free-text note on any element and it travels in edits.json as note. It is the one field that carries intent rather than measurement — "reuse the CTA's spacing scale", "extract this into a component" — and an element may carry a note and nothing else. INSTRUCTIONS tells the receiving agent to treat it as the most authoritative field in the entry and to follow it where it disagrees with the measured diff.
  • Note markers. Each noted element gets a numbered pin, a halo redrawing its box, and a card anchored beside it — never over it. Hover previews; click pins it open and lets you edit the note in place, delete it, or open the element in the panel. Unsaved notes read in the warning colour with a dashed guide. "Open in panel" expands the panel's Note section and drops the cursor in it.
  • Pin clustering. Pins that land within 30px of each other collapse into a counter that fans out over an arc when opened, leaving a dot on the true anchor — so two notes on a row and its cell no longer hide each other, and the page never under-reports how many notes it carries.
  • Note rail. A rail down the right edge carries a tick per note at its position in the document, not the window: hover reads the note, click scrolls to the element and opens it. A count reports how many notes exist and how many are still unexported. Where the browser supports CSS scroll-state queries (Chrome 133+), an expanded note's fade tracks its scroll position natively; elsewhere it degrades to no fade, never to broken text.

Fixed

  • A stale mountVisualEditor() handle no longer tears down the editor that replaced it. Hosts that keep the handle to unmount on hot reload — import.meta.hot?.dispose(() => handle.unmount()) — could lose the live editor when dispose ran after the replacing module had mounted.

0.2.0

21 de julio de 2026 · comparar en GitHub

First release that installs and type-checks cleanly outside a bundler.

Added

  • Framework-agnostic mount. mountVisualEditor() boots the editor into its own React root, so Vue, Angular, Svelte, Astro and plain-HTML hosts can run it without touching React themselves.
  • /standalone entry with React bundled in: one import, nothing to install, for hosts with no React in node_modules.
  • Vue 3 and Angular component detection. The payload now carries component ancestry and live props/inputs on those hosts, not only on React.
  • Design-token colour picker. Colour rows bind to the page's own custom properties, keeping the token name and its alpha, so the payload says var(--brand) rather than a hex that merely matches it.

Fixed

  • Published types now resolve for every consumer. Subpath types (/server, /standalone) failed under the classic moduleResolution: "node"; typesVersions gives that resolver the fallback it needs. src is now published too, so declaration and source maps resolve and Go to Definition lands on real code.
  • pnpm build works from a clean checkout. pnpm-workspace.yaml carried the literal placeholder pnpm writes when it wants a build script approved, which aborted the build before tsc ran.
  • The Custom CSS suggest menu no longer goes see-through while typing.

Docs

  • The Astro endpoint is documented. Astro hands routes an APIContext rather than a bare Request, so re-exporting the handlers Next-style type-checks and then fails at runtime on POST.

0.1.1

17 de julio de 2026 · comparar en GitHub

Fixed

  • The package is installable: it builds to dist/ with full ESM specifiers, so plain Node's resolver can load it. Before this it could not be imported outside a bundler.