@git-diff-view/react 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.development.js +431 -290
- package/dist/cjs/index.development.js.map +1 -1
- package/dist/cjs/index.production.js +431 -290
- package/dist/cjs/index.production.js.map +1 -1
- package/dist/css/diff-view-pure.css +4 -0
- package/dist/css/diff-view.css +4 -0
- package/dist/esm/index.mjs +362 -224
- package/dist/esm/index.mjs.map +1 -1
- package/index.d.ts +303 -23
- package/package.json +4 -3
- package/src/_base.css +3 -0
- package/src/_base_pure.css +2 -0
- package/src/_com.css +172 -0
- package/src/_theme.css +2 -0
- package/src/components/DiffAddWidget.tsx +86 -0
- package/src/components/DiffContent.tsx +367 -0
- package/src/components/DiffContent_v2.tsx +344 -0
- package/src/components/DiffExpand.tsx +25 -0
- package/src/components/DiffNoNewLine.tsx +10 -0
- package/src/components/DiffSplitContentLineNormal.tsx +164 -0
- package/src/components/DiffSplitContentLineWrap.tsx +234 -0
- package/src/components/DiffSplitExtendLineNormal.tsx +150 -0
- package/src/components/DiffSplitExtendLineWrap.tsx +133 -0
- package/src/components/DiffSplitHunkLineNormal.tsx +316 -0
- package/src/components/DiffSplitHunkLineWrap.tsx +340 -0
- package/src/components/DiffSplitView.tsx +46 -0
- package/src/components/DiffSplitViewNormal.tsx +205 -0
- package/src/components/DiffSplitViewWrap.tsx +141 -0
- package/src/components/DiffSplitWidgetLineNormal.tsx +149 -0
- package/src/components/DiffSplitWidgetLineWrap.tsx +127 -0
- package/src/components/DiffUnifiedContentLine.tsx +342 -0
- package/src/components/DiffUnifiedExtendLine.tsx +103 -0
- package/src/components/DiffUnifiedHunkLine.tsx +148 -0
- package/src/components/DiffUnifiedView.tsx +159 -0
- package/src/components/DiffUnifiedWidgetLine.tsx +104 -0
- package/src/components/DiffView.tsx +365 -0
- package/src/components/DiffViewContext.ts +11 -0
- package/src/components/DiffWidgetContext.ts +17 -0
- package/src/components/tools.ts +132 -0
- package/src/components/v2/DiffSplitContentLineNormal_v2.tsx +152 -0
- package/src/components/v2/DiffSplitContentLineWrap_v2.tsx +259 -0
- package/src/components/v2/DiffSplitExtendLineNormal_v2.tsx +146 -0
- package/src/components/v2/DiffSplitExtendLineWrap_v2.tsx +123 -0
- package/src/components/v2/DiffSplitHunkLineNormal_v2.tsx +302 -0
- package/src/components/v2/DiffSplitHunkLineWrap_v2.tsx +326 -0
- package/src/components/v2/DiffSplitViewLineNormal_v2.tsx +33 -0
- package/src/components/v2/DiffSplitViewLineWrap_v2.tsx +24 -0
- package/src/components/v2/DiffSplitViewNormal_v2.tsx +159 -0
- package/src/components/v2/DiffSplitViewWrap_v2.tsx +104 -0
- package/src/components/v2/DiffSplitView_v2.tsx +47 -0
- package/src/components/v2/DiffSplitWidgetLineNormal_v2.tsx +132 -0
- package/src/components/v2/DiffSplitWidgetLineWrap_v2.tsx +119 -0
- package/src/global.d.ts +12 -0
- package/src/hooks/useCallbackRef.ts +18 -0
- package/src/hooks/useDomWidth.ts +67 -0
- package/src/hooks/useIsMounted.ts +11 -0
- package/src/hooks/useSafeLayout.ts +5 -0
- package/src/hooks/useSyncHeight.ts +87 -0
- package/src/hooks/useTextWidth.ts +27 -0
- package/src/hooks/useUnmount.ts +10 -0
- package/src/index.ts +3 -0
- package/src/tailwind.css +3 -0
- package/src/tailwind_pure.css +3 -0
- package/styles/diff-view-pure.css +4 -0
- package/styles/diff-view.css +4 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { emptyBGName } from "@git-diff-view/utils";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import { useDomWidth } from "../../hooks/useDomWidth";
|
|
5
|
+
import { useSyncHeight } from "../../hooks/useSyncHeight";
|
|
6
|
+
import { SplitSide } from "../DiffView";
|
|
7
|
+
import { useDiffViewContext } from "../DiffViewContext";
|
|
8
|
+
import { useDiffWidgetContext } from "../DiffWidgetContext";
|
|
9
|
+
|
|
10
|
+
import type { DiffFile } from "@git-diff-view/core";
|
|
11
|
+
|
|
12
|
+
const InternalDiffSplitWidgetLine = ({
|
|
13
|
+
index,
|
|
14
|
+
side,
|
|
15
|
+
diffFile,
|
|
16
|
+
lineNumber,
|
|
17
|
+
}: {
|
|
18
|
+
index: number;
|
|
19
|
+
side: SplitSide;
|
|
20
|
+
diffFile: DiffFile;
|
|
21
|
+
lineNumber: number;
|
|
22
|
+
}) => {
|
|
23
|
+
const { useWidget } = useDiffWidgetContext();
|
|
24
|
+
|
|
25
|
+
const { useDiffContext } = useDiffViewContext();
|
|
26
|
+
|
|
27
|
+
const oldLine = diffFile.getSplitLeftLine(index);
|
|
28
|
+
|
|
29
|
+
const newLine = diffFile.getSplitRightLine(index);
|
|
30
|
+
|
|
31
|
+
const widgetSide = useWidget.getReadonlyState().widgetSide;
|
|
32
|
+
|
|
33
|
+
const widgetLineNumber = useWidget.getReadonlyState().widgetLineNumber;
|
|
34
|
+
|
|
35
|
+
const setWidget = useWidget.getReadonlyState().setWidget;
|
|
36
|
+
|
|
37
|
+
const oldLineWidget = oldLine.lineNumber && widgetSide === SplitSide.old && widgetLineNumber === oldLine.lineNumber;
|
|
38
|
+
|
|
39
|
+
const newLineWidget = newLine.lineNumber && widgetSide === SplitSide.new && widgetLineNumber === newLine.lineNumber;
|
|
40
|
+
|
|
41
|
+
const currentLine = side === SplitSide.old ? oldLine : newLine;
|
|
42
|
+
|
|
43
|
+
const otherSide = side === SplitSide.old ? SplitSide.new : SplitSide.old;
|
|
44
|
+
|
|
45
|
+
const currentHasWidget = side === SplitSide.old ? oldLineWidget : newLineWidget;
|
|
46
|
+
|
|
47
|
+
const hasWidget = oldLineWidget || newLineWidget;
|
|
48
|
+
|
|
49
|
+
const renderWidgetLine = useDiffContext.useShallowStableSelector((s) => s.renderWidgetLine);
|
|
50
|
+
|
|
51
|
+
useSyncHeight({
|
|
52
|
+
wrapper: `div[data-state="widget"][data-line="${lineNumber}-widget"]`,
|
|
53
|
+
selector: `div[data-line="${lineNumber}-widget-content"]`,
|
|
54
|
+
side: SplitSide[currentHasWidget ? side : otherSide],
|
|
55
|
+
enable: hasWidget && typeof renderWidgetLine === "function",
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const width = useDomWidth({
|
|
59
|
+
selector: side === SplitSide.old ? ".old-diff-table-wrapper" : ".new-diff-table-wrapper",
|
|
60
|
+
enable: !!currentHasWidget && typeof renderWidgetLine === "function",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (!renderWidgetLine) return null;
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
data-line={`${lineNumber}-widget`}
|
|
68
|
+
data-state="widget"
|
|
69
|
+
data-side={SplitSide[side]}
|
|
70
|
+
className="diff-line diff-line-widget"
|
|
71
|
+
>
|
|
72
|
+
{currentHasWidget ? (
|
|
73
|
+
<div className={`diff-line-widget-${SplitSide[side]}-content p-0`}>
|
|
74
|
+
<div
|
|
75
|
+
data-line={`${lineNumber}-widget-content`}
|
|
76
|
+
data-side={SplitSide[side]}
|
|
77
|
+
className="diff-line-widget-wrapper sticky left-0 z-[1]"
|
|
78
|
+
style={{ width }}
|
|
79
|
+
>
|
|
80
|
+
{width > 0 &&
|
|
81
|
+
renderWidgetLine?.({
|
|
82
|
+
diffFile,
|
|
83
|
+
side,
|
|
84
|
+
lineNumber: currentLine.lineNumber,
|
|
85
|
+
onClose: () => setWidget({}),
|
|
86
|
+
})}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
) : (
|
|
90
|
+
<div
|
|
91
|
+
className={`diff-line-widget-${SplitSide[side]}-placeholder h-full select-none p-0`}
|
|
92
|
+
style={{ backgroundColor: `var(${emptyBGName})` }}
|
|
93
|
+
>
|
|
94
|
+
<div data-line={`${lineNumber}-widget-content`} data-side={SplitSide[side]} />
|
|
95
|
+
</div>
|
|
96
|
+
)}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const DiffSplitWidgetLine = ({
|
|
102
|
+
index,
|
|
103
|
+
diffFile,
|
|
104
|
+
side,
|
|
105
|
+
lineNumber,
|
|
106
|
+
}: {
|
|
107
|
+
index: number;
|
|
108
|
+
side: SplitSide;
|
|
109
|
+
diffFile: DiffFile;
|
|
110
|
+
lineNumber: number;
|
|
111
|
+
}) => {
|
|
112
|
+
const { useWidget } = useDiffWidgetContext();
|
|
113
|
+
|
|
114
|
+
const { widgetLineNumber, widgetSide } = useWidget.useShallowStableSelector((s) => ({
|
|
115
|
+
widgetLineNumber: s.widgetLineNumber,
|
|
116
|
+
widgetSide: s.widgetSide,
|
|
117
|
+
}));
|
|
118
|
+
|
|
119
|
+
const oldLine = diffFile.getSplitLeftLine(index);
|
|
120
|
+
|
|
121
|
+
const newLine = diffFile.getSplitRightLine(index);
|
|
122
|
+
|
|
123
|
+
const oldLineWidget = oldLine.lineNumber && widgetSide === SplitSide.old && widgetLineNumber === oldLine.lineNumber;
|
|
124
|
+
|
|
125
|
+
const newLineWidget = newLine.lineNumber && widgetSide === SplitSide.new && widgetLineNumber === newLine.lineNumber;
|
|
126
|
+
|
|
127
|
+
const currentIsShow = oldLineWidget || newLineWidget;
|
|
128
|
+
|
|
129
|
+
if (!currentIsShow) return null;
|
|
130
|
+
|
|
131
|
+
return <InternalDiffSplitWidgetLine index={index} diffFile={diffFile} side={side} lineNumber={lineNumber} />;
|
|
132
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { borderColorName, emptyBGName } from "@git-diff-view/utils";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import { SplitSide } from "../DiffView";
|
|
5
|
+
import { useDiffViewContext } from "../DiffViewContext";
|
|
6
|
+
import { useDiffWidgetContext } from "../DiffWidgetContext";
|
|
7
|
+
|
|
8
|
+
import type { DiffFile } from "@git-diff-view/core";
|
|
9
|
+
|
|
10
|
+
const InternalDiffSplitWidgetLine = ({
|
|
11
|
+
index,
|
|
12
|
+
diffFile,
|
|
13
|
+
lineNumber,
|
|
14
|
+
oldLineWidget,
|
|
15
|
+
newLineWidget,
|
|
16
|
+
}: {
|
|
17
|
+
index: number;
|
|
18
|
+
diffFile: DiffFile;
|
|
19
|
+
lineNumber: number;
|
|
20
|
+
oldLineWidget: boolean;
|
|
21
|
+
newLineWidget: boolean;
|
|
22
|
+
}) => {
|
|
23
|
+
const { useWidget } = useDiffWidgetContext();
|
|
24
|
+
|
|
25
|
+
const setWidget = useWidget.getReadonlyState().setWidget;
|
|
26
|
+
|
|
27
|
+
const { useDiffContext } = useDiffViewContext();
|
|
28
|
+
|
|
29
|
+
const renderWidgetLine = useDiffContext.useShallowStableSelector((s) => s.renderWidgetLine);
|
|
30
|
+
|
|
31
|
+
const oldLine = diffFile.getSplitLeftLine(index);
|
|
32
|
+
|
|
33
|
+
const newLine = diffFile.getSplitRightLine(index);
|
|
34
|
+
|
|
35
|
+
if (!renderWidgetLine) return null;
|
|
36
|
+
|
|
37
|
+
const oldWidgetRendered =
|
|
38
|
+
oldLineWidget &&
|
|
39
|
+
renderWidgetLine?.({
|
|
40
|
+
diffFile,
|
|
41
|
+
side: SplitSide.old,
|
|
42
|
+
lineNumber: oldLine.lineNumber,
|
|
43
|
+
onClose: () => setWidget({}),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const newWidgetRendered =
|
|
47
|
+
newLineWidget &&
|
|
48
|
+
renderWidgetLine?.({
|
|
49
|
+
diffFile,
|
|
50
|
+
side: SplitSide.new,
|
|
51
|
+
lineNumber: newLine.lineNumber,
|
|
52
|
+
onClose: () => setWidget({}),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div data-line={`${lineNumber}-widget`} data-state="widget" className="diff-line diff-line-widget flex">
|
|
57
|
+
{oldWidgetRendered ? (
|
|
58
|
+
<div className="diff-line-widget-old-content w-[50%] p-0">
|
|
59
|
+
<div className="diff-line-widget-wrapper">{oldWidgetRendered}</div>
|
|
60
|
+
</div>
|
|
61
|
+
) : (
|
|
62
|
+
<div
|
|
63
|
+
className="diff-line-widget-old-placeholder w-[50%] select-none p-0"
|
|
64
|
+
style={{ backgroundColor: `var(${emptyBGName})` }}
|
|
65
|
+
/>
|
|
66
|
+
)}
|
|
67
|
+
<div className="diff-split-line w-[1px] flex-shrink-0" style={{ backgroundColor: `var(${borderColorName})` }} />
|
|
68
|
+
{newWidgetRendered ? (
|
|
69
|
+
<div className="diff-line-widget-new-content w-[50%] p-0">
|
|
70
|
+
<div className="diff-line-widget-wrapper">{newWidgetRendered}</div>
|
|
71
|
+
</div>
|
|
72
|
+
) : (
|
|
73
|
+
<div
|
|
74
|
+
className="diff-line-widget-new-placeholder w-[50%] select-none p-0"
|
|
75
|
+
style={{ backgroundColor: `var(${emptyBGName})` }}
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const DiffSplitWidgetLine = ({
|
|
83
|
+
index,
|
|
84
|
+
diffFile,
|
|
85
|
+
lineNumber,
|
|
86
|
+
}: {
|
|
87
|
+
index: number;
|
|
88
|
+
diffFile: DiffFile;
|
|
89
|
+
lineNumber: number;
|
|
90
|
+
}) => {
|
|
91
|
+
const { useWidget } = useDiffWidgetContext();
|
|
92
|
+
|
|
93
|
+
const { widgetLineNumber, widgetSide } = useWidget.useShallowStableSelector((s) => ({
|
|
94
|
+
widgetLineNumber: s.widgetLineNumber,
|
|
95
|
+
widgetSide: s.widgetSide,
|
|
96
|
+
}));
|
|
97
|
+
|
|
98
|
+
const oldLine = diffFile.getSplitLeftLine(index);
|
|
99
|
+
|
|
100
|
+
const newLine = diffFile.getSplitRightLine(index);
|
|
101
|
+
|
|
102
|
+
const oldLineWidget = oldLine.lineNumber && widgetSide === SplitSide.old && widgetLineNumber === oldLine.lineNumber;
|
|
103
|
+
|
|
104
|
+
const newLineWidget = newLine.lineNumber && widgetSide === SplitSide.new && widgetLineNumber === newLine.lineNumber;
|
|
105
|
+
|
|
106
|
+
const currentIsShow = oldLineWidget || newLineWidget;
|
|
107
|
+
|
|
108
|
+
if (!currentIsShow) return null;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<InternalDiffSplitWidgetLine
|
|
112
|
+
index={index}
|
|
113
|
+
diffFile={diffFile}
|
|
114
|
+
lineNumber={lineNumber}
|
|
115
|
+
oldLineWidget={oldLineWidget}
|
|
116
|
+
newLineWidget={newLineWidget}
|
|
117
|
+
/>
|
|
118
|
+
);
|
|
119
|
+
};
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useCallback, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
4
|
+
export const useCallbackRef = <T extends Function>(cb?: T): T => {
|
|
5
|
+
const cbRef = useRef(cb);
|
|
6
|
+
|
|
7
|
+
cbRef.current = cb;
|
|
8
|
+
|
|
9
|
+
const stableCallback = useCallback((...args: any[]) => {
|
|
10
|
+
if (args.length) {
|
|
11
|
+
return cbRef.current?.(...args);
|
|
12
|
+
} else {
|
|
13
|
+
return cbRef.current?.();
|
|
14
|
+
}
|
|
15
|
+
}, []) as unknown as T;
|
|
16
|
+
|
|
17
|
+
return stableCallback;
|
|
18
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { useDiffViewContext } from "../components/DiffViewContext";
|
|
4
|
+
|
|
5
|
+
export type ObserveElement = HTMLElement & {
|
|
6
|
+
__observeCallback: Set<() => void>;
|
|
7
|
+
__observeInstance: ResizeObserver;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const useDomWidth = ({ selector, enable }: { selector: string; enable: boolean }) => {
|
|
11
|
+
const [width, setWidth] = useState(0);
|
|
12
|
+
|
|
13
|
+
const { useDiffContext } = useDiffViewContext();
|
|
14
|
+
|
|
15
|
+
const { id, mounted } = useDiffContext.useShallowStableSelector((s) => ({ id: s.id, mounted: s.mounted }));
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (enable) {
|
|
19
|
+
const container = document.querySelector(`#diff-root${id}`);
|
|
20
|
+
|
|
21
|
+
const wrapper = container?.querySelector(selector);
|
|
22
|
+
|
|
23
|
+
if (!wrapper) return;
|
|
24
|
+
|
|
25
|
+
const typedWrapper = wrapper as ObserveElement;
|
|
26
|
+
|
|
27
|
+
const cb = () => {
|
|
28
|
+
const rect = wrapper?.getBoundingClientRect();
|
|
29
|
+
setWidth(rect?.width ?? 0);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
cb();
|
|
33
|
+
|
|
34
|
+
const cleanCb = () => {
|
|
35
|
+
typedWrapper.__observeCallback.delete(cb);
|
|
36
|
+
if (typedWrapper.__observeCallback.size === 0) {
|
|
37
|
+
typedWrapper.__observeInstance?.disconnect();
|
|
38
|
+
typedWrapper.removeAttribute("data-observe");
|
|
39
|
+
delete typedWrapper.__observeCallback;
|
|
40
|
+
delete typedWrapper.__observeInstance;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (typedWrapper.__observeCallback) {
|
|
45
|
+
typedWrapper.__observeCallback.add(cb);
|
|
46
|
+
|
|
47
|
+
return () => cleanCb();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
typedWrapper.__observeCallback = new Set();
|
|
51
|
+
|
|
52
|
+
typedWrapper.__observeCallback.add(cb);
|
|
53
|
+
|
|
54
|
+
const observer = new ResizeObserver(() => typedWrapper.__observeCallback.forEach((cb) => cb()));
|
|
55
|
+
|
|
56
|
+
typedWrapper.__observeInstance = observer;
|
|
57
|
+
|
|
58
|
+
observer.observe(typedWrapper);
|
|
59
|
+
|
|
60
|
+
typedWrapper.setAttribute("data-observe", "height");
|
|
61
|
+
|
|
62
|
+
return () => cleanCb();
|
|
63
|
+
}
|
|
64
|
+
}, [selector, enable, id, mounted]);
|
|
65
|
+
|
|
66
|
+
return width;
|
|
67
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
import { useDiffViewContext } from "../components/DiffViewContext";
|
|
4
|
+
|
|
5
|
+
import type { ObserveElement } from "./useDomWidth";
|
|
6
|
+
|
|
7
|
+
export const useSyncHeight = ({
|
|
8
|
+
selector,
|
|
9
|
+
wrapper,
|
|
10
|
+
side,
|
|
11
|
+
enable,
|
|
12
|
+
}: {
|
|
13
|
+
selector: string;
|
|
14
|
+
wrapper?: string;
|
|
15
|
+
side: string;
|
|
16
|
+
enable: boolean;
|
|
17
|
+
}) => {
|
|
18
|
+
const { useDiffContext } = useDiffViewContext();
|
|
19
|
+
|
|
20
|
+
const { id, mounted } = useDiffContext.useShallowStableSelector((s) => ({ id: s.id, mounted: s.mounted }));
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (enable) {
|
|
24
|
+
const container = document.querySelector(`#diff-root${id}`);
|
|
25
|
+
|
|
26
|
+
const elements = Array.from(container?.querySelectorAll(selector) || []);
|
|
27
|
+
|
|
28
|
+
const wrappers = wrapper ? Array.from(container?.querySelectorAll(wrapper) || []) : elements;
|
|
29
|
+
|
|
30
|
+
if (elements.length === 2 && wrappers.length === 2) {
|
|
31
|
+
const ele1 = elements[0] as HTMLElement;
|
|
32
|
+
const ele2 = elements[1] as HTMLElement;
|
|
33
|
+
|
|
34
|
+
const wrapper1 = wrappers[0] as HTMLElement;
|
|
35
|
+
const wrapper2 = wrappers[1] as HTMLElement;
|
|
36
|
+
|
|
37
|
+
const target = ele1.getAttribute("data-side") === side ? ele1 : ele2;
|
|
38
|
+
|
|
39
|
+
const typedTarget = target as ObserveElement;
|
|
40
|
+
|
|
41
|
+
const cb = () => {
|
|
42
|
+
ele1.style.height = "auto";
|
|
43
|
+
ele2.style.height = "auto";
|
|
44
|
+
const rect1 = ele1.getBoundingClientRect();
|
|
45
|
+
const rect2 = ele2.getBoundingClientRect();
|
|
46
|
+
const maxHeight = Math.max(rect1.height, rect2.height);
|
|
47
|
+
wrapper1.style.height = maxHeight + "px";
|
|
48
|
+
wrapper2.style.height = maxHeight + "px";
|
|
49
|
+
wrapper1.setAttribute("data-sync-height", String(maxHeight));
|
|
50
|
+
wrapper2.setAttribute("data-sync-height", String(maxHeight));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
cb();
|
|
54
|
+
|
|
55
|
+
const cleanCb = () => {
|
|
56
|
+
typedTarget.__observeCallback.delete(cb);
|
|
57
|
+
if (typedTarget.__observeCallback.size === 0) {
|
|
58
|
+
typedTarget.__observeInstance?.disconnect();
|
|
59
|
+
typedTarget.removeAttribute("data-observe");
|
|
60
|
+
delete typedTarget.__observeCallback;
|
|
61
|
+
delete typedTarget.__observeInstance;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
if (typedTarget.__observeCallback) {
|
|
66
|
+
typedTarget.__observeCallback.add(cb);
|
|
67
|
+
|
|
68
|
+
return () => cleanCb();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
typedTarget.__observeCallback = new Set();
|
|
72
|
+
|
|
73
|
+
typedTarget.__observeCallback.add(cb);
|
|
74
|
+
|
|
75
|
+
const observer = new ResizeObserver(() => typedTarget.__observeCallback.forEach((cb) => cb()));
|
|
76
|
+
|
|
77
|
+
typedTarget.__observeInstance = observer;
|
|
78
|
+
|
|
79
|
+
observer.observe(target);
|
|
80
|
+
|
|
81
|
+
target.setAttribute("data-observe", "height");
|
|
82
|
+
|
|
83
|
+
return () => cleanCb();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}, [selector, enable, side, id, wrapper, mounted]);
|
|
87
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getTextMeasureInstance } from "@git-diff-view/utils";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
|
|
4
|
+
import { useSafeLayout } from "./useSafeLayout";
|
|
5
|
+
|
|
6
|
+
export const useTextWidth = ({
|
|
7
|
+
text,
|
|
8
|
+
font,
|
|
9
|
+
}: {
|
|
10
|
+
text: string;
|
|
11
|
+
font: { fontFamily?: string; fontStyle?: string; fontSize?: string };
|
|
12
|
+
}) => {
|
|
13
|
+
const [width, setWidth] = useState(() => {
|
|
14
|
+
const fontSize = parseInt(font.fontSize);
|
|
15
|
+
let baseSize = 6;
|
|
16
|
+
baseSize += fontSize > 10 ? (fontSize - 10) * 0.6 : 0;
|
|
17
|
+
return baseSize * text.length;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
useSafeLayout(() => {
|
|
21
|
+
const width = getTextMeasureInstance().measure(text, font);
|
|
22
|
+
|
|
23
|
+
setWidth(width);
|
|
24
|
+
}, [text, font]);
|
|
25
|
+
|
|
26
|
+
return width;
|
|
27
|
+
};
|
package/src/index.ts
ADDED
package/src/tailwind.css
ADDED
|
@@ -280,7 +280,9 @@
|
|
|
280
280
|
--diff-plain-content--: #ffffff;
|
|
281
281
|
--diff-expand-content--: #fafafa;
|
|
282
282
|
--diff-plain-lineNumber--: #fafafa;
|
|
283
|
+
--diff-expand-lineNumber--: #fafafa;
|
|
283
284
|
--diff-plain-lineNumber-color--: #555555;
|
|
285
|
+
--diff-expand-lineNumber-color--: #555555;
|
|
284
286
|
--diff-hunk-content--: #ddf4ff;
|
|
285
287
|
--diff-hunk-lineNumber--: #c7ecff;
|
|
286
288
|
--diff-hunk-lineNumber-hover--: #0969da;
|
|
@@ -307,7 +309,9 @@
|
|
|
307
309
|
--diff-plain-content--: #0d1117;
|
|
308
310
|
--diff-expand-content--: #161b22;
|
|
309
311
|
--diff-plain-lineNumber--: #161b22;
|
|
312
|
+
--diff-expand-lineNumber--: #161b22;
|
|
310
313
|
--diff-plain-lineNumber-color--: #a0aaab;
|
|
314
|
+
--diff-expand-lineNumber-color--: #a0aaab;
|
|
311
315
|
--diff-hunk-content--: #131d2e;
|
|
312
316
|
--diff-hunk-lineNumber--: #204274;
|
|
313
317
|
--diff-hunk-lineNumber-hover--: #1f6feb;
|
package/styles/diff-view.css
CHANGED
|
@@ -786,7 +786,9 @@ video {
|
|
|
786
786
|
--diff-plain-content--: #ffffff;
|
|
787
787
|
--diff-expand-content--: #fafafa;
|
|
788
788
|
--diff-plain-lineNumber--: #fafafa;
|
|
789
|
+
--diff-expand-lineNumber--: #fafafa;
|
|
789
790
|
--diff-plain-lineNumber-color--: #555555;
|
|
791
|
+
--diff-expand-lineNumber-color--: #555555;
|
|
790
792
|
--diff-hunk-content--: #ddf4ff;
|
|
791
793
|
--diff-hunk-lineNumber--: #c7ecff;
|
|
792
794
|
--diff-hunk-lineNumber-hover--: #0969da;
|
|
@@ -813,7 +815,9 @@ video {
|
|
|
813
815
|
--diff-plain-content--: #0d1117;
|
|
814
816
|
--diff-expand-content--: #161b22;
|
|
815
817
|
--diff-plain-lineNumber--: #161b22;
|
|
818
|
+
--diff-expand-lineNumber--: #161b22;
|
|
816
819
|
--diff-plain-lineNumber-color--: #a0aaab;
|
|
820
|
+
--diff-expand-lineNumber-color--: #a0aaab;
|
|
817
821
|
--diff-hunk-content--: #131d2e;
|
|
818
822
|
--diff-hunk-lineNumber--: #204274;
|
|
819
823
|
--diff-hunk-lineNumber-hover--: #1f6feb;
|