Skip to content

Commit 6cd8315

Browse files
authoredNov 26, 2020
Merge pull request nicoespeon#392 from oceanbit-dev/fix-strict-mode
[React] Fix strict mode label placement
2 parents be9cdf4 + 5504df0 commit 6cd8315

File tree

6 files changed

+217
-290
lines changed

6 files changed

+217
-290
lines changed
 
+46-58
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as React from "react";
22
import { Branch, Commit, GitgraphCore } from "@gitgraph/core";
3-
import { CommitElement, ReactSvgElement } from "./types";
3+
import { ReactSvgElement } from "./types";
4+
import { MutableRefObject } from "react";
45

56
interface BranchLabelBaseProps {
67
branch: Branch<React.ReactElement<SVGElement>>;
@@ -11,6 +12,7 @@ function DefaultBranchLabel({branch, commit}: BranchLabelBaseProps) {
1112
const [textSizing, setTextSizing] = React.useState({ textWidth: 0, textHeight: 0 })
1213

1314
const getSizing = React.useCallback((node) => {
15+
if (!node) return;
1416
const box = node.getBBox();
1517
setTextSizing({ textWidth: box.width, textHeight: box.height });
1618
}, [])
@@ -44,69 +46,55 @@ function DefaultBranchLabel({branch, commit}: BranchLabelBaseProps) {
4446

4547
interface BranchLabelProps extends BranchLabelBaseProps {
4648
gitgraph: GitgraphCore<ReactSvgElement>;
47-
initCommitElements: (commit: Commit<ReactSvgElement>) => void;
48-
commitsElements: {
49-
[commitHash: string]: CommitElement;
50-
};
49+
ref: MutableRefObject<SVGGElement | undefined>;
50+
branchLabelX: number;
5151
}
5252

53-
export class BranchLabel extends React.Component<BranchLabelProps> {
54-
public static readonly paddingX = 10;
55-
public static readonly paddingY = 5;
56-
57-
public render() {
58-
const {branch, commit} = this.props;
59-
if (!branch.style.label.display) return null;
60-
61-
if (!this.props.gitgraph.branchLabelOnEveryCommit) {
62-
const commitHash = this.props.gitgraph.refs.getCommit(branch.name);
63-
if (commit.hash !== commitHash) return null;
64-
}
65-
66-
// For the moment, we don't handle multiple branch labels.
67-
// To do so, we'd need to reposition each of them appropriately.
68-
if (commit.branchToDisplay !== branch.name) return null;
69-
70-
const ref = this.createBranchLabelRef(commit);
71-
const branchLabel = branch.renderLabel ? (
72-
branch.renderLabel(branch)
73-
) : (
74-
<DefaultBranchLabel branch={branch} commit={commit} />
75-
);
53+
export interface CompoundedComponent extends React.ForwardRefExoticComponent<BranchLabelProps> {
54+
paddingX: number;
55+
paddingY: number;
56+
}
7657

77-
if (this.props.gitgraph.isVertical) {
78-
return (
79-
<g ref={ref}>
80-
{branchLabel}
81-
</g>
82-
);
83-
} else {
84-
const commitDotSize = commit.style.dot.size * 2;
85-
const horizontalMarginTop = 10;
86-
const y = commitDotSize + horizontalMarginTop;
58+
export const BranchLabel = React.forwardRef<SVGGElement, BranchLabelProps>((props, ref) => {
59+
const {branch, commit, branchLabelX} = props;
60+
if (!branch.style.label.display) return null;
8761

88-
return (
89-
<g
90-
ref={ref}
91-
transform={`translate(${commit.x}, ${y})`}
92-
>
93-
{branchLabel}
94-
</g>
95-
);
96-
}
62+
if (!props.gitgraph.branchLabelOnEveryCommit) {
63+
const commitHash = props.gitgraph.refs.getCommit(branch.name);
64+
if (commit.hash !== commitHash) return null;
9765
}
9866

99-
private createBranchLabelRef(
100-
commit: Commit<ReactSvgElement>,
101-
): React.RefObject<SVGGElement> {
102-
const ref = React.createRef<SVGGElement>();
103-
104-
if (!this.props.commitsElements[commit.hashAbbrev]) {
105-
this.props.initCommitElements(commit);
106-
}
67+
// For the moment, we don't handle multiple branch labels.
68+
// To do so, we'd need to reposition each of them appropriately.
69+
if (commit.branchToDisplay !== branch.name) return null;
10770

108-
this.props.commitsElements[commit.hashAbbrev].branchLabel = ref;
71+
const branchLabel = branch.renderLabel ? (
72+
branch.renderLabel(branch)
73+
) : (
74+
<DefaultBranchLabel branch={branch} commit={commit} />
75+
);
10976

110-
return ref;
77+
if (props.gitgraph.isVertical) {
78+
return (
79+
<g ref={ref} transform={`translate(${branchLabelX || 0}, 0)`}>
80+
{branchLabel}
81+
</g>
82+
);
83+
} else {
84+
const commitDotSize = commit.style.dot.size * 2;
85+
const horizontalMarginTop = 10;
86+
const y = commitDotSize + horizontalMarginTop;
87+
88+
return (
89+
<g
90+
ref={ref}
91+
transform={`translate(${commit.x}, ${y})`}
92+
>
93+
{branchLabel}
94+
</g>
95+
);
11196
}
112-
}
97+
}) as CompoundedComponent;
98+
99+
BranchLabel.paddingX = 10;
100+
BranchLabel.paddingY = 5;
+143-88
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,190 @@
11
import * as React from "react";
22
import {
33
GitgraphCore,
4-
Commit,
4+
Commit as CommitCore,
55
Mode,
66
Coordinate,
77
} from "@gitgraph/core";
8-
import { CommitElement, ReactSvgElement } from "./types";
8+
import { ReactSvgElement } from "./types";
99
import { Dot } from "./Dot";
1010
import { Tooltip } from "./Tooltip";
1111
import { Arrow } from "./Arrow";
1212
import { Message } from "./Message";
13-
import { Tag } from "./Tag";
13+
import { Tag, TAG_PADDING_X } from "./Tag";
1414
import { BranchLabel } from "./BranchLabel";
15+
import { MutableRefObject } from "react";
1516

1617
interface CommitsProps {
17-
commits: Array<Commit<ReactSvgElement>>;
18-
commit: Commit<ReactSvgElement>;
19-
currentCommitOver: Commit<ReactSvgElement> | null;
18+
commits: Array<CommitCore<ReactSvgElement>>;
19+
commit: CommitCore<ReactSvgElement>;
20+
currentCommitOver: CommitCore<ReactSvgElement> | null;
2021
gitgraph: GitgraphCore<ReactSvgElement>;
21-
initCommitElements: (commit: Commit<ReactSvgElement>) => void;
22-
commitsElements: {
23-
[commitHash: string]: CommitElement;
24-
};
2522
getWithCommitOffset: (props: any) => Coordinate;
2623
setTooltip: (val: React.ReactElement<SVGGElement> | null) => void;
27-
setCurrentCommitOver: (val: Commit<ReactSvgElement> | null) => void;
24+
setCurrentCommitOver: (val: CommitCore<ReactSvgElement> | null) => void;
25+
commitMessagesX: number;
2826
}
2927

30-
export class CommitComp extends React.Component<CommitsProps, {}> {
31-
public render() {
32-
const commit = this.props.commit;
33-
const { x, y } = this.props.getWithCommitOffset(commit);
34-
35-
const shouldRenderTooltip =
36-
this.props.currentCommitOver === commit &&
37-
(this.props.gitgraph.isHorizontal ||
38-
(this.props.gitgraph.mode === Mode.Compact &&
39-
commit.style.hasTooltipInCompactMode));
40-
41-
if (shouldRenderTooltip) {
42-
this.props.setTooltip(
43-
<g transform={`translate(${x}, ${y})`}>
44-
<Tooltip commit={commit}>
45-
{commit.hashAbbrev} - {commit.subject}
46-
</Tooltip>
47-
</g>,
48-
);
49-
}
28+
export const Commit = (props: CommitsProps) => {
29+
const {commit, commits, gitgraph, commitMessagesX} = props;
5030

51-
return (
52-
<g transform={`translate(${x}, ${y})`}>
53-
<Dot
54-
commit={commit}
55-
onMouseOver={() => {
56-
this.props.setCurrentCommitOver(commit);
57-
commit.onMouseOver();
58-
}}
59-
onMouseOut={() => {
60-
this.props.setCurrentCommitOver(null);
61-
this.props.setTooltip(null);
62-
commit.onMouseOut();
63-
}}
64-
/>
65-
{this.props.gitgraph.template.arrow.size && this.renderArrows(commit)}
66-
67-
{/* These elements are positionned after component update. */}
68-
<g transform={`translate(${-x}, 0)`}>
69-
{
70-
commit.style.message.display &&
71-
<Message
72-
commit={commit}
73-
commitsElements={this.props.commitsElements}
74-
initCommitElements={this.props.initCommitElements}
75-
/>
76-
}
77-
{this.renderBranchLabels(commit)}
78-
{this.renderTags(commit)}
79-
</g>
80-
</g>
81-
);
82-
}
31+
/**
32+
* This _should_ likely be an array, but is not in order to intentionally keep
33+
* a potential bug in the codebase that existed prior to Hook-ifying this component
34+
* @see https://github.com/nicoespeon/gitgraph.js/blob/be9cdf45c7f00970e68e1a4ba579ca7f5c672da4/packages/gitgraph-react/src/Gitgraph.tsx#L197
35+
* (notice that it's a single `null` value instead of an array
36+
*
37+
* The potential bug in question is "what happens when there are more than one
38+
* branch label rendered? Do they overlap or cause the message X position to be
39+
* in the wrong position?"
40+
*
41+
* TODO: Investigate potential bug outlined above
42+
*/
43+
const branchLabelRef = React.useRef<SVGGElement>();
44+
const tagRefs: MutableRefObject<SVGGElement[]> = React.useRef([]);
45+
// "as unknown as any" needed to avoid `ref` mistypings later. :(
46+
const messageRef: MutableRefObject<SVGGElement> = React.useRef<SVGGElement>() as unknown as any;
47+
48+
const [branchLabelX, setBranchLabelX] = React.useState(0);
49+
const [tagXs, setTagXs] = React.useState<number[]>([]);
50+
const [messageX, setMessageX] = React.useState(0);
8351

84-
private renderArrows(commit: Commit<ReactSvgElement>) {
52+
const arrows = React.useMemo(() => {
53+
if (!gitgraph.template.arrow.size) return null;
8554
const commitRadius = commit.style.dot.size;
8655

8756
return commit.parents.map((parentHash: string) => {
8857
return (
8958
<Arrow
9059
key={parentHash}
91-
commits={this.props.commits}
60+
commits={commits}
9261
commit={commit}
93-
gitgraph={this.props.gitgraph}
62+
gitgraph={gitgraph}
9463
parentHash={parentHash}
9564
commitRadius={commitRadius}
9665
/>
9766
);
9867
});
99-
}
68+
}, [commits, commit, gitgraph]);
10069

70+
const branchLabels = React.useMemo(() => {
71+
// @gitgraph/core could compute branch labels into commits directly.
72+
// That will make it easier to retrieve them, just like tags.
73+
const branches = Array.from(gitgraph.branches.values());
74+
return branches.map((branch) => {
75+
return (
76+
<BranchLabel
77+
key={branch.name}
78+
gitgraph={gitgraph}
79+
branch={branch}
80+
commit={commit}
81+
ref={branchLabelRef}
82+
branchLabelX={branchLabelX}
83+
/>
84+
);
85+
});
86+
}, [gitgraph, commit, branchLabelX])
10187

102-
private renderTags(commit: Commit<ReactSvgElement>) {
88+
const tags = React.useMemo(() => {
89+
tagRefs.current = [];
10390
if (!commit.tags) return null;
104-
if (this.props.gitgraph.isHorizontal) return null;
91+
if (gitgraph.isHorizontal) return null;
10592

106-
return commit.tags.map((tag) =>
93+
return commit.tags.map((tag, i) =>
10794
<Tag
10895
key={`${commit.hashAbbrev}-${tag.name}`}
10996
commit={commit}
110-
initCommitElements={this.props.initCommitElements}
111-
commitsElements={this.props.commitsElements}
11297
tag={tag}
98+
ref={r => tagRefs.current[i] = r!}
99+
tagX={tagXs[i] || 0}
113100
/>,
114101
);
115-
}
102+
}, [commit, gitgraph, tagXs])
116103

104+
const { x, y } = props.getWithCommitOffset(commit);
117105

118-
private renderBranchLabels(commit: Commit<ReactSvgElement>) {
119-
// @gitgraph/core could compute branch labels into commits directly.
120-
// That will make it easier to retrieve them, just like tags.
121-
const branches = Array.from(this.props.gitgraph.branches.values());
122-
return branches.map((branch) => {
123-
return (
124-
<BranchLabel
125-
key={branch.name}
126-
gitgraph={this.props.gitgraph}
127-
initCommitElements={this.props.initCommitElements}
128-
commitsElements={this.props.commitsElements}
129-
branch={branch}
130-
commit={commit}
131-
/>
132-
);
106+
// positionCommitsElements
107+
React.useLayoutEffect(() => {
108+
if (gitgraph.isHorizontal) {
109+
// Elements don't appear on horizontal mode, yet.
110+
return;
111+
}
112+
113+
const padding = 10;
114+
115+
let translateX = commitMessagesX;
116+
117+
if (branchLabelRef.current) {
118+
setBranchLabelX(translateX);
119+
120+
// For some reason, one paddingX is missing in BBox width.
121+
const branchLabelWidth =
122+
branchLabelRef.current.getBBox().width + BranchLabel.paddingX;
123+
translateX += branchLabelWidth + padding;
124+
}
125+
126+
const allTagXs = tagRefs.current.map((tag) => {
127+
if (!tag) return 0;
128+
129+
const tagX = translateX;
130+
131+
// For some reason, one paddingX is missing in BBox width.
132+
const tagWidth = tag.getBBox().width + TAG_PADDING_X;
133+
translateX += tagWidth + padding;
134+
135+
return tagX;
133136
});
137+
138+
setTagXs(allTagXs);
139+
140+
if (messageRef.current) {
141+
setMessageX(translateX);
142+
}
143+
}, [tagRefs, gitgraph, commitMessagesX])
144+
145+
const shouldRenderTooltip =
146+
props.currentCommitOver === commit &&
147+
(props.gitgraph.isHorizontal ||
148+
(props.gitgraph.mode === Mode.Compact &&
149+
commit.style.hasTooltipInCompactMode));
150+
151+
if (shouldRenderTooltip) {
152+
props.setTooltip(
153+
<g transform={`translate(${x}, ${y})`}>
154+
<Tooltip commit={commit}>
155+
{commit.hashAbbrev} - {commit.subject}
156+
</Tooltip>
157+
</g>,
158+
);
134159
}
160+
161+
return (
162+
<g transform={`translate(${x}, ${y})`}>
163+
<Dot
164+
commit={commit}
165+
onMouseOver={() => {
166+
props.setCurrentCommitOver(commit);
167+
commit.onMouseOver();
168+
}}
169+
onMouseOut={() => {
170+
props.setCurrentCommitOver(null);
171+
props.setTooltip(null);
172+
commit.onMouseOut();
173+
}}
174+
/>
175+
{arrows}
176+
<g transform={`translate(${-x}, 0)`}>
177+
{
178+
commit.style.message.display &&
179+
<Message
180+
commit={commit}
181+
ref={messageRef}
182+
messageX={messageX}
183+
/>
184+
}
185+
{branchLabels}
186+
{tags}
187+
</g>
188+
</g>
189+
);
135190
}

‎packages/gitgraph-react/src/Gitgraph.tsx

+8-72
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
GitgraphCore,
44
GitgraphOptions,
55
GitgraphUserApi,
6-
Commit,
6+
Commit as CommitCore,
77
MergeStyle,
88
Mode,
99
Orientation,
@@ -15,9 +15,8 @@ import {
1515

1616
import { BranchLabel } from "./BranchLabel";
1717
import { Tooltip } from "./Tooltip";
18-
import { TAG_PADDING_X } from "./Tag";
19-
import { CommitElement, ReactSvgElement, CommitOptions, BranchOptions, TagOptions, MergeOptions, Branch } from "./types";
20-
import { CommitComp } from "./Commit";
18+
import { ReactSvgElement, CommitOptions, BranchOptions, TagOptions, MergeOptions, Branch } from "./types";
19+
import { Commit } from "./Commit";
2120
import { BranchPath } from "./BranchPath";
2221

2322
export {
@@ -54,7 +53,7 @@ function isPropsWithGraph(
5453
}
5554

5655
interface GitgraphState {
57-
commits: Array<Commit<ReactSvgElement>>;
56+
commits: Array<CommitCore<ReactSvgElement>>;
5857
branchesPaths: BranchesPaths<ReactSvgElement>;
5958
commitMessagesX: number;
6059
// Store a map to replace commits y with the correct value,
@@ -63,7 +62,7 @@ interface GitgraphState {
6362
// Offset should be computed when graph is rendered (componentDidUpdate).
6463
commitYWithOffsets: { [key: number]: number };
6564
shouldRecomputeOffsets: boolean;
66-
currentCommitOver: Commit<ReactSvgElement> | null;
65+
currentCommitOver: CommitCore<ReactSvgElement> | null;
6766
}
6867

6968
class Gitgraph extends React.Component<GitgraphProps, GitgraphState> {
@@ -75,9 +74,6 @@ class Gitgraph extends React.Component<GitgraphProps, GitgraphState> {
7574
private $graph = React.createRef<SVGSVGElement>();
7675
private $commits = React.createRef<SVGGElement>();
7776
private $tooltip: React.ReactElement<SVGGElement> | null = null;
78-
private commitsElements: {
79-
[commitHash: string]: CommitElement;
80-
} = {};
8177

8278
constructor(props: GitgraphProps) {
8379
super(props);
@@ -112,17 +108,16 @@ class Gitgraph extends React.Component<GitgraphProps, GitgraphState> {
112108
{this.renderBranchesPaths()}
113109
<g ref={this.$commits}>
114110
{this.state.commits.map((commit) =>
115-
<CommitComp
111+
<Commit
116112
key={commit.hashAbbrev}
117113
commits={this.state.commits}
118114
commit={commit}
119115
currentCommitOver={this.state.currentCommitOver}
120116
setCurrentCommitOver={this.setCurrentCommitOver.bind(this)}
121117
gitgraph={this.gitgraph}
122-
initCommitElements={this.initCommitElements.bind(this)}
123-
commitsElements={this.commitsElements}
124118
getWithCommitOffset={this.getWithCommitOffset.bind(this)}
125119
setTooltip={this.setTooltip.bind(this)}
120+
commitMessagesX={this.state.commitMessagesX}
126121
/>
127122
)}
128123
</g>
@@ -157,16 +152,14 @@ class Gitgraph extends React.Component<GitgraphProps, GitgraphState> {
157152
if (!this.state.shouldRecomputeOffsets) return;
158153
if (!this.$commits.current) return;
159154

160-
this.positionCommitsElements();
161-
162155
const commits = Array.from(this.$commits.current.children);
163156
this.setState({
164157
commitYWithOffsets: this.computeOffsets(commits),
165158
shouldRecomputeOffsets: false,
166159
});
167160
}
168161

169-
private setCurrentCommitOver(v: Commit<ReactSvgElement> | null) {
162+
private setCurrentCommitOver(v: CommitCore<ReactSvgElement> | null) {
170163
this.setState({ currentCommitOver: v });
171164
}
172165

@@ -192,55 +185,6 @@ class Gitgraph extends React.Component<GitgraphProps, GitgraphState> {
192185
));
193186
}
194187

195-
private initCommitElements(commit: Commit<ReactSvgElement>): void {
196-
this.commitsElements[commit.hashAbbrev] = {
197-
branchLabel: null,
198-
tags: [],
199-
message: null,
200-
};
201-
}
202-
203-
private positionCommitsElements(): void {
204-
if (this.gitgraph.isHorizontal) {
205-
// Elements don't appear on horizontal mode, yet.
206-
return;
207-
}
208-
209-
const padding = 10;
210-
211-
// Ensure commits elements (branch labels, message…) are well positionned.
212-
// It can't be done at render time since elements size is dynamic.
213-
Object.keys(this.commitsElements).forEach((commitHash) => {
214-
const { branchLabel, tags, message } = this.commitsElements[commitHash];
215-
216-
// We'll store X position progressively and translate elements.
217-
let x = this.state.commitMessagesX;
218-
219-
if (branchLabel && branchLabel.current) {
220-
moveElement(branchLabel.current, x);
221-
222-
// For some reason, one paddingX is missing in BBox width.
223-
const branchLabelWidth =
224-
branchLabel.current.getBBox().width + BranchLabel.paddingX;
225-
x += branchLabelWidth + padding;
226-
}
227-
228-
tags.forEach((tag) => {
229-
if (!tag || !tag.current) return;
230-
231-
moveElement(tag.current, x);
232-
233-
// For some reason, one paddingX is missing in BBox width.
234-
const tagWidth = tag.current.getBBox().width + TAG_PADDING_X;
235-
x += tagWidth + padding;
236-
});
237-
238-
if (message && message.current) {
239-
moveElement(message.current, x);
240-
}
241-
});
242-
}
243-
244188
private computeOffsets(
245189
commits: Element[],
246190
): GitgraphState["commitYWithOffsets"] {
@@ -299,11 +243,3 @@ class Gitgraph extends React.Component<GitgraphProps, GitgraphState> {
299243
return { x, y: this.state.commitYWithOffsets[y] || y };
300244
}
301245
}
302-
303-
function moveElement(target: Element, x: number): void {
304-
const transform = target.getAttribute("transform") || "translate(0, 0)";
305-
target.setAttribute(
306-
"transform",
307-
transform.replace(/translate\(([\d\.]+),/, `translate(${x},`),
308-
);
309-
}
+7-27
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
import * as React from 'react';
2-
import { CommitElement, ReactSvgElement } from "./types";
2+
import { ReactSvgElement } from "./types";
33
import { Commit } from "@gitgraph/core";
44

55
interface MessageProps {
66
commit: Commit<ReactSvgElement>;
7-
initCommitElements: (commit: Commit<ReactSvgElement>) => void;
8-
commitsElements: {
9-
[commitHash: string]: CommitElement;
10-
};
7+
messageX: number;
118
}
129

13-
export class Message extends React.Component<MessageProps> {
14-
public render() {
15-
const commit = this.props.commit;
16-
const ref = this.createMessageRef(commit);
10+
export const Message = React.forwardRef<SVGGElement, MessageProps>((props, ref) => {
11+
const {commit, messageX} = props;
1712

1813
if (commit.renderMessage) {
19-
return <g ref={ref}>{commit.renderMessage(commit)}</g>;
14+
return <g ref={ref} transform={`translate(${messageX}, 0)`}>{commit.renderMessage(commit)}</g>;
2015
}
2116

2217
let body = null;
@@ -32,7 +27,7 @@ export class Message extends React.Component<MessageProps> {
3227
const y = commit.style.dot.size;
3328

3429
return (
35-
<g ref={ref} transform={`translate(0, ${y})`}>
30+
<g ref={ref} transform={`translate(${messageX}, ${y})`}>
3631
<text
3732
alignmentBaseline="central"
3833
fill={commit.style.message.color}
@@ -44,19 +39,4 @@ export class Message extends React.Component<MessageProps> {
4439
{body}
4540
</g>
4641
);
47-
}
48-
49-
private createMessageRef(
50-
commit: Commit<ReactSvgElement>,
51-
): React.RefObject<SVGGElement> {
52-
const ref = React.createRef<SVGGElement>();
53-
54-
if (!this.props.commitsElements[commit.hashAbbrev]) {
55-
this.props.initCommitElements(commit);
56-
}
57-
58-
this.props.commitsElements[commit.hashAbbrev].message = ref;
59-
60-
return ref;
61-
}
62-
}
42+
});

‎packages/gitgraph-react/src/Tag.tsx

+13-39
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from "react";
22
import { Tag as CoreTag, Commit } from "@gitgraph/core";
3-
import { CommitElement, ReactSvgElement } from "./types";
3+
import { ReactSvgElement } from "./types";
44

55
interface BaseTagProps {
66
tag: CoreTag<React.ReactElement<SVGElement>>;
@@ -60,44 +60,18 @@ function DefaultTag(props: BaseTagProps) {
6060

6161
interface TagProps extends BaseTagProps {
6262
commit: Commit<ReactSvgElement>;
63-
initCommitElements: (commit: Commit<ReactSvgElement>) => void;
64-
commitsElements: {
65-
[commitHash: string]: CommitElement;
66-
};
63+
tagX: number;
6764
}
6865

69-
/**
70-
* This needs to be refactored into a functional component as well - likely
71-
* merged with DefaultTag with an early return instead
72-
*/
73-
export class Tag extends React.Component<TagProps> {
74-
public render() {
75-
const tag = this.props.tag;
76-
const commit = this.props.commit;
77-
const ref = this.createTagRef(commit);
78-
79-
return (
80-
<g
81-
ref={ref}
82-
transform={`translate(0, ${commit.style.dot.size})`}
83-
>
84-
{tag.render ? tag.render(tag.name, tag.style) : <DefaultTag tag={tag} />}
85-
</g>
86-
);
87-
}
88-
89-
private createTagRef(
90-
commit: Commit<ReactSvgElement>,
91-
): React.RefObject<SVGGElement> {
92-
const ref = React.createRef<SVGGElement>();
93-
94-
if (!this.props.commitsElements[commit.hashAbbrev]) {
95-
this.props.initCommitElements(commit);
96-
}
97-
98-
this.props.commitsElements[commit.hashAbbrev].tags.push(ref);
99-
100-
return ref;
101-
}
102-
}
66+
export const Tag = React.forwardRef<SVGGElement, TagProps>((props, ref) => {
67+
const {tag, commit, tagX} = props;
10368

69+
return (
70+
<g
71+
ref={ref}
72+
transform={`translate(${tagX || 0}, ${commit.style.dot.size})`}
73+
>
74+
{tag.render ? tag.render(tag.name, tag.style) : <DefaultTag tag={tag} />}
75+
</g>
76+
);
77+
});

‎packages/gitgraph-react/src/types.ts

-6
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,3 @@ export type BranchOptions = GitgraphBranchOptions<ReactSvgElement>;
1414
export type TagOptions = GitgraphTagOptions<ReactSvgElement>;
1515
export type MergeOptions = GitgraphMergeOptions<ReactSvgElement>;
1616
export type Branch = BranchUserApi<ReactSvgElement>;
17-
18-
export interface CommitElement {
19-
branchLabel: React.RefObject<SVGGElement> | null;
20-
tags: Array<React.RefObject<SVGGElement>>;
21-
message: React.RefObject<SVGGElement> | null;
22-
}

0 commit comments

Comments
 (0)
Please sign in to comment.