@scm-manager/ui-components 3.7.2-20250119-163935 → 3.7.2

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.7.2-20250119-163935",
3
+ "version": "3.7.2",
4
4
  "description": "UI Components for SCM-Manager and its plugins",
5
5
  "main": "src/index.ts",
6
6
  "files": [
@@ -32,14 +32,14 @@
32
32
  "react-query": "^3.39.2"
33
33
  },
34
34
  "devDependencies": {
35
- "@scm-manager/ui-tests": "3.7.2-20250119-163935",
36
- "@scm-manager/ui-types": "3.7.2-20250119-163935",
35
+ "@scm-manager/ui-tests": "3.7.2",
36
+ "@scm-manager/ui-types": "3.7.2",
37
37
  "@types/fetch-mock": "^7.3.1",
38
38
  "@types/react-select": "^2.0.19",
39
39
  "@types/unist": "^2.0.3",
40
40
  "gitdiff-parser": "^0.2.2",
41
41
  "i18next-fetch-backend": "4",
42
- "webpack": "^5.76.0",
42
+ "webpack": "^5.72.0",
43
43
  "@storybook/addon-actions": "^6.5.10",
44
44
  "@storybook/addon-essentials": "^6.5.10",
45
45
  "@storybook/addon-interactions": "^6.5.10",
@@ -67,17 +67,17 @@
67
67
  "@scm-manager/jest-preset": "^2.14.1",
68
68
  "@scm-manager/prettier-config": "^2.12.0",
69
69
  "@scm-manager/tsconfig": "^2.13.0",
70
- "@scm-manager/ui-syntaxhighlighting": "3.7.2-20250119-163935",
71
- "@scm-manager/ui-shortcuts": "3.7.2-20250119-163935",
72
- "@scm-manager/ui-text": "3.7.2-20250119-163935"
70
+ "@scm-manager/ui-syntaxhighlighting": "3.7.2",
71
+ "@scm-manager/ui-shortcuts": "3.7.2",
72
+ "@scm-manager/ui-text": "3.7.2"
73
73
  },
74
74
  "dependencies": {
75
- "@scm-manager/ui-core": "3.7.2-20250119-163935",
76
- "@scm-manager/ui-overlays": "3.7.2-20250119-163935",
77
- "@scm-manager/ui-layout": "3.7.2-20250119-163935",
78
- "@scm-manager/ui-buttons": "3.7.2-20250119-163935",
79
- "@scm-manager/ui-api": "3.7.2-20250119-163935",
80
- "@scm-manager/ui-extensions": "3.7.2-20250119-163935",
75
+ "@scm-manager/ui-core": "3.7.2",
76
+ "@scm-manager/ui-overlays": "3.7.2",
77
+ "@scm-manager/ui-layout": "3.7.2",
78
+ "@scm-manager/ui-buttons": "3.7.2",
79
+ "@scm-manager/ui-api": "3.7.2",
80
+ "@scm-manager/ui-extensions": "3.7.2",
81
81
  "deepmerge": "^4.2.2",
82
82
  "hast-util-sanitize": "^3.0.2",
83
83
  "react-diff-view": "^2.4.10",
@@ -78158,18 +78158,11 @@ exports[`Storyshots Secondary Navigation Active when match 1`] = `
78158
78158
  <div>
78159
78159
  <button
78160
78160
  aria-label="secondaryNavigation.hideContent"
78161
- className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label"
78161
+ className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label is-clickable"
78162
78162
  collapsed={false}
78163
78163
  onClick={[Function]}
78164
78164
  type="button"
78165
78165
  >
78166
- <i
78167
- className="SecondaryNavigation__Icon-sc-8p1rgi-1 gqxbcY is-medium"
78168
- >
78169
- <i
78170
- className="fas fa-caret-down"
78171
- />
78172
- </i>
78173
78166
  Hitchhiker
78174
78167
  </button>
78175
78168
  <ul
@@ -78222,7 +78215,7 @@ exports[`Storyshots Secondary Navigation Default 1`] = `
78222
78215
  <div>
78223
78216
  <button
78224
78217
  aria-label="secondaryNavigation.hideContent"
78225
- className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label"
78218
+ className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label is-clickable"
78226
78219
  collapsed={false}
78227
78220
  onClick={[Function]}
78228
78221
  type="button"
@@ -78285,7 +78278,7 @@ exports[`Storyshots Secondary Navigation Extension Point 1`] = `
78285
78278
  <div>
78286
78279
  <button
78287
78280
  aria-label="secondaryNavigation.hideContent"
78288
- className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label"
78281
+ className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label is-clickable"
78289
78282
  collapsed={false}
78290
78283
  onClick={[Function]}
78291
78284
  type="button"
@@ -78376,7 +78369,7 @@ exports[`Storyshots Secondary Navigation Sub Navigation 1`] = `
78376
78369
  <div>
78377
78370
  <button
78378
78371
  aria-label="secondaryNavigation.hideContent"
78379
- className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label"
78372
+ className="button SecondaryNavigation__MenuButton-sc-8p1rgi-2 fkeiWf menu-label is-clickable"
78380
78373
  collapsed={false}
78381
78374
  onClick={[Function]}
78382
78375
  type="button"
@@ -17,7 +17,6 @@
17
17
  import React, { FC } from "react";
18
18
  import styled from "styled-components";
19
19
  import { useSecondaryNavigation } from "../useSecondaryNavigation";
20
- import { SecondaryNavigationProvider } from "../navigation/SecondaryNavigationContext";
21
20
 
22
21
  const SecondaryColumn = styled.div<{ collapsed: boolean }>`
23
22
  flex: 0 0 auto;
@@ -29,7 +28,7 @@ const SecondaryColumn = styled.div<{ collapsed: boolean }>`
29
28
  }
30
29
  `;
31
30
 
32
- const SecondaryNavigationColumnIntern: FC = ({ children }) => {
31
+ const SecondaryNavigationColumn: FC = ({ children }) => {
33
32
  const { collapsed } = useSecondaryNavigation();
34
33
 
35
34
  return (
@@ -39,12 +38,4 @@ const SecondaryNavigationColumnIntern: FC = ({ children }) => {
39
38
  );
40
39
  };
41
40
 
42
- const SecondaryNavigationColumn: FC = ({ children }) => {
43
- return (
44
- <SecondaryNavigationProvider>
45
- <SecondaryNavigationColumnIntern>{children}</SecondaryNavigationColumnIntern>
46
- </SecondaryNavigationProvider>
47
- );
48
- };
49
-
50
41
  export default SecondaryNavigationColumn;
@@ -14,10 +14,11 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
- import React, { FC } from "react";
17
+ import React, { FC, useContext } from "react";
18
18
  import classNames from "classnames";
19
19
  import { useSecondaryNavigation } from "../useSecondaryNavigation";
20
20
  import ExternalLink from "./ExternalLink";
21
+ import { SecondaryNavigationContext } from "./SecondaryNavigationContext";
21
22
 
22
23
  type Props = {
23
24
  to: string;
@@ -27,6 +28,7 @@ type Props = {
27
28
 
28
29
  const ExternalNavLink: FC<Props> = ({ to, icon, label }) => {
29
30
  const { collapsed } = useSecondaryNavigation();
31
+ const isSecondaryNavigation = useContext(SecondaryNavigationContext);
30
32
 
31
33
  let showIcon;
32
34
  if (icon) {
@@ -41,7 +43,7 @@ const ExternalNavLink: FC<Props> = ({ to, icon, label }) => {
41
43
  <li title={collapsed ? label : undefined}>
42
44
  <ExternalLink to={to} className={collapsed ? "has-text-centered" : ""} aria-label={collapsed ? label : undefined}>
43
45
  {showIcon}
44
- {collapsed ? null : label}
46
+ {isSecondaryNavigation && collapsed ? null : label}
45
47
  </ExternalLink>
46
48
  </li>
47
49
  );
@@ -17,11 +17,12 @@
17
17
  import React, { FC, useContext, useEffect } from "react";
18
18
  import classNames from "classnames";
19
19
  import { Link } from "react-router-dom";
20
- import { createAttributesForTesting } from "@scm-manager/ui-core";
21
20
  import { useSecondaryNavigation } from "../useSecondaryNavigation";
22
21
  import { RoutingProps } from "./RoutingProps";
23
- import { SubNavigationContext } from "./SubNavigationContext";
24
22
  import useActiveMatch from "./useActiveMatch";
23
+ import { createAttributesForTesting } from "@scm-manager/ui-core";
24
+ import { SecondaryNavigationContext } from "./SecondaryNavigationContext";
25
+ import { SubNavigationContext } from "./SubNavigationContext";
25
26
 
26
27
  type Props = RoutingProps & {
27
28
  label: string;
@@ -50,13 +51,14 @@ const NavLinkContent: FC<NavLinkContentProp> = ({ label, icon, collapsed }) => (
50
51
  const NavLink: FC<Props> = ({ to, activeWhenMatch, activeOnlyWhenExact, title, testId, children, ...contentProps }) => {
51
52
  const active = useActiveMatch({ to, activeWhenMatch, activeOnlyWhenExact });
52
53
  const { collapsed, setCollapsible } = useSecondaryNavigation();
54
+ const isSecondaryNavigation = useContext(SecondaryNavigationContext);
53
55
  const isSubNavigation = useContext(SubNavigationContext);
54
56
 
55
57
  useEffect(() => {
56
- if (active) {
58
+ if (isSecondaryNavigation && active) {
57
59
  setCollapsible(!isSubNavigation);
58
60
  }
59
- }, [active, isSubNavigation, setCollapsible]);
61
+ }, [active, isSecondaryNavigation, isSubNavigation, setCollapsible]);
60
62
 
61
63
  return (
62
64
  <li title={collapsed ? title : undefined}>
@@ -67,7 +69,11 @@ const NavLink: FC<Props> = ({ to, activeWhenMatch, activeOnlyWhenExact, title, t
67
69
  aria-label={collapsed ? title : undefined}
68
70
  {...(active ? { "aria-current": "page" } : {})}
69
71
  >
70
- {children || <NavLinkContent {...contentProps} collapsed={collapsed} />}
72
+ {children ? (
73
+ children
74
+ ) : (
75
+ <NavLinkContent {...contentProps} collapsed={(isSecondaryNavigation && collapsed) ?? false} />
76
+ )}
71
77
  </Link>
72
78
  </li>
73
79
  );
@@ -16,13 +16,12 @@
16
16
 
17
17
  import { storiesOf } from "@storybook/react";
18
18
  import React, { ReactElement } from "react";
19
- import { MemoryRouter } from "react-router-dom";
20
- import styled from "styled-components";
21
- import { Binder, ExtensionPoint, BinderContext } from "@scm-manager/ui-extensions";
22
- import { SecondaryNavigationProvider } from "./SecondaryNavigationContext";
23
19
  import SecondaryNavigation from "./SecondaryNavigation";
24
20
  import SecondaryNavigationItem from "./SecondaryNavigationItem";
21
+ import styled from "styled-components";
25
22
  import SubNavigation from "./SubNavigation";
23
+ import { Binder, ExtensionPoint, BinderContext } from "@scm-manager/ui-extensions";
24
+ import { MemoryRouter } from "react-router-dom";
26
25
 
27
26
  const Columns = styled.div`
28
27
  margin: 2rem;
@@ -47,9 +46,7 @@ const withRoute = (route: string) => {
47
46
  storiesOf("Secondary Navigation", module)
48
47
  .addDecorator((story) => (
49
48
  <Columns className="columns">
50
- <div className="column is-3">
51
- <SecondaryNavigationProvider>{story()}</SecondaryNavigationProvider>
52
- </div>
49
+ <div className="column is-3">{story()}</div>
53
50
  </Columns>
54
51
  ))
55
52
  .add("Default", () =>
@@ -16,8 +16,10 @@
16
16
 
17
17
  import React, { FC } from "react";
18
18
  import styled from "styled-components";
19
+ import classNames from "classnames";
19
20
  import { useTranslation } from "react-i18next";
20
21
  import { useSecondaryNavigation } from "../useSecondaryNavigation";
22
+ import { SecondaryNavigationContext } from "./SecondaryNavigationContext";
21
23
  import { Button } from "@scm-manager/ui-buttons";
22
24
 
23
25
  type Props = {
@@ -71,9 +73,14 @@ const SecondaryNavigation: FC<Props> = ({ label, children, collapsible = true })
71
73
  const menuAriaLabel = collapsed ? t("secondaryNavigation.showContent") : t("secondaryNavigation.hideContent");
72
74
 
73
75
  return (
74
- <SectionContainer className="menu" collapsed={collapsed}>
76
+ <SectionContainer className="menu" collapsed={collapsed ?? false}>
75
77
  <div>
76
- <MenuButton className="menu-label" collapsed={collapsed} onClick={toggleCollapse} aria-label={menuAriaLabel}>
78
+ <MenuButton
79
+ className={classNames("menu-label", { "is-clickable": true })}
80
+ collapsed={collapsed}
81
+ onClick={toggleCollapse}
82
+ aria-label={menuAriaLabel}
83
+ >
77
84
  {isCollapsible ? (
78
85
  <Icon className="is-medium" collapsed={collapsed}>
79
86
  {arrowIcon}
@@ -81,7 +88,9 @@ const SecondaryNavigation: FC<Props> = ({ label, children, collapsible = true })
81
88
  ) : null}
82
89
  {collapsed ? "" : label}
83
90
  </MenuButton>
84
- <ul className="menu-list">{children}</ul>
91
+ <ul className="menu-list">
92
+ <SecondaryNavigationContext.Provider value={true}>{children}</SecondaryNavigationContext.Provider>
93
+ </ul>
85
94
  </div>
86
95
  </SectionContainer>
87
96
  );
@@ -0,0 +1,19 @@
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 React from "react";
18
+
19
+ export const SecondaryNavigationContext = React.createContext(false);
@@ -15,14 +15,17 @@
15
15
  */
16
16
 
17
17
  import { useLocalStorage } from "@scm-manager/ui-api";
18
- import { useCallback, useContext } from "react";
19
- import { SecondaryNavigationContext } from "./navigation/SecondaryNavigationContext";
18
+ import { useCallback, useMemo } from "react";
20
19
 
21
20
  export const useSecondaryNavigation = (isNavigationCollapsible = true) => {
22
- const { collapsible, setCollapsible } = useContext(SecondaryNavigationContext);
23
- const [isCollapsed, setCollapsed] = useLocalStorage("secondaryNavigation.collapsed", false);
21
+ const [isCollapsed, setCollapsed] = useLocalStorage<boolean>("secondaryNavigation.collapsed", false);
22
+ const [isRouteCollapsible, setRouteCollapsible] = useLocalStorage<boolean>("secondaryNavigation.collapsible", true);
24
23
 
25
- const collapsed = collapsible && isCollapsed;
24
+ const collapsible = useMemo(
25
+ () => isRouteCollapsible && isNavigationCollapsible,
26
+ [isNavigationCollapsible, isRouteCollapsible]
27
+ );
28
+ const collapsed = useMemo(() => collapsible && isCollapsed, [collapsible, isCollapsed]);
26
29
 
27
30
  const toggleCollapse = useCallback(() => {
28
31
  if (collapsible) {
@@ -30,10 +33,13 @@ export const useSecondaryNavigation = (isNavigationCollapsible = true) => {
30
33
  }
31
34
  }, [collapsible, setCollapsed]);
32
35
 
33
- return {
34
- collapsed,
35
- collapsible,
36
- setCollapsible,
37
- toggleCollapse,
38
- };
36
+ return useMemo(
37
+ () => ({
38
+ collapsed,
39
+ collapsible,
40
+ setCollapsible: setRouteCollapsible,
41
+ toggleCollapse,
42
+ }),
43
+ [collapsed, collapsible, setRouteCollapsible, toggleCollapse]
44
+ );
39
45
  };
@@ -1,37 +0,0 @@
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 React, { ReactNode, useMemo, useState } from "react";
18
-
19
- type SecondaryNavigationContextState = {
20
- collapsible: boolean;
21
- setCollapsible: (collapsed: boolean) => void;
22
- };
23
-
24
- const dummy: SecondaryNavigationContextState = {
25
- collapsible: false,
26
- // eslint-disable-next-line @typescript-eslint/no-empty-function
27
- setCollapsible: () => {},
28
- };
29
-
30
- export const SecondaryNavigationContext = React.createContext<SecondaryNavigationContextState>(dummy);
31
-
32
- export const SecondaryNavigationProvider = ({ children }: { children: ReactNode }) => {
33
- const [collapsible, setCollapsible] = useState(true);
34
- const contextValue = useMemo(() => ({ collapsible, setCollapsible }), [collapsible, setCollapsible]);
35
-
36
- return <SecondaryNavigationContext.Provider value={contextValue}>{children}</SecondaryNavigationContext.Provider>;
37
- };