From 9d2f887c79a4a0aac38bf1efce897ed7491534d4 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Wed, 2 Oct 2024 10:56:54 +0200 Subject: [PATCH] Dom sampler measures grid placeholders to store grid cell global frames (#6410) **Problem:** Setting `justifyContent` or `alignContent` etc properties is not reflected in the calculated grid cell bounds (and that ruins most grid interactions and controls). **Fix:** So it turned out that calculating the grid cell bounds from the computedStyle is just too complicated and error prone. Calculating the grid cell width/height is easy, but to get the position we would need to reimplement some of the grid layouting algorithm of the browser. The solution is to go back to measure the placeholders of the grid control in the DOM, but let's do it in the dom sampler, and save the measurements in the metadata. This way we can keep the advantages of the domquery -> metadata refactor (because all strategies and controls still use the metadata to get the cell bounds), but we can still rely on the precise dom measurements. Using the dom api is fine, because we keep it inside the dom sampler which does dom measurements anyway. This solution needs 2 extra hacks to work properly: - sometimes the grid controls are not on the screen when an interaction starts. In these cases the startingMetadata does not contain the grid cell bounds. As a workaround I wrote a helper which gets the bounds from either the startingMetadata or the latestMetadata, and stores it in the custom strategy state. So in these grid strategies we don't really use the startingMetadata, but the first metadata which already contains the grid bounds. - the grid cells are measured on the grid controls, but the controls render later than then canvas. First canvas store is flushed, then the dom sampler runs, then the editor store is flushed and the controls are rendered. This order is important, because the controls rely on the metadata produced by the dom sampler. This means that after certain changes (e.g. a zoom in) the grid controls are outdated when the dom sampler runs, and we can't measure the correct cell bounds. To circumvent this, I added an observer to the grid controls, which triggers another dom sampling after a grid control change. **Commit Details:** - Introduced new field `gridCellGlobalFrames` in `specialSizeMeasurements` - Filling in `gridCellGlobalFrames` in `getSpecialMeasurements` by finding the grid placeholders in the canvas control. - Removed `getGlobalFramesOfGridCells`, because it would just need to return `specialSizeMeasurements.gridCellGlobalFrames` - Introduced `getMetadataWithGridCellBounds` which gets the metadata either from startingMetadata or latestMetadada, and chooses the one with grid cell bounds in it (if possible) - Added new observer to `DomWalkerMutableState` called `gridControlObserver` - Added a parameter to `runDOMWalker` action which makes it possible to restrict the dom sampler run to a given array of element paths (necessary so we can trigger a dom walker run only on the grid). **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../ui-jsx-canvas-bugs.spec.tsx.snap | 2 + .../__snapshots__/ui-jsx-canvas.spec.tsx.snap | 257 ++++++++++++++++ .../canvas-strategy-types.ts | 7 +- .../strategies/grid-cell-bounds.ts | 12 +- .../grid-draw-to-insert-strategy.tsx | 45 ++- .../strategies/grid-helpers.spec.browser2.tsx | 262 ---------------- .../strategies/grid-helpers.ts | 112 ++++--- .../grid-rearrange-move-duplicate-strategy.ts | 1 + ...-rearrange-move-strategy.spec.browser2.tsx | 21 ++ .../grid-rearrange-move-strategy.ts | 2 + ...grid-reparent-strategies.spec.browser2.tsx | 61 +++- .../strategies/grid-reparent-strategy.tsx | 41 ++- ...-resize-element-strategy.spec.browser2.tsx | 3 + .../canvas/controls/grid-controls.tsx | 7 +- .../select-mode/select-mode-hooks.tsx | 2 +- .../canvas/dom-sampler.spec.browser2.tsx | 279 +++++++++++++++++- editor/src/components/canvas/dom-walker.ts | 118 +++++++- .../canvas/editor-dispatch-flow.tsx | 12 +- editor/src/components/canvas/gap-utils.ts | 3 +- .../remix/remix-error-handling.test-utils.tsx | 2 +- .../remix/remix-navigator.spec.browser2.tsx | 2 +- .../remix/remix-rendering.spec.browser2.tsx | 6 +- editor/src/components/editor/action-types.ts | 1 + .../editor/actions/action-creators.ts | 3 +- .../remix-navigation-bar.spec.browser2.tsx | 2 +- .../editor/store/dispatch-strategies.spec.tsx | 8 + .../store-deep-equality-instances-3.spec.ts | 7 + .../store/store-deep-equality-instances.ts | 1 + .../left-pane/settings-pane.spec.browser2.tsx | 2 +- editor/src/core/shared/element-template.ts | 4 + editor/src/templates/editor.tsx | 71 ++++- 31 files changed, 953 insertions(+), 403 deletions(-) delete mode 100644 editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.spec.browser2.tsx diff --git a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap index c0e3d91a1384..e945250df896 100644 --- a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap +++ b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap @@ -209,6 +209,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -358,6 +359,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", diff --git a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap index 0e6854cbdb80..1bfd4ad728a5 100644 --- a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap +++ b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap @@ -250,6 +250,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -422,6 +423,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -889,6 +891,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -1205,6 +1208,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -1376,6 +1380,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -1547,6 +1552,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -1718,6 +1724,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -1994,6 +2001,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -2166,6 +2174,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -2444,6 +2453,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -2719,6 +2729,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -2891,6 +2902,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -3043,6 +3055,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -3336,6 +3349,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -3508,6 +3522,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -3887,6 +3902,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -4232,6 +4248,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -4432,6 +4449,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -4598,6 +4616,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -4798,6 +4817,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -4964,6 +4984,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -5164,6 +5185,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -5330,6 +5352,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -5674,6 +5697,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -5846,6 +5870,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -6446,6 +6471,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -7012,6 +7038,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -7418,6 +7445,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -7790,6 +7818,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -8010,6 +8039,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -8196,6 +8226,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -8416,6 +8447,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -8602,6 +8634,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -8822,6 +8855,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -9008,6 +9042,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -9414,6 +9449,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -9786,6 +9822,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -10006,6 +10043,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -10192,6 +10230,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -10412,6 +10451,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -10598,6 +10638,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -10818,6 +10859,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -11004,6 +11046,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -11410,6 +11453,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -11782,6 +11826,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -12002,6 +12047,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -12188,6 +12234,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -12408,6 +12455,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -12594,6 +12642,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -12814,6 +12863,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -13000,6 +13050,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -13287,6 +13338,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -13459,6 +13511,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -13672,6 +13725,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -13825,6 +13879,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -13978,6 +14033,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -14253,6 +14309,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -14425,6 +14482,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -14690,6 +14748,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -14983,6 +15042,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -15155,6 +15215,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -15551,6 +15612,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -15912,6 +15974,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -16132,6 +16195,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -16352,6 +16416,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -16572,6 +16637,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -16865,6 +16931,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -17037,6 +17104,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -17433,6 +17501,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -17794,6 +17863,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -18014,6 +18084,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -18234,6 +18305,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -18454,6 +18526,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -18741,6 +18814,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -18913,6 +18987,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -19126,6 +19201,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -19279,6 +19355,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -19432,6 +19509,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -19719,6 +19797,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -19891,6 +19970,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -20209,6 +20289,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -20493,6 +20574,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -20647,6 +20729,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -20801,6 +20884,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -21104,6 +21188,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -21291,6 +21376,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -21757,6 +21843,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -22042,6 +22129,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -22344,6 +22432,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -22531,6 +22620,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -22997,6 +23087,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -23282,6 +23373,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -23585,6 +23677,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -23772,6 +23865,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -24289,6 +24383,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -24625,6 +24720,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -24928,6 +25024,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -25115,6 +25212,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -25632,6 +25730,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -25968,6 +26067,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -26242,6 +26342,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -26414,6 +26515,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -26566,6 +26668,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -26963,6 +27066,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -27135,6 +27239,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -29065,6 +29170,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -30541,6 +30647,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -31983,6 +32090,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -32607,6 +32715,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -32959,6 +33068,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -33583,6 +33693,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -33935,6 +34046,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -34559,6 +34671,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -34911,6 +35024,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -35573,6 +35687,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -35967,6 +36082,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -36629,6 +36745,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -37023,6 +37140,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -37685,6 +37803,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -38079,6 +38198,7 @@ export var storyboard = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -38376,6 +38496,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -38548,6 +38669,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -38795,6 +38917,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -38965,6 +39088,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -39135,6 +39259,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -39411,6 +39536,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -39583,6 +39709,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -39802,6 +39929,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -40077,6 +40205,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -40249,6 +40378,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -40572,6 +40702,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -40893,6 +41024,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -41065,6 +41197,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -41345,6 +41478,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -41574,6 +41708,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -41752,6 +41887,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -42055,6 +42191,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -42242,6 +42379,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -42599,6 +42737,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -42778,6 +42917,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -43234,6 +43374,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -43421,6 +43562,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -43780,6 +43922,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -43959,6 +44102,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -44346,6 +44490,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -44517,6 +44662,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -45313,6 +45459,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -45467,6 +45614,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -45621,6 +45769,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -45775,6 +45924,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -45931,6 +46081,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -46085,6 +46236,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -46239,6 +46391,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -46393,6 +46546,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -46615,6 +46769,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -46798,6 +46953,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -46954,6 +47110,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -47108,6 +47265,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -47262,6 +47420,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -47416,6 +47575,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -47570,6 +47730,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -47724,6 +47885,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -47878,6 +48040,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -48032,6 +48195,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -48186,6 +48350,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -48340,6 +48505,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -48494,6 +48660,7 @@ export var App = (props) => { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -48787,6 +48954,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -48959,6 +49127,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -49355,6 +49524,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -49716,6 +49886,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -49936,6 +50107,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -50156,6 +50328,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -50376,6 +50549,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -50669,6 +50843,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -50841,6 +51016,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -51236,6 +51412,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -51596,6 +51773,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -51816,6 +51994,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -52036,6 +52215,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -52256,6 +52436,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -52549,6 +52730,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -52721,6 +52903,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -53160,6 +53343,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -53564,6 +53748,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -53784,6 +53969,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -54004,6 +54190,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -54224,6 +54411,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -54523,6 +54711,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -54710,6 +54899,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -54976,6 +55166,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -55155,6 +55346,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -55432,6 +55624,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -55581,6 +55774,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -55778,6 +55972,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -55937,6 +56132,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -56096,6 +56292,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -56360,6 +56557,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -56509,6 +56707,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -56764,6 +56963,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -56961,6 +57161,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -57121,6 +57322,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -57373,6 +57575,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -57522,6 +57725,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -57787,6 +57991,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -57961,6 +58166,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -58213,6 +58419,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -58362,6 +58569,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -58514,6 +58722,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -58774,6 +58983,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -58923,6 +59133,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -59153,6 +59364,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -59332,6 +59544,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -59586,6 +59799,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -59735,6 +59949,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -60062,6 +60277,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -60255,6 +60471,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -60448,6 +60665,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -60701,6 +60919,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -60850,6 +61069,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -61019,6 +61239,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -61317,6 +61538,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -61489,6 +61711,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -61998,6 +62221,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -62157,6 +62381,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -62430,6 +62655,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -62701,6 +62927,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -62896,6 +63123,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -63089,6 +63317,7 @@ export var storyboard = ( "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -63369,6 +63598,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -63541,6 +63771,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -63742,6 +63973,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -63912,6 +64144,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -64190,6 +64423,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -64362,6 +64596,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -64514,6 +64749,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -64822,6 +65058,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -64994,6 +65231,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -65415,6 +65653,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -65801,6 +66040,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -66035,6 +66275,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -66239,6 +66480,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -66409,6 +66651,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -66643,6 +66886,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -66847,6 +67091,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -67017,6 +67262,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -67251,6 +67497,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -67455,6 +67702,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -67625,6 +67873,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -67902,6 +68151,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -68074,6 +68324,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -68226,6 +68477,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -68513,6 +68765,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -68685,6 +68938,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -68905,6 +69159,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -69095,6 +69350,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", @@ -69255,6 +69511,7 @@ Object { "gap": null, "globalContentBoxForChildren": null, "globalFrameWithTextContent": null, + "gridCellGlobalFrames": null, "hasPositionOffset": false, "hasTransform": false, "htmlElementName": "div", diff --git a/editor/src/components/canvas/canvas-strategies/canvas-strategy-types.ts b/editor/src/components/canvas/canvas-strategies/canvas-strategy-types.ts index 4a0686b16e2c..cbf09892f86c 100644 --- a/editor/src/components/canvas/canvas-strategies/canvas-strategy-types.ts +++ b/editor/src/components/canvas/canvas-strategies/canvas-strategy-types.ts @@ -1,7 +1,10 @@ import React from 'react' import type { BuiltInDependencies } from '../../../core/es-modules/package-manager/built-in-dependencies-list' import type { ElementPathTrees } from '../../../core/shared/element-path-tree' -import type { ElementInstanceMetadataMap } from '../../../core/shared/element-template' +import type { + ElementInstanceMetadata, + ElementInstanceMetadataMap, +} from '../../../core/shared/element-template' import type { CanvasVector } from '../../../core/shared/math-utils' import type { ElementPath, NodeModules } from '../../../core/shared/project-file-types' import type { ProjectContentTreeRoot } from '../../assets' @@ -30,6 +33,7 @@ export type GridCustomStrategyState = { draggingFromCell: GridCellCoordinates | null originalRootCell: GridCellCoordinates | null currentRootCell: GridCellCoordinates | null + metadataCacheForGrids: { [gridPath: string]: ElementInstanceMetadata } } export type CustomStrategyStatePatch = Partial @@ -47,6 +51,7 @@ export function defaultCustomStrategyState(): CustomStrategyState { draggingFromCell: null, originalRootCell: null, currentRootCell: null, + metadataCacheForGrids: {}, }, } } diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-cell-bounds.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-cell-bounds.ts index f90d461ddae0..29f819d35a98 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-cell-bounds.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-cell-bounds.ts @@ -4,14 +4,10 @@ import { canvasPoint, isInfinityRectangle, offsetPoint, - rectContainsPoint, + rectContainsPointInclusive, } from '../../../../core/shared/math-utils' import * as EP from '../../../../core/shared/element-path' -import { - getGlobalFramesOfGridCells, - type GridCellGlobalFrames, - type TargetGridCellData, -} from './grid-helpers' +import { type GridCellGlobalFrames, type TargetGridCellData } from './grid-helpers' import type { CanvasPoint } from '../../../../core/shared/math-utils' export type GridCellCoordinates = { row: number; column: number } @@ -34,7 +30,7 @@ export function getGridCellUnderMouseFromMetadata( grid: ElementInstanceMetadata, point: CanvasPoint, ): TargetGridCellData | null { - const gridCellGlobalFrames = getGlobalFramesOfGridCells(grid) + const gridCellGlobalFrames = grid.specialSizeMeasurements.gridCellGlobalFrames if (gridCellGlobalFrames == null) { return null @@ -50,7 +46,7 @@ function getGridCellUnderPoint( ): TargetGridCellData | null { for (let i = 0; i < gridCellGlobalFrames.length; i++) { for (let j = 0; j < gridCellGlobalFrames[i].length; j++) { - if (rectContainsPoint(gridCellGlobalFrames[i][j], point)) { + if (rectContainsPointInclusive(gridCellGlobalFrames[i][j], point)) { return { gridCellCoordinates: gridCellCoordinates(i + 1, j + 1), cellCanvasRectangle: gridCellGlobalFrames[i][j], diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx index 8846b941cb08..1e1ed0429722 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx @@ -43,7 +43,7 @@ import { getStyleAttributesForFrameInAbsolutePosition, updateInsertionSubjectWithAttributes, } from './draw-to-insert-metastrategy' -import { setGridPropsCommands } from './grid-helpers' +import { getMetadataWithGridCellBounds, setGridPropsCommands } from './grid-helpers' import { newReparentSubjects } from './reparent-helpers/reparent-strategy-helpers' import { getReparentTargetUnified } from './reparent-helpers/reparent-strategy-parent-lookup' import { getGridCellUnderMouseFromMetadata } from './grid-cell-bounds' @@ -132,9 +132,11 @@ const gridDrawToInsertStrategyInner = canvasState.propertyControlsInfo, )?.newParent.intendedParentPath - const parent = MetadataUtils.findElementByElementPath( - canvasState.startingMetadata, + const { metadata: parent, foundIn } = getMetadataWithGridCellBounds( targetParent, + canvasState.startingMetadata, + interactionSession.latestMetadata, + customStrategyState, ) if (targetParent == null || parent == null || !MetadataUtils.isGridLayoutedContainer(parent)) { @@ -158,6 +160,32 @@ const gridDrawToInsertStrategyInner = const newTargetCell = getGridCellUnderMouseFromMetadata(parent, canvasPointToUse) if (strategyLifecycle === 'mid-interaction' && interactionData.type === 'HOVER') { + const customStatePatch = + foundIn === 'latestMetadata' + ? { + ...customStrategyState, + grid: { + ...customStrategyState.grid, + // this is added here during the hover interaction so that + // `GridControls` can render the hover highlight based on the + // coordinates in `targetCellData` + targetCellData: newTargetCell ?? customStrategyState.grid.targetCellData, + metadataCacheForGrids: { + ...customStrategyState.grid.metadataCacheForGrids, + [EP.toString(targetParent)]: parent, + }, + }, + } + : { + ...customStrategyState, + grid: { + ...customStrategyState.grid, + // this is added here during the hover interaction so that + // `GridControls` can render the hover highlight based on the + // coordinates in `targetCellData` + targetCellData: newTargetCell ?? customStrategyState.grid.targetCellData, + }, + } return strategyApplicationResult( [ wildcardPatch('mid-interaction', { @@ -167,16 +195,7 @@ const gridDrawToInsertStrategyInner = updateHighlightedViews('mid-interaction', [targetParent]), ], [], - { - ...customStrategyState, - grid: { - ...customStrategyState.grid, - // this is added here during the hover interaction so that - // `GridControls` can render the hover highlight based on the - // coordinates in `targetCellData` - targetCellData: newTargetCell ?? customStrategyState.grid.targetCellData, - }, - }, + customStatePatch, ) } diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.spec.browser2.tsx deleted file mode 100644 index c7232d1373e2..000000000000 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.spec.browser2.tsx +++ /dev/null @@ -1,262 +0,0 @@ -import { matchInlineSnapshotBrowser } from '../../../../../test/karma-snapshots' -import { runDOMWalker } from '../../../editor/actions/action-creators' -import { makeTestProjectCodeWithSnippet, renderTestEditorWithCode } from '../../ui-jsx.test-utils' -import { getGlobalFramesOfGridCells } from './grid-helpers' - -describe('Grids', () => { - it('can calculate global frames of grid cells', async () => { - const editor = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(`
-
-
-
-
-
-
-
-
`), - 'await-first-dom-report', - ) - - await editor.dispatch([runDOMWalker()], true) - - // non-grids don't have cell measurements: - expect( - getGlobalFramesOfGridCells( - editor.getEditorState().editor.jsxMetadata[ - 'utopia-storyboard-uid/scene-aaa/app-entity:grid/child' - ], - ), - ).toBeNull() - - // grids have cell measurements: - matchInlineSnapshotBrowser( - getGlobalFramesOfGridCells( - editor.getEditorState().editor.jsxMetadata[ - 'utopia-storyboard-uid/scene-aaa/app-entity:grid' - ], - ), - `Array [ - Array [ - Object { - \"height\": 50, - \"width\": 150, - \"x\": 132, - \"y\": 89, - }, - Object { - \"height\": 50, - \"width\": 80, - \"x\": 302, - \"y\": 89, - }, - Object { - \"height\": 50, - \"width\": 109.5, - \"x\": 402, - \"y\": 89, - }, - Object { - \"height\": 50, - \"width\": 109.5, - \"x\": 531.5, - \"y\": 89, - }, - ], - Array [ - Object { - \"height\": 85.75, - \"width\": 150, - \"x\": 132, - \"y\": 149, - }, - Object { - \"height\": 85.75, - \"width\": 80, - \"x\": 302, - \"y\": 149, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 402, - \"y\": 149, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 531.5, - \"y\": 149, - }, - ], - Array [ - Object { - \"height\": 85.75, - \"width\": 150, - \"x\": 132, - \"y\": 244.75, - }, - Object { - \"height\": 85.75, - \"width\": 80, - \"x\": 302, - \"y\": 244.75, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 402, - \"y\": 244.75, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 531.5, - \"y\": 244.75, - }, - ], - Array [ - Object { - \"height\": 85.75, - \"width\": 150, - \"x\": 132, - \"y\": 340.5, - }, - Object { - \"height\": 85.75, - \"width\": 80, - \"x\": 302, - \"y\": 340.5, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 402, - \"y\": 340.5, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 531.5, - \"y\": 340.5, - }, - ], - Array [ - Object { - \"height\": 85.75, - \"width\": 150, - \"x\": 132, - \"y\": 436.25, - }, - Object { - \"height\": 85.75, - \"width\": 80, - \"x\": 302, - \"y\": 436.25, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 402, - \"y\": 436.25, - }, - Object { - \"height\": 85.75, - \"width\": 109.5, - \"x\": 531.5, - \"y\": 436.25, - }, - ], -]`, - ) - }) -}) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts index 210964ae37dc..aa54f900d266 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts @@ -4,7 +4,6 @@ import * as EP from '../../../../core/shared/element-path' import type { ElementInstanceMetadataMap, GridPositionValue, - GridTemplate, } from '../../../../core/shared/element-template' import { gridPositionValue, @@ -16,7 +15,6 @@ import { import type { CanvasRectangle } from '../../../../core/shared/math-utils' import { canvasPoint, - canvasRectangle, canvasVector, isInfinityRectangle, offsetPoint, @@ -36,11 +34,14 @@ import { deleteProperties } from '../../commands/delete-properties-command' import { reorderElement } from '../../commands/reorder-element-command' import { setCssLengthProperty } from '../../commands/set-css-length-command' import { setProperty } from '../../commands/set-property-command' -import type { GridCustomStrategyState } from '../canvas-strategy-types' +import type { + CustomStrategyState, + CustomStrategyStatePatch, + GridCustomStrategyState, +} from '../canvas-strategy-types' import type { DragInteractionData } from '../interaction-state' import type { GridCellCoordinates } from './grid-cell-bounds' import { getGridCellUnderMouseFromMetadata, gridCellCoordinates } from './grid-cell-bounds' -import { memoize } from '../../../../core/shared/memoize' import { mapDropNulls } from '../../../../core/shared/array-utils' import { assertNever } from '../../../../core/shared/utils' @@ -580,48 +581,11 @@ function getGridPositionIndex(props: { export type GridCellGlobalFrames = Array> -function getGlobalFramesOfGridCellsInner( - metadata: ElementInstanceMetadata, -): GridCellGlobalFrames | null { - const { globalFrame } = metadata - if (globalFrame == null || isInfinityRectangle(globalFrame)) { - return null - } - - const { containerGridProperties, padding, rowGap, columnGap } = metadata.specialSizeMeasurements - - const columnWidths = gridTemplateToNumbers(containerGridProperties.gridTemplateColumns) - - const rowHeights = gridTemplateToNumbers(containerGridProperties.gridTemplateRows) - - if (columnWidths == null || rowHeights == null) { - return null - } - - const cellRects: Array> = [] - let yOffset = globalFrame.y + (padding.top ?? 0) - rowHeights.forEach((height) => { - let xOffset = globalFrame.x + (padding.left ?? 0) - const rowRects: CanvasRectangle[] = [] - columnWidths.forEach((width) => { - const rect = canvasRectangle({ x: xOffset, y: yOffset, width: width, height: height }) - rowRects.push(rect) - xOffset += width + (columnGap ?? 0) - }) - cellRects.push(rowRects) - yOffset += height + (rowGap ?? 0) - }) - - return cellRects -} - -export const getGlobalFramesOfGridCells = memoize(getGlobalFramesOfGridCellsInner) - export function getGlobalFrameOfGridCell( grid: ElementInstanceMetadata, coords: GridCellCoordinates, ): CanvasRectangle | null { - const gridCellGlobalFrames = getGlobalFramesOfGridCells(grid) + const gridCellGlobalFrames = grid.specialSizeMeasurements.gridCellGlobalFrames if (gridCellGlobalFrames == null) { return null } @@ -629,23 +593,6 @@ export function getGlobalFrameOfGridCell( return gridCellGlobalFrames[coords.row - 1]?.[coords.column - 1] ?? null } -function gridTemplateToNumbers(gridTemplate: GridTemplate | null): Array | null { - if (gridTemplate?.type !== 'DIMENSIONS') { - return null - } - - const result: Array = [] - - for (const dimension of gridTemplate.dimensions) { - if (dimension.type !== 'NUMBER') { - return null - } - result.push(dimension.value.value) - } - - return result -} - type DimensionIndexes = { originalIndex: number // the index of this element in the original values repeatedIndex: number // the index of this element, if it's generated via a repeat, inside the repeated values array definition @@ -815,3 +762,50 @@ export function getGridRelatedIndexes(params: { return expandedRelatedIndexes[params.index] ?? [] } + +export function getMetadataWithGridCellBounds( + path: ElementPath | null | undefined, + startingMetadata: ElementInstanceMetadataMap, + latestMetadata: ElementInstanceMetadataMap, + customStrategyState: CustomStrategyState, +): { + metadata: ElementInstanceMetadata | null + foundIn: 'startingMetadata' | 'latestMetadata' | 'strategyState' | null +} { + if (path == null) { + return { + metadata: null, + foundIn: null, + } + } + + const fromStartingMetadata = MetadataUtils.findElementByElementPath(startingMetadata, path) + + if (fromStartingMetadata?.specialSizeMeasurements.gridCellGlobalFrames != null) { + return { + metadata: fromStartingMetadata, + foundIn: 'startingMetadata', + } + } + + const fromStrategyState = customStrategyState.grid.metadataCacheForGrids[EP.toString(path)] + if (fromStrategyState != null) { + return { + metadata: fromStrategyState, + foundIn: 'strategyState', + } + } + + const fromLatestMetadata = MetadataUtils.findElementByElementPath(latestMetadata, path) + if (fromLatestMetadata?.specialSizeMeasurements.gridCellGlobalFrames != null) { + return { + metadata: fromLatestMetadata, + foundIn: 'latestMetadata', + } + } + + return { + metadata: fromStartingMetadata, + foundIn: 'startingMetadata', + } +} diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts index 671f74fe51f6..bf8d3fa9fb23 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts @@ -100,6 +100,7 @@ export const gridRearrangeMoveDuplicateStrategy: CanvasStrategyFactory = ( [...selectedElements, targetElement], { grid: { + ...customState.grid, targetCellData: targetGridCellData, draggingFromCell: draggingFromCell, originalRootCell: originalRootCell, diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.spec.browser2.tsx index 2a84da3a561e..f72f00a4ef17 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.spec.browser2.tsx @@ -187,6 +187,9 @@ export var storyboard = ( height: targetRect.height, }), ), + { + moveBeforeMouseDown: true, + }, ) const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = @@ -281,6 +284,9 @@ export var storyboard = ( editor.renderedDOM.getByTestId(GridCellTestId(EP.fromString('sb/scene/grid/child'))), childCenter, offsetPoint(childCenter, windowPoint({ x: 20, y: 20 })), + { + moveBeforeMouseDown: true, + }, ) { @@ -323,6 +329,9 @@ export var storyboard = ( editor.renderedDOM.getByTestId(GridCellTestId(EP.fromString('sb/scene/grid/child'))), childCenter, offsetPoint(childCenter, windowPoint({ x: 240, y: 240 })), + { + moveBeforeMouseDown: true, + }, ) { @@ -363,6 +372,9 @@ export var storyboard = ( editor.renderedDOM.getByTestId(GridCellTestId(EP.fromString('sb/scene/grid/child'))), childCenter, offsetPoint(childCenter, windowPoint({ x: 240, y: 240 })), + { + moveBeforeMouseDown: true, + }, ) { @@ -446,6 +458,9 @@ export var storyboard = ( editor.renderedDOM.getByTestId(GridCellTestId(EP.fromString('sb/scene/grid/child'))), startPoint, offsetPoint(startPoint, windowPoint({ x: -100, y: -100 })), + { + moveBeforeMouseDown: true, + }, ) { @@ -536,6 +551,9 @@ export var storyboard = ( editor.renderedDOM.getByTestId(GridCellTestId(EP.fromString('sb/scene/grid/child'))), childCenter, offsetPoint(childCenter, windowPoint({ x: 280, y: 120 })), + { + moveBeforeMouseDown: true, + }, ) { @@ -712,6 +730,9 @@ async function runMoveTest( height: targetRect.height, }), ), + { + moveBeforeMouseDown: true, + }, ) return editor.renderedDOM.getByTestId(props.testId).style diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts index f3bc35a2a0a9..dd30a943a8b4 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts @@ -190,6 +190,7 @@ function getCommandsAndPatchForGridRearrange( commands: commands, patch: { grid: { + ...customState.grid, targetCellData: targetGridCell, draggingFromCell: draggingFromCell, originalRootCell: originalRootCell, @@ -229,6 +230,7 @@ function getCommandsAndPatchForReparent( return applyGridReparent( canvasState, interactionData, + interactionSession, customState, strategy.target, [targetElement], diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx index 8b65e186af9c..f0a5fda43079 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx @@ -10,7 +10,9 @@ import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' import type { Point } from '../../event-helpers.test-utils' import { mouseClickAtPoint, + mouseDownAtPoint, mouseDragFromPointToPoint, + mouseMoveToPoint, mouseUpAtPoint, } from '../../event-helpers.test-utils' import type { EditorRenderResult } from '../../ui-jsx.test-utils' @@ -627,8 +629,15 @@ describe('grid reparent strategies', () => { await selectComponentsForTest(editor, [EP.fromString('sb/grid/dragme')]) - await dragOut(editor, 'grid', EP.fromString('sb/grid/dragme'), { x: 2200, y: 2200 }) - + await dragOutToAnotherGrid( + editor, + 'another-grid', + { + x: 10, + y: 180, + }, + EP.fromString('sb/grid/dragme'), + ) expect(getPrintedUiJsCode(editor.getEditorState())).toEqual( formatTestProjectCode( makeTestProjectCode({ @@ -814,3 +823,51 @@ async function dragOut( }) await mouseUpAtPoint(grid, gridRect, { modifiers: cmdModifier }) } + +async function dragOutToAnotherGrid( + renderResult: EditorRenderResult, + anotherGridTestId: string, + offsetInAnotherGrid: Point, + cell: ElementPath, +) { + const sourceGridCell = renderResult.renderedDOM.getByTestId(GridCellTestId(cell)) + const sourceRect = sourceGridCell.getBoundingClientRect() + + const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + const anotherGrid = renderResult.renderedDOM.getByTestId(anotherGridTestId) + const anotherGridRect = anotherGrid.getBoundingClientRect() + + // selecting the cell + await mouseClickAtPoint( + sourceGridCell, + { x: sourceRect.x + 5, y: sourceRect.y + 5 }, + { modifiers: cmdModifier }, + ) + + // starting the drag + await mouseDownAtPoint( + sourceGridCell, + { x: sourceRect.x + 5, y: sourceRect.y + 5 }, + { modifiers: cmdModifier }, + ) + + // first move over target grid hovers the grid controls, so the dom sampler can run + await mouseMoveToPoint( + canvasControlsLayer, + { x: anotherGridRect.x + offsetInAnotherGrid.x, y: anotherGridRect.y + offsetInAnotherGrid.y }, + { modifiers: cmdModifier }, + ) + + // second move runs the strategy for the first time with cell metadata + await mouseMoveToPoint( + canvasControlsLayer, + { x: anotherGridRect.x + offsetInAnotherGrid.x, y: anotherGridRect.y + offsetInAnotherGrid.y }, + { modifiers: cmdModifier }, + ) + + await mouseUpAtPoint( + canvasControlsLayer, + { x: anotherGridRect.x + offsetInAnotherGrid.x, y: anotherGridRect.y + offsetInAnotherGrid.y }, + { modifiers: cmdModifier }, + ) +} diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx index e348e82132ac..f2829f667c44 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx @@ -8,7 +8,7 @@ import { gridPositionValue, type ElementInstanceMetadataMap, } from '../../../../core/shared/element-template' -import type { CanvasRectangle, CanvasVector } from '../../../../core/shared/math-utils' +import type { CanvasRectangle } from '../../../../core/shared/math-utils' import { canvasVector, isInfinityRectangle, offsetPoint } from '../../../../core/shared/math-utils' import type { ElementPath } from '../../../../core/shared/project-file-types' import * as PP from '../../../../core/shared/property-path' @@ -39,7 +39,7 @@ import { import type { DragInteractionData, InteractionSession, UpdatedPathMap } from '../interaction-state' import { honoursPropsPosition, shouldKeepMovingDraggedGroupChildren } from './absolute-utils' import { replaceFragmentLikePathsWithTheirChildrenRecursive } from './fragment-like-helpers' -import { setGridPropsCommands } from './grid-helpers' +import { getMetadataWithGridCellBounds, setGridPropsCommands } from './grid-helpers' import { ifAllowedToReparent, isAllowedToReparent } from './reparent-helpers/reparent-helpers' import { removeAbsolutePositioningProps } from './reparent-helpers/reparent-property-changes' import type { ReparentTarget } from './reparent-helpers/reparent-strategy-helpers' @@ -105,6 +105,7 @@ export function gridReparentStrategy( apply: applyGridReparent( canvasState, dragInteractionData, + interactionSession, customStrategyState, reparentTarget, filteredSelectedElements, @@ -141,6 +142,7 @@ export function controlsForGridReparent(reparentTarget: ReparentTarget): Control export function applyGridReparent( canvasState: InteractionCanvasState, interactionData: DragInteractionData, + interactionSession: InteractionSession, customStrategyState: CustomStrategyState, reparentTarget: ReparentTarget, selectedElements: ElementPath[], @@ -163,9 +165,11 @@ export function applyGridReparent( return emptyStrategyApplicationResult } - const grid = MetadataUtils.findElementByElementPath( - canvasState.startingMetadata, + const { metadata: grid, foundIn } = getMetadataWithGridCellBounds( newParent.intendedParentPath, + canvasState.startingMetadata, + interactionSession.latestMetadata, + customStrategyState, ) if (grid == null) { @@ -237,6 +241,27 @@ export function applyGridReparent( ...selectedElements.map(EP.parentPath), ]) + const customStrategyStatePatch = + foundIn === 'latestMetadata' + ? { + elementsToRerender: elementsToRerender, + grid: { + ...customStrategyState.grid, + targetCellData: targetCellData, + metadataCacheForGrids: { + ...customStrategyState.grid.metadataCacheForGrids, + [EP.toString(newParent.intendedParentPath)]: grid, + }, + }, + } + : { + elementsToRerender: elementsToRerender, + grid: { + ...customStrategyState.grid, + targetCellData: targetCellData, + }, + } + return strategyApplicationResult( [ ...outcomes.flatMap((c) => c.commands), @@ -246,13 +271,7 @@ export function applyGridReparent( showGridControls('mid-interaction', reparentTarget.newParent.intendedParentPath), ], elementsToRerender, - { - elementsToRerender: elementsToRerender, - grid: { - ...customStrategyState.grid, - targetCellData: targetCellData, - }, - }, + customStrategyStatePatch, ) }, ) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx index 7b39be3806b6..67897cb9e309 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx @@ -41,6 +41,9 @@ async function runCellResizeTest( height: targetGridCell.getBoundingClientRect().height, }), ), + { + moveBeforeMouseDown: true, + }, ) } diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index bbdba72e9a10..556b3fab8f1c 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -898,7 +898,7 @@ export const GridControls = controlForStrategyMemoized(({ tar } return ( - +
{/* grid lines */} {grids.map((grid) => { @@ -949,6 +949,7 @@ export const GridControls = controlForStrategyMemoized(({ tar
{placeholders.map((cell) => { @@ -992,6 +993,8 @@ export const GridControls = controlForStrategyMemoized(({ tar position: 'relative', pointerEvents: 'initial', }} + data-grid-row={countedRow} + data-grid-column={countedColumn} > {when( features.Grid.dotgrid, @@ -1120,7 +1123,7 @@ export const GridControls = controlForStrategyMemoized(({ tar ) : null} - +
) }) diff --git a/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx b/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx index 83047c82baf1..48b74f4fb8ae 100644 --- a/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx +++ b/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx @@ -805,7 +805,7 @@ function useSelectOrLiveModeSelectAndHover( dispatch(editorActions, 'canvas-fast-selection-hack') // first we dispatch only to update the editor state, but not run the expensive parts await new Promise((resolve) => requestAnimationFrame(resolve)) // the first requestAnimationFrame fires in the same animation frame we are in, so we need to wait one more await new Promise((resolve) => requestAnimationFrame(resolve)) // the second requestAnimationFrame is fired in the next actual animation frame, at which point it is safe to run the expensive parts - dispatch([runDOMWalker()], 'resume-canvas-fast-selection-hack') // then we dispatch to run the expensive parts + dispatch([runDOMWalker(null)], 'resume-canvas-fast-selection-hack') // then we dispatch to run the expensive parts } else { dispatch(editorActions) } diff --git a/editor/src/components/canvas/dom-sampler.spec.browser2.tsx b/editor/src/components/canvas/dom-sampler.spec.browser2.tsx index 3b93654cda41..43ff3cfbcdfb 100644 --- a/editor/src/components/canvas/dom-sampler.spec.browser2.tsx +++ b/editor/src/components/canvas/dom-sampler.spec.browser2.tsx @@ -5,6 +5,7 @@ import { BakedInStoryboardVariableName } from '../../core/model/scene-utils' import * as EP from '../../core/shared/element-path' import { objectMap } from '../../core/shared/object-utils' import { optionalMap } from '../../core/shared/optional-utils' +import { selectComponentsForTest } from '../../utils/utils.test-utils' import { runDOMWalker, setFocusedElement } from '../editor/actions/action-creators' import { navigatorEntryToKey } from '../editor/store/editor-state' import { getNavigatorTargetsFromEditorState } from '../navigator/navigator-utils' @@ -82,7 +83,7 @@ export var Playground = ({ style }) => { 'await-first-dom-report', ) - await editor.dispatch([runDOMWalker()], true) + await editor.dispatch([runDOMWalker(null)], true) matchInlineSnapshotBrowser( Object.keys(editor.getEditorState().editor.jsxMetadata), @@ -457,3 +458,279 @@ function makeTestProjectCodeWithStoryboard(codeForComponents: string): string { return formatTestProjectCode(code) } + +describe('Grid dom sampler tests', () => { + it('gridCellGlobalFrames calculated correctly', async () => { + const editor = await renderTestEditorWithCode( + `import * as React from 'react' +import { Scene, Storyboard } from 'utopia-api' + +export var storyboard = ( + + +
+
+
+
+
+
+
+
+
+ + +) +`, + 'await-first-dom-report', + ) + + await selectComponentsForTest(editor, [EP.fromString('storyboard/scene/grid')]) + await editor.dispatch([runDOMWalker(null)], true) + + // non-grids don't have cell measurements: + expect( + editor.getEditorState().editor.jsxMetadata['storyboard/scene/grid/child'] + .specialSizeMeasurements.gridCellGlobalFrames, + ).toBeNull() + + // grids have cell measurements: + matchInlineSnapshotBrowser( + editor.getEditorState().editor.jsxMetadata['storyboard/scene/grid'].specialSizeMeasurements + .gridCellGlobalFrames, + `Array [ + Array [ + Object { + \"height\": 50, + \"width\": 150, + \"x\": 268, + \"y\": 174, + }, + Object { + \"height\": 50, + \"width\": 80, + \"x\": 438, + \"y\": 174, + }, + Object { + \"height\": 50, + \"width\": 121.5, + \"x\": 538, + \"y\": 174, + }, + Object { + \"height\": 50, + \"width\": 121.5, + \"x\": 679.5, + \"y\": 174, + }, + ], + Array [ + Object { + \"height\": 87.5, + \"width\": 150, + \"x\": 268, + \"y\": 244, + }, + Object { + \"height\": 87.5, + \"width\": 80, + \"x\": 438, + \"y\": 244, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 538, + \"y\": 244, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 679.5, + \"y\": 244, + }, + ], + Array [ + Object { + \"height\": 87.5, + \"width\": 150, + \"x\": 268, + \"y\": 351.5, + }, + Object { + \"height\": 87.5, + \"width\": 80, + \"x\": 438, + \"y\": 351.5, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 538, + \"y\": 351.5, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 679.5, + \"y\": 351.5, + }, + ], + Array [ + Object { + \"height\": 87.5, + \"width\": 150, + \"x\": 268, + \"y\": 458.5, + }, + Object { + \"height\": 87.5, + \"width\": 80, + \"x\": 438, + \"y\": 458.5, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 538, + \"y\": 458.5, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 679.5, + \"y\": 458.5, + }, + ], + Array [ + Object { + \"height\": 87.5, + \"width\": 150, + \"x\": 268, + \"y\": 566, + }, + Object { + \"height\": 87.5, + \"width\": 80, + \"x\": 438, + \"y\": 566, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 538, + \"y\": 566, + }, + Object { + \"height\": 87.5, + \"width\": 121.5, + \"x\": 679.5, + \"y\": 566, + }, + ], +]`, + ) + }) +}) diff --git a/editor/src/components/canvas/dom-walker.ts b/editor/src/components/canvas/dom-walker.ts index 5b2ea0ba4de3..3a0e979335fe 100644 --- a/editor/src/components/canvas/dom-walker.ts +++ b/editor/src/components/canvas/dom-walker.ts @@ -4,16 +4,13 @@ import * as ResizeObserverSyntheticDefault from 'resize-observer-polyfill' import * as EP from '../../core/shared/element-path' import type { DetectedLayoutSystem, - ComputedStyle, SpecialSizeMeasurements, - StyleAttributeMetadata, ElementInstanceMetadataMap, GridContainerProperties, GridElementProperties, DomElementMetadata, } from '../../core/shared/element-template' import { - elementInstanceMetadata, specialSizeMeasurements, gridContainerProperties, gridElementProperties, @@ -47,7 +44,6 @@ import type { CSSNumber, CSSPosition } from '../inspector/common/css-utils' import { parseCSSLength, positionValues, - computedStyleKeys, parseDirection, parseFlexDirection, parseCSSPx, @@ -57,17 +53,18 @@ import { parseGridAutoFlow, isCSSKeyword, } from '../inspector/common/css-utils' -import { camelCaseToDashed } from '../../core/shared/string-utils' import type { UtopiaStoreAPI } from '../editor/store/store-hook' -import { UTOPIA_SCENE_ID_KEY, UTOPIA_UID_KEY } from '../../core/model/utopia-constants' +import { + UTOPIA_PATH_KEY, + UTOPIA_SCENE_ID_KEY, + UTOPIA_UID_KEY, +} from '../../core/model/utopia-constants' import { emptySet } from '../../core/shared/set-utils' -import type { PathWithString } from '../../core/shared/uid-utils' import { getDeepestPathOnDomElement, getPathStringsOnDomElement } from '../../core/shared/uid-utils' import { forceNotNull } from '../../core/shared/optional-utils' import { fastForEach } from '../../core/shared/utils' import type { EditorState, EditorStorePatched } from '../editor/store/editor-state' import { shallowEqual } from '../../core/shared/equality-utils' -import { pick } from '../../core/shared/object-utils' import { getFlexAlignment, getFlexJustifyContent, @@ -78,6 +75,7 @@ import type { EditorDispatch } from '../editor/action-types' import { runDOMWalker } from '../editor/actions/action-creators' import { CanvasContainerOuterId } from './canvas-component-entry' import { ElementsToRerenderGLOBAL } from './ui-jsx-canvas' +import type { GridCellGlobalFrames } from './canvas-strategies/strategies/grid-helpers' export const ResizeObserver = window.ResizeObserver ?? ResizeObserverSyntheticDefault.default ?? ResizeObserverSyntheticDefault @@ -264,6 +262,7 @@ export interface DomWalkerMutableStateData { initComplete: boolean mutationObserver: MutationObserver resizeObserver: ResizeObserver + gridControlObserver: MutationObserver } export function createDomWalkerMutableState( @@ -276,12 +275,13 @@ export function createDomWalkerMutableState( initComplete: true, mutationObserver: null as any, resizeObserver: null as any, + gridControlObserver: null as any, } const observers = initDomWalkerObservers(mutableData, editorStoreApi, dispatch) mutableData.mutationObserver = observers.mutationObserver mutableData.resizeObserver = observers.resizeObserver - + mutableData.gridControlObserver = observers.gridControlObserver return mutableData } @@ -296,8 +296,10 @@ function useDomWalkerMutableStateContext() { export function resubscribeObservers(domWalkerMutableState: { mutationObserver: MutationObserver resizeObserver: ResizeObserver + gridControlObserver: MutationObserver }) { const canvasRootContainer = document.getElementById(CanvasContainerOuterId) + const gridControls = document.getElementById('grid-controls') if ( ObserversAvailable && @@ -309,6 +311,9 @@ export function resubscribeObservers(domWalkerMutableState: { domWalkerMutableState.resizeObserver.observe(elem) }) domWalkerMutableState.mutationObserver.observe(canvasRootContainer, MutationObserverConfig) + if (gridControls != null) { + domWalkerMutableState.gridControlObserver.observe(gridControls, MutationObserverConfig) + } } } @@ -321,12 +326,16 @@ export function initDomWalkerObservers( domWalkerMutableState: DomWalkerMutableStateData, editorStore: UtopiaStoreAPI, dispatch: EditorDispatch, -): { resizeObserver: ResizeObserver; mutationObserver: MutationObserver } { +): { + resizeObserver: ResizeObserver + mutationObserver: MutationObserver + gridControlObserver: MutationObserver +} { let domWalkerTimeoutID: number | null = null - function queueUpDomWalker(): void { + function queueUpDomWalker(restrictToElements: Array | null): void { if (domWalkerTimeoutID == null) { domWalkerTimeoutID = window.setTimeout(() => { - dispatch([runDOMWalker()]) + dispatch([runDOMWalker(restrictToElements)]) domWalkerTimeoutID = null }) } @@ -362,7 +371,7 @@ export function initDomWalkerObservers( } } if (shouldRunDOMWalker) { - queueUpDomWalker() + queueUpDomWalker(null) } } }) @@ -394,12 +403,29 @@ export function initDomWalkerObservers( } } if (shouldRunDOMWalker) { - queueUpDomWalker() + queueUpDomWalker(null) } } }) - return { resizeObserver, mutationObserver } + const gridControlObserver = new window.MutationObserver((mutations: MutationRecord[]) => { + let shouldRunDOMWalkerOnPath = null + mutations.forEach((mutation) => { + if (mutation.target instanceof HTMLElement) { + for (const child of mutation.target.children) { + const gridPath = child.getAttribute('data-grid-path') + if (gridPath != null) { + shouldRunDOMWalkerOnPath = EP.fromString(gridPath) + } + } + } + }) + if (shouldRunDOMWalkerOnPath != null) { + queueUpDomWalker([shouldRunDOMWalkerOnPath]) + } + }) + + return { resizeObserver, mutationObserver, gridControlObserver } } export function invalidateDomWalkerIfNecessary( @@ -857,6 +883,21 @@ function getSpecialMeasurements( const parentContainerGridProperties = getGridContainerProperties(parentElementStyle) const containerGridProperties = getGridContainerProperties(elementStyle) + + const paddingValue = isRight(padding) + ? padding.value + : sides(undefined, undefined, undefined, undefined) + + const gridCellGlobalFrames = + layoutSystemForChildren === 'grid' + ? measureGlobalFramesOfGridCellsFromControl( + element, + scale, + containerRectLazy, + elementCanvasRectangleCache, + ) + : null + const containerElementProperties = getGridElementProperties( parentContainerGridProperties, elementStyle, @@ -881,7 +922,7 @@ function getSpecialMeasurements( elementStyle.display, position, isRight(margin) ? margin.value : sides(undefined, undefined, undefined, undefined), - isRight(padding) ? padding.value : sides(undefined, undefined, undefined, undefined), + paddingValue, naturalWidth, naturalHeight, clientWidth, @@ -918,6 +959,7 @@ function getSpecialMeasurements( containerElementPropertiesFromProps, rowGap, columnGap, + gridCellGlobalFrames, justifySelf, alignSelf, ) @@ -976,3 +1018,47 @@ function getClosestOffsetParent(element: HTMLElement): Element | null { } return null } + +function measureGlobalFramesOfGridCellsFromControl( + grid: HTMLElement, + scale: number, + containerRectLazy: CanvasPoint | (() => CanvasPoint), + elementCanvasRectangleCache: ElementCanvasRectangleCache, +): GridCellGlobalFrames | null { + const path = grid.getAttribute(UTOPIA_PATH_KEY) + let gridCellGlobalFrames: Array> | null = null + if (path != null) { + const gridControlElement = document.getElementById(`grid-${path}`) + if (gridControlElement != null) { + gridCellGlobalFrames = [] + for (const cell of gridControlElement.children) { + if (!(cell instanceof HTMLElement)) { + continue + } + const rowIndexAttr = cell.getAttribute('data-grid-row') + const columnIndexAttr = cell.getAttribute('data-grid-column') + if (rowIndexAttr == null || columnIndexAttr == null) { + continue + } + const rowIndex = parseInt(rowIndexAttr) + const columnIndex = parseInt(columnIndexAttr) + if (!isFinite(rowIndex) || !isFinite(columnIndex)) { + continue + } + const row = gridCellGlobalFrames[rowIndex - 1] + if (row == null) { + gridCellGlobalFrames[rowIndex - 1] = [] + } + gridCellGlobalFrames[rowIndex - 1][columnIndex - 1] = globalFrameForElement( + cell, + scale, + containerRectLazy, + 'without-text-content', + 'nearest-half', + elementCanvasRectangleCache, + ) + } + } + } + return gridCellGlobalFrames +} diff --git a/editor/src/components/canvas/editor-dispatch-flow.tsx b/editor/src/components/canvas/editor-dispatch-flow.tsx index eadd05a9ed58..fbfdf7987849 100644 --- a/editor/src/components/canvas/editor-dispatch-flow.tsx +++ b/editor/src/components/canvas/editor-dispatch-flow.tsx @@ -1,3 +1,4 @@ +import type { ElementPath } from 'utopia-shared/src/types' import type { EditorDispatch } from '../editor/action-types' import { updateMetadataInEditorState } from '../editor/actions/action-creators' import type { DispatchResult } from '../editor/store/dispatch' @@ -29,11 +30,20 @@ export function runDomSamplerAndSaveResults( domWalkerMutableState: { mutationObserver: MutationObserver resizeObserver: ResizeObserver + gridControlObserver: MutationObserver }, spyCollector: UiJsxCanvasContextData, + restrictToElements: + | 'run-full' + | { + restrictToElements: Array + }, ) { const metadataResult = runDomSamplerRegular({ - elementsToFocusOn: ElementsToRerenderGLOBAL.current, + elementsToFocusOn: + restrictToElements === 'run-full' + ? ElementsToRerenderGLOBAL.current + : restrictToElements.restrictToElements, domWalkerAdditionalElementsToFocusOn: storedState.patchedEditor.canvas.domWalkerAdditionalElementsToUpdate, scale: storedState.patchedEditor.canvas.scale, diff --git a/editor/src/components/canvas/gap-utils.ts b/editor/src/components/canvas/gap-utils.ts index cddd81efd7a6..07a945aae2b8 100644 --- a/editor/src/components/canvas/gap-utils.ts +++ b/editor/src/components/canvas/gap-utils.ts @@ -33,7 +33,6 @@ import { treatElementAsFragmentLike } from './canvas-strategies/strategies/fragm import type { AllElementProps } from '../editor/store/editor-state' import type { GridData } from './controls/grid-controls' import { getNullableAutoOrTemplateBaseString } from './controls/grid-controls' -import { getGlobalFramesOfGridCells } from './canvas-strategies/strategies/grid-helpers' export interface PathWithBounds { bounds: CanvasRectangle @@ -221,7 +220,7 @@ export function gridGapControlBoundsFromMetadata( gridRowColumnInfo.gridTemplateColumns, ) - const gridCellBounds = getGlobalFramesOfGridCells(grid) + const gridCellBounds = grid.specialSizeMeasurements.gridCellGlobalFrames if (gridCellBounds == null) { return emptyResult diff --git a/editor/src/components/canvas/remix/remix-error-handling.test-utils.tsx b/editor/src/components/canvas/remix/remix-error-handling.test-utils.tsx index 492b757571c9..e1d229403149 100644 --- a/editor/src/components/canvas/remix/remix-error-handling.test-utils.tsx +++ b/editor/src/components/canvas/remix/remix-error-handling.test-utils.tsx @@ -25,7 +25,7 @@ export async function renderRemixProject(project: PersistentModel) { notLoggedIn, false, ) - await renderResult.dispatch([runDOMWalker()], true) + await renderResult.dispatch([runDOMWalker(null)], true) return renderResult } diff --git a/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx b/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx index b56940dc5344..982859397dac 100644 --- a/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx +++ b/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx @@ -23,7 +23,7 @@ const RootTextContent = 'This is root!' async function renderRemixProject(project: PersistentModel) { const renderResult = await renderTestEditorWithModel(project, 'await-first-dom-report') - await renderResult.dispatch([runDOMWalker()], true) + await renderResult.dispatch([runDOMWalker(null)], true) return renderResult } diff --git a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx index 197fe32db18f..d31daf6c75b0 100644 --- a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx +++ b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx @@ -81,7 +81,7 @@ async function renderRemixProject( undefined, strategiesToUse, ) - await renderResult.dispatch([runDOMWalker()], true) + await renderResult.dispatch([runDOMWalker(null)], true) return renderResult } @@ -1765,7 +1765,7 @@ export default function Index() { it('flex reorder elements inside Remix', async () => { const renderResult = await renderRemixProject(remixProjectForEditingTests) - await renderResult.dispatch([runDOMWalker()], true) + await renderResult.dispatch([runDOMWalker(null)], true) expect( getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( @@ -1871,7 +1871,7 @@ export default function Index() { it('draw to insert into Remix', async () => { const renderResult = await renderRemixProject(remixProjectForEditingTests) - await renderResult.dispatch([runDOMWalker()], true) + await renderResult.dispatch([runDOMWalker(null)], true) expect( getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( diff --git a/editor/src/components/editor/action-types.ts b/editor/src/components/editor/action-types.ts index 757fa6769497..ca9ef5a0290c 100644 --- a/editor/src/components/editor/action-types.ts +++ b/editor/src/components/editor/action-types.ts @@ -788,6 +788,7 @@ export interface UpdateMetadataInEditorState { export interface RunDOMWalker { action: 'RUN_DOM_WALKER' + restrictToElements: Array | null } export interface TrueUpElements { diff --git a/editor/src/components/editor/actions/action-creators.ts b/editor/src/components/editor/actions/action-creators.ts index 723c48306606..f78aa83dba6b 100644 --- a/editor/src/components/editor/actions/action-creators.ts +++ b/editor/src/components/editor/actions/action-creators.ts @@ -1246,9 +1246,10 @@ export function updateMetadataInEditorState( } } -export function runDOMWalker(): RunDOMWalker { +export function runDOMWalker(restrictToElements: Array | null): RunDOMWalker { return { action: 'RUN_DOM_WALKER', + restrictToElements: restrictToElements, } } diff --git a/editor/src/components/editor/remix-navigation-bar.spec.browser2.tsx b/editor/src/components/editor/remix-navigation-bar.spec.browser2.tsx index f14856bb17c8..116b3e904569 100644 --- a/editor/src/components/editor/remix-navigation-bar.spec.browser2.tsx +++ b/editor/src/components/editor/remix-navigation-bar.spec.browser2.tsx @@ -13,7 +13,7 @@ import { getFeaturedRoutesFromPackageJSON } from '../../printer-parsers/html/ext async function renderRemixProject(project: PersistentModel): Promise { const renderResult = await renderTestEditorWithModel(project, 'await-first-dom-report') - await renderResult.dispatch([runDOMWalker()], true) + await renderResult.dispatch([runDOMWalker(null)], true) return renderResult } diff --git a/editor/src/components/editor/store/dispatch-strategies.spec.tsx b/editor/src/components/editor/store/dispatch-strategies.spec.tsx index a3ffdb94c054..dbb51ea5f9cb 100644 --- a/editor/src/components/editor/store/dispatch-strategies.spec.tsx +++ b/editor/src/components/editor/store/dispatch-strategies.spec.tsx @@ -201,6 +201,7 @@ describe('interactionStart', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, @@ -269,6 +270,7 @@ describe('interactionStart', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, @@ -357,6 +359,7 @@ describe('interactionUpdate', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, @@ -445,6 +448,7 @@ describe('interactionUpdate', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, @@ -527,6 +531,7 @@ describe('interactionHardReset', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, @@ -617,6 +622,7 @@ describe('interactionHardReset', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, @@ -713,6 +719,7 @@ describe('interactionUpdate with user changed strategy', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, @@ -804,6 +811,7 @@ describe('interactionUpdate with user changed strategy', () => { "grid": Object { "currentRootCell": null, "draggingFromCell": null, + "metadataCacheForGrids": Object {}, "originalRootCell": null, "targetCellData": null, }, diff --git a/editor/src/components/editor/store/store-deep-equality-instances-3.spec.ts b/editor/src/components/editor/store/store-deep-equality-instances-3.spec.ts index cd020e303e72..7d92822b622e 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances-3.spec.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances-3.spec.ts @@ -322,6 +322,7 @@ describe('SpecialSizeMeasurementsKeepDeepEquality', () => { }, rowGap: null, columnGap: null, + gridCellGlobalFrames: null, justifySelf: null, alignSelf: null, } @@ -443,6 +444,7 @@ describe('SpecialSizeMeasurementsKeepDeepEquality', () => { }, rowGap: null, columnGap: null, + gridCellGlobalFrames: null, justifySelf: null, alignSelf: null, } @@ -619,6 +621,7 @@ describe('ElementInstanceMetadataKeepDeepEquality', () => { }, rowGap: null, columnGap: null, + gridCellGlobalFrames: null, justifySelf: null, alignSelf: null, }, @@ -772,6 +775,7 @@ describe('ElementInstanceMetadataKeepDeepEquality', () => { }, rowGap: null, columnGap: null, + gridCellGlobalFrames: null, justifySelf: null, alignSelf: null, }, @@ -950,6 +954,7 @@ describe('ElementInstanceMetadataMapKeepDeepEquality', () => { }, rowGap: null, columnGap: null, + gridCellGlobalFrames: null, justifySelf: null, alignSelf: null, }, @@ -1105,6 +1110,7 @@ describe('ElementInstanceMetadataMapKeepDeepEquality', () => { }, rowGap: null, columnGap: null, + gridCellGlobalFrames: null, justifySelf: null, alignSelf: null, }, @@ -1260,6 +1266,7 @@ describe('ElementInstanceMetadataMapKeepDeepEquality', () => { }, rowGap: null, columnGap: null, + gridCellGlobalFrames: null, justifySelf: null, alignSelf: null, }, diff --git a/editor/src/components/editor/store/store-deep-equality-instances.ts b/editor/src/components/editor/store/store-deep-equality-instances.ts index 06e57d5b3d14..9bf286061a5c 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.ts @@ -2366,6 +2366,7 @@ export function SpecialSizeMeasurementsKeepDeepEquality(): KeepDeepEqualityCall< newSize.elementGridPropertiesFromProps, newSize.rowGap, newSize.columnGap, + newSize.gridCellGlobalFrames, newSize.justifySelf, newSize.alignSelf, ) diff --git a/editor/src/components/navigator/left-pane/settings-pane.spec.browser2.tsx b/editor/src/components/navigator/left-pane/settings-pane.spec.browser2.tsx index a9c311417bfb..b76adcba9ef4 100644 --- a/editor/src/components/navigator/left-pane/settings-pane.spec.browser2.tsx +++ b/editor/src/components/navigator/left-pane/settings-pane.spec.browser2.tsx @@ -7,7 +7,7 @@ import { StoryboardFilePath } from '../../editor/store/editor-state' async function renderRemixProject(project: PersistentModel) { const renderResult = await renderTestEditorWithModel(project, 'await-first-dom-report') - await renderResult.dispatch([runDOMWalker()], true) + await renderResult.dispatch([runDOMWalker(null)], true) return renderResult } diff --git a/editor/src/core/shared/element-template.ts b/editor/src/core/shared/element-template.ts index f0c68e7b10f1..8a7b76c2d1e9 100644 --- a/editor/src/core/shared/element-template.ts +++ b/editor/src/core/shared/element-template.ts @@ -2837,6 +2837,7 @@ export interface SpecialSizeMeasurements { elementGridPropertiesFromProps: GridElementProperties rowGap: number | null columnGap: number | null + gridCellGlobalFrames: Array> | null } export function specialSizeMeasurements( @@ -2888,6 +2889,7 @@ export function specialSizeMeasurements( elementGridPropertiesFromProps: GridElementProperties, rowGap: number | null, columnGap: number | null, + gridCellGlobalFrames: Array> | null, justifySelf: SelfAlignment | null, alignSelf: SelfAlignment | null, ): SpecialSizeMeasurements { @@ -2940,6 +2942,7 @@ export function specialSizeMeasurements( elementGridPropertiesFromProps, rowGap, columnGap, + gridCellGlobalFrames, justifySelf, alignSelf, } @@ -3021,6 +3024,7 @@ export const emptySpecialSizeMeasurements = specialSizeMeasurements( null, null, null, + null, ) export function walkElement( diff --git a/editor/src/templates/editor.tsx b/editor/src/templates/editor.tsx index 6185db8ee773..07ede0693cff 100644 --- a/editor/src/templates/editor.tsx +++ b/editor/src/templates/editor.tsx @@ -21,6 +21,7 @@ import type { DispatchPriority, EditorAction, EditorDispatch, + RunDOMWalker, } from '../components/editor/action-types' import { actionActionsOptic, isLoggedIn } from '../components/editor/action-types' import * as EditorActions from '../components/editor/actions/action-creators' @@ -100,7 +101,7 @@ import * as EP from '../core/shared/element-path' import { waitUntil } from '../core/shared/promise-utils' import { sendSetVSCodeTheme } from '../core/vscode/vscode-bridge' import type { ElementPath } from '../core/shared/project-file-types' -import { mapDropNulls, uniqBy } from '../core/shared/array-utils' +import { uniq, uniqBy } from '../core/shared/array-utils' import { updateUserDetailsWhenAuthenticated } from '../core/shared/github/helpers' import { DispatchContext } from '../components/editor/store/dispatch-context' import { @@ -123,12 +124,8 @@ import { InitialOnlineState, startOnlineStatusPolling } from '../components/edit import { useAnimate } from 'framer-motion' import { AnimationContext } from '../components/canvas/ui-jsx-canvas-renderer/animation-context' import { anyCodeAhead } from '../components/assets' -import { anyBy, toArrayOf } from '../core/shared/optics/optic-utilities' -import { - fromField, - traverseArray, - traverseReadOnlyArray, -} from '../core/shared/optics/optic-creators' +import { toArrayOf } from '../core/shared/optics/optic-utilities' +import { fromTypeGuard, traverseReadOnlyArray } from '../core/shared/optics/optic-creators' import { keysEqualityExhaustive, shallowEqual } from '../core/shared/equality-utils' import { resetDomSamplerExecutionCounts, @@ -478,17 +475,18 @@ export class Editor { }) } - const runDomWalker = - shouldRunDOMWalker(dispatchedActions, oldEditorState, this.storedState) && - !this.temporarilyDisableStoreUpdates + const runDomWalker = this.temporarilyDisableStoreUpdates + ? 'dont-run' + : shouldRunDOMWalker(dispatchedActions, oldEditorState, this.storedState) // run the dom-walker - if (runDomWalker) { + if (runDomWalker !== 'dont-run') { const metadataUpdateDispatchResult = runDomSamplerAndSaveResults( this.boundDispatch, this.storedState, this.domWalkerMutableState, this.spyCollector, + runDomWalker, ) this.storedState = metadataUpdateDispatchResult @@ -853,7 +851,12 @@ export function shouldRunDOMWalker( dispatchedActions: ReadonlyArray, storeBefore: EditorStoreFull, storeAfter: EditorStoreFull, -): boolean { +): + | 'dont-run' + | 'run-full' + | { + restrictToElements: Array + } { const patchedEditorBefore = storeBefore.patchedEditor const patchedEditorAfter = storeAfter.patchedEditor const patchedEditorChanged = @@ -895,10 +898,46 @@ export function shouldRunDOMWalker( patchedDerivedBefore.remixData !== patchedDerivedAfter.remixData const storeChanged = patchedEditorChanged || patchedDerivedChanged - const actionsIndicateDOMWalkerShouldRun = anyBy( - traverseReadOnlyArray().compose(actionActionsOptic), - (action) => action.action === 'RUN_DOM_WALKER', + + // if the store changed run the dom walker + if (storeChanged) { + return 'run-full' + } + + // if there are runDomWalker actions, run the dom walker, and merge their restrictToElements + const runDomWalkerActions = toArrayOf( + traverseReadOnlyArray() + .compose(actionActionsOptic) + .compose( + fromTypeGuard((action): action is RunDOMWalker => action.action === 'RUN_DOM_WALKER'), + ), dispatchedActions, ) - return storeChanged || actionsIndicateDOMWalkerShouldRun + + if (runDomWalkerActions.length === 0) { + return 'dont-run' + } + + const restrictToElements = runDomWalkerActions.reduce | null>( + (acc, action) => { + if (action.restrictToElements != null) { + if (acc == null) { + return action.restrictToElements + } + return [...acc, ...action.restrictToElements] + } + return acc + }, + null, + ) + + if (restrictToElements == null) { + return 'run-full' + } + + const uniqRestrictToElements = uniq(restrictToElements.map(EP.toString)).map(EP.fromString) + + return { + restrictToElements: uniqRestrictToElements, + } }