Skip to content
PanZoomWrapper.tsx 1.62 KiB
Newer Older
import React, { useRef, useState, useEffect } from "react";
import { RendererContext } from "./RendererContext";
import { PanZoom } from "./PanZoom";

export const PanZoomWrapper = ({
  children,
  initialPosition,
}: {
  children: React.ReactNode;
  initialPosition?: (useCssZoom: boolean) =>
    | {
        x: number;
        y: number;
        zoom?: number;
      }
    | undefined;
}) => {
  const wrapper = useRef<HTMLDivElement>(null);
  const zoom = useRef<HTMLDivElement>(null);
  const move = useRef<HTMLDivElement>(null);

  const instance = useRef(new PanZoom()).current;

  useEffect(() => {
    const $wrapper = wrapper.current;
    const $zoom = zoom.current;
    const $move = move.current;

    if ($wrapper && $zoom && $move) {
      if (initialPosition) {
        const pos = initialPosition(instance.flags.useZoom);
        if (pos) {
          instance.setPosition(
            {
              x: pos.x,
              y: pos.y,
              zoom: pos.zoom || 0,
            },
            { suppressEmit: true }
          );
        } else {
          console.warn("Failed to set position via initialPosition; no pos");
        }
      }

      instance.initialize($wrapper, $zoom, $move);
    }

    return () => {
      instance.cleanup();
    };
  }, []);

  return (
    <RendererContext.Provider value={instance}>
      <div
        ref={wrapper}
        className="board-wrapper"
        style={{ touchAction: "none" }}
      >
        <div ref={zoom} className="board-zoom">
          <div ref={move} className="board-move">
            {children}
          </div>
        </div>
      </div>
    </RendererContext.Provider>
  );
};