@backstage/plugin-catalog 1.29.0-next.1 → 1.29.0-next.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +1 -1
  3. package/dist/alpha/DefaultEntityContentLayout.esm.js +14 -3
  4. package/dist/alpha/DefaultEntityContentLayout.esm.js.map +1 -1
  5. package/dist/alpha/components/EntityHeader/EntityHeader.esm.js +57 -42
  6. package/dist/alpha/components/EntityHeader/EntityHeader.esm.js.map +1 -1
  7. package/dist/alpha/components/EntityLabels/EntityLabels.esm.js +25 -22
  8. package/dist/alpha/components/EntityLabels/EntityLabels.esm.js.map +1 -1
  9. package/dist/alpha/components/EntityLayout/EntityLayout.esm.js +24 -9
  10. package/dist/alpha/components/EntityLayout/EntityLayout.esm.js.map +1 -1
  11. package/dist/alpha/components/EntityTabs/EntityTabs.esm.js +9 -2
  12. package/dist/alpha/components/EntityTabs/EntityTabs.esm.js.map +1 -1
  13. package/dist/alpha/components/EntityTabs/EntityTabsGroup.esm.js +69 -53
  14. package/dist/alpha/components/EntityTabs/EntityTabsGroup.esm.js.map +1 -1
  15. package/dist/alpha/components/EntityTabs/EntityTabsList.esm.js +31 -30
  16. package/dist/alpha/components/EntityTabs/EntityTabsList.esm.js.map +1 -1
  17. package/dist/alpha/components/EntityTabs/EntityTabsPanel.esm.js +5 -5
  18. package/dist/alpha/components/EntityTabs/EntityTabsPanel.esm.js.map +1 -1
  19. package/dist/alpha/contextMenuItems.esm.js +106 -0
  20. package/dist/alpha/contextMenuItems.esm.js.map +1 -0
  21. package/dist/alpha/entityCards.esm.js +11 -11
  22. package/dist/alpha/entityCards.esm.js.map +1 -1
  23. package/dist/alpha/entityContents.esm.js +5 -4
  24. package/dist/alpha/entityContents.esm.js.map +1 -1
  25. package/dist/alpha/filter/FilterWrapper.esm.js +1 -0
  26. package/dist/alpha/filter/FilterWrapper.esm.js.map +1 -1
  27. package/dist/alpha/filters.esm.js +10 -10
  28. package/dist/alpha/filters.esm.js.map +1 -1
  29. package/dist/alpha/pages.esm.js +15 -11
  30. package/dist/alpha/pages.esm.js.map +1 -1
  31. package/dist/alpha/plugin.esm.js +2 -0
  32. package/dist/alpha/plugin.esm.js.map +1 -1
  33. package/dist/alpha/searchResultItems.esm.js.map +1 -1
  34. package/dist/alpha.d.ts +58 -44
  35. package/dist/alpha.esm.js +0 -1
  36. package/dist/alpha.esm.js.map +1 -1
  37. package/dist/components/AboutCard/AboutCard.esm.js +50 -41
  38. package/dist/components/AboutCard/AboutCard.esm.js.map +1 -1
  39. package/dist/components/AboutCard/AboutContent.esm.js +106 -96
  40. package/dist/components/AboutCard/AboutContent.esm.js.map +1 -1
  41. package/dist/components/AboutCard/AboutField.esm.js +6 -3
  42. package/dist/components/AboutCard/AboutField.esm.js.map +1 -1
  43. package/dist/components/CatalogEntityPage/CatalogEntityPage.esm.js +2 -2
  44. package/dist/components/CatalogEntityPage/CatalogEntityPage.esm.js.map +1 -1
  45. package/dist/components/CatalogKindHeader/CatalogKindHeader.esm.js +7 -6
  46. package/dist/components/CatalogKindHeader/CatalogKindHeader.esm.js.map +1 -1
  47. package/dist/components/CatalogPage/CatalogPage.esm.js +2 -2
  48. package/dist/components/CatalogPage/CatalogPage.esm.js.map +1 -1
  49. package/dist/components/CatalogPage/DefaultCatalogPage.esm.js +21 -12
  50. package/dist/components/CatalogPage/DefaultCatalogPage.esm.js.map +1 -1
  51. package/dist/components/CatalogSearchResultListItem/CatalogSearchResultListItem.esm.js +57 -46
  52. package/dist/components/CatalogSearchResultListItem/CatalogSearchResultListItem.esm.js.map +1 -1
  53. package/dist/components/CatalogTable/CatalogTable.esm.js +19 -12
  54. package/dist/components/CatalogTable/CatalogTable.esm.js.map +1 -1
  55. package/dist/components/CatalogTable/CatalogTableToolbar.esm.js +5 -2
  56. package/dist/components/CatalogTable/CatalogTableToolbar.esm.js.map +1 -1
  57. package/dist/components/CatalogTable/CursorPaginatedCatalogTable.esm.js +2 -2
  58. package/dist/components/CatalogTable/CursorPaginatedCatalogTable.esm.js.map +1 -1
  59. package/dist/components/CatalogTable/OffsetPaginatedCatalogTable.esm.js +4 -3
  60. package/dist/components/CatalogTable/OffsetPaginatedCatalogTable.esm.js.map +1 -1
  61. package/dist/components/CatalogTable/columns.esm.js +15 -15
  62. package/dist/components/CatalogTable/columns.esm.js.map +1 -1
  63. package/dist/components/DependencyOfComponentsCard/DependencyOfComponentsCard.esm.js +2 -2
  64. package/dist/components/DependencyOfComponentsCard/DependencyOfComponentsCard.esm.js.map +1 -1
  65. package/dist/components/DependsOnComponentsCard/DependsOnComponentsCard.esm.js +2 -2
  66. package/dist/components/DependsOnComponentsCard/DependsOnComponentsCard.esm.js.map +1 -1
  67. package/dist/components/DependsOnResourcesCard/DependsOnResourcesCard.esm.js +2 -2
  68. package/dist/components/DependsOnResourcesCard/DependsOnResourcesCard.esm.js.map +1 -1
  69. package/dist/components/EntityContextMenu/EntityContextMenu.esm.js +91 -59
  70. package/dist/components/EntityContextMenu/EntityContextMenu.esm.js.map +1 -1
  71. package/dist/components/EntityContextMenu/UnregisterEntity.esm.js +10 -8
  72. package/dist/components/EntityContextMenu/UnregisterEntity.esm.js.map +1 -1
  73. package/dist/components/EntityLabelsCard/EntityLabelsCard.esm.js +4 -4
  74. package/dist/components/EntityLabelsCard/EntityLabelsCard.esm.js.map +1 -1
  75. package/dist/components/EntityLabelsCard/EntityLabelsEmptyState.esm.js +24 -20
  76. package/dist/components/EntityLabelsCard/EntityLabelsEmptyState.esm.js.map +1 -1
  77. package/dist/components/EntityLayout/EntityLayout.esm.js +106 -77
  78. package/dist/components/EntityLayout/EntityLayout.esm.js.map +1 -1
  79. package/dist/components/EntityLinksCard/EntityLinksCard.esm.js +3 -3
  80. package/dist/components/EntityLinksCard/EntityLinksCard.esm.js.map +1 -1
  81. package/dist/components/EntityLinksCard/EntityLinksEmptyState.esm.js +24 -20
  82. package/dist/components/EntityLinksCard/EntityLinksEmptyState.esm.js.map +1 -1
  83. package/dist/components/EntityLinksCard/IconLink.esm.js +5 -2
  84. package/dist/components/EntityLinksCard/IconLink.esm.js.map +1 -1
  85. package/dist/components/EntityLinksCard/LinksGridList.esm.js +2 -2
  86. package/dist/components/EntityLinksCard/LinksGridList.esm.js.map +1 -1
  87. package/dist/components/EntityOrphanWarning/DeleteEntityDialog.esm.js +18 -11
  88. package/dist/components/EntityOrphanWarning/DeleteEntityDialog.esm.js.map +1 -1
  89. package/dist/components/EntityOrphanWarning/EntityOrphanWarning.esm.js +14 -10
  90. package/dist/components/EntityOrphanWarning/EntityOrphanWarning.esm.js.map +1 -1
  91. package/dist/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.esm.js +10 -3
  92. package/dist/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.esm.js.map +1 -1
  93. package/dist/components/EntityRelationWarning/EntityRelationWarning.esm.js +7 -3
  94. package/dist/components/EntityRelationWarning/EntityRelationWarning.esm.js.map +1 -1
  95. package/dist/components/EntitySwitch/EntitySwitch.esm.js +4 -4
  96. package/dist/components/EntitySwitch/EntitySwitch.esm.js.map +1 -1
  97. package/dist/components/HasComponentsCard/HasComponentsCard.esm.js +2 -2
  98. package/dist/components/HasComponentsCard/HasComponentsCard.esm.js.map +1 -1
  99. package/dist/components/HasResourcesCard/HasResourcesCard.esm.js +2 -2
  100. package/dist/components/HasResourcesCard/HasResourcesCard.esm.js.map +1 -1
  101. package/dist/components/HasSubcomponentsCard/HasSubcomponentsCard.esm.js +2 -2
  102. package/dist/components/HasSubcomponentsCard/HasSubcomponentsCard.esm.js.map +1 -1
  103. package/dist/components/HasSubdomainsCard/HasSubdomainsCard.esm.js +2 -2
  104. package/dist/components/HasSubdomainsCard/HasSubdomainsCard.esm.js.map +1 -1
  105. package/dist/components/HasSystemsCard/HasSystemsCard.esm.js +2 -2
  106. package/dist/components/HasSystemsCard/HasSystemsCard.esm.js.map +1 -1
  107. package/dist/components/RelatedEntitiesCard/RelatedEntitiesCard.esm.js +8 -5
  108. package/dist/components/RelatedEntitiesCard/RelatedEntitiesCard.esm.js.map +1 -1
  109. package/dist/context/EntityContextMenuContext.esm.js +18 -0
  110. package/dist/context/EntityContextMenuContext.esm.js.map +1 -0
  111. package/dist/index.d.ts +23 -22
  112. package/package.json +18 -17
  113. package/dist/alpha/blueprints/CatalogFilterBlueprint.esm.js +0 -17
  114. package/dist/alpha/blueprints/CatalogFilterBlueprint.esm.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,74 @@
1
1
  # @backstage/plugin-catalog
2
2
 
3
+ ## 1.29.0-next.2
4
+
5
+ ### Minor Changes
6
+
7
+ - 61d350f: **BREAKING ALPHA**: `CatalogFilterBlueprint`, used in the new frontend system, is now exported under plugin-catalog-react instead of plugin-catalog.
8
+
9
+ ```diff
10
+ + import { CatalogFilterBlueprint } from '@backstage/plugin-catalog-react/alpha';
11
+ - import { CatalogFilterBlueprint } from '@backstage/plugin-catalog/alpha';
12
+ ```
13
+
14
+ - 09afd67: Adds `EntityContextMenuItemBlueprint` to enable extending the entity page's context menu with user defined items.
15
+
16
+ For example:
17
+
18
+ ```ts
19
+ import { EntityContextMenuItemBlueprint } from '@backstage/plugin-catalog-react/alpha';
20
+
21
+ const myCustomHref = EntityContextMenuItemBlueprint.make({
22
+ name: 'test-href',
23
+ params: {
24
+ icon: <span>Example Icon</span>,
25
+ useProps: () => ({
26
+ title: 'Example Href',
27
+ href: '/example-path',
28
+ disabled: false,
29
+ component: 'a',
30
+ }),
31
+ },
32
+ });
33
+
34
+ const myCustomOnClick = EntityContextMenuItemBlueprint.make({
35
+ name: 'test-click',
36
+ params: {
37
+ icon: <span>Test Icon</span>,
38
+ useProps: () => ({
39
+ title: 'Example onClick',
40
+ onClick: () => window.alert('Hello world!'),
41
+ disabled: false,
42
+ }),
43
+ },
44
+ });
45
+ ```
46
+
47
+ ### Patch Changes
48
+
49
+ - e655f62: Updated `README.md` to use `yarn start` instead of `yarn dev`.
50
+ - a47fd39: Removes instances of default React imports, a necessary update for the upcoming React 19 migration.
51
+
52
+ <https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html>
53
+
54
+ - Updated dependencies
55
+ - @backstage/frontend-plugin-api@0.10.1-next.1
56
+ - @backstage/integration-react@1.2.6-next.1
57
+ - @backstage/core-compat-api@0.4.1-next.2
58
+ - @backstage/core-components@0.17.1-next.1
59
+ - @backstage/core-plugin-api@1.10.6-next.0
60
+ - @backstage/plugin-permission-react@0.4.33-next.0
61
+ - @backstage/plugin-catalog-react@1.17.0-next.2
62
+ - @backstage/plugin-search-react@1.8.8-next.1
63
+ - @backstage/catalog-client@1.9.1
64
+ - @backstage/catalog-model@1.7.3
65
+ - @backstage/errors@1.2.7
66
+ - @backstage/types@1.2.1
67
+ - @backstage/version-bridge@1.0.11
68
+ - @backstage/plugin-catalog-common@1.1.3
69
+ - @backstage/plugin-scaffolder-common@1.5.10
70
+ - @backstage/plugin-search-common@1.2.17
71
+
3
72
  ## 1.29.0-next.1
4
73
 
5
74
  ### Patch Changes
package/README.md CHANGED
@@ -93,7 +93,7 @@ To evaluate the catalog and have a greater amount of functionality available,
93
93
  run the entire Backstage example application from the root folder:
94
94
 
95
95
  ```bash
96
- yarn dev
96
+ yarn start
97
97
  ```
98
98
 
99
99
  This will launch both frontend and backend in the same window, populated with
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import Grid from '@material-ui/core/Grid';
3
3
  import { makeStyles } from '@material-ui/core/styles';
4
4
  import { EntitySwitch } from '../components/EntitySwitch/EntitySwitch.esm.js';
@@ -63,7 +63,11 @@ const useStyles = makeStyles((theme) => ({
63
63
  }
64
64
  }
65
65
  }));
66
- const entityWarningContent = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(EntitySwitch, null, /* @__PURE__ */ React.createElement(EntitySwitch.Case, { if: isOrphan }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(EntityOrphanWarning, null)))), /* @__PURE__ */ React.createElement(EntitySwitch, null, /* @__PURE__ */ React.createElement(EntitySwitch.Case, { if: hasRelationWarnings }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(EntityRelationWarning, null)))), /* @__PURE__ */ React.createElement(EntitySwitch, null, /* @__PURE__ */ React.createElement(EntitySwitch.Case, { if: hasCatalogProcessingErrors }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(EntityProcessingErrorsPanel, null)))));
66
+ const entityWarningContent = /* @__PURE__ */ jsxs(Fragment, { children: [
67
+ /* @__PURE__ */ jsx(EntitySwitch, { children: /* @__PURE__ */ jsx(EntitySwitch.Case, { if: isOrphan, children: /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(EntityOrphanWarning, {}) }) }) }),
68
+ /* @__PURE__ */ jsx(EntitySwitch, { children: /* @__PURE__ */ jsx(EntitySwitch.Case, { if: hasRelationWarnings, children: /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(EntityRelationWarning, {}) }) }) }),
69
+ /* @__PURE__ */ jsx(EntitySwitch, { children: /* @__PURE__ */ jsx(EntitySwitch.Case, { if: hasCatalogProcessingErrors, children: /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(EntityProcessingErrorsPanel, {}) }) }) })
70
+ ] });
67
71
  function DefaultEntityContentLayout(props) {
68
72
  const { cards } = props;
69
73
  const infoCards = cards.filter((card) => card.type === "info");
@@ -76,7 +80,14 @@ function DefaultEntityContentLayout(props) {
76
80
  summaryCards: !!summaryCards.length,
77
81
  contentCards: !!contentCards.length
78
82
  });
79
- return /* @__PURE__ */ React.createElement(React.Fragment, null, entityWarningContent, /* @__PURE__ */ React.createElement("div", { className: classes.root }, infoCards.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: classes.infoArea }, infoCards.map((card) => card.element)) : null, summaryCards.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: classes.summaryArea }, /* @__PURE__ */ React.createElement(HorizontalScrollGrid, null, summaryCards.map((card) => /* @__PURE__ */ React.createElement("div", { className: classes.summaryCard }, card.element)))) : null, contentCards.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: classes.contentArea }, contentCards.map((card) => card.element)) : null));
83
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
84
+ entityWarningContent,
85
+ /* @__PURE__ */ jsxs("div", { className: classes.root, children: [
86
+ infoCards.length > 0 ? /* @__PURE__ */ jsx("div", { className: classes.infoArea, children: infoCards.map((card) => card.element) }) : null,
87
+ summaryCards.length > 0 ? /* @__PURE__ */ jsx("div", { className: classes.summaryArea, children: /* @__PURE__ */ jsx(HorizontalScrollGrid, { children: summaryCards.map((card) => /* @__PURE__ */ jsx("div", { className: classes.summaryCard, children: card.element })) }) }) : null,
88
+ contentCards.length > 0 ? /* @__PURE__ */ jsx("div", { className: classes.contentArea, children: contentCards.map((card) => card.element) }) : null
89
+ ] })
90
+ ] });
80
91
  }
81
92
 
82
93
  export { DefaultEntityContentLayout };
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultEntityContentLayout.esm.js","sources":["../../src/alpha/DefaultEntityContentLayout.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 React from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport { makeStyles, Theme } from '@material-ui/core/styles';\nimport { EntityContentLayoutProps } from '@backstage/plugin-catalog-react/alpha';\nimport { EntitySwitch } from '../components/EntitySwitch';\nimport {\n EntityOrphanWarning,\n isOrphan,\n} from '../components/EntityOrphanWarning';\nimport {\n EntityRelationWarning,\n hasRelationWarnings,\n} from '../components/EntityRelationWarning';\nimport {\n EntityProcessingErrorsPanel,\n hasCatalogProcessingErrors,\n} from '../components/EntityProcessingErrorsPanel';\nimport { HorizontalScrollGrid } from '@backstage/core-components';\n\nconst useStyles = makeStyles<\n Theme,\n { infoCards: boolean; summaryCards: boolean; contentCards: boolean }\n>(theme => ({\n root: {\n display: 'flex',\n flexFlow: 'column nowrap',\n gap: theme.spacing(3),\n },\n contentArea: {\n display: 'flex',\n flexFlow: 'column',\n gap: theme.spacing(3),\n alignItems: 'stretch',\n minWidth: 0,\n },\n infoArea: {\n display: 'flex',\n flexFlow: 'column nowrap',\n alignItems: 'stretch',\n gap: theme.spacing(3),\n minWidth: 0,\n },\n summaryArea: {\n margin: theme.spacing(1.5), // To counteract MUI negative grid margin\n },\n summaryCard: {\n flex: '0 0 auto',\n '& + &': {\n marginLeft: theme.spacing(3),\n },\n },\n [theme.breakpoints.up('md')]: {\n root: {\n display: 'grid',\n gap: 0,\n gridTemplateAreas: ({ summaryCards }) => `\n \"${summaryCards ? 'summary' : 'content'} info\"\n \"content info\"\n `,\n gridTemplateColumns: ({ infoCards }) => (infoCards ? '2fr 1fr' : '1fr'),\n alignItems: 'start',\n },\n infoArea: {\n gridArea: 'info',\n position: 'sticky',\n top: theme.spacing(3),\n marginLeft: theme.spacing(3),\n },\n contentArea: {\n gridArea: 'content',\n },\n summaryArea: {\n gridArea: 'summary',\n marginBottom: theme.spacing(3),\n },\n },\n}));\n\nconst entityWarningContent = (\n <>\n <EntitySwitch>\n <EntitySwitch.Case if={isOrphan}>\n <Grid item xs={12}>\n <EntityOrphanWarning />\n </Grid>\n </EntitySwitch.Case>\n </EntitySwitch>\n\n <EntitySwitch>\n <EntitySwitch.Case if={hasRelationWarnings}>\n <Grid item xs={12}>\n <EntityRelationWarning />\n </Grid>\n </EntitySwitch.Case>\n </EntitySwitch>\n\n <EntitySwitch>\n <EntitySwitch.Case if={hasCatalogProcessingErrors}>\n <Grid item xs={12}>\n <EntityProcessingErrorsPanel />\n </Grid>\n </EntitySwitch.Case>\n </EntitySwitch>\n </>\n);\n\nexport function DefaultEntityContentLayout(props: EntityContentLayoutProps) {\n const { cards } = props;\n\n const infoCards = cards.filter(card => card.type === 'info');\n const summaryCards = cards.filter(card => card.type === 'summary');\n const contentCards = cards.filter(\n card => !card.type || card.type === 'content',\n );\n\n const classes = useStyles({\n infoCards: !!infoCards.length,\n summaryCards: !!summaryCards.length,\n contentCards: !!contentCards.length,\n });\n\n return (\n <>\n {entityWarningContent}\n <div className={classes.root}>\n {infoCards.length > 0 ? (\n <div className={classes.infoArea}>\n {infoCards.map(card => card.element)}\n </div>\n ) : null}\n {summaryCards.length > 0 ? (\n <div className={classes.summaryArea}>\n <HorizontalScrollGrid>\n {summaryCards.map(card => (\n <div className={classes.summaryCard}>{card.element}</div>\n ))}\n </HorizontalScrollGrid>\n </div>\n ) : null}\n {contentCards.length > 0 ? (\n <div className={classes.contentArea}>\n {contentCards.map(card => card.element)}\n </div>\n ) : null}\n </div>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DefaultEntityContentLayout.esm.js","sources":["../../src/alpha/DefaultEntityContentLayout.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 Grid from '@material-ui/core/Grid';\nimport { makeStyles, Theme } from '@material-ui/core/styles';\nimport { EntityContentLayoutProps } from '@backstage/plugin-catalog-react/alpha';\nimport { EntitySwitch } from '../components/EntitySwitch';\nimport {\n EntityOrphanWarning,\n isOrphan,\n} from '../components/EntityOrphanWarning';\nimport {\n EntityRelationWarning,\n hasRelationWarnings,\n} from '../components/EntityRelationWarning';\nimport {\n EntityProcessingErrorsPanel,\n hasCatalogProcessingErrors,\n} from '../components/EntityProcessingErrorsPanel';\nimport { HorizontalScrollGrid } from '@backstage/core-components';\n\nconst useStyles = makeStyles<\n Theme,\n { infoCards: boolean; summaryCards: boolean; contentCards: boolean }\n>(theme => ({\n root: {\n display: 'flex',\n flexFlow: 'column nowrap',\n gap: theme.spacing(3),\n },\n contentArea: {\n display: 'flex',\n flexFlow: 'column',\n gap: theme.spacing(3),\n alignItems: 'stretch',\n minWidth: 0,\n },\n infoArea: {\n display: 'flex',\n flexFlow: 'column nowrap',\n alignItems: 'stretch',\n gap: theme.spacing(3),\n minWidth: 0,\n },\n summaryArea: {\n margin: theme.spacing(1.5), // To counteract MUI negative grid margin\n },\n summaryCard: {\n flex: '0 0 auto',\n '& + &': {\n marginLeft: theme.spacing(3),\n },\n },\n [theme.breakpoints.up('md')]: {\n root: {\n display: 'grid',\n gap: 0,\n gridTemplateAreas: ({ summaryCards }) => `\n \"${summaryCards ? 'summary' : 'content'} info\"\n \"content info\"\n `,\n gridTemplateColumns: ({ infoCards }) => (infoCards ? '2fr 1fr' : '1fr'),\n alignItems: 'start',\n },\n infoArea: {\n gridArea: 'info',\n position: 'sticky',\n top: theme.spacing(3),\n marginLeft: theme.spacing(3),\n },\n contentArea: {\n gridArea: 'content',\n },\n summaryArea: {\n gridArea: 'summary',\n marginBottom: theme.spacing(3),\n },\n },\n}));\n\nconst entityWarningContent = (\n <>\n <EntitySwitch>\n <EntitySwitch.Case if={isOrphan}>\n <Grid item xs={12}>\n <EntityOrphanWarning />\n </Grid>\n </EntitySwitch.Case>\n </EntitySwitch>\n\n <EntitySwitch>\n <EntitySwitch.Case if={hasRelationWarnings}>\n <Grid item xs={12}>\n <EntityRelationWarning />\n </Grid>\n </EntitySwitch.Case>\n </EntitySwitch>\n\n <EntitySwitch>\n <EntitySwitch.Case if={hasCatalogProcessingErrors}>\n <Grid item xs={12}>\n <EntityProcessingErrorsPanel />\n </Grid>\n </EntitySwitch.Case>\n </EntitySwitch>\n </>\n);\n\nexport function DefaultEntityContentLayout(props: EntityContentLayoutProps) {\n const { cards } = props;\n\n const infoCards = cards.filter(card => card.type === 'info');\n const summaryCards = cards.filter(card => card.type === 'summary');\n const contentCards = cards.filter(\n card => !card.type || card.type === 'content',\n );\n\n const classes = useStyles({\n infoCards: !!infoCards.length,\n summaryCards: !!summaryCards.length,\n contentCards: !!contentCards.length,\n });\n\n return (\n <>\n {entityWarningContent}\n <div className={classes.root}>\n {infoCards.length > 0 ? (\n <div className={classes.infoArea}>\n {infoCards.map(card => card.element)}\n </div>\n ) : null}\n {summaryCards.length > 0 ? (\n <div className={classes.summaryArea}>\n <HorizontalScrollGrid>\n {summaryCards.map(card => (\n <div className={classes.summaryCard}>{card.element}</div>\n ))}\n </HorizontalScrollGrid>\n </div>\n ) : null}\n {contentCards.length > 0 ? (\n <div className={classes.contentArea}>\n {contentCards.map(card => card.element)}\n </div>\n ) : null}\n </div>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import React, { useState, useCallback, useEffect } from 'react';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useCallback, useEffect } from 'react';
2
3
  import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
3
4
  import useAsync from 'react-use/esm/useAsync';
4
5
  import { makeStyles } from '@material-ui/core/styles';
@@ -56,16 +57,19 @@ function EntityHeaderTitle() {
56
57
  const { entity } = useAsyncEntity();
57
58
  const { kind, namespace, name } = useRouteRefParams(entityRouteRef);
58
59
  const { headerTitle: title } = headerProps(kind, namespace, name, entity);
59
- return /* @__PURE__ */ React.createElement(Box, { display: "inline-flex", alignItems: "center", height: "1em", maxWidth: "100%" }, /* @__PURE__ */ React.createElement(
60
- Box,
61
- {
62
- component: "span",
63
- textOverflow: "ellipsis",
64
- whiteSpace: "nowrap",
65
- overflow: "hidden"
66
- },
67
- entity ? /* @__PURE__ */ React.createElement(EntityDisplayName, { entityRef: entity, hideIcon: true }) : title
68
- ), entity && /* @__PURE__ */ React.createElement(FavoriteEntity, { entity }));
60
+ return /* @__PURE__ */ jsxs(Box, { display: "inline-flex", alignItems: "center", height: "1em", maxWidth: "100%", children: [
61
+ /* @__PURE__ */ jsx(
62
+ Box,
63
+ {
64
+ component: "span",
65
+ textOverflow: "ellipsis",
66
+ whiteSpace: "nowrap",
67
+ overflow: "hidden",
68
+ children: entity ? /* @__PURE__ */ jsx(EntityDisplayName, { entityRef: entity, hideIcon: true }) : title
69
+ }
70
+ ),
71
+ entity && /* @__PURE__ */ jsx(FavoriteEntity, { entity })
72
+ ] });
69
73
  }
70
74
  function EntityHeaderSubtitle(props) {
71
75
  const { parentEntityRelations } = props;
@@ -86,12 +90,17 @@ function EntityHeaderSubtitle(props) {
86
90
  }
87
91
  return null;
88
92
  }, [parentEntity, catalogApi]);
89
- return parentEntity ? /* @__PURE__ */ React.createElement(Breadcrumbs, { separator: ">", className: classes.breadcrumbs }, ancestorEntity && /* @__PURE__ */ React.createElement(EntityRefLink, { entityRef: ancestorEntity.targetRef, disableTooltip: true }), /* @__PURE__ */ React.createElement(EntityRefLink, { entityRef: parentEntity.targetRef, disableTooltip: true }), name) : null;
93
+ return parentEntity ? /* @__PURE__ */ jsxs(Breadcrumbs, { separator: ">", className: classes.breadcrumbs, children: [
94
+ ancestorEntity && /* @__PURE__ */ jsx(EntityRefLink, { entityRef: ancestorEntity.targetRef, disableTooltip: true }),
95
+ /* @__PURE__ */ jsx(EntityRefLink, { entityRef: parentEntity.targetRef, disableTooltip: true }),
96
+ name
97
+ ] }) : null;
90
98
  }
91
99
  function EntityHeader(props) {
92
100
  const {
93
101
  UNSTABLE_extraContextMenuItems,
94
102
  UNSTABLE_contextMenuOptions,
103
+ contextMenuItems,
95
104
  parentEntityRelations,
96
105
  title,
97
106
  subtitle
@@ -146,40 +155,46 @@ function EntityHeader(props) {
146
155
  [setSearchParams]
147
156
  );
148
157
  const inspectDialogOpen = typeof selectedInspectEntityDialogTab === "string";
149
- return /* @__PURE__ */ React.createElement(
158
+ return /* @__PURE__ */ jsx(
150
159
  Header,
151
160
  {
152
161
  pageTitleOverride: entityFallbackText,
153
162
  type,
154
- title: title ?? /* @__PURE__ */ React.createElement(EntityHeaderTitle, null),
155
- subtitle: subtitle ?? /* @__PURE__ */ React.createElement(EntityHeaderSubtitle, { parentEntityRelations })
156
- },
157
- entity && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(EntityLabels, { entity }), /* @__PURE__ */ React.createElement(
158
- EntityContextMenu,
159
- {
160
- UNSTABLE_extraContextMenuItems,
161
- UNSTABLE_contextMenuOptions,
162
- onInspectEntity: openInspectEntityDialog,
163
- onUnregisterEntity: openUnregisterEntityDialog
164
- }
165
- ), /* @__PURE__ */ React.createElement(
166
- InspectEntityDialog,
167
- {
168
- entity,
169
- initialTab: selectedInspectEntityDialogTab || void 0,
170
- open: inspectDialogOpen,
171
- onClose: closeInspectEntityDialog,
172
- onSelect: setInspectEntityDialogTab
173
- }
174
- ), /* @__PURE__ */ React.createElement(
175
- UnregisterEntityDialog,
176
- {
177
- entity,
178
- open: confirmationDialogOpen,
179
- onClose: closeUnregisterEntityDialog,
180
- onConfirm: cleanUpAfterUnregisterConfirmation
181
- }
182
- ))
163
+ title: title ?? /* @__PURE__ */ jsx(EntityHeaderTitle, {}),
164
+ subtitle: subtitle ?? /* @__PURE__ */ jsx(EntityHeaderSubtitle, { parentEntityRelations }),
165
+ children: entity && /* @__PURE__ */ jsxs(Fragment, { children: [
166
+ /* @__PURE__ */ jsx(EntityLabels, { entity }),
167
+ /* @__PURE__ */ jsx(
168
+ EntityContextMenu,
169
+ {
170
+ UNSTABLE_extraContextMenuItems,
171
+ UNSTABLE_contextMenuOptions,
172
+ contextMenuItems,
173
+ onInspectEntity: openInspectEntityDialog,
174
+ onUnregisterEntity: openUnregisterEntityDialog
175
+ }
176
+ ),
177
+ /* @__PURE__ */ jsx(
178
+ InspectEntityDialog,
179
+ {
180
+ entity,
181
+ initialTab: selectedInspectEntityDialogTab || void 0,
182
+ open: inspectDialogOpen,
183
+ onClose: closeInspectEntityDialog,
184
+ onSelect: setInspectEntityDialogTab
185
+ }
186
+ ),
187
+ /* @__PURE__ */ jsx(
188
+ UnregisterEntityDialog,
189
+ {
190
+ entity,
191
+ open: confirmationDialogOpen,
192
+ onClose: closeUnregisterEntityDialog,
193
+ onConfirm: cleanUpAfterUnregisterConfirmation
194
+ }
195
+ )
196
+ ] })
197
+ }
183
198
  );
184
199
  }
185
200
 
@@ -1 +1 @@
1
- {"version":3,"file":"EntityHeader.esm.js","sources":["../../../../src/alpha/components/EntityHeader/EntityHeader.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 */\n\nimport React, {\n useState,\n useCallback,\n useEffect,\n ComponentProps,\n ReactNode,\n} from 'react';\nimport { useNavigate, useLocation, useSearchParams } from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport Box from '@material-ui/core/Box';\n\nimport { Header, Breadcrumbs } from '@backstage/core-components';\nimport {\n useApi,\n useRouteRef,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { IconComponent } from '@backstage/frontend-plugin-api';\n\nimport {\n Entity,\n EntityRelation,\n DEFAULT_NAMESPACE,\n} from '@backstage/catalog-model';\n\nimport {\n useAsyncEntity,\n entityRouteRef,\n catalogApiRef,\n EntityRefLink,\n InspectEntityDialog,\n UnregisterEntityDialog,\n EntityDisplayName,\n FavoriteEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { EntityLabels } from '../EntityLabels';\nimport { EntityContextMenu } from '../../../components/EntityContextMenu';\nimport { rootRouteRef, unregisterRedirectRouteRef } from '../../../routes';\n\nfunction headerProps(\n paramKind: string | undefined,\n paramNamespace: string | undefined,\n paramName: string | undefined,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } {\n const kind = paramKind ?? entity?.kind ?? '';\n const namespace = paramNamespace ?? entity?.metadata.namespace ?? '';\n const name =\n entity?.metadata.title ?? paramName ?? entity?.metadata.name ?? '';\n\n return {\n headerTitle: `${name}${\n namespace && namespace !== DEFAULT_NAMESPACE ? ` in ${namespace}` : ''\n }`,\n headerType: (() => {\n let t = kind.toLocaleLowerCase('en-US');\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US');\n }\n return t;\n })(),\n };\n}\n\nfunction findParentRelation(\n entityRelations: EntityRelation[] = [],\n relationTypes: string[] = [],\n) {\n for (const type of relationTypes) {\n const foundRelation = entityRelations.find(\n relation => relation.type === type,\n );\n if (foundRelation) {\n return foundRelation; // Return the first found relation and stop\n }\n }\n return null;\n}\n\nconst useStyles = makeStyles(theme => ({\n breadcrumbs: {\n color: theme.page.fontColor,\n fontSize: theme.typography.caption.fontSize,\n textTransform: 'uppercase',\n marginTop: theme.spacing(1),\n opacity: 0.8,\n '& span ': {\n color: theme.page.fontColor,\n textDecoration: 'underline',\n textUnderlineOffset: '3px',\n },\n },\n}));\n\nfunction EntityHeaderTitle() {\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: title } = headerProps(kind, namespace, name, entity);\n return (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\" maxWidth=\"100%\">\n <Box\n component=\"span\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n >\n {entity ? <EntityDisplayName entityRef={entity} hideIcon /> : title}\n </Box>\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n );\n}\n\nfunction EntityHeaderSubtitle(props: { parentEntityRelations?: string[] }) {\n const { parentEntityRelations } = props;\n const classes = useStyles();\n const { entity } = useAsyncEntity();\n const { name } = useRouteRefParams(entityRouteRef);\n const parentEntity = findParentRelation(\n entity?.relations ?? [],\n parentEntityRelations ?? [],\n );\n\n const catalogApi = useApi(catalogApiRef);\n\n const { value: ancestorEntity } = useAsync(async () => {\n if (parentEntity) {\n return findParentRelation(\n (await catalogApi.getEntityByRef(parentEntity?.targetRef))?.relations,\n parentEntityRelations,\n );\n }\n return null;\n }, [parentEntity, catalogApi]);\n\n return parentEntity ? (\n <Breadcrumbs separator=\">\" className={classes.breadcrumbs}>\n {ancestorEntity && (\n <EntityRefLink entityRef={ancestorEntity.targetRef} disableTooltip />\n )}\n <EntityRefLink entityRef={parentEntity.targetRef} disableTooltip />\n {name}\n </Breadcrumbs>\n ) : null;\n}\n\n/** @alpha */\nexport function EntityHeader(props: {\n // NOTE(freben): Intentionally not exported at this point, since it's part of\n // the unstable extra context menu items concept below\n UNSTABLE_extraContextMenuItems?: {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n }[];\n // NOTE(blam): Intentionally not exported at this point, since it's part of\n // unstable context menu option, eg: disable the unregister entity menu\n UNSTABLE_contextMenuOptions?: {\n disableUnregister: boolean | 'visible' | 'hidden' | 'disable';\n };\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 title?: ReactNode;\n subtitle?: ReactNode;\n}) {\n const {\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n parentEntityRelations,\n title,\n subtitle,\n } = props;\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: entityFallbackText, headerType: type } = headerProps(\n kind,\n namespace,\n name,\n entity,\n );\n\n const location = useLocation();\n const navigate = useNavigate();\n const catalogRoute = useRouteRef(rootRouteRef);\n const unregisterRedirectRoute = useRouteRef(unregisterRedirectRouteRef);\n\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n\n const openUnregisterEntityDialog = useCallback(\n () => setConfirmationDialogOpen(true),\n [setConfirmationDialogOpen],\n );\n\n const closeUnregisterEntityDialog = useCallback(\n () => setConfirmationDialogOpen(false),\n [setConfirmationDialogOpen],\n );\n\n const cleanUpAfterUnregisterConfirmation = useCallback(async () => {\n setConfirmationDialogOpen(false);\n navigate(\n unregisterRedirectRoute ? unregisterRedirectRoute() : catalogRoute(),\n );\n }, [\n navigate,\n catalogRoute,\n unregisterRedirectRoute,\n setConfirmationDialogOpen,\n ]);\n\n // Make sure to close the dialog if the user clicks links in it that navigate\n // to another entity.\n useEffect(() => {\n setConfirmationDialogOpen(false);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [location.pathname]);\n\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedInspectEntityDialogTab = searchParams.get('inspect');\n\n const setInspectEntityDialogTab = useCallback(\n (newTab: string) => setSearchParams(`inspect=${newTab}`),\n [setSearchParams],\n );\n\n const openInspectEntityDialog = useCallback(\n () => setSearchParams('inspect'),\n [setSearchParams],\n );\n\n const closeInspectEntityDialog = useCallback(\n () => setSearchParams(),\n [setSearchParams],\n );\n\n const inspectDialogOpen = typeof selectedInspectEntityDialogTab === 'string';\n\n return (\n <Header\n pageTitleOverride={entityFallbackText}\n type={type}\n title={title ?? <EntityHeaderTitle />}\n subtitle={\n subtitle ?? (\n <EntityHeaderSubtitle parentEntityRelations={parentEntityRelations} />\n )\n }\n >\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}\n onInspectEntity={openInspectEntityDialog}\n onUnregisterEntity={openUnregisterEntityDialog}\n />\n <InspectEntityDialog\n entity={entity!}\n initialTab={\n (selectedInspectEntityDialogTab as ComponentProps<\n typeof InspectEntityDialog\n >['initialTab']) || undefined\n }\n open={inspectDialogOpen}\n onClose={closeInspectEntityDialog}\n onSelect={setInspectEntityDialogTab}\n />\n <UnregisterEntityDialog\n entity={entity!}\n open={confirmationDialogOpen}\n onClose={closeUnregisterEntityDialog}\n onConfirm={cleanUpAfterUnregisterConfirmation}\n />\n </>\n )}\n </Header>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityHeader.esm.js","sources":["../../../../src/alpha/components/EntityHeader/EntityHeader.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 */\n\nimport {\n useState,\n useCallback,\n useEffect,\n ComponentProps,\n ReactNode,\n} from 'react';\nimport { useNavigate, useLocation, useSearchParams } from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport Box from '@material-ui/core/Box';\n\nimport { Header, Breadcrumbs } from '@backstage/core-components';\nimport {\n useApi,\n useRouteRef,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { IconComponent } from '@backstage/frontend-plugin-api';\n\nimport {\n Entity,\n EntityRelation,\n DEFAULT_NAMESPACE,\n} from '@backstage/catalog-model';\n\nimport {\n useAsyncEntity,\n entityRouteRef,\n catalogApiRef,\n EntityRefLink,\n InspectEntityDialog,\n UnregisterEntityDialog,\n EntityDisplayName,\n FavoriteEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { EntityLabels } from '../EntityLabels';\nimport { EntityContextMenu } from '../../../components/EntityContextMenu';\nimport { rootRouteRef, unregisterRedirectRouteRef } from '../../../routes';\n\nfunction headerProps(\n paramKind: string | undefined,\n paramNamespace: string | undefined,\n paramName: string | undefined,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } {\n const kind = paramKind ?? entity?.kind ?? '';\n const namespace = paramNamespace ?? entity?.metadata.namespace ?? '';\n const name =\n entity?.metadata.title ?? paramName ?? entity?.metadata.name ?? '';\n\n return {\n headerTitle: `${name}${\n namespace && namespace !== DEFAULT_NAMESPACE ? ` in ${namespace}` : ''\n }`,\n headerType: (() => {\n let t = kind.toLocaleLowerCase('en-US');\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US');\n }\n return t;\n })(),\n };\n}\n\nfunction findParentRelation(\n entityRelations: EntityRelation[] = [],\n relationTypes: string[] = [],\n) {\n for (const type of relationTypes) {\n const foundRelation = entityRelations.find(\n relation => relation.type === type,\n );\n if (foundRelation) {\n return foundRelation; // Return the first found relation and stop\n }\n }\n return null;\n}\n\nconst useStyles = makeStyles(theme => ({\n breadcrumbs: {\n color: theme.page.fontColor,\n fontSize: theme.typography.caption.fontSize,\n textTransform: 'uppercase',\n marginTop: theme.spacing(1),\n opacity: 0.8,\n '& span ': {\n color: theme.page.fontColor,\n textDecoration: 'underline',\n textUnderlineOffset: '3px',\n },\n },\n}));\n\nfunction EntityHeaderTitle() {\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: title } = headerProps(kind, namespace, name, entity);\n return (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\" maxWidth=\"100%\">\n <Box\n component=\"span\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n >\n {entity ? <EntityDisplayName entityRef={entity} hideIcon /> : title}\n </Box>\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n );\n}\n\nfunction EntityHeaderSubtitle(props: { parentEntityRelations?: string[] }) {\n const { parentEntityRelations } = props;\n const classes = useStyles();\n const { entity } = useAsyncEntity();\n const { name } = useRouteRefParams(entityRouteRef);\n const parentEntity = findParentRelation(\n entity?.relations ?? [],\n parentEntityRelations ?? [],\n );\n\n const catalogApi = useApi(catalogApiRef);\n\n const { value: ancestorEntity } = useAsync(async () => {\n if (parentEntity) {\n return findParentRelation(\n (await catalogApi.getEntityByRef(parentEntity?.targetRef))?.relations,\n parentEntityRelations,\n );\n }\n return null;\n }, [parentEntity, catalogApi]);\n\n return parentEntity ? (\n <Breadcrumbs separator=\">\" className={classes.breadcrumbs}>\n {ancestorEntity && (\n <EntityRefLink entityRef={ancestorEntity.targetRef} disableTooltip />\n )}\n <EntityRefLink entityRef={parentEntity.targetRef} disableTooltip />\n {name}\n </Breadcrumbs>\n ) : null;\n}\n\n/** @alpha */\nexport function EntityHeader(props: {\n // NOTE(freben): Intentionally not exported at this point, since it's part of\n // the unstable extra context menu items concept below\n UNSTABLE_extraContextMenuItems?: {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n }[];\n // NOTE(blam): Intentionally not exported at this point, since it's part of\n // unstable context menu option, eg: disable the unregister entity menu\n UNSTABLE_contextMenuOptions?: {\n disableUnregister: boolean | 'visible' | 'hidden' | 'disable';\n };\n contextMenuItems?: React.JSX.Element[];\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 title?: ReactNode;\n subtitle?: ReactNode;\n}) {\n const {\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n contextMenuItems,\n parentEntityRelations,\n title,\n subtitle,\n } = props;\n const { entity } = useAsyncEntity();\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const { headerTitle: entityFallbackText, headerType: type } = headerProps(\n kind,\n namespace,\n name,\n entity,\n );\n\n const location = useLocation();\n const navigate = useNavigate();\n const catalogRoute = useRouteRef(rootRouteRef);\n const unregisterRedirectRoute = useRouteRef(unregisterRedirectRouteRef);\n\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n\n const openUnregisterEntityDialog = useCallback(\n () => setConfirmationDialogOpen(true),\n [setConfirmationDialogOpen],\n );\n\n const closeUnregisterEntityDialog = useCallback(\n () => setConfirmationDialogOpen(false),\n [setConfirmationDialogOpen],\n );\n\n const cleanUpAfterUnregisterConfirmation = useCallback(async () => {\n setConfirmationDialogOpen(false);\n navigate(\n unregisterRedirectRoute ? unregisterRedirectRoute() : catalogRoute(),\n );\n }, [\n navigate,\n catalogRoute,\n unregisterRedirectRoute,\n setConfirmationDialogOpen,\n ]);\n\n // Make sure to close the dialog if the user clicks links in it that navigate\n // to another entity.\n useEffect(() => {\n setConfirmationDialogOpen(false);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [location.pathname]);\n\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedInspectEntityDialogTab = searchParams.get('inspect');\n\n const setInspectEntityDialogTab = useCallback(\n (newTab: string) => setSearchParams(`inspect=${newTab}`),\n [setSearchParams],\n );\n\n const openInspectEntityDialog = useCallback(\n () => setSearchParams('inspect'),\n [setSearchParams],\n );\n\n const closeInspectEntityDialog = useCallback(\n () => setSearchParams(),\n [setSearchParams],\n );\n\n const inspectDialogOpen = typeof selectedInspectEntityDialogTab === 'string';\n\n return (\n <Header\n pageTitleOverride={entityFallbackText}\n type={type}\n title={title ?? <EntityHeaderTitle />}\n subtitle={\n subtitle ?? (\n <EntityHeaderSubtitle parentEntityRelations={parentEntityRelations} />\n )\n }\n >\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}\n contextMenuItems={contextMenuItems}\n onInspectEntity={openInspectEntityDialog}\n onUnregisterEntity={openUnregisterEntityDialog}\n />\n <InspectEntityDialog\n entity={entity!}\n initialTab={\n (selectedInspectEntityDialogTab as ComponentProps<\n typeof InspectEntityDialog\n >['initialTab']) || undefined\n }\n open={inspectDialogOpen}\n onClose={closeInspectEntityDialog}\n onSelect={setInspectEntityDialogTab}\n />\n <UnregisterEntityDialog\n entity={entity!}\n open={confirmationDialogOpen}\n onClose={closeUnregisterEntityDialog}\n onConfirm={cleanUpAfterUnregisterConfirmation}\n />\n </>\n )}\n </Header>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA0DA,SAAS,WACP,CAAA,SAAA,EACA,cACA,EAAA,SAAA,EACA,MAC6C,EAAA;AAC7C,EAAM,MAAA,IAAA,GAAO,SAAa,IAAA,MAAA,EAAQ,IAAQ,IAAA,EAAA;AAC1C,EAAA,MAAM,SAAY,GAAA,cAAA,IAAkB,MAAQ,EAAA,QAAA,CAAS,SAAa,IAAA,EAAA;AAClE,EAAA,MAAM,OACJ,MAAQ,EAAA,QAAA,CAAS,SAAS,SAAa,IAAA,MAAA,EAAQ,SAAS,IAAQ,IAAA,EAAA;AAElE,EAAO,OAAA;AAAA,IACL,WAAA,EAAa,CAAG,EAAA,IAAI,CAClB,EAAA,SAAA,IAAa,cAAc,iBAAoB,GAAA,CAAA,IAAA,EAAO,SAAS,CAAA,CAAA,GAAK,EACtE,CAAA,CAAA;AAAA,IACA,aAAa,MAAM;AACjB,MAAI,IAAA,CAAA,GAAI,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAA;AACtC,MAAA,IAAI,MAAU,IAAA,MAAA,CAAO,IAAQ,IAAA,MAAA,IAAU,OAAO,IAAM,EAAA;AAClD,QAAK,CAAA,IAAA,UAAA;AACL,QAAA,CAAA,IAAM,MAAO,CAAA,IAAA,CAA0B,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAA;AAAA;AAEvE,MAAO,OAAA,CAAA;AAAA,KACN;AAAA,GACL;AACF;AAEA,SAAS,mBACP,eAAoC,GAAA,EACpC,EAAA,aAAA,GAA0B,EAC1B,EAAA;AACA,EAAA,KAAA,MAAW,QAAQ,aAAe,EAAA;AAChC,IAAA,MAAM,gBAAgB,eAAgB,CAAA,IAAA;AAAA,MACpC,CAAA,QAAA,KAAY,SAAS,IAAS,KAAA;AAAA,KAChC;AACA,IAAA,IAAI,aAAe,EAAA;AACjB,MAAO,OAAA,aAAA;AAAA;AACT;AAEF,EAAO,OAAA,IAAA;AACT;AAEA,MAAM,SAAA,GAAY,WAAW,CAAU,KAAA,MAAA;AAAA,EACrC,WAAa,EAAA;AAAA,IACX,KAAA,EAAO,MAAM,IAAK,CAAA,SAAA;AAAA,IAClB,QAAA,EAAU,KAAM,CAAA,UAAA,CAAW,OAAQ,CAAA,QAAA;AAAA,IACnC,aAAe,EAAA,WAAA;AAAA,IACf,SAAA,EAAW,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC1B,OAAS,EAAA,GAAA;AAAA,IACT,SAAW,EAAA;AAAA,MACT,KAAA,EAAO,MAAM,IAAK,CAAA,SAAA;AAAA,MAClB,cAAgB,EAAA,WAAA;AAAA,MAChB,mBAAqB,EAAA;AAAA;AACvB;AAEJ,CAAE,CAAA,CAAA;AAEF,SAAS,iBAAoB,GAAA;AAC3B,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,cAAe,EAAA;AAClC,EAAA,MAAM,EAAE,IAAM,EAAA,SAAA,EAAW,IAAK,EAAA,GAAI,kBAAkB,cAAc,CAAA;AAClE,EAAM,MAAA,EAAE,aAAa,KAAM,EAAA,GAAI,YAAY,IAAM,EAAA,SAAA,EAAW,MAAM,MAAM,CAAA;AACxE,EACE,uBAAA,IAAA,CAAC,OAAI,OAAQ,EAAA,aAAA,EAAc,YAAW,QAAS,EAAA,MAAA,EAAO,KAAM,EAAA,QAAA,EAAS,MACnE,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACC,SAAU,EAAA,MAAA;AAAA,QACV,YAAa,EAAA,UAAA;AAAA,QACb,UAAW,EAAA,QAAA;AAAA,QACX,QAAS,EAAA,QAAA;AAAA,QAER,mCAAU,GAAA,CAAA,iBAAA,EAAA,EAAkB,WAAW,MAAQ,EAAA,QAAA,EAAQ,MAAC,CAAK,GAAA;AAAA;AAAA,KAChE;AAAA,IACC,MAAA,oBAAW,GAAA,CAAA,cAAA,EAAA,EAAe,MAAgB,EAAA;AAAA,GAC7C,EAAA,CAAA;AAEJ;AAEA,SAAS,qBAAqB,KAA6C,EAAA;AACzE,EAAM,MAAA,EAAE,uBAA0B,GAAA,KAAA;AAClC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,cAAe,EAAA;AAClC,EAAA,MAAM,EAAE,IAAA,EAAS,GAAA,iBAAA,CAAkB,cAAc,CAAA;AACjD,EAAA,MAAM,YAAe,GAAA,kBAAA;AAAA,IACnB,MAAA,EAAQ,aAAa,EAAC;AAAA,IACtB,yBAAyB;AAAC,GAC5B;AAEA,EAAM,MAAA,UAAA,GAAa,OAAO,aAAa,CAAA;AAEvC,EAAA,MAAM,EAAE,KAAA,EAAO,cAAe,EAAA,GAAI,SAAS,YAAY;AACrD,IAAA,IAAI,YAAc,EAAA;AAChB,MAAO,OAAA,kBAAA;AAAA,QAAA,CACJ,MAAM,UAAA,CAAW,cAAe,CAAA,YAAA,EAAc,SAAS,CAAI,GAAA,SAAA;AAAA,QAC5D;AAAA,OACF;AAAA;AAEF,IAAO,OAAA,IAAA;AAAA,GACN,EAAA,CAAC,YAAc,EAAA,UAAU,CAAC,CAAA;AAE7B,EAAA,OAAO,+BACJ,IAAA,CAAA,WAAA,EAAA,EAAY,WAAU,GAAI,EAAA,SAAA,EAAW,QAAQ,WAC3C,EAAA,QAAA,EAAA;AAAA,IAAA,cAAA,wBACE,aAAc,EAAA,EAAA,SAAA,EAAW,cAAe,CAAA,SAAA,EAAW,gBAAc,IAAC,EAAA,CAAA;AAAA,wBAEpE,aAAc,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,SAAA,EAAW,gBAAc,IAAC,EAAA,CAAA;AAAA,IAChE;AAAA,GAAA,EACH,CACE,GAAA,IAAA;AACN;AAGO,SAAS,aAAa,KA2B1B,EAAA;AACD,EAAM,MAAA;AAAA,IACJ,8BAAA;AAAA,IACA,2BAAA;AAAA,IACA,gBAAA;AAAA,IACA,qBAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACE,GAAA,KAAA;AACJ,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,cAAe,EAAA;AAClC,EAAA,MAAM,EAAE,IAAM,EAAA,SAAA,EAAW,IAAK,EAAA,GAAI,kBAAkB,cAAc,CAAA;AAClE,EAAA,MAAM,EAAE,WAAA,EAAa,kBAAoB,EAAA,UAAA,EAAY,MAAS,GAAA,WAAA;AAAA,IAC5D,IAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAM,MAAA,YAAA,GAAe,YAAY,YAAY,CAAA;AAC7C,EAAM,MAAA,uBAAA,GAA0B,YAAY,0BAA0B,CAAA;AAEtE,EAAA,MAAM,CAAC,sBAAA,EAAwB,yBAAyB,CAAA,GAAI,SAAS,KAAK,CAAA;AAE1E,EAAA,MAAM,0BAA6B,GAAA,WAAA;AAAA,IACjC,MAAM,0BAA0B,IAAI,CAAA;AAAA,IACpC,CAAC,yBAAyB;AAAA,GAC5B;AAEA,EAAA,MAAM,2BAA8B,GAAA,WAAA;AAAA,IAClC,MAAM,0BAA0B,KAAK,CAAA;AAAA,IACrC,CAAC,yBAAyB;AAAA,GAC5B;AAEA,EAAM,MAAA,kCAAA,GAAqC,YAAY,YAAY;AACjE,IAAA,yBAAA,CAA0B,KAAK,CAAA;AAC/B,IAAA,QAAA;AAAA,MACE,uBAAA,GAA0B,uBAAwB,EAAA,GAAI,YAAa;AAAA,KACrE;AAAA,GACC,EAAA;AAAA,IACD,QAAA;AAAA,IACA,YAAA;AAAA,IACA,uBAAA;AAAA,IACA;AAAA,GACD,CAAA;AAID,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,yBAAA,CAA0B,KAAK,CAAA;AAAA,GAE9B,EAAA,CAAC,QAAS,CAAA,QAAQ,CAAC,CAAA;AAEtB,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,eAAgB,EAAA;AACxD,EAAM,MAAA,8BAAA,GAAiC,YAAa,CAAA,GAAA,CAAI,SAAS,CAAA;AAEjE,EAAA,MAAM,yBAA4B,GAAA,WAAA;AAAA,IAChC,CAAC,MAAA,KAAmB,eAAgB,CAAA,CAAA,QAAA,EAAW,MAAM,CAAE,CAAA,CAAA;AAAA,IACvD,CAAC,eAAe;AAAA,GAClB;AAEA,EAAA,MAAM,uBAA0B,GAAA,WAAA;AAAA,IAC9B,MAAM,gBAAgB,SAAS,CAAA;AAAA,IAC/B,CAAC,eAAe;AAAA,GAClB;AAEA,EAAA,MAAM,wBAA2B,GAAA,WAAA;AAAA,IAC/B,MAAM,eAAgB,EAAA;AAAA,IACtB,CAAC,eAAe;AAAA,GAClB;AAEA,EAAM,MAAA,iBAAA,GAAoB,OAAO,8BAAmC,KAAA,QAAA;AAEpE,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,iBAAmB,EAAA,kBAAA;AAAA,MACnB,IAAA;AAAA,MACA,KAAA,EAAO,KAAS,oBAAA,GAAA,CAAC,iBAAkB,EAAA,EAAA,CAAA;AAAA,MACnC,QACE,EAAA,QAAA,oBACG,GAAA,CAAA,oBAAA,EAAA,EAAqB,qBAA8C,EAAA,CAAA;AAAA,MAIvE,oCAEG,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,gBAAa,MAAgB,EAAA,CAAA;AAAA,wBAC9B,GAAA;AAAA,UAAC,iBAAA;AAAA,UAAA;AAAA,YACC,8BAAA;AAAA,YACA,2BAAA;AAAA,YACA,gBAAA;AAAA,YACA,eAAiB,EAAA,uBAAA;AAAA,YACjB,kBAAoB,EAAA;AAAA;AAAA,SACtB;AAAA,wBACA,GAAA;AAAA,UAAC,mBAAA;AAAA,UAAA;AAAA,YACC,MAAA;AAAA,YACA,YACG,8BAEmB,IAAA,KAAA,CAAA;AAAA,YAEtB,IAAM,EAAA,iBAAA;AAAA,YACN,OAAS,EAAA,wBAAA;AAAA,YACT,QAAU,EAAA;AAAA;AAAA,SACZ;AAAA,wBACA,GAAA;AAAA,UAAC,sBAAA;AAAA,UAAA;AAAA,YACC,MAAA;AAAA,YACA,IAAM,EAAA,sBAAA;AAAA,YACN,OAAS,EAAA,2BAAA;AAAA,YACT,SAAW,EAAA;AAAA;AAAA;AACb,OACF,EAAA;AAAA;AAAA,GAEJ;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import { HeaderLabel } from '@backstage/core-components';
3
3
  import { RELATION_OWNED_BY } from '@backstage/catalog-model';
4
4
  import { getEntityRelations, EntityRefLinks } from '@backstage/plugin-catalog-react';
@@ -9,27 +9,30 @@ function EntityLabels(props) {
9
9
  const { entity } = props;
10
10
  const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);
11
11
  const { t } = useTranslationRef(catalogTranslationRef);
12
- return /* @__PURE__ */ React.createElement(React.Fragment, null, ownedByRelations.length > 0 && /* @__PURE__ */ React.createElement(
13
- HeaderLabel,
14
- {
15
- label: t("entityLabels.ownerLabel"),
16
- contentTypograpyRootComponent: "p",
17
- value: /* @__PURE__ */ React.createElement(
18
- EntityRefLinks,
19
- {
20
- entityRefs: ownedByRelations,
21
- defaultKind: "Group",
22
- color: "inherit"
23
- }
24
- )
25
- }
26
- ), entity.spec?.lifecycle && /* @__PURE__ */ React.createElement(
27
- HeaderLabel,
28
- {
29
- label: t("entityLabels.lifecycleLabel"),
30
- value: entity.spec.lifecycle?.toString()
31
- }
32
- ));
12
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
13
+ ownedByRelations.length > 0 && /* @__PURE__ */ jsx(
14
+ HeaderLabel,
15
+ {
16
+ label: t("entityLabels.ownerLabel"),
17
+ contentTypograpyRootComponent: "p",
18
+ value: /* @__PURE__ */ jsx(
19
+ EntityRefLinks,
20
+ {
21
+ entityRefs: ownedByRelations,
22
+ defaultKind: "Group",
23
+ color: "inherit"
24
+ }
25
+ )
26
+ }
27
+ ),
28
+ entity.spec?.lifecycle && /* @__PURE__ */ jsx(
29
+ HeaderLabel,
30
+ {
31
+ label: t("entityLabels.lifecycleLabel"),
32
+ value: entity.spec.lifecycle?.toString()
33
+ }
34
+ )
35
+ ] });
33
36
  }
34
37
 
35
38
  export { EntityLabels };
@@ -1 +1 @@
1
- {"version":3,"file":"EntityLabels.esm.js","sources":["../../../../src/alpha/components/EntityLabels/EntityLabels.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 */\n\nimport React from 'react';\nimport { HeaderLabel } from '@backstage/core-components';\nimport { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model';\nimport {\n EntityRefLinks,\n getEntityRelations,\n} from '@backstage/plugin-catalog-react';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { catalogTranslationRef } from '../../translation';\n\ntype EntityLabelsProps = {\n entity: Entity;\n};\n\nexport function EntityLabels(props: EntityLabelsProps) {\n const { entity } = props;\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n const { t } = useTranslationRef(catalogTranslationRef);\n return (\n <>\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label={t('entityLabels.ownerLabel')}\n contentTypograpyRootComponent=\"p\"\n value={\n <EntityRefLinks\n entityRefs={ownedByRelations}\n defaultKind=\"Group\"\n color=\"inherit\"\n />\n }\n />\n )}\n {entity.spec?.lifecycle && (\n <HeaderLabel\n label={t('entityLabels.lifecycleLabel')}\n value={entity.spec.lifecycle?.toString()}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;AA8BO,SAAS,aAAa,KAA0B,EAAA;AACrD,EAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AACnB,EAAM,MAAA,gBAAA,GAAmB,kBAAmB,CAAA,MAAA,EAAQ,iBAAiB,CAAA;AACrE,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,qBAAqB,CAAA;AACrD,EACE,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EACG,gBAAiB,CAAA,MAAA,GAAS,CACzB,oBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,EAAE,yBAAyB,CAAA;AAAA,MAClC,6BAA8B,EAAA,GAAA;AAAA,MAC9B,KACE,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACC,UAAY,EAAA,gBAAA;AAAA,UACZ,WAAY,EAAA,OAAA;AAAA,UACZ,KAAM,EAAA;AAAA;AAAA;AACR;AAAA,GAEJ,EAED,MAAO,CAAA,IAAA,EAAM,SACZ,oBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,EAAE,6BAA6B,CAAA;AAAA,MACtC,KAAO,EAAA,MAAA,CAAO,IAAK,CAAA,SAAA,EAAW,QAAS;AAAA;AAAA,GAG7C,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"EntityLabels.esm.js","sources":["../../../../src/alpha/components/EntityLabels/EntityLabels.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 */\n\nimport { HeaderLabel } from '@backstage/core-components';\nimport { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model';\nimport {\n EntityRefLinks,\n getEntityRelations,\n} from '@backstage/plugin-catalog-react';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { catalogTranslationRef } from '../../translation';\n\ntype EntityLabelsProps = {\n entity: Entity;\n};\n\nexport function EntityLabels(props: EntityLabelsProps) {\n const { entity } = props;\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n const { t } = useTranslationRef(catalogTranslationRef);\n return (\n <>\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label={t('entityLabels.ownerLabel')}\n contentTypograpyRootComponent=\"p\"\n value={\n <EntityRefLinks\n entityRefs={ownedByRelations}\n defaultKind=\"Group\"\n color=\"inherit\"\n />\n }\n />\n )}\n {entity.spec?.lifecycle && (\n <HeaderLabel\n label={t('entityLabels.lifecycleLabel')}\n value={entity.spec.lifecycle?.toString()}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;AA6BO,SAAS,aAAa,KAA0B,EAAA;AACrD,EAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AACnB,EAAM,MAAA,gBAAA,GAAmB,kBAAmB,CAAA,MAAA,EAAQ,iBAAiB,CAAA;AACrE,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,qBAAqB,CAAA;AACrD,EAAA,uBAEK,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,IAAA,gBAAA,CAAiB,SAAS,CACzB,oBAAA,GAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,EAAE,yBAAyB,CAAA;AAAA,QAClC,6BAA8B,EAAA,GAAA;AAAA,QAC9B,KACE,kBAAA,GAAA;AAAA,UAAC,cAAA;AAAA,UAAA;AAAA,YACC,UAAY,EAAA,gBAAA;AAAA,YACZ,WAAY,EAAA,OAAA;AAAA,YACZ,KAAM,EAAA;AAAA;AAAA;AACR;AAAA,KAEJ;AAAA,IAED,MAAA,CAAO,MAAM,SACZ,oBAAA,GAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,EAAE,6BAA6B,CAAA;AAAA,QACtC,KAAO,EAAA,MAAA,CAAO,IAAK,CAAA,SAAA,EAAW,QAAS;AAAA;AAAA;AACzC,GAEJ,EAAA,CAAA;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import Alert from '@material-ui/lab/Alert';
3
3
  import { attachComponentData, useRouteRefParams, useElementFilter } from '@backstage/core-plugin-api';
4
4
  import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
@@ -16,6 +16,7 @@ const EntityLayout = (props) => {
16
16
  const {
17
17
  UNSTABLE_extraContextMenuItems,
18
18
  UNSTABLE_contextMenuOptions,
19
+ contextMenuItems,
19
20
  children,
20
21
  header,
21
22
  NotFoundComponent,
@@ -47,14 +48,28 @@ const EntityLayout = (props) => {
47
48
  [entity]
48
49
  );
49
50
  const { t } = useTranslationRef(catalogTranslationRef);
50
- return /* @__PURE__ */ React.createElement(Page, { themeId: entity?.spec?.type?.toString() ?? "home" }, header ?? /* @__PURE__ */ React.createElement(
51
- EntityHeader,
52
- {
53
- parentEntityRelations,
54
- UNSTABLE_contextMenuOptions,
55
- UNSTABLE_extraContextMenuItems
56
- }
57
- ), loading && /* @__PURE__ */ React.createElement(Progress, null), entity && /* @__PURE__ */ React.createElement(EntityTabs, { routes }), error && /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Alert, { severity: "error" }, error.toString())), !loading && !error && !entity && /* @__PURE__ */ React.createElement(Content, null, NotFoundComponent ? NotFoundComponent : /* @__PURE__ */ React.createElement(WarningPanel, { title: t("entityLabels.warningPanelTitle") }, "There is no ", kind, " with the requested", " ", /* @__PURE__ */ React.createElement(Link, { to: "https://backstage.io/docs/features/software-catalog/references" }, "kind, namespace, and name"), ".")));
51
+ return /* @__PURE__ */ jsxs(Page, { themeId: entity?.spec?.type?.toString() ?? "home", children: [
52
+ header ?? /* @__PURE__ */ jsx(
53
+ EntityHeader,
54
+ {
55
+ parentEntityRelations,
56
+ UNSTABLE_contextMenuOptions,
57
+ UNSTABLE_extraContextMenuItems,
58
+ contextMenuItems
59
+ }
60
+ ),
61
+ loading && /* @__PURE__ */ jsx(Progress, {}),
62
+ entity && /* @__PURE__ */ jsx(EntityTabs, { routes }),
63
+ error && /* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.toString() }) }),
64
+ !loading && !error && !entity && /* @__PURE__ */ jsx(Content, { children: NotFoundComponent ? NotFoundComponent : /* @__PURE__ */ jsxs(WarningPanel, { title: t("entityLabels.warningPanelTitle"), children: [
65
+ "There is no ",
66
+ kind,
67
+ " with the requested",
68
+ " ",
69
+ /* @__PURE__ */ jsx(Link, { to: "https://backstage.io/docs/features/software-catalog/references", children: "kind, namespace, and name" }),
70
+ "."
71
+ ] }) })
72
+ ] });
58
73
  };
59
74
  EntityLayout.Route = Route;
60
75
 
@@ -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 React, { 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: string;\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 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}\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 children,\n header,\n NotFoundComponent,\n parentEntityRelations,\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 },\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 />\n )}\n\n {loading && <Progress />}\n\n {entity && <EntityTabs routes={routes} />}\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 There is no {kind} with the requested{' '}\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n kind, namespace, and name\n </Link>\n .\n </WarningPanel>\n )}\n </Content>\n )}\n </Page>\n );\n};\n\nEntityLayout.Route = Route;\n"],"names":[],"mappings":";;;;;;;;;;AAmDA,MAAM,OAAU,GAAA,kCAAA;AAChB,MAAM,QAAiD,MAAM,IAAA;AAC7D,mBAAoB,CAAA,KAAA,EAAO,SAAS,IAAI,CAAA;AACxC,mBAAoB,CAAA,KAAA,EAAO,0BAA0B,IAAI,CAAA;AA2C5C,MAAA,YAAA,GAAe,CAAC,KAA6B,KAAA;AACxD,EAAM,MAAA;AAAA,IACJ,8BAAA;AAAA,IACA,2BAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,iBAAA;AAAA,IACA;AAAA,GACE,GAAA,KAAA;AACJ,EAAA,MAAM,EAAE,IAAA,EAAS,GAAA,iBAAA,CAAkB,cAAc,CAAA;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAS,EAAA,KAAA,KAAU,cAAe,EAAA;AAElD,EAAA,MAAM,MAAS,GAAA,gBAAA;AAAA,IACb,QAAA;AAAA,IACA,CAAA,QAAA,KACE,SACG,qBAAsB,CAAA;AAAA,MACrB,GAAK,EAAA,OAAA;AAAA,MACL,eACE,EAAA;AAAA,KACH,EACA,WAAoC,EAAA,CACpC,QAAQ,CAAC,EAAE,KAAO,EAAA,YAAA,EAAmB,KAAA;AACpC,MAAA,IAAI,CAAC,MAAQ,EAAA;AACX,QAAA,OAAO,EAAC;AAAA;AAEV,MAAA,IAAI,aAAa,EAAM,IAAA,CAAC,YAAa,CAAA,EAAA,CAAG,MAAM,CAAG,EAAA;AAC/C,QAAA,OAAO,EAAC;AAAA;AAEV,MAAO,OAAA;AAAA,QACL;AAAA,UACE,MAAM,YAAa,CAAA,IAAA;AAAA,UACnB,OAAO,YAAa,CAAA,KAAA;AAAA,UACpB,OAAO,YAAa,CAAA,KAAA;AAAA,UACpB,UAAU,YAAa,CAAA;AAAA;AACzB,OACF;AAAA,KACD,CAAA;AAAA,IACL,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,qBAAqB,CAAA;AAErD,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,OAAS,EAAA,MAAA,EAAQ,MAAM,IAAM,EAAA,QAAA,EAAc,IAAA,MAAA,EAAA,EAC9C,MACC,oBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,qBAAA;AAAA,MACA,2BAAA;AAAA,MACA;AAAA;AAAA,GACF,EAGD,2BAAY,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAS,GAErB,MAAU,oBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,MAAA,EAAgB,CAEtC,EAAA,KAAA,wCACE,OACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,KAAM,EAAA,EAAA,QAAA,EAAS,OAAS,EAAA,EAAA,KAAA,CAAM,UAAW,CAC5C,CAGD,EAAA,CAAC,OAAW,IAAA,CAAC,SAAS,CAAC,MAAA,wCACrB,OACE,EAAA,IAAA,EAAA,iBAAA,GACC,oCAEC,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,KAAO,EAAA,CAAA,CAAE,gCAAgC,CAAA,EAAA,EAAG,gBAC3C,IAAK,EAAA,qBAAA,EAAoB,GACtC,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,EAAA,EAAG,oEAAiE,2BAE1E,CAAA,EAAO,GAET,CAEJ,CAEJ,CAAA;AAEJ;AAEA,YAAA,CAAa,KAAQ,GAAA,KAAA;;;;"}
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: string;\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}\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 } = 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 },\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 && <EntityTabs routes={routes} />}\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 There is no {kind} with the requested{' '}\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n kind, namespace, and name\n </Link>\n .\n </WarningPanel>\n )}\n </Content>\n )}\n </Page>\n );\n};\n\nEntityLayout.Route = Route;\n"],"names":[],"mappings":";;;;;;;;;;AAmDA,MAAM,OAAU,GAAA,kCAAA;AAChB,MAAM,QAAiD,MAAM,IAAA;AAC7D,mBAAoB,CAAA,KAAA,EAAO,SAAS,IAAI,CAAA;AACxC,mBAAoB,CAAA,KAAA,EAAO,0BAA0B,IAAI,CAAA;AA4C5C,MAAA,YAAA,GAAe,CAAC,KAA6B,KAAA;AACxD,EAAM,MAAA;AAAA,IACJ,8BAAA;AAAA,IACA,2BAAA;AAAA,IACA,gBAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,iBAAA;AAAA,IACA;AAAA,GACE,GAAA,KAAA;AACJ,EAAA,MAAM,EAAE,IAAA,EAAS,GAAA,iBAAA,CAAkB,cAAc,CAAA;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAS,EAAA,KAAA,KAAU,cAAe,EAAA;AAElD,EAAA,MAAM,MAAS,GAAA,gBAAA;AAAA,IACb,QAAA;AAAA,IACA,CAAA,QAAA,KACE,SACG,qBAAsB,CAAA;AAAA,MACrB,GAAK,EAAA,OAAA;AAAA,MACL,eACE,EAAA;AAAA,KACH,EACA,WAAoC,EAAA,CACpC,QAAQ,CAAC,EAAE,KAAO,EAAA,YAAA,EAAmB,KAAA;AACpC,MAAA,IAAI,CAAC,MAAQ,EAAA;AACX,QAAA,OAAO,EAAC;AAAA;AAEV,MAAA,IAAI,aAAa,EAAM,IAAA,CAAC,YAAa,CAAA,EAAA,CAAG,MAAM,CAAG,EAAA;AAC/C,QAAA,OAAO,EAAC;AAAA;AAEV,MAAO,OAAA;AAAA,QACL;AAAA,UACE,MAAM,YAAa,CAAA,IAAA;AAAA,UACnB,OAAO,YAAa,CAAA,KAAA;AAAA,UACpB,OAAO,YAAa,CAAA,KAAA;AAAA,UACpB,UAAU,YAAa,CAAA;AAAA;AACzB,OACF;AAAA,KACD,CAAA;AAAA,IACL,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,qBAAqB,CAAA;AAErD,EACE,uBAAA,IAAA,CAAC,QAAK,OAAS,EAAA,MAAA,EAAQ,MAAM,IAAM,EAAA,QAAA,MAAc,MAC9C,EAAA,QAAA,EAAA;AAAA,IACC,MAAA,oBAAA,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,qBAAA;AAAA,QACA,2BAAA;AAAA,QACA,8BAAA;AAAA,QACA;AAAA;AAAA,KACF;AAAA,IAGD,OAAA,wBAAY,QAAS,EAAA,EAAA,CAAA;AAAA,IAErB,MAAA,oBAAW,GAAA,CAAA,UAAA,EAAA,EAAW,MAAgB,EAAA,CAAA;AAAA,IAEtC,KAAA,oBACE,GAAA,CAAA,OAAA,EAAA,EACC,QAAC,kBAAA,GAAA,CAAA,KAAA,EAAA,EAAM,UAAS,OAAS,EAAA,QAAA,EAAA,KAAA,CAAM,QAAS,EAAA,EAAE,CAC5C,EAAA,CAAA;AAAA,IAGD,CAAC,OAAA,IAAW,CAAC,KAAA,IAAS,CAAC,MACtB,oBAAA,GAAA,CAAC,OACE,EAAA,EAAA,QAAA,EAAA,iBAAA,GACC,oCAEC,IAAA,CAAA,YAAA,EAAA,EAAa,KAAO,EAAA,CAAA,CAAE,gCAAgC,CAAG,EAAA,QAAA,EAAA;AAAA,MAAA,cAAA;AAAA,MAC3C,IAAA;AAAA,MAAK,qBAAA;AAAA,MAAoB,GAAA;AAAA,sBACrC,GAAA,CAAA,IAAA,EAAA,EAAK,EAAG,EAAA,gEAAA,EAAiE,QAE1E,EAAA,2BAAA,EAAA,CAAA;AAAA,MAAO;AAAA,KAAA,EAET,CAEJ,EAAA;AAAA,GAEJ,EAAA,CAAA;AAEJ;AAEA,YAAA,CAAa,KAAQ,GAAA,KAAA;;;;"}
@@ -1,4 +1,5 @@
1
- import React, { useMemo } from 'react';
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useMemo } from 'react';
2
3
  import { Helmet } from 'react-helmet';
3
4
  import { useParams, useRoutes, matchRoutes } from 'react-router-dom';
4
5
  import { EntityTabsPanel } from './EntityTabsPanel.esm.js';
@@ -48,7 +49,13 @@ function EntityTabs(props) {
48
49
  }),
49
50
  [routes]
50
51
  );
51
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(EntityTabsList, { tabs, selectedIndex: index }), /* @__PURE__ */ React.createElement(EntityTabsPanel, null, /* @__PURE__ */ React.createElement(Helmet, { title: route?.title }), element));
52
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
53
+ /* @__PURE__ */ jsx(EntityTabsList, { tabs, selectedIndex: index }),
54
+ /* @__PURE__ */ jsxs(EntityTabsPanel, { children: [
55
+ /* @__PURE__ */ jsx(Helmet, { title: route?.title }),
56
+ element
57
+ ] })
58
+ ] });
52
59
  }
53
60
 
54
61
  export { EntityTabs, useSelectedSubRoute };
@@ -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 React, { 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: string;\n path: string;\n title: string;\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};\n\nexport function EntityTabs(props: EntityTabsProps) {\n const { routes } = props;\n\n const { index, route, element } = useSelectedSubRoute(routes);\n\n const tabs = useMemo(\n () =>\n routes.map(t => {\n const { path, title, group } = 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 };\n }),\n [routes],\n );\n\n return (\n <>\n <EntityTabsList tabs={tabs} selectedIndex={index} />\n <EntityTabsPanel>\n <Helmet title={route?.title} />\n {element}\n </EntityTabsPanel>\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;AA4BO,SAAS,oBAAoB,SAIlC,EAAA;AACA,EAAA,MAAM,SAAS,SAAU,EAAA;AAEzB,EAAA,MAAM,SAAS,SAAU,CAAA,GAAA,CAAI,CAAC,EAAE,IAAA,EAAM,UAAgB,MAAA;AAAA,IACpD,aAAe,EAAA,KAAA;AAAA,IACf,IAAA,EAAM,GAAG,IAAI,CAAA,EAAA,CAAA;AAAA,IACb,OAAS,EAAA;AAAA,GACT,CAAA,CAAA;AAGF,EAAA,MAAM,eAAe,MAAO,CAAA,IAAA;AAAA,IAAK,CAAC,CAAG,EAAA,CAAA;AAAA;AAAA,MAEnC,CAAE,CAAA,IAAA,CAAK,OAAQ,CAAA,OAAA,EAAS,EAAE,CAAA,CAAE,aAAc,CAAA,CAAA,CAAE,IAAK,CAAA,OAAA,CAAQ,OAAS,EAAA,EAAE,CAAC;AAAA;AAAA,GACvE;AAEA,EAAA,MAAM,UAAU,SAAU,CAAA,YAAY,CAAK,IAAA,SAAA,CAAU,CAAC,CAAG,EAAA,QAAA;AAKzD,EAAI,IAAA,YAAA,GAAe,MAAO,CAAA,GAAG,CAAK,IAAA,EAAA;AAClC,EAAA,IAAI,CAAC,YAAA,CAAa,UAAW,CAAA,GAAG,CAAG,EAAA;AACjC,IAAA,YAAA,GAAe,IAAI,YAAY,CAAA,CAAA;AAAA;AAGjC,EAAA,MAAM,CAAC,YAAY,CAAA,GAAI,YAAY,YAAc,EAAA,YAAY,KAAK,EAAC;AACnE,EAAA,MAAM,UAAa,GAAA,YAAA,GACf,SAAU,CAAA,SAAA,CAAU,CAAK,CAAA,KAAA,CAAA,EAAG,CAAE,CAAA,IAAI,CAAS,EAAA,CAAA,KAAA,YAAA,CAAa,KAAM,CAAA,IAAI,CAClE,GAAA,CAAA;AAEJ,EAAO,OAAA;AAAA,IACL,KAAA,EAAO,UAAe,KAAA,CAAA,CAAA,GAAK,CAAI,GAAA,UAAA;AAAA,IAC/B,OAAA;AAAA,IACA,KAAO,EAAA,SAAA,CAAU,UAAU,CAAA,IAAK,UAAU,CAAC;AAAA,GAC7C;AACF;AAMO,SAAS,WAAW,KAAwB,EAAA;AACjD,EAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AAEnB,EAAA,MAAM,EAAE,KAAO,EAAA,KAAA,EAAO,OAAQ,EAAA,GAAI,oBAAoB,MAAM,CAAA;AAE5D,EAAA,MAAM,IAAO,GAAA,OAAA;AAAA,IACX,MACE,MAAO,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA;AACd,MAAA,MAAM,EAAE,IAAA,EAAM,KAAO,EAAA,KAAA,EAAU,GAAA,CAAA;AAC/B,MAAA,IAAI,EAAK,GAAA,IAAA;AAET,MAAK,EAAA,GAAA,EAAA,CAAG,OAAQ,CAAA,OAAA,EAAS,EAAE,CAAA;AAE3B,MAAK,EAAA,GAAA,EAAA,CAAG,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAA;AACzB,MAAO,OAAA;AAAA,QACL,KAAA;AAAA,QACA,EAAI,EAAA,IAAA;AAAA,QACJ,IAAM,EAAA,EAAA;AAAA,QACN,KAAO,EAAA;AAAA,OACT;AAAA,KACD,CAAA;AAAA,IACH,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,iFAEK,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,EAAe,IAAY,EAAA,aAAA,EAAe,OAAO,CAClD,kBAAA,KAAA,CAAA,aAAA,CAAC,eACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAO,KAAO,EAAA,KAAA,EAAO,KAAO,EAAA,CAAA,EAC5B,OACH,CACF,CAAA;AAEJ;;;;"}
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: string;\n path: string;\n title: string;\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};\n\nexport function EntityTabs(props: EntityTabsProps) {\n const { routes } = props;\n\n const { index, route, element } = useSelectedSubRoute(routes);\n\n const tabs = useMemo(\n () =>\n routes.map(t => {\n const { path, title, group } = 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 };\n }),\n [routes],\n );\n\n return (\n <>\n <EntityTabsList tabs={tabs} selectedIndex={index} />\n <EntityTabsPanel>\n <Helmet title={route?.title} />\n {element}\n </EntityTabsPanel>\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;AA4BO,SAAS,oBAAoB,SAIlC,EAAA;AACA,EAAA,MAAM,SAAS,SAAU,EAAA;AAEzB,EAAA,MAAM,SAAS,SAAU,CAAA,GAAA,CAAI,CAAC,EAAE,IAAA,EAAM,UAAgB,MAAA;AAAA,IACpD,aAAe,EAAA,KAAA;AAAA,IACf,IAAA,EAAM,GAAG,IAAI,CAAA,EAAA,CAAA;AAAA,IACb,OAAS,EAAA;AAAA,GACT,CAAA,CAAA;AAGF,EAAA,MAAM,eAAe,MAAO,CAAA,IAAA;AAAA,IAAK,CAAC,CAAG,EAAA,CAAA;AAAA;AAAA,MAEnC,CAAE,CAAA,IAAA,CAAK,OAAQ,CAAA,OAAA,EAAS,EAAE,CAAA,CAAE,aAAc,CAAA,CAAA,CAAE,IAAK,CAAA,OAAA,CAAQ,OAAS,EAAA,EAAE,CAAC;AAAA;AAAA,GACvE;AAEA,EAAA,MAAM,UAAU,SAAU,CAAA,YAAY,CAAK,IAAA,SAAA,CAAU,CAAC,CAAG,EAAA,QAAA;AAKzD,EAAI,IAAA,YAAA,GAAe,MAAO,CAAA,GAAG,CAAK,IAAA,EAAA;AAClC,EAAA,IAAI,CAAC,YAAA,CAAa,UAAW,CAAA,GAAG,CAAG,EAAA;AACjC,IAAA,YAAA,GAAe,IAAI,YAAY,CAAA,CAAA;AAAA;AAGjC,EAAA,MAAM,CAAC,YAAY,CAAA,GAAI,YAAY,YAAc,EAAA,YAAY,KAAK,EAAC;AACnE,EAAA,MAAM,UAAa,GAAA,YAAA,GACf,SAAU,CAAA,SAAA,CAAU,CAAK,CAAA,KAAA,CAAA,EAAG,CAAE,CAAA,IAAI,CAAS,EAAA,CAAA,KAAA,YAAA,CAAa,KAAM,CAAA,IAAI,CAClE,GAAA,CAAA;AAEJ,EAAO,OAAA;AAAA,IACL,KAAA,EAAO,UAAe,KAAA,CAAA,CAAA,GAAK,CAAI,GAAA,UAAA;AAAA,IAC/B,OAAA;AAAA,IACA,KAAO,EAAA,SAAA,CAAU,UAAU,CAAA,IAAK,UAAU,CAAC;AAAA,GAC7C;AACF;AAMO,SAAS,WAAW,KAAwB,EAAA;AACjD,EAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AAEnB,EAAA,MAAM,EAAE,KAAO,EAAA,KAAA,EAAO,OAAQ,EAAA,GAAI,oBAAoB,MAAM,CAAA;AAE5D,EAAA,MAAM,IAAO,GAAA,OAAA;AAAA,IACX,MACE,MAAO,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA;AACd,MAAA,MAAM,EAAE,IAAA,EAAM,KAAO,EAAA,KAAA,EAAU,GAAA,CAAA;AAC/B,MAAA,IAAI,EAAK,GAAA,IAAA;AAET,MAAK,EAAA,GAAA,EAAA,CAAG,OAAQ,CAAA,OAAA,EAAS,EAAE,CAAA;AAE3B,MAAK,EAAA,GAAA,EAAA,CAAG,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAA;AACzB,MAAO,OAAA;AAAA,QACL,KAAA;AAAA,QACA,EAAI,EAAA,IAAA;AAAA,QACJ,IAAM,EAAA,EAAA;AAAA,QACN,KAAO,EAAA;AAAA,OACT;AAAA,KACD,CAAA;AAAA,IACH,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,uBAEI,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAC,GAAA,CAAA,cAAA,EAAA,EAAe,IAAY,EAAA,aAAA,EAAe,KAAO,EAAA,CAAA;AAAA,yBACjD,eACC,EAAA,EAAA,QAAA,EAAA;AAAA,sBAAC,GAAA,CAAA,MAAA,EAAA,EAAO,KAAO,EAAA,KAAA,EAAO,KAAO,EAAA,CAAA;AAAA,MAC5B;AAAA,KACH,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}