@backstage/plugin-catalog 1.33.0-next.1 → 1.33.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/CHANGELOG.md +71 -0
- package/dist/alpha/components/EntityLayout/EntityLayout.esm.js +16 -10
- package/dist/alpha/components/EntityLayout/EntityLayout.esm.js.map +1 -1
- package/dist/alpha/components/EntityTabs/EntityTabs.esm.js +13 -4
- package/dist/alpha/components/EntityTabs/EntityTabs.esm.js.map +1 -1
- package/dist/alpha/components/EntityTabs/EntityTabsGroup.esm.js +76 -52
- package/dist/alpha/components/EntityTabs/EntityTabsGroup.esm.js.map +1 -1
- package/dist/alpha/components/EntityTabs/EntityTabsList.esm.js +34 -44
- package/dist/alpha/components/EntityTabs/EntityTabsList.esm.js.map +1 -1
- package/dist/alpha/pages.esm.js +40 -51
- package/dist/alpha/pages.esm.js.map +1 -1
- package/dist/alpha/plugin.esm.js +7 -1
- package/dist/alpha/plugin.esm.js.map +1 -1
- package/dist/alpha/translation.esm.js +17 -3
- package/dist/alpha/translation.esm.js.map +1 -1
- package/dist/alpha.d.ts +115 -53
- package/dist/components/AboutCard/AboutCard.esm.js +2 -2
- package/dist/components/AboutCard/AboutCard.esm.js.map +1 -1
- package/dist/components/AboutCard/AboutContent.esm.js +1 -1
- package/dist/components/AboutCard/AboutContent.esm.js.map +1 -1
- package/dist/components/AboutCard/AboutField.esm.js +4 -1
- package/dist/components/AboutCard/AboutField.esm.js.map +1 -1
- package/dist/components/CatalogSearchResultListItem/CatalogSearchResultListItem.esm.js +15 -3
- package/dist/components/CatalogSearchResultListItem/CatalogSearchResultListItem.esm.js.map +1 -1
- package/dist/components/CatalogTable/CatalogTable.esm.js +3 -1
- package/dist/components/CatalogTable/CatalogTable.esm.js.map +1 -1
- package/dist/components/EntityContextMenu/EntityContextMenu.esm.js +1 -1
- package/dist/components/EntityContextMenu/EntityContextMenu.esm.js.map +1 -1
- package/dist/components/EntityLayout/EntityLayout.esm.js +3 -7
- package/dist/components/EntityLayout/EntityLayout.esm.js.map +1 -1
- package/dist/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.esm.js +4 -4
- package/dist/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.esm.js.map +1 -1
- package/dist/components/EntityRelationWarning/EntityRelationWarning.esm.js +16 -9
- package/dist/components/EntityRelationWarning/EntityRelationWarning.esm.js.map +1 -1
- package/dist/package.json.esm.js +3 -3
- package/package.json +28 -28
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
1
|
# @backstage/plugin-catalog
|
|
2
2
|
|
|
3
|
+
## 1.33.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 491a06c: Add the ability to show icons for the tabs on the entity page (new frontend)
|
|
8
|
+
- 05aac34: Migrated `DeleteEntityDialog` and `EntityOrphanWarning` components to Backstage UI.
|
|
9
|
+
|
|
10
|
+
The `deleteEntity.description` translation key no longer includes "Click here to delete" text. A new `deleteEntity.actionButtonTitle` key was added for the action button.
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 220d6c3: Add missing translation entries for catalog UI text.
|
|
15
|
+
|
|
16
|
+
This change adds translation keys and updates relevant UI components to use the correct localized labels and text in the catalog plugin. It ensures that catalog screens such as entity layout, tabs, search result items, table labels, and other UI elements correctly reference the i18n system for translation.
|
|
17
|
+
|
|
18
|
+
No functional behavior is changed aside from the improved internationalization support.
|
|
19
|
+
|
|
20
|
+
- 8d4c48b: Fixed vertical spacing between tags in the catalog table.
|
|
21
|
+
- 7feb83b: Adjusted to use the new `@backstage/filter-predicates` types for predicate expressions.
|
|
22
|
+
- 018ca87: Added `title` and `icon` to the plugin definition for the new frontend system.
|
|
23
|
+
- e8258d0: The default entity content layout still supports rendering summary cards at runtime for backward compatibility, but logs a console warning when they are detected to help identify where migration is needed.
|
|
24
|
+
- a7e0d50: Updated `react-router-dom` peer dependency to `^6.30.2` and explicitly disabled v7 future flags to suppress deprecation warnings.
|
|
25
|
+
- 75ac651: Migrated `EntityRelationWarning` and `EntityProcessingErrorsPanel` components from Material UI to Backstage UI.
|
|
26
|
+
- Updated dependencies
|
|
27
|
+
- @backstage/ui@0.12.0
|
|
28
|
+
- @backstage/plugin-catalog-react@2.0.0
|
|
29
|
+
- @backstage/core-components@0.18.7
|
|
30
|
+
- @backstage/plugin-search-common@1.2.22
|
|
31
|
+
- @backstage/core-compat-api@0.5.8
|
|
32
|
+
- @backstage/frontend-plugin-api@0.14.0
|
|
33
|
+
- @backstage/catalog-client@1.13.0
|
|
34
|
+
- @backstage/core-plugin-api@1.12.3
|
|
35
|
+
- @backstage/plugin-techdocs-react@1.3.8
|
|
36
|
+
- @backstage/integration-react@1.2.15
|
|
37
|
+
- @backstage/plugin-permission-react@0.4.40
|
|
38
|
+
- @backstage/version-bridge@1.0.12
|
|
39
|
+
- @backstage/plugin-search-react@1.10.3
|
|
40
|
+
- @backstage/plugin-catalog-common@1.1.8
|
|
41
|
+
- @backstage/plugin-scaffolder-common@1.7.6
|
|
42
|
+
|
|
43
|
+
## 1.33.0-next.2
|
|
44
|
+
|
|
45
|
+
### Minor Changes
|
|
46
|
+
|
|
47
|
+
- 491a06c: Add the ability to show icons for the tabs on the entity page (new frontend)
|
|
48
|
+
|
|
49
|
+
### Patch Changes
|
|
50
|
+
|
|
51
|
+
- 220d6c3: Add missing translation entries for catalog UI text.
|
|
52
|
+
|
|
53
|
+
This change adds translation keys and updates relevant UI components to use the correct localized labels and text in the catalog plugin. It ensures that catalog screens such as entity layout, tabs, search result items, table labels, and other UI elements correctly reference the i18n system for translation.
|
|
54
|
+
|
|
55
|
+
No functional behavior is changed aside from the improved internationalization support.
|
|
56
|
+
|
|
57
|
+
- 7feb83b: Adjusted to use the new `@backstage/filter-predicates` types for predicate expressions.
|
|
58
|
+
- a7e0d50: Prepare for React Router v7 migration by updating to v6.30.2 across all NFS packages and enabling v7 future flags. Convert routes from splat paths to parent/child structure with Outlet components.
|
|
59
|
+
- 75ac651: Migrated `EntityRelationWarning` and `EntityProcessingErrorsPanel` components from Material UI to Backstage UI.
|
|
60
|
+
- Updated dependencies
|
|
61
|
+
- @backstage/ui@0.12.0-next.2
|
|
62
|
+
- @backstage/plugin-catalog-react@2.0.0-next.2
|
|
63
|
+
- @backstage/catalog-client@1.12.2-next.0
|
|
64
|
+
- @backstage/frontend-plugin-api@0.14.0-next.2
|
|
65
|
+
- @backstage/integration-react@1.2.15-next.2
|
|
66
|
+
- @backstage/core-compat-api@0.5.8-next.2
|
|
67
|
+
- @backstage/core-components@0.18.7-next.2
|
|
68
|
+
- @backstage/core-plugin-api@1.12.3-next.1
|
|
69
|
+
- @backstage/plugin-permission-react@0.4.40-next.1
|
|
70
|
+
- @backstage/version-bridge@1.0.12-next.0
|
|
71
|
+
- @backstage/plugin-techdocs-react@1.3.8-next.1
|
|
72
|
+
- @backstage/plugin-search-react@1.10.3-next.2
|
|
73
|
+
|
|
3
74
|
## 1.33.0-next.1
|
|
4
75
|
|
|
5
76
|
### Minor Changes
|
|
@@ -20,7 +20,9 @@ const EntityLayout = (props) => {
|
|
|
20
20
|
children,
|
|
21
21
|
header,
|
|
22
22
|
NotFoundComponent,
|
|
23
|
-
parentEntityRelations
|
|
23
|
+
parentEntityRelations,
|
|
24
|
+
groupDefinitions,
|
|
25
|
+
showNavItemIcons
|
|
24
26
|
} = props;
|
|
25
27
|
const { kind } = useRouteRefParams(entityRouteRef);
|
|
26
28
|
const { entity, loading, error } = useAsyncEntity();
|
|
@@ -41,7 +43,8 @@ const EntityLayout = (props) => {
|
|
|
41
43
|
path: elementProps.path,
|
|
42
44
|
title: elementProps.title,
|
|
43
45
|
group: elementProps.group,
|
|
44
|
-
children: elementProps.children
|
|
46
|
+
children: elementProps.children,
|
|
47
|
+
icon: elementProps.icon
|
|
45
48
|
}
|
|
46
49
|
];
|
|
47
50
|
}),
|
|
@@ -59,16 +62,19 @@ const EntityLayout = (props) => {
|
|
|
59
62
|
}
|
|
60
63
|
),
|
|
61
64
|
loading && /* @__PURE__ */ jsx(Progress, {}),
|
|
62
|
-
entity && /* @__PURE__ */ jsx(
|
|
65
|
+
entity && /* @__PURE__ */ jsx(
|
|
66
|
+
EntityTabs,
|
|
67
|
+
{
|
|
68
|
+
routes,
|
|
69
|
+
groupDefinitions,
|
|
70
|
+
showIcons: showNavItemIcons
|
|
71
|
+
}
|
|
72
|
+
),
|
|
63
73
|
error && /* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.toString() }) }),
|
|
64
|
-
!loading && !error && !entity && /* @__PURE__ */ jsx(Content, { children: NotFoundComponent ? NotFoundComponent : /* @__PURE__ */
|
|
65
|
-
"There is no ",
|
|
74
|
+
!loading && !error && !entity && /* @__PURE__ */ jsx(Content, { children: NotFoundComponent ? NotFoundComponent : /* @__PURE__ */ jsx(WarningPanel, { title: t("entityLabels.warningPanelTitle"), children: t("entityPage.notFoundMessage", {
|
|
66
75
|
kind,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
/* @__PURE__ */ jsx(Link, { to: "https://backstage.io/docs/features/software-catalog/references", children: "kind, namespace, and name" }),
|
|
70
|
-
"."
|
|
71
|
-
] }) })
|
|
76
|
+
link: /* @__PURE__ */ jsx(Link, { to: "https://backstage.io/docs/features/software-catalog/references", children: t("entityPage.notFoundLinkText") })
|
|
77
|
+
}) }) })
|
|
72
78
|
] });
|
|
73
79
|
};
|
|
74
80
|
EntityLayout.Route = Route;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityLayout.esm.js","sources":["../../../../src/alpha/components/EntityLayout/EntityLayout.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ComponentProps, ReactNode } from 'react';\n\nimport Alert from '@material-ui/lab/Alert';\n\nimport {\n attachComponentData,\n useElementFilter,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n Content,\n Link,\n Page,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n entityRouteRef,\n useAsyncEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { catalogTranslationRef } from '../../translation';\nimport { EntityHeader } from '../EntityHeader';\nimport { EntityTabs } from '../EntityTabs';\n\nexport type EntityLayoutRouteProps = {\n path: string;\n title: string;\n group
|
|
1
|
+
{"version":3,"file":"EntityLayout.esm.js","sources":["../../../../src/alpha/components/EntityLayout/EntityLayout.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ComponentProps, ReactNode, ReactElement } from 'react';\n\nimport Alert from '@material-ui/lab/Alert';\n\nimport {\n attachComponentData,\n useElementFilter,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n Content,\n Link,\n Page,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n entityRouteRef,\n useAsyncEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { catalogTranslationRef } from '../../translation';\nimport { EntityHeader } from '../EntityHeader';\nimport { EntityTabs } from '../EntityTabs';\nimport { EntityContentGroupDefinitions } from '@backstage/plugin-catalog-react/alpha';\n\nexport type EntityLayoutRouteProps = {\n path: string;\n title: string;\n group?: string;\n icon?: string | ReactElement;\n children: JSX.Element;\n if?: (entity: Entity) => boolean;\n};\n\nconst dataKey = 'plugin.catalog.entityLayoutRoute';\nconst Route: (props: EntityLayoutRouteProps) => null = () => null;\nattachComponentData(Route, dataKey, true);\nattachComponentData(Route, 'core.gatherMountPoints', true); // This causes all mount points that are discovered within this route to use the path of the route itself\n\n/** @public */\nexport interface EntityLayoutProps {\n UNSTABLE_contextMenuOptions?: ComponentProps<\n typeof EntityHeader\n >['UNSTABLE_contextMenuOptions'];\n UNSTABLE_extraContextMenuItems?: ComponentProps<\n typeof EntityHeader\n >['UNSTABLE_extraContextMenuItems'];\n contextMenuItems?: ComponentProps<typeof EntityHeader>['contextMenuItems'];\n children?: ReactNode;\n header?: JSX.Element;\n NotFoundComponent?: ReactNode;\n /**\n * An array of relation types used to determine the parent entities in the hierarchy.\n * These relations are prioritized in the order provided, allowing for flexible\n * navigation through entity relationships.\n *\n * For example, use relation types like `[\"partOf\", \"memberOf\", \"ownedBy\"]` to define how the entity is related to\n * its parents in the Entity Catalog.\n *\n * It adds breadcrumbs in the Entity page to enhance user navigation and context awareness.\n */\n parentEntityRelations?: string[];\n groupDefinitions: EntityContentGroupDefinitions;\n showNavItemIcons?: boolean;\n}\n\n/**\n * EntityLayout is a compound component, which allows you to define a layout for\n * entities using a sub-navigation mechanism.\n *\n * Consists of two parts: EntityLayout and EntityLayout.Route\n *\n * @example\n * ```jsx\n * <EntityLayout>\n * <EntityLayout.Route path=\"/example\" title=\"Example tab\">\n * <div>This is rendered under /example/anything-here route</div>\n * </EntityLayout.Route>\n * </EntityLayout>\n * ```\n *\n * @public\n */\nexport const EntityLayout = (props: EntityLayoutProps) => {\n const {\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n contextMenuItems,\n children,\n header,\n NotFoundComponent,\n parentEntityRelations,\n groupDefinitions,\n showNavItemIcons,\n } = props;\n const { kind } = useRouteRefParams(entityRouteRef);\n const { entity, loading, error } = useAsyncEntity();\n\n const routes = useElementFilter(\n children,\n elements =>\n elements\n .selectByComponentData({\n key: dataKey,\n withStrictError:\n 'Child of EntityLayout must be an EntityLayout.Route',\n })\n .getElements<EntityLayoutRouteProps>() // all nodes, element data, maintain structure or not?\n .flatMap(({ props: elementProps }) => {\n if (!entity) {\n return [];\n }\n if (elementProps.if && !elementProps.if(entity)) {\n return [];\n }\n return [\n {\n path: elementProps.path,\n title: elementProps.title,\n group: elementProps.group,\n children: elementProps.children,\n icon: elementProps.icon,\n },\n ];\n }),\n [entity],\n );\n\n const { t } = useTranslationRef(catalogTranslationRef);\n\n return (\n <Page themeId={entity?.spec?.type?.toString() ?? 'home'}>\n {header ?? (\n <EntityHeader\n parentEntityRelations={parentEntityRelations}\n UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n contextMenuItems={contextMenuItems}\n />\n )}\n\n {loading && <Progress />}\n\n {entity && (\n <EntityTabs\n routes={routes}\n groupDefinitions={groupDefinitions}\n showIcons={showNavItemIcons}\n />\n )}\n\n {error && (\n <Content>\n <Alert severity=\"error\">{error.toString()}</Alert>\n </Content>\n )}\n\n {!loading && !error && !entity && (\n <Content>\n {NotFoundComponent ? (\n NotFoundComponent\n ) : (\n <WarningPanel title={t('entityLabels.warningPanelTitle')}>\n {t('entityPage.notFoundMessage', {\n kind,\n link: (\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n {t('entityPage.notFoundLinkText')}\n </Link>\n ),\n })}\n </WarningPanel>\n )}\n </Content>\n )}\n </Page>\n );\n};\n\nEntityLayout.Route = Route;\n"],"names":[],"mappings":"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"}
|
|
@@ -32,11 +32,11 @@ function useSelectedSubRoute(subRoutes) {
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
function EntityTabs(props) {
|
|
35
|
-
const { routes } = props;
|
|
35
|
+
const { routes, groupDefinitions, showIcons } = props;
|
|
36
36
|
const { index, route, element } = useSelectedSubRoute(routes);
|
|
37
37
|
const tabs = useMemo(
|
|
38
38
|
() => routes.map((t) => {
|
|
39
|
-
const { path, title, group } = t;
|
|
39
|
+
const { path, title, group, icon } = t;
|
|
40
40
|
let to = path;
|
|
41
41
|
to = to.replace(/\/\*$/, "");
|
|
42
42
|
to = to.replace(/^\//, "");
|
|
@@ -44,13 +44,22 @@ function EntityTabs(props) {
|
|
|
44
44
|
group,
|
|
45
45
|
id: path,
|
|
46
46
|
path: to,
|
|
47
|
-
label: title
|
|
47
|
+
label: title,
|
|
48
|
+
icon
|
|
48
49
|
};
|
|
49
50
|
}),
|
|
50
51
|
[routes]
|
|
51
52
|
);
|
|
52
53
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
53
|
-
/* @__PURE__ */ jsx(
|
|
54
|
+
/* @__PURE__ */ jsx(
|
|
55
|
+
EntityTabsList,
|
|
56
|
+
{
|
|
57
|
+
tabs,
|
|
58
|
+
selectedIndex: index,
|
|
59
|
+
showIcons,
|
|
60
|
+
groupDefinitions
|
|
61
|
+
}
|
|
62
|
+
),
|
|
54
63
|
/* @__PURE__ */ jsxs(EntityTabsPanel, { children: [
|
|
55
64
|
/* @__PURE__ */ jsx(Helmet, { title: route?.title }),
|
|
56
65
|
element
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityTabs.esm.js","sources":["../../../../src/alpha/components/EntityTabs/EntityTabs.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useMemo } from 'react';\nimport { Helmet } from 'react-helmet';\nimport { matchRoutes, useParams, useRoutes } from 'react-router-dom';\nimport { EntityTabsPanel } from './EntityTabsPanel';\nimport { EntityTabsList } from './EntityTabsList';\n\ntype SubRoute = {\n group
|
|
1
|
+
{"version":3,"file":"EntityTabs.esm.js","sources":["../../../../src/alpha/components/EntityTabs/EntityTabs.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ReactElement, useMemo } from 'react';\nimport { Helmet } from 'react-helmet';\nimport { matchRoutes, useParams, useRoutes } from 'react-router-dom';\nimport { EntityTabsPanel } from './EntityTabsPanel';\nimport { EntityTabsList } from './EntityTabsList';\nimport { EntityContentGroupDefinitions } from '@backstage/plugin-catalog-react/alpha';\n\ntype SubRoute = {\n group?: string;\n path: string;\n title: string;\n icon?: string | ReactElement;\n children: JSX.Element;\n};\n\nexport function useSelectedSubRoute(subRoutes: SubRoute[]): {\n index: number;\n route?: SubRoute;\n element?: JSX.Element;\n} {\n const params = useParams();\n\n const routes = subRoutes.map(({ path, children }) => ({\n caseSensitive: false,\n path: `${path}/*`,\n element: children,\n }));\n\n // TODO: remove once react-router updated\n const sortedRoutes = routes.sort((a, b) =>\n // remove \"/*\" symbols from path end before comparing\n b.path.replace(/\\/\\*$/, '').localeCompare(a.path.replace(/\\/\\*$/, '')),\n );\n\n const element = useRoutes(sortedRoutes) ?? subRoutes[0]?.children;\n\n // TODO(Rugvip): Once we only support v6 stable we can always prefix\n // This avoids having a double / prefix for react-router v6 beta, which in turn breaks\n // the tab highlighting when using relative paths for the tabs.\n let currentRoute = params['*'] ?? '';\n if (!currentRoute.startsWith('/')) {\n currentRoute = `/${currentRoute}`;\n }\n\n const [matchedRoute] = matchRoutes(sortedRoutes, currentRoute) ?? [];\n const foundIndex = matchedRoute\n ? subRoutes.findIndex(t => `${t.path}/*` === matchedRoute.route.path)\n : 0;\n\n return {\n index: foundIndex === -1 ? 0 : foundIndex,\n element,\n route: subRoutes[foundIndex] ?? subRoutes[0],\n };\n}\n\ntype EntityTabsProps = {\n routes: SubRoute[];\n groupDefinitions: EntityContentGroupDefinitions;\n showIcons?: boolean;\n};\n\nexport function EntityTabs(props: EntityTabsProps) {\n const { routes, groupDefinitions, showIcons } = props;\n\n const { index, route, element } = useSelectedSubRoute(routes);\n\n const tabs = useMemo(\n () =>\n routes.map(t => {\n const { path, title, group, icon } = t;\n let to = path;\n // Remove trailing /*\n to = to.replace(/\\/\\*$/, '');\n // And remove leading / for relative navigation\n to = to.replace(/^\\//, '');\n return {\n group,\n id: path,\n path: to,\n label: title,\n icon,\n };\n }),\n [routes],\n );\n\n return (\n <>\n <EntityTabsList\n tabs={tabs}\n selectedIndex={index}\n showIcons={showIcons}\n groupDefinitions={groupDefinitions}\n />\n <EntityTabsPanel>\n <Helmet title={route?.title} />\n {element}\n </EntityTabsPanel>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import { jsxs,
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { forwardRef, useState } from 'react';
|
|
3
3
|
import { Link } from 'react-router-dom';
|
|
4
4
|
import classnames from 'classnames';
|
|
5
5
|
import Typography from '@material-ui/core/Typography';
|
|
6
|
-
import ButtonBase from '@material-ui/core/ButtonBase';
|
|
7
6
|
import Popover from '@material-ui/core/Popover';
|
|
8
7
|
import { capitalize } from '@material-ui/core/utils';
|
|
9
8
|
import { withStyles, createStyles } from '@material-ui/core/styles';
|
|
10
9
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
10
|
+
import Button from '@material-ui/core/Button';
|
|
11
|
+
import ListItem from '@material-ui/core/ListItem';
|
|
12
|
+
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
|
13
|
+
import ListItemText from '@material-ui/core/ListItemText';
|
|
14
|
+
import List from '@material-ui/core/List';
|
|
15
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
16
|
+
import { iconsApiRef } from '@backstage/frontend-plugin-api';
|
|
11
17
|
|
|
12
18
|
const styles = (theme) => createStyles({
|
|
13
19
|
/* Styles applied to the root element. */
|
|
@@ -30,9 +36,6 @@ const styles = (theme) => createStyles({
|
|
|
30
36
|
minWidth: 160
|
|
31
37
|
}
|
|
32
38
|
},
|
|
33
|
-
popInButton: {
|
|
34
|
-
width: "100%"
|
|
35
|
-
},
|
|
36
39
|
defaultTab: {
|
|
37
40
|
...theme.typography.caption,
|
|
38
41
|
padding: theme.spacing(3, 3),
|
|
@@ -112,8 +115,22 @@ const styles = (theme) => createStyles({
|
|
|
112
115
|
flexDirection: "row"
|
|
113
116
|
}
|
|
114
117
|
});
|
|
118
|
+
function resolveIcon(icon, iconsApi, showIcons) {
|
|
119
|
+
if (!showIcons) {
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
if (typeof icon === "string") {
|
|
123
|
+
const Icon = iconsApi.getIcon(icon);
|
|
124
|
+
if (Icon) {
|
|
125
|
+
return /* @__PURE__ */ jsx(Icon, {});
|
|
126
|
+
}
|
|
127
|
+
return void 0;
|
|
128
|
+
}
|
|
129
|
+
return icon;
|
|
130
|
+
}
|
|
115
131
|
const Tab = forwardRef(function Tab2(props, ref) {
|
|
116
132
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
133
|
+
const iconsApi = useApi(iconsApiRef);
|
|
117
134
|
const open = Boolean(anchorEl);
|
|
118
135
|
const submenuId = open ? "tabbed-submenu" : void 0;
|
|
119
136
|
const {
|
|
@@ -123,15 +140,16 @@ const Tab = forwardRef(function Tab2(props, ref) {
|
|
|
123
140
|
disableFocusRipple = false,
|
|
124
141
|
items,
|
|
125
142
|
fullWidth,
|
|
126
|
-
icon,
|
|
127
143
|
indicator,
|
|
128
144
|
label,
|
|
129
145
|
onSelectTab,
|
|
130
146
|
selected,
|
|
131
147
|
textColor = "inherit",
|
|
132
148
|
wrapped = false,
|
|
133
|
-
highlightedButton
|
|
149
|
+
highlightedButton,
|
|
150
|
+
showIcons = false
|
|
134
151
|
} = props;
|
|
152
|
+
const groupIcon = resolveIcon(props.icon, iconsApi, showIcons);
|
|
135
153
|
const testId = "data-testid" in props && props["data-testid"];
|
|
136
154
|
const handleMenuClose = () => {
|
|
137
155
|
setAnchorEl(null);
|
|
@@ -145,30 +163,24 @@ const Tab = forwardRef(function Tab2(props, ref) {
|
|
|
145
163
|
classes && {
|
|
146
164
|
[classes.disabled]: disabled,
|
|
147
165
|
[classes.selected]: selected,
|
|
148
|
-
[classes.labelIcon]: label &&
|
|
166
|
+
[classes.labelIcon]: label && groupIcon,
|
|
149
167
|
[classes.fullWidth]: fullWidth,
|
|
150
168
|
[classes.wrapped]: wrapped
|
|
151
169
|
},
|
|
152
170
|
className
|
|
153
171
|
];
|
|
154
|
-
const innerButtonClasses = [
|
|
155
|
-
classes?.root,
|
|
156
|
-
classes?.[`textColor${capitalize(textColor)}`],
|
|
157
|
-
classes?.defaultTab,
|
|
158
|
-
classes && {
|
|
159
|
-
[classes.disabled]: disabled,
|
|
160
|
-
[classes.labelIcon]: label && icon,
|
|
161
|
-
[classes.fullWidth]: fullWidth,
|
|
162
|
-
[classes.wrapped]: wrapped
|
|
163
|
-
}
|
|
164
|
-
];
|
|
165
172
|
if (items.length === 1) {
|
|
166
173
|
return /* @__PURE__ */ jsxs(
|
|
167
|
-
|
|
174
|
+
Button,
|
|
168
175
|
{
|
|
169
176
|
focusRipple: !disableFocusRipple,
|
|
170
177
|
"data-testid": testId,
|
|
171
|
-
className: classnames(
|
|
178
|
+
className: classnames(
|
|
179
|
+
classArray,
|
|
180
|
+
classes && {
|
|
181
|
+
[classes.labelIcon]: label && (items[0].icon ?? groupIcon)
|
|
182
|
+
}
|
|
183
|
+
),
|
|
172
184
|
ref,
|
|
173
185
|
role: "tab",
|
|
174
186
|
"aria-selected": selected,
|
|
@@ -176,19 +188,18 @@ const Tab = forwardRef(function Tab2(props, ref) {
|
|
|
176
188
|
component: Link,
|
|
177
189
|
onClick: onSelectTab,
|
|
178
190
|
to: items[0]?.path,
|
|
191
|
+
startIcon: resolveIcon(items[0].icon, iconsApi, showIcons),
|
|
179
192
|
children: [
|
|
180
|
-
/* @__PURE__ */
|
|
181
|
-
icon,
|
|
182
|
-
items[0].label
|
|
183
|
-
] }),
|
|
193
|
+
/* @__PURE__ */ jsx(Typography, { className: classes?.wrapper, variant: "button", children: items[0].label }),
|
|
184
194
|
indicator
|
|
185
195
|
]
|
|
186
196
|
}
|
|
187
197
|
);
|
|
188
198
|
}
|
|
199
|
+
const hasIcons = showIcons && items.some((i) => i.icon);
|
|
189
200
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
190
201
|
/* @__PURE__ */ jsxs(
|
|
191
|
-
|
|
202
|
+
Button,
|
|
192
203
|
{
|
|
193
204
|
"data-testid": testId,
|
|
194
205
|
focusRipple: !disableFocusRipple,
|
|
@@ -198,6 +209,7 @@ const Tab = forwardRef(function Tab2(props, ref) {
|
|
|
198
209
|
"aria-selected": selected,
|
|
199
210
|
disabled,
|
|
200
211
|
onClick: handleMenuClick,
|
|
212
|
+
startIcon: groupIcon,
|
|
201
213
|
children: [
|
|
202
214
|
/* @__PURE__ */ jsx(Typography, { className: classes?.wrapper, variant: "button", children: label }),
|
|
203
215
|
/* @__PURE__ */ jsx(ExpandMoreIcon, {})
|
|
@@ -219,33 +231,45 @@ const Tab = forwardRef(function Tab2(props, ref) {
|
|
|
219
231
|
vertical: "top",
|
|
220
232
|
horizontal: "center"
|
|
221
233
|
},
|
|
222
|
-
children:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
234
|
+
children: /* @__PURE__ */ jsx(List, { component: "nav", children: items.map((i) => {
|
|
235
|
+
const itemIcon = resolveIcon(i.icon, iconsApi, showIcons);
|
|
236
|
+
return /* @__PURE__ */ jsxs(
|
|
237
|
+
ListItem,
|
|
238
|
+
{
|
|
239
|
+
button: true,
|
|
240
|
+
focusRipple: !disableFocusRipple,
|
|
241
|
+
classes: {
|
|
242
|
+
selected: classnames(classes?.selectedButton),
|
|
243
|
+
default: classnames(classes?.unselectedButton),
|
|
244
|
+
disabled: classnames(classes?.disabled)
|
|
245
|
+
},
|
|
246
|
+
ref,
|
|
247
|
+
"aria-selected": selected,
|
|
248
|
+
disabled,
|
|
249
|
+
selected: highlightedButton === i.id,
|
|
250
|
+
component: Link,
|
|
251
|
+
onClick: (e) => {
|
|
252
|
+
handleMenuClose();
|
|
253
|
+
onSelectTab?.(e);
|
|
254
|
+
},
|
|
255
|
+
to: i.path,
|
|
256
|
+
children: [
|
|
257
|
+
itemIcon && /* @__PURE__ */ jsx(ListItemIcon, { children: itemIcon }),
|
|
258
|
+
/* @__PURE__ */ jsx(
|
|
259
|
+
ListItemText,
|
|
260
|
+
{
|
|
261
|
+
inset: !itemIcon && hasIcons,
|
|
262
|
+
primary: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
263
|
+
/* @__PURE__ */ jsx(Typography, { variant: "button", children: i.label }),
|
|
264
|
+
indicator
|
|
265
|
+
] })
|
|
266
|
+
}
|
|
267
|
+
)
|
|
268
|
+
]
|
|
238
269
|
},
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
icon,
|
|
243
|
-
i.label
|
|
244
|
-
] }),
|
|
245
|
-
indicator
|
|
246
|
-
]
|
|
247
|
-
}
|
|
248
|
-
) }, `popover_item_${idx}`))
|
|
270
|
+
`popover_item_${i.id}`
|
|
271
|
+
);
|
|
272
|
+
}) })
|
|
249
273
|
}
|
|
250
274
|
)
|
|
251
275
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityTabsGroup.esm.js","sources":["../../../../src/alpha/components/EntityTabs/EntityTabsGroup.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ReactNode,\n forwardRef,\n useState,\n MouseEvent,\n MouseEventHandler,\n} from 'react';\nimport { Link } from 'react-router-dom';\nimport classnames from 'classnames';\n\nimport Typography from '@material-ui/core/Typography';\nimport ButtonBase from '@material-ui/core/ButtonBase';\nimport Popover from '@material-ui/core/Popover';\nimport { TabProps, TabClassKey } from '@material-ui/core/Tab';\nimport { capitalize } from '@material-ui/core/utils';\nimport { createStyles, Theme, withStyles } from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\n\nconst styles = (theme: Theme) =>\n createStyles({\n /* Styles applied to the root element. */\n root: {\n ...theme.typography.button,\n maxWidth: 264,\n minWidth: 72,\n position: 'relative',\n boxSizing: 'border-box',\n minHeight: 48,\n flexShrink: 0,\n padding: '6px 12px',\n [theme.breakpoints.up('sm')]: {\n padding: '6px 24px',\n },\n overflow: 'hidden',\n whiteSpace: 'normal',\n textAlign: 'center',\n [theme.breakpoints.up('sm')]: {\n minWidth: 160,\n },\n },\n popInButton: {\n width: '100%',\n },\n defaultTab: {\n ...theme.typography.caption,\n padding: theme.spacing(3, 3),\n textTransform: 'uppercase',\n fontWeight: theme.typography.fontWeightBold,\n color: theme.palette.text.secondary,\n },\n /* Styles applied to the root element if both `icon` and `label` are provided. */\n labelIcon: {\n minHeight: 72,\n paddingTop: 9,\n '& $wrapper > *:first-child': {\n marginBottom: 6,\n },\n },\n /* Styles applied to the root element if the parent [`Tabs`](/api/tabs/) has `textColor=\"inherit\"`. */\n textColorInherit: {\n color: 'inherit',\n opacity: 0.7,\n '&$selected': {\n opacity: 1,\n },\n '&$disabled': {\n opacity: 0.5,\n },\n },\n selectedButton: {\n color: `${theme.palette.text.primary}`,\n opacity: `${1}`,\n },\n unselectedButton: {\n color: `${theme.palette.text.secondary}`,\n opacity: `${0.7}`,\n },\n /* Styles applied to the root element if the parent [`Tabs`](/api/tabs/) has `textColor=\"primary\"`. */\n textColorPrimary: {\n color: theme.palette.text.secondary,\n '&$selected': {\n color: theme.palette.primary.main,\n },\n '&$disabled': {\n color: theme.palette.text.disabled,\n },\n },\n /* Styles applied to the root element if the parent [`Tabs`](/api/tabs/) has `textColor=\"secondary\"`. */\n textColorSecondary: {\n color: theme.palette.text.secondary,\n '&$selected': {\n color: theme.palette.secondary.main,\n },\n '&$disabled': {\n color: theme.palette.text.disabled,\n },\n },\n /* Pseudo-class applied to the root element if `selected={true}` (controlled by the Tabs component). */\n selected: {},\n /* Pseudo-class applied to the root element if `disabled={true}` (controlled by the Tabs component). */\n disabled: {},\n /* Styles applied to the root element if `fullWidth={true}` (controlled by the Tabs component). */\n fullWidth: {\n flexShrink: 1,\n flexGrow: 1,\n flexBasis: 0,\n maxWidth: 'none',\n },\n /* Styles applied to the root element if `wrapped={true}`. */\n wrapped: {\n fontSize: theme.typography.pxToRem(12),\n lineHeight: 1.5,\n },\n /* Styles applied to the `icon` and `label`'s wrapper element. */\n wrapper: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n flexDirection: 'row',\n },\n });\n\ntype EntityTabsGroupItem = {\n id: string;\n index: number;\n label: string;\n path: string;\n group: string;\n};\n\ntype EntityTabsGroupProps = TabProps & {\n classes?: Partial<ReturnType<typeof styles>>;\n indicator?: ReactNode;\n highlightedButton?: number;\n items: EntityTabsGroupItem[];\n onSelectTab: MouseEventHandler<HTMLAnchorElement>;\n};\n\nconst Tab = forwardRef(function Tab(props: EntityTabsGroupProps, ref: any) {\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);\n\n const open = Boolean(anchorEl);\n const submenuId = open ? 'tabbed-submenu' : undefined;\n\n const {\n classes,\n className,\n disabled = false,\n disableFocusRipple = false,\n items,\n fullWidth,\n icon,\n indicator,\n label,\n onSelectTab,\n selected,\n textColor = 'inherit',\n wrapped = false,\n highlightedButton,\n } = props;\n\n const testId = 'data-testid' in props && props['data-testid'];\n\n const handleMenuClose = () => {\n setAnchorEl(null);\n };\n\n const handleMenuClick = (event: MouseEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const classArray = [\n classes?.root,\n classes?.[`textColor${capitalize(textColor)}` as TabClassKey],\n classes && {\n [classes.disabled!]: disabled,\n [classes.selected!]: selected,\n [classes.labelIcon!]: label && icon,\n [classes.fullWidth!]: fullWidth,\n [classes.wrapped!]: wrapped,\n },\n className,\n ];\n\n const innerButtonClasses = [\n classes?.root,\n classes?.[`textColor${capitalize(textColor)}` as TabClassKey],\n classes?.defaultTab,\n classes && {\n [classes.disabled!]: disabled,\n [classes.labelIcon!]: label && icon,\n [classes.fullWidth!]: fullWidth,\n [classes.wrapped!]: wrapped,\n },\n ];\n\n if (items.length === 1) {\n return (\n <ButtonBase\n focusRipple={!disableFocusRipple}\n data-testid={testId}\n className={classnames(classArray)}\n ref={ref}\n role=\"tab\"\n aria-selected={selected}\n disabled={disabled}\n component={Link}\n onClick={onSelectTab}\n to={items[0]?.path}\n >\n <Typography className={classes?.wrapper} variant=\"button\">\n {icon}\n {items[0].label}\n </Typography>\n {indicator}\n </ButtonBase>\n );\n }\n return (\n <>\n <ButtonBase\n data-testid={testId}\n focusRipple={!disableFocusRipple}\n className={classnames(classArray)}\n ref={ref}\n role=\"tab\"\n aria-selected={selected}\n disabled={disabled}\n onClick={handleMenuClick}\n >\n <Typography className={classes?.wrapper} variant=\"button\">\n {label}\n </Typography>\n <ExpandMoreIcon />\n </ButtonBase>\n <Popover\n id={submenuId}\n open={open}\n anchorEl={anchorEl}\n onClose={handleMenuClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'center',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'center',\n }}\n >\n {items.map((i, idx) => (\n <div key={`popover_item_${idx}`}>\n <ButtonBase\n focusRipple={!disableFocusRipple}\n className={classnames(\n innerButtonClasses,\n classes?.popInButton,\n highlightedButton === i.index\n ? classes?.selectedButton\n : classes?.unselectedButton,\n )}\n ref={ref}\n aria-selected={selected}\n disabled={disabled}\n component={Link}\n onClick={e => {\n handleMenuClose();\n onSelectTab(e);\n }}\n to={i.path}\n >\n <Typography className={classes?.wrapper} variant=\"button\">\n {icon}\n {i.label}\n </Typography>\n {indicator}\n </ButtonBase>\n </div>\n ))}\n </Popover>\n </>\n );\n});\n\n// @ts-ignore\nexport const EntityTabsGroup = withStyles(styles, { name: 'MuiTab' })(Tab);\n"],"names":["Tab"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityTabsGroup.esm.js","sources":["../../../../src/alpha/components/EntityTabs/EntityTabsGroup.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ReactNode,\n forwardRef,\n useState,\n MouseEvent,\n MouseEventHandler,\n ReactElement,\n} from 'react';\nimport { Link } from 'react-router-dom';\nimport classnames from 'classnames';\n\nimport Typography from '@material-ui/core/Typography';\nimport Popover from '@material-ui/core/Popover';\nimport { TabProps, TabClassKey } from '@material-ui/core/Tab';\nimport { capitalize } from '@material-ui/core/utils';\nimport { createStyles, Theme, withStyles } from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport Button from '@material-ui/core/Button';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport List from '@material-ui/core/List';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { IconsApi, iconsApiRef } from '@backstage/frontend-plugin-api';\n\nconst styles = (theme: Theme) =>\n createStyles({\n /* Styles applied to the root element. */\n root: {\n ...theme.typography.button,\n maxWidth: 264,\n minWidth: 72,\n position: 'relative',\n boxSizing: 'border-box',\n minHeight: 48,\n flexShrink: 0,\n padding: '6px 12px',\n [theme.breakpoints.up('sm')]: {\n padding: '6px 24px',\n },\n overflow: 'hidden',\n whiteSpace: 'normal',\n textAlign: 'center',\n [theme.breakpoints.up('sm')]: {\n minWidth: 160,\n },\n },\n defaultTab: {\n ...theme.typography.caption,\n padding: theme.spacing(3, 3),\n textTransform: 'uppercase',\n fontWeight: theme.typography.fontWeightBold,\n color: theme.palette.text.secondary,\n },\n /* Styles applied to the root element if both `icon` and `label` are provided. */\n labelIcon: {\n minHeight: 72,\n paddingTop: 9,\n '& $wrapper > *:first-child': {\n marginBottom: 6,\n },\n },\n /* Styles applied to the root element if the parent [`Tabs`](/api/tabs/) has `textColor=\"inherit\"`. */\n textColorInherit: {\n color: 'inherit',\n opacity: 0.7,\n '&$selected': {\n opacity: 1,\n },\n '&$disabled': {\n opacity: 0.5,\n },\n },\n selectedButton: {\n color: `${theme.palette.text.primary}`,\n opacity: `${1}`,\n },\n unselectedButton: {\n color: `${theme.palette.text.secondary}`,\n opacity: `${0.7}`,\n },\n /* Styles applied to the root element if the parent [`Tabs`](/api/tabs/) has `textColor=\"primary\"`. */\n textColorPrimary: {\n color: theme.palette.text.secondary,\n '&$selected': {\n color: theme.palette.primary.main,\n },\n '&$disabled': {\n color: theme.palette.text.disabled,\n },\n },\n /* Styles applied to the root element if the parent [`Tabs`](/api/tabs/) has `textColor=\"secondary\"`. */\n textColorSecondary: {\n color: theme.palette.text.secondary,\n '&$selected': {\n color: theme.palette.secondary.main,\n },\n '&$disabled': {\n color: theme.palette.text.disabled,\n },\n },\n /* Pseudo-class applied to the root element if `selected={true}` (controlled by the Tabs component). */\n selected: {},\n /* Pseudo-class applied to the root element if `disabled={true}` (controlled by the Tabs component). */\n disabled: {},\n /* Styles applied to the root element if `fullWidth={true}` (controlled by the Tabs component). */\n fullWidth: {\n flexShrink: 1,\n flexGrow: 1,\n flexBasis: 0,\n maxWidth: 'none',\n },\n /* Styles applied to the root element if `wrapped={true}`. */\n wrapped: {\n fontSize: theme.typography.pxToRem(12),\n lineHeight: 1.5,\n },\n /* Styles applied to the `icon` and `label`'s wrapper element. */\n wrapper: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n flexDirection: 'row',\n },\n });\n\ntype EntityTabsGroupItem = {\n id: string;\n label: string;\n path: string;\n icon?: string | ReactElement;\n};\n\ntype EntityTabsGroupProps = TabProps & {\n classes?: Partial<ReturnType<typeof styles>>;\n indicator?: ReactNode;\n highlightedButton?: string;\n items: EntityTabsGroupItem[];\n onSelectTab?: MouseEventHandler<HTMLAnchorElement>;\n showIcons?: boolean;\n};\n\nfunction resolveIcon(\n icon: string | ReactElement | undefined,\n iconsApi: IconsApi,\n showIcons: boolean,\n) {\n if (!showIcons) {\n return undefined;\n }\n if (typeof icon === 'string') {\n const Icon = iconsApi.getIcon(icon);\n if (Icon) {\n return <Icon />;\n }\n return undefined;\n }\n return icon;\n}\n\nconst Tab = forwardRef(function Tab(props: EntityTabsGroupProps, ref: any) {\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);\n const iconsApi = useApi(iconsApiRef);\n\n const open = Boolean(anchorEl);\n const submenuId = open ? 'tabbed-submenu' : undefined;\n\n const {\n classes,\n className,\n disabled = false,\n disableFocusRipple = false,\n items,\n fullWidth,\n indicator,\n label,\n onSelectTab,\n selected,\n textColor = 'inherit',\n wrapped = false,\n highlightedButton,\n showIcons = false,\n } = props;\n\n const groupIcon = resolveIcon(props.icon, iconsApi, showIcons);\n const testId = 'data-testid' in props && props['data-testid'];\n\n const handleMenuClose = () => {\n setAnchorEl(null);\n };\n\n const handleMenuClick = (event: MouseEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const classArray = [\n classes?.root,\n classes?.[`textColor${capitalize(textColor)}` as TabClassKey],\n classes && {\n [classes.disabled!]: disabled,\n [classes.selected!]: selected,\n [classes.labelIcon!]: label && groupIcon,\n [classes.fullWidth!]: fullWidth,\n [classes.wrapped!]: wrapped,\n },\n className,\n ];\n\n if (items.length === 1) {\n return (\n <Button\n focusRipple={!disableFocusRipple}\n data-testid={testId}\n className={classnames(\n classArray,\n classes && {\n [classes.labelIcon!]: label && (items[0].icon ?? groupIcon),\n },\n )}\n ref={ref}\n role=\"tab\"\n aria-selected={selected}\n disabled={disabled}\n component={Link}\n onClick={onSelectTab}\n to={items[0]?.path}\n startIcon={resolveIcon(items[0].icon, iconsApi, showIcons)}\n >\n <Typography className={classes?.wrapper} variant=\"button\">\n {items[0].label}\n </Typography>\n {indicator}\n </Button>\n );\n }\n const hasIcons = showIcons && items.some(i => i.icon);\n return (\n <>\n <Button\n data-testid={testId}\n focusRipple={!disableFocusRipple}\n className={classnames(classArray)}\n ref={ref}\n role=\"tab\"\n aria-selected={selected}\n disabled={disabled}\n onClick={handleMenuClick}\n startIcon={groupIcon}\n >\n <Typography className={classes?.wrapper} variant=\"button\">\n {label}\n </Typography>\n <ExpandMoreIcon />\n </Button>\n <Popover\n id={submenuId}\n open={open}\n anchorEl={anchorEl}\n onClose={handleMenuClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'center',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'center',\n }}\n >\n <List component=\"nav\">\n {items.map(i => {\n const itemIcon = resolveIcon(i.icon, iconsApi, showIcons);\n return (\n <ListItem\n key={`popover_item_${i.id}`}\n button\n focusRipple={!disableFocusRipple}\n classes={{\n selected: classnames(classes?.selectedButton),\n default: classnames(classes?.unselectedButton),\n disabled: classnames(classes?.disabled),\n }}\n ref={ref}\n aria-selected={selected}\n disabled={disabled}\n selected={highlightedButton === i.id}\n component={Link}\n onClick={e => {\n handleMenuClose();\n onSelectTab?.(e);\n }}\n to={i.path}\n >\n {itemIcon && <ListItemIcon>{itemIcon}</ListItemIcon>}\n <ListItemText\n inset={!itemIcon && hasIcons}\n primary={\n <>\n <Typography variant=\"button\">{i.label}</Typography>\n {indicator}\n </>\n }\n />\n </ListItem>\n );\n })}\n </List>\n </Popover>\n </>\n );\n});\n\n// @ts-ignore\nexport const EntityTabsGroup = withStyles(styles, { name: 'MuiTab' })(Tab);\n"],"names":["Tab"],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useMemo
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
3
|
import Box from '@material-ui/core/Box';
|
|
4
4
|
import Tabs from '@material-ui/core/Tabs';
|
|
5
5
|
import { makeStyles } from '@material-ui/core/styles';
|
|
6
|
+
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
|
|
6
7
|
import { EntityTabsGroup } from './EntityTabsGroup.esm.js';
|
|
8
|
+
import { catalogTranslationRef } from '../../translation.esm.js';
|
|
7
9
|
|
|
8
10
|
const useStyles = makeStyles(
|
|
9
11
|
(theme) => ({
|
|
@@ -34,24 +36,22 @@ const useStyles = makeStyles(
|
|
|
34
36
|
);
|
|
35
37
|
function EntityTabsList(props) {
|
|
36
38
|
const styles = useStyles();
|
|
37
|
-
const {
|
|
39
|
+
const { t } = useTranslationRef(catalogTranslationRef);
|
|
40
|
+
const { tabs: items, selectedIndex = 0, showIcons, groupDefinitions } = props;
|
|
38
41
|
const groups = useMemo(
|
|
39
|
-
() =>
|
|
40
|
-
|
|
42
|
+
() => items.reduce((result, tab) => {
|
|
43
|
+
const group = tab.group ? groupDefinitions[tab.group] : void 0;
|
|
44
|
+
const groupOrId = group && tab.group ? tab.group : tab.id;
|
|
45
|
+
result[groupOrId] = result[groupOrId] ?? {
|
|
46
|
+
group,
|
|
47
|
+
items: []
|
|
48
|
+
};
|
|
49
|
+
result[groupOrId].items.push(tab);
|
|
50
|
+
return result;
|
|
51
|
+
}, {}),
|
|
52
|
+
[items, groupDefinitions]
|
|
41
53
|
);
|
|
42
|
-
const
|
|
43
|
-
selectedItem && items[selectedItem] ? groups.indexOf(items[selectedItem].group) : 0
|
|
44
|
-
);
|
|
45
|
-
const handleChange = useCallback(
|
|
46
|
-
(index) => {
|
|
47
|
-
if (selectedItem !== index) onChange?.(index);
|
|
48
|
-
},
|
|
49
|
-
[selectedItem, onChange]
|
|
50
|
-
);
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
if (selectedItem === void 0 || !items[selectedItem]) return;
|
|
53
|
-
setSelectedGroup(groups.indexOf(items[selectedItem].group));
|
|
54
|
-
}, [items, selectedItem, groups, setSelectedGroup]);
|
|
54
|
+
const selectedItem = items[selectedIndex];
|
|
55
55
|
return /* @__PURE__ */ jsx(Box, { className: styles.tabsWrapper, children: /* @__PURE__ */ jsx(
|
|
56
56
|
Tabs,
|
|
57
57
|
{
|
|
@@ -60,33 +60,23 @@ function EntityTabsList(props) {
|
|
|
60
60
|
textColor: "inherit",
|
|
61
61
|
variant: "scrollable",
|
|
62
62
|
scrollButtons: "auto",
|
|
63
|
-
"aria-label": "
|
|
64
|
-
value:
|
|
65
|
-
children: groups.map((
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
classes: { selected: styles.selected, root: styles.tabRoot },
|
|
81
|
-
label: group,
|
|
82
|
-
value: groupIndex,
|
|
83
|
-
items: groupItems,
|
|
84
|
-
highlightedButton: selectedItem,
|
|
85
|
-
onSelectTab: () => handleChange(groupIndex)
|
|
86
|
-
},
|
|
87
|
-
group
|
|
88
|
-
);
|
|
89
|
-
})
|
|
63
|
+
"aria-label": t("entityTabs.tabsAriaLabel"),
|
|
64
|
+
value: selectedItem?.group ?? selectedItem?.id,
|
|
65
|
+
children: Object.entries(groups).map(([id, tabGroup]) => /* @__PURE__ */ jsx(
|
|
66
|
+
EntityTabsGroup,
|
|
67
|
+
{
|
|
68
|
+
"data-testid": `header-tab-${id}`,
|
|
69
|
+
className: styles.defaultTab,
|
|
70
|
+
classes: { selected: styles.selected, root: styles.tabRoot },
|
|
71
|
+
label: tabGroup.group?.title,
|
|
72
|
+
icon: tabGroup.group?.icon,
|
|
73
|
+
value: id,
|
|
74
|
+
items: tabGroup.items,
|
|
75
|
+
highlightedButton: selectedItem?.id,
|
|
76
|
+
showIcons
|
|
77
|
+
},
|
|
78
|
+
id
|
|
79
|
+
))
|
|
90
80
|
}
|
|
91
81
|
) });
|
|
92
82
|
}
|