Skip to content

Commit c896bbd

Browse files
author
Ronald A Richardson
committed
fix: stable element object identity prevents interact.js destruction on addElement; add canvas boundary clamping
Root cause of persistent drag/resize breakage ---------------------------------------------- The previous implementation stored the entire template (including content array) in a single @Tracked _template object. Every mutation went through _updateTemplate(), which did: JSON.parse(JSON.stringify(merged)) This deep-clone creates brand-new JS object references for EVERY element in the content array, even elements that were not changed. Glimmer's {{#each}} loop compares item references to decide whether to reuse or recreate a component. Because every object was a new reference after every operation (addElement, updateElement, deleteElement, reorderElement), Glimmer destroyed and recreated EVERY ElementRenderer component on every single mutation. This fired will-destroy (teardownElement -> interactable.unset()) followed by did-insert (setupElement -> new interactable) for all elements — not just the one that changed. Fix: split state into @Tracked _meta (non-content template fields) and @Tracked _content (element array). The invariant is that existing element objects keep their JS identity across renders: addElement -> push new object onto _content; existing objects unchanged; Glimmer creates exactly one new ElementRenderer updateElement -> Object.assign onto the existing object (preserves identity); replace _content with [..._content] (same refs) to notify Glimmer; {{#each}} reuses all existing components moveElement -> Object.assign only; no _content replacement; zero re-renders deleteElement -> filter to new array without target; only that component is destroyed reorderElement-> mutate z_index in-place; replace array ref for reactivity undo/redo -> restore from deep-cloned snapshot; full re-render acceptable since it is an explicit user action Canvas boundary clamping ------------------------ Added position and size clamping in both the drag.move and resize.move handlers in canvas.js. Elements are now constrained to [0, canvasWidth - elW] on the x axis and [0, canvasHeight - elH] on the y axis. Canvas dimensions are read at event time (getCanvasDims()) so paper-size changes are reflected without recreating interactables.
1 parent 548d603 commit c896bbd

File tree

2 files changed

+188
-148
lines changed

2 files changed

+188
-148
lines changed

0 commit comments

Comments
 (0)