Polish diff view hunk controls
This commit is contained in:
@@ -99,7 +99,7 @@
|
||||
},
|
||||
"packages/electron": {
|
||||
"name": "@openchamber/electron",
|
||||
"version": "1.12.3",
|
||||
"version": "1.12.4",
|
||||
"dependencies": {
|
||||
"@openchamber/web": "workspace:*",
|
||||
"electron-context-menu": "^4.1.2",
|
||||
@@ -114,7 +114,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@openchamber/ui",
|
||||
"version": "1.12.3",
|
||||
"version": "1.12.4",
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.4.0",
|
||||
"@codemirror/autocomplete": "^6.20.0",
|
||||
@@ -146,7 +146,7 @@
|
||||
"@ibm/plex": "^6.4.1",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
"@opencode-ai/sdk": "^1.17.0",
|
||||
"@pierre/diffs": "1.1.0-beta.13",
|
||||
"@pierre/diffs": "1.3.0-beta.4",
|
||||
"@replit/codemirror-vim": "^6.3.0",
|
||||
"@simplewebauthn/browser": "13.3.0",
|
||||
"@tanstack/react-virtual": "^3.13.18",
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"packages/vscode": {
|
||||
"name": "openchamber",
|
||||
"version": "1.12.3",
|
||||
"version": "1.12.4",
|
||||
"dependencies": {
|
||||
"@openchamber/ui": "workspace:*",
|
||||
"@opencode-ai/sdk": "^1.17.0",
|
||||
@@ -239,7 +239,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@openchamber/web",
|
||||
"version": "1.12.3",
|
||||
"version": "1.12.4",
|
||||
"bin": {
|
||||
"openchamber": "./bin/cli.js",
|
||||
},
|
||||
@@ -969,7 +969,11 @@
|
||||
|
||||
"@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="],
|
||||
|
||||
"@pierre/diffs": ["@pierre/diffs@1.1.0-beta.13", "", { "dependencies": { "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-D35rxDu5V7XHX5aVGU6PF12GhscL+I+9QYgxK/i3h0d2XSirAxDdVNm49aYwlOhgmdvL0NbS1IHxPswVB5yJvw=="],
|
||||
"@pierre/diffs": ["@pierre/diffs@1.3.0-beta.4", "", { "dependencies": { "@pierre/theme": "1.0.3", "@pierre/theming": "0.0.1", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-poFcsvhcQt9lH/InzAPaGs47WYHMidnFCjuYGNU41HiVLJP4mkIQDSdvcnPIkBuh/cYbPOQg/YE3T1kSpr01GA=="],
|
||||
|
||||
"@pierre/theme": ["@pierre/theme@1.0.3", "", {}, "sha512-sWHv11TMoqKxKDgTIk5VbhQjdPhs8DCcBxbjh3mRlS3YOM/OcrWoGX6MM8eBGn9cUu3M46Py0JnxsG2nJaFTuA=="],
|
||||
|
||||
"@pierre/theming": ["@pierre/theming@0.0.1", "", { "peerDependencies": { "@pierre/theme": "^1.0.0", "@shikijs/themes": "^3.0.0 || ^4.0.0", "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0", "shiki": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@pierre/theme", "@shikijs/themes", "react", "react-dom", "shiki"] }, "sha512-1thlEtJbqdyLzc1ZS2KQa1q7FzDGHT4dTEdKHoyQjOMeWWOmbVG5/ndEfOKfAb5Fzkz8cNJrOjFLiZoDH/A03A=="],
|
||||
|
||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"@ibm/plex": "^6.4.1",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
"@opencode-ai/sdk": "^1.17.0",
|
||||
"@pierre/diffs": "1.1.0-beta.13",
|
||||
"@pierre/diffs": "1.3.0-beta.4",
|
||||
"@replit/codemirror-vim": "^6.3.0",
|
||||
"@simplewebauthn/browser": "13.3.0",
|
||||
"@tanstack/react-virtual": "^3.13.18",
|
||||
|
||||
@@ -119,7 +119,7 @@ const TOOL_DIFF_METRICS = {
|
||||
lineHeight: 24,
|
||||
diffHeaderHeight: 44,
|
||||
hunkSeparatorHeight: 24,
|
||||
fileGap: 0,
|
||||
spacing: 0,
|
||||
};
|
||||
|
||||
const usePierreThemeConfig = (): PierreThemeConfig => {
|
||||
|
||||
@@ -1388,7 +1388,7 @@ const TOOL_DIFF_METRICS = {
|
||||
lineHeight: 24,
|
||||
diffHeaderHeight: 44,
|
||||
hunkSeparatorHeight: 24,
|
||||
fileGap: 0,
|
||||
spacing: 0,
|
||||
};
|
||||
|
||||
const TOOL_COLLAPSED_CUSTOM_STYLE: React.CSSProperties = {
|
||||
|
||||
@@ -599,15 +599,15 @@ const MultiFileDiffEntry = React.memo<MultiFileDiffEntryProps>(({
|
||||
|
||||
return (
|
||||
<div ref={setSectionRef} className="scroll-mt-9 border-b border-[var(--interactive-border)]/40 last:border-b-0">
|
||||
<div className="sticky top-0 z-10 bg-[var(--surface-muted)]">
|
||||
<div className="sticky top-0 z-10 border-b border-[var(--interactive-border)]/35 bg-[var(--surface-elevated)]/90 backdrop-blur-md supports-[backdrop-filter]:bg-[var(--surface-elevated)]/80">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleToggle}
|
||||
className={cn(
|
||||
'group/header relative flex w-full items-center gap-2 px-3 py-1.5 overflow-hidden',
|
||||
'group/header relative flex min-h-9 w-full items-center gap-2 overflow-hidden px-3 py-2',
|
||||
'bg-transparent',
|
||||
'text-muted-foreground hover:text-foreground',
|
||||
isSelected ? 'bg-[var(--interactive-selection)]/40' : null
|
||||
isSelected ? 'bg-[var(--interactive-selection)]/35' : null
|
||||
)}
|
||||
>
|
||||
<div className="absolute inset-0 pointer-events-none group-hover/header:bg-[var(--interactive-hover)]/50" />
|
||||
|
||||
@@ -91,6 +91,104 @@ const WEBKIT_SCROLL_FIX_CSS = `
|
||||
height: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
[data-separator="line-info-basic"] {
|
||||
height: 24px !important;
|
||||
background: var(--diffs-bg) !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[data-diff-type="single"] [data-gutter],
|
||||
[data-diff-type="split"] [data-deletions] [data-gutter] {
|
||||
[data-separator-wrapper] {
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: unset;
|
||||
width: max-content;
|
||||
background: transparent;
|
||||
color: var(--diffs-fg-number);
|
||||
font-family: var(--diffs-header-font-family, var(--font-sans));
|
||||
font-size: 0.75rem;
|
||||
line-height: 1;
|
||||
margin-left: calc(-2ch - 2px);
|
||||
}
|
||||
|
||||
[data-separator-wrapper][data-separator-multi-button] {
|
||||
margin-left: calc(-3ch - 2px);
|
||||
}
|
||||
|
||||
[data-expand-button],
|
||||
[data-separator-content] {
|
||||
display: block;
|
||||
align-self: unset;
|
||||
min-width: unset;
|
||||
min-height: unset;
|
||||
padding: 0;
|
||||
flex-shrink: 0;
|
||||
grid-column: unset;
|
||||
border: none;
|
||||
width: auto;
|
||||
height: auto;
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
[data-expand-button]:not([data-expand-all-button]) {
|
||||
&[data-expand-down]::before {
|
||||
content: '\\2191';
|
||||
}
|
||||
|
||||
&[data-expand-up]::before {
|
||||
content: '\\2193';
|
||||
}
|
||||
|
||||
&[data-expand-both]::before {
|
||||
content: '\\2195';
|
||||
}
|
||||
|
||||
svg {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
[data-separator-content] {
|
||||
background: transparent;
|
||||
margin-left: calc(2px + 1ch);
|
||||
}
|
||||
|
||||
[data-expand-all-button] {
|
||||
position: relative;
|
||||
margin-left: 14px;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
[data-expand-all-button]::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: -8px;
|
||||
margin-top: -1px;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
border-radius: 2px;
|
||||
background-color: var(--diffs-fg-number);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[data-separator-content]:hover,
|
||||
[data-expand-button]:hover,
|
||||
[data-expand-all-button]:hover {
|
||||
color: var(--diffs-fg);
|
||||
}
|
||||
|
||||
[data-expand-all-button]:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Fast cache key - use length + samples instead of full hash
|
||||
@@ -267,7 +365,7 @@ const virtualizerCache = new WeakMap<Document | HTMLElement, VirtualizerEntry>()
|
||||
const VIRTUAL_METRICS: Partial<VirtualFileMetrics> = {
|
||||
lineHeight: 24,
|
||||
hunkSeparatorHeight: 24,
|
||||
fileGap: 0,
|
||||
spacing: 0,
|
||||
};
|
||||
|
||||
function resolveVirtualizerTarget(container: HTMLElement): VirtualizerTarget {
|
||||
@@ -324,7 +422,7 @@ function acquireSharedVirtualizer(container: HTMLElement): SharedVirtualizer | n
|
||||
}
|
||||
|
||||
const wakeVirtualizer = (
|
||||
instance: PierreFileDiff<unknown>,
|
||||
instance: PierreFileDiff<PierreAnnotationData>,
|
||||
sharedVirtualizer: SharedVirtualizer | null,
|
||||
forceUpdate: () => void,
|
||||
): (() => void) => {
|
||||
@@ -545,11 +643,11 @@ export const PierreDiffViewer: React.FC<PierreDiffViewerProps> = ({
|
||||
|
||||
const diffRootRef = useRef<HTMLDivElement | null>(null);
|
||||
const diffContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const diffInstanceRef = useRef<PierreFileDiff<unknown> | null>(null);
|
||||
const diffInstanceRef = useRef<PierreFileDiff<PierreAnnotationData> | null>(null);
|
||||
const sharedVirtualizerRef = useRef<SharedVirtualizer | null>(null);
|
||||
const instanceVirtualizerRef = useRef<Virtualizer | null>(null);
|
||||
const instanceWorkerPoolRef = useRef<unknown>(null);
|
||||
const instanceVirtualHunkSeparatorsRef = useRef<FileDiffOptions<unknown>['hunkSeparators'] | undefined>(undefined);
|
||||
const instanceVirtualHunkSeparatorsRef = useRef<FileDiffOptions<PierreAnnotationData>['hunkSeparators'] | undefined>(undefined);
|
||||
const instanceFileDiffRef = useRef<FileDiffMetadata | undefined>(undefined);
|
||||
const instanceOldFileRef = useRef<FileContents | undefined>(undefined);
|
||||
const instanceNewFileRef = useRef<FileContents | undefined>(undefined);
|
||||
@@ -755,17 +853,17 @@ export const PierreDiffViewer: React.FC<PierreDiffViewerProps> = ({
|
||||
: false;
|
||||
if (!instance) {
|
||||
instance = sharedVirtualizer
|
||||
? new VirtualizedFileDiff(
|
||||
options as unknown as FileDiffOptions<unknown>,
|
||||
? new VirtualizedFileDiff<PierreAnnotationData>(
|
||||
options as FileDiffOptions<PierreAnnotationData>,
|
||||
sharedVirtualizer.virtualizer,
|
||||
VIRTUAL_METRICS,
|
||||
workerPool,
|
||||
)
|
||||
: new PierreFileDiff(options as unknown as FileDiffOptions<unknown>, workerPool);
|
||||
: new PierreFileDiff(options as FileDiffOptions<PierreAnnotationData>, workerPool);
|
||||
diffInstanceRef.current = instance;
|
||||
lastAppliedSelectionRef.current = null;
|
||||
} else {
|
||||
instance.setOptions(options as unknown as FileDiffOptions<unknown>);
|
||||
instance.setOptions(options as FileDiffOptions<PierreAnnotationData>);
|
||||
}
|
||||
|
||||
instanceVirtualizerRef.current = virtualizer;
|
||||
|
||||
Reference in New Issue
Block a user