@scm-manager/ui-core 3.6.1 → 3.7.0
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/.storybook/main.js +4 -2
- package/.storybook/preview.js +8 -8
- package/.turbo/turbo-typecheck.log +1 -1
- package/package.json +3 -3
- package/src/base/buttons/Button.tsx +2 -0
- package/src/base/buttons/index.ts +1 -1
- package/src/base/helpers/index.ts +1 -0
- package/src/base/helpers/useDocumentTitle.test.ts +48 -0
- package/src/base/helpers/useDocumentTitle.ts +51 -0
- package/src/base/misc/Title.tsx +1 -11
package/.storybook/main.js
CHANGED
|
@@ -22,7 +22,6 @@ const ReactDOM = require("react-dom");
|
|
|
22
22
|
|
|
23
23
|
const root = path.resolve("..");
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
const themedir = path.join(root, "ui-styles", "src");
|
|
27
26
|
|
|
28
27
|
ReactDOM.createPortal = (node) => node;
|
|
@@ -46,7 +45,7 @@ module.exports = {
|
|
|
46
45
|
"@storybook/addon-essentials",
|
|
47
46
|
"@storybook/addon-interactions",
|
|
48
47
|
"@storybook/addon-a11y",
|
|
49
|
-
"storybook-addon-pseudo-states"
|
|
48
|
+
"storybook-addon-pseudo-states",
|
|
50
49
|
],
|
|
51
50
|
framework: "@storybook/react",
|
|
52
51
|
webpackFinal: async (config) => {
|
|
@@ -75,6 +74,9 @@ module.exports = {
|
|
|
75
74
|
// to filter our themes from the output.
|
|
76
75
|
config.plugins.push(new RemoveThemesPlugin());
|
|
77
76
|
|
|
77
|
+
// force node version of "decode-named-character-reference" instead of browser version which does not work in web worker
|
|
78
|
+
config.resolve.alias["decode-named-character-reference"] = require.resolve("decode-named-character-reference");
|
|
79
|
+
|
|
78
80
|
// force cjs instead of esm
|
|
79
81
|
// https://github.com/tannerlinsley/react-query/issues/3513
|
|
80
82
|
config.resolve.alias["react-query/devtools"] = require.resolve("react-query/devtools");
|
package/.storybook/preview.js
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
import i18next from "i18next";
|
|
18
18
|
import { initReactI18next } from "react-i18next";
|
|
19
19
|
import { withI18next } from "storybook-addon-i18next";
|
|
20
|
-
import React, {useEffect} from "react";
|
|
20
|
+
import React, { useEffect } from "react";
|
|
21
21
|
import withApiProvider from "./withApiProvider";
|
|
22
|
-
import { withThemes } from
|
|
22
|
+
import { withThemes } from "storybook-addon-themes/react";
|
|
23
23
|
|
|
24
24
|
let i18n = i18next;
|
|
25
25
|
|
|
@@ -27,7 +27,7 @@ let i18n = i18next;
|
|
|
27
27
|
// and not for storyshots
|
|
28
28
|
if (!process.env.JEST_WORKER_ID) {
|
|
29
29
|
const Backend = require("i18next-fetch-backend");
|
|
30
|
-
i18n = i18n.use(Backend
|
|
30
|
+
i18n = i18n.use(Backend);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
i18n.use(initReactI18next).init({
|
|
@@ -58,18 +58,18 @@ export const decorators = [
|
|
|
58
58
|
},
|
|
59
59
|
}),
|
|
60
60
|
withApiProvider,
|
|
61
|
-
withThemes
|
|
61
|
+
withThemes,
|
|
62
62
|
];
|
|
63
63
|
|
|
64
|
-
const Decorator = ({children, themeName}) => {
|
|
64
|
+
const Decorator = ({ children, themeName }) => {
|
|
65
65
|
useEffect(() => {
|
|
66
66
|
const link = document.querySelector("#ui-theme");
|
|
67
67
|
if (link && link["data-theme"] !== themeName) {
|
|
68
|
-
link.href =
|
|
68
|
+
link.href = `/ui-theme-${themeName}.css`;
|
|
69
69
|
link["data-theme"] = themeName;
|
|
70
70
|
}
|
|
71
71
|
}, [themeName]);
|
|
72
|
-
return <>{children}
|
|
72
|
+
return <>{children}</>;
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
export const parameters = {
|
|
@@ -83,5 +83,5 @@ export const parameters = {
|
|
|
83
83
|
{ name: "highcontrast", color: "#050514" },
|
|
84
84
|
{ name: "dark", color: "#121212" },
|
|
85
85
|
],
|
|
86
|
-
}
|
|
86
|
+
},
|
|
87
87
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
@scm-manager/ui-core:typecheck: cache hit, replaying output
|
|
1
|
+
@scm-manager/ui-core:typecheck: cache hit, replaying output c71948b9c8540fde
|
|
2
2
|
@scm-manager/ui-core:typecheck: $ tsc
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scm-manager/ui-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"main": "./src/index.ts",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"scripts": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"styled-components": "5"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@scm-manager/ui-api": "3.
|
|
23
|
+
"@scm-manager/ui-api": "3.7.0",
|
|
24
24
|
"@radix-ui/react-radio-group": "^1.1.3",
|
|
25
25
|
"@radix-ui/react-slot": "^1.0.1",
|
|
26
26
|
"@radix-ui/react-visually-hidden": "^1.0.3",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@scm-manager/eslint-config": "^2.17.0",
|
|
38
38
|
"@scm-manager/tsconfig": "^2.12.0",
|
|
39
39
|
"@scm-manager/babel-preset": "^2.13.1",
|
|
40
|
-
"@scm-manager/ui-types": "3.
|
|
40
|
+
"@scm-manager/ui-types": "3.7.0",
|
|
41
41
|
"@types/mousetrap": "1.6.5",
|
|
42
42
|
"@testing-library/react-hooks": "8.0.1",
|
|
43
43
|
"@testing-library/react": "12.1.5",
|
|
@@ -29,6 +29,7 @@ export const ButtonVariants = {
|
|
|
29
29
|
SECONDARY: "secondary",
|
|
30
30
|
TERTIARY: "tertiary",
|
|
31
31
|
SIGNAL: "signal",
|
|
32
|
+
INFO: "info",
|
|
32
33
|
} as const;
|
|
33
34
|
|
|
34
35
|
export const ButtonVariantList = Object.values(ButtonVariants);
|
|
@@ -41,6 +42,7 @@ const createButtonClasses = (variant?: ButtonVariant, isLoading?: boolean) =>
|
|
|
41
42
|
"is-primary is-outlined": variant === "secondary",
|
|
42
43
|
"is-primary is-inverted": variant === "tertiary",
|
|
43
44
|
"is-warning": variant === "signal",
|
|
45
|
+
"is-info is-outlined": variant === "info",
|
|
44
46
|
"is-loading": isLoading,
|
|
45
47
|
});
|
|
46
48
|
|
|
@@ -14,5 +14,5 @@
|
|
|
14
14
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
export { Button, LinkButton, ExternalLinkButton, ExternalLink, ButtonVariants } from "./Button";
|
|
17
|
+
export { Button, LinkButton, IconButton, ExternalLinkButton, ExternalLink, ButtonVariants } from "./Button";
|
|
18
18
|
export { default as Icon } from "./Icon";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2020 - present Cloudogu GmbH
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU Affero General Public License as published by the Free
|
|
6
|
+
* Software Foundation, version 3.
|
|
7
|
+
*
|
|
8
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
9
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
10
|
+
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
11
|
+
* details.
|
|
12
|
+
*
|
|
13
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
14
|
+
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { renderHook } from "@testing-library/react-hooks";
|
|
18
|
+
import { Repository } from "@scm-manager/ui-types";
|
|
19
|
+
import { binder } from "@scm-manager/ui-extensions";
|
|
20
|
+
import useDocumentTitle, { useDocumentTitleForRepository } from "./useDocumentTitle";
|
|
21
|
+
|
|
22
|
+
describe("useDocumentTitle", () => {
|
|
23
|
+
it("should set document title", () => {
|
|
24
|
+
renderHook(() => useDocumentTitle("Part1", "Part2"));
|
|
25
|
+
expect(document.title).toBe("Part1 - Part2 - SCM-Manager");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should append title if extension is a string", () => {
|
|
29
|
+
binder.getExtension = () => ({ documentTitle: "myInstance" });
|
|
30
|
+
renderHook(() => useDocumentTitle("Part1", "Part2"));
|
|
31
|
+
expect(document.title).toBe("Part1 - Part2 - SCM-Manager (myInstance)");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should modify title if extension is a function", () => {
|
|
35
|
+
binder.getExtension = () => ({ documentTitle: (title: string) => `Modified: ${title}` });
|
|
36
|
+
renderHook(() => useDocumentTitle("Part1", "Part2"));
|
|
37
|
+
expect(document.title).toBe("Modified: Part1 - Part2 - SCM-Manager");
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe("useDocumentTitleForRepository", () => {
|
|
42
|
+
const repository: Repository = { namespace: "namespace", name: "name" } as Repository;
|
|
43
|
+
|
|
44
|
+
it("should set the document title for a repository", () => {
|
|
45
|
+
renderHook(() => useDocumentTitleForRepository(repository, "Part1", "Part2"));
|
|
46
|
+
expect(document.title).toBe("Part1 - Part2 - namespace/name - SCM-Manager");
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2020 - present Cloudogu GmbH
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU Affero General Public License as published by the Free
|
|
6
|
+
* Software Foundation, version 3.
|
|
7
|
+
*
|
|
8
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
9
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
10
|
+
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
11
|
+
* details.
|
|
12
|
+
*
|
|
13
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
14
|
+
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { useEffect } from "react";
|
|
18
|
+
import { binder, extensionPoints } from "@scm-manager/ui-extensions";
|
|
19
|
+
import { Repository } from "@scm-manager/ui-types";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook to set the document title.
|
|
23
|
+
*
|
|
24
|
+
* @param titleParts - An array of title parts to be joined.
|
|
25
|
+
* Title parts should be sorted with the highest specificity first.
|
|
26
|
+
*/
|
|
27
|
+
export default function useDocumentTitle(...titleParts: string[]) {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const extension = binder.getExtension<extensionPoints.DocumentTitleExtensionPoint>("document.title");
|
|
30
|
+
let title = `${titleParts.join(" - ")} - SCM-Manager`;
|
|
31
|
+
if (extension) {
|
|
32
|
+
if (typeof extension.documentTitle === "string") {
|
|
33
|
+
title += ` (${extension.documentTitle})`;
|
|
34
|
+
} else if (typeof extension.documentTitle === "function") {
|
|
35
|
+
title = extension.documentTitle(title);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
document.title = title;
|
|
39
|
+
}, [titleParts]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Hook to set the document title for a repository.
|
|
44
|
+
*
|
|
45
|
+
* @param repository - The repository for which the title should be set.
|
|
46
|
+
* @param titleParts - An array of title parts to be joined.
|
|
47
|
+
* Title parts should be sorted with the highest specificity first.
|
|
48
|
+
*/
|
|
49
|
+
export function useDocumentTitleForRepository(repository: Repository, ...titleParts: string[]) {
|
|
50
|
+
useDocumentTitle(...titleParts, repository.namespace + "/" + repository.name);
|
|
51
|
+
}
|
package/src/base/misc/Title.tsx
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import React, { HTMLAttributes
|
|
17
|
+
import React, { HTMLAttributes } from "react";
|
|
18
18
|
import classNames from "classnames";
|
|
19
19
|
|
|
20
20
|
type Props = {
|
|
@@ -24,16 +24,6 @@ type Props = {
|
|
|
24
24
|
};
|
|
25
25
|
const Title = React.forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement> & Props>(
|
|
26
26
|
({ title, customPageTitle, preventRefreshingPageTitle, children, className, ...props }, ref) => {
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (!preventRefreshingPageTitle) {
|
|
29
|
-
if (customPageTitle) {
|
|
30
|
-
document.title = customPageTitle;
|
|
31
|
-
} else if (title) {
|
|
32
|
-
document.title = title;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}, [title, preventRefreshingPageTitle, customPageTitle]);
|
|
36
|
-
|
|
37
27
|
if (children || title) {
|
|
38
28
|
return (
|
|
39
29
|
<h1 className={classNames("title", className)} {...props} ref={ref}>
|