Merge pull request #30700 from backstage/blam/lowercase

`frontend-plugin-api`: Updating `Component` params to `component`
This commit is contained in:
Ben Lambert
2025-08-04 12:38:04 +02:00
committed by GitHub
11 changed files with 81 additions and 43 deletions
+39
View File
@@ -0,0 +1,39 @@
---
'@backstage/frontend-plugin-api': minor
---
**BREAKING**: In an attempt to align some of the API's around providing components to `Blueprints`, we've renamed the parameters for both the `RouterBlueprint` and `AppRootWrapperBlueprint` from `Component` to `component`.
```tsx
// old
RouterBlueprint.make({
params: {
Component: ({ children }) => <div>{children}</div>,
},
});
// new
RouterBlueprint.make({
params: {
component: ({ children }) => <div>{children}</div>,
},
});
```
```tsx
// old
AppRootWrapperBlueprint.make({
params: {
Component: ({ children }) => <div>{children}</div>,
},
});
// new
AppRootWrapperBlueprint.make({
params: {
component: ({ children }) => <div>{children}</div>,
},
});
```
As part of this change, the type for `component` has also changed from `ComponentType<PropsWithChildren<{}>>` to `(props: { children: ReactNode }) => JSX.Element | null` which is not breaking, just a little more reflective of the actual expected component.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/frontend-test-utils': patch
'@backstage/core-compat-api': patch
'@backstage/plugin-app': patch
---
Updated the usage of the `RouterBlueprint` and `AppRootWrapperBlueprint` to use the lowercase `component` parameter
@@ -139,7 +139,7 @@ export function convertLegacyAppOptions(
if (Router) {
extensions.push(
RouterBlueprint.make({
params: { Component: componentCompatWrapper(Router) },
params: { component: componentCompatWrapper(Router) },
}),
);
}
+8 -15
View File
@@ -71,7 +71,6 @@ import { OpenIdConnectApi } from '@backstage/core-plugin-api';
import { PendingOAuthRequest } from '@backstage/core-plugin-api';
import { ProfileInfo } from '@backstage/core-plugin-api';
import { ProfileInfoApi } from '@backstage/core-plugin-api';
import { PropsWithChildren } from 'react';
import { ReactNode } from 'react';
import { RouteRef as RouteRef_2 } from '@backstage/frontend-plugin-api';
import { SessionApi } from '@backstage/core-plugin-api';
@@ -268,12 +267,11 @@ export const AppRootWrapperBlueprint: ExtensionBlueprint<{
kind: 'app-root-wrapper';
name: undefined;
params: {
Component: ComponentType<PropsWithChildren<{}>>;
Component?: [error: 'Use the `component` parameter instead'];
component: (props: { children: ReactNode }) => JSX.Element | null;
};
output: ConfigurableExtensionDataRef<
ComponentType<{
children?: ReactNode | undefined;
}>,
(props: { children: ReactNode }) => JSX.Element | null,
'app.root.wrapper',
{}
>;
@@ -282,9 +280,7 @@ export const AppRootWrapperBlueprint: ExtensionBlueprint<{
configInput: {};
dataRefs: {
component: ConfigurableExtensionDataRef<
ComponentType<{
children?: ReactNode | undefined;
}>,
(props: { children: ReactNode }) => JSX.Element | null,
'app.root.wrapper',
{}
>;
@@ -1726,12 +1722,11 @@ export const RouterBlueprint: ExtensionBlueprint<{
kind: 'app-router-component';
name: undefined;
params: {
Component: ComponentType<PropsWithChildren<{}>>;
Component?: [error: 'Use the `component` parameter instead'];
component: (props: { children: ReactNode }) => JSX.Element | null;
};
output: ConfigurableExtensionDataRef<
ComponentType<{
children?: ReactNode | undefined;
}>,
(props: { children: ReactNode }) => JSX.Element | null,
'app.router.wrapper',
{}
>;
@@ -1740,9 +1735,7 @@ export const RouterBlueprint: ExtensionBlueprint<{
configInput: {};
dataRefs: {
component: ConfigurableExtensionDataRef<
ComponentType<{
children?: ReactNode | undefined;
}>,
(props: { children: ReactNode }) => JSX.Element | null,
'app.router.wrapper',
{}
>;
@@ -27,7 +27,7 @@ describe('AppRootWrapperBlueprint', () => {
it('should return an extension with sensible defaults', () => {
const extension = AppRootWrapperBlueprint.make({
params: {
Component: () => <div>Hello</div>,
component: () => <div>Hello</div>,
},
});
@@ -59,7 +59,7 @@ describe('AppRootWrapperBlueprint', () => {
const extension = AppRootWrapperBlueprint.make({
name: 'test',
params: {
Component: () => <div>Hello</div>,
component: () => <div>Hello</div>,
},
});
@@ -80,7 +80,7 @@ describe('AppRootWrapperBlueprint', () => {
},
*factory(originalFactory, { inputs, config }) {
yield* originalFactory({
Component: ({ children }) => (
component: ({ children }) => (
<div data-testid={`${config.name}-${inputs.children.length}`}>
{children}
{inputs.children.flatMap(c =>
@@ -14,11 +14,11 @@
* limitations under the License.
*/
import { ComponentType, PropsWithChildren } from 'react';
import { ReactNode } from 'react';
import { createExtensionBlueprint, createExtensionDataRef } from '../wiring';
const componentDataRef = createExtensionDataRef<
ComponentType<PropsWithChildren<{}>>
(props: { children: ReactNode }) => JSX.Element | null
>().with({ id: 'app.root.wrapper' });
/**
@@ -35,12 +35,11 @@ export const AppRootWrapperBlueprint = createExtensionBlueprint({
dataRefs: {
component: componentDataRef,
},
*factory(params: { Component: ComponentType<PropsWithChildren<{}>> }) {
// todo(blam): not sure that this wrapping is even necessary anymore.
const Component = (props: PropsWithChildren<{}>) => {
return <params.Component>{props.children}</params.Component>;
};
yield componentDataRef(Component);
*factory(params: {
/** @deprecated use the `component` parameter instead */
Component?: [error: 'Use the `component` parameter instead'];
component: (props: { children: ReactNode }) => JSX.Element | null;
}) {
yield componentDataRef(params.component);
},
});
@@ -27,7 +27,7 @@ describe('RouterBlueprint', () => {
it('should return an extension when calling make with sensible defaults', () => {
const extension = RouterBlueprint.make({
params: {
Component: props => <div>{props.children}</div>,
component: props => <div>{props.children}</div>,
},
});
@@ -58,7 +58,7 @@ describe('RouterBlueprint', () => {
it('should work with simple options', async () => {
const extension = RouterBlueprint.make({
params: {
Component: ({ children }) => (
component: ({ children }) => (
<MemoryRouter>
<div data-testid="test-router">{children}</div>
</MemoryRouter>
@@ -94,7 +94,7 @@ describe('RouterBlueprint', () => {
},
*factory(originalFactory, { inputs, config }) {
yield* originalFactory({
Component: ({ children }) => (
component: ({ children }) => (
<MemoryRouter>
<div
data-testid={`test-router-${config.name}-${inputs.children.length}`}
@@ -14,11 +14,11 @@
* limitations under the License.
*/
import { ComponentType, PropsWithChildren } from 'react';
import { ReactNode } from 'react';
import { createExtensionBlueprint, createExtensionDataRef } from '../wiring';
const componentDataRef = createExtensionDataRef<
ComponentType<PropsWithChildren<{}>>
(props: { children: ReactNode }) => JSX.Element | null
>().with({ id: 'app.router.wrapper' });
/** @public */
@@ -29,7 +29,11 @@ export const RouterBlueprint = createExtensionBlueprint({
dataRefs: {
component: componentDataRef,
},
*factory({ Component }: { Component: ComponentType<PropsWithChildren<{}>> }) {
yield componentDataRef(Component);
*factory(params: {
/** @deprecated use the `component` parameter instead */
Component?: [error: 'Use the `component` parameter instead'];
component: (props: { children: ReactNode }) => JSX.Element | null;
}) {
yield componentDataRef(params.component);
},
});
@@ -160,7 +160,7 @@ export function renderInTestApp(
}),
RouterBlueprint.make({
params: {
Component: ({ children }) => (
component: ({ children }) => (
<MemoryRouter initialEntries={options?.initialRouteEntries}>
{children}
</MemoryRouter>
+2 -6
View File
@@ -130,9 +130,7 @@ const appPlugin: FrontendPlugin<
inputs: {
router: ExtensionInput<
ConfigurableExtensionDataRef<
ComponentType<{
children?: ReactNode | undefined;
}>,
(props: { children: ReactNode }) => JSX.Element | null,
'app.router.wrapper',
{}
>,
@@ -168,9 +166,7 @@ const appPlugin: FrontendPlugin<
>;
wrappers: ExtensionInput<
ConfigurableExtensionDataRef<
ComponentType<{
children?: ReactNode | undefined;
}>,
(props: { children: ReactNode }) => JSX.Element | null,
'app.root.wrapper',
{}
>,
+1 -1
View File
@@ -182,7 +182,7 @@ type RouteResolverProxy = {
export interface AppRouterProps {
children?: ReactNode;
SignInPageComponent?: ComponentType<SignInPageProps>;
RouterComponent?: ComponentType<PropsWithChildren<{}>>;
RouterComponent?: (props: { children: ReactNode }) => JSX.Element | null;
extraElements?: Array<JSX.Element>;
}