@scm-manager/ui-components 3.10.2 → 3.10.3-20250815-132001

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scm-manager/ui-components",
3
- "version": "3.10.2",
3
+ "version": "3.10.3-20250815-132001",
4
4
  "description": "UI Components for SCM-Manager and its plugins",
5
5
  "main": "src/index.ts",
6
6
  "files": [
@@ -32,8 +32,8 @@
32
32
  "react-query": "^3.39.2"
33
33
  },
34
34
  "devDependencies": {
35
- "@scm-manager/ui-tests": "3.10.2",
36
- "@scm-manager/ui-types": "3.10.2",
35
+ "@scm-manager/ui-tests": "3.10.3-20250815-132001",
36
+ "@scm-manager/ui-types": "3.10.3-20250815-132001",
37
37
  "@types/fetch-mock": "^7.3.1",
38
38
  "@types/react-select": "^2.0.19",
39
39
  "@types/unist": "^2.0.3",
@@ -68,17 +68,17 @@
68
68
  "@scm-manager/jest-preset": "^2.14.1",
69
69
  "@scm-manager/prettier-config": "^2.12.0",
70
70
  "@scm-manager/tsconfig": "^2.13.0",
71
- "@scm-manager/ui-syntaxhighlighting": "3.10.2",
72
- "@scm-manager/ui-shortcuts": "3.10.2",
73
- "@scm-manager/ui-text": "3.10.2"
71
+ "@scm-manager/ui-syntaxhighlighting": "3.10.3-20250815-132001",
72
+ "@scm-manager/ui-shortcuts": "3.10.3-20250815-132001",
73
+ "@scm-manager/ui-text": "3.10.3-20250815-132001"
74
74
  },
75
75
  "dependencies": {
76
- "@scm-manager/ui-core": "3.10.2",
77
- "@scm-manager/ui-overlays": "3.10.2",
78
- "@scm-manager/ui-layout": "3.10.2",
79
- "@scm-manager/ui-buttons": "3.10.2",
80
- "@scm-manager/ui-api": "3.10.2",
81
- "@scm-manager/ui-extensions": "3.10.2",
76
+ "@scm-manager/ui-core": "3.10.3-20250815-132001",
77
+ "@scm-manager/ui-overlays": "3.10.3-20250815-132001",
78
+ "@scm-manager/ui-layout": "3.10.3-20250815-132001",
79
+ "@scm-manager/ui-buttons": "3.10.3-20250815-132001",
80
+ "@scm-manager/ui-api": "3.10.3-20250815-132001",
81
+ "@scm-manager/ui-extensions": "3.10.3-20250815-132001",
82
82
  "deepmerge": "^4.2.2",
83
83
  "hast-util-sanitize": "^3.0.2",
84
84
  "react-diff-view": "^2.4.10",
@@ -14,9 +14,9 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
- import { ReactNode } from "react";
17
+ import { FC, ReactNode } from "react";
18
18
  import { DefaultCollapsed } from "./defaultCollapsed";
19
- import { Change, Hunk, FileDiff as File } from "@scm-manager/ui-types";
19
+ import { Change, Hunk, FileDiff as File, FileChangeType } from "@scm-manager/ui-types";
20
20
 
21
21
  export type ChangeEvent = {
22
22
  change: Change;
@@ -31,6 +31,18 @@ export type AnnotationFactoryContext = BaseContext;
31
31
 
32
32
  export type FileAnnotationFactory = (file: File) => ReactNode[];
33
33
 
34
+ export type FileTreeNodeWrapper = FC<{
35
+ name: string;
36
+ path: string;
37
+ changeType?: FileChangeType;
38
+ iconName: string;
39
+ iconColor: string;
40
+ isFile: boolean;
41
+ originalIcon: ReactNode;
42
+ originalLabel: ReactNode;
43
+ isCurrentFile: boolean;
44
+ }>;
45
+
34
46
  // key = change id, value = react component
35
47
  export type AnnotationFactory = (context: AnnotationFactoryContext) => {
36
48
  [key: string]: any;
@@ -18,12 +18,19 @@ import React, { FC } from "react";
18
18
  import { Link } from "react-router-dom";
19
19
  import { useTranslation } from "react-i18next";
20
20
  import classNames from "classnames";
21
- import { FileTree } from "@scm-manager/ui-types";
21
+ import { FileChangeType, FileTree } from "@scm-manager/ui-types";
22
22
  import { FileDiffContent, StackedSpan, StyledIcon } from "./styledElements";
23
+ import { FileTreeNodeWrapper } from "../DiffTypes";
23
24
 
24
- type Props = { tree: FileTree; currentFile: string; setCurrentFile: (path: string) => void; gap?: number };
25
+ type Props = {
26
+ tree: FileTree;
27
+ currentFile: string;
28
+ setCurrentFile: (path: string) => void;
29
+ gap?: number;
30
+ FileTreeNodeWrapper?: FileTreeNodeWrapper;
31
+ };
25
32
 
26
- const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15 }) => {
33
+ const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15, FileTreeNodeWrapper }) => {
27
34
  return (
28
35
  <FileDiffContent gap={gap}>
29
36
  {Object.keys(tree.children).map((key) => (
@@ -33,6 +40,7 @@ const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15 }
33
40
  parentPath=""
34
41
  currentFile={currentFile}
35
42
  setCurrentFile={setCurrentFile}
43
+ FileTreeNodeWrapper={FileTreeNodeWrapper}
36
44
  />
37
45
  ))}
38
46
  </FileDiffContent>
@@ -41,9 +49,13 @@ const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15 }
41
49
 
42
50
  export default DiffFileTree;
43
51
 
44
- type ChangeType = "add" | "modify" | "delete" | "rename" | "copy";
45
-
46
- type NodeProps = { node: FileTree; parentPath: string; currentFile: string; setCurrentFile: (path: string) => void };
52
+ type NodeProps = {
53
+ node: FileTree;
54
+ parentPath: string;
55
+ currentFile: string;
56
+ setCurrentFile: (path: string) => void;
57
+ FileTreeNodeWrapper?: FileTreeNodeWrapper;
58
+ };
47
59
 
48
60
  const addPath = (parentPath: string, path: string) => {
49
61
  if ("" === parentPath) {
@@ -52,16 +64,31 @@ const addPath = (parentPath: string, path: string) => {
52
64
  return parentPath + "/" + path;
53
65
  };
54
66
 
55
- const TreeNode: FC<NodeProps> = ({ node, parentPath, currentFile, setCurrentFile }) => {
67
+ const TreeNode: FC<NodeProps> = ({ node, parentPath, currentFile, setCurrentFile, FileTreeNodeWrapper }) => {
56
68
  const [t] = useTranslation("repos");
57
69
 
70
+ FileTreeNodeWrapper = FileTreeNodeWrapper || (({ children }) => <>{children}</>);
71
+
72
+ const label = <div className="ml-1">{node.nodeName}</div>;
73
+ const icon = <StyledIcon alt={t("diff.showContent")}>folder</StyledIcon>;
58
74
  return (
59
75
  <li>
60
76
  {Object.keys(node.children).length > 0 ? (
61
77
  <ul className="py-1 pl-3">
62
78
  <li className="is-flex has-text-grey">
63
- <StyledIcon alt={t("diff.showContent")}>folder</StyledIcon>
64
- <div className="ml-1">{node.nodeName}</div>
79
+ <FileTreeNodeWrapper
80
+ path={addPath(parentPath, node.nodeName)}
81
+ isFile={false}
82
+ isCurrentFile={false}
83
+ name={node.nodeName}
84
+ iconName={"folder"}
85
+ iconColor={"grey"}
86
+ originalIcon={icon}
87
+ originalLabel={label}
88
+ >
89
+ {icon}
90
+ {label}
91
+ </FileTreeNodeWrapper>
65
92
  </li>
66
93
  {Object.keys(node.children).map((key) => (
67
94
  <TreeNode
@@ -70,23 +97,25 @@ const TreeNode: FC<NodeProps> = ({ node, parentPath, currentFile, setCurrentFile
70
97
  parentPath={addPath(parentPath, node.nodeName)}
71
98
  currentFile={currentFile}
72
99
  setCurrentFile={setCurrentFile}
100
+ FileTreeNodeWrapper={FileTreeNodeWrapper}
73
101
  />
74
102
  ))}
75
103
  </ul>
76
104
  ) : (
77
105
  <TreeFile
78
- changeType={node.changeType.toLowerCase() as ChangeType}
106
+ changeType={node.changeType.toLowerCase() as FileChangeType}
79
107
  path={node.nodeName}
80
108
  parentPath={parentPath}
81
109
  currentFile={currentFile}
82
110
  setCurrentFile={setCurrentFile}
111
+ FileTreeNodeWrapper={FileTreeNodeWrapper}
83
112
  />
84
113
  )}
85
114
  </li>
86
115
  );
87
116
  };
88
117
 
89
- const getColor = (changeType: ChangeType) => {
118
+ const getColor = (changeType: FileChangeType) => {
90
119
  switch (changeType) {
91
120
  case "add":
92
121
  return "success";
@@ -99,7 +128,7 @@ const getColor = (changeType: ChangeType) => {
99
128
  }
100
129
  };
101
130
 
102
- const getIcon = (changeType: ChangeType) => {
131
+ const getIcon = (changeType: FileChangeType) => {
103
132
  switch (changeType) {
104
133
  case "add":
105
134
  case "copy":
@@ -113,14 +142,22 @@ const getIcon = (changeType: ChangeType) => {
113
142
  };
114
143
 
115
144
  type FileProps = {
116
- changeType: ChangeType;
145
+ changeType: FileChangeType;
117
146
  path: string;
118
147
  parentPath: string;
119
148
  currentFile: string;
120
149
  setCurrentFile: (path: string) => void;
150
+ FileTreeNodeWrapper: FileTreeNodeWrapper;
121
151
  };
122
152
 
123
- const TreeFile: FC<FileProps> = ({ changeType, path, parentPath, currentFile, setCurrentFile }) => {
153
+ const TreeFile: FC<FileProps> = ({
154
+ changeType,
155
+ path,
156
+ parentPath,
157
+ currentFile,
158
+ setCurrentFile,
159
+ FileTreeNodeWrapper,
160
+ }) => {
124
161
  const [t] = useTranslation("repos");
125
162
  const completePath = addPath(parentPath, path);
126
163
 
@@ -128,35 +165,50 @@ const TreeFile: FC<FileProps> = ({ changeType, path, parentPath, currentFile, se
128
165
  return currentFile === completePath;
129
166
  };
130
167
 
168
+ const iconName = getIcon(changeType);
169
+
170
+ const icon = (
171
+ <StackedSpan className="fa-stack">
172
+ <StyledIcon
173
+ className={classNames("fa-stack-2x", `has-text-${getColor(changeType)}`)}
174
+ key={completePath + "file"}
175
+ type="fas"
176
+ alt={t("diff.showContent")}
177
+ >
178
+ file
179
+ </StyledIcon>
180
+ <StyledIcon
181
+ className={classNames("fa-stack-1x", "is-relative", "has-text-secondary-least")}
182
+ isSmaller={iconName === "circle"}
183
+ key={changeType}
184
+ alt={t(`diff.changes.${changeType}`)}
185
+ >
186
+ {iconName}
187
+ </StyledIcon>
188
+ </StackedSpan>
189
+ );
190
+ const label = <div className={classNames("ml-1", isCurrentFile() ? "has-text-weight-bold" : "")}>{path}</div>;
191
+
131
192
  return (
132
193
  <Link
133
194
  className="is-flex py-1 pl-3 has-cursor-pointer"
134
195
  onClick={() => setCurrentFile(completePath)}
135
196
  to={`#diff-${encodeURIComponent(completePath)}`}
136
197
  >
137
- <StackedSpan className="fa-stack">
138
- <StyledIcon
139
- className={classNames("fa-stack-2x", `has-text-${getColor(changeType)}`)}
140
- key={completePath + "file"}
141
- type={isCurrentFile() ? "fas" : "far"}
142
- alt={t("diff.showContent")}
143
- >
144
- file
145
- </StyledIcon>
146
- <StyledIcon
147
- className={classNames(
148
- "fa-stack-1x",
149
- "is-relative",
150
- isCurrentFile() ? "has-text-secondary-least" : `has-text-${getColor(changeType)}`
151
- )}
152
- isSmaller={getIcon(changeType) === "circle"}
153
- key={changeType}
154
- alt={t(`diff.changes.${changeType}`)}
155
- >
156
- {getIcon(changeType)}
157
- </StyledIcon>
158
- </StackedSpan>
159
- <div className="ml-1">{path}</div>
198
+ <FileTreeNodeWrapper
199
+ name={path}
200
+ path={completePath}
201
+ changeType={changeType}
202
+ isFile={true}
203
+ iconName={iconName}
204
+ iconColor={getColor(changeType)}
205
+ originalIcon={icon}
206
+ originalLabel={label}
207
+ isCurrentFile={isCurrentFile()}
208
+ >
209
+ {icon}
210
+ {label}
211
+ </FileTreeNodeWrapper>
160
212
  </Link>
161
213
  );
162
214
  };