@scm-manager/ui-components 3.10.2-20250728-184027 → 3.10.2-20250802-135601

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-20250728-184027",
3
+ "version": "3.10.2-20250802-135601",
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-20250728-184027",
36
- "@scm-manager/ui-types": "3.10.2-20250728-184027",
35
+ "@scm-manager/ui-tests": "3.10.2-20250802-135601",
36
+ "@scm-manager/ui-types": "3.10.2-20250802-135601",
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-20250728-184027",
72
- "@scm-manager/ui-shortcuts": "3.10.2-20250728-184027",
73
- "@scm-manager/ui-text": "3.10.2-20250728-184027"
71
+ "@scm-manager/ui-syntaxhighlighting": "3.10.2-20250802-135601",
72
+ "@scm-manager/ui-shortcuts": "3.10.2-20250802-135601",
73
+ "@scm-manager/ui-text": "3.10.2-20250802-135601"
74
74
  },
75
75
  "dependencies": {
76
- "@scm-manager/ui-core": "3.10.2-20250728-184027",
77
- "@scm-manager/ui-overlays": "3.10.2-20250728-184027",
78
- "@scm-manager/ui-layout": "3.10.2-20250728-184027",
79
- "@scm-manager/ui-buttons": "3.10.2-20250728-184027",
80
- "@scm-manager/ui-api": "3.10.2-20250728-184027",
81
- "@scm-manager/ui-extensions": "3.10.2-20250728-184027",
76
+ "@scm-manager/ui-core": "3.10.2-20250802-135601",
77
+ "@scm-manager/ui-overlays": "3.10.2-20250802-135601",
78
+ "@scm-manager/ui-layout": "3.10.2-20250802-135601",
79
+ "@scm-manager/ui-buttons": "3.10.2-20250802-135601",
80
+ "@scm-manager/ui-api": "3.10.2-20250802-135601",
81
+ "@scm-manager/ui-extensions": "3.10.2-20250802-135601",
82
82
  "deepmerge": "^4.2.2",
83
83
  "hast-util-sanitize": "^3.0.2",
84
84
  "react-diff-view": "^2.4.10",
@@ -20389,7 +20389,7 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
20389
20389
  className="media-left mt-2 mr-2"
20390
20390
  >
20391
20391
  <div
20392
- className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 dLAXC image"
20392
+ className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 gwbxYG image"
20393
20393
  >
20394
20394
  <img
20395
20395
  alt="SCM Administrator"
@@ -20448,6 +20448,7 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
20448
20448
  <img
20449
20449
  alt="Ford Prefect"
20450
20450
  className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
20451
+ crossOrigin="anonymous"
20451
20452
  src="https://robohash.org/ford.prefect@hitchhiker.com"
20452
20453
  />
20453
20454
  </a>
@@ -20458,6 +20459,7 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
20458
20459
  <img
20459
20460
  alt="Zaphod Beeblebrox"
20460
20461
  className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
20462
+ crossOrigin="anonymous"
20461
20463
  src="https://robohash.org/zaphod.beeblebrox@hitchhiker.cm"
20462
20464
  />
20463
20465
  </a>
@@ -20468,6 +20470,7 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
20468
20470
  <img
20469
20471
  alt="Tricia Marie McMillan"
20470
20472
  className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
20473
+ crossOrigin="anonymous"
20471
20474
  src="https://robohash.org/trillian@hitchhiker.cm"
20472
20475
  />
20473
20476
  </a>
@@ -20564,7 +20567,7 @@ exports[`Storyshots Repositories/Changesets Commiter and Co-Authors with avatar
20564
20567
  className="media-left mt-2 mr-2"
20565
20568
  >
20566
20569
  <div
20567
- className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 dLAXC image"
20570
+ className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 gwbxYG image"
20568
20571
  >
20569
20572
  <img
20570
20573
  alt="SCM Administrator"
@@ -20618,6 +20621,7 @@ exports[`Storyshots Repositories/Changesets Commiter and Co-Authors with avatar
20618
20621
  <img
20619
20622
  alt="Zaphod Beeblebrox"
20620
20623
  className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
20624
+ crossOrigin="anonymous"
20621
20625
  src="https://robohash.org/zaphod.beeblebrox@hitchhiker.cm"
20622
20626
  />
20623
20627
  </a>
@@ -20633,6 +20637,7 @@ exports[`Storyshots Repositories/Changesets Commiter and Co-Authors with avatar
20633
20637
  <img
20634
20638
  alt="Ford Prefect"
20635
20639
  className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
20640
+ crossOrigin="anonymous"
20636
20641
  src="https://robohash.org/ford.prefect@hitchhiker.com"
20637
20642
  />
20638
20643
  </a>
@@ -21637,7 +21642,7 @@ exports[`Storyshots Repositories/Changesets With avatar 1`] = `
21637
21642
  className="media-left mt-2 mr-2"
21638
21643
  >
21639
21644
  <div
21640
- className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 dLAXC image"
21645
+ className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 gwbxYG image"
21641
21646
  >
21642
21647
  <img
21643
21648
  alt="SCM Administrator"
@@ -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;
@@ -57,11 +57,11 @@ const ContributorWithAvatar: FC<PersonAvatarProps> = ({ person, avatar }) => {
57
57
  if (person.mail) {
58
58
  return (
59
59
  <a href={"mailto:" + person.mail} title={t("changeset.contributors.mailto") + " " + person.mail}>
60
- <ContributorAvatar src={avatar} alt={person.name} />
60
+ <ContributorAvatar src={avatar} alt={person.name} crossOrigin="anonymous" />
61
61
  </a>
62
62
  );
63
63
  }
64
- return <ContributorAvatar src={avatar} alt={person.name} title={person.name} />;
64
+ return <ContributorAvatar src={avatar} alt={person.name} title={person.name} crossOrigin="anonymous" />;
65
65
  };
66
66
 
67
67
  export const SingleContributor: FC<PersonProps> = ({ person, className, displayTextOnly }) => {
@@ -37,7 +37,7 @@ type Props = {
37
37
  const FixedSizedAvatar = styled.div`
38
38
  width: 35px;
39
39
  height: 35px;
40
- min-width: fit-content;
40
+ overflow: hidden;
41
41
  `;
42
42
 
43
43
  const FullWidthDiv = styled.div`
@@ -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
  };