@nospt/backstage-plugin-apigee 1.1.0-rc4 → 1.1.0-rc5

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 (41) hide show
  1. package/config.d.ts +0 -10
  2. package/dist/components/ApiCard.esm.js +24 -15
  3. package/dist/components/ApiCard.esm.js.map +1 -1
  4. package/dist/components/ApiCard.module.css.esm.js +2 -2
  5. package/dist/components/ApiCardGrid.esm.js +3 -11
  6. package/dist/components/ApiCardGrid.esm.js.map +1 -1
  7. package/dist/components/ApiDetailsDrawer.esm.js +335 -0
  8. package/dist/components/ApiDetailsDrawer.esm.js.map +1 -0
  9. package/dist/components/ApiDetailsDrawer.module.css.esm.js +8 -0
  10. package/dist/components/ApiDetailsDrawer.module.css.esm.js.map +1 -0
  11. package/dist/components/ApiTable.esm.js +10 -2
  12. package/dist/components/ApiTable.esm.js.map +1 -1
  13. package/dist/components/ApiTable.module.css.esm.js +2 -2
  14. package/dist/components/ApigeeApiCatalogPage.esm.js +62 -49
  15. package/dist/components/ApigeeApiCatalogPage.esm.js.map +1 -1
  16. package/dist/components/FilterToolbar.esm.js +27 -26
  17. package/dist/components/FilterToolbar.esm.js.map +1 -1
  18. package/dist/components/FilterToolbar.module.css.esm.js +2 -2
  19. package/dist/components/apiCardViewModel.esm.js +1 -2
  20. package/dist/components/apiCardViewModel.esm.js.map +1 -1
  21. package/dist/components/apiDetailViewModel.esm.js +60 -0
  22. package/dist/components/apiDetailViewModel.esm.js.map +1 -0
  23. package/dist/components/apigeeFacetFilters.esm.js +3 -6
  24. package/dist/components/apigeeFacetFilters.esm.js.map +1 -1
  25. package/dist/components/apigeeSearchParams.esm.js +0 -1
  26. package/dist/components/apigeeSearchParams.esm.js.map +1 -1
  27. package/dist/components/facetModel.esm.js +3 -29
  28. package/dist/components/facetModel.esm.js.map +1 -1
  29. package/dist/components/useApigeeFilters.esm.js +1 -3
  30. package/dist/components/useApigeeFilters.esm.js.map +1 -1
  31. package/dist/constants.esm.js +1 -2
  32. package/dist/constants.esm.js.map +1 -1
  33. package/dist/index.d.ts +52 -1
  34. package/dist/index.esm.js +1 -1
  35. package/dist/plugin.esm.js +17 -7
  36. package/dist/plugin.esm.js.map +1 -1
  37. package/dist/routes.esm.js +2 -1
  38. package/dist/routes.esm.js.map +1 -1
  39. package/package.json +2 -2
  40. package/dist/components/categoryIcons.esm.js +0 -53
  41. package/dist/components/categoryIcons.esm.js.map +0 -1
package/config.d.ts CHANGED
@@ -2,16 +2,6 @@
2
2
  export interface Config {
3
3
  apigee?: {
4
4
  catalog?: {
5
- /**
6
- * Optional override of the default category -> icon map (UI-10 / D-08).
7
- * Keys are category slugs (matching the apigee.com/category annotation);
8
- * values are icon KEYS from the fixed allow-list resolved by
9
- * src/components/categoryIcons.tsx. Unknown/disallowed values fall back to
10
- * the `Category` icon (a value is NEVER a module path or component — see
11
- * Registry Safety in 05-UI-SPEC.md).
12
- * @visibility frontend
13
- */
14
- categoryIcons?: { [categorySlug: string]: string };
15
5
  /**
16
6
  * Optional org-id -> display-label map for the Org facet.
17
7
  * Keys are raw annotation values (for example `apigee-x-private-p-495866`);
@@ -21,26 +21,23 @@ function LifecycleBadge({
21
21
  }) {
22
22
  return /* @__PURE__ */ jsx("span", { className: `${styles.badge} ${BADGE_KIND_CLASS[kind]}`, children: label });
23
23
  }
24
- function ApiCard({ vm, icon: Icon }) {
24
+ function ApiCard({ vm, onSelect }) {
25
25
  const entityRoute = useRouteRef(entityRouteRef);
26
26
  const { kind, namespace, name } = vm.targetRef;
27
27
  const href = entityRoute ? entityRoute({ kind: kind.toLowerCase(), namespace, name }) : void 0;
28
28
  const ariaLabel = `Open ${vm.name} API details`;
29
29
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
30
30
  /* @__PURE__ */ jsxs("div", { className: styles.header, children: [
31
- /* @__PURE__ */ jsxs("div", { className: styles.titleRow, children: [
32
- Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: styles.categoryIcon, size: 20 }) : null,
33
- /* @__PURE__ */ jsx(
34
- Text,
35
- {
36
- variant: "body-medium",
37
- weight: "bold",
38
- as: "h3",
39
- className: styles.name,
40
- children: vm.name
41
- }
42
- )
43
- ] }),
31
+ /* @__PURE__ */ jsx("div", { className: styles.titleRow, children: /* @__PURE__ */ jsx(
32
+ Text,
33
+ {
34
+ variant: "body-large",
35
+ weight: "bold",
36
+ as: "h3",
37
+ className: styles.name,
38
+ children: vm.name
39
+ }
40
+ ) }),
44
41
  /* @__PURE__ */ jsxs("div", { className: styles.badges, children: [
45
42
  /* @__PURE__ */ jsx(LifecycleBadge, { kind: vm.badge.kind, label: vm.badge.label }),
46
43
  vm.version ? /* @__PURE__ */ jsx("span", { className: `${styles.badge} ${styles.badgeVersion}`, children: vm.version }) : null
@@ -81,7 +78,19 @@ function ApiCard({ vm, icon: Icon }) {
81
78
  /* @__PURE__ */ jsx("div", { className: styles.rightCol })
82
79
  ] })
83
80
  ] });
84
- return /* @__PURE__ */ jsx("div", { className: styles.card, children: href ? /* @__PURE__ */ jsx(Link, { to: href, className: styles.action, "aria-label": ariaLabel, children: content }) : /* @__PURE__ */ jsx("div", { className: styles.action, children: content }) });
81
+ if (onSelect) {
82
+ return /* @__PURE__ */ jsx(
83
+ "button",
84
+ {
85
+ type: "button",
86
+ className: styles.card,
87
+ "aria-label": ariaLabel,
88
+ onClick: () => onSelect(vm),
89
+ children: content
90
+ }
91
+ );
92
+ }
93
+ return href ? /* @__PURE__ */ jsx(Link, { to: href, className: styles.card, "aria-label": ariaLabel, children: content }) : /* @__PURE__ */ jsx("div", { className: styles.card, children: content });
85
94
  }
86
95
 
87
96
  export { ApiCard, LifecycleBadge, VISIBILITY_ICON };
@@ -1 +1 @@
1
- {"version":3,"file":"ApiCard.esm.js","sources":["../../src/components/ApiCard.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { Link } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/frontend-plugin-api';\nimport { entityRouteRef } from '@backstage/plugin-catalog-react';\nimport { Text } from '@backstage/ui';\nimport {\n RiBuildingLine,\n RiFileTextLine,\n RiGlobalLine,\n RiLockLine,\n RiTeamLine,\n type RemixiconComponentType,\n} from '@remixicon/react';\nimport type {\n ApiCardViewModel,\n ApiVisibility,\n LifecycleBadgeKind,\n} from './apiCardViewModel';\nimport styles from './ApiCard.module.css';\n\nexport interface ApiCardProps {\n vm: ApiCardViewModel;\n /** Category icon resolved by the parent grid (05-05); decorative. */\n icon?: RemixiconComponentType;\n}\n\nconst BADGE_KIND_CLASS: Record<LifecycleBadgeKind, string> = {\n ok: styles.badgeOk,\n warning: styles.badgeWarning,\n error: styles.badgeError,\n};\n\nexport const VISIBILITY_ICON: Record<ApiVisibility, RemixiconComponentType> = {\n private: RiLockLine,\n public: RiGlobalLine,\n};\n\n/** Solid colored status pill (D-04). Color conveys state; the text label is the\n * accessible source of truth so it never relies on color alone. */\nexport function LifecycleBadge({\n kind,\n label,\n}: {\n kind: LifecycleBadgeKind;\n label: string;\n}) {\n return (\n <span className={`${styles.badge} ${BADGE_KIND_CLASS[kind]}`}>{label}</span>\n );\n}\n\n/**\n * A single Apigee API tile. The whole card is one anchor-based control whose href is\n * resolved via `entityRouteRef` (never hardcoded — TR04); it degrades to a non-link\n * button when the route ref is unbound (dev harness). Entity text renders as React\n * children only — never via raw HTML injection (T-05-03). (UI-02, UI-03)\n */\nexport function ApiCard({ vm, icon: Icon }: ApiCardProps) {\n const entityRoute = useRouteRef(entityRouteRef);\n const { kind, namespace, name } = vm.targetRef;\n const href = entityRoute\n ? entityRoute({ kind: kind.toLowerCase(), namespace, name })\n : undefined;\n const ariaLabel = `Open ${vm.name} API details`;\n\n const content = (\n <>\n <div className={styles.header}>\n <div className={styles.titleRow}>\n {Icon ? (\n <Icon aria-hidden className={styles.categoryIcon} size={20} />\n ) : null}\n <Text\n variant=\"body-medium\"\n weight=\"bold\"\n as=\"h3\"\n className={styles.name}\n >\n {vm.name}\n </Text>\n </div>\n <div className={styles.badges}>\n <LifecycleBadge kind={vm.badge.kind} label={vm.badge.label} />\n {vm.version ? (\n <span className={`${styles.badge} ${styles.badgeVersion}`}>\n {vm.version}\n </span>\n ) : null}\n </div>\n {vm.description ? (\n <Text\n variant=\"body-small\"\n color=\"secondary\"\n as=\"p\"\n className={styles.description}\n >\n {vm.description}\n </Text>\n ) : null}\n </div>\n\n <div className={styles.body}>\n <div className={styles.leftCol}>\n <div className={styles.metaItem}>\n <RiTeamLine aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n {vm.ownerLabel}\n </Text>\n </div>\n {vm.department ? (\n <div className={styles.metaItem}>\n <RiBuildingLine aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n {vm.department}\n </Text>\n </div>\n ) : null}\n {vm.visibilities.map(visibility => {\n const VisibilityIcon = VISIBILITY_ICON[visibility];\n return (\n <div key={visibility} className={styles.metaItem}>\n <VisibilityIcon aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n {visibility}\n </Text>\n </div>\n );\n })}\n {vm.hasSpec ? (\n <div className={styles.metaItem}>\n <RiFileTextLine aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n OpenAPI spec\n </Text>\n </div>\n ) : null}\n </div>\n\n <div className={styles.rightCol}>\n {/* Quality score + information coverage list — to be implemented later */}\n </div>\n </div>\n </>\n );\n\n return (\n <div className={styles.card}>\n {href ? (\n <Link to={href} className={styles.action} aria-label={ariaLabel}>\n {content}\n </Link>\n ) : (\n <div className={styles.action}>{content}</div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ApiCard.esm.js","sources":["../../src/components/ApiCard.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { Link } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/frontend-plugin-api';\nimport { entityRouteRef } from '@backstage/plugin-catalog-react';\nimport { Text } from '@backstage/ui';\nimport {\n RiBuildingLine,\n RiFileTextLine,\n RiGlobalLine,\n RiLockLine,\n RiTeamLine,\n type RemixiconComponentType,\n} from '@remixicon/react';\nimport type {\n ApiCardViewModel,\n ApiVisibility,\n LifecycleBadgeKind,\n} from './apiCardViewModel';\nimport styles from './ApiCard.module.css';\n\nexport interface ApiCardProps {\n vm: ApiCardViewModel;\n /** When provided, clicking the card opens the details drawer (via this callback)\n * instead of navigating to the catalog entity page. */\n onSelect?: (vm: ApiCardViewModel) => void;\n}\n\nconst BADGE_KIND_CLASS: Record<LifecycleBadgeKind, string> = {\n ok: styles.badgeOk,\n warning: styles.badgeWarning,\n error: styles.badgeError,\n};\n\nexport const VISIBILITY_ICON: Record<ApiVisibility, RemixiconComponentType> = {\n private: RiLockLine,\n public: RiGlobalLine,\n};\n\n/** Solid colored status pill (D-04). Color conveys state; the text label is the\n * accessible source of truth so it never relies on color alone. */\nexport function LifecycleBadge({\n kind,\n label,\n}: {\n kind: LifecycleBadgeKind;\n label: string;\n}) {\n return (\n <span className={`${styles.badge} ${BADGE_KIND_CLASS[kind]}`}>{label}</span>\n );\n}\n\n/**\n * A single Apigee API tile. The whole card is one anchor-based control whose href is\n * resolved via `entityRouteRef` (never hardcoded — TR04); it degrades to a non-link\n * button when the route ref is unbound (dev harness). Entity text renders as React\n * children only — never via raw HTML injection (T-05-03). (UI-02, UI-03)\n */\nexport function ApiCard({ vm, onSelect }: ApiCardProps) {\n const entityRoute = useRouteRef(entityRouteRef);\n const { kind, namespace, name } = vm.targetRef;\n const href = entityRoute\n ? entityRoute({ kind: kind.toLowerCase(), namespace, name })\n : undefined;\n const ariaLabel = `Open ${vm.name} API details`;\n\n const content = (\n <>\n <div className={styles.header}>\n <div className={styles.titleRow}>\n <Text\n variant=\"body-large\"\n weight=\"bold\"\n as=\"h3\"\n className={styles.name}\n >\n {vm.name}\n </Text>\n </div>\n <div className={styles.badges}>\n <LifecycleBadge kind={vm.badge.kind} label={vm.badge.label} />\n {vm.version ? (\n <span className={`${styles.badge} ${styles.badgeVersion}`}>\n {vm.version}\n </span>\n ) : null}\n </div>\n {vm.description ? (\n <Text\n variant=\"body-small\"\n color=\"secondary\"\n as=\"p\"\n className={styles.description}\n >\n {vm.description}\n </Text>\n ) : null}\n </div>\n\n <div className={styles.body}>\n <div className={styles.leftCol}>\n <div className={styles.metaItem}>\n <RiTeamLine aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n {vm.ownerLabel}\n </Text>\n </div>\n {vm.department ? (\n <div className={styles.metaItem}>\n <RiBuildingLine aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n {vm.department}\n </Text>\n </div>\n ) : null}\n {vm.visibilities.map(visibility => {\n const VisibilityIcon = VISIBILITY_ICON[visibility];\n return (\n <div key={visibility} className={styles.metaItem}>\n <VisibilityIcon aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n {visibility}\n </Text>\n </div>\n );\n })}\n {vm.hasSpec ? (\n <div className={styles.metaItem}>\n <RiFileTextLine aria-hidden size={16} />\n <Text variant=\"body-small\" color=\"secondary\" as=\"span\">\n OpenAPI spec\n </Text>\n </div>\n ) : null}\n </div>\n\n <div className={styles.rightCol}>\n {/* Quality score + information coverage list — to be implemented later */}\n </div>\n </div>\n </>\n );\n\n if (onSelect) {\n return (\n <button\n type=\"button\"\n className={styles.card}\n aria-label={ariaLabel}\n onClick={() => onSelect(vm)}\n >\n {content}\n </button>\n );\n }\n\n return href ? (\n <Link to={href} className={styles.card} aria-label={ariaLabel}>\n {content}\n </Link>\n ) : (\n <div className={styles.card}>{content}</div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import styleInject from '../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
2
 
3
- var css_248z = ".ApiCard_card__3afe92d8c5 {\n height: 100%;\n border: 1px solid var(--bui-border-1);\n border-radius: var(--bui-radius-3);\n background-color: var(--bui-bg-neutral-1);\n transition: box-shadow 200ms ease;\n}\n\n.ApiCard_card__3afe92d8c5:hover {\n box-shadow: var(--bui-shadow);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ApiCard_card__3afe92d8c5 {\n transition: none;\n }\n}\n\n.ApiCard_action__3afe92d8c5 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-2);\n height: 100%;\n min-height: 172px;\n padding: var(--bui-space-4);\n color: inherit;\n text-decoration: none;\n border-radius: var(--bui-radius-3);\n}\n\n.ApiCard_action__3afe92d8c5:focus-visible {\n outline: 2px solid var(--bui-ring);\n outline-offset: 2px;\n}\n\n.ApiCard_header__3afe92d8c5 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-2);\n}\n\n.ApiCard_titleRow__3afe92d8c5 {\n display: flex;\n align-items: flex-start;\n gap: var(--bui-space-2);\n}\n\n.ApiCard_categoryIcon__3afe92d8c5 {\n margin-top: 2px;\n color: var(--bui-fg-secondary);\n}\n\n.ApiCard_name__3afe92d8c5 {\n flex: 1;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n word-break: break-word;\n}\n\n.ApiCard_badges__3afe92d8c5 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--bui-space-1);\n}\n\n.ApiCard_badge__3afe92d8c5 {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n padding: 2px var(--bui-space-2);\n border-radius: var(--bui-radius-full);\n font-size: var(--bui-font-size-1);\n font-weight: var(--bui-font-weight-bold);\n line-height: 1.5;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n white-space: nowrap;\n}\n\n.ApiCard_badgeOk__3afe92d8c5 {\n background-color: var(--bui-bg-success);\n color: var(--bui-fg-success-on-bg);\n}\n\n.ApiCard_badgeWarning__3afe92d8c5 {\n background-color: var(--bui-bg-warning);\n color: var(--bui-fg-warning-on-bg);\n}\n\n.ApiCard_badgeError__3afe92d8c5 {\n background-color: var(--bui-bg-danger);\n color: var(--bui-fg-danger-on-bg);\n}\n\n.ApiCard_badgeVersion__3afe92d8c5 {\n background-color: var(--bui-bg-info);\n color: var(--bui-fg-info-on-bg);\n text-transform: none;\n}\n\n.ApiCard_body__3afe92d8c5 {\n display: flex;\n align-items: flex-start;\n gap: var(--bui-space-4);\n}\n\n.ApiCard_leftCol__3afe92d8c5,\n.ApiCard_rightCol__3afe92d8c5 {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-1);\n}\n\n.ApiCard_leftCol__3afe92d8c5 {\n color: var(--bui-fg-secondary);\n}\n\n.ApiCard_metaItem__3afe92d8c5 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--bui-space-1);\n}\n\n.ApiCard_description__3afe92d8c5 {\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n";
4
- var styles = {"card":"ApiCard_card__3afe92d8c5","action":"ApiCard_action__3afe92d8c5","header":"ApiCard_header__3afe92d8c5","titleRow":"ApiCard_titleRow__3afe92d8c5","categoryIcon":"ApiCard_categoryIcon__3afe92d8c5","name":"ApiCard_name__3afe92d8c5","badges":"ApiCard_badges__3afe92d8c5","badge":"ApiCard_badge__3afe92d8c5","badgeOk":"ApiCard_badgeOk__3afe92d8c5","badgeWarning":"ApiCard_badgeWarning__3afe92d8c5","badgeError":"ApiCard_badgeError__3afe92d8c5","badgeVersion":"ApiCard_badgeVersion__3afe92d8c5","body":"ApiCard_body__3afe92d8c5","leftCol":"ApiCard_leftCol__3afe92d8c5","rightCol":"ApiCard_rightCol__3afe92d8c5","metaItem":"ApiCard_metaItem__3afe92d8c5","description":"ApiCard_description__3afe92d8c5"};
3
+ var css_248z = ".ApiCard_card__b286a50f58 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-2);\n height: 100%;\n min-height: 172px;\n padding: var(--bui-space-4);\n color: inherit;\n text-decoration: none;\n border: 1px solid var(--bui-border-1);\n border-radius: var(--bui-radius-3);\n background-color: var(--bui-bg-neutral-1);\n transition: box-shadow 200ms ease;\n}\n\n/* The card IS a MUI Link; element+class beats MUI's class so its self-applied link colour/underline doesn't bleed onto the card content. */\na.ApiCard_card__b286a50f58,\na.ApiCard_card__b286a50f58:hover {\n color: inherit;\n text-decoration: none;\n}\n\n/* The card can also be a <button> (opens the details drawer). Reset UA button\n styling so it renders identically to the anchor/div variants. */\nbutton.ApiCard_card__b286a50f58 {\n width: 100%;\n font: inherit;\n text-align: left;\n cursor: pointer;\n appearance: none;\n}\n\n.ApiCard_card__b286a50f58:hover {\n box-shadow: var(--bui-shadow);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ApiCard_card__b286a50f58 {\n transition: none;\n }\n}\n\n.ApiCard_card__b286a50f58:focus-visible {\n outline: 2px solid var(--bui-ring);\n outline-offset: 2px;\n}\n\n.ApiCard_header__b286a50f58 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-2);\n}\n\n.ApiCard_titleRow__b286a50f58 {\n display: flex;\n align-items: flex-start;\n gap: var(--bui-space-2);\n}\n\n.ApiCard_name__b286a50f58 {\n flex: 1;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n word-break: break-word;\n}\n\n.ApiCard_badges__b286a50f58 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--bui-space-1);\n}\n\n.ApiCard_badge__b286a50f58 {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n padding: 2px var(--bui-space-2);\n border-radius: var(--bui-radius-full);\n font-size: var(--bui-font-size-1);\n font-weight: var(--bui-font-weight-bold);\n line-height: 1.5;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n white-space: nowrap;\n}\n\n.ApiCard_badgeOk__b286a50f58 {\n background-color: var(--bui-bg-success);\n color: var(--bui-fg-success-on-bg);\n}\n\n.ApiCard_badgeWarning__b286a50f58 {\n background-color: var(--bui-bg-warning);\n color: var(--bui-fg-warning-on-bg);\n}\n\n.ApiCard_badgeError__b286a50f58 {\n background-color: var(--bui-bg-danger);\n color: var(--bui-fg-danger-on-bg);\n}\n\n.ApiCard_badgeVersion__b286a50f58 {\n background-color: var(--bui-bg-info);\n color: var(--bui-fg-info-on-bg);\n text-transform: none;\n}\n\n.ApiCard_body__b286a50f58 {\n display: flex;\n align-items: flex-start;\n gap: var(--bui-space-4);\n}\n\n.ApiCard_leftCol__b286a50f58,\n.ApiCard_rightCol__b286a50f58 {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-1);\n}\n\n.ApiCard_leftCol__b286a50f58 {\n color: var(--bui-fg-secondary);\n}\n\n.ApiCard_metaItem__b286a50f58 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--bui-space-1);\n}\n\n.ApiCard_description__b286a50f58 {\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n";
4
+ var styles = {"card":"ApiCard_card__b286a50f58","header":"ApiCard_header__b286a50f58","titleRow":"ApiCard_titleRow__b286a50f58","name":"ApiCard_name__b286a50f58","badges":"ApiCard_badges__b286a50f58","badge":"ApiCard_badge__b286a50f58","badgeOk":"ApiCard_badgeOk__b286a50f58","badgeWarning":"ApiCard_badgeWarning__b286a50f58","badgeError":"ApiCard_badgeError__b286a50f58","badgeVersion":"ApiCard_badgeVersion__b286a50f58","body":"ApiCard_body__b286a50f58","leftCol":"ApiCard_leftCol__b286a50f58","rightCol":"ApiCard_rightCol__b286a50f58","metaItem":"ApiCard_metaItem__b286a50f58","description":"ApiCard_description__b286a50f58"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { styles as default };
@@ -2,20 +2,12 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import { ItemCardGrid } from '@backstage/core-components';
3
3
  import { ApiCard } from './ApiCard.esm.js';
4
4
  import { ApiTable } from './ApiTable.esm.js';
5
- import { resolveCategoryIcon } from './categoryIcons.esm.js';
6
5
 
7
- function ApiCardGrid({ vms, viewMode, overrides }) {
6
+ function ApiCardGrid({ vms, viewMode, onSelect }) {
8
7
  if (viewMode === "list") {
9
- return /* @__PURE__ */ jsx(ApiTable, { vms });
8
+ return /* @__PURE__ */ jsx(ApiTable, { vms, onSelect });
10
9
  }
11
- return /* @__PURE__ */ jsx(ItemCardGrid, { children: vms.map((vm) => /* @__PURE__ */ jsx(
12
- ApiCard,
13
- {
14
- vm,
15
- icon: resolveCategoryIcon(vm.category, overrides)
16
- },
17
- vm.targetRef.name
18
- )) });
10
+ return /* @__PURE__ */ jsx(ItemCardGrid, { children: vms.map((vm) => /* @__PURE__ */ jsx(ApiCard, { vm, onSelect }, vm.targetRef.name)) });
19
11
  }
20
12
 
21
13
  export { ApiCardGrid };
@@ -1 +1 @@
1
- {"version":3,"file":"ApiCardGrid.esm.js","sources":["../../src/components/ApiCardGrid.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { ItemCardGrid } from '@backstage/core-components';\nimport { ApiCard } from './ApiCard';\nimport { ApiTable } from './ApiTable';\nimport type { ApiCardViewModel } from './apiCardViewModel';\nimport { resolveCategoryIcon } from './categoryIcons';\n\nexport type ViewMode = 'flat' | 'list';\n\nexport interface ApiCardGridProps {\n vms: ApiCardViewModel[];\n viewMode: ViewMode;\n /** Raw `apigee.catalog.categoryIcons` override map (slug -> IconKey string). */\n overrides?: Record<string, string>;\n}\n\n/**\n * Presentational grid of `ApiCard` tiles. In `flat` mode a single responsive grid; in\n * `list` mode a table. No data fetching. (UI-01, UI-11)\n */\nexport function ApiCardGrid({ vms, viewMode, overrides }: ApiCardGridProps) {\n if (viewMode === 'list') {\n return <ApiTable vms={vms} />;\n }\n\n return (\n <ItemCardGrid>\n {vms.map(vm => (\n <ApiCard\n key={vm.targetRef.name}\n vm={vm}\n icon={resolveCategoryIcon(vm.category, overrides)}\n />\n ))}\n </ItemCardGrid>\n );\n}\n"],"names":[],"mappings":";;;;;;AAoBO,SAAS,WAAA,CAAY,EAAE,GAAA,EAAK,QAAA,EAAU,WAAU,EAAqB;AAC1E,EAAA,IAAI,aAAa,MAAA,EAAQ;AACvB,IAAA,uBAAO,GAAA,CAAC,YAAS,GAAA,EAAU,CAAA;AAAA,EAC7B;AAEA,EAAA,uBACE,GAAA,CAAC,YAAA,EAAA,EACE,QAAA,EAAA,GAAA,CAAI,GAAA,CAAI,CAAA,EAAA,qBACP,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MAEC,EAAA;AAAA,MACA,IAAA,EAAM,mBAAA,CAAoB,EAAA,CAAG,QAAA,EAAU,SAAS;AAAA,KAAA;AAAA,IAF3C,GAAG,SAAA,CAAU;AAAA,GAIrB,CAAA,EACH,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ApiCardGrid.esm.js","sources":["../../src/components/ApiCardGrid.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { ItemCardGrid } from '@backstage/core-components';\nimport { ApiCard } from './ApiCard';\nimport { ApiTable } from './ApiTable';\nimport type { ApiCardViewModel } from './apiCardViewModel';\n\nexport type ViewMode = 'flat' | 'list';\n\nexport interface ApiCardGridProps {\n vms: ApiCardViewModel[];\n viewMode: ViewMode;\n /** Opens the details drawer for a clicked card/row (both views). */\n onSelect?: (vm: ApiCardViewModel) => void;\n}\n\n/**\n * Presentational grid of `ApiCard` tiles. In `flat` mode a single responsive grid; in\n * `list` mode a table. No data fetching. (UI-01, UI-11)\n */\nexport function ApiCardGrid({ vms, viewMode, onSelect }: ApiCardGridProps) {\n if (viewMode === 'list') {\n return <ApiTable vms={vms} onSelect={onSelect} />;\n }\n\n return (\n <ItemCardGrid>\n {vms.map(vm => (\n <ApiCard key={vm.targetRef.name} vm={vm} onSelect={onSelect} />\n ))}\n </ItemCardGrid>\n );\n}\n"],"names":[],"mappings":";;;;;AAmBO,SAAS,WAAA,CAAY,EAAE,GAAA,EAAK,QAAA,EAAU,UAAS,EAAqB;AACzE,EAAA,IAAI,aAAa,MAAA,EAAQ;AACvB,IAAA,uBAAO,GAAA,CAAC,QAAA,EAAA,EAAS,GAAA,EAAU,QAAA,EAAoB,CAAA;AAAA,EACjD;AAEA,EAAA,uBACE,GAAA,CAAC,YAAA,EAAA,EACE,QAAA,EAAA,GAAA,CAAI,GAAA,CAAI,CAAA,EAAA,qBACP,GAAA,CAAC,OAAA,EAAA,EAAgC,EAAA,EAAQ,QAAA,EAAA,EAA3B,EAAA,CAAG,SAAA,CAAU,IAAkC,CAC9D,CAAA,EACH,CAAA;AAEJ;;;;"}
@@ -0,0 +1,335 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { Link } from '@backstage/core-components';
3
+ import { useApi } from '@backstage/core-plugin-api';
4
+ import { useRouteRef } from '@backstage/frontend-plugin-api';
5
+ import { parseEntityRef } from '@backstage/catalog-model';
6
+ import { catalogApiRef, entityRouteRef, EntityRefLink } from '@backstage/plugin-catalog-react';
7
+ import { Text, ButtonIcon, Button, Tabs, TabList, Tab, TabPanel } from '@backstage/ui';
8
+ import { RiCloseLine, RiExternalLinkLine, RiDownloadLine, RiFileCopyLine } from '@remixicon/react';
9
+ import { useState, useEffect, useMemo, Fragment as Fragment$1 } from 'react';
10
+ import { useNavigate } from 'react-router-dom';
11
+ import { LifecycleBadge } from './ApiCard.esm.js';
12
+ import { toApiDetailViewModel, specFileName } from './apiDetailViewModel.esm.js';
13
+ import styles from './ApiDetailsDrawer.module.css.esm.js';
14
+
15
+ function MetaRow({
16
+ label,
17
+ value,
18
+ children
19
+ }) {
20
+ return /* @__PURE__ */ jsxs("div", { className: styles.metaRow, children: [
21
+ /* @__PURE__ */ jsx("dt", { className: styles.metaLabel, children: label }),
22
+ /* @__PURE__ */ jsx("dd", { className: styles.metaValue, children: children ?? value })
23
+ ] });
24
+ }
25
+ function OwnerValue({ vm }) {
26
+ if (vm.ownerRef) {
27
+ try {
28
+ parseEntityRef(vm.ownerRef, {
29
+ defaultKind: "group",
30
+ defaultNamespace: "default"
31
+ });
32
+ return /* @__PURE__ */ jsx(EntityRefLink, { entityRef: vm.ownerRef, defaultKind: "group" });
33
+ } catch {
34
+ }
35
+ }
36
+ return /* @__PURE__ */ jsx(Fragment, { children: vm.ownerLabel });
37
+ }
38
+ function SpecSection({
39
+ definition,
40
+ fileBaseName,
41
+ definitionHref
42
+ }) {
43
+ const navigate = useNavigate();
44
+ const [copied, setCopied] = useState(false);
45
+ if (!definition.trim()) {
46
+ return /* @__PURE__ */ jsx(Text, { variant: "body-small", color: "secondary", as: "p", children: "No specification available for preview." });
47
+ }
48
+ const handleCopy = async () => {
49
+ await navigator.clipboard.writeText(definition);
50
+ setCopied(true);
51
+ setTimeout(() => setCopied(false), 2e3);
52
+ };
53
+ const handleDownload = () => {
54
+ const blob = new Blob([definition], { type: "text/plain;charset=utf-8" });
55
+ const url = URL.createObjectURL(blob);
56
+ try {
57
+ const anchor = document.createElement("a");
58
+ anchor.href = url;
59
+ anchor.download = specFileName(fileBaseName, definition);
60
+ anchor.click();
61
+ } finally {
62
+ URL.revokeObjectURL(url);
63
+ }
64
+ };
65
+ return /* @__PURE__ */ jsxs("div", { className: styles.spec, children: [
66
+ /* @__PURE__ */ jsxs("div", { className: styles.specActions, children: [
67
+ /* @__PURE__ */ jsx(
68
+ Button,
69
+ {
70
+ size: "small",
71
+ variant: "secondary",
72
+ iconStart: /* @__PURE__ */ jsx(RiDownloadLine, {}),
73
+ onPress: handleDownload,
74
+ children: "Download"
75
+ }
76
+ ),
77
+ /* @__PURE__ */ jsx(
78
+ Button,
79
+ {
80
+ size: "small",
81
+ variant: "secondary",
82
+ iconStart: /* @__PURE__ */ jsx(RiFileCopyLine, {}),
83
+ onPress: handleCopy,
84
+ children: copied ? "Copied!" : "Copy"
85
+ }
86
+ )
87
+ ] }),
88
+ /* @__PURE__ */ jsxs(
89
+ Tabs,
90
+ {
91
+ selectedKey: "raw",
92
+ onSelectionChange: (key) => {
93
+ if (key === "openapi" && definitionHref) {
94
+ navigate(definitionHref);
95
+ }
96
+ },
97
+ children: [
98
+ /* @__PURE__ */ jsxs(TabList, { "aria-label": "Specification format", className: styles.tabList, children: [
99
+ /* @__PURE__ */ jsx(Tab, { id: "openapi", isDisabled: !definitionHref, children: /* @__PURE__ */ jsxs("span", { className: styles.tabLabel, children: [
100
+ "OpenAPI ",
101
+ /* @__PURE__ */ jsx(RiExternalLinkLine, { "aria-hidden": true, size: 12 })
102
+ ] }) }),
103
+ /* @__PURE__ */ jsx(Tab, { id: "raw", children: "Raw" })
104
+ ] }),
105
+ /* @__PURE__ */ jsx(TabPanel, { id: "raw", children: /* @__PURE__ */ jsx("pre", { className: styles.code, children: /* @__PURE__ */ jsx("code", { children: definition }) }) })
106
+ ]
107
+ }
108
+ )
109
+ ] });
110
+ }
111
+ function ApiDetailsDrawerContent({
112
+ entity,
113
+ orgLabels,
114
+ onClose
115
+ }) {
116
+ const catalogApi = useApi(catalogApiRef);
117
+ const entityRoute = useRouteRef(entityRouteRef);
118
+ const [component, setComponent] = useState();
119
+ const namespace = entity.metadata.namespace ?? "default";
120
+ const name = entity.metadata.name;
121
+ useEffect(() => {
122
+ let active = true;
123
+ catalogApi.getEntityByRef({ kind: "Component", namespace, name }).then((found) => {
124
+ if (active) {
125
+ setComponent(found ?? void 0);
126
+ }
127
+ }).catch(() => {
128
+ if (active) {
129
+ setComponent(void 0);
130
+ }
131
+ });
132
+ return () => {
133
+ active = false;
134
+ };
135
+ }, [catalogApi, namespace, name]);
136
+ const vm = useMemo(
137
+ () => toApiDetailViewModel(entity, component, orgLabels),
138
+ [entity, component, orgLabels]
139
+ );
140
+ const catalogHref = entityRoute ? entityRoute({
141
+ kind: vm.targetRef.kind.toLowerCase(),
142
+ namespace: vm.targetRef.namespace,
143
+ name: vm.targetRef.name
144
+ }) : void 0;
145
+ const [open, setOpen] = useState(false);
146
+ useEffect(() => {
147
+ const id = requestAnimationFrame(() => setOpen(true));
148
+ return () => cancelAnimationFrame(id);
149
+ }, []);
150
+ useEffect(() => {
151
+ const onKey = (event) => {
152
+ if (event.key === "Escape") {
153
+ onClose();
154
+ }
155
+ };
156
+ document.addEventListener("keydown", onKey);
157
+ return () => document.removeEventListener("keydown", onKey);
158
+ }, [onClose]);
159
+ const showDeployments = vm.runtimeOrgs.length > 0;
160
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
161
+ /* @__PURE__ */ jsx(
162
+ "div",
163
+ {
164
+ className: styles.overlay,
165
+ "data-open": open,
166
+ onClick: onClose,
167
+ role: "presentation",
168
+ "aria-hidden": !open
169
+ }
170
+ ),
171
+ /* @__PURE__ */ jsxs(
172
+ "aside",
173
+ {
174
+ className: styles.drawer,
175
+ "data-open": open,
176
+ role: "dialog",
177
+ "aria-modal": "true",
178
+ "aria-label": `${vm.name} API details`,
179
+ children: [
180
+ /* @__PURE__ */ jsxs("header", { className: styles.header, children: [
181
+ /* @__PURE__ */ jsxs("div", { className: styles.headerText, children: [
182
+ /* @__PURE__ */ jsx(
183
+ Text,
184
+ {
185
+ variant: "title-small",
186
+ weight: "bold",
187
+ as: "h2",
188
+ className: styles.title,
189
+ children: vm.name
190
+ }
191
+ ),
192
+ /* @__PURE__ */ jsxs("div", { className: styles.badges, children: [
193
+ vm.version ? /* @__PURE__ */ jsx("span", { className: `${styles.badge} ${styles.badgeVersion}`, children: vm.version }) : null,
194
+ /* @__PURE__ */ jsx(LifecycleBadge, { kind: vm.badge.kind, label: vm.badge.label })
195
+ ] })
196
+ ] }),
197
+ /* @__PURE__ */ jsx(
198
+ ButtonIcon,
199
+ {
200
+ icon: /* @__PURE__ */ jsx(RiCloseLine, {}),
201
+ variant: "tertiary",
202
+ onPress: onClose,
203
+ "aria-label": "Close"
204
+ }
205
+ )
206
+ ] }),
207
+ /* @__PURE__ */ jsxs("div", { className: styles.body, children: [
208
+ /* @__PURE__ */ jsxs("section", { className: styles.card, "aria-labelledby": "apigee-overview-title", children: [
209
+ /* @__PURE__ */ jsx(
210
+ Text,
211
+ {
212
+ id: "apigee-overview-title",
213
+ variant: "title-x-small",
214
+ weight: "bold",
215
+ as: "h3",
216
+ className: styles.cardTitle,
217
+ children: "Overview"
218
+ }
219
+ ),
220
+ /* @__PURE__ */ jsxs("dl", { className: styles.metaList, children: [
221
+ /* @__PURE__ */ jsx(MetaRow, { label: "Title", value: vm.name }),
222
+ vm.description ? /* @__PURE__ */ jsx(MetaRow, { label: "Description", value: vm.description }) : null,
223
+ /* @__PURE__ */ jsx(MetaRow, { label: "Kind", value: vm.kind }),
224
+ vm.type ? /* @__PURE__ */ jsx(MetaRow, { label: "Type", value: vm.type }) : null,
225
+ vm.version ? /* @__PURE__ */ jsx(MetaRow, { label: "Version", value: vm.version }) : null,
226
+ /* @__PURE__ */ jsx(MetaRow, { label: "Lifecycle", value: vm.badge.label }),
227
+ /* @__PURE__ */ jsx(MetaRow, { label: "Owner", children: /* @__PURE__ */ jsx(OwnerValue, { vm }) }),
228
+ vm.department ? /* @__PURE__ */ jsx(MetaRow, { label: "Department", value: vm.department }) : null,
229
+ vm.tags.length > 0 ? /* @__PURE__ */ jsx(MetaRow, { label: "Tags", children: /* @__PURE__ */ jsx("div", { className: styles.tags, children: vm.tags.map((tag) => /* @__PURE__ */ jsx("span", { className: styles.tag, children: tag }, tag)) }) }) : null
230
+ ] }),
231
+ showDeployments ? /* @__PURE__ */ jsxs("div", { className: styles.deployments, children: [
232
+ /* @__PURE__ */ jsx(
233
+ Text,
234
+ {
235
+ variant: "body-small",
236
+ weight: "bold",
237
+ as: "h4",
238
+ className: styles.deploymentsTitle,
239
+ children: "Deployments"
240
+ }
241
+ ),
242
+ /* @__PURE__ */ jsxs("table", { className: styles.deploymentsTable, children: [
243
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
244
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "Org" }),
245
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "Environment" }),
246
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "Revision" })
247
+ ] }) }),
248
+ /* @__PURE__ */ jsx("tbody", { children: vm.runtimeOrgs.map((org) => /* @__PURE__ */ jsx(Fragment$1, { children: org.environments.length > 0 ? org.environments.map((env, index) => /* @__PURE__ */ jsxs("tr", { children: [
249
+ index === 0 ? /* @__PURE__ */ jsx(
250
+ "th",
251
+ {
252
+ scope: "rowgroup",
253
+ rowSpan: org.environments.length,
254
+ className: styles.orgCell,
255
+ children: org.label
256
+ }
257
+ ) : null,
258
+ /* @__PURE__ */ jsx("td", { children: env.name }),
259
+ /* @__PURE__ */ jsx("td", { children: env.revision })
260
+ ] }, env.name)) : /* @__PURE__ */ jsxs("tr", { children: [
261
+ /* @__PURE__ */ jsx("th", { scope: "row", className: styles.orgCell, children: org.label }),
262
+ /* @__PURE__ */ jsx("td", { colSpan: 2, className: styles.noDeployments, children: "No deployments" })
263
+ ] }) }, org.value)) })
264
+ ] })
265
+ ] }) : null
266
+ ] }),
267
+ /* @__PURE__ */ jsxs("section", { className: styles.card, "aria-labelledby": "apigee-spec-title", children: [
268
+ /* @__PURE__ */ jsx(
269
+ Text,
270
+ {
271
+ id: "apigee-spec-title",
272
+ variant: "title-x-small",
273
+ weight: "bold",
274
+ as: "h3",
275
+ className: styles.cardTitle,
276
+ children: "Specification"
277
+ }
278
+ ),
279
+ /* @__PURE__ */ jsx(
280
+ SpecSection,
281
+ {
282
+ definition: vm.definition,
283
+ fileBaseName: vm.targetRef.name,
284
+ definitionHref: catalogHref ? `${catalogHref}/definition` : void 0
285
+ }
286
+ )
287
+ ] }),
288
+ catalogHref || vm.sourceRepo ? /* @__PURE__ */ jsxs("section", { className: styles.card, "aria-labelledby": "apigee-links-title", children: [
289
+ /* @__PURE__ */ jsx(
290
+ Text,
291
+ {
292
+ id: "apigee-links-title",
293
+ variant: "title-x-small",
294
+ weight: "bold",
295
+ as: "h3",
296
+ className: styles.cardTitle,
297
+ children: "Links"
298
+ }
299
+ ),
300
+ catalogHref ? /* @__PURE__ */ jsxs(Link, { to: catalogHref, className: styles.catalogLink, children: [
301
+ /* @__PURE__ */ jsx(RiExternalLinkLine, { "aria-hidden": true, size: 14 }),
302
+ " View in catalog"
303
+ ] }) : null,
304
+ vm.sourceRepo ? /* @__PURE__ */ jsxs(Link, { to: vm.sourceRepo.url, className: styles.sourceRepo, children: [
305
+ /* @__PURE__ */ jsx(RiExternalLinkLine, { "aria-hidden": true, size: 14 }),
306
+ " ",
307
+ vm.sourceRepo.title
308
+ ] }) : null
309
+ ] }) : null
310
+ ] })
311
+ ]
312
+ }
313
+ )
314
+ ] });
315
+ }
316
+ function ApiDetailsDrawer({
317
+ entity,
318
+ orgLabels,
319
+ onClose
320
+ }) {
321
+ if (!entity) {
322
+ return null;
323
+ }
324
+ return /* @__PURE__ */ jsx(
325
+ ApiDetailsDrawerContent,
326
+ {
327
+ entity,
328
+ orgLabels,
329
+ onClose
330
+ }
331
+ );
332
+ }
333
+
334
+ export { ApiDetailsDrawer };
335
+ //# sourceMappingURL=ApiDetailsDrawer.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiDetailsDrawer.esm.js","sources":["../../src/components/ApiDetailsDrawer.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { Link } from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useRouteRef } from '@backstage/frontend-plugin-api';\nimport { type Entity, parseEntityRef } from '@backstage/catalog-model';\nimport {\n catalogApiRef,\n entityRouteRef,\n EntityRefLink,\n} from '@backstage/plugin-catalog-react';\nimport {\n Button,\n ButtonIcon,\n Tab,\n TabList,\n TabPanel,\n Tabs,\n Text,\n} from '@backstage/ui';\nimport {\n RiCloseLine,\n RiDownloadLine,\n RiExternalLinkLine,\n RiFileCopyLine,\n} from '@remixicon/react';\nimport { Fragment, type ReactNode, useEffect, useMemo, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { LifecycleBadge } from './ApiCard';\nimport {\n specFileName,\n toApiDetailViewModel,\n type ApiDetailViewModel,\n} from './apiDetailViewModel';\nimport styles from './ApiDetailsDrawer.module.css';\n\nexport interface ApiDetailsDrawerProps {\n /** The selected API entity, or undefined when the drawer is closed. */\n entity: Entity | undefined;\n /** Config `apigee.catalog.orgLabels` — friendly names for org values. */\n orgLabels?: Record<string, string>;\n onClose: () => void;\n}\n\n/** One label/value row in the Overview card. */\nfunction MetaRow({\n label,\n value,\n children,\n}: {\n label: string;\n value?: string;\n children?: ReactNode;\n}) {\n return (\n <div className={styles.metaRow}>\n <dt className={styles.metaLabel}>{label}</dt>\n <dd className={styles.metaValue}>{children ?? value}</dd>\n </div>\n );\n}\n\n/** Owner as a catalog link when the ref parses, else plain humanised text. */\nfunction OwnerValue({ vm }: { vm: ApiDetailViewModel }) {\n if (vm.ownerRef) {\n try {\n parseEntityRef(vm.ownerRef, {\n defaultKind: 'group',\n defaultNamespace: 'default',\n });\n return <EntityRefLink entityRef={vm.ownerRef} defaultKind=\"group\" />;\n } catch {\n // Unparseable ref — fall back to the humanised label below.\n }\n }\n return <>{vm.ownerLabel}</>;\n}\n\n/** The Specification card body: OpenAPI/Raw tabs plus Download + Copy actions. */\n/** The Specification card body: an inline Raw spec tab, plus an OpenAPI tab that redirects to\n * the catalog's API definition page (rendered there by @backstage/plugin-api-docs). Download +\n * Copy act on the raw spec. */\nfunction SpecSection({\n definition,\n fileBaseName,\n definitionHref,\n}: {\n definition: string;\n fileBaseName: string;\n definitionHref?: string;\n}) {\n const navigate = useNavigate();\n const [copied, setCopied] = useState(false);\n\n if (!definition.trim()) {\n return (\n <Text variant=\"body-small\" color=\"secondary\" as=\"p\">\n No specification available for preview.\n </Text>\n );\n }\n\n const handleCopy = async () => {\n await navigator.clipboard.writeText(definition);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n const handleDownload = () => {\n const blob = new Blob([definition], { type: 'text/plain;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n try {\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = specFileName(fileBaseName, definition);\n anchor.click();\n } finally {\n URL.revokeObjectURL(url);\n }\n };\n\n return (\n <div className={styles.spec}>\n <div className={styles.specActions}>\n <Button\n size=\"small\"\n variant=\"secondary\"\n iconStart={<RiDownloadLine />}\n onPress={handleDownload}\n >\n Download\n </Button>\n <Button\n size=\"small\"\n variant=\"secondary\"\n iconStart={<RiFileCopyLine />}\n onPress={handleCopy}\n >\n {copied ? 'Copied!' : 'Copy'}\n </Button>\n </div>\n <Tabs\n selectedKey=\"raw\"\n onSelectionChange={key => {\n // The OpenAPI tab is a redirect to the catalog's API definition page, not an\n // inline panel — the raw tab stays selected and the browser navigates away.\n if (key === 'openapi' && definitionHref) {\n navigate(definitionHref);\n }\n }}\n >\n <TabList aria-label=\"Specification format\" className={styles.tabList}>\n <Tab id=\"openapi\" isDisabled={!definitionHref}>\n <span className={styles.tabLabel}>\n OpenAPI <RiExternalLinkLine aria-hidden size={12} />\n </span>\n </Tab>\n <Tab id=\"raw\">Raw</Tab>\n </TabList>\n <TabPanel id=\"raw\">\n <pre className={styles.code}>\n <code>{definition}</code>\n </pre>\n </TabPanel>\n </Tabs>\n </div>\n );\n}\n\n/**\n * The drawer body. Split from the exported wrapper so `useApi(catalogApiRef)` and the\n * Component fetch only run while a drawer is actually open — the closed drawer renders\n * nothing and touches no APIs (keeps the catalog page's other tests API-free).\n */\nfunction ApiDetailsDrawerContent({\n entity,\n orgLabels,\n onClose,\n}: {\n entity: Entity;\n orgLabels?: Record<string, string>;\n onClose: () => void;\n}) {\n const catalogApi = useApi(catalogApiRef);\n const entityRoute = useRouteRef(entityRouteRef);\n\n // Runtime env/revision data lives on the sibling Component (same name/namespace),\n // fetched lazily on open. Hub-only APIs have no Component → orgs render without envs.\n const [component, setComponent] = useState<Entity | undefined>();\n const namespace = entity.metadata.namespace ?? 'default';\n const name = entity.metadata.name;\n useEffect(() => {\n let active = true;\n catalogApi\n .getEntityByRef({ kind: 'Component', namespace, name })\n .then(found => {\n if (active) {\n setComponent(found ?? undefined);\n }\n })\n .catch(() => {\n if (active) {\n setComponent(undefined);\n }\n });\n return () => {\n active = false;\n };\n }, [catalogApi, namespace, name]);\n\n const vm = useMemo(\n () => toApiDetailViewModel(entity, component, orgLabels),\n [entity, component, orgLabels],\n );\n\n const catalogHref = entityRoute\n ? entityRoute({\n kind: vm.targetRef.kind.toLowerCase(),\n namespace: vm.targetRef.namespace,\n name: vm.targetRef.name,\n })\n : undefined;\n\n // Mount closed, then flip open on the next frame so the slide-in transition plays.\n const [open, setOpen] = useState(false);\n useEffect(() => {\n const id = requestAnimationFrame(() => setOpen(true));\n return () => cancelAnimationFrame(id);\n }, []);\n\n useEffect(() => {\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n const showDeployments = vm.runtimeOrgs.length > 0;\n\n return (\n <>\n <div\n className={styles.overlay}\n data-open={open}\n onClick={onClose}\n role=\"presentation\"\n aria-hidden={!open}\n />\n <aside\n className={styles.drawer}\n data-open={open}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`${vm.name} API details`}\n >\n <header className={styles.header}>\n <div className={styles.headerText}>\n <Text\n variant=\"title-small\"\n weight=\"bold\"\n as=\"h2\"\n className={styles.title}\n >\n {vm.name}\n </Text>\n <div className={styles.badges}>\n {vm.version ? (\n <span className={`${styles.badge} ${styles.badgeVersion}`}>\n {vm.version}\n </span>\n ) : null}\n <LifecycleBadge kind={vm.badge.kind} label={vm.badge.label} />\n </div>\n </div>\n <ButtonIcon\n icon={<RiCloseLine />}\n variant=\"tertiary\"\n onPress={onClose}\n aria-label=\"Close\"\n />\n </header>\n\n <div className={styles.body}>\n <section className={styles.card} aria-labelledby=\"apigee-overview-title\">\n <Text\n id=\"apigee-overview-title\"\n variant=\"title-x-small\"\n weight=\"bold\"\n as=\"h3\"\n className={styles.cardTitle}\n >\n Overview\n </Text>\n <dl className={styles.metaList}>\n <MetaRow label=\"Title\" value={vm.name} />\n {vm.description ? (\n <MetaRow label=\"Description\" value={vm.description} />\n ) : null}\n <MetaRow label=\"Kind\" value={vm.kind} />\n {vm.type ? <MetaRow label=\"Type\" value={vm.type} /> : null}\n {vm.version ? (\n <MetaRow label=\"Version\" value={vm.version} />\n ) : null}\n <MetaRow label=\"Lifecycle\" value={vm.badge.label} />\n <MetaRow label=\"Owner\">\n <OwnerValue vm={vm} />\n </MetaRow>\n {vm.department ? (\n <MetaRow label=\"Department\" value={vm.department} />\n ) : null}\n {vm.tags.length > 0 ? (\n <MetaRow label=\"Tags\">\n <div className={styles.tags}>\n {vm.tags.map(tag => (\n <span key={tag} className={styles.tag}>\n {tag}\n </span>\n ))}\n </div>\n </MetaRow>\n ) : null}\n </dl>\n\n {showDeployments ? (\n <div className={styles.deployments}>\n <Text\n variant=\"body-small\"\n weight=\"bold\"\n as=\"h4\"\n className={styles.deploymentsTitle}\n >\n Deployments\n </Text>\n <table className={styles.deploymentsTable}>\n <thead>\n <tr>\n <th scope=\"col\">Org</th>\n <th scope=\"col\">Environment</th>\n <th scope=\"col\">Revision</th>\n </tr>\n </thead>\n <tbody>\n {vm.runtimeOrgs.map(org => (\n <Fragment key={org.value}>\n {org.environments.length > 0 ? (\n org.environments.map((env, index) => (\n <tr key={env.name}>\n {index === 0 ? (\n <th\n scope=\"rowgroup\"\n rowSpan={org.environments.length}\n className={styles.orgCell}\n >\n {org.label}\n </th>\n ) : null}\n <td>{env.name}</td>\n <td>{env.revision}</td>\n </tr>\n ))\n ) : (\n <tr>\n <th scope=\"row\" className={styles.orgCell}>\n {org.label}\n </th>\n <td colSpan={2} className={styles.noDeployments}>\n No deployments\n </td>\n </tr>\n )}\n </Fragment>\n ))}\n </tbody>\n </table>\n </div>\n ) : null}\n </section>\n\n <section className={styles.card} aria-labelledby=\"apigee-spec-title\">\n <Text\n id=\"apigee-spec-title\"\n variant=\"title-x-small\"\n weight=\"bold\"\n as=\"h3\"\n className={styles.cardTitle}\n >\n Specification\n </Text>\n <SpecSection\n definition={vm.definition}\n fileBaseName={vm.targetRef.name}\n definitionHref={\n catalogHref ? `${catalogHref}/definition` : undefined\n }\n />\n </section>\n\n {catalogHref || vm.sourceRepo ? (\n <section className={styles.card} aria-labelledby=\"apigee-links-title\">\n <Text\n id=\"apigee-links-title\"\n variant=\"title-x-small\"\n weight=\"bold\"\n as=\"h3\"\n className={styles.cardTitle}\n >\n Links\n </Text>\n {catalogHref ? (\n <Link to={catalogHref} className={styles.catalogLink}>\n <RiExternalLinkLine aria-hidden size={14} /> View in catalog\n </Link>\n ) : null}\n {vm.sourceRepo ? (\n <Link to={vm.sourceRepo.url} className={styles.sourceRepo}>\n <RiExternalLinkLine aria-hidden size={14} /> {vm.sourceRepo.title}\n </Link>\n ) : null}\n </section>\n ) : null}\n </div>\n </aside>\n </>\n );\n}\n\n/**\n * Side drawer with full details for an Apigee API — opened from a card/row instead of\n * navigating to the catalog entity page. Renders nothing when no entity is selected.\n * (Header: title + version/lifecycle badges · Overview · Specification · Links cards.)\n */\nexport function ApiDetailsDrawer({\n entity,\n orgLabels,\n onClose,\n}: ApiDetailsDrawerProps) {\n if (!entity) {\n return null;\n }\n return (\n <ApiDetailsDrawerContent\n entity={entity}\n orgLabels={orgLabels}\n onClose={onClose}\n />\n );\n}\n"],"names":["Fragment"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = "/* SPDX-License-Identifier: Apache-2.0 */\n\n.ApiDetailsDrawer_overlay__4d2ff9c469 {\n position: fixed;\n inset: 0;\n background-color: rgba(0, 0, 0, 0.3);\n z-index: 1299;\n opacity: 0;\n pointer-events: none;\n transition: opacity 220ms ease;\n}\n\n.ApiDetailsDrawer_overlay__4d2ff9c469[data-open='true'] {\n opacity: 1;\n pointer-events: auto;\n}\n\n.ApiDetailsDrawer_drawer__4d2ff9c469 {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 560px;\n max-width: 100vw;\n display: flex;\n flex-direction: column;\n /* An opaque surface token: the drawer floats over the page, so it must bring its own\n background rather than a translucent neutral that assumes a solid layer beneath it. */\n background-color: var(--bui-bg-app);\n border-left: 1px solid var(--bui-border-1);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1300;\n transform: translateX(100%);\n transition: transform 260ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.ApiDetailsDrawer_drawer__4d2ff9c469[data-open='true'] {\n transform: translateX(0);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ApiDetailsDrawer_overlay__4d2ff9c469,\n .ApiDetailsDrawer_drawer__4d2ff9c469 {\n transition: none;\n }\n}\n\n.ApiDetailsDrawer_header__4d2ff9c469 {\n display: flex;\n align-items: flex-start;\n gap: var(--bui-space-2);\n padding: var(--bui-space-4);\n border-bottom: 1px solid var(--bui-border-1);\n}\n\n.ApiDetailsDrawer_headerText__4d2ff9c469 {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-2);\n}\n\n.ApiDetailsDrawer_title__4d2ff9c469 {\n word-break: break-word;\n}\n\n.ApiDetailsDrawer_badges__4d2ff9c469 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--bui-space-1);\n}\n\n.ApiDetailsDrawer_badge__4d2ff9c469 {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n padding: 2px var(--bui-space-2);\n border-radius: var(--bui-radius-full);\n font-size: var(--bui-font-size-1);\n font-weight: var(--bui-font-weight-bold);\n line-height: 1.5;\n white-space: nowrap;\n}\n\n.ApiDetailsDrawer_badgeVersion__4d2ff9c469 {\n background-color: var(--bui-bg-info);\n color: var(--bui-fg-info-on-bg);\n}\n\n.ApiDetailsDrawer_body__4d2ff9c469 {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-4);\n padding: var(--bui-space-4);\n}\n\n.ApiDetailsDrawer_card__4d2ff9c469 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-3);\n padding: var(--bui-space-4);\n border: 1px solid var(--bui-border-1);\n border-radius: var(--bui-radius-3);\n background-color: var(--bui-bg-neutral-1);\n}\n\n.ApiDetailsDrawer_cardTitle__4d2ff9c469 {\n margin: 0;\n}\n\n.ApiDetailsDrawer_catalogLink__4d2ff9c469,\n.ApiDetailsDrawer_sourceRepo__4d2ff9c469 {\n display: inline-flex;\n align-items: center;\n gap: var(--bui-space-1);\n width: fit-content;\n}\n\n.ApiDetailsDrawer_metaList__4d2ff9c469 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-2);\n margin: 0;\n}\n\n.ApiDetailsDrawer_metaRow__4d2ff9c469 {\n display: grid;\n grid-template-columns: 120px 1fr;\n gap: var(--bui-space-2);\n align-items: start;\n}\n\n.ApiDetailsDrawer_metaLabel__4d2ff9c469 {\n margin: 0;\n color: var(--bui-fg-secondary);\n font-size: var(--bui-font-size-2);\n font-weight: var(--bui-font-weight-bold);\n}\n\n.ApiDetailsDrawer_metaValue__4d2ff9c469 {\n margin: 0;\n min-width: 0;\n font-size: var(--bui-font-size-2);\n word-break: break-word;\n}\n\n.ApiDetailsDrawer_tags__4d2ff9c469 {\n display: flex;\n flex-wrap: wrap;\n gap: var(--bui-space-1);\n}\n\n.ApiDetailsDrawer_tag__4d2ff9c469 {\n display: inline-flex;\n align-items: center;\n padding: 1px var(--bui-space-2);\n border-radius: var(--bui-radius-full);\n background-color: var(--bui-bg-neutral-2);\n color: var(--bui-fg-secondary);\n font-size: var(--bui-font-size-1);\n}\n\n.ApiDetailsDrawer_deployments__4d2ff9c469 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-2);\n padding-top: var(--bui-space-2);\n border-top: 1px solid var(--bui-border-1);\n}\n\n.ApiDetailsDrawer_deploymentsTitle__4d2ff9c469 {\n margin: 0;\n}\n\n.ApiDetailsDrawer_deploymentsTable__4d2ff9c469 {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--bui-font-size-2);\n}\n\n.ApiDetailsDrawer_deploymentsTable__4d2ff9c469 th,\n.ApiDetailsDrawer_deploymentsTable__4d2ff9c469 td {\n padding: var(--bui-space-1) var(--bui-space-2);\n text-align: left;\n border: 1px solid var(--bui-border-1);\n}\n\n.ApiDetailsDrawer_deploymentsTable__4d2ff9c469 thead th {\n color: var(--bui-fg-secondary);\n font-weight: var(--bui-font-weight-bold);\n background-color: var(--bui-bg-neutral-2);\n}\n\n.ApiDetailsDrawer_orgCell__4d2ff9c469 {\n vertical-align: top;\n font-weight: var(--bui-font-weight-bold);\n white-space: nowrap;\n}\n\n.ApiDetailsDrawer_noDeployments__4d2ff9c469 {\n color: var(--bui-fg-secondary);\n}\n\n.ApiDetailsDrawer_spec__4d2ff9c469 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-3);\n}\n\n.ApiDetailsDrawer_specActions__4d2ff9c469 {\n display: flex;\n gap: var(--bui-space-2);\n}\n\n.ApiDetailsDrawer_tabList__4d2ff9c469 {\n margin-bottom: var(--bui-space-2);\n}\n\n.ApiDetailsDrawer_tabLabel__4d2ff9c469 {\n display: inline-flex;\n align-items: center;\n gap: var(--bui-space-1);\n}\n\n.ApiDetailsDrawer_code__4d2ff9c469 {\n margin: 0;\n max-height: 320px;\n overflow: auto;\n padding: var(--bui-space-3);\n border-radius: var(--bui-radius-2);\n background-color: var(--bui-bg-neutral-2);\n font-family: var(--bui-font-family-mono, monospace);\n font-size: var(--bui-font-size-1);\n line-height: 1.5;\n white-space: pre;\n tab-size: 2;\n}\n";
4
+ var styles = {"overlay":"ApiDetailsDrawer_overlay__4d2ff9c469","drawer":"ApiDetailsDrawer_drawer__4d2ff9c469","header":"ApiDetailsDrawer_header__4d2ff9c469","headerText":"ApiDetailsDrawer_headerText__4d2ff9c469","title":"ApiDetailsDrawer_title__4d2ff9c469","badges":"ApiDetailsDrawer_badges__4d2ff9c469","badge":"ApiDetailsDrawer_badge__4d2ff9c469","badgeVersion":"ApiDetailsDrawer_badgeVersion__4d2ff9c469","body":"ApiDetailsDrawer_body__4d2ff9c469","card":"ApiDetailsDrawer_card__4d2ff9c469","cardTitle":"ApiDetailsDrawer_cardTitle__4d2ff9c469","catalogLink":"ApiDetailsDrawer_catalogLink__4d2ff9c469","sourceRepo":"ApiDetailsDrawer_sourceRepo__4d2ff9c469","metaList":"ApiDetailsDrawer_metaList__4d2ff9c469","metaRow":"ApiDetailsDrawer_metaRow__4d2ff9c469","metaLabel":"ApiDetailsDrawer_metaLabel__4d2ff9c469","metaValue":"ApiDetailsDrawer_metaValue__4d2ff9c469","tags":"ApiDetailsDrawer_tags__4d2ff9c469","tag":"ApiDetailsDrawer_tag__4d2ff9c469","deployments":"ApiDetailsDrawer_deployments__4d2ff9c469","deploymentsTitle":"ApiDetailsDrawer_deploymentsTitle__4d2ff9c469","deploymentsTable":"ApiDetailsDrawer_deploymentsTable__4d2ff9c469","orgCell":"ApiDetailsDrawer_orgCell__4d2ff9c469","noDeployments":"ApiDetailsDrawer_noDeployments__4d2ff9c469","spec":"ApiDetailsDrawer_spec__4d2ff9c469","specActions":"ApiDetailsDrawer_specActions__4d2ff9c469","tabList":"ApiDetailsDrawer_tabList__4d2ff9c469","tabLabel":"ApiDetailsDrawer_tabLabel__4d2ff9c469","code":"ApiDetailsDrawer_code__4d2ff9c469"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=ApiDetailsDrawer.module.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiDetailsDrawer.module.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}