@backstage/plugin-app 0.4.1-next.2 → 0.4.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 (54) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/apis/PluginHeaderActionsApi/DefaultPluginHeaderActionsApi.esm.js +8 -1
  3. package/dist/apis/PluginHeaderActionsApi/DefaultPluginHeaderActionsApi.esm.js.map +1 -1
  4. package/dist/apis/PluginWrapperApi/DefaultPluginWrapperApi.esm.js +134 -15
  5. package/dist/apis/PluginWrapperApi/DefaultPluginWrapperApi.esm.js.map +1 -1
  6. package/dist/apis/ToastApiForwarder.esm.js +94 -0
  7. package/dist/apis/ToastApiForwarder.esm.js.map +1 -0
  8. package/dist/apis/toastApiForwarderRef.esm.js +8 -0
  9. package/dist/apis/toastApiForwarderRef.esm.js.map +1 -0
  10. package/dist/components/Toast/Toast.esm.js +156 -0
  11. package/dist/components/Toast/Toast.esm.js.map +1 -0
  12. package/dist/components/Toast/Toast.module.css.esm.js +8 -0
  13. package/dist/components/Toast/Toast.module.css.esm.js.map +1 -0
  14. package/dist/components/Toast/ToastContainer.esm.js +90 -0
  15. package/dist/components/Toast/ToastContainer.esm.js.map +1 -0
  16. package/dist/components/Toast/ToastDisplay.esm.js +51 -0
  17. package/dist/components/Toast/ToastDisplay.esm.js.map +1 -0
  18. package/dist/defaultApis.esm.js +19 -1
  19. package/dist/defaultApis.esm.js.map +1 -1
  20. package/dist/extensions/AppNav.esm.js +35 -6
  21. package/dist/extensions/AppNav.esm.js.map +1 -1
  22. package/dist/extensions/AppRoot.esm.js +40 -34
  23. package/dist/extensions/AppRoot.esm.js.map +1 -1
  24. package/dist/extensions/IconsApi.esm.js.map +1 -1
  25. package/dist/extensions/PluginWrapperApi.esm.js +1 -2
  26. package/dist/extensions/PluginWrapperApi.esm.js.map +1 -1
  27. package/dist/extensions/components.esm.js +30 -18
  28. package/dist/extensions/components.esm.js.map +1 -1
  29. package/dist/extensions/elements.esm.js +4 -2
  30. package/dist/extensions/elements.esm.js.map +1 -1
  31. package/dist/hooks/useInvertedThemeMode.esm.js +41 -0
  32. package/dist/hooks/useInvertedThemeMode.esm.js.map +1 -0
  33. package/dist/index.d.ts +20 -6
  34. package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js +29 -0
  35. package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js.map +1 -0
  36. package/dist/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.esm.js +7 -0
  37. package/dist/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.esm.js.map +1 -1
  38. package/dist/packages/core-app-api/src/apis/implementations/auth/saml/types.esm.js +1 -1
  39. package/dist/packages/core-app-api/src/apis/implementations/auth/saml/types.esm.js.map +1 -1
  40. package/dist/packages/core-app-api/src/app/AppRouter.esm.js +11 -10
  41. package/dist/packages/core-app-api/src/app/AppRouter.esm.js.map +1 -1
  42. package/dist/packages/frontend-app-api/src/apis/implementations/IconsApi/DefaultIconsApi.esm.js +39 -3
  43. package/dist/packages/frontend-app-api/src/apis/implementations/IconsApi/DefaultIconsApi.esm.js.map +1 -1
  44. package/dist/packages/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js.map +1 -1
  45. package/dist/packages/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js.map +1 -1
  46. package/dist/packages/ui/src/hooks/useBg.esm.js +19 -0
  47. package/dist/packages/ui/src/hooks/useBg.esm.js.map +1 -0
  48. package/dist/packages/ui/src/hooks/useBreakpoint.esm.js +17 -0
  49. package/dist/packages/ui/src/hooks/useBreakpoint.esm.js.map +1 -0
  50. package/dist/packages/ui/src/hooks/useDefinition/helpers.esm.js +4 -0
  51. package/dist/packages/ui/src/hooks/useDefinition/helpers.esm.js.map +1 -0
  52. package/dist/plugins/app/package.json.esm.js +9 -2
  53. package/dist/plugins/app/package.json.esm.js.map +1 -1
  54. package/package.json +24 -17
@@ -0,0 +1,8 @@
1
+ import styleInject from '../../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = "/*\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\n/* Toast Container - Container for all toasts (bottom center) */\n.Toast_container__de4a119ac3 {\n position: fixed;\n bottom: 1rem;\n left: 50%;\n transform: translateX(-50%);\n z-index: 100050;\n width: 300px;\n outline: none;\n}\n\n@media (min-width: 500px) {\n .Toast_container__de4a119ac3 {\n width: 350px;\n bottom: 2rem;\n }\n}\n\n/* Individual Toast */\n.Toast_toast__de4a119ac3 {\n /* CSS Variables */\n --toast-peek: 0.75rem;\n --toast-scale: calc(max(0, 1 - (var(--toast-index) * 0.05)));\n\n /* Layout */\n position: absolute;\n bottom: 0;\n left: 0;\n width: 100%;\n margin: 0 auto;\n box-sizing: border-box;\n\n outline: none;\n cursor: default;\n user-select: none;\n /* All toasts need pointer-events to trigger hover expansion */\n pointer-events: auto;\n\n /* Stacking */\n z-index: calc(1000 - var(--toast-index));\n transform-origin: bottom center;\n}\n\n.Toast_surface__de4a119ac3 {\n width: 100%;\n box-sizing: border-box;\n display: flex;\n align-items: flex-start;\n padding: var(--bui-space-4);\n gap: var(--bui-space-3);\n border-radius: var(--bui-radius-3);\n font-size: var(--bui-font-size-3);\n background-color: var(--bui-bg-app);\n border: 1px solid var(--bui-border-1);\n color: var(--bui-fg-primary);\n box-shadow: var(--bui-shadow);\n}\n\n.Toast_toast__de4a119ac3:focus-visible {\n outline: 2px solid var(--bui-ring);\n outline-offset: 2px;\n}\n\n/* Extend hover area above each toast to fill gaps when expanded */\n/* This prevents the stack from collapsing when hovering between toasts */\n.Toast_toast__de4a119ac3::before {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 0;\n right: 0;\n /* Height matches the expanded gap to ensure continuous hover */\n height: 12px;\n pointer-events: auto;\n}\n\n/* Status variants - color icon and title */\n.Toast_toast__de4a119ac3[data-status='neutral'] .Toast_title__de4a119ac3 {\n color: var(--bui-fg-primary);\n}\n\n.Toast_toast__de4a119ac3[data-status='info'] .Toast_icon__de4a119ac3,\n.Toast_toast__de4a119ac3[data-status='info'] .Toast_title__de4a119ac3 {\n color: var(--bui-fg-info);\n}\n\n.Toast_toast__de4a119ac3[data-status='success'] .Toast_icon__de4a119ac3,\n.Toast_toast__de4a119ac3[data-status='success'] .Toast_title__de4a119ac3 {\n color: var(--bui-fg-success);\n}\n\n.Toast_toast__de4a119ac3[data-status='warning'] .Toast_icon__de4a119ac3,\n.Toast_toast__de4a119ac3[data-status='warning'] .Toast_title__de4a119ac3 {\n color: var(--bui-fg-warning);\n}\n\n.Toast_toast__de4a119ac3[data-status='danger'] .Toast_icon__de4a119ac3,\n.Toast_toast__de4a119ac3[data-status='danger'] .Toast_title__de4a119ac3 {\n color: var(--bui-fg-danger);\n}\n\n.Toast_wrapper__de4a119ac3 {\n display: flex;\n align-items: flex-start;\n gap: var(--bui-space-3);\n flex: 1;\n min-width: 0;\n}\n\n.Toast_content__de4a119ac3 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-1);\n}\n\n/* Icon */\n.Toast_icon__de4a119ac3 {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-top: var(--bui-space-0_5);\n}\n\n.Toast_icon__de4a119ac3 svg {\n width: 1rem;\n height: 1rem;\n}\n\n/* Title */\n.Toast_title__de4a119ac3 {\n font-weight: var(--bui-font-weight-bold);\n font-size: var(--bui-font-size-3);\n word-wrap: break-word;\n margin-top: var(--bui-space-0_5);\n}\n\n/* Description */\n.Toast_description__de4a119ac3 {\n color: var(--bui-fg-secondary);\n font-size: var(--bui-font-size-3);\n opacity: 0.9;\n word-wrap: break-word;\n}\n\n/* Links */\n.Toast_links__de4a119ac3 {\n display: flex;\n flex-wrap: wrap;\n gap: var(--bui-space-3);\n margin-top: var(--bui-space-1);\n}\n\n.Toast_links__de4a119ac3 a {\n font-family: var(--bui-font-regular);\n padding: 0;\n margin: 0;\n cursor: pointer;\n display: inline-block;\n\n text-decoration-line: underline;\n text-decoration-style: solid;\n text-decoration-thickness: min(2px, max(1px, 0.05em));\n text-underline-offset: calc(0.025em + 2px);\n text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);\n}\n\n.Toast_links__de4a119ac3 a:hover {\n text-decoration-line: underline;\n text-decoration-style: solid;\n text-decoration-thickness: min(2px, max(1px, 0.05em));\n text-underline-offset: calc(0.025em + 2px);\n text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);\n}\n\n/* Close Button */\n.Toast_closeButton__de4a119ac3 {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n margin: -0.25rem -0.25rem 0 0;\n padding: 0;\n border: none;\n border-radius: var(--bui-radius-2);\n background: transparent;\n color: inherit;\n cursor: pointer;\n transition: background-color 0.15s ease;\n color: var(--bui-fg-primary);\n}\n\n.Toast_closeButton__de4a119ac3 svg {\n width: 1rem;\n height: 1rem;\n}\n\n.Toast_closeButton__de4a119ac3:hover {\n background-color: var(--bui-bg-neutral-1-hover);\n}\n\n.Toast_closeButton__de4a119ac3:focus-visible {\n outline: 2px solid var(--bui-ring);\n outline-offset: 1px;\n}\n\n.Toast_closeButton__de4a119ac3:active {\n background-color: var(--bui-bg-neutral-1-pressed);\n}\n";
4
+ var styles = {"container":"Toast_container__de4a119ac3","toast":"Toast_toast__de4a119ac3","surface":"Toast_surface__de4a119ac3","title":"Toast_title__de4a119ac3","icon":"Toast_icon__de4a119ac3","wrapper":"Toast_wrapper__de4a119ac3","content":"Toast_content__de4a119ac3","description":"Toast_description__de4a119ac3","links":"Toast_links__de4a119ac3","closeButton":"Toast_closeButton__de4a119ac3"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=Toast.module.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.module.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,90 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { forwardRef, useRef, useState, useCallback, useMemo } from 'react';
3
+ import { useToastRegion } from '@react-aria/toast';
4
+ import { useToastQueue } from '@react-stately/toast';
5
+ import { AnimatePresence } from 'motion/react';
6
+ import { useInvertedThemeMode } from '../../hooks/useInvertedThemeMode.esm.js';
7
+ import { Toast } from './Toast.esm.js';
8
+ import styles from './Toast.module.css.esm.js';
9
+
10
+ const ToastContainer = forwardRef(
11
+ (props, ref) => {
12
+ const { queue, className } = props;
13
+ const state = useToastQueue(queue);
14
+ const internalRef = useRef(null);
15
+ const containerRef = ref || internalRef;
16
+ const { regionProps } = useToastRegion({}, state, containerRef);
17
+ const [isHovered, setIsHovered] = useState(false);
18
+ const [isHoverLocked, setIsHoverLocked] = useState(false);
19
+ const unlockTimerRef = useRef(null);
20
+ const isExpanded = isHovered || isHoverLocked;
21
+ const [toastHeights, setToastHeights] = useState(
22
+ {}
23
+ );
24
+ const handleHeightChange = useCallback((key, height) => {
25
+ setToastHeights((prev) => {
26
+ if (prev[key] === height) return prev;
27
+ return { ...prev, [key]: height };
28
+ });
29
+ }, []);
30
+ const { expandedYPositions, frontToastHeight } = useMemo(() => {
31
+ const gap = 8;
32
+ const positions = {};
33
+ let frontHeight = 60;
34
+ const toasts = state.visibleToasts;
35
+ if (toasts.length > 0 && toastHeights[toasts[0].key]) {
36
+ frontHeight = toastHeights[toasts[0].key];
37
+ }
38
+ let cumulativeY = 0;
39
+ for (let i = 0; i < toasts.length; i++) {
40
+ positions[toasts[i].key] = -cumulativeY;
41
+ const height = toastHeights[toasts[i].key] || 60;
42
+ cumulativeY += height + gap;
43
+ }
44
+ return { expandedYPositions: positions, frontToastHeight: frontHeight };
45
+ }, [state.visibleToasts, toastHeights]);
46
+ const invertedThemeMode = useInvertedThemeMode();
47
+ const handleClose = () => {
48
+ setIsHoverLocked(true);
49
+ if (unlockTimerRef.current) {
50
+ clearTimeout(unlockTimerRef.current);
51
+ }
52
+ unlockTimerRef.current = setTimeout(() => {
53
+ setIsHoverLocked(false);
54
+ }, 500);
55
+ };
56
+ return /* @__PURE__ */ jsx(
57
+ "div",
58
+ {
59
+ ...regionProps,
60
+ ref: containerRef,
61
+ className: className || styles.container,
62
+ "data-theme-mode": invertedThemeMode,
63
+ "data-hover-locked": isHoverLocked ? "" : void 0,
64
+ onMouseEnter: () => setIsHovered(true),
65
+ onMouseLeave: () => setIsHovered(false),
66
+ onFocus: () => setIsHovered(true),
67
+ onBlur: () => setIsHovered(false),
68
+ children: /* @__PURE__ */ jsx(AnimatePresence, { children: state.visibleToasts.map((toast, index) => /* @__PURE__ */ jsx(
69
+ Toast,
70
+ {
71
+ toast,
72
+ state,
73
+ index,
74
+ isExpanded,
75
+ onClose: handleClose,
76
+ expandedY: expandedYPositions[toast.key] ?? 0,
77
+ collapsedHeight: index > 0 ? frontToastHeight : void 0,
78
+ naturalHeight: toastHeights[toast.key],
79
+ onHeightChange: handleHeightChange
80
+ },
81
+ toast.key
82
+ )) })
83
+ }
84
+ );
85
+ }
86
+ );
87
+ ToastContainer.displayName = "ToastContainer";
88
+
89
+ export { ToastContainer };
90
+ //# sourceMappingURL=ToastContainer.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToastContainer.esm.js","sources":["../../../src/components/Toast/ToastContainer.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 { forwardRef, Ref, useState, useRef, useCallback, useMemo } from 'react';\nimport { useToastRegion } from '@react-aria/toast';\nimport { useToastQueue } from '@react-stately/toast';\nimport { AnimatePresence } from 'motion/react';\nimport type { ToastApiMessageContainerProps } from './types';\nimport { useInvertedThemeMode } from '../../hooks/useInvertedThemeMode';\nimport { Toast } from './Toast';\nimport styles from './Toast.module.css';\n\n/**\n * A ToastContainer displays one or more toast notifications in the bottom-center of the screen.\n *\n * @remarks\n * The ToastContainer component should typically be placed once at the root of your application.\n * It manages the display and stacking of all toast notifications added to its queue.\n * Toasts appear in the bottom-center with deep stacking when multiple are visible.\n * Toast containers are ARIA landmark regions that can be navigated using F6 (forward) and\n * Shift+F6 (backward) for keyboard accessibility.\n *\n * @internal\n */\nexport const ToastContainer = forwardRef(\n (props: ToastApiMessageContainerProps, ref: Ref<HTMLDivElement>) => {\n const { queue, className } = props;\n\n // Subscribe to the toast queue state\n const state = useToastQueue(queue);\n\n // Use internal ref if none provided\n const internalRef = useRef<HTMLDivElement>(null);\n const containerRef =\n (ref as React.RefObject<HTMLDivElement>) || internalRef;\n\n // Get ARIA props for the toast region\n const { regionProps } = useToastRegion({}, state, containerRef);\n\n // Track hover state for expanding/collapsing the stack\n const [isHovered, setIsHovered] = useState(false);\n\n // Lock expanded state after close to prevent stack collapse during exit animation\n const [isHoverLocked, setIsHoverLocked] = useState(false);\n const unlockTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Toasts are expanded when hovered, focused, or locked\n const isExpanded = isHovered || isHoverLocked;\n\n // Track heights of all toasts by their key\n const [toastHeights, setToastHeights] = useState<Record<string, number>>(\n {},\n );\n\n // Callback for toasts to report their height\n const handleHeightChange = useCallback((key: string, height: number) => {\n setToastHeights(prev => {\n if (prev[key] === height) return prev;\n return { ...prev, [key]: height };\n });\n }, []);\n\n // Calculate expanded Y positions and get front toast height\n const { expandedYPositions, frontToastHeight } = useMemo(() => {\n const gap = 8;\n const positions: Record<string, number> = {};\n let frontHeight = 60; // Default fallback\n\n // visibleToasts[0] is the front toast (newest)\n const toasts = state.visibleToasts;\n\n if (toasts.length > 0 && toastHeights[toasts[0].key]) {\n frontHeight = toastHeights[toasts[0].key];\n }\n\n // Calculate cumulative Y position for each toast when expanded\n // Position is negative Y (moving up from bottom)\n let cumulativeY = 0;\n for (let i = 0; i < toasts.length; i++) {\n positions[toasts[i].key] = -cumulativeY;\n const height = toastHeights[toasts[i].key] || 60;\n cumulativeY += height + gap;\n }\n\n return { expandedYPositions: positions, frontToastHeight: frontHeight };\n }, [state.visibleToasts, toastHeights]);\n\n // Get inverted theme mode for toasts (light when app is dark, dark when app is light)\n const invertedThemeMode = useInvertedThemeMode();\n\n const handleClose = () => {\n // Lock the expanded state while toast is being removed\n setIsHoverLocked(true);\n\n // Clear any pending unlock\n if (unlockTimerRef.current) {\n clearTimeout(unlockTimerRef.current);\n }\n\n // Unlock after a short delay to allow exit animation to complete\n unlockTimerRef.current = setTimeout(() => {\n setIsHoverLocked(false);\n }, 500);\n };\n\n return (\n <div\n {...regionProps}\n ref={containerRef}\n className={className || styles.container}\n data-theme-mode={invertedThemeMode}\n data-hover-locked={isHoverLocked ? '' : undefined}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onFocus={() => setIsHovered(true)}\n onBlur={() => setIsHovered(false)}\n >\n <AnimatePresence>\n {state.visibleToasts.map((toast, index) => (\n <Toast\n key={toast.key}\n toast={toast}\n state={state}\n index={index}\n isExpanded={isExpanded}\n onClose={handleClose}\n expandedY={expandedYPositions[toast.key] ?? 0}\n collapsedHeight={index > 0 ? frontToastHeight : undefined}\n naturalHeight={toastHeights[toast.key]}\n onHeightChange={handleHeightChange}\n />\n ))}\n </AnimatePresence>\n </div>\n );\n },\n);\n\nToastContainer.displayName = 'ToastContainer';\n"],"names":[],"mappings":";;;;;;;;;AAqCO,MAAM,cAAA,GAAiB,UAAA;AAAA,EAC5B,CAAC,OAAsC,GAAA,KAA6B;AAClE,IAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAU,GAAI,KAAA;AAG7B,IAAA,MAAM,KAAA,GAAQ,cAAc,KAAK,CAAA;AAGjC,IAAA,MAAM,WAAA,GAAc,OAAuB,IAAI,CAAA;AAC/C,IAAA,MAAM,eACH,GAAA,IAA2C,WAAA;AAG9C,IAAA,MAAM,EAAE,WAAA,EAAY,GAAI,eAAe,EAAC,EAAG,OAAO,YAAY,CAAA;AAG9D,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAGhD,IAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA;AACxD,IAAA,MAAM,cAAA,GAAiB,OAA6C,IAAI,CAAA;AAGxE,IAAA,MAAM,aAAa,SAAA,IAAa,aAAA;AAGhC,IAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAA;AAAA,MACtC;AAAC,KACH;AAGA,IAAA,MAAM,kBAAA,GAAqB,WAAA,CAAY,CAAC,GAAA,EAAa,MAAA,KAAmB;AACtE,MAAA,eAAA,CAAgB,CAAA,IAAA,KAAQ;AACtB,QAAA,IAAI,IAAA,CAAK,GAAG,CAAA,KAAM,MAAA,EAAQ,OAAO,IAAA;AACjC,QAAA,OAAO,EAAE,GAAG,IAAA,EAAM,CAAC,GAAG,GAAG,MAAA,EAAO;AAAA,MAClC,CAAC,CAAA;AAAA,IACH,CAAA,EAAG,EAAE,CAAA;AAGL,IAAA,MAAM,EAAE,kBAAA,EAAoB,gBAAA,EAAiB,GAAI,QAAQ,MAAM;AAC7D,MAAA,MAAM,GAAA,GAAM,CAAA;AACZ,MAAA,MAAM,YAAoC,EAAC;AAC3C,MAAA,IAAI,WAAA,GAAc,EAAA;AAGlB,MAAA,MAAM,SAAS,KAAA,CAAM,aAAA;AAErB,MAAA,IAAI,MAAA,CAAO,SAAS,CAAA,IAAK,YAAA,CAAa,OAAO,CAAC,CAAA,CAAE,GAAG,CAAA,EAAG;AACpD,QAAA,WAAA,GAAc,YAAA,CAAa,MAAA,CAAO,CAAC,CAAA,CAAE,GAAG,CAAA;AAAA,MAC1C;AAIA,MAAA,IAAI,WAAA,GAAc,CAAA;AAClB,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,CAAE,GAAG,IAAI,CAAC,WAAA;AAC5B,QAAA,MAAM,SAAS,YAAA,CAAa,MAAA,CAAO,CAAC,CAAA,CAAE,GAAG,CAAA,IAAK,EAAA;AAC9C,QAAA,WAAA,IAAe,MAAA,GAAS,GAAA;AAAA,MAC1B;AAEA,MAAA,OAAO,EAAE,kBAAA,EAAoB,SAAA,EAAW,gBAAA,EAAkB,WAAA,EAAY;AAAA,IACxE,CAAA,EAAG,CAAC,KAAA,CAAM,aAAA,EAAe,YAAY,CAAC,CAAA;AAGtC,IAAA,MAAM,oBAAoB,oBAAA,EAAqB;AAE/C,IAAA,MAAM,cAAc,MAAM;AAExB,MAAA,gBAAA,CAAiB,IAAI,CAAA;AAGrB,MAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,QAAA,YAAA,CAAa,eAAe,OAAO,CAAA;AAAA,MACrC;AAGA,MAAA,cAAA,CAAe,OAAA,GAAU,WAAW,MAAM;AACxC,QAAA,gBAAA,CAAiB,KAAK,CAAA;AAAA,MACxB,GAAG,GAAG,CAAA;AAAA,IACR,CAAA;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACE,GAAG,WAAA;AAAA,QACJ,GAAA,EAAK,YAAA;AAAA,QACL,SAAA,EAAW,aAAa,MAAA,CAAO,SAAA;AAAA,QAC/B,iBAAA,EAAiB,iBAAA;AAAA,QACjB,mBAAA,EAAmB,gBAAgB,EAAA,GAAK,MAAA;AAAA,QACxC,YAAA,EAAc,MAAM,YAAA,CAAa,IAAI,CAAA;AAAA,QACrC,YAAA,EAAc,MAAM,YAAA,CAAa,KAAK,CAAA;AAAA,QACtC,OAAA,EAAS,MAAM,YAAA,CAAa,IAAI,CAAA;AAAA,QAChC,MAAA,EAAQ,MAAM,YAAA,CAAa,KAAK,CAAA;AAAA,QAEhC,8BAAC,eAAA,EAAA,EACE,QAAA,EAAA,KAAA,CAAM,cAAc,GAAA,CAAI,CAAC,OAAO,KAAA,qBAC/B,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YAEC,KAAA;AAAA,YACA,KAAA;AAAA,YACA,KAAA;AAAA,YACA,UAAA;AAAA,YACA,OAAA,EAAS,WAAA;AAAA,YACT,SAAA,EAAW,kBAAA,CAAmB,KAAA,CAAM,GAAG,CAAA,IAAK,CAAA;AAAA,YAC5C,eAAA,EAAiB,KAAA,GAAQ,CAAA,GAAI,gBAAA,GAAmB,MAAA;AAAA,YAChD,aAAA,EAAe,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA;AAAA,YACrC,cAAA,EAAgB;AAAA,WAAA;AAAA,UATX,KAAA,CAAM;AAAA,SAWd,CAAA,EACH;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AAEA,cAAA,CAAe,WAAA,GAAc,gBAAA;;;;"}
@@ -0,0 +1,51 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { useApi, alertApiRef } from '@backstage/core-plugin-api';
4
+ import { ToastQueue } from '@react-stately/toast';
5
+ import { ToastContainer } from './ToastContainer.esm.js';
6
+ import 'zen-observable';
7
+ import { toastApiForwarderRef } from '../../apis/toastApiForwarderRef.esm.js';
8
+
9
+ function mapSeverity(severity) {
10
+ if (severity === "error") {
11
+ return "danger";
12
+ }
13
+ return severity ?? "success";
14
+ }
15
+ function ToastDisplay(props) {
16
+ const alertApi = useApi(alertApiRef);
17
+ const toastApi = useApi(toastApiForwarderRef);
18
+ const { transientTimeoutMs = 5e3 } = props;
19
+ const [toastQueue] = useState(
20
+ () => new ToastQueue({ maxVisibleToasts: 4 })
21
+ );
22
+ useEffect(() => {
23
+ const subscription = toastApi.toast$().subscribe((toast) => {
24
+ const content = {
25
+ title: toast.title,
26
+ description: toast.description,
27
+ status: toast.status ?? "success",
28
+ links: toast.links
29
+ };
30
+ const options = toast.timeout ? { timeout: toast.timeout } : {};
31
+ const queueKey = toastQueue.add(content, options);
32
+ toast.onClose(() => toastQueue.close(queueKey));
33
+ });
34
+ return () => subscription.unsubscribe();
35
+ }, [toastApi, toastQueue]);
36
+ useEffect(() => {
37
+ const subscription = alertApi.alert$().subscribe((alert) => {
38
+ const content = {
39
+ title: alert.message,
40
+ status: mapSeverity(alert.severity)
41
+ };
42
+ const options = alert.display === "transient" ? { timeout: transientTimeoutMs } : {};
43
+ toastQueue.add(content, options);
44
+ });
45
+ return () => subscription.unsubscribe();
46
+ }, [alertApi, transientTimeoutMs, toastQueue]);
47
+ return /* @__PURE__ */ jsx(ToastContainer, { queue: toastQueue });
48
+ }
49
+
50
+ export { ToastDisplay };
51
+ //# sourceMappingURL=ToastDisplay.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToastDisplay.esm.js","sources":["../../../src/components/Toast/ToastDisplay.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 { useEffect, useState } from 'react';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport { ToastQueue } from '@react-stately/toast';\nimport { ToastContainer } from './ToastContainer';\nimport { toastApiForwarderRef } from '../../apis';\nimport type {\n ToastApiMessageDisplayProps,\n ToastApiMessageContent,\n} from './types';\n\n/**\n * Maps AlertApi severity to Toast status.\n * AlertApi uses 'error' while Toast uses 'danger' for the same semantic meaning.\n */\nfunction mapSeverity(\n severity: 'success' | 'info' | 'warning' | 'error' | undefined,\n): ToastApiMessageContent['status'] {\n if (severity === 'error') {\n return 'danger';\n }\n return severity ?? 'success';\n}\n\n/**\n * ToastDisplay bridges both the ToastApi and AlertApi with the Toast notification system.\n *\n * @remarks\n * This component provides a migration bridge between the deprecated AlertApi and the new ToastApi.\n * During the migration period, it subscribes to both APIs simultaneously, allowing plugins to\n * migrate incrementally without breaking existing functionality.\n *\n * **Subscriptions:**\n * - `toastApi.toast$()` - New toast notifications with full features (title, description, links, icons)\n * - `alertApi.alert$()` - Deprecated alerts for backward compatibility (message maps to title only)\n *\n * **ToastApi (recommended):**\n * - Uses toast content directly (title, description, status, icon, links)\n * - Uses the provided timeout from the toast message\n * - Supports programmatic dismiss via the returned `close()` handle\n *\n * **AlertApi (deprecated - please migrate to ToastApi):**\n * - `alert.message` → `toast.title`\n * - `alert.severity` → `toast.status` ('error' maps to 'danger')\n * - `alert.display` → `timeout` (transient gets default timeout, permanent stays until dismissed)\n *\n * @example\n * ```tsx\n * // In your app root element extension\n * <ToastDisplay transientTimeoutMs={5000} />\n *\n * // Using the new ToastApi (recommended):\n * import { toastApiRef, useApi } from '@backstage/frontend-plugin-api';\n * const toastApi = useApi(toastApiRef);\n * const { close } = toastApi.post({\n * title: 'Entity saved',\n * description: 'Your changes have been saved successfully.',\n * status: 'success',\n * timeout: 5000,\n * });\n * // Later: close() to dismiss programmatically\n *\n * // Using the deprecated AlertApi (migrate to ToastApi):\n * import { alertApiRef, useApi } from '@backstage/core-plugin-api';\n * const alertApi = useApi(alertApiRef);\n * alertApi.post({ message: 'Saved!', severity: 'success', display: 'transient' });\n * ```\n *\n * @public\n */\nexport function ToastDisplay(props: ToastApiMessageDisplayProps) {\n const alertApi = useApi(alertApiRef);\n const toastApi = useApi(toastApiForwarderRef);\n const { transientTimeoutMs = 5000 } = props;\n\n // Create toast queue once per component instance\n const [toastQueue] = useState(\n () => new ToastQueue<ToastApiMessageContent>({ maxVisibleToasts: 4 }),\n );\n\n // Subscribe to ToastApi\n useEffect(() => {\n const subscription = toastApi.toast$().subscribe(toast => {\n const content: ToastApiMessageContent = {\n title: toast.title,\n description: toast.description,\n status: toast.status ?? 'success',\n links: toast.links,\n };\n\n // Use the timeout from the toast message if provided\n const options = toast.timeout ? { timeout: toast.timeout } : {};\n\n const queueKey = toastQueue.add(content, options);\n\n // When the toast is programmatically closed, remove it from the queue\n toast.onClose(() => toastQueue.close(queueKey));\n });\n\n return () => subscription.unsubscribe();\n }, [toastApi, toastQueue]);\n\n // Subscribe to AlertApi (deprecated - provides backward compatibility during migration)\n // This subscription will be removed when AlertApi is fully deprecated\n useEffect(() => {\n const subscription = alertApi.alert$().subscribe(alert => {\n const content: ToastApiMessageContent = {\n title: alert.message,\n status: mapSeverity(alert.severity),\n };\n\n // Transient alerts auto-dismiss after timeout, permanent alerts stay until dismissed\n const options =\n alert.display === 'transient' ? { timeout: transientTimeoutMs } : {};\n\n toastQueue.add(content, options);\n });\n\n return () => subscription.unsubscribe();\n }, [alertApi, transientTimeoutMs, toastQueue]);\n\n return <ToastContainer queue={toastQueue} />;\n}\n"],"names":[],"mappings":";;;;;;;;AA8BA,SAAS,YACP,QAAA,EACkC;AAClC,EAAA,IAAI,aAAa,OAAA,EAAS;AACxB,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAA,IAAY,SAAA;AACrB;AAgDO,SAAS,aAAa,KAAA,EAAoC;AAC/D,EAAA,MAAM,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,OAAO,oBAAoB,CAAA;AAC5C,EAAA,MAAM,EAAE,kBAAA,GAAqB,GAAA,EAAK,GAAI,KAAA;AAGtC,EAAA,MAAM,CAAC,UAAU,CAAA,GAAI,QAAA;AAAA,IACnB,MAAM,IAAI,UAAA,CAAmC,EAAE,gBAAA,EAAkB,GAAG;AAAA,GACtE;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,MAAA,EAAO,CAAE,UAAU,CAAA,KAAA,KAAS;AACxD,MAAA,MAAM,OAAA,GAAkC;AAAA,QACtC,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,MAAA,EAAQ,MAAM,MAAA,IAAU,SAAA;AAAA,QACxB,OAAO,KAAA,CAAM;AAAA,OACf;AAGA,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,GAAU,EAAE,SAAS,KAAA,CAAM,OAAA,KAAY,EAAC;AAE9D,MAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,CAAI,OAAA,EAAS,OAAO,CAAA;AAGhD,MAAA,KAAA,CAAM,OAAA,CAAQ,MAAM,UAAA,CAAW,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,IAChD,CAAC,CAAA;AAED,IAAA,OAAO,MAAM,aAAa,WAAA,EAAY;AAAA,EACxC,CAAA,EAAG,CAAC,QAAA,EAAU,UAAU,CAAC,CAAA;AAIzB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,MAAA,EAAO,CAAE,UAAU,CAAA,KAAA,KAAS;AACxD,MAAA,MAAM,OAAA,GAAkC;AAAA,QACtC,OAAO,KAAA,CAAM,OAAA;AAAA,QACb,MAAA,EAAQ,WAAA,CAAY,KAAA,CAAM,QAAQ;AAAA,OACpC;AAGA,MAAA,MAAM,OAAA,GACJ,MAAM,OAAA,KAAY,WAAA,GAAc,EAAE,OAAA,EAAS,kBAAA,KAAuB,EAAC;AAErE,MAAA,UAAA,CAAW,GAAA,CAAI,SAAS,OAAO,CAAA;AAAA,IACjC,CAAC,CAAA;AAED,IAAA,OAAO,MAAM,aAAa,WAAA,EAAY;AAAA,EACxC,CAAA,EAAG,CAAC,QAAA,EAAU,kBAAA,EAAoB,UAAU,CAAC,CAAA;AAE7C,EAAA,uBAAO,GAAA,CAAC,cAAA,EAAA,EAAe,KAAA,EAAO,UAAA,EAAY,CAAA;AAC5C;;;;"}
@@ -22,7 +22,9 @@ import { createFetchApi } from './packages/core-app-api/src/apis/implementations
22
22
  import { FetchMiddlewares } from './packages/core-app-api/src/apis/implementations/FetchApi/FetchMiddlewares.esm.js';
23
23
  import { OAuthRequestManager } from './packages/core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.esm.js';
24
24
  import { WebStorage } from './packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.esm.js';
25
- import { ApiBlueprint, dialogApiRef } from '@backstage/frontend-plugin-api';
25
+ import { ToastApiForwarder } from './apis/ToastApiForwarder.esm.js';
26
+ import { toastApiForwarderRef } from './apis/toastApiForwarderRef.esm.js';
27
+ import { ApiBlueprint, dialogApiRef, toastApiRef } from '@backstage/frontend-plugin-api';
26
28
  import { ScmAuth, ScmIntegrationsApi, scmIntegrationsApiRef } from '@backstage/integration-react';
27
29
  import { IdentityPermissionApi, permissionApiRef } from '@backstage/plugin-permission-react';
28
30
  import { DefaultDialogApi } from './apis/DefaultDialogApi.esm.js';
@@ -55,6 +57,22 @@ const apis = [
55
57
  factory: () => new AlertApiForwarder()
56
58
  })
57
59
  }),
60
+ ApiBlueprint.make({
61
+ name: "toast-forwarder",
62
+ params: (defineParams) => defineParams({
63
+ api: toastApiForwarderRef,
64
+ deps: {},
65
+ factory: () => new ToastApiForwarder()
66
+ })
67
+ }),
68
+ ApiBlueprint.make({
69
+ name: "toast",
70
+ params: (defineParams) => defineParams({
71
+ api: toastApiRef,
72
+ deps: { forwarder: toastApiForwarderRef },
73
+ factory: ({ forwarder }) => forwarder
74
+ })
75
+ }),
58
76
  analyticsApi,
59
77
  ApiBlueprint.make({
60
78
  name: "error",
@@ -1 +1 @@
1
- {"version":3,"file":"defaultApis.esm.js","sources":["../src/defaultApis.ts"],"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\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n AlertApiForwarder,\n ErrorApiForwarder,\n ErrorAlerter,\n GoogleAuth,\n GithubAuth,\n OktaAuth,\n GitlabAuth,\n MicrosoftAuth,\n BitbucketAuth,\n BitbucketServerAuth,\n OAuthRequestManager,\n WebStorage,\n UrlPatternDiscovery,\n OneLoginAuth,\n UnhandledErrorForwarder,\n AtlassianAuth,\n createFetchApi,\n FetchMiddlewares,\n VMwareCloudAuth,\n OpenShiftAuth,\n} from '../../../packages/core-app-api/src/apis/implementations';\n\nimport {\n alertApiRef,\n errorApiRef,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n oauthRequestApiRef,\n googleAuthApiRef,\n githubAuthApiRef,\n oktaAuthApiRef,\n gitlabAuthApiRef,\n microsoftAuthApiRef,\n storageApiRef,\n configApiRef,\n oneloginAuthApiRef,\n bitbucketAuthApiRef,\n bitbucketServerAuthApiRef,\n atlassianAuthApiRef,\n vmwareCloudAuthApiRef,\n openshiftAuthApiRef,\n} from '@backstage/core-plugin-api';\nimport { ApiBlueprint, dialogApiRef } from '@backstage/frontend-plugin-api';\nimport {\n ScmAuth,\n ScmIntegrationsApi,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport {\n permissionApiRef,\n IdentityPermissionApi,\n} from '@backstage/plugin-permission-react';\nimport { DefaultDialogApi } from './apis/DefaultDialogApi';\nimport { analyticsApi } from './extensions/AnalyticsApi';\n\nexport const apis = [\n ApiBlueprint.make({\n name: 'dialog',\n params: defineParams =>\n defineParams({\n api: dialogApiRef,\n deps: {},\n factory: () => new DefaultDialogApi(),\n }),\n }),\n ApiBlueprint.make({\n name: 'discovery',\n params: defineParams =>\n defineParams({\n api: discoveryApiRef,\n deps: { configApi: configApiRef },\n factory: ({ configApi }) =>\n UrlPatternDiscovery.compile(\n `${configApi.getString('backend.baseUrl')}/api/{{ pluginId }}`,\n ),\n }),\n }),\n ApiBlueprint.make({\n name: 'alert',\n params: defineParams =>\n defineParams({\n api: alertApiRef,\n deps: {},\n factory: () => new AlertApiForwarder(),\n }),\n }),\n analyticsApi,\n ApiBlueprint.make({\n name: 'error',\n params: defineParams =>\n defineParams({\n api: errorApiRef,\n deps: { alertApi: alertApiRef },\n factory: ({ alertApi }) => {\n const errorApi = new ErrorAlerter(alertApi, new ErrorApiForwarder());\n UnhandledErrorForwarder.forward(errorApi, { hidden: false });\n return errorApi;\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'storage',\n params: defineParams =>\n defineParams({\n api: storageApiRef,\n deps: { errorApi: errorApiRef },\n factory: ({ errorApi }) => WebStorage.create({ errorApi }),\n }),\n }),\n ApiBlueprint.make({\n name: 'fetch',\n params: defineParams =>\n defineParams({\n api: fetchApiRef,\n deps: {\n configApi: configApiRef,\n identityApi: identityApiRef,\n discoveryApi: discoveryApiRef,\n },\n factory: ({ configApi, identityApi, discoveryApi }) => {\n return createFetchApi({\n middleware: [\n FetchMiddlewares.resolvePluginProtocol({\n discoveryApi,\n }),\n FetchMiddlewares.injectIdentityAuth({\n identityApi,\n config: configApi,\n }),\n ],\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'oauth-request',\n params: defineParams =>\n defineParams({\n api: oauthRequestApiRef,\n deps: {},\n factory: () => new OAuthRequestManager(),\n }),\n }),\n ApiBlueprint.make({\n name: 'google-auth',\n params: defineParams =>\n defineParams({\n api: googleAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GoogleAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'microsoft-auth',\n params: defineParams =>\n defineParams({\n api: microsoftAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n MicrosoftAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'github-auth',\n params: defineParams =>\n defineParams({\n api: githubAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GithubAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['read:user'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'okta-auth',\n params: defineParams =>\n defineParams({\n api: oktaAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n OktaAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'gitlab-auth',\n params: defineParams =>\n defineParams({\n api: gitlabAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GitlabAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'onelogin-auth',\n params: defineParams =>\n defineParams({\n api: oneloginAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n OneLoginAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'bitbucket-auth',\n params: defineParams =>\n defineParams({\n api: bitbucketAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n BitbucketAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['account'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'bitbucket-server-auth',\n params: defineParams =>\n defineParams({\n api: bitbucketServerAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n BitbucketServerAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['REPO_READ'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'atlassian-auth',\n params: defineParams =>\n defineParams({\n api: atlassianAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return AtlassianAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'vmware-cloud-auth',\n params: defineParams =>\n defineParams({\n api: vmwareCloudAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return VMwareCloudAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'openshift-auth',\n params: defineParams =>\n defineParams({\n api: openshiftAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return OpenShiftAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'permission',\n params: defineParams =>\n defineParams({\n api: permissionApiRef,\n deps: {\n discovery: discoveryApiRef,\n identity: identityApiRef,\n config: configApiRef,\n },\n factory: ({ config, discovery, identity }) =>\n IdentityPermissionApi.create({ config, discovery, identity }),\n }),\n }),\n ApiBlueprint.make({\n name: 'scm-auth',\n params: defineParams => defineParams(ScmAuth.createDefaultApiFactory()),\n }),\n ApiBlueprint.make({\n name: 'scm-integrations',\n params: defineParams =>\n defineParams({\n api: scmIntegrationsApiRef,\n deps: { configApi: configApiRef },\n factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi),\n }),\n }),\n] as const;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"defaultApis.esm.js","sources":["../src/defaultApis.ts"],"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\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n AlertApiForwarder,\n ErrorApiForwarder,\n ErrorAlerter,\n GoogleAuth,\n GithubAuth,\n OktaAuth,\n GitlabAuth,\n MicrosoftAuth,\n BitbucketAuth,\n BitbucketServerAuth,\n OAuthRequestManager,\n WebStorage,\n UrlPatternDiscovery,\n OneLoginAuth,\n UnhandledErrorForwarder,\n AtlassianAuth,\n createFetchApi,\n FetchMiddlewares,\n VMwareCloudAuth,\n OpenShiftAuth,\n} from '../../../packages/core-app-api/src/apis/implementations';\nimport { ToastApiForwarder, toastApiForwarderRef } from './apis';\n\nimport {\n alertApiRef,\n errorApiRef,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n oauthRequestApiRef,\n googleAuthApiRef,\n githubAuthApiRef,\n oktaAuthApiRef,\n gitlabAuthApiRef,\n microsoftAuthApiRef,\n storageApiRef,\n configApiRef,\n oneloginAuthApiRef,\n bitbucketAuthApiRef,\n bitbucketServerAuthApiRef,\n atlassianAuthApiRef,\n vmwareCloudAuthApiRef,\n openshiftAuthApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n ApiBlueprint,\n dialogApiRef,\n toastApiRef,\n} from '@backstage/frontend-plugin-api';\nimport {\n ScmAuth,\n ScmIntegrationsApi,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport {\n permissionApiRef,\n IdentityPermissionApi,\n} from '@backstage/plugin-permission-react';\nimport { DefaultDialogApi } from './apis/DefaultDialogApi';\nimport { analyticsApi } from './extensions/AnalyticsApi';\n\nexport const apis = [\n ApiBlueprint.make({\n name: 'dialog',\n params: defineParams =>\n defineParams({\n api: dialogApiRef,\n deps: {},\n factory: () => new DefaultDialogApi(),\n }),\n }),\n ApiBlueprint.make({\n name: 'discovery',\n params: defineParams =>\n defineParams({\n api: discoveryApiRef,\n deps: { configApi: configApiRef },\n factory: ({ configApi }) =>\n UrlPatternDiscovery.compile(\n `${configApi.getString('backend.baseUrl')}/api/{{ pluginId }}`,\n ),\n }),\n }),\n ApiBlueprint.make({\n name: 'alert',\n params: defineParams =>\n defineParams({\n api: alertApiRef,\n deps: {},\n factory: () => new AlertApiForwarder(),\n }),\n }),\n ApiBlueprint.make({\n name: 'toast-forwarder',\n params: defineParams =>\n defineParams({\n api: toastApiForwarderRef,\n deps: {},\n factory: () => new ToastApiForwarder(),\n }),\n }),\n ApiBlueprint.make({\n name: 'toast',\n params: defineParams =>\n defineParams({\n api: toastApiRef,\n deps: { forwarder: toastApiForwarderRef },\n factory: ({ forwarder }) => forwarder,\n }),\n }),\n analyticsApi,\n ApiBlueprint.make({\n name: 'error',\n params: defineParams =>\n defineParams({\n api: errorApiRef,\n deps: { alertApi: alertApiRef },\n factory: ({ alertApi }) => {\n const errorApi = new ErrorAlerter(alertApi, new ErrorApiForwarder());\n UnhandledErrorForwarder.forward(errorApi, { hidden: false });\n return errorApi;\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'storage',\n params: defineParams =>\n defineParams({\n api: storageApiRef,\n deps: { errorApi: errorApiRef },\n factory: ({ errorApi }) => WebStorage.create({ errorApi }),\n }),\n }),\n ApiBlueprint.make({\n name: 'fetch',\n params: defineParams =>\n defineParams({\n api: fetchApiRef,\n deps: {\n configApi: configApiRef,\n identityApi: identityApiRef,\n discoveryApi: discoveryApiRef,\n },\n factory: ({ configApi, identityApi, discoveryApi }) => {\n return createFetchApi({\n middleware: [\n FetchMiddlewares.resolvePluginProtocol({\n discoveryApi,\n }),\n FetchMiddlewares.injectIdentityAuth({\n identityApi,\n config: configApi,\n }),\n ],\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'oauth-request',\n params: defineParams =>\n defineParams({\n api: oauthRequestApiRef,\n deps: {},\n factory: () => new OAuthRequestManager(),\n }),\n }),\n ApiBlueprint.make({\n name: 'google-auth',\n params: defineParams =>\n defineParams({\n api: googleAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GoogleAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'microsoft-auth',\n params: defineParams =>\n defineParams({\n api: microsoftAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n MicrosoftAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'github-auth',\n params: defineParams =>\n defineParams({\n api: githubAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GithubAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['read:user'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'okta-auth',\n params: defineParams =>\n defineParams({\n api: oktaAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n OktaAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'gitlab-auth',\n params: defineParams =>\n defineParams({\n api: gitlabAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GitlabAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'onelogin-auth',\n params: defineParams =>\n defineParams({\n api: oneloginAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n OneLoginAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'bitbucket-auth',\n params: defineParams =>\n defineParams({\n api: bitbucketAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n BitbucketAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['account'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'bitbucket-server-auth',\n params: defineParams =>\n defineParams({\n api: bitbucketServerAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n BitbucketServerAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['REPO_READ'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n }),\n ApiBlueprint.make({\n name: 'atlassian-auth',\n params: defineParams =>\n defineParams({\n api: atlassianAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return AtlassianAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'vmware-cloud-auth',\n params: defineParams =>\n defineParams({\n api: vmwareCloudAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return VMwareCloudAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'openshift-auth',\n params: defineParams =>\n defineParams({\n api: openshiftAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return OpenShiftAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n }),\n ApiBlueprint.make({\n name: 'permission',\n params: defineParams =>\n defineParams({\n api: permissionApiRef,\n deps: {\n discovery: discoveryApiRef,\n identity: identityApiRef,\n config: configApiRef,\n },\n factory: ({ config, discovery, identity }) =>\n IdentityPermissionApi.create({ config, discovery, identity }),\n }),\n }),\n ApiBlueprint.make({\n name: 'scm-auth',\n params: defineParams => defineParams(ScmAuth.createDefaultApiFactory()),\n }),\n ApiBlueprint.make({\n name: 'scm-integrations',\n params: defineParams =>\n defineParams({\n api: scmIntegrationsApiRef,\n deps: { configApi: configApiRef },\n factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi),\n }),\n }),\n] as const;\n"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ class NavItemBag {
8
8
  #items;
9
9
  #index;
10
10
  #taken;
11
+ #restItems;
11
12
  constructor(items, taken) {
12
13
  this.#items = items;
13
14
  this.#index = new Map(items.map((item) => [item.node.spec.id, item]));
@@ -15,29 +16,54 @@ class NavItemBag {
15
16
  }
16
17
  take(id) {
17
18
  const item = this.#index.get(id);
18
- if (item) {
19
+ if (item && !this.#taken.has(id)) {
19
20
  this.#taken.add(id);
21
+ if (this.#restItems) {
22
+ const index = this.#restItems.findIndex(
23
+ (restItem) => restItem.node.spec.id === id
24
+ );
25
+ if (index !== -1) {
26
+ this.#restItems.splice(index, 1);
27
+ }
28
+ }
20
29
  }
21
30
  return item;
22
31
  }
23
32
  rest() {
24
- return this.#items.filter((item) => !this.#taken.has(item.node.spec.id));
33
+ if (!this.#restItems) {
34
+ this.#restItems = this.#items.filter(
35
+ (item) => !this.#taken.has(item.node.spec.id)
36
+ );
37
+ }
38
+ return this.#restItems;
25
39
  }
26
40
  clone() {
27
41
  return new NavItemBag(this.#items, this.#taken);
28
42
  }
29
43
  withComponent(Component) {
44
+ let renderedItems;
30
45
  return {
31
46
  take: (id) => {
32
47
  const item = this.take(id);
33
- return item ? /* @__PURE__ */ jsx(Component, { ...item }) : null;
48
+ if (item && renderedItems) {
49
+ const index = renderedItems.findIndex(
50
+ (renderedItem) => renderedItem.key === item.node.spec.id
51
+ );
52
+ if (index !== -1) {
53
+ renderedItems.splice(index, 1);
54
+ }
55
+ }
56
+ return item ? /* @__PURE__ */ jsx(Component, { ...item }, item.node.spec.id) : null;
34
57
  },
35
58
  rest: (options) => {
36
59
  const items = this.rest();
37
- if (options?.sortBy === "title") {
38
- items.sort((a, b) => a.title.localeCompare(b.title));
60
+ if (!renderedItems) {
61
+ if (options?.sortBy === "title") {
62
+ items.sort((a, b) => a.title.localeCompare(b.title));
63
+ }
64
+ renderedItems = items.map((item) => /* @__PURE__ */ jsx(Component, { ...item }, item.node.spec.id));
39
65
  }
40
- return items.map((item) => /* @__PURE__ */ jsx(Component, { ...item }, item.node.spec.id));
66
+ return renderedItems;
41
67
  }
42
68
  };
43
69
  }
@@ -97,6 +123,7 @@ function NavContentRenderer(props) {
97
123
  const matchingNavItem = navItemsByRouteRef.get(routeRef);
98
124
  const resolvedTitle = node.instance.getData(coreExtensionData.title);
99
125
  const pluginTitle = node.spec.plugin.title;
126
+ const pluginIcon = node.spec.plugin.icon;
100
127
  const pluginId = node.spec.plugin.pluginId;
101
128
  const hasExplicitPageTitle = resolvedTitle !== void 0 && resolvedTitle !== pluginTitle && resolvedTitle !== pluginId;
102
129
  const title = hasExplicitPageTitle ? resolvedTitle : matchingNavItem?.title ?? pluginTitle ?? pluginId;
@@ -110,6 +137,8 @@ function NavContentRenderer(props) {
110
137
  icon = /* @__PURE__ */ jsx(NavItemIcon, {});
111
138
  } else if (resolvedIcon) {
112
139
  icon = resolvedIcon;
140
+ } else if (pluginIcon) {
141
+ icon = pluginIcon;
113
142
  }
114
143
  if (!title || !icon) {
115
144
  return [];
@@ -1 +1 @@
1
- {"version":3,"file":"AppNav.esm.js","sources":["../../src/extensions/AppNav.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 {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n NavItemBlueprint,\n routeResolutionApiRef,\n appTreeApiRef,\n IconComponent,\n IconElement,\n RouteRef,\n RouteResolutionApi,\n useApi,\n} from '@backstage/frontend-plugin-api';\nimport {\n NavContentBlueprint,\n NavContentComponent,\n NavContentComponentProps,\n NavContentNavItem,\n NavContentNavItems,\n} from '@backstage/plugin-app-react';\nimport { Sidebar, SidebarItem } from '@backstage/core-components';\nimport { useMemo } from 'react';\n\nclass NavItemBag implements NavContentNavItems {\n readonly #items: NavContentNavItem[];\n readonly #index: Map<string, NavContentNavItem>;\n readonly #taken: Set<string>;\n\n constructor(items: NavContentNavItem[], taken?: Iterable<string>) {\n this.#items = items;\n this.#index = new Map(items.map(item => [item.node.spec.id, item]));\n this.#taken = new Set(taken);\n }\n\n take(id: string): NavContentNavItem | undefined {\n const item = this.#index.get(id);\n if (item) {\n this.#taken.add(id);\n }\n return item;\n }\n\n rest(): NavContentNavItem[] {\n return this.#items.filter(item => !this.#taken.has(item.node.spec.id));\n }\n\n clone(): NavContentNavItems {\n return new NavItemBag(this.#items, this.#taken);\n }\n\n withComponent(Component: (props: NavContentNavItem) => JSX.Element) {\n return {\n take: (id: string) => {\n const item = this.take(id);\n return item ? <Component {...item} /> : null;\n },\n rest: (options?: { sortBy?: 'title' }) => {\n const items = this.rest();\n if (options?.sortBy === 'title') {\n items.sort((a, b) => a.title.localeCompare(b.title));\n }\n return items.map(item => (\n <Component key={item.node.spec.id} {...item} />\n ));\n },\n };\n }\n}\n\nfunction DefaultNavContent(props: NavContentComponentProps) {\n const items = props.navItems.rest();\n return (\n <Sidebar>\n {items.map(item => (\n <SidebarItem\n to={item.href}\n icon={() => item.icon}\n text={item.title}\n key={item.node.spec.id}\n />\n ))}\n </Sidebar>\n );\n}\n\n// Tries to resolve a routeRef to a link path, returning undefined if it\n// can't be resolved (e.g. parameterized routes).\nfunction tryResolveLink(\n routeResolutionApi: RouteResolutionApi,\n routeRef: RouteRef,\n): string | undefined {\n try {\n const link = routeResolutionApi.resolve(routeRef);\n return link?.();\n } catch {\n return undefined;\n }\n}\n\n// Defers rendering until the app is fully initialized so that APIs like\n// RouteResolutionApi and AppTreeApi are available.\nfunction NavContentRenderer(props: {\n Content: NavContentComponent;\n legacyNavItems: Array<{\n title: string;\n icon: IconComponent;\n routeRef: RouteRef<undefined>;\n }>;\n}) {\n const appTreeApi = useApi(appTreeApiRef);\n const routeResolutionApi = useApi(routeResolutionApiRef);\n\n // Deprecated items: just resolve nav item routeRefs to paths, no page discovery.\n const legacyItems = useMemo(() => {\n return props.legacyNavItems.flatMap(item => {\n const link = routeResolutionApi.resolve(item.routeRef);\n if (!link) return [];\n return [\n {\n to: link(),\n text: item.title,\n icon: item.icon,\n title: item.title,\n routeRef: item.routeRef,\n },\n ];\n });\n }, [props.legacyNavItems, routeResolutionApi]);\n\n // New navItems: discover pages from the extension tree, merged with nav items.\n const navItems = useMemo(() => {\n const { tree } = appTreeApi.getTree();\n const routesNode = tree.nodes.get('app/routes');\n if (!routesNode) return new NavItemBag([]);\n\n // Index nav items by routeRef for matching against pages\n const navItemsByRouteRef = new Map<\n RouteRef,\n { title: string; icon: IconComponent }\n >(props.legacyNavItems.map(item => [item.routeRef, item]));\n\n const pageNodes = routesNode.edges.attachments.get('routes') ?? [];\n const items = pageNodes.flatMap((node): NavContentNavItem[] => {\n if (!node.instance || node.spec.disabled) {\n return [];\n }\n\n const routeRef = node.instance.getData(coreExtensionData.routeRef);\n if (!routeRef) {\n return [];\n }\n\n const matchingNavItem = navItemsByRouteRef.get(routeRef);\n\n // PageBlueprint resolves title as: config.title ?? params.title ?? plugin.title ?? pluginId\n // We want the priority: page (config/params) -> nav item -> plugin -> pluginId\n const resolvedTitle = node.instance.getData(coreExtensionData.title);\n const pluginTitle = node.spec.plugin.title;\n const pluginId = node.spec.plugin.pluginId;\n const hasExplicitPageTitle =\n resolvedTitle !== undefined &&\n resolvedTitle !== pluginTitle &&\n resolvedTitle !== pluginId;\n const title = hasExplicitPageTitle\n ? resolvedTitle\n : matchingNavItem?.title ?? pluginTitle ?? pluginId;\n\n // PageBlueprint resolves icon as: params.icon ?? plugin.icon\n // We want the priority: page (params) -> nav item -> plugin -> (excluded)\n const resolvedIcon = node.instance.getData(coreExtensionData.icon);\n const hasExplicitPageIcon = resolvedIcon && !node.spec.plugin.icon;\n const NavItemIcon = matchingNavItem?.icon;\n\n let icon: IconElement | undefined;\n if (hasExplicitPageIcon) {\n icon = resolvedIcon;\n } else if (NavItemIcon) {\n icon = <NavItemIcon />;\n } else if (resolvedIcon) {\n icon = resolvedIcon;\n }\n\n if (!title || !icon) {\n return [];\n }\n\n const to = tryResolveLink(routeResolutionApi, routeRef);\n if (!to) {\n return [];\n }\n\n return [{ node, href: to, title, icon, routeRef }];\n });\n\n return new NavItemBag(items);\n }, [appTreeApi, routeResolutionApi, props.legacyNavItems]);\n\n return <props.Content navItems={navItems} items={legacyItems} />;\n}\n\nexport const AppNav = createExtension({\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n inputs: {\n items: createExtensionInput([NavItemBlueprint.dataRefs.target]),\n content: createExtensionInput([NavContentBlueprint.dataRefs.component], {\n singleton: true,\n optional: true,\n internal: true,\n }),\n },\n output: [coreExtensionData.reactElement],\n *factory({ inputs }) {\n const Content =\n inputs.content?.get(NavContentBlueprint.dataRefs.component) ??\n DefaultNavContent;\n\n yield coreExtensionData.reactElement(\n <NavContentRenderer\n legacyNavItems={inputs.items.map(item =>\n item.get(NavItemBlueprint.dataRefs.target),\n )}\n Content={Content}\n />,\n );\n },\n});\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AppNav.esm.js","sources":["../../src/extensions/AppNav.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 {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n NavItemBlueprint,\n routeResolutionApiRef,\n appTreeApiRef,\n IconComponent,\n IconElement,\n RouteRef,\n RouteResolutionApi,\n useApi,\n} from '@backstage/frontend-plugin-api';\nimport {\n NavContentBlueprint,\n NavContentComponent,\n NavContentComponentProps,\n NavContentNavItem,\n NavContentNavItems,\n} from '@backstage/plugin-app-react';\nimport { Sidebar, SidebarItem } from '@backstage/core-components';\nimport { useMemo } from 'react';\n\nclass NavItemBag implements NavContentNavItems {\n readonly #items: NavContentNavItem[];\n readonly #index: Map<string, NavContentNavItem>;\n readonly #taken: Set<string>;\n #restItems: NavContentNavItem[] | undefined;\n\n constructor(items: NavContentNavItem[], taken?: Iterable<string>) {\n this.#items = items;\n this.#index = new Map(items.map(item => [item.node.spec.id, item]));\n this.#taken = new Set(taken);\n }\n\n take(id: string): NavContentNavItem | undefined {\n const item = this.#index.get(id);\n if (item && !this.#taken.has(id)) {\n this.#taken.add(id);\n if (this.#restItems) {\n const index = this.#restItems.findIndex(\n restItem => restItem.node.spec.id === id,\n );\n if (index !== -1) {\n this.#restItems.splice(index, 1);\n }\n }\n }\n return item;\n }\n\n rest(): NavContentNavItem[] {\n if (!this.#restItems) {\n this.#restItems = this.#items.filter(\n item => !this.#taken.has(item.node.spec.id),\n );\n }\n return this.#restItems;\n }\n\n clone(): NavContentNavItems {\n return new NavItemBag(this.#items, this.#taken);\n }\n\n withComponent(Component: (props: NavContentNavItem) => JSX.Element) {\n let renderedItems: JSX.Element[] | undefined;\n\n return {\n take: (id: string) => {\n const item = this.take(id);\n if (item && renderedItems) {\n const index = renderedItems.findIndex(\n renderedItem => renderedItem.key === item.node.spec.id,\n );\n if (index !== -1) {\n renderedItems.splice(index, 1);\n }\n }\n return item ? <Component key={item.node.spec.id} {...item} /> : null;\n },\n rest: (options?: { sortBy?: 'title' }) => {\n const items = this.rest();\n if (!renderedItems) {\n if (options?.sortBy === 'title') {\n items.sort((a, b) => a.title.localeCompare(b.title));\n }\n renderedItems = items.map(item => (\n <Component key={item.node.spec.id} {...item} />\n ));\n }\n return renderedItems;\n },\n };\n }\n}\n\nfunction DefaultNavContent(props: NavContentComponentProps) {\n const items = props.navItems.rest();\n return (\n <Sidebar>\n {items.map(item => (\n <SidebarItem\n to={item.href}\n icon={() => item.icon}\n text={item.title}\n key={item.node.spec.id}\n />\n ))}\n </Sidebar>\n );\n}\n\n// Tries to resolve a routeRef to a link path, returning undefined if it\n// can't be resolved (e.g. parameterized routes).\nfunction tryResolveLink(\n routeResolutionApi: RouteResolutionApi,\n routeRef: RouteRef,\n): string | undefined {\n try {\n const link = routeResolutionApi.resolve(routeRef);\n return link?.();\n } catch {\n return undefined;\n }\n}\n\n// Defers rendering until the app is fully initialized so that APIs like\n// RouteResolutionApi and AppTreeApi are available.\nfunction NavContentRenderer(props: {\n Content: NavContentComponent;\n legacyNavItems: Array<{\n title: string;\n icon: IconComponent;\n routeRef: RouteRef<undefined>;\n }>;\n}) {\n const appTreeApi = useApi(appTreeApiRef);\n const routeResolutionApi = useApi(routeResolutionApiRef);\n\n // Deprecated items: just resolve nav item routeRefs to paths, no page discovery.\n const legacyItems = useMemo(() => {\n return props.legacyNavItems.flatMap(item => {\n const link = routeResolutionApi.resolve(item.routeRef);\n if (!link) return [];\n return [\n {\n to: link(),\n text: item.title,\n icon: item.icon,\n title: item.title,\n routeRef: item.routeRef,\n },\n ];\n });\n }, [props.legacyNavItems, routeResolutionApi]);\n\n // New navItems: discover pages from the extension tree, merged with nav items.\n const navItems = useMemo(() => {\n const { tree } = appTreeApi.getTree();\n const routesNode = tree.nodes.get('app/routes');\n if (!routesNode) return new NavItemBag([]);\n\n // Index nav items by routeRef for matching against pages\n const navItemsByRouteRef = new Map<\n RouteRef,\n { title: string; icon: IconComponent }\n >(props.legacyNavItems.map(item => [item.routeRef, item]));\n\n const pageNodes = routesNode.edges.attachments.get('routes') ?? [];\n const items = pageNodes.flatMap((node): NavContentNavItem[] => {\n if (!node.instance || node.spec.disabled) {\n return [];\n }\n\n const routeRef = node.instance.getData(coreExtensionData.routeRef);\n if (!routeRef) {\n return [];\n }\n\n const matchingNavItem = navItemsByRouteRef.get(routeRef);\n\n // PageBlueprint resolves title as: config.title ?? params.title ?? plugin.title ?? pluginId\n // We want the priority: page (config/params) -> nav item -> plugin -> pluginId\n const resolvedTitle = node.instance.getData(coreExtensionData.title);\n const pluginTitle = node.spec.plugin.title;\n const pluginIcon = node.spec.plugin.icon;\n const pluginId = node.spec.plugin.pluginId;\n const hasExplicitPageTitle =\n resolvedTitle !== undefined &&\n resolvedTitle !== pluginTitle &&\n resolvedTitle !== pluginId;\n const title = hasExplicitPageTitle\n ? resolvedTitle\n : matchingNavItem?.title ?? pluginTitle ?? pluginId;\n\n // PageBlueprint resolves icon as: params.icon ?? plugin.icon\n // We want the priority: page (params) -> nav item -> plugin -> (excluded)\n const resolvedIcon = node.instance.getData(coreExtensionData.icon);\n const hasExplicitPageIcon = resolvedIcon && !node.spec.plugin.icon;\n const NavItemIcon = matchingNavItem?.icon;\n\n let icon: IconElement | undefined;\n if (hasExplicitPageIcon) {\n icon = resolvedIcon;\n } else if (NavItemIcon) {\n icon = <NavItemIcon />;\n } else if (resolvedIcon) {\n icon = resolvedIcon;\n } else if (pluginIcon) {\n icon = pluginIcon;\n }\n\n if (!title || !icon) {\n return [];\n }\n\n const to = tryResolveLink(routeResolutionApi, routeRef);\n if (!to) {\n return [];\n }\n\n return [{ node, href: to, title, icon, routeRef }];\n });\n\n return new NavItemBag(items);\n }, [appTreeApi, routeResolutionApi, props.legacyNavItems]);\n\n return <props.Content navItems={navItems} items={legacyItems} />;\n}\n\nexport const AppNav = createExtension({\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n inputs: {\n items: createExtensionInput([NavItemBlueprint.dataRefs.target]),\n content: createExtensionInput([NavContentBlueprint.dataRefs.component], {\n singleton: true,\n optional: true,\n internal: true,\n }),\n },\n output: [coreExtensionData.reactElement],\n *factory({ inputs }) {\n const Content =\n inputs.content?.get(NavContentBlueprint.dataRefs.component) ??\n DefaultNavContent;\n\n yield coreExtensionData.reactElement(\n <NavContentRenderer\n legacyNavItems={inputs.items.map(item =>\n item.get(NavItemBlueprint.dataRefs.target),\n )}\n Content={Content}\n />,\n );\n },\n});\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { useState } from 'react';
3
- import { createExtension, coreExtensionData, createExtensionInput, discoveryApiRef, errorApiRef, fetchApiRef, useAnalytics, routeResolutionApiRef } from '@backstage/frontend-plugin-api';
3
+ import { createExtension, coreExtensionData, createExtensionInput, discoveryApiRef, errorApiRef, fetchApiRef, pluginWrapperApiRef, ExtensionBoundary, routeResolutionApiRef, useAnalytics } from '@backstage/frontend-plugin-api';
4
4
  import { AppRootWrapperBlueprint, RouterBlueprint, SignInPageBlueprint } from '@backstage/plugin-app-react';
5
5
  import { BUIProvider } from '@backstage/ui';
6
6
  import { identityApiRef, useApi, configApiRef } from '@backstage/core-plugin-api';
@@ -24,7 +24,8 @@ const AppRoot = createExtension({
24
24
  internal: true
25
25
  }),
26
26
  children: createExtensionInput([coreExtensionData.reactElement], {
27
- singleton: true
27
+ singleton: true,
28
+ optional: true
28
29
  }),
29
30
  elements: createExtensionInput([coreExtensionData.reactElement]),
30
31
  wrappers: createExtensionInput(
@@ -35,7 +36,7 @@ const AppRoot = createExtension({
35
36
  )
36
37
  },
37
38
  output: [coreExtensionData.reactElement],
38
- factory({ inputs, apis }) {
39
+ factory({ inputs, apis, node }) {
39
40
  if (isProtectedApp()) {
40
41
  const identityApi = apis.get(identityApiRef);
41
42
  if (!identityApi) {
@@ -56,18 +57,21 @@ const AppRoot = createExtension({
56
57
  fetchApi
57
58
  });
58
59
  }
59
- let content = inputs.children.get(
60
- coreExtensionData.reactElement
61
- );
60
+ let content = inputs.children?.get(coreExtensionData.reactElement);
62
61
  for (const wrapper of inputs.wrappers) {
63
62
  const Component = wrapper.get(AppRootWrapperBlueprint.dataRefs.component);
64
63
  if (Component) {
65
64
  content = /* @__PURE__ */ jsx(Component, { children: content });
66
65
  }
67
66
  }
67
+ const pluginWrapperApi = apis.get(pluginWrapperApiRef);
68
+ const RootWrapper = pluginWrapperApi?.getRootWrapper();
69
+ if (RootWrapper) {
70
+ content = /* @__PURE__ */ jsx(RootWrapper, { children: content });
71
+ }
68
72
  return [
69
73
  coreExtensionData.reactElement(
70
- /* @__PURE__ */ jsx(BUIProvider, { useAnalytics, children: /* @__PURE__ */ jsx(
74
+ /* @__PURE__ */ jsx(ExtensionBoundary, { node, children: /* @__PURE__ */ jsx(
71
75
  AppRouter,
72
76
  {
73
77
  SignInPageComponent: inputs.signInPage?.get(
@@ -139,36 +143,38 @@ function AppRouter(props) {
139
143
  }
140
144
  const routeObjects = routeResolutionsApi.getRouteObjects();
141
145
  if (!SignInPageComponent) {
142
- appIdentityProxy.setTarget(
143
- {
144
- getUserId: () => "guest",
145
- getIdToken: async () => void 0,
146
- getProfile: () => ({
147
- email: "guest@example.com",
148
- displayName: "Guest"
149
- }),
150
- getProfileInfo: async () => ({
151
- email: "guest@example.com",
152
- displayName: "Guest"
153
- }),
154
- getBackstageIdentity: async () => ({
155
- type: "user",
156
- userEntityRef: "user:default/guest",
157
- ownershipEntityRefs: ["user:default/guest"]
158
- }),
159
- getCredentials: async () => ({}),
160
- signOut: async () => {
161
- }
162
- },
163
- { signOutTargetUrl: basePath || "/" }
164
- );
165
- return /* @__PURE__ */ jsxs(RouterComponent, { children: [
146
+ if (!isProtectedApp()) {
147
+ appIdentityProxy.setTarget(
148
+ {
149
+ getUserId: () => "guest",
150
+ getIdToken: async () => void 0,
151
+ getProfile: () => ({
152
+ email: "guest@example.com",
153
+ displayName: "Guest"
154
+ }),
155
+ getProfileInfo: async () => ({
156
+ email: "guest@example.com",
157
+ displayName: "Guest"
158
+ }),
159
+ getBackstageIdentity: async () => ({
160
+ type: "user",
161
+ userEntityRef: "user:default/guest",
162
+ ownershipEntityRefs: ["user:default/guest"]
163
+ }),
164
+ getCredentials: async () => ({}),
165
+ signOut: async () => {
166
+ }
167
+ },
168
+ { signOutTargetUrl: basePath || "/" }
169
+ );
170
+ }
171
+ return /* @__PURE__ */ jsx(RouterComponent, { children: /* @__PURE__ */ jsxs(BUIProvider, { useAnalytics, children: [
166
172
  ...extraElements,
167
173
  /* @__PURE__ */ jsx(RouteTracker, { routeObjects }),
168
174
  children
169
- ] });
175
+ ] }) });
170
176
  }
171
- return /* @__PURE__ */ jsxs(RouterComponent, { children: [
177
+ return /* @__PURE__ */ jsx(RouterComponent, { children: /* @__PURE__ */ jsxs(BUIProvider, { useAnalytics, children: [
172
178
  ...extraElements,
173
179
  /* @__PURE__ */ jsx(RouteTracker, { routeObjects }),
174
180
  /* @__PURE__ */ jsx(
@@ -179,7 +185,7 @@ function AppRouter(props) {
179
185
  children
180
186
  }
181
187
  )
182
- ] });
188
+ ] }) });
183
189
  }
184
190
 
185
191
  export { AppRoot, AppRouter };