All files / webview-app/src/components/CanvasComponent componentView.tsx

0% Statements 0/18
0% Branches 0/20
0% Functions 0/9
0% Lines 0/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111                                                                                                                                                                                                                             
import type { PointerEvent, ReactNode, RefObject } from "react";
 
import { ResizeHandles } from "@/components/CanvasComponent/resizeHandles";
import type { ResizeHandle } from "@/lib/geometry";
import type { CanvasComponent as CanvasComponentModel } from "@/types/canvas";
 
interface CanvasComponentViewProps {
  rootRef: RefObject<HTMLDivElement | null>;
  component: CanvasComponentModel;
  isSelected: boolean;
  isDragging: boolean;
  isResizing: boolean;
  preview: ReactNode;
  onMovePointerDown: (event: PointerEvent<HTMLDivElement>) => boolean;
  onPointerMove: (event: PointerEvent<HTMLDivElement>) => void;
  onPointerFinish: (event: PointerEvent<HTMLDivElement>) => boolean;
  onResizeHandlePointerDown: (
    event: PointerEvent<HTMLButtonElement>,
    handle: ResizeHandle,
  ) => boolean;
  onSelect: (id: string) => void;
  children?: ReactNode;
}
 
export function CanvasComponentView({
  rootRef,
  component,
  isSelected,
  isDragging,
  isResizing,
  preview,
  onMovePointerDown,
  onPointerMove,
  onPointerFinish,
  onResizeHandlePointerDown,
  onSelect,
  children,
}: CanvasComponentViewProps) {
  const capturePointer = (pointerId: number) => {
    rootRef.current?.setPointerCapture(pointerId);
  };
 
  const releasePointer = (pointerId: number) => {
    if (rootRef.current?.hasPointerCapture(pointerId)) {
      rootRef.current.releasePointerCapture(pointerId);
    }
  };
 
  const handleActivate = () => {
    onSelect(component.id);
  };
 
  return (
    <div
      ref={rootRef}
      role="button"
      tabIndex={0}
      data-canvas-component="true"
      data-dragging={isDragging ? "true" : "false"}
      data-resizing={isResizing ? "true" : "false"}
      aria-label={`${component.type} component`}
      onPointerDown={(event) => {
        if (onMovePointerDown(event)) {
          capturePointer(event.pointerId);
        }
      }}
      onPointerMove={onPointerMove}
      onPointerUp={(event) => {
        if (onPointerFinish(event)) {
          releasePointer(event.pointerId);
        }
      }}
      onPointerCancel={(event) => {
        if (onPointerFinish(event)) {
          releasePointer(event.pointerId);
        }
      }}
      onClick={handleActivate}
      onKeyUp={(event) => {
        if (event.key === "Enter" || event.key === " ") {
          handleActivate();
        }
      }}
      className={`absolute touch-none select-none border-none bg-transparent p-0 text-left outline-none ${
        isSelected ? "ring-1 ring-(--canvas-selection)" : ""
      }`}
      style={{
        left: component.x,
        top: component.y,
        width: component.width,
        height: component.height,
      }}
    >
      <div className="relative h-full w-full overflow-hidden">
        {preview}
        {children}
      </div>
 
      <ResizeHandles
        isSelected={isSelected}
        componentType={component.type}
        onHandlePointerDown={(event, handle) => {
          if (onResizeHandlePointerDown(event, handle)) {
            capturePointer(event.pointerId);
          }
        }}
      />
    </div>
  );
}