Skip to content

Commit da92917

Browse files
authored
fix: delayed anchor render on html layer (#54)
1 parent 0553bfa commit da92917

File tree

2 files changed

+27
-28
lines changed

2 files changed

+27
-28
lines changed

src/react-component/Anchor.tsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { CSSProperties, useMemo } from "react";
1+
import React, { useMemo } from "react";
22

33
import { TAnchor } from "../components/canvas/anchors";
44
import { Graph } from "../graph";
@@ -22,9 +22,10 @@ export function GraphBlockAnchor({
2222
className?: string;
2323
children?: React.ReactNode | ((anchorState: AnchorState) => React.ReactNode);
2424
}) {
25+
const anchorContainerRef = React.useRef<HTMLDivElement>(null);
2526
const anchorState = useBlockAnchorState(graph, anchor);
2627

27-
const coords = useBlockAnchorPosition(anchorState);
28+
useBlockAnchorPosition(anchorState, anchorContainerRef);
2829

2930
const selected = useSignal(anchorState?.$selected);
3031

@@ -38,15 +39,7 @@ export function GraphBlockAnchor({
3839
if (!anchorState) return null;
3940

4041
return (
41-
<div
42-
style={
43-
{
44-
"--graph-block-anchor-x": `${coords.x}px`,
45-
"--graph-block-anchor-y": `${coords.y}px`,
46-
} as CSSProperties
47-
}
48-
className={classNames}
49-
>
42+
<div ref={anchorContainerRef} className={classNames}>
5043
{render(anchorState)}
5144
</div>
5245
);
Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { useLayoutEffect, useMemo, useState } from "react";
1+
import { useCallback, useLayoutEffect, useMemo } from "react";
22

33
import { computed } from "@preact/signals-core";
4-
import debounce from "lodash/debounce";
54

65
import { TAnchor } from "../../components/canvas/anchors";
76
import { Graph } from "../../graph";
87
import { AnchorState } from "../../store/anchor/Anchor";
8+
import { noop } from "../../utils/functions";
99

1010
import { useBlockState } from "./useBlockState";
1111
import { useSignal } from "./useSignal";
@@ -14,31 +14,37 @@ export function useBlockAnchorState(graph: Graph, anchor: TAnchor): AnchorState
1414
const blockState = useBlockState(graph, anchor.blockId);
1515
const signal = useMemo(() => {
1616
return computed(() => {
17-
if (!blockState) return;
18-
if (!Array.isArray(blockState.$anchorStates?.value)) return;
17+
if (!blockState) return undefined;
18+
if (!Array.isArray(blockState.$anchorStates?.value)) return undefined;
1919

2020
return blockState.$anchorStates.value.find((a) => a.id === anchor.id);
2121
});
2222
}, [blockState, anchor]);
2323
return useSignal(signal);
2424
}
2525

26-
export function useBlockAnchorPosition(state: AnchorState | undefined) {
27-
const [pos, setPos] = useState<{ x: number; y: number }>(
28-
state.block ? state.block.getViewComponent().getAnchorPosition(state.state) : { x: 0, y: 0 }
29-
);
26+
export function useBlockAnchorPosition(
27+
state: AnchorState | undefined,
28+
anchorContainerRef: React.MutableRefObject<HTMLDivElement> | undefined
29+
) {
30+
const refreshAnchorPosition = useCallback(() => {
31+
const position = state.block.getViewComponent().getAnchorPosition(state.state) || { x: 0, y: 0 };
32+
anchorContainerRef.current.style.setProperty("--graph-block-anchor-x", `${position.x}px`);
33+
anchorContainerRef.current.style.setProperty("--graph-block-anchor-y", `${position.y}px`);
34+
}, []);
3035

3136
useLayoutEffect(() => {
3237
if (!state) {
33-
return;
38+
return noop;
3439
}
35-
return state.block.$geometry.subscribe(
36-
debounce(() => {
37-
const position = state.block.getViewComponent().getAnchorPosition(state.state);
38-
setPos(position);
39-
}, 16)
40-
);
41-
}, [state.block]);
40+
if (!anchorContainerRef || !anchorContainerRef.current) {
41+
return noop;
42+
}
43+
44+
refreshAnchorPosition();
4245

43-
return pos;
46+
return state.block.$geometry.subscribe(() => {
47+
refreshAnchorPosition();
48+
});
49+
}, [state.block]);
4450
}

0 commit comments

Comments
 (0)