136 lines · 4.8 KB
import { ClientOnly } from "@tanstack/react-router";
import { parsePatchFiles } from "@pierre/diffs";
import type { DiffLineAnnotation, FileDiffMetadata, SelectedLineRange } from "@pierre/diffs";
import { FileDiff } from "@pierre/diffs/react";
import { useState } from "react";
import { Button } from "./ui/Button";
import { EmptyState } from "./ui/Primitives";
import type { DiffResult } from "~/lib/types";

export type DiffSide = "LEFT" | "RIGHT";

export type LineAnchor<T> = { path: string; line: number; side: DiffSide; data: T };

/** First line of a multi-line selection; the anchor line is its last line. */
export type RangeStart = { line: number; side: DiffSide };

type LineAction = (path: string, line: number, side: DiffSide, start?: RangeStart) => void;

function selectionAction(path: string, range: SelectedLineRange, onLineAction: LineAction) {
  const startSide: DiffSide = range.side === "deletions" ? "LEFT" : "RIGHT";
  const endSide: DiffSide = (range.endSide ?? range.side) === "deletions" ? "LEFT" : "RIGHT";
  const forward = range.end >= range.start || startSide !== endSide;
  const [first, last] = forward
    ? [
        { line: range.start, side: startSide },
        { line: range.end, side: endSide },
      ]
    : [
        { line: range.end, side: endSide },
        { line: range.start, side: startSide },
      ];
  const multiLine = first.line !== last.line || first.side !== last.side;
  onLineAction(path, last.line, last.side, multiLine ? first : undefined);
}

type Props<T> = {
  diff: DiffResult;
  anchors?: LineAnchor<T>[];
  renderAnchor?: (anchor: LineAnchor<T>) => React.ReactNode;
  onLineAction?: LineAction;