diff --git a/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx b/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx index f11cf7d3be..8dc6e5340a 100644 --- a/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx @@ -16,12 +16,12 @@ import React from 'react'; import { createScaffolderLayout, - ObjectFieldTemplate, + LayoutTemplate, scaffolderPlugin, } from '@backstage/plugin-scaffolder'; import { Grid } from '@material-ui/core'; -const TwoColum: ObjectFieldTemplate = ({ properties, description, title }) => { +const TwoColumn: LayoutTemplate = ({ properties, description, title }) => { const mid = Math.ceil(properties.length / 2); const left = properties.slice(0, mid); const right = properties.slice(mid); @@ -49,6 +49,6 @@ const TwoColum: ObjectFieldTemplate = ({ properties, description, title }) => { export const TwoColumnLayout = scaffolderPlugin.provide( createScaffolderLayout({ name: 'TwoColumn', - component: TwoColum, + component: TwoColumn, }), ); diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 3d91316ceb..65ec8f7ff9 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -16,6 +16,7 @@ import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FetchApi } from '@backstage/core-plugin-api'; import { FieldProps } from '@rjsf/core'; import { FieldValidation } from '@rjsf/core'; +import type { FormProps } from '@rjsf/core'; import { IdentityApi } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; @@ -38,10 +39,7 @@ export function createScaffolderFieldExtension< options: FieldExtensionOptions, ): Extension>; -// Warning: (ae-forgotten-export) The symbol "GetProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "createScaffolderLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function createScaffolderLayout( options: LayoutOptions, ): Extension>; @@ -119,16 +117,27 @@ export type FieldExtensionOptions< validation?: CustomFieldValidator; }; -// Warning: (ae-missing-release-tag) "LayoutOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public +export type GetProps = T extends LayoutOptions + ? T['component'] extends LayoutTemplate + ? LayoutComponent> + : never + : never; + +// @public +export type LayoutComponent<_TInputProps> = () => null; + +// @public export interface LayoutOptions

{ // (undocumented) - component: ObjectFieldTemplate

; + component: LayoutTemplate

; // (undocumented) name: string; } +// @public +export type LayoutTemplate = FormProps['ObjectFieldTemplate']; + // @public export type ListActionsResponse = Array<{ id: string; @@ -168,13 +177,6 @@ export const NextScaffolderPage: ( props: PropsWithChildren, ) => JSX.Element; -// Warning: (ae-missing-release-tag) "ObjectFieldTemplate" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ObjectFieldTemplate

= ( - c: ObjectFieldTemplateProps

, -) => JSX.Element; - // @public export const OwnedEntityPickerFieldExtension: FieldExtensionComponent< string, @@ -375,9 +377,7 @@ export interface ScaffolderGetIntegrationsListResponse { }[]; } -// Warning: (ae-missing-release-tag) "ScaffolderLayouts" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const ScaffolderLayouts: React.ComponentType; // @public (undocumented) diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index b00c43ccbd..d4f5ae48bf 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -49,7 +49,12 @@ export type { FieldExtensionComponent, } from './extensions'; export { createScaffolderLayout, ScaffolderLayouts } from './layouts'; -export type { LayoutOptions, ObjectFieldTemplate } from './layouts'; +export type { + LayoutOptions, + LayoutTemplate, + GetProps, + LayoutComponent, +} from './layouts'; export { EntityPickerFieldExtension, EntityNamePickerFieldExtension, diff --git a/plugins/scaffolder/src/layouts/index.tsx b/plugins/scaffolder/src/layouts/index.tsx index ff6544174d..85bfb43c5e 100644 --- a/plugins/scaffolder/src/layouts/index.tsx +++ b/plugins/scaffolder/src/layouts/index.tsx @@ -16,19 +16,34 @@ import { attachComponentData, Extension } from '@backstage/core-plugin-api'; import { ObjectFieldTemplateProps } from '@rjsf/core'; -import type { LayoutOptions, ObjectFieldTemplate } from './types'; +import type { LayoutOptions, LayoutTemplate } from './types'; export const LAYOUTS_KEY = 'scaffolder.layout.v1'; export const LAYOUTS_WRAPPER_KEY = 'scaffolder.layouts.wrapper.v1'; -type LayoutComponent<_TInputProps> = () => null; +/** + * The type used to wrap up the Layout and embed the input props + * + * @public + */ +export type LayoutComponent<_TInputProps> = () => null; -type GetProps = T extends LayoutOptions - ? T['component'] extends ObjectFieldTemplate +/** + * utility type to extract the component props from the LayoutOptions + * + * @public + */ +export type GetProps = T extends LayoutOptions + ? T['component'] extends LayoutTemplate ? LayoutComponent> : never : never; +/** + * Method for creating custom Layouts that can be used in the scaffolder frontend form + * + * @public + */ export function createScaffolderLayout( options: LayoutOptions, ): Extension> { @@ -43,12 +58,17 @@ export function createScaffolderLayout( }; } +/** + * The wrapping component for defining scaffolder layouts as children + * + * @public + */ export const ScaffolderLayouts: React.ComponentType = (): JSX.Element | null => null; attachComponentData(ScaffolderLayouts, LAYOUTS_WRAPPER_KEY, true); -export type { LayoutOptions, ObjectFieldTemplate } from './types'; +export type { LayoutOptions, LayoutTemplate } from './types'; export { DEFAULT_SCAFFOLDER_LAYOUT } from './default'; diff --git a/plugins/scaffolder/src/layouts/resolveStepLayout.ts b/plugins/scaffolder/src/layouts/resolveStepLayout.ts index 7e4e4f7c11..309b53b38d 100644 --- a/plugins/scaffolder/src/layouts/resolveStepLayout.ts +++ b/plugins/scaffolder/src/layouts/resolveStepLayout.ts @@ -16,12 +16,12 @@ import { UiSchema } from '@rjsf/core'; import { DEFAULT_SCAFFOLDER_LAYOUT } from './default'; -import { LayoutOptions, ObjectFieldTemplate } from './types'; +import { LayoutOptions, LayoutTemplate } from './types'; export function resolveStepLayout( uiSchema: UiSchema = {}, layouts: LayoutOptions[], -): ObjectFieldTemplate { +): LayoutTemplate { const layoutName = uiSchema?.['ui:layout'] ?? DEFAULT_SCAFFOLDER_LAYOUT.name; delete uiSchema?.['ui:layout']; diff --git a/plugins/scaffolder/src/layouts/types.ts b/plugins/scaffolder/src/layouts/types.ts index 2c52d5a1d7..94186d82bf 100644 --- a/plugins/scaffolder/src/layouts/types.ts +++ b/plugins/scaffolder/src/layouts/types.ts @@ -13,13 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { ObjectFieldTemplateProps } from '@rjsf/core'; +import type { FormProps } from '@rjsf/core'; -export type ObjectFieldTemplate

= ( - c: ObjectFieldTemplateProps

, -) => JSX.Element; +/** + * The field template from \@rjsf/core which is a react component that gets passed \@rjsf/core field related props. + * + * @public + */ +export type LayoutTemplate = FormProps['ObjectFieldTemplate']; +/** + * The type of layouts that is passed to the TemplateForms + * + * @public + */ export interface LayoutOptions

{ name: string; - component: ObjectFieldTemplate

; + component: LayoutTemplate

; }