openpencil/src/components/CodePanel.vue

456 lines
15 KiB
Vue
Raw Normal View History

<script setup lang="ts">
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
import { useClipboard, useDebounceFn } from '@vueuse/core'
import { tv } from 'tailwind-variants'
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
import {
computed,
defineAsyncComponent,
onBeforeUnmount,
ref,
shallowRef,
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
nextTick,
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
useTemplateRef,
watch
} from 'vue'
import { JSX_REFERENCE } from '@open-pencil/design-jsx'
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
import type { SceneNode } from '@open-pencil/scene-graph'
import { useEditorEvent, useI18n } from '@open-pencil/vue'
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
import {
commitDOMCodeSession,
createDOMCodeSession,
previewDOMCode,
resetDOMCodePreview,
type DOMCodeSession
} from '@/app/code/dom-preview'
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
import { generatedCodeFor, type GeneratedCode } from '@/app/code/generated'
import { useCodeLayers } from '@/app/code/layers/use'
import {
createDesignJSXEditSession,
previewDesignJSX,
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
reapplyCanvasEdits,
resetDesignJSXPreview,
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
type DesignJSXEditSession,
type DesignJSXLayerLine
} from '@/app/code/live-preview'
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
import { starterSourceFor, type CodeSource } from '@/app/code/templates'
Refactor architecture boundaries across core, app, and packages (#234) * refactor(core): decompose editor factory and action modules Split the monolithic editor factory and large action modules into focused domain helpers: - create.ts assembles context through bridge modules (clipboard, components, structure, undo) and delegates to graph-reads, graph-events, layout-runner, component-sync, and state factory - structure.ts delegates to group, container-wrap, auto-layout-wrap, reorder, and state-toggle helpers - selection.ts delegates to hit-test, overlays, container navigation, and read helpers - clipboard.ts delegates to subtree-history, images, export, copy, fonts, and placement helpers - shapes.ts delegates to pen actions and section-adopt - components.ts delegates to focus and instances helpers - alignment.ts delegates to flip-rotate helper - text.ts uses explicit TextEditSession for snapshot comparison New focused modules: nudge, variable-bindings, layout-mode, page-viewports, tool-registry, color-space Undo: history/position and history/snapshot helpers, hardened batch/rollback with nested batch support and configurable limit * refactor(core): split tool definitions by domain Split the monolithic tool registry into domain-specific modules: - read/ — selection, find, pages, fonts, components, nodes, query, jsx - create/ — basic shapes, components, vector, JSX render - modify/ — paint, effects, geometry, layout, state, text, update - structure/ — basic, arrange, batch, hierarchy, replace, tree - variables/ — bindings, collections, read, values - vector/ — boolean, path, export, viewport - analyze/ — colors, typography, spacing, clusters, diff, eval - describe/ — summaries, tree, roles, layout-issues - stock-photo/ — providers, requests, apply - codegen/ — component-map, tokens Split registry into core/extended tiers; refine schema and AI adapter * refactor(core): restructure kiwi codec and instance overrides Reorganize the Kiwi .fig codec into domain subdirectories: - binary/ — codec, schema, protocol - fig/ — file, import, parse (core, worker, transfer) - node-change/ — convert, export-node, serialize, plugin-data - instance-overrides/ — constraints, dsd, populate, props, resolve, symbol-overrides, symbol-props, sync, types Vendored kiwi-schema/ left isolated * refactor(core): split profiler, icons, IO, and add subpath exports Profiler: speedscope-export, capture-session, hud-controller Icons: api, svg, types, render, create-icons tool IO: format registry and subpath exports Canvas/color/text/vector: targeted cleanup Add deliberate subpath exports: random, xpath, vector, color, canvas, scene-graph, kiwi, design-jsx, io, tools, editor, layout, canvaskit, profiler, text, lint, rpc, figma-api, constants * refactor(vue): decompose canvas input, surface lifecycle, and controls Canvas surface: gl-surface, kit-loader, render-loop, resize-observer Canvas input handlers: - move: drop-target, move-snap, duplicate-drag - select: select-move, select-hover, select-hit - resize: resize-rect, resize-vector, resize-start - transform: rotation, marquee, pan, text-selection - text-edit: navigation, clipboard, textarea lifecycle - Shared: click-count, space-key, pan, pan-zoom, draw, raf-scheduler Editor composition: - commands split: actions, context, metadata, edit, selection, view - menu-model split: command-groups, builders, types - Gradient stop composable reuse in primitive root Controls: fill, layout, typography, appearance, effects, stroke, okhcl, prop-scrub, node-props, undo-batch, color-variable-binding Variables/i18n/document/export helpers Organize canvas, primitives, controls, editor, and variables into cohesive module directories with package-local import aliases Expose MenuActionNode/MenuSeparatorNode from public API * refactor(app): split document IO, editor session, and automation bridge Document IO: source-state, naming, writer, reload-source, reload-state, imported-document, watch-targets, save-targets Editor session: create, modules, types, accessors, computed, refs Editor canvas: loader-overlay, collaboration-awareness, context-selection, menu-actions, menu-model Automation bridge: eval, tools, exports, files, selection, RPC fallback AI/ACP: transport, map-update, permission, debug, chat effects/storage Collab: awareness, graph-bindings, yjs-sync, follow, session, types Shell keyboard: actions, bindings, clipboard, focus, nudging, raw-events, registry, reserved, shortcuts, space-tool Shell menu: app-menu, document-name, entry, files Demo: colors, effects, helpers, section builders (components, app-preview, effects, standalone, variables) — document.ts reduced from 981 to 32 lines as pure orchestrator Move app modules under src/app/ with organized domain structure: editor, document, ai, collab, shell, automation, demo, tabs * refactor(app): decompose UI components with provide/inject context Split monolithic components using Reka UI-inspired namespace folders with scoped provide/inject context — no prop drilling: - CollabPanel/ — context, avatars, share, connected, join - ColorPickerPanel/ — context, area, format, field groups, sliders - MobileHud/ — context, action toast, tool badge, file menu, presence - ProviderSettings/ — context, API key/type, endpoint, tokens, photos - Toolbar/ — actions, types, desktop, mobile, tool button, flyout - LayoutSection/ — types, auto-layout, flex, grid, padding, size, clip Properties helpers: fill-okhcl adapter, fill-label, color-style-row Menu: entry helpers, document-name rename, stale type removal * refactor(mcp): split server into focused modules - browser-rpc — WebSocket client management - mcp-sessions — session lifecycle - tool-output — response formatting - tool-schema — Zod schema generation from ToolDefs - jsx-preprocess — JSX source transformation - result — result helpers - tool-registration — MCP tool wiring - auth — API key validation - http-options — CORS/request handling - stdio-bridge — stdio transport adapter * refactor(cli): split analyze subcommands and shared helpers - Analyze subcommands: clusters, colors, spacing, typography - RPC data loading helper - Migrate imports to targeted core subpath exports * refactor(docs): split VitePress config and shared table component Config helpers: sdk-sidebar, seo, labels, sidebars, locale-theme, root-theme, locales Shared SdkDataTable component replaces duplicated table markup in SdkPropsTable, SdkEventsTable, and SdkSlotsTable Update contributing and testing docs * refactor(tauri): decompose desktop entrypoint Split lib.rs into focused service modules: - fig_container.rs — .fig archive/compression commands - fonts.rs — font cache and system font enumeration - menu.rs — native menu construction - menu_events.rs — menu event dispatch and devtools toggle - window.rs — main window show/focus lifecycle * test: share domain test factories and migrate fixtures New shared helpers: - tests/helpers/scene.ts — makeSceneGraph factory - tests/helpers/vector-network.ts — vertex/segment/network builders - tests/helpers/fig-traversal.ts — all-node collection, type counts - tests/helpers/undo.ts — undo test utilities - tests/helpers/editor-history.ts — editor history test helpers Migrate render, vector, fig-roundtrip, and undo tests to use shared factories instead of inline fixture construction * build: add structural lint rules, split vite config, update docs Structural lint (oxlint.structure.json + lint/plugin.js): - 20+ custom rules enforcing package boundaries, lifecycle patterns, naming conventions, and import discipline Vite config split: raw-markdown, canvaskit-assets, pwa, server, aliases, automation plugins Remove legacy shims and utils superseded by SDK/core modules Update AGENTS.md, CONTRIBUTING.md, eval-command docs, tsconfig * fix(vue): normalize canvas directory casing and remove duplicate export - Rename Canvas/ to canvas/ in git index to match #vue/canvas/* imports (PascalCase was correct for component primitives but canvas/ is a non-component domain directory) - Remove duplicate ./random subpath export in core package.json * fix: add #vue and #core Vite resolve aliases for dev server * refactor(core): reduce remaining large modules Split the remaining large core hotspots into cohesive domain modules while preserving public facades and behavior. - Extract scene graph types, variables, node defaults, and vector-network helpers - Decompose canvas renderer orchestration, state, paints, colors, lifecycle, labels, and delegated domain methods into renderer/ and labels/ subfolders - Split Kiwi node-change, binary variable binding, layout, RPC, vector, JSX export, clipboard, design JSX, and Figma proxy helpers - Replace collision-driven *Fn import aliases with namespace imports and enforce the pattern in lint Validation: - bun run check - bun --filter @open-pencil/vue build - bun run test:dupes * fix(app): forward color input attrs * fix(app): cover section drawing errors * fix(editor): undo option-drag duplicates * docs: document domain subfolder convention * fix(app): handle undo redo on keydown * refactor(app): dispatch shortcuts from keydown * refactor: group prefixed domain modules * refactor(app): use tinykeys for shortcuts * refactor(core): group symbol override modules * refactor(core): group fig kiwi container helper * refactor(canvas): split overlay rendering modules * refactor(vue): remove unused internal barrels * fix(app): lay out demo components before instancing * fix(app): restore demo badge spacing * perf(canvas): split scene and overlay rendering * refactor(vue): wrap wheel gesture lifecycle * fix(canvas): wait for fonts before hiding loader * docs: update unreleased changelog
2026-04-30 12:14:19 +00:00
import { useEditorStore } from '@/app/editor/active-store'
import AppButton from '@/components/ui/button/AppButton.vue'
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
import AppPlaceholder from '@/components/ui/feedback/AppPlaceholder.vue'
import Tip from '@/components/ui/overlay/Tip.vue'
import AppSelect from '@/components/ui/select/AppSelect.vue'
import statusTheme from '@/theme/feedback/status'
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const CodeEditor = defineAsyncComponent(() => import('@/components/code-editor/CodeEditor.vue'))
const { active = true } = defineProps<{ active?: boolean }>()
const store = useEditorStore()
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const editorActive = computed(() => active)
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
const { code, common } = useI18n()
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const { copy, copied } = useClipboard({ copiedDuring: 2000 })
const { copy: copyReference, copied: copiedReference } = useClipboard({ copiedDuring: 2000 })
const source = ref<CodeSource>('design-jsx')
const draft = ref('')
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
/** The person has written in the code since it was generated for the current selection. */
const edited = ref(false)
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const status = ref<'idle' | 'updating' | 'updated' | 'error'>('idle')
const error = ref('')
const designSession = shallowRef<DesignJSXEditSession | null>(null)
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
const codeEditor = useTemplateRef<InstanceType<typeof CodeEditor>>('codeEditor')
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
let domSession: DOMCodeSession | null = null
let previewQueue = Promise.resolve()
let pendingPreview: Promise<void> | undefined
let commitPromise: Promise<void> | undefined
let updateVersion = 0
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
/** Previews in flight; their canvas changes come from the code, not onto it. */
let previewing = 0
/** Scene version a preview left the canvas at, which the code already describes. */
let previewedVersion: number | null = null
/** The selection the code was generated for. */
let followedSelection: string | null = null
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
/** Code typed since the last preview started, which the canvas does not show yet. */
let previewDue = false
/**
* Canvas edits made while code waits to render. Code replaced as a whole has no links to patch
* them into until its preview links it again, so they are applied once more after that preview.
*/
let canvasEdits = new Map<string, Partial<SceneNode>>()
useEditorEvent('node:updated', (id, changes) => {
if (!previewDue || previewing > 0 || source.value !== 'design-jsx') return
canvasEdits.set(id, { ...canvasEdits.get(id), ...structuredClone(changes) })
})
function takeCanvasEdits(): Map<string, Partial<SceneNode>> {
const edits = canvasEdits
canvasEdits = new Map()
previewDue = false
return edits
}
/** Hands edits taken by a superseded or failed preview to the next one, behind any made since. */
function returnCanvasEdits(edits: ReadonlyMap<string, Partial<SceneNode>>) {
for (const [id, changes] of edits) canvasEdits.set(id, { ...changes, ...canvasEdits.get(id) })
}
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
/** Set by "Write JSX": the editor stays open for new layers until something is selected. */
const composing = ref(false)
/**
* Generated code needs a selection; without one the panel says so instead of showing a
* template that looks like a real layer. Writing new Design JSX is an explicit action.
*/
const showEmptyState = computed(
() =>
source.value !== 'html-css' &&
store.state.selectedIds.size === 0 &&
!composing.value &&
!designSession.value &&
!edited.value
)
watch(
() => store.state.selectedIds.size,
(size) => {
if (size > 0) composing.value = false
}
)
function writeJSX() {
composing.value = true
}
const codeLayers = useCodeLayers(source)
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const sourceOptions = computed(() => [
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
{ value: 'design-jsx' as const, label: code.value.sourceDesignJSX },
{ value: 'tailwind-jsx' as const, label: code.value.sourceTailwindJSX },
{ value: 'html-css' as const, label: code.value.sourceHTMLCSS }
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
])
const readOnly = computed(() => source.value === 'tailwind-jsx')
const editorLabel = computed(() =>
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
source.value === 'html-css' ? code.value.editorHTMLCSSLabel : code.value.editorDesignLabel
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
)
const statusTone = computed(() => {
if (status.value === 'error') return 'error'
if (status.value === 'updated') return 'success'
return 'neutral'
})
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const statusStyles = computed(() => tv(statusTheme)({ tone: statusTone.value }))
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const statusText = computed(() => {
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
if (status.value === 'updating') return code.value.updating
if (status.value === 'error') return code.value.previewFailed
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
if (edited.value) return code.value.updatedLive
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
return code.value.jsxUpToDate
})
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
function beginDesignSession(): DesignJSXEditSession | null {
if (designSession.value) return designSession.value
const result = createDesignJSXEditSession(store)
if (!result.ok) {
status.value = 'error'
error.value = result.error
return null
}
designSession.value = result.session
return result.session
}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
function beginDOMSession(): DOMCodeSession {
domSession ??= createDOMCodeSession(store)
return domSession
}
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
/** Design JSX previews are recorded as they apply; an HTML/CSS preview is committed here. */
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
async function commitCurrentSession(): Promise<void> {
if (commitPromise) return commitPromise
const operation = (async () => {
await pendingPreview
await previewQueue
updateVersion += 1
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
takeCanvasEdits()
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const dom = domSession
designSession.value = null
domSession = null
if (dom) commitDOMCodeSession(store, dom)
pendingPreview = undefined
})()
commitPromise = operation
try {
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
await operation
} finally {
if (commitPromise === operation) commitPromise = undefined
}
}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
async function runPreview(version: number): Promise<void> {
if (version !== updateVersion || readOnly.value || !draft.value.trim()) return
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
const edits = takeCanvasEdits()
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
status.value = 'updating'
error.value = ''
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
previewing += 1
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
let result: { ok: true } | { ok: false; error: string }
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
let previewLayers: DesignJSXLayerLine[] | null = null
try {
if (source.value === 'html-css') {
result = await previewDOMCode(store, beginDOMSession(), draft.value)
} else {
const session = beginDesignSession()
const preview = session
? await previewDesignJSX(store, session, draft.value)
: ({ ok: false, error: error.value } as const)
if (preview.ok) previewLayers = preview.layers
result = preview
}
} finally {
previewing -= 1
previewedVersion = store.state.sceneVersion
followedSelection = selectionKey.value
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
}
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
if (version !== updateVersion) {
returnCanvasEdits(edits)
return
}
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
if (previewLayers) codeLayers.showPreview(previewLayers)
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
if (!result.ok) {
status.value = 'error'
error.value = result.error
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
// The code still waits to render, so its next preview applies these and later edits.
previewDue = true
returnCanvasEdits(edits)
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
return
}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
status.value = 'updated'
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
const session = designSession.value
if (!session || edits.size === 0) return
// Once the code is linked again, the edits reach it as canvas changes do.
await nextTick()
if (version === updateVersion) reapplyCanvasEdits(store, session, edits)
else returnCanvasEdits(edits)
}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const schedulePreview = useDebounceFn(
(version: number) => {
previewQueue = previewQueue.then(() => runPreview(version))
return previewQueue
},
350,
{ maxWait: 1_000 }
)
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
function updateDraft(value: string, origin: 'user' | 'layers'): void {
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
draft.value = value
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
// Patches from the canvas already match it; only the person's typing renders.
if (origin === 'layers') return
edited.value = true
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
error.value = ''
updateVersion += 1
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
previewDue = true
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
pendingPreview = schedulePreview(updateVersion)
}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
async function resetDraft(): Promise<void> {
updateVersion += 1
await pendingPreview
await previewQueue
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
takeCanvasEdits()
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
const design = designSession.value
const dom = domSession
designSession.value = null
domSession = null
if (design) resetDesignJSXPreview(store, design)
if (dom) resetDOMCodePreview(store, dom)
pendingPreview = undefined
error.value = ''
status.value = 'idle'
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
edited.value = false
if (source.value === 'html-css') draft.value = starterSourceFor('html-css')
else showCanvas(source.value)
}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
async function changeSource(next: CodeSource): Promise<void> {
if (next === source.value) return
await commitCurrentSession()
source.value = next
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
edited.value = false
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
error.value = ''
status.value = 'idle'
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
if (next === 'html-css') {
codeLayers.showGenerated(null)
draft.value = starterSourceFor(next)
} else {
showCanvas(next)
}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
}
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
const selectionKey = computed(() => [...store.state.selectedIds].join(','))
/** Shows the code generated for the selection, replacing whatever the editor held. */
function showCanvas(next: Exclude<CodeSource, 'html-css'>) {
const generated: GeneratedCode = generatedCodeFor(next, store.graph, [...store.state.selectedIds])
followedSelection = selectionKey.value
codeLayers.showGenerated(generated)
draft.value = generated.code
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
}
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
/**
* Keeps the code in step with the canvas, like the Design panel. Code nobody has written in is
* generated again; code the person wrote is patched where layers changed, keeping the rest as
* written. Another selection starts over with its generated code.
*/
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
function followCanvas(live = false) {
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
const current = source.value
if (!editorActive.value || current === 'html-css' || previewing > 0) return
if (selectionKey.value !== followedSelection) {
if (designSession.value) designSession.value = null
edited.value = false
}
if (!edited.value) {
showCanvas(current)
return
}
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
// A live preview leaves the scene version alone, so it is followed whatever the version.
if (!live && store.state.sceneVersion === previewedVersion) return
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
codeEditor.value?.patchFromLayers()
}
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
watch([() => store.state.sceneVersion, selectionKey, source, editorActive], () => followCanvas(), {
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
immediate: true
})
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
/** Dragging or scrubbing a value previews it; the code follows once per frame, like the Design panel. */
let livePreviewFrame = 0
useEditorEvent('node:previewUpdated', () => {
if (livePreviewFrame) return
livePreviewFrame = requestAnimationFrame(() => {
livePreviewFrame = 0
followCanvas(true)
})
})
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
onBeforeUnmount(() => {
feat(lint): suggest group-to-frame and hidden-layer fixes; keep canvas edits in code previews (#870) * feat(lint): suggest converting groups to frames and deleting hidden layers no-groups and no-hidden-layers now carry suggestions the Lint panel, the lint_fix tool and editor.applyLintFixes can apply. A group becomes a frame in place, keeping its id, children, bounds and look; a hidden layer is deleted with its children. Neither is offered for locked layers or inside components and instances, and both are checked again when applied. The editor gains convertGroupToFrame and deleteNodes, which deleteSelected now uses, and applies lint fixes through a bridge so structure changes and property updates share one undo step. lint_fix becomes a document mutation because atomic tools cannot remove layers. * fix(code): keep canvas edits made while replaced code waits to render Replacing all the code drops its layer links until the preview links it again, so a canvas edit in the preview delay could not be patched into the code and the preview drew over it. Edits made while code waits to render are now applied again once the preview has linked the code, in the same undo step, and reach the code like any other canvas change. * fix(figma-api): default paint opacity and visibility like Figma Plugin scripts may leave out a paint's opacity and visible; Figma reads them back as 1 and true. The fills and strokes setters stored the paint as given, so the Design panel received an undefined opacity. * build(dev): forward only errors from the browser console Vite forwards browser logs when an agent starts the dev server. Serializing a Vue warning's component props walks the editor state and freezes the tab, so warnings stay in the browser console. * fix(code): follow values while they are dragged or scrubbed Live previews change layers without a new scene version, so the code kept the old value until the gesture ended. The Code tab now follows preview updates once per frame, as the Design panel does, and goes back when the gesture is cancelled. * fix(code): keep canvas edits when the replaced code fails to preview A failed preview took the canvas edits waiting for it and dropped them, and stopped recording new ones, so correcting the code drew over them. The edits now wait for the next preview.
2026-10-04 12:46:06 +00:00
cancelAnimationFrame(livePreviewFrame)
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
void commitCurrentSession()
})
watch(
() => editorActive.value,
(value) => {
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
if (!value) void commitCurrentSession()
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
}
)
</script>
<template>
<div data-test-id="code-panel-root" class="flex min-h-0 flex-1 flex-col">
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
<header class="flex shrink-0 items-center gap-2 border-b border-border px-3 py-2">
<AppSelect
:model-value="source"
:options="sourceOptions"
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
:label="code.source"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
data-test-id="code-panel-source"
:ui="{ trigger: 'h-7 min-w-0 flex-1 text-[11px]' }"
@update:model-value="changeSource"
/>
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
<Tip v-if="source !== 'html-css'" :label="code.copyJSXReference">
<AppButton
color="neutral"
variant="ghost"
size="xs"
shape="square"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
data-test-id="code-panel-copy-ref"
@click="copyReference(JSX_REFERENCE)"
>
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
<icon-lucide-check v-if="copiedReference" class="size-3 text-[var(--color-success)]" />
<icon-lucide-book-open v-else class="size-3" />
</AppButton>
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
</Tip>
</header>
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
<AppPlaceholder
v-if="showEmptyState"
:label="code.noSelection"
:description="
source === 'design-jsx' ? code.noSelectionDesignJSX : code.noSelectionTailwindJSX
"
:fill="false"
:ui="{ root: 'pt-10' }"
data-test-id="code-panel-empty"
>
<template #icon>
<icon-lucide-code class="size-4" />
</template>
<template v-if="source === 'design-jsx'" #action>
<AppButton color="neutral" variant="soft" size="xs" @click="writeJSX">
<icon-lucide-pencil class="size-3" />
{{ code.writeJSX }}
</AppButton>
</template>
</AppPlaceholder>
<div v-else class="flex min-h-0 flex-1 flex-col overflow-hidden">
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
<CodeEditor
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
ref="codeEditor"
:autofocus="composing"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
:model-value="draft"
:language="source"
:read-only="readOnly"
:label="editorLabel"
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
:layer-links="codeLayers.links.value"
:layer-issues="codeLayers.issues.value"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
@update:model-value="updateDraft"
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
:describe-layer="source === 'design-jsx' ? codeLayers.describe : undefined"
:layer-snippet="source === 'design-jsx' ? codeLayers.snippet : undefined"
@active-layers="codeLayers.markActive"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
/>
</div>
<div
v-if="error"
role="alert"
data-test-id="code-panel-error"
class="shrink-0 border-t border-[var(--color-error-border)] bg-[var(--color-error-bg)] px-3 py-2 text-[11px] leading-snug text-[var(--color-error)]"
>
{{ error }}
</div>
<footer
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
v-if="!showEmptyState"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
class="flex shrink-0 items-center justify-between gap-2 border-t border-border px-3 py-2"
>
<span
data-test-id="code-panel-status"
class="min-w-0 truncate"
:data-tone="statusTone"
:class="statusStyles.text()"
>
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
{{ readOnly ? code.generatedReadOnly : statusText }}
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
</span>
<div class="flex items-center gap-1">
<AppButton
feat(code): link the Code tab to canvas layers and sync both ways (#805) * feat(code): link code to canvas layers and underline design issues Code in the Code tab and layers on the canvas were unrelated: finding the element behind a layer, or the layer behind an element, meant reading names. Generated Design JSX and Tailwind JSX report the layer behind each element in the order elements open, and edited Design JSX keeps the source line of every element through the sandbox and renderer, so hovering an element highlights its layer, Cmd/Ctrl-click brings it into view without changing the selection the code shows, and errors and warnings from the design check are underlined on the property that causes them. * feat(code): explain the Code tab when nothing is selected With no selection the editor showed a starter frame that read like a real layer. The tab now says it shows the selected layers' code and offers Write JSX, which opens the editor focused on the starter template. * refactor(code): group code-to-layer linking into its own domain Layer link types, issue mapping, and the hover and reveal behavior move from the Code panel and a component file into src/app/code/layers, with useCodeLayers as the panel's entry point, so app code no longer imports types from components. * fix(code): underline off-scale gaps after the spacing rule renamed its property * feat(code): mark the layer of the element around the cursor Hover highlighting and ⌘-click reveal replaced by one model: the element around the cursor marks its opening and closing tag names and outlines its layer on the canvas while the editor has focus. ⌘-click also collided with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a cursor so it links the same way. Leaving the editor now ends a live Design JSX edit as one undo step. Before, canvas edits made after typing never reached the code until the tab was reopened, and their undo entries landed before the edit's. * feat(code): sync the Code tab and the canvas both ways by patching Canvas edits now patch the Design JSX a person wrote instead of waiting for them to leave the editor: each linked element remembers the layer as Design JSX last wrote it, and a canvas change rewrites only the attributes, text and child elements that differ from that base, as CodeMirror changes that keep the cursor, comments, formatting and history. Attributes written as expressions are never overwritten; the code marks them when the canvas now differs. Untouched code is regenerated with a minimal text change. Code edits update layers in place: the new render is reconciled into the existing layers (reconcileRenderedLayers), which keep their ids, so links, selection and canvas edits survive typing. Each edit is one coalesced undo step, replacing the restore-and-rerender preview and the commit on blur. * feat(code): patch reordered layers and aliased properties in edited code Reordering layers on the canvas now moves their elements in code a person wrote: each child element and the blank lines and comments above it form a block kept as written, and the children are written again in the new order, staying linked. Children that cannot move safely, such as a loop between them, keep their order and are marked. Properties accepted under several names now come from one alias table in the Design JSX schema, which the renderer resolves through and the patcher and issue underlines use, so a canvas change to `w` patches `width` where the person wrote that, instead of adding a second attribute. * feat(code): keep the cursor in moved code and patch values written in style A reorder rewrites the children span in one change, which collapsed a cursor or out-of-sync marker inside a moved element to the span's edge. The patch now carries where each block moved and places selections and markers inside it at their new position. Properties the renderer also reads from style={{ … }} come from a table in the Design JSX schema instead of a hand-written list, keeping the rule that an attribute under any of its names wins. The patcher uses it to update a value written in style where it is, as a number or a px string as written; values the renderer cannot read, such as '50%', are marked. The layer patcher is split by concern: syntax helpers, attribute and style patches, child patches, out-of-sync state and transaction assembly. * feat(code): show the code's layer on the canvas as a tinted box The layer of the element around the cursor used the canvas hover slot, so moving the pointer over the canvas replaced it and the two read the same. It now has its own shared editor state, codeFocusNodeId, drawn as the hover outline over a light tint in every pane: hover stays an outline and the selection keeps its handles, without borrowing the dashed outlines that already mean component sets, drag parents and ghosts. * fix(code): write added and removed layers when a reorder cannot move the code When children could not be moved, such as two written on one line, the patch marked the order and returned before adding or removing elements, so a layer created in the same change never reached the code. It now marks the order and still writes additions and removals. * refactor(design-jsx): format the rebased layer description and stroke aliases * feat(code): mount the layer-linked code editor through useCodeMirror Master moved the code editor onto the shared useCodeMirror composable. Its layer links, issue underlines, canvas patches, minimal text updates, autofocus and read-only cursor now sit on that composable instead of a hand-mounted view.
2026-10-04 10:08:40 +00:00
v-if="edited && !readOnly"
color="neutral"
variant="ghost"
size="xs"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
data-test-id="code-panel-reset"
@click="resetDraft"
>
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
<icon-lucide-rotate-ccw class="size-3" />
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
{{ code.reset }}
</AppButton>
<AppButton
color="neutral"
variant="ghost"
size="xs"
data-test-id="code-panel-copy"
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
@click="copy(draft)"
>
<icon-lucide-check v-if="copied" class="size-3 text-[var(--color-success)]" />
<icon-lucide-copy v-else class="size-3" />
refactor(i18n): migrate app copy to domain namespaces * refactor(i18n): migrate app copy to domain namespaces - Replace the monolithic dialogs catalog with 16 flat product-domain catalogs - Preserve every translated locale value while moving all 356 messages - Expose narrow domain composables and retain useI18n as a compatibility aggregate - Document namespace ownership and admission rules * fix(i18n): complete migrated locale coverage - Translate exposed MCP automation, code editor, credential, and media placeholders - Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics - Preserve technical product terms and interpolation placeholders * fix(i18n): polish remaining locale wording - Correct the mixed-language German code source label - Preserve stock_photo and Pexels semantics in German and Polish - Improve Italian MCP and code-editor grammar - Use the standard Russian term for MCP endpoint * fix(i18n): migrate diagnostics copy after rebase - Add a diagnostics domain for newly merged usage and telemetry settings - Keep settings navigation labels in the settings domain - Preserve translated diagnostics catalogs from current master * style(app): format rebased settings components * refactor(i18n): simplify domain message keys - Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs - Move feature-specific actions out of the common namespace - Preserve current-master language picker and diagnostics copy across every locale - Update consumers to concise semantic keys * fix(app): preserve font and updater contracts - Restore browser and abort-aware font loading from current master - Remove the unused parameter helper from common messages - Update updater tests for semantic domain keys * fix(i18n): finish semantic diagnostics access * refactor(i18n): derive active MCP status message * fix(i18n): preserve rendering settings after rebase - Add a rendering domain for tiled canvas preferences - Preserve the current-master language and rendering settings UI - Move every translated renderer preference out of the retired dialogs catalog * fix(i18n): polish reviewed locale semantics * test(i18n): enforce translation completeness baseline - Fail on interpolation placeholder drift and suspicious mixed-script values - Reject new source-identical translations while tracking existing debt explicitly - Report translated-message coverage for every supported locale - Require baseline cleanup when existing placeholders are translated * refactor(i18n): baseline reviewed mixed-script messages - Replace brittle product-vocabulary exceptions with Unicode script detection - Track reviewed mixed-script messages by stable locale and message identity - Reject new entries and stale baseline debt without hardcoded terminology * fix(fig): resolve relocated stroke test helper
2026-08-31 20:54:14 +00:00
{{ copied ? common.copied : common.copy }}
</AppButton>
</div>
feat(code): add live JSX and HTML/CSS editing (#525) * feat(code): isolate Design JSX execution - Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker - Block ambient network capabilities and enforce source, timeout, output, depth, and element limits - Validate that only bounded plain structured data returns to the application * feat(code): add editable Design JSX - Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling - Convert validated sandbox output into trusted Design JSX helpers before rendering - Apply or insert JSX as one undoable graph transaction while preserving dirty drafts * feat(code): localize JSX editor actions - Add translated-message fallbacks for editing, applying, inserting, and draft state - Document the editable JSX workflow in the unreleased changelog * fix(code): satisfy typed sandbox validation - Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint * test(code): resolve sandbox probes through app aliases * fix(code): bound sandbox results before cloning - Enforce string, array, object, depth, element, and byte limits inside the disposable worker - Retain host-side validation as a second structured-data boundary * fix(code): keep JSX and HTML editing modes separate - Switch generated Tailwind output back to OpenPencil JSX before editing - Close the JSX editor when opening HTML/CSS import and avoid stacking both editors * feat(code): support authored Design JSX programs - Allow local constants, function components, arrays, conditionals, fragments, and multiple roots - Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections - Cover multi-root undo, redo, and all-or-nothing rollback * feat(code): add explicit JSX view mode - Let authors leave CodeMirror without applying a draft - Keep the editable surface and HTML/CSS importer mutually exclusive * feat(code): diagnose unknown JSX vocabulary - Warn on OpenPencil elements and properties that are absent from the canonical schema - Surface diagnostics inline through CodeMirror lint markers * test(code): accept WebKit isolation diagnostics - Cover the sandbox architecture against Playwright WebKit - Accept engine-specific wording while preserving the same unavailable-window assertion * refactor(code): consolidate Design JSX vocabulary - Drive renderer warnings, completion, and diagnostics from one supported-property schema - Recognize locally declared components and add focused schema and transform tests - Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package * fix(code): support Design JSX variable helpers * refactor(code): unify JSX sandbox validation * fix(code): account for complete sandbox output * fix(code): preserve locked JSX descendants * fix(code): preserve JSX sibling order * fix(code): recompute JSX parent layouts * feat(code): add live code previews * test(code): centralize graph assertions * fix(code): harden live preview sessions * docs: describe live code editing * fix(code): update editor accessibility labels * fix(code): use theme-aware error colors * fix(dev): stop Vite disconnect error loops * fix(code): clarify live preview status * fix(ui): avoid tooltip attribute warnings * test(code): assert semantic preview status * refactor(code): remove obsolete editor messages * fix(code): harden preview concurrency and isolation * fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
</footer>
</div>
</template>