Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
type Instance,
type Props,
descendantComponent,
rootComponent,
} from "@webstudio-is/sdk";
import {
theme,
Expand Down Expand Up @@ -344,7 +345,7 @@ export const PropsSectionContainer = ({
});

const propsMetas = useStore($selectedInstancePropsMetas);
if (propsMetas.size === 0) {
if (propsMetas.size === 0 || instance.component === rootComponent) {
return;
}

Expand Down
47 changes: 21 additions & 26 deletions apps/builder/app/canvas/collapsed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { $selectedBreakpoint } from "~/shared/nano-states";
import { $selectedPage } from "~/shared/awareness";
import { serverSyncStore } from "~/shared/sync";
import { doNotTrackMutation } from "~/shared/dom-utils";

const isHtmlTag = (tag: string): tag is HtmlTags =>
htmlTags.includes(tag as HtmlTags);
Expand All @@ -34,22 +35,6 @@ const isSelectorSupported = (selector: string) => {
}
};

// This mark helps us detect if mutations were caused by the collapse algorithm
const markCollapsedMutationProperty = `--ws-sys-collapsed-mutation`;

/**
* Avoid infinite loop of mutations
*/
export const hasCollapsedMutationRecord = (
mutationRecords: MutationRecord[]
) => {
return mutationRecords.some((record) =>
record.type === "attributes"
? (record.oldValue?.includes(markCollapsedMutationProperty) ?? false)
: false
);
};

const getInstanceSize = (instanceId: string, tagName: HtmlTags | undefined) => {
const metas = $registeredComponentMetas.get();
const breakpoints = $breakpoints.get();
Expand Down Expand Up @@ -246,14 +231,25 @@ const recalculate = () => {
// If most elements are collapsed at the next step, scrollHeight becomes equal to clientHeight,
// which resets the scroll position. To prevent this, we set the document's height to the current scrollHeight
// to preserve the scroll position.
const preserveHeight = document.documentElement.style.height;

// Mark that we are in the process of recalculating collapsed elements
document.documentElement.style.setProperty(
markCollapsedMutationProperty,
`true`
);
document.documentElement.style.height = `${document.documentElement.scrollHeight}px`;
// use nested element to avoid full page repaint and freeze on big projects
let collapsedElement = document.querySelector(
"#ws-collapsed"
) as null | HTMLElement;
if (!collapsedElement) {
collapsedElement = document.createElement("div") as HTMLElement;
collapsedElement.style.position = "absolute";
collapsedElement.style.top = "0px";
collapsedElement.style.left = "0px";
collapsedElement.style.right = "0px";
collapsedElement.setAttribute("id", "ws-collapsed");
collapsedElement.setAttribute("hidden", "true");
// Mark that we are in the process of recalculating collapsed elements
// to avoid infinite loop of mutations
doNotTrackMutation(collapsedElement);
document.documentElement.appendChild(collapsedElement);
}
collapsedElement.removeAttribute("hidden");
collapsedElement.style.height = `${document.documentElement.scrollHeight}px`;

// Now combine all operations in batches.

Expand Down Expand Up @@ -299,8 +295,7 @@ const recalculate = () => {
element.setAttribute(collapsedAttribute, value);
}

document.documentElement.style.height = preserveHeight;
document.documentElement.style.removeProperty(markCollapsedMutationProperty);
collapsedElement.setAttribute("hidden", "true");
};

/**
Expand Down
11 changes: 2 additions & 9 deletions apps/builder/app/canvas/instance-selected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ import {
} from "~/shared/dom-utils";
import { subscribeScrollState } from "~/canvas/shared/scroll-state";
import { $selectedInstanceOutline } from "~/shared/nano-states";
import {
hasCollapsedMutationRecord,
setDataCollapsed,
} from "~/canvas/collapsed";
import { setDataCollapsed } from "~/canvas/collapsed";
import type { InstanceSelector } from "~/shared/tree-utils";
import { $awareness } from "~/shared/awareness";

Expand Down Expand Up @@ -236,7 +233,7 @@ const subscribeSelectedInstance = (

// Lightweight update
const updateOutline: MutationCallback = (mutationRecords) => {
if (hasCollapsedMutationRecord(mutationRecords)) {
if (hasDoNotTrackMutationRecord(mutationRecords)) {
return;
}

Expand All @@ -250,10 +247,6 @@ const subscribeSelectedInstance = (
return;
}

if (hasCollapsedMutationRecord(mutationRecords)) {
return;
}

update();
};

Expand Down
14 changes: 12 additions & 2 deletions apps/builder/app/shared/dom-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ export const getAllElementsBoundingBox = (

const doNotTrackMutationAttribute = "data-ws-do-not-track-mutation";

export const doNotTrackMutation = (element: Element) => {
element.setAttribute(doNotTrackMutationAttribute, "true");
};

export const hasDoNotTrackMutationAttribute = (element: Element) => {
return element.hasAttribute(doNotTrackMutationAttribute);
};
Expand Down Expand Up @@ -363,7 +367,10 @@ export const scrollIntoView = (anchor: HTMLElement, rect: DOMRect) => {

requestAnimationFrame(() => {
const savedPosition = (scrollParent as HTMLElement).style.position;
(scrollParent as HTMLElement).style.position = "relative";
// avoid updating <html> to prevent full page repaint and freeze on big projects
if (scrollParent.tagName !== "HTML") {
(scrollParent as HTMLElement).style.position = "relative";
}

const matrix = getViewportToLocalMatrix(scrollParent);

Expand All @@ -387,6 +394,9 @@ export const scrollIntoView = (anchor: HTMLElement, rect: DOMRect) => {

scrollParent.removeChild(scrollDiv);

(scrollParent as HTMLElement).style.position = savedPosition;
// avoid updating <html> to prevent full page repaint and freeze on big projects
if (scrollParent.tagName !== "HTML") {
(scrollParent as HTMLElement).style.position = savedPosition;
}
});
};