mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 21:15:18 +09:00
fixes the case that setSelectedInstance can be called before the instance actually renders
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
import { useCallback, useEffect } from "react";
|
|
import { type Instance } from "@webstudio-is/sdk";
|
|
import { findInstanceById } from "~/shared/tree-utils";
|
|
import {
|
|
useSelectedInstance,
|
|
useSelectedElement,
|
|
useRootInstance,
|
|
} from "./nano-values";
|
|
import { publish, useSubscribe } from "./pubsub";
|
|
|
|
const eventOptions = {
|
|
passive: true,
|
|
};
|
|
|
|
export const useActiveElementTracking = () => {
|
|
const [rootInstance] = useRootInstance();
|
|
const [selectedInstance, setSelectedInstance] = useSelectedInstance();
|
|
const [selectedElement, setSelectedElement] = useSelectedElement();
|
|
|
|
useSubscribe("focusElement", (id: Instance["id"]) => {
|
|
const element = document.getElementById(id);
|
|
element?.focus();
|
|
select(element);
|
|
});
|
|
|
|
const select = useCallback(
|
|
(element: Element | null) => {
|
|
if (element === null || rootInstance === undefined) return;
|
|
const id = element?.id;
|
|
if (!id) return;
|
|
if (selectedElement?.id === id) return;
|
|
const instance = findInstanceById(rootInstance, element.id);
|
|
if (instance === undefined) return;
|
|
setSelectedInstance(instance);
|
|
setSelectedElement(element);
|
|
},
|
|
[rootInstance, selectedElement, setSelectedElement, setSelectedInstance]
|
|
);
|
|
|
|
useEffect(() => {
|
|
const handleFocus = () => {
|
|
select(document.activeElement);
|
|
};
|
|
|
|
window.addEventListener("focus", handleFocus, eventOptions);
|
|
|
|
const handleClick = (event: MouseEvent) => {
|
|
// Notify in general that document was clicked
|
|
// e.g. to hide the side panel
|
|
publish<"clickCanvas">({ type: "clickCanvas" });
|
|
if (event.target instanceof Element) select(event.target);
|
|
};
|
|
window.addEventListener("click", handleClick, eventOptions);
|
|
|
|
return () => {
|
|
window.removeEventListener("focus", handleFocus);
|
|
window.removeEventListener("click", handleClick);
|
|
};
|
|
}, [select]);
|
|
|
|
return selectedInstance;
|
|
};
|