Skip to content

Commit 6dea0db

Browse files
select
1 parent 58c6703 commit 6dea0db

File tree

7 files changed

+168
-55
lines changed

7 files changed

+168
-55
lines changed

packages/react/src/components/DiffSplitViewNormal.tsx

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
borderColorName,
88
diffAsideWidthName,
99
} from "@git-diff-view/utils";
10-
import { Fragment, memo, useEffect, useRef } from "react";
10+
import { Fragment, memo, useEffect, useRef, useState } from "react";
1111
import * as React from "react";
1212
import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
1313

@@ -22,31 +22,47 @@ import { useDiffViewContext } from "./DiffViewContext";
2222

2323
import type { MouseEventHandler } from "react";
2424

25-
const onMouseDown: MouseEventHandler<HTMLTableSectionElement> = (e) => {
26-
const ele = e.target;
27-
28-
// need remove all the selection
29-
if (ele && ele instanceof HTMLElement && ele.nodeName === "BUTTON") {
30-
removeAllSelection();
31-
return;
32-
}
33-
};
34-
3525
const DiffSplitViewTable = ({
3626
side,
3727
diffFile,
3828
enableAddWidget,
3929
enableHighlight,
30+
onSelect,
4031
}: {
4132
side: SplitSide;
4233
diffFile: DiffFile;
4334
enableHighlight: boolean;
4435
enableAddWidget: boolean;
36+
onSelect?: (side: SplitSide) => void;
4537
}) => {
4638
const className = side === SplitSide.new ? "new-diff-table" : "old-diff-table";
4739

4840
const lines = getSplitContentLines(diffFile);
4941

42+
const onMouseDown: MouseEventHandler<HTMLTableSectionElement> = (e) => {
43+
let ele = e.target as HTMLElement;
44+
45+
if (ele && ele?.nodeName === "BUTTON") {
46+
removeAllSelection();
47+
return;
48+
}
49+
50+
while (ele && ele instanceof HTMLElement) {
51+
const state = ele.getAttribute("data-state");
52+
if (state) {
53+
if (state === "extend" || state === "hunk" || state === "widget") {
54+
onSelect?.(undefined);
55+
removeAllSelection();
56+
} else {
57+
onSelect?.(side);
58+
removeAllSelection();
59+
}
60+
return;
61+
}
62+
ele = ele.parentElement;
63+
}
64+
};
65+
5066
return (
5167
<table className={className + " w-full border-collapse border-spacing-0"} data-mode={SplitSide[side]}>
5268
<colgroup>
@@ -91,6 +107,8 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
91107

92108
const ref2 = useRef<HTMLDivElement>(null);
93109

110+
const [side, setSide] = useState<SplitSide>();
111+
94112
const splitLineLength = Math.max(diffFile.splitLineLength, diffFile.fileLineLength);
95113

96114
const { useDiffContext } = useDiffViewContext();
@@ -122,8 +140,13 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
122140

123141
const width = Math.max(40, _width + 25);
124142

143+
const id = `diff-root${diffFile.getId()}`
144+
125145
return (
126146
<div className="split-diff-view split-diff-view-normal flex w-full basis-[50%]">
147+
<style data-select-style>
148+
{side ? `#${id} [data-state="extend"] {user-select: none} \n #${id} [data-state="hunk"] {user-select: none} \n #${id} [data-state="widget"] {user-select: none}` : ''}
149+
</style>
127150
<div
128151
className="old-diff-table-wrapper diff-table-scroll-container w-full overflow-x-auto overflow-y-hidden"
129152
ref={ref1}
@@ -140,6 +163,7 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
140163
diffFile={diffFile}
141164
enableAddWidget={enableAddWidget}
142165
enableHighlight={enableHighlight}
166+
onSelect={setSide}
143167
/>
144168
</div>
145169
<div className="diff-split-line w-[1.5px]" style={{ backgroundColor: `var(${borderColorName})` }} />
@@ -159,6 +183,7 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
159183
diffFile={diffFile}
160184
enableAddWidget={enableAddWidget}
161185
enableHighlight={enableHighlight}
186+
onSelect={setSide}
162187
/>
163188
</div>
164189
</div>

packages/react/src/components/DiffSplitViewWrap.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ const Style = ({
3131
return (
3232
<style data-select-style>
3333
{splitRef === SplitSide.old
34-
? `#${id} td[data-side="${SplitSide[SplitSide.new]}"] {user-select: none}`
34+
? `#${id} [data-side="${SplitSide[SplitSide.new]}"] {user-select: none} \n #${id} [data-state="extend"] {user-select: none} \n #${id} [data-state="hunk"] {user-select: none} \n #${id} [data-state="widget"] {user-select: none}`
3535
: splitRef === SplitSide.new
36-
? `#${id} td[data-side="${SplitSide[SplitSide.old]}"] {user-select: none}`
36+
? `#${id} [data-side="${SplitSide[SplitSide.old]}"] {user-select: none} \n #${id} [data-state="extend"] {user-select: none} \n #${id} [data-state="hunk"] {user-select: none} \n #${id} [data-state="widget"] {user-select: none}`
3737
: ""}
3838
</style>
3939
);
@@ -65,16 +65,24 @@ export const DiffSplitViewWrap = memo(({ diffFile }: { diffFile: DiffFile }) =>
6565
return;
6666
}
6767

68-
while (ele && ele instanceof HTMLElement && ele.nodeName !== "TD") {
69-
ele = ele.parentElement;
70-
}
71-
72-
if (ele instanceof HTMLElement) {
68+
while (ele && ele instanceof HTMLElement) {
69+
const state = ele.getAttribute("data-state");
7370
const side = ele.getAttribute("data-side");
7471
if (side) {
7572
setSelectSide(SplitSide[side]);
7673
removeAllSelection();
7774
}
75+
if (state) {
76+
if (state === "extend" || state === "hunk" || state === "widget") {
77+
setSelectSide(undefined);
78+
removeAllSelection();
79+
return;
80+
} else {
81+
return;
82+
}
83+
}
84+
85+
ele = ele.parentElement;
7886
}
7987
// eslint-disable-next-line react-hooks/exhaustive-deps
8088
}, []);

packages/react/src/components/v2/DiffSplitViewNormal_v2.tsx

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
diffAsideWidthName,
88
borderColorName,
99
} from "@git-diff-view/utils";
10-
import { memo, useEffect, useRef } from "react";
10+
import { memo, useEffect, useRef, useState } from "react";
1111
import * as React from "react";
1212
import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
1313

@@ -19,21 +19,43 @@ import { DiffSplitViewLine } from "./DiffSplitViewLineNormal_v2";
1919

2020
import type { MouseEventHandler } from "react";
2121

22-
const onMouseDown: MouseEventHandler<HTMLTableSectionElement> = (e) => {
23-
const ele = e.target;
24-
25-
// need remove all the selection
26-
if (ele && ele instanceof HTMLElement && ele.nodeName === "BUTTON") {
27-
removeAllSelection();
28-
return;
29-
}
30-
};
31-
32-
export const DiffSplitViewTable = ({ side, diffFile }: { side: SplitSide; diffFile: DiffFile }) => {
22+
export const DiffSplitViewTable = ({
23+
side,
24+
diffFile,
25+
onSelect,
26+
}: {
27+
side: SplitSide;
28+
diffFile: DiffFile;
29+
onSelect?: (side: SplitSide) => void;
30+
}) => {
3331
const className = side === SplitSide.new ? "new-diff-table" : "old-diff-table";
3432

3533
const lines = getSplitLines(diffFile);
3634

35+
const onMouseDown: MouseEventHandler<HTMLTableSectionElement> = (e) => {
36+
let ele = e.target as HTMLElement;
37+
38+
if (ele && ele?.nodeName === "BUTTON") {
39+
removeAllSelection();
40+
return;
41+
}
42+
43+
while (ele && ele instanceof HTMLElement) {
44+
const state = ele.getAttribute("data-state");
45+
if (state) {
46+
if (state === "extend" || state === "hunk" || state === "widget") {
47+
onSelect?.(undefined);
48+
removeAllSelection();
49+
} else {
50+
onSelect?.(side);
51+
removeAllSelection();
52+
}
53+
return;
54+
}
55+
ele = ele.parentElement;
56+
}
57+
};
58+
3759
return (
3860
<div className={className + " w-max min-w-full"} data-mode={SplitSide[side]}>
3961
<div className="diff-table-body leading-[1.6]" onMouseDownCapture={onMouseDown}>
@@ -55,6 +77,8 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
5577

5678
const ref2 = useRef<HTMLDivElement>(null);
5779

80+
const [side, setSide] = useState<SplitSide>();
81+
5882
const splitLineLength = Math.max(diffFile.splitLineLength, diffFile.fileLineLength);
5983

6084
const { useDiffContext } = useDiffViewContext();
@@ -82,8 +106,15 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
82106

83107
const width = Math.max(40, _width + 25);
84108

109+
const id = `diff-root${diffFile.getId()}`;
110+
85111
return (
86112
<div className="split-diff-view split-diff-view-normal flex w-full basis-[50%]">
113+
<style data-select-style>
114+
{side
115+
? `#${id} [data-state="extend"] {user-select: none} \n #${id} [data-state="hunk"] {user-select: none} \n #${id} [data-state="widget"] {user-select: none}`
116+
: ""}
117+
</style>
87118
<div
88119
className="old-diff-table-wrapper diff-table-scroll-container w-full overflow-x-auto overflow-y-hidden"
89120
ref={ref1}
@@ -95,7 +126,7 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
95126
fontSize: `var(${diffFontSizeName})`,
96127
}}
97128
>
98-
<DiffSplitViewTable side={SplitSide.old} diffFile={diffFile} />
129+
<DiffSplitViewTable side={SplitSide.old} diffFile={diffFile} onSelect={setSide} />
99130
</div>
100131
<div className="diff-split-line w-[1.5px]" style={{ backgroundColor: `var(${borderColorName})` }} />
101132
<div
@@ -109,7 +140,7 @@ export const DiffSplitViewNormal = memo(({ diffFile }: { diffFile: DiffFile }) =
109140
fontSize: `var(${diffFontSizeName})`,
110141
}}
111142
>
112-
<DiffSplitViewTable side={SplitSide.new} diffFile={diffFile} />
143+
<DiffSplitViewTable side={SplitSide.new} diffFile={diffFile} onSelect={setSide} />
113144
</div>
114145
</div>
115146
);

packages/react/src/components/v2/DiffSplitViewWrap_v2.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ const Style = ({
2828
return (
2929
<style data-select-style>
3030
{splitRef === SplitSide.old
31-
? `#${id} td[data-side="${SplitSide[SplitSide.new]}"] {user-select: none}`
31+
? `#${id} [data-side="${SplitSide[SplitSide.new]}"] {user-select: none} \n #${id} [data-state="extend"] {user-select: none} \n #${id} [data-state="hunk"] {user-select: none} \n #${id} [data-state="widget"] {user-select: none}`
3232
: splitRef === SplitSide.new
33-
? `#${id} td[data-side="${SplitSide[SplitSide.old]}"] {user-select: none}`
33+
? `#${id} [data-side="${SplitSide[SplitSide.old]}"] {user-select: none} \n #${id} [data-state="extend"] {user-select: none} \n #${id} [data-state="hunk"] {user-select: none} \n #${id} [data-state="widget"] {user-select: none}`
3434
: ""}
3535
</style>
3636
);
@@ -58,16 +58,24 @@ export const DiffSplitViewWrap = memo(({ diffFile }: { diffFile: DiffFile }) =>
5858
return;
5959
}
6060

61-
while (ele && ele instanceof HTMLElement && ele.nodeName !== "TD") {
62-
ele = ele.parentElement;
63-
}
64-
65-
if (ele instanceof HTMLElement) {
61+
while (ele && ele instanceof HTMLElement) {
62+
const state = ele.getAttribute("data-state");
6663
const side = ele.getAttribute("data-side");
6764
if (side) {
6865
setSelectSide(SplitSide[side]);
6966
removeAllSelection();
7067
}
68+
if (state) {
69+
if (state === "extend" || state === "hunk" || state === "widget") {
70+
setSelectSide(undefined);
71+
removeAllSelection();
72+
return;
73+
} else {
74+
return;
75+
}
76+
}
77+
78+
ele = ele.parentElement;
7179
}
7280
// eslint-disable-next-line react-hooks/exhaustive-deps
7381
}, []);

packages/vue/src/components/DiffSplitHunkLineWrap.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const DiffSplitHunkLineGitHub = defineComponent(
6666
if (!currentIsShow.value && !currentIsPureHunk.value) return null;
6767

6868
return (
69-
<tr data-line={`${props.lineNumber}-hunk`} data-state="hunk" class="diff-line diff-line-hunk select-none">
69+
<tr data-line={`${props.lineNumber}-hunk`} data-state="hunk" class="diff-line diff-line-hunk">
7070
<td
7171
class="diff-line-hunk-action relative w-[1%] min-w-[40px] select-none p-[1px]"
7272
style={{
@@ -199,7 +199,7 @@ const DiffSplitHunkLineGitLab = defineComponent(
199199
if (!currentIsShow.value && !currentIsPureHunk.value) return null;
200200

201201
return (
202-
<tr data-line={`${props.lineNumber}-hunk`} data-state="hunk" class="diff-line diff-line-hunk select-none">
202+
<tr data-line={`${props.lineNumber}-hunk`} data-state="hunk" class="diff-line diff-line-hunk">
203203
<td
204204
class="diff-line-hunk-action relative w-[1%] min-w-[40px] select-none p-[1px]"
205205
style={{

0 commit comments

Comments
 (0)