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 withdata-fve-src="path:line:col", and each edit now carries the nearest one assource: the strongest anchor in the payload, because it ends the agent's search instead of narrowing it. Without the plugin nothing changes —sourceisnulland every existing anchor still ships. The plugin needs atypescriptwith the in-memory parser (5.x); a TypeScript 7 host can hand one over viavisualEditorSource({ typescript }), and without one the plugin warns once and stays out of the way. - Per-edit delete.
DELETEaccepts?selector=…&url=…and removes that one entry; Reset on an element whose edit was already saved now retracts it fromedits.jsoninstead of leaving a change the user took back for the agent to apply. Providing half the key is a400, 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=1response and is logged once to the browser console — a missing Component section is now traceable to the file that caused it. NewscanCvaserver export returns{ components, warnings };scanCvaComponentsbehaves 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 nativeconfirm()— 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/:activetabs at the top of the panel. Edit under one and the element previews as it would look in that state, and the change exports understates.hoverrather thanstyles. It is the one intent the payload could not express at all before. These carry the value you want and nobefore::hoverhas no computed style the browser will give JS, and every otherbeforein 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 intoedits.json— it makes the element dirty again, which is the truth. - Multi-layer and inset shadows.
box-shadowis parsed into layers and each gets an editable row, Figma-style, withinset, reordering and add/remove. A layer keeps its colour in the notation it arrived in, so editing one layer leaves anoklch()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
typescriptthat still parses, quoted axis keys ('2xl':), template literals, an aliasedcvaimport andcn()composition all resolve correctly, andtv()(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.
POSTandDELETEshare oneisSameElement, which keys onsourcewhen 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 markedsourceAmbiguousand 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
MutationObservernow 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.