mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 18:22:38 +00:00
* perf(app): keep large diffs responsive Render file headers on the canvas and bound expensive text shaping to the active viewport while preserving sticky, hover, and horizontal-scroll behavior. Let native scroll cancellation arbitrate header presses so finger scrolling cannot expand files. * test(app): assert canvas diff header accessibility * test(app): assert canvas diff header semantics
68 lines
2.7 KiB
TypeScript
68 lines
2.7 KiB
TypeScript
import type { Theme } from "@/styles/theme";
|
|
import { hexColorWithAlpha } from "@/utils/color";
|
|
import type { DiffCell, DiffPalette } from "./types";
|
|
|
|
export function createDiffPalette(theme: Theme): DiffPalette {
|
|
return {
|
|
surface: theme.colors.surface0,
|
|
headerSurface: theme.colors.surface0,
|
|
border: theme.colors.border,
|
|
foreground: theme.colors.foreground,
|
|
foregroundMuted: theme.colors.foregroundMuted,
|
|
addition: theme.colors.statusSuccess,
|
|
deletion: theme.colors.statusDanger,
|
|
additionBackground: hexColorWithAlpha(theme.colors.statusSuccess, 0.15),
|
|
deletionBackground: hexColorWithAlpha(theme.colors.statusDanger, 0.1),
|
|
emptyBackground: theme.colors.surface0,
|
|
selection: theme.colors.terminal.blue,
|
|
headerActiveSurface: theme.colors.surface1,
|
|
headerBorder: theme.colors.borderAccent,
|
|
statusSuccess: theme.colors.statusSuccess,
|
|
statusDanger: theme.colors.statusDanger,
|
|
statusWarning: theme.colors.statusWarning,
|
|
syntax: theme.colors.syntax,
|
|
};
|
|
}
|
|
|
|
export function retainDiffPalette(previous: DiffPalette, next: DiffPalette): DiffPalette {
|
|
if (
|
|
previous.surface !== next.surface ||
|
|
previous.headerSurface !== next.headerSurface ||
|
|
previous.border !== next.border ||
|
|
previous.foreground !== next.foreground ||
|
|
previous.foregroundMuted !== next.foregroundMuted ||
|
|
previous.addition !== next.addition ||
|
|
previous.deletion !== next.deletion ||
|
|
previous.additionBackground !== next.additionBackground ||
|
|
previous.deletionBackground !== next.deletionBackground ||
|
|
previous.emptyBackground !== next.emptyBackground ||
|
|
previous.selection !== next.selection ||
|
|
previous.headerActiveSurface !== next.headerActiveSurface ||
|
|
previous.headerBorder !== next.headerBorder ||
|
|
previous.statusSuccess !== next.statusSuccess ||
|
|
previous.statusDanger !== next.statusDanger ||
|
|
previous.statusWarning !== next.statusWarning ||
|
|
!sameColorMap(previous.syntax, next.syntax)
|
|
) {
|
|
return next;
|
|
}
|
|
return previous;
|
|
}
|
|
|
|
function sameColorMap(left: Record<string, string>, right: Record<string, string>): boolean {
|
|
const leftKeys = Object.keys(left);
|
|
const rightKeys = Object.keys(right);
|
|
return leftKeys.length === rightKeys.length && leftKeys.every((key) => left[key] === right[key]);
|
|
}
|
|
|
|
export function codeTextColor(cell: DiffCell, palette: DiffPalette): string {
|
|
return cell.type === "header" ? palette.foregroundMuted : palette.foreground;
|
|
}
|
|
|
|
export function codeLineNumberTone(cell: DiffCell): "addition" | "deletion" | "foregroundMuted" {
|
|
"worklet";
|
|
if (cell.type === "add") return "addition";
|
|
if (cell.type === "remove") return "deletion";
|
|
return "foregroundMuted";
|
|
}
|