diff options
Diffstat (limited to 'apps/web/src/preview/components')
| -rw-r--r-- | apps/web/src/preview/components/context-menu.tsx | 6 | ||||
| -rw-r--r-- | apps/web/src/preview/components/index.tsx | 26 | ||||
| -rw-r--r-- | apps/web/src/preview/components/preview-viewport.tsx | 16 | ||||
| -rw-r--r-- | apps/web/src/preview/components/text-edit-overlay.tsx | 1 |
4 files changed, 25 insertions, 24 deletions
diff --git a/apps/web/src/preview/components/context-menu.tsx b/apps/web/src/preview/components/context-menu.tsx index fca55d71..a0f1bc5c 100644 --- a/apps/web/src/preview/components/context-menu.tsx +++ b/apps/web/src/preview/components/context-menu.tsx @@ -13,12 +13,12 @@ import { toast } from "sonner"; export function PreviewContextMenu({ onToggleFullscreen, - containerRef, + container, overlayControls, onOverlayVisibilityChange, }: { onToggleFullscreen: () => void; - containerRef: React.RefObject<HTMLElement | null>; + container: HTMLElement | null; overlayControls: PreviewOverlayControl[]; onOverlayVisibilityChange: (params: { overlayId: string; @@ -51,7 +51,7 @@ export function PreviewContextMenu({ }; return ( - <ContextMenuContent className="w-56" container={containerRef.current}> + <ContextMenuContent className="w-56" container={container}> <ContextMenuItem onClick={viewport.fitToScreen} inset> Fit to screen </ContextMenuItem> diff --git a/apps/web/src/preview/components/index.tsx b/apps/web/src/preview/components/index.tsx index e8f5c572..894eec78 100644 --- a/apps/web/src/preview/components/index.tsx +++ b/apps/web/src/preview/components/index.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCallback, useEffect, useMemo, useRef } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import useDeepCompareEffect from "use-deep-compare-effect"; import { useEditor } from "@/editor/use-editor"; import { useRafLoop } from "@/hooks/use-raf-loop"; @@ -68,15 +68,20 @@ export function PreviewPanel({ }) => void; }) { const containerRef = useRef<HTMLDivElement>(null); + const [container, setContainer] = useState<HTMLDivElement | null>(null); const { toggleFullscreen } = useFullscreen({ containerRef }); + const handleContainerRef = useCallback((node: HTMLDivElement | null) => { + containerRef.current = node; + setContainer(node); + }, []); return ( <div - ref={containerRef} + ref={handleContainerRef} className="panel bg-background relative flex size-full min-h-0 min-w-0 flex-col rounded-sm border" > <PreviewCanvas - containerRef={containerRef} + container={container} onToggleFullscreen={toggleFullscreen} overlayControls={overlayControls} overlayInstances={overlayInstances} @@ -117,13 +122,13 @@ function RenderTreeController() { } function PreviewCanvas({ - containerRef, + container, onToggleFullscreen, overlayControls, overlayInstances, onOverlayVisibilityChange, }: { - containerRef: React.RefObject<HTMLElement | null>; + container: HTMLElement | null; onToggleFullscreen: () => void; overlayControls: PreviewOverlayControl[]; overlayInstances: PreviewOverlayInstance[]; @@ -149,6 +154,7 @@ function PreviewCanvas({ viewportRef, viewportWidth: viewportSize.width, }); + const { canPan, panByScreenDelta, scaleZoom } = viewport; const renderer = useMemo(() => { return new CanvasRenderer({ @@ -240,7 +246,7 @@ function PreviewCanvas({ Math.min(Math.abs(pendingZoomDelta), 30); const zoomFactor = Math.exp(-cappedDelta / 300); - viewport.scaleZoom({ factor: zoomFactor }); + scaleZoom({ factor: zoomFactor }); pendingZoomDelta = 0; zoomRafId = null; }); @@ -249,7 +255,7 @@ function PreviewCanvas({ return; } - if (!viewport.canPan) { + if (!canPan) { return; } @@ -263,7 +269,7 @@ function PreviewCanvas({ if (panRafId === null) { panRafId = requestAnimationFrame(() => { - viewport.panByScreenDelta({ + panByScreenDelta({ deltaX: pendingPanDeltaX, deltaY: pendingPanDeltaY, }); @@ -290,7 +296,7 @@ function PreviewCanvas({ cancelAnimationFrame(panRafId); } }; - }, [viewport.canPan, viewport.panByScreenDelta, viewport.scaleZoom]); + }, [canPan, panByScreenDelta, scaleZoom]); return ( <PreviewViewportProvider value={viewport}> @@ -329,7 +335,7 @@ function PreviewCanvas({ </ContextMenuTrigger> <PreviewContextMenu onToggleFullscreen={onToggleFullscreen} - containerRef={containerRef} + container={container} overlayControls={overlayControls} onOverlayVisibilityChange={onOverlayVisibilityChange} /> diff --git a/apps/web/src/preview/components/preview-viewport.tsx b/apps/web/src/preview/components/preview-viewport.tsx index 6dc9f084..be261adc 100644 --- a/apps/web/src/preview/components/preview-viewport.tsx +++ b/apps/web/src/preview/components/preview-viewport.tsx @@ -9,6 +9,7 @@ import { useRef,
useState,
} from "react";
+import { useCommittedRef } from "@/hooks/use-committed-ref";
import {
canvasToOverlay,
getDisplayScale,
@@ -219,8 +220,7 @@ export function usePreviewViewportState({ }));
const [isPanning, setIsPanning] = useState(false);
const panSessionRef = useRef<PanSession | null>(null);
- const centerRef = useRef(center);
- centerRef.current = center;
+ const centerRef = useCommittedRef(center);
const fitScale = useMemo(
() =>
@@ -409,10 +409,10 @@ export function usePreviewViewportState({ pointerId: event.pointerId,
};
setIsPanning(true);
- (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
+ event.currentTarget.setPointerCapture(event.pointerId);
return true;
},
- [zoom],
+ [centerRef, zoom],
);
const handlePanPointerMove = useCallback(
@@ -451,13 +451,9 @@ export function usePreviewViewportState({ }
if (
- (event.currentTarget as HTMLElement).hasPointerCapture(
- panSession.pointerId,
- )
+ event.currentTarget.hasPointerCapture(panSession.pointerId)
) {
- (event.currentTarget as HTMLElement).releasePointerCapture(
- panSession.pointerId,
- );
+ event.currentTarget.releasePointerCapture(panSession.pointerId);
}
panSessionRef.current = null;
diff --git a/apps/web/src/preview/components/text-edit-overlay.tsx b/apps/web/src/preview/components/text-edit-overlay.tsx index 1d599b3b..dd6364d6 100644 --- a/apps/web/src/preview/components/text-edit-overlay.tsx +++ b/apps/web/src/preview/components/text-edit-overlay.tsx @@ -120,7 +120,6 @@ export function TextEditOverlay({ transformOrigin: "center center", }} > - {/* biome-ignore lint/a11y/useSemanticElements: contenteditable required for multiline, IME, paste */} <div ref={divRef} contentEditable |
