@backstage/frontend-plugin-api 0.16.0-next.2 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/alpha.d.ts +2 -1
- package/dist/apis/definitions/DialogApi.esm.js.map +1 -1
- package/dist/blueprints/NavItemBlueprint.esm.js +3 -4
- package/dist/blueprints/NavItemBlueprint.esm.js.map +1 -1
- package/dist/blueprints/PageBlueprint.esm.js +4 -5
- package/dist/blueprints/PageBlueprint.esm.js.map +1 -1
- package/dist/blueprints/SubPageBlueprint.esm.js +4 -5
- package/dist/blueprints/SubPageBlueprint.esm.js.map +1 -1
- package/dist/index.d.ts +65 -79
- package/dist/schema/createPortableSchema.esm.js +207 -0
- package/dist/schema/createPortableSchema.esm.js.map +1 -0
- package/dist/types/{alpha.d-CfDtkom8.d.ts → alpha.d-D3gnSOzm.d.ts} +236 -19
- package/dist/wiring/createExtension.esm.js +17 -10
- package/dist/wiring/createExtension.esm.js.map +1 -1
- package/dist/wiring/createExtensionBlueprint.esm.js +11 -1
- package/dist/wiring/createExtensionBlueprint.esm.js.map +1 -1
- package/dist/wiring/createFrontendModule.esm.js +5 -29
- package/dist/wiring/createFrontendModule.esm.js.map +1 -1
- package/dist/wiring/createFrontendPlugin.esm.js +10 -27
- package/dist/wiring/createFrontendPlugin.esm.js.map +1 -1
- package/dist/wiring/resolveExtensionDefinition.esm.js +28 -1
- package/dist/wiring/resolveExtensionDefinition.esm.js.map +1 -1
- package/package.json +11 -10
- package/dist/schema/createSchemaFromZod.esm.js +0 -34
- package/dist/schema/createSchemaFromZod.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @backstage/frontend-plugin-api
|
|
2
2
|
|
|
3
|
+
## 0.16.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6b60bd7: Replaced old config schema values from existing extensions and blueprints.
|
|
8
|
+
|
|
9
|
+
## 0.16.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- fa55078: **BREAKING**: Removed the deprecated `createSchemaFromZod` helper. Use the new `configSchema` option instead. See the [1.50 migration documentation](https://backstage.io/docs/frontend-system/architecture/migrations#150) for more information.
|
|
14
|
+
- 49397c1: Simplified the type signature of `createRouteRef` by replacing the dual `TParams`/`TParamKeys` type parameters with a single `TParamKey` parameter. This is a breaking change for callers that explicitly provided type arguments, but most usage that relies on inference is unaffected.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 4c09967: Fixed the duplicate extension error message in `createFrontendModule` to correctly say "Module" instead of "Plugin".
|
|
19
|
+
- e4804ab: Added `open` method to `DialogApi` that renders dialogs without any built-in dialog chrome, giving the caller full control over the dialog presentation. This avoids focus trap conflicts that occur when mixing components from different design libraries. The existing `show` and `showModal` methods are now deprecated in favor of `open`.
|
|
20
|
+
- ddc5247: Fixed `FlattenedMessages` type to avoid excessive type instantiation depth in TypeScript 6 when using `createTranslationRef` with the `translations` option.
|
|
21
|
+
- a2a6c3b: Added a new `configSchema` option for `createExtension` and `createExtensionBlueprint` that accepts direct schema values from any [Standard Schema](https://github.com/standard-schema/standard-schema) compatible library with JSON Schema support, such as zod v4 or the `zod/v4` subpath from zod v3. The old `config.schema` option is now deprecated. Note that direct zod v3 schemas are not supported by the new `configSchema` option — use `import { z } from 'zod/v4'` from the zod v3 package, or upgrade to zod v4. See the [1.50 migration documentation](https://backstage.io/docs/frontend-system/architecture/migrations#150) for more information.
|
|
22
|
+
- d66a3ec: Added `titleLink` prop to `PageLayoutProps` so the plugin header title can link back to the plugin root.
|
|
23
|
+
- e220589: Removed the unnecessary need to use `defineParams` callback from `PluginHeaderActionBlueprint`. It still works, but is no longer required.
|
|
24
|
+
- Updated dependencies
|
|
25
|
+
- @backstage/errors@1.3.0
|
|
26
|
+
- @backstage/filter-predicates@0.1.2
|
|
27
|
+
|
|
3
28
|
## 0.16.0-next.2
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/dist/alpha.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { A as AnyRouteRefParams, e as ApiHolder, d as ApiRef, b as AppNode, i as AppNodeEdges, j as AppNodeInstance, k as AppNodeSpec, l as AppTree, C as ConfigurableExtensionDataRef, r as Extension, s as ExtensionAttachTo, t as ExtensionBlueprint, u as ExtensionBlueprintDefineParams, v as ExtensionBlueprintParameters, w as ExtensionBlueprintParams, x as ExtensionDataContainer, y as ExtensionDataRef, z as ExtensionDataValue, B as ExtensionDefinition, D as ExtensionDefinitionAttachTo, G as ExtensionDefinitionParameters, J as ExtensionInput, E as ExternalRouteRef, c as FrontendPlugin, M as FrontendPluginInfo, I as IconElement, O as OverridableExtensionDefinition, U as PluginWrapperApi, V as PluginWrapperBlueprint, W as PluginWrapperDefinition, X as PortableSchema, R as RouteRef, S as SubRouteRef, $ as createExtensionBlueprintParams, a7 as pluginWrapperApiRef } from './types/alpha.d-
|
|
1
|
+
export { A as AnyRouteRefParams, e as ApiHolder, d as ApiRef, b as AppNode, i as AppNodeEdges, j as AppNodeInstance, k as AppNodeSpec, l as AppTree, C as ConfigurableExtensionDataRef, r as Extension, s as ExtensionAttachTo, t as ExtensionBlueprint, u as ExtensionBlueprintDefineParams, v as ExtensionBlueprintParameters, w as ExtensionBlueprintParams, x as ExtensionDataContainer, y as ExtensionDataRef, z as ExtensionDataValue, B as ExtensionDefinition, D as ExtensionDefinitionAttachTo, G as ExtensionDefinitionParameters, J as ExtensionInput, E as ExternalRouteRef, c as FrontendPlugin, M as FrontendPluginInfo, I as IconElement, O as OverridableExtensionDefinition, U as PluginWrapperApi, V as PluginWrapperBlueprint, W as PluginWrapperDefinition, X as PortableSchema, R as RouteRef, S as SubRouteRef, $ as createExtensionBlueprintParams, a7 as pluginWrapperApiRef } from './types/alpha.d-D3gnSOzm.js';
|
|
2
|
+
export { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
3
|
import '@backstage/frontend-plugin-api';
|
|
3
4
|
import 'react';
|
|
4
5
|
import '@backstage/types';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DialogApi.esm.js","sources":["../../../src/apis/definitions/DialogApi.ts"],"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 { createApiRef } from '../system';\n\n/**\n * A handle for an open dialog that can be used to interact with it.\n *\n * @remarks\n *\n * Dialogs
|
|
1
|
+
{"version":3,"file":"DialogApi.esm.js","sources":["../../../src/apis/definitions/DialogApi.ts"],"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 { createApiRef } from '../system';\n\n/**\n * A handle for an open dialog that can be used to interact with it.\n *\n * @remarks\n *\n * Dialogs are opened using {@link DialogApi.open}.\n *\n * @public\n */\nexport interface DialogApiDialog<TResult = void> {\n /**\n * Closes the dialog with the provided result.\n *\n * @remarks\n *\n * Whether a result is required depends on the `TResult` type parameter\n * chosen when the dialog was opened. If the type includes `undefined`,\n * calling `close()` without a result is allowed.\n */\n close(\n ...args: undefined extends TResult ? [result?: TResult] : [result: TResult]\n ): void;\n\n /**\n * Replaces the rendered dialog with the provided element or component.\n *\n * @remarks\n *\n * Just like the element or component passed to {@link DialogApi.open}, the\n * caller is responsible for providing the full dialog including all chrome.\n */\n update(\n elementOrComponent:\n | JSX.Element\n | ((props: { dialog: DialogApiDialog<TResult> }) => JSX.Element),\n ): void;\n\n /**\n * Wait until the dialog is closed and return the result.\n */\n result(): Promise<TResult>;\n}\n\n/**\n * A Utility API for showing dialogs that render in the React tree and return a result.\n *\n * @public\n */\nexport interface DialogApi {\n /**\n * Opens a dialog and returns a handle to it.\n *\n * @remarks\n *\n * The provided element or component is rendered as-is in the app's React tree.\n * It is the caller's responsibility to provide all dialog chrome, such as an\n * overlay, backdrop, and dialog surface. This makes the method agnostic to the\n * design library used for the dialog.\n *\n * @example\n *\n * ### Example with inline dialog element\n * ```tsx\n * const dialog = dialogApi.open<boolean>(\n * <Dialog isOpen onOpenChange={isOpen => !isOpen && dialog.close()}>\n * <DialogHeader>Are you sure?</DialogHeader>\n * <DialogBody>This action cannot be undone.</DialogBody>\n * <DialogFooter>\n * <Button onPress={() => dialog.close(false)}>Cancel</Button>\n * <Button onPress={() => dialog.close(true)}>Confirm</Button>\n * </DialogFooter>\n * </Dialog>\n * );\n * const result = await dialog.result();\n * ```\n *\n * @example\n *\n * ### Example with a dialog component\n * ```tsx\n * function ConfirmDialog({ dialog }: { dialog: DialogApiDialog<boolean> }) {\n * return (\n * <Dialog isOpen onOpenChange={isOpen => !isOpen && dialog.close()}>\n * <DialogHeader>Are you sure?</DialogHeader>\n * <DialogBody>This action cannot be undone.</DialogBody>\n * <DialogFooter>\n * <Button onPress={() => dialog.close(false)}>Cancel</Button>\n * <Button onPress={() => dialog.close(true)}>Confirm</Button>\n * </DialogFooter>\n * </Dialog>\n * );\n * }\n * const result = await dialogApi.open(ConfirmDialog).result();\n * ```\n *\n * @param elementOrComponent - The element or component to render. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.\n */\n open<TResult = void>(\n elementOrComponent:\n | JSX.Element\n | ((props: { dialog: DialogApiDialog<TResult> }) => JSX.Element),\n ): DialogApiDialog<TResult>;\n\n /**\n * Opens a dialog with built-in dialog chrome and returns a handle to it.\n *\n * @deprecated Use {@link DialogApi.open} instead. The `open` method does not\n * render any dialog chrome, giving the caller full control over the dialog\n * presentation. This avoids focus trap conflicts across design libraries.\n *\n * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.\n */\n show<TResult = void>(\n elementOrComponent:\n | JSX.Element\n | ((props: {\n dialog: DialogApiDialog<TResult | undefined>;\n }) => JSX.Element),\n ): DialogApiDialog<TResult | undefined>;\n\n /**\n * Opens a modal dialog with built-in dialog chrome and returns a handle to it.\n *\n * @deprecated Use {@link DialogApi.open} instead. The `open` method does not\n * render any dialog chrome, giving the caller full control over the dialog\n * presentation. This avoids focus trap conflicts across design libraries.\n *\n * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.\n */\n showModal<TResult = void>(\n elementOrComponent:\n | JSX.Element\n | ((props: { dialog: DialogApiDialog<TResult> }) => JSX.Element),\n ): DialogApiDialog<TResult>;\n}\n\n/**\n * The `ApiRef` of {@link DialogApi}.\n *\n * @public\n */\nexport const dialogApiRef = createApiRef<DialogApi>().with({\n id: 'core.dialog',\n pluginId: 'app',\n});\n"],"names":[],"mappings":";;;;;AA+JO,MAAM,YAAA,GAAe,YAAA,EAAwB,CAAE,IAAA,CAAK;AAAA,EACzD,EAAA,EAAI,aAAA;AAAA,EACJ,QAAA,EAAU;AACZ,CAAC;;;;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
1
2
|
import '../wiring/coreExtensionData.esm.js';
|
|
2
3
|
import 'zod/v3';
|
|
3
4
|
import 'zod-to-json-schema';
|
|
@@ -23,10 +24,8 @@ const NavItemBlueprint = createExtensionBlueprint({
|
|
|
23
24
|
routeRef
|
|
24
25
|
})
|
|
25
26
|
],
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
title: (z) => z.string().optional()
|
|
29
|
-
}
|
|
27
|
+
configSchema: {
|
|
28
|
+
title: z.string().optional()
|
|
30
29
|
}
|
|
31
30
|
});
|
|
32
31
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavItemBlueprint.esm.js","sources":["../../src/blueprints/NavItemBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { IconComponent } from '../icons/types';\nimport { RouteRef } from '../routing';\nimport { createExtensionBlueprint, createExtensionDataRef } from '../wiring';\n\n// TODO(Rugvip): Should this be broken apart into separate refs? title/icon/routeRef\nconst targetDataRef = createExtensionDataRef<{\n title: string;\n icon: IconComponent;\n routeRef: RouteRef<undefined>;\n}>().with({ id: 'core.nav-item.target' });\n\n/**\n * Creates extensions that make up the items of the nav bar.\n *\n * @public\n * @deprecated Nav items are now automatically inferred from `PageBlueprint`\n * extensions based on their `title` and `icon` params. You can remove your\n * `NavItemBlueprint` usage and instead pass `title` and `icon` directly to\n * the `PageBlueprint`.\n */\nexport const NavItemBlueprint = createExtensionBlueprint({\n kind: 'nav-item',\n attachTo: { id: 'app/nav', input: 'items' },\n output: [targetDataRef],\n dataRefs: {\n target: targetDataRef,\n },\n factory: (\n {\n icon,\n routeRef,\n title,\n }: {\n title: string;\n icon: IconComponent;\n routeRef: RouteRef<undefined>;\n },\n { config },\n ) => [\n targetDataRef({\n title: config.title ?? title,\n icon,\n routeRef,\n }),\n ],\n
|
|
1
|
+
{"version":3,"file":"NavItemBlueprint.esm.js","sources":["../../src/blueprints/NavItemBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { z } from 'zod/v4';\nimport { IconComponent } from '../icons/types';\nimport { RouteRef } from '../routing';\nimport { createExtensionBlueprint, createExtensionDataRef } from '../wiring';\n\n// TODO(Rugvip): Should this be broken apart into separate refs? title/icon/routeRef\nconst targetDataRef = createExtensionDataRef<{\n title: string;\n icon: IconComponent;\n routeRef: RouteRef<undefined>;\n}>().with({ id: 'core.nav-item.target' });\n\n/**\n * Creates extensions that make up the items of the nav bar.\n *\n * @public\n * @deprecated Nav items are now automatically inferred from `PageBlueprint`\n * extensions based on their `title` and `icon` params. You can remove your\n * `NavItemBlueprint` usage and instead pass `title` and `icon` directly to\n * the `PageBlueprint`.\n */\nexport const NavItemBlueprint = createExtensionBlueprint({\n kind: 'nav-item',\n attachTo: { id: 'app/nav', input: 'items' },\n output: [targetDataRef],\n dataRefs: {\n target: targetDataRef,\n },\n factory: (\n {\n icon,\n routeRef,\n title,\n }: {\n title: string;\n icon: IconComponent;\n routeRef: RouteRef<undefined>;\n },\n { config },\n ) => [\n targetDataRef({\n title: config.title ?? title,\n icon,\n routeRef,\n }),\n ],\n configSchema: {\n title: z.string().optional(),\n },\n});\n"],"names":[],"mappings":";;;;;;;AAsBA,MAAM,gBAAgB,sBAAA,EAInB,CAAE,KAAK,EAAE,EAAA,EAAI,wBAAwB,CAAA;AAWjC,MAAM,mBAAmB,wBAAA,CAAyB;AAAA,EACvD,IAAA,EAAM,UAAA;AAAA,EACN,QAAA,EAAU,EAAE,EAAA,EAAI,SAAA,EAAW,OAAO,OAAA,EAAQ;AAAA,EAC1C,MAAA,EAAQ,CAAC,aAAa,CAAA;AAAA,EACtB,QAAA,EAAU;AAAA,IACR,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,SAAS,CACP;AAAA,IACE,IAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACF,EAKA,EAAE,MAAA,EAAO,KACN;AAAA,IACH,aAAA,CAAc;AAAA,MACZ,KAAA,EAAO,OAAO,KAAA,IAAS,KAAA;AAAA,MACvB,IAAA;AAAA,MACA;AAAA,KACD;AAAA,GACH;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS;AAE/B,CAAC;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { z } from 'zod/v4';
|
|
2
3
|
import { Routes, Route, Navigate } from 'react-router-dom';
|
|
3
4
|
import { coreExtensionData } from '../wiring/coreExtensionData.esm.js';
|
|
4
5
|
import 'zod/v3';
|
|
@@ -63,11 +64,9 @@ const PageBlueprint = createExtensionBlueprint({
|
|
|
63
64
|
coreExtensionData.title.optional(),
|
|
64
65
|
coreExtensionData.icon.optional()
|
|
65
66
|
],
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
title: (z) => z.string().optional()
|
|
70
|
-
}
|
|
67
|
+
configSchema: {
|
|
68
|
+
path: z.string().optional(),
|
|
69
|
+
title: z.string().optional()
|
|
71
70
|
},
|
|
72
71
|
*factory(params, { config, node, inputs }) {
|
|
73
72
|
const title = config.title ?? params.title;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageBlueprint.esm.js","sources":["../../src/blueprints/PageBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { JSX } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\nimport { IconElement } from '../icons/types';\nimport { RouteRef } from '../routing';\nimport {\n coreExtensionData,\n createExtensionBlueprint,\n createExtensionInput,\n} from '../wiring';\nimport { ExtensionBoundary, PageLayout, PageLayoutTab } from '../components';\nimport { useApi } from '../apis/system';\nimport { routeResolutionApiRef } from '../apis/definitions/RouteResolutionApi';\nimport { pluginHeaderActionsApiRef } from '../apis/definitions/PluginHeaderActionsApi';\nimport { RouteResolutionApi } from '../apis/definitions/RouteResolutionApi';\n\nfunction resolveTitleLink(\n routeResolutionApi: RouteResolutionApi,\n routeRef: RouteRef | undefined,\n): string | undefined {\n if (!routeRef) {\n return undefined;\n }\n try {\n return routeResolutionApi.resolve(routeRef)?.();\n } catch {\n // Route ref may require params not available in the current context\n return undefined;\n }\n}\n\n/**\n * Creates extensions that are routable React page components.\n *\n * @public\n */\nexport const PageBlueprint = createExtensionBlueprint({\n kind: 'page',\n attachTo: { id: 'app/routes', input: 'routes' },\n inputs: {\n pages: createExtensionInput([\n coreExtensionData.routePath,\n coreExtensionData.routeRef.optional(),\n coreExtensionData.reactElement,\n coreExtensionData.title.optional(),\n coreExtensionData.icon.optional(),\n ]),\n },\n output: [\n coreExtensionData.routePath,\n coreExtensionData.reactElement,\n coreExtensionData.routeRef.optional(),\n coreExtensionData.title.optional(),\n coreExtensionData.icon.optional(),\n ],\n config: {\n schema: {\n path: z => z.string().optional(),\n title: z => z.string().optional(),\n },\n },\n *factory(\n params: {\n path: string;\n title?: string;\n icon?: IconElement;\n loader?: () => Promise<JSX.Element>;\n routeRef?: RouteRef;\n /**\n * Hide the default plugin page header, making the page fill up all available space.\n */\n noHeader?: boolean;\n },\n { config, node, inputs },\n ) {\n const title = config.title ?? params.title;\n const icon = params.icon;\n const pluginId = node.spec.plugin.pluginId;\n const noHeader = params.noHeader ?? false;\n const resolvedTitle =\n title ?? node.spec.plugin.title ?? node.spec.plugin.pluginId;\n const resolvedIcon = icon ?? node.spec.plugin.icon;\n const titleRouteRef =\n (node.spec.plugin.routes as { root?: RouteRef }).root ?? params.routeRef;\n\n yield coreExtensionData.routePath(config.path ?? params.path);\n if (params.loader) {\n const loader = params.loader;\n const PageContent = () => {\n const routeResolutionApi = useApi(routeResolutionApiRef);\n const titleLink = resolveTitleLink(routeResolutionApi, titleRouteRef);\n const headerActionsApi = useApi(pluginHeaderActionsApiRef);\n const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);\n\n return (\n <PageLayout\n title={resolvedTitle}\n icon={resolvedIcon}\n noHeader={noHeader}\n titleLink={titleLink}\n headerActions={headerActions}\n >\n {ExtensionBoundary.lazy(node, loader)}\n </PageLayout>\n );\n };\n yield coreExtensionData.reactElement(<PageContent />);\n } else if (inputs.pages.length > 0) {\n // Parent page with sub-pages - render header with tabs\n const tabs: PageLayoutTab[] = inputs.pages.map(page => {\n const path = page.get(coreExtensionData.routePath);\n const tabTitle = page.get(coreExtensionData.title);\n const tabIcon = page.get(coreExtensionData.icon);\n return {\n id: path,\n label: tabTitle || path,\n icon: tabIcon,\n href: path,\n };\n });\n\n const PageContent = () => {\n const firstPagePath = inputs.pages[0]?.get(coreExtensionData.routePath);\n const routeResolutionApi = useApi(routeResolutionApiRef);\n const titleLink = resolveTitleLink(routeResolutionApi, titleRouteRef);\n\n const headerActionsApi = useApi(pluginHeaderActionsApiRef);\n const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);\n\n return (\n <PageLayout\n title={resolvedTitle}\n icon={resolvedIcon}\n tabs={tabs}\n titleLink={titleLink}\n headerActions={headerActions}\n >\n <Routes>\n {firstPagePath && (\n <Route\n index\n element={<Navigate to={firstPagePath} replace />}\n />\n )}\n {inputs.pages.map((page, index) => {\n const path = page.get(coreExtensionData.routePath);\n const element = page.get(coreExtensionData.reactElement);\n return (\n <Route key={index} path={`${path}/*`} element={element} />\n );\n })}\n </Routes>\n </PageLayout>\n );\n };\n\n yield coreExtensionData.reactElement(<PageContent />);\n } else {\n const PageContent = () => {\n const routeResolutionApi = useApi(routeResolutionApiRef);\n const titleLink = resolveTitleLink(routeResolutionApi, titleRouteRef);\n const headerActionsApi = useApi(pluginHeaderActionsApiRef);\n const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);\n return (\n <PageLayout\n title={resolvedTitle}\n icon={resolvedIcon}\n titleLink={titleLink}\n headerActions={headerActions}\n />\n );\n };\n yield coreExtensionData.reactElement(<PageContent />);\n }\n if (params.routeRef) {\n yield coreExtensionData.routeRef(params.routeRef);\n }\n if (title) {\n yield coreExtensionData.title(title);\n }\n if (icon) {\n yield coreExtensionData.icon(icon);\n }\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PageBlueprint.esm.js","sources":["../../src/blueprints/PageBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { z } from 'zod/v4';\nimport { JSX } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\nimport { IconElement } from '../icons/types';\nimport { RouteRef } from '../routing';\nimport {\n coreExtensionData,\n createExtensionBlueprint,\n createExtensionInput,\n} from '../wiring';\nimport { ExtensionBoundary, PageLayout, PageLayoutTab } from '../components';\nimport { useApi } from '../apis/system';\nimport { routeResolutionApiRef } from '../apis/definitions/RouteResolutionApi';\nimport { pluginHeaderActionsApiRef } from '../apis/definitions/PluginHeaderActionsApi';\nimport { RouteResolutionApi } from '../apis/definitions/RouteResolutionApi';\n\nfunction resolveTitleLink(\n routeResolutionApi: RouteResolutionApi,\n routeRef: RouteRef | undefined,\n): string | undefined {\n if (!routeRef) {\n return undefined;\n }\n try {\n return routeResolutionApi.resolve(routeRef)?.();\n } catch {\n // Route ref may require params not available in the current context\n return undefined;\n }\n}\n\n/**\n * Creates extensions that are routable React page components.\n *\n * @public\n */\nexport const PageBlueprint = createExtensionBlueprint({\n kind: 'page',\n attachTo: { id: 'app/routes', input: 'routes' },\n inputs: {\n pages: createExtensionInput([\n coreExtensionData.routePath,\n coreExtensionData.routeRef.optional(),\n coreExtensionData.reactElement,\n coreExtensionData.title.optional(),\n coreExtensionData.icon.optional(),\n ]),\n },\n output: [\n coreExtensionData.routePath,\n coreExtensionData.reactElement,\n coreExtensionData.routeRef.optional(),\n coreExtensionData.title.optional(),\n coreExtensionData.icon.optional(),\n ],\n configSchema: {\n path: z.string().optional(),\n title: z.string().optional(),\n },\n *factory(\n params: {\n path: string;\n title?: string;\n icon?: IconElement;\n loader?: () => Promise<JSX.Element>;\n routeRef?: RouteRef;\n /**\n * Hide the default plugin page header, making the page fill up all available space.\n */\n noHeader?: boolean;\n },\n { config, node, inputs },\n ) {\n const title = config.title ?? params.title;\n const icon = params.icon;\n const pluginId = node.spec.plugin.pluginId;\n const noHeader = params.noHeader ?? false;\n const resolvedTitle =\n title ?? node.spec.plugin.title ?? node.spec.plugin.pluginId;\n const resolvedIcon = icon ?? node.spec.plugin.icon;\n const titleRouteRef =\n (node.spec.plugin.routes as { root?: RouteRef }).root ?? params.routeRef;\n\n yield coreExtensionData.routePath(config.path ?? params.path);\n if (params.loader) {\n const loader = params.loader;\n const PageContent = () => {\n const routeResolutionApi = useApi(routeResolutionApiRef);\n const titleLink = resolveTitleLink(routeResolutionApi, titleRouteRef);\n const headerActionsApi = useApi(pluginHeaderActionsApiRef);\n const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);\n\n return (\n <PageLayout\n title={resolvedTitle}\n icon={resolvedIcon}\n noHeader={noHeader}\n titleLink={titleLink}\n headerActions={headerActions}\n >\n {ExtensionBoundary.lazy(node, loader)}\n </PageLayout>\n );\n };\n yield coreExtensionData.reactElement(<PageContent />);\n } else if (inputs.pages.length > 0) {\n // Parent page with sub-pages - render header with tabs\n const tabs: PageLayoutTab[] = inputs.pages.map(page => {\n const path = page.get(coreExtensionData.routePath);\n const tabTitle = page.get(coreExtensionData.title);\n const tabIcon = page.get(coreExtensionData.icon);\n return {\n id: path,\n label: tabTitle || path,\n icon: tabIcon,\n href: path,\n };\n });\n\n const PageContent = () => {\n const firstPagePath = inputs.pages[0]?.get(coreExtensionData.routePath);\n const routeResolutionApi = useApi(routeResolutionApiRef);\n const titleLink = resolveTitleLink(routeResolutionApi, titleRouteRef);\n\n const headerActionsApi = useApi(pluginHeaderActionsApiRef);\n const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);\n\n return (\n <PageLayout\n title={resolvedTitle}\n icon={resolvedIcon}\n tabs={tabs}\n titleLink={titleLink}\n headerActions={headerActions}\n >\n <Routes>\n {firstPagePath && (\n <Route\n index\n element={<Navigate to={firstPagePath} replace />}\n />\n )}\n {inputs.pages.map((page, index) => {\n const path = page.get(coreExtensionData.routePath);\n const element = page.get(coreExtensionData.reactElement);\n return (\n <Route key={index} path={`${path}/*`} element={element} />\n );\n })}\n </Routes>\n </PageLayout>\n );\n };\n\n yield coreExtensionData.reactElement(<PageContent />);\n } else {\n const PageContent = () => {\n const routeResolutionApi = useApi(routeResolutionApiRef);\n const titleLink = resolveTitleLink(routeResolutionApi, titleRouteRef);\n const headerActionsApi = useApi(pluginHeaderActionsApiRef);\n const headerActions = headerActionsApi.getPluginHeaderActions(pluginId);\n return (\n <PageLayout\n title={resolvedTitle}\n icon={resolvedIcon}\n titleLink={titleLink}\n headerActions={headerActions}\n />\n );\n };\n yield coreExtensionData.reactElement(<PageContent />);\n }\n if (params.routeRef) {\n yield coreExtensionData.routeRef(params.routeRef);\n }\n if (title) {\n yield coreExtensionData.title(title);\n }\n if (icon) {\n yield coreExtensionData.icon(icon);\n }\n },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
1
2
|
import { coreExtensionData } from '../wiring/coreExtensionData.esm.js';
|
|
2
3
|
import 'zod/v3';
|
|
3
4
|
import 'zod-to-json-schema';
|
|
@@ -43,11 +44,9 @@ const SubPageBlueprint = createExtensionBlueprint({
|
|
|
43
44
|
coreExtensionData.routeRef.optional(),
|
|
44
45
|
coreExtensionData.icon.optional()
|
|
45
46
|
],
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
title: (z) => z.string().optional()
|
|
50
|
-
}
|
|
47
|
+
configSchema: {
|
|
48
|
+
path: z.string().optional(),
|
|
49
|
+
title: z.string().optional()
|
|
51
50
|
},
|
|
52
51
|
*factory(params, { config, node }) {
|
|
53
52
|
yield coreExtensionData.routePath(config.path ?? params.path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubPageBlueprint.esm.js","sources":["../../src/blueprints/SubPageBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { IconElement } from '../icons/types';\nimport { RouteRef } from '../routing';\nimport { coreExtensionData, createExtensionBlueprint } from '../wiring';\nimport { ExtensionBoundary } from '../components';\n\n/**\n * Creates extensions that are sub-page React components attached to a parent page.\n * Sub-pages are rendered as tabs within the parent page's header.\n *\n * @public\n * @example\n * ```tsx\n * const overviewRouteRef = createRouteRef();\n *\n * const mySubPage = SubPageBlueprint.make({\n * attachTo: { id: 'page:my-plugin', input: 'pages' },\n * name: 'overview',\n * params: {\n * path: 'overview',\n * title: 'Overview',\n * routeRef: overviewRouteRef,\n * loader: () => import('./components/Overview').then(m => <m.Overview />),\n * },\n * });\n * ```\n */\nexport const SubPageBlueprint = createExtensionBlueprint({\n kind: 'sub-page',\n attachTo: { relative: { kind: 'page' }, input: 'pages' },\n output: [\n coreExtensionData.routePath,\n coreExtensionData.reactElement,\n coreExtensionData.title,\n coreExtensionData.routeRef.optional(),\n coreExtensionData.icon.optional(),\n ],\n
|
|
1
|
+
{"version":3,"file":"SubPageBlueprint.esm.js","sources":["../../src/blueprints/SubPageBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { z } from 'zod/v4';\nimport { IconElement } from '../icons/types';\nimport { RouteRef } from '../routing';\nimport { coreExtensionData, createExtensionBlueprint } from '../wiring';\nimport { ExtensionBoundary } from '../components';\n\n/**\n * Creates extensions that are sub-page React components attached to a parent page.\n * Sub-pages are rendered as tabs within the parent page's header.\n *\n * @public\n * @example\n * ```tsx\n * const overviewRouteRef = createRouteRef();\n *\n * const mySubPage = SubPageBlueprint.make({\n * attachTo: { id: 'page:my-plugin', input: 'pages' },\n * name: 'overview',\n * params: {\n * path: 'overview',\n * title: 'Overview',\n * routeRef: overviewRouteRef,\n * loader: () => import('./components/Overview').then(m => <m.Overview />),\n * },\n * });\n * ```\n */\nexport const SubPageBlueprint = createExtensionBlueprint({\n kind: 'sub-page',\n attachTo: { relative: { kind: 'page' }, input: 'pages' },\n output: [\n coreExtensionData.routePath,\n coreExtensionData.reactElement,\n coreExtensionData.title,\n coreExtensionData.routeRef.optional(),\n coreExtensionData.icon.optional(),\n ],\n configSchema: {\n path: z.string().optional(),\n title: z.string().optional(),\n },\n *factory(\n params: {\n /**\n * The path for this sub-page, relative to the parent page. Must **not** start with '/'.\n *\n * @example 'overview', 'settings', 'details'\n */\n path: string;\n /**\n * The title displayed in the tab for this sub-page.\n */\n title: string;\n /**\n * Optional icon for this sub-page, displayed in the tab.\n */\n icon?: IconElement;\n /**\n * A function that returns a promise resolving to the React element to render.\n * This enables lazy loading of the sub-page content.\n */\n loader: () => Promise<JSX.Element>;\n /**\n * Optional route reference for this sub-page.\n */\n routeRef?: RouteRef;\n },\n { config, node },\n ) {\n yield coreExtensionData.routePath(config.path ?? params.path);\n yield coreExtensionData.title(config.title ?? params.title);\n yield coreExtensionData.reactElement(\n ExtensionBoundary.lazy(node, params.loader),\n );\n if (params.routeRef) {\n yield coreExtensionData.routeRef(params.routeRef);\n }\n if (params.icon) {\n yield coreExtensionData.icon(params.icon);\n }\n },\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CO,MAAM,mBAAmB,wBAAA,CAAyB;AAAA,EACvD,IAAA,EAAM,UAAA;AAAA,EACN,QAAA,EAAU,EAAE,QAAA,EAAU,EAAE,MAAM,MAAA,EAAO,EAAG,OAAO,OAAA,EAAQ;AAAA,EACvD,MAAA,EAAQ;AAAA,IACN,iBAAA,CAAkB,SAAA;AAAA,IAClB,iBAAA,CAAkB,YAAA;AAAA,IAClB,iBAAA,CAAkB,KAAA;AAAA,IAClB,iBAAA,CAAkB,SAAS,QAAA,EAAS;AAAA,IACpC,iBAAA,CAAkB,KAAK,QAAA;AAAS,GAClC;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,IAC1B,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS,GAC7B;AAAA,EACA,CAAC,OAAA,CACC,MAAA,EAyBA,EAAE,MAAA,EAAQ,MAAK,EACf;AACA,IAAA,MAAM,iBAAA,CAAkB,SAAA,CAAU,MAAA,CAAO,IAAA,IAAQ,OAAO,IAAI,CAAA;AAC5D,IAAA,MAAM,iBAAA,CAAkB,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,OAAO,KAAK,CAAA;AAC1D,IAAA,MAAM,iBAAA,CAAkB,YAAA;AAAA,MACtB,iBAAA,CAAkB,IAAA,CAAK,IAAA,EAAM,MAAA,CAAO,MAAM;AAAA,KAC5C;AACA,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,MAAM,iBAAA,CAAkB,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA;AAAA,IAClD;AACA,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,MAAM,iBAAA,CAAkB,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA;AAAA,IAC1C;AAAA,EACF;AACF,CAAC;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,10 +2,11 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, JSX as JSX$1, ComponentType, PropsWithChildren } from 'react';
|
|
4
4
|
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
5
|
-
import { I as IconElement, R as RouteRef, A as AnyRouteRefParams, S as SubRouteRef, E as ExternalRouteRef, F as FrontendFeature, a as IconComponent, b as AppNode, c as FrontendPlugin, d as ApiRef, e as ApiHolder, T as TypesToApiRefs, f as ApiFactory, g as AnyApiFactory } from './types/alpha.d-
|
|
6
|
-
export { h as AnyApiRef, i as AppNodeEdges, j as AppNodeInstance, k as AppNodeSpec, l as AppTree, m as AppTreeApi, C as ConfigurableExtensionDataRef, n as CreateExtensionBlueprintOptions, o as CreateExtensionOptions, p as CreateFrontendModuleOptions, q as CreateFrontendPluginOptions, r as Extension, s as ExtensionAttachTo, t as ExtensionBlueprint, u as ExtensionBlueprintDefineParams, v as ExtensionBlueprintParameters, w as ExtensionBlueprintParams, x as ExtensionDataContainer, y as ExtensionDataRef, z as ExtensionDataValue, B as ExtensionDefinition, D as ExtensionDefinitionAttachTo, G as ExtensionDefinitionParameters, H as ExtensionFactoryMiddleware, J as ExtensionInput, K as FeatureFlagConfig, L as FrontendModule, M as FrontendPluginInfo, N as FrontendPluginInfoOptions, O as OverridableExtensionDefinition, P as OverridableFrontendPlugin, Q as PluginOptions, U as PluginWrapperApi, V as PluginWrapperBlueprint, W as PluginWrapperDefinition, X as PortableSchema, Y as appTreeApiRef, Z as createExtension, _ as createExtensionBlueprint, $ as createExtensionBlueprintParams, a0 as createExtensionDataRef, a1 as createExtensionInput, a2 as createExternalRouteRef, a3 as createFrontendModule, a4 as createFrontendPlugin, a5 as createRouteRef, a6 as createSubRouteRef, a7 as pluginWrapperApiRef } from './types/alpha.d-
|
|
5
|
+
import { I as IconElement, R as RouteRef, A as AnyRouteRefParams, S as SubRouteRef, E as ExternalRouteRef, F as FrontendFeature, a as IconComponent, b as AppNode, c as FrontendPlugin, d as ApiRef, e as ApiHolder, T as TypesToApiRefs, f as ApiFactory, g as AnyApiFactory } from './types/alpha.d-D3gnSOzm.js';
|
|
6
|
+
export { h as AnyApiRef, i as AppNodeEdges, j as AppNodeInstance, k as AppNodeSpec, l as AppTree, m as AppTreeApi, C as ConfigurableExtensionDataRef, n as CreateExtensionBlueprintOptions, o as CreateExtensionOptions, p as CreateFrontendModuleOptions, q as CreateFrontendPluginOptions, r as Extension, s as ExtensionAttachTo, t as ExtensionBlueprint, u as ExtensionBlueprintDefineParams, v as ExtensionBlueprintParameters, w as ExtensionBlueprintParams, x as ExtensionDataContainer, y as ExtensionDataRef, z as ExtensionDataValue, B as ExtensionDefinition, D as ExtensionDefinitionAttachTo, G as ExtensionDefinitionParameters, H as ExtensionFactoryMiddleware, J as ExtensionInput, K as FeatureFlagConfig, L as FrontendModule, M as FrontendPluginInfo, N as FrontendPluginInfoOptions, O as OverridableExtensionDefinition, P as OverridableFrontendPlugin, Q as PluginOptions, U as PluginWrapperApi, V as PluginWrapperBlueprint, W as PluginWrapperDefinition, X as PortableSchema, Y as appTreeApiRef, Z as createExtension, _ as createExtensionBlueprint, $ as createExtensionBlueprintParams, a0 as createExtensionDataRef, a1 as createExtensionInput, a2 as createExternalRouteRef, a3 as createFrontendModule, a4 as createFrontendPlugin, a5 as createRouteRef, a6 as createSubRouteRef, a7 as pluginWrapperApiRef } from './types/alpha.d-D3gnSOzm.js';
|
|
7
7
|
import { Observable, JsonValue, Expand, ExpandRecursive } from '@backstage/types';
|
|
8
8
|
import { Config } from '@backstage/config';
|
|
9
|
+
export { StandardSchemaV1 } from '@standard-schema/spec';
|
|
9
10
|
import '@backstage/filter-predicates';
|
|
10
11
|
import 'zod/v3';
|
|
11
12
|
|
|
@@ -1106,31 +1107,34 @@ declare const identityApiRef: _backstage_frontend_plugin_api.ApiRef<IdentityApi,
|
|
|
1106
1107
|
*
|
|
1107
1108
|
* @remarks
|
|
1108
1109
|
*
|
|
1109
|
-
* Dialogs
|
|
1110
|
+
* Dialogs are opened using {@link DialogApi.open}.
|
|
1110
1111
|
*
|
|
1111
1112
|
* @public
|
|
1112
1113
|
*/
|
|
1113
1114
|
interface DialogApiDialog<TResult = void> {
|
|
1114
1115
|
/**
|
|
1115
|
-
* Closes the dialog with
|
|
1116
|
+
* Closes the dialog with the provided result.
|
|
1116
1117
|
*
|
|
1117
1118
|
* @remarks
|
|
1118
1119
|
*
|
|
1119
|
-
*
|
|
1120
|
+
* Whether a result is required depends on the `TResult` type parameter
|
|
1121
|
+
* chosen when the dialog was opened. If the type includes `undefined`,
|
|
1122
|
+
* calling `close()` without a result is allowed.
|
|
1120
1123
|
*/
|
|
1121
1124
|
close(...args: undefined extends TResult ? [result?: TResult] : [result: TResult]): void;
|
|
1122
1125
|
/**
|
|
1123
|
-
* Replaces the
|
|
1126
|
+
* Replaces the rendered dialog with the provided element or component.
|
|
1127
|
+
*
|
|
1128
|
+
* @remarks
|
|
1129
|
+
*
|
|
1130
|
+
* Just like the element or component passed to {@link DialogApi.open}, the
|
|
1131
|
+
* caller is responsible for providing the full dialog including all chrome.
|
|
1124
1132
|
*/
|
|
1125
1133
|
update(elementOrComponent: JSX.Element | ((props: {
|
|
1126
1134
|
dialog: DialogApiDialog<TResult>;
|
|
1127
1135
|
}) => JSX.Element)): void;
|
|
1128
1136
|
/**
|
|
1129
1137
|
* Wait until the dialog is closed and return the result.
|
|
1130
|
-
*
|
|
1131
|
-
* @remarks
|
|
1132
|
-
*
|
|
1133
|
-
* If the dialog is a modal dialog a result will always be returned. If it's a regular dialog then the result may be `undefined`.
|
|
1134
1138
|
*/
|
|
1135
1139
|
result(): Promise<TResult>;
|
|
1136
1140
|
}
|
|
@@ -1141,98 +1145,76 @@ interface DialogApiDialog<TResult = void> {
|
|
|
1141
1145
|
*/
|
|
1142
1146
|
interface DialogApi {
|
|
1143
1147
|
/**
|
|
1144
|
-
* Opens a
|
|
1148
|
+
* Opens a dialog and returns a handle to it.
|
|
1145
1149
|
*
|
|
1146
1150
|
* @remarks
|
|
1147
1151
|
*
|
|
1148
|
-
*
|
|
1149
|
-
*
|
|
1150
|
-
*
|
|
1151
|
-
*
|
|
1152
|
+
* The provided element or component is rendered as-is in the app's React tree.
|
|
1153
|
+
* It is the caller's responsibility to provide all dialog chrome, such as an
|
|
1154
|
+
* overlay, backdrop, and dialog surface. This makes the method agnostic to the
|
|
1155
|
+
* design library used for the dialog.
|
|
1152
1156
|
*
|
|
1153
1157
|
* @example
|
|
1154
1158
|
*
|
|
1155
|
-
* ### Example with inline dialog
|
|
1159
|
+
* ### Example with inline dialog element
|
|
1156
1160
|
* ```tsx
|
|
1157
|
-
* const dialog = dialogApi.
|
|
1158
|
-
* <
|
|
1159
|
-
* <
|
|
1160
|
-
* <
|
|
1161
|
-
*
|
|
1162
|
-
* <Button
|
|
1163
|
-
*
|
|
1164
|
-
*
|
|
1161
|
+
* const dialog = dialogApi.open<boolean>(
|
|
1162
|
+
* <Dialog isOpen onOpenChange={isOpen => !isOpen && dialog.close()}>
|
|
1163
|
+
* <DialogHeader>Are you sure?</DialogHeader>
|
|
1164
|
+
* <DialogBody>This action cannot be undone.</DialogBody>
|
|
1165
|
+
* <DialogFooter>
|
|
1166
|
+
* <Button onPress={() => dialog.close(false)}>Cancel</Button>
|
|
1167
|
+
* <Button onPress={() => dialog.close(true)}>Confirm</Button>
|
|
1168
|
+
* </DialogFooter>
|
|
1169
|
+
* </Dialog>
|
|
1165
1170
|
* );
|
|
1166
1171
|
* const result = await dialog.result();
|
|
1167
1172
|
* ```
|
|
1168
1173
|
*
|
|
1169
1174
|
* @example
|
|
1170
1175
|
*
|
|
1171
|
-
* ### Example with
|
|
1176
|
+
* ### Example with a dialog component
|
|
1172
1177
|
* ```tsx
|
|
1173
|
-
* function
|
|
1178
|
+
* function ConfirmDialog({ dialog }: { dialog: DialogApiDialog<boolean> }) {
|
|
1174
1179
|
* return (
|
|
1175
|
-
* <
|
|
1176
|
-
* <
|
|
1177
|
-
* <
|
|
1178
|
-
*
|
|
1179
|
-
* <Button
|
|
1180
|
-
*
|
|
1181
|
-
*
|
|
1182
|
-
*
|
|
1180
|
+
* <Dialog isOpen onOpenChange={isOpen => !isOpen && dialog.close()}>
|
|
1181
|
+
* <DialogHeader>Are you sure?</DialogHeader>
|
|
1182
|
+
* <DialogBody>This action cannot be undone.</DialogBody>
|
|
1183
|
+
* <DialogFooter>
|
|
1184
|
+
* <Button onPress={() => dialog.close(false)}>Cancel</Button>
|
|
1185
|
+
* <Button onPress={() => dialog.close(true)}>Confirm</Button>
|
|
1186
|
+
* </DialogFooter>
|
|
1187
|
+
* </Dialog>
|
|
1188
|
+
* );
|
|
1183
1189
|
* }
|
|
1184
|
-
* const result = await dialogApi.
|
|
1190
|
+
* const result = await dialogApi.open(ConfirmDialog).result();
|
|
1185
1191
|
* ```
|
|
1186
1192
|
*
|
|
1193
|
+
* @param elementOrComponent - The element or component to render. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.
|
|
1194
|
+
*/
|
|
1195
|
+
open<TResult = void>(elementOrComponent: JSX.Element | ((props: {
|
|
1196
|
+
dialog: DialogApiDialog<TResult>;
|
|
1197
|
+
}) => JSX.Element)): DialogApiDialog<TResult>;
|
|
1198
|
+
/**
|
|
1199
|
+
* Opens a dialog with built-in dialog chrome and returns a handle to it.
|
|
1200
|
+
*
|
|
1201
|
+
* @deprecated Use {@link DialogApi.open} instead. The `open` method does not
|
|
1202
|
+
* render any dialog chrome, giving the caller full control over the dialog
|
|
1203
|
+
* presentation. This avoids focus trap conflicts across design libraries.
|
|
1204
|
+
*
|
|
1187
1205
|
* @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.
|
|
1188
|
-
* @public
|
|
1189
1206
|
*/
|
|
1190
1207
|
show<TResult = void>(elementOrComponent: JSX.Element | ((props: {
|
|
1191
1208
|
dialog: DialogApiDialog<TResult | undefined>;
|
|
1192
1209
|
}) => JSX.Element)): DialogApiDialog<TResult | undefined>;
|
|
1193
1210
|
/**
|
|
1194
|
-
* Opens a modal dialog and returns a handle to it.
|
|
1195
|
-
*
|
|
1196
|
-
* @remarks
|
|
1197
|
-
*
|
|
1198
|
-
* This dialog can not be closed in any other way than calling the `close` method on the returned handle and providing a result.
|
|
1211
|
+
* Opens a modal dialog with built-in dialog chrome and returns a handle to it.
|
|
1199
1212
|
*
|
|
1200
|
-
* @
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1203
|
-
* ```tsx
|
|
1204
|
-
* const dialog = dialogApi.showModal<boolean>(
|
|
1205
|
-
* <DialogContent>
|
|
1206
|
-
* <DialogTitle>Are you sure?</DialogTitle>
|
|
1207
|
-
* <DialogActions>
|
|
1208
|
-
* <Button onClick={() => dialog.close(true)}>Yes</Button>
|
|
1209
|
-
* <Button onClick={() => dialog.close(false)}>No</Button>
|
|
1210
|
-
* </DialogActions>
|
|
1211
|
-
* </DialogContent>
|
|
1212
|
-
* );
|
|
1213
|
-
* const result = await dialog.result();
|
|
1214
|
-
* ```
|
|
1215
|
-
*
|
|
1216
|
-
* @example
|
|
1217
|
-
*
|
|
1218
|
-
* ### Example with separate dialog component
|
|
1219
|
-
* ```tsx
|
|
1220
|
-
* function CustomDialog({ dialog }: { dialog: DialogApiDialog<boolean> }) {
|
|
1221
|
-
* return (
|
|
1222
|
-
* <DialogContent>
|
|
1223
|
-
* <DialogTitle>Are you sure?</DialogTitle>
|
|
1224
|
-
* <DialogActions>
|
|
1225
|
-
* <Button onClick={() => dialog.close(true)}>Yes</Button>
|
|
1226
|
-
* <Button onClick={() => dialog.close(false)}>No</Button>
|
|
1227
|
-
* </DialogActions>
|
|
1228
|
-
* </DialogContent>
|
|
1229
|
-
* )
|
|
1230
|
-
* }
|
|
1231
|
-
* const result = await dialogApi.showModal(CustomDialog).result();
|
|
1232
|
-
* ```
|
|
1213
|
+
* @deprecated Use {@link DialogApi.open} instead. The `open` method does not
|
|
1214
|
+
* render any dialog chrome, giving the caller full control over the dialog
|
|
1215
|
+
* presentation. This avoids focus trap conflicts across design libraries.
|
|
1233
1216
|
*
|
|
1234
1217
|
* @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.
|
|
1235
|
-
* @public
|
|
1236
1218
|
*/
|
|
1237
1219
|
showModal<TResult = void>(elementOrComponent: JSX.Element | ((props: {
|
|
1238
1220
|
dialog: DialogApiDialog<TResult>;
|
|
@@ -2286,8 +2268,12 @@ declare const NavItemBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprin
|
|
|
2286
2268
|
routeRef: RouteRef<undefined>;
|
|
2287
2269
|
}, "core.nav-item.target", {}>;
|
|
2288
2270
|
inputs: {};
|
|
2289
|
-
config: {
|
|
2290
|
-
|
|
2271
|
+
config: {
|
|
2272
|
+
title: string | undefined;
|
|
2273
|
+
};
|
|
2274
|
+
configInput: {
|
|
2275
|
+
title?: string | undefined;
|
|
2276
|
+
};
|
|
2291
2277
|
dataRefs: {
|
|
2292
2278
|
target: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
|
|
2293
2279
|
title: string;
|
|
@@ -2340,8 +2326,8 @@ declare const PageBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
|
|
|
2340
2326
|
title: string | undefined;
|
|
2341
2327
|
};
|
|
2342
2328
|
configInput: {
|
|
2343
|
-
title?: string | undefined;
|
|
2344
2329
|
path?: string | undefined;
|
|
2330
|
+
title?: string | undefined;
|
|
2345
2331
|
};
|
|
2346
2332
|
dataRefs: never;
|
|
2347
2333
|
}>;
|
|
@@ -2405,8 +2391,8 @@ declare const SubPageBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprin
|
|
|
2405
2391
|
title: string | undefined;
|
|
2406
2392
|
};
|
|
2407
2393
|
configInput: {
|
|
2408
|
-
title?: string | undefined;
|
|
2409
2394
|
path?: string | undefined;
|
|
2395
|
+
title?: string | undefined;
|
|
2410
2396
|
};
|
|
2411
2397
|
dataRefs: never;
|
|
2412
2398
|
}>;
|