feat: started to promote the bare minmum
Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
@@ -16,3 +16,5 @@
|
||||
|
||||
export * from './next';
|
||||
export type { FormProps } from './next';
|
||||
|
||||
export * from './legacy';
|
||||
|
||||
@@ -14,23 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
CustomFieldExtensionSchema,
|
||||
CustomFieldValidator,
|
||||
FieldExtensionOptions,
|
||||
FieldExtensionComponentProps,
|
||||
FieldExtensionUiSchema,
|
||||
} from './types';
|
||||
import { Extension, attachComponentData } from '@backstage/core-plugin-api';
|
||||
import { UIOptionsType } from '@rjsf/utils';
|
||||
import { FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY } from './keys';
|
||||
|
||||
/**
|
||||
* The type used to wrap up the Layout and embed the input props
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null;
|
||||
|
||||
/**
|
||||
* Method for creating field extensions that can be used in the scaffolder
|
||||
* frontend form.
|
||||
@@ -38,7 +31,7 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null;
|
||||
*/
|
||||
export function createScaffolderFieldExtension<
|
||||
TReturnValue = unknown,
|
||||
TInputProps = unknown,
|
||||
TInputProps extends UIOptionsType = {},
|
||||
>(
|
||||
options: FieldExtensionOptions<TReturnValue, TInputProps>,
|
||||
): Extension<FieldExtensionComponent<TReturnValue, TInputProps>> {
|
||||
@@ -72,9 +65,16 @@ attachComponentData(
|
||||
true,
|
||||
);
|
||||
|
||||
/**
|
||||
* The type used to wrap up the Layout and embed the input props
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null;
|
||||
|
||||
export type {
|
||||
CustomFieldExtensionSchema,
|
||||
CustomFieldValidator,
|
||||
FieldExtensionOptions,
|
||||
FieldExtensionComponentProps,
|
||||
FieldExtensionUiSchema,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentType, ElementType, FormEvent, ReactNode, Ref } from 'react';
|
||||
import {
|
||||
ErrorSchema,
|
||||
FormContextType,
|
||||
GenericObjectType,
|
||||
IdSchema,
|
||||
Registry,
|
||||
RJSFSchema,
|
||||
StrictRJSFSchema,
|
||||
UiSchema,
|
||||
ValidatorType,
|
||||
TemplatesType,
|
||||
RegistryWidgetsType,
|
||||
RJSFValidationError,
|
||||
CustomValidator,
|
||||
Experimental_DefaultFormStateBehavior,
|
||||
ErrorTransformer,
|
||||
} from '@rjsf/utils';
|
||||
import { HTMLAttributes } from 'react';
|
||||
import Form, { IChangeEvent } from '@rjsf/core-v5';
|
||||
|
||||
/**
|
||||
* The props for the `Field` components
|
||||
* @public
|
||||
*/
|
||||
export interface ScaffolderRJSFFieldProps<
|
||||
T = any,
|
||||
S extends StrictRJSFSchema = RJSFSchema,
|
||||
F extends FormContextType = any,
|
||||
> extends GenericObjectType,
|
||||
Pick<
|
||||
HTMLAttributes<HTMLElement>,
|
||||
Exclude<
|
||||
keyof HTMLAttributes<HTMLElement>,
|
||||
'onBlur' | 'onFocus' | 'onChange'
|
||||
>
|
||||
> {
|
||||
/** The JSON subschema object for this field */
|
||||
schema: S;
|
||||
/** The uiSchema for this field */
|
||||
uiSchema: UiSchema<T, S, F>;
|
||||
/** The tree of unique ids for every child field */
|
||||
idSchema: IdSchema<T>;
|
||||
/** The data for this field */
|
||||
formData: T;
|
||||
/** The tree of errors for this field and its children */
|
||||
errorSchema?: ErrorSchema<T>;
|
||||
/** The field change event handler; called with the updated form data and an optional `ErrorSchema` */
|
||||
onChange: (
|
||||
newFormData: T | undefined,
|
||||
es?: ErrorSchema<T>,
|
||||
id?: string,
|
||||
) => any;
|
||||
/** The input blur event handler; call it with the field id and value */
|
||||
onBlur: (id: string, value: any) => void;
|
||||
/** The input focus event handler; call it with the field id and value */
|
||||
onFocus: (id: string, value: any) => void;
|
||||
/** The `formContext` object that you passed to `Form` */
|
||||
formContext?: F;
|
||||
/** A boolean value stating if the field should autofocus */
|
||||
autofocus?: boolean;
|
||||
/** A boolean value stating if the field is disabled */
|
||||
disabled: boolean;
|
||||
/** A boolean value stating if the field is hiding its errors */
|
||||
hideError?: boolean;
|
||||
/** A boolean value stating if the field is read-only */
|
||||
readonly: boolean;
|
||||
/** The required status of this field */
|
||||
required?: boolean;
|
||||
/** The unique name of the field, usually derived from the name of the property in the JSONSchema */
|
||||
name: string;
|
||||
/** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids;
|
||||
* Default is `root`
|
||||
*/
|
||||
idPrefix?: string;
|
||||
/** To avoid using a path separator that is present in field names, it is possible to change the separator used for
|
||||
* ids (Default is `_`)
|
||||
*/
|
||||
idSeparator?: string;
|
||||
/** An array of strings listing all generated error messages from encountered errors for this field */
|
||||
rawErrors: string[];
|
||||
/** The `registry` object */
|
||||
registry: Registry<T, S, F>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The properties that are passed to the `Form`
|
||||
* @public
|
||||
*/
|
||||
export interface ScaffolderRJSFFormProps<
|
||||
T = any,
|
||||
S extends StrictRJSFSchema = RJSFSchema,
|
||||
F extends FormContextType = any,
|
||||
> {
|
||||
/** The JSON schema object for the form */
|
||||
schema: S;
|
||||
/** An implementation of the `ValidatorType` interface that is needed for form validation to work */
|
||||
validator: ValidatorType<T, S, F>;
|
||||
/** The optional children for the form, if provided, it will replace the default `SubmitButton` */
|
||||
children?: ReactNode;
|
||||
/** The uiSchema for the form */
|
||||
uiSchema?: UiSchema<T, S, F>;
|
||||
/** The data for the form, used to prefill a form with existing data */
|
||||
formData?: T;
|
||||
/** You can provide a `formContext` object to the form, which is passed down to all fields and widgets. Useful for
|
||||
* implementing context aware fields and widgets.
|
||||
*
|
||||
* NOTE: Setting `{readonlyAsDisabled: false}` on the formContext will make the antd theme treat readOnly fields as
|
||||
* disabled.
|
||||
*/
|
||||
formContext?: F;
|
||||
/** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids;
|
||||
* Default is `root`
|
||||
*/
|
||||
idPrefix?: string;
|
||||
/** To avoid using a path separator that is present in field names, it is possible to change the separator used for
|
||||
* ids (Default is `_`)
|
||||
*/
|
||||
idSeparator?: string;
|
||||
/** It's possible to disable the whole form by setting the `disabled` prop. The `disabled` prop is then forwarded down
|
||||
* to each field of the form. If you just want to disable some fields, see the `ui:disabled` parameter in `uiSchema`
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/** It's possible to make the whole form read-only by setting the `readonly` prop. The `readonly` prop is then
|
||||
* forwarded down to each field of the form. If you just want to make some fields read-only, see the `ui:readonly`
|
||||
* parameter in `uiSchema`
|
||||
*/
|
||||
readonly?: boolean;
|
||||
/** The dictionary of registered fields in the form */
|
||||
fields?: ScaffolderRJSFRegistryFieldsType<T, S, F>;
|
||||
/** The dictionary of registered templates in the form; Partial allows a subset to be provided beyond the defaults */
|
||||
templates?: Partial<Omit<TemplatesType<T, S, F>, 'ButtonTemplates'>> & {
|
||||
ButtonTemplates?: Partial<TemplatesType<T, S, F>['ButtonTemplates']>;
|
||||
};
|
||||
/** The dictionary of registered widgets in the form */
|
||||
widgets?: RegistryWidgetsType<T, S, F>;
|
||||
/** If you plan on being notified every time the form data are updated, you can pass an `onChange` handler, which will
|
||||
* receive the same args as `onSubmit` any time a value is updated in the form. Can also return the `id` of the field
|
||||
* that caused the change
|
||||
*/
|
||||
onChange?: (data: IChangeEvent<T, S, F>, id?: string) => void;
|
||||
/** To react when submitted form data are invalid, pass an `onError` handler. It will be passed the list of
|
||||
* encountered errors
|
||||
*/
|
||||
onError?: (errors: RJSFValidationError[]) => void;
|
||||
/** You can pass a function as the `onSubmit` prop of your `Form` component to listen to when the form is submitted
|
||||
* and its data are valid. It will be passed a result object having a `formData` attribute, which is the valid form
|
||||
* data you're usually after. The original event will also be passed as a second parameter
|
||||
*/
|
||||
onSubmit?: (data: IChangeEvent<T, S, F>, event: FormEvent<any>) => void;
|
||||
/** Sometimes you may want to trigger events or modify external state when a field has been touched, so you can pass
|
||||
* an `onBlur` handler, which will receive the id of the input that was blurred and the field value
|
||||
*/
|
||||
onBlur?: (id: string, data: any) => void;
|
||||
/** Sometimes you may want to trigger events or modify external state when a field has been focused, so you can pass
|
||||
* an `onFocus` handler, which will receive the id of the input that is focused and the field value
|
||||
*/
|
||||
onFocus?: (id: string, data: any) => void;
|
||||
/** The value of this prop will be passed to the `accept-charset` HTML attribute on the form */
|
||||
acceptcharset?: string;
|
||||
/** The value of this prop will be passed to the `action` HTML attribute on the form
|
||||
*
|
||||
* NOTE: this just renders the `action` attribute in the HTML markup. There is no real network request being sent to
|
||||
* this `action` on submit. Instead, react-jsonschema-form catches the submit event with `event.preventDefault()`
|
||||
* and then calls the `onSubmit` function, where you could send a request programmatically with `fetch` or similar.
|
||||
*/
|
||||
action?: string;
|
||||
/** The value of this prop will be passed to the `autocomplete` HTML attribute on the form */
|
||||
autoComplete?: string;
|
||||
/** The value of this prop will be passed to the `class` HTML attribute on the form */
|
||||
className?: string;
|
||||
/** The value of this prop will be passed to the `enctype` HTML attribute on the form */
|
||||
enctype?: string;
|
||||
/** The value of this prop will be passed to the `id` HTML attribute on the form */
|
||||
id?: string;
|
||||
/** The value of this prop will be passed to the `name` HTML attribute on the form */
|
||||
name?: string;
|
||||
/** The value of this prop will be passed to the `method` HTML attribute on the form */
|
||||
method?: string;
|
||||
/** It's possible to change the default `form` tag name to a different HTML tag, which can be helpful if you are
|
||||
* nesting forms. However, native browser form behaviour, such as submitting when the `Enter` key is pressed, may no
|
||||
* longer work
|
||||
*/
|
||||
tagName?: ElementType;
|
||||
/** The value of this prop will be passed to the `target` HTML attribute on the form */
|
||||
target?: string;
|
||||
/** Formerly the `validate` prop; Takes a function that specifies custom validation rules for the form */
|
||||
customValidate?: CustomValidator<T, S, F>;
|
||||
/** This prop allows passing in custom errors that are augmented with the existing JSON Schema errors on the form; it
|
||||
* can be used to implement asynchronous validation
|
||||
*/
|
||||
extraErrors?: ErrorSchema<T>;
|
||||
/** If set to true, turns off HTML5 validation on the form; Set to `false` by default */
|
||||
noHtml5Validate?: boolean;
|
||||
/** If set to true, turns off all validation. Set to `false` by default
|
||||
*
|
||||
* @deprecated - In a future release, this switch may be replaced by making `validator` prop optional
|
||||
*/
|
||||
noValidate?: boolean;
|
||||
/** If set to true, the form will perform validation and show any validation errors whenever the form data is changed,
|
||||
* rather than just on submit
|
||||
*/
|
||||
liveValidate?: boolean;
|
||||
/** If `omitExtraData` and `liveOmit` are both set to true, then extra form data values that are not in any form field
|
||||
* will be removed whenever `onChange` is called. Set to `false` by default
|
||||
*/
|
||||
liveOmit?: boolean;
|
||||
/** If set to true, then extra form data values that are not in any form field will be removed whenever `onSubmit` is
|
||||
* called. Set to `false` by default.
|
||||
*/
|
||||
omitExtraData?: boolean;
|
||||
/** When this prop is set to `top` or 'bottom', a list of errors (or the custom error list defined in the `ErrorList`) will also
|
||||
* show. When set to false, only inline input validation errors will be shown. Set to `top` by default
|
||||
*/
|
||||
showErrorList?: false | 'top' | 'bottom';
|
||||
/** A function can be passed to this prop in order to make modifications to the default errors resulting from JSON
|
||||
* Schema validation
|
||||
*/
|
||||
transformErrors?: ErrorTransformer<T, S, F>;
|
||||
/** If set to true, then the first field with an error will receive the focus when the form is submitted with errors
|
||||
*/
|
||||
focusOnFirstError?: boolean | ((error: RJSFValidationError) => void);
|
||||
/** Optional string translation function, if provided, allows users to change the translation of the RJSF internal
|
||||
* strings. Some strings contain replaceable parameter values as indicated by `%1`, `%2`, etc. The number after the
|
||||
* `%` indicates the order of the parameter. The ordering of parameters is important because some languages may choose
|
||||
* to put the second parameter before the first in its translation.
|
||||
*/
|
||||
translateString?: Registry['translateString'];
|
||||
/** Optional configuration object with flags, if provided, allows users to override default form state behavior
|
||||
* Currently only affecting minItems on array fields and handling of setting defaults based on the value of
|
||||
* `emptyObjectFields`
|
||||
*/
|
||||
experimental_defaultFormStateBehavior?: Experimental_DefaultFormStateBehavior;
|
||||
/**
|
||||
* _internalFormWrapper is currently used by the semantic-ui theme to provide a custom wrapper around `<Form />`
|
||||
* that supports the proper rendering of those themes. To use this prop, one must pass a component that takes two
|
||||
* props: `children` and `as`. That component, at minimum, should render the `children` inside of a <form /> tag
|
||||
* unless `as` is provided, in which case, use the `as` prop in place of `<form />`.
|
||||
* i.e.:
|
||||
* ```
|
||||
* export default function InternalForm({ children, as }) {
|
||||
* const FormTag = as || 'form';
|
||||
* return <FormTag>{children}</FormTag>;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Use at your own risk as this prop is private and may change at any time without notice.
|
||||
*/
|
||||
_internalFormWrapper?: ElementType;
|
||||
/** Support receiving a React ref to the Form
|
||||
*/
|
||||
ref?: Ref<Form<T, S, F>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The set of `Fields` stored in the `Registry`
|
||||
* @public
|
||||
*/
|
||||
export type ScaffolderRJSFRegistryFieldsType<
|
||||
T = any,
|
||||
S extends StrictRJSFSchema = RJSFSchema,
|
||||
F extends FormContextType = any,
|
||||
> = {
|
||||
/** A `Field` indexed by `name` */
|
||||
[name: string]: ScaffolderRJSFField<T, S, F>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The `Field` type for Field Extensions
|
||||
* @public
|
||||
*/
|
||||
export type ScaffolderRJSFField<
|
||||
T = any,
|
||||
S extends StrictRJSFSchema = RJSFSchema,
|
||||
F extends FormContextType = any,
|
||||
> = ComponentType<ScaffolderRJSFFieldProps<T, S, F>>;
|
||||
@@ -14,19 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ApiHolder } from '@backstage/core-plugin-api';
|
||||
import { FieldValidation, FieldProps } from '@rjsf/core';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { JSONSchema7 } from 'json-schema';
|
||||
import { UiSchema, UIOptionsType, FieldValidation } from '@rjsf/utils';
|
||||
import { ScaffolderRJSFFieldProps } from './rjsf';
|
||||
|
||||
/**
|
||||
* Field validation type for Custom Field Extensions.
|
||||
* Type for Field Extension Props for RJSF v5
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type CustomFieldValidator<TFieldReturnValue> = (
|
||||
data: TFieldReturnValue,
|
||||
field: FieldValidation,
|
||||
context: { apiHolder: ApiHolder },
|
||||
) => void | Promise<void>;
|
||||
export interface FieldExtensionComponentProps<
|
||||
TFieldReturnValue,
|
||||
TUiOptions = {},
|
||||
> extends PropsWithChildren<ScaffolderRJSFFieldProps<TFieldReturnValue>> {
|
||||
uiSchema: FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type for the Custom Field Extension schema.
|
||||
@@ -38,6 +42,32 @@ export type CustomFieldExtensionSchema = {
|
||||
uiOptions?: JSONSchema7;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type for Field Extension UiSchema
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>
|
||||
extends UiSchema<TFieldReturnValue> {
|
||||
'ui:options'?: TUiOptions & UIOptionsType<TFieldReturnValue>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field validation type for Custom Field Extensions.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type CustomFieldValidator<TFieldReturnValue, TUiOptions = unknown> = (
|
||||
data: TFieldReturnValue,
|
||||
field: FieldValidation,
|
||||
context: {
|
||||
apiHolder: ApiHolder;
|
||||
formData: JsonObject;
|
||||
schema: JsonObject;
|
||||
uiSchema?: FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>;
|
||||
},
|
||||
) => void | Promise<void>;
|
||||
|
||||
/**
|
||||
* Type for the Custom Field Extension with the
|
||||
* name and components and validation function.
|
||||
@@ -46,27 +76,12 @@ export type CustomFieldExtensionSchema = {
|
||||
*/
|
||||
export type FieldExtensionOptions<
|
||||
TFieldReturnValue = unknown,
|
||||
TInputProps = unknown,
|
||||
TUiOptions = unknown,
|
||||
> = {
|
||||
name: string;
|
||||
component: (
|
||||
props: FieldExtensionComponentProps<TFieldReturnValue, TInputProps>,
|
||||
props: FieldExtensionComponentProps<TFieldReturnValue, TUiOptions>,
|
||||
) => JSX.Element | null;
|
||||
validation?: CustomFieldValidator<TFieldReturnValue>;
|
||||
validation?: CustomFieldValidator<TFieldReturnValue, TUiOptions>;
|
||||
schema?: CustomFieldExtensionSchema;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type for field extensions and being able to type
|
||||
* incoming props easier.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface FieldExtensionComponentProps<
|
||||
TFieldReturnValue,
|
||||
TUiOptions = unknown,
|
||||
> extends FieldProps<TFieldReturnValue> {
|
||||
uiSchema: FieldProps['uiSchema'] & {
|
||||
'ui:options'?: TUiOptions;
|
||||
};
|
||||
}
|
||||
|
||||
+10
-13
@@ -15,26 +15,24 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
NextCustomFieldValidator,
|
||||
NextFieldExtensionOptions,
|
||||
NextFieldExtensionComponentProps,
|
||||
NextFieldExtensionUiSchema,
|
||||
CustomFieldValidator,
|
||||
FieldExtensionOptions,
|
||||
FieldExtensionComponentProps,
|
||||
} from './types';
|
||||
import { Extension, attachComponentData } from '@backstage/core-plugin-api';
|
||||
import { UIOptionsType } from '@rjsf/utils';
|
||||
import { FIELD_EXTENSION_KEY } from '../../extensions/keys';
|
||||
import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react';
|
||||
import { FieldExtensionComponent } from '../../extensions';
|
||||
|
||||
/**
|
||||
* Method for creating field extensions that can be used in the scaffolder
|
||||
* frontend form.
|
||||
* @alpha
|
||||
*/
|
||||
export function createNextScaffolderFieldExtension<
|
||||
export function createLegacyScaffolderFieldExtension<
|
||||
TReturnValue = unknown,
|
||||
TInputProps extends UIOptionsType = {},
|
||||
TInputProps = unknown,
|
||||
>(
|
||||
options: NextFieldExtensionOptions<TReturnValue, TInputProps>,
|
||||
options: FieldExtensionOptions<TReturnValue, TInputProps>,
|
||||
): Extension<FieldExtensionComponent<TReturnValue, TInputProps>> {
|
||||
return {
|
||||
expose() {
|
||||
@@ -52,8 +50,7 @@ export function createNextScaffolderFieldExtension<
|
||||
}
|
||||
|
||||
export type {
|
||||
NextCustomFieldValidator,
|
||||
NextFieldExtensionOptions,
|
||||
NextFieldExtensionComponentProps,
|
||||
NextFieldExtensionUiSchema,
|
||||
CustomFieldValidator,
|
||||
FieldExtensionOptions,
|
||||
FieldExtensionComponentProps,
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ApiHolder } from '@backstage/core-plugin-api';
|
||||
import { FieldValidation, FieldProps } from '@rjsf/core';
|
||||
import { CustomFieldExtensionSchema } from '../../extensions/types';
|
||||
|
||||
/**
|
||||
* Field validation type for Custom Field Extensions.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type CustomFieldValidator<TFieldReturnValue> = (
|
||||
data: TFieldReturnValue,
|
||||
field: FieldValidation,
|
||||
context: { apiHolder: ApiHolder },
|
||||
) => void | Promise<void>;
|
||||
|
||||
/**
|
||||
* Type for the Custom Field Extension with the
|
||||
* name and components and validation function.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type FieldExtensionOptions<
|
||||
TFieldReturnValue = unknown,
|
||||
TInputProps = unknown,
|
||||
> = {
|
||||
name: string;
|
||||
component: (
|
||||
props: FieldExtensionComponentProps<TFieldReturnValue, TInputProps>,
|
||||
) => JSX.Element | null;
|
||||
validation?: CustomFieldValidator<TFieldReturnValue>;
|
||||
schema?: CustomFieldExtensionSchema;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type for field extensions and being able to type
|
||||
* incoming props easier.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export interface FieldExtensionComponentProps<
|
||||
TFieldReturnValue,
|
||||
TUiOptions = unknown,
|
||||
> extends FieldProps<TFieldReturnValue> {
|
||||
uiSchema: FieldProps['uiSchema'] & {
|
||||
'ui:options'?: TUiOptions;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export * from './extensions';
|
||||
@@ -19,6 +19,7 @@ import React from 'react';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { FieldTemplate } from './FieldTemplate';
|
||||
import { DescriptionFieldTemplate } from './DescriptionFieldTemplate';
|
||||
import { FieldProps } from '@rjsf/utils';
|
||||
|
||||
// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly
|
||||
// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because
|
||||
@@ -30,10 +31,31 @@ const WrappedForm = withTheme(require('@rjsf/material-ui-v5').Theme);
|
||||
* @alpha
|
||||
*/
|
||||
export const Form = (props: PropsWithChildren<FormProps>) => {
|
||||
// This is where we unbreak the changes from RJSF, and make it work with our custom fields so we don't pass on this
|
||||
// breaking change to our users. We will look more into a better API for this in scaffolderv2.
|
||||
const wrappedFields = Object.fromEntries(
|
||||
Object.entries(props.fields ?? {}).map(([key, Component]) => [
|
||||
key,
|
||||
(wrapperProps: FieldProps) => {
|
||||
return (
|
||||
<Component
|
||||
{...wrapperProps}
|
||||
uiSchema={wrapperProps.uiSchema ?? {}}
|
||||
formData={wrapperProps.formData ?? {}}
|
||||
rawErrors={wrapperProps.rawErrors ?? []}
|
||||
/>
|
||||
);
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const templates = {
|
||||
FieldTemplate,
|
||||
DescriptionFieldTemplate,
|
||||
...props.templates,
|
||||
};
|
||||
return <WrappedForm {...props} templates={templates} />;
|
||||
|
||||
return (
|
||||
<WrappedForm {...props} templates={templates} fields={wrappedFields} />
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { act, fireEvent } from '@testing-library/react';
|
||||
import type { RJSFValidationError } from '@rjsf/utils';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { NextFieldExtensionComponentProps } from '../../extensions';
|
||||
import { NextFieldExtensionComponentProps } from '../../../extensions';
|
||||
import { LayoutTemplate } from '../../../layouts';
|
||||
|
||||
describe('Stepper', () => {
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
import { type IChangeEvent } from '@rjsf/core-v5';
|
||||
import { ErrorSchema } from '@rjsf/utils';
|
||||
import React, { useCallback, useMemo, useState, type ReactNode } from 'react';
|
||||
import { NextFieldExtensionOptions } from '../../extensions';
|
||||
import { NextFieldExtensionOptions } from '../../../extensions';
|
||||
import {
|
||||
createAsyncValidators,
|
||||
type FormValidation,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { NextCustomFieldValidator } from '../../extensions';
|
||||
import { NextCustomFieldValidator } from '../../../extensions';
|
||||
import { createAsyncValidators } from './createAsyncValidators';
|
||||
|
||||
describe('createAsyncValidators', () => {
|
||||
|
||||
@@ -19,7 +19,7 @@ import type { JsonObject, JsonValue } from '@backstage/types';
|
||||
import { ApiHolder } from '@backstage/core-plugin-api';
|
||||
import { Draft07 as JSONSchema } from 'json-schema-library';
|
||||
import { createFieldValidation, extractSchemaFromStep } from '../../lib';
|
||||
import { NextCustomFieldValidator } from '../../extensions';
|
||||
import { NextCustomFieldValidator } from '../../../extensions';
|
||||
import { isObject } from './utils';
|
||||
import { NextFieldExtensionUiSchema } from '../../extensions/types';
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ApiHolder } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
UIOptionsType,
|
||||
FieldProps as FieldPropsV5,
|
||||
UiSchema as UiSchemaV5,
|
||||
FieldValidation as FieldValidationV5,
|
||||
} from '@rjsf/utils';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react';
|
||||
|
||||
/**
|
||||
* Type for Field Extension Props for RJSF v5
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export interface NextFieldExtensionComponentProps<
|
||||
TFieldReturnValue,
|
||||
TUiOptions = {},
|
||||
> extends PropsWithChildren<FieldPropsV5<TFieldReturnValue>> {
|
||||
uiSchema?: NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type for Field Extension UiSchema
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export interface NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions>
|
||||
extends UiSchemaV5<TFieldReturnValue> {
|
||||
'ui:options'?: TUiOptions & UIOptionsType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field validation type for Custom Field Extensions.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type NextCustomFieldValidator<
|
||||
TFieldReturnValue,
|
||||
TUiOptions = unknown,
|
||||
> = (
|
||||
data: TFieldReturnValue,
|
||||
field: FieldValidationV5,
|
||||
context: {
|
||||
apiHolder: ApiHolder;
|
||||
formData: JsonObject;
|
||||
schema: JsonObject;
|
||||
uiSchema?: NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions>;
|
||||
},
|
||||
) => void | Promise<void>;
|
||||
|
||||
/**
|
||||
* Type for the Custom Field Extension with the
|
||||
* name and components and validation function.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type NextFieldExtensionOptions<
|
||||
TFieldReturnValue = unknown,
|
||||
TUiOptions = unknown,
|
||||
> = {
|
||||
name: string;
|
||||
component: (
|
||||
props: NextFieldExtensionComponentProps<TFieldReturnValue, TUiOptions>,
|
||||
) => JSX.Element | null;
|
||||
validation?: NextCustomFieldValidator<TFieldReturnValue, TUiOptions>;
|
||||
schema?: CustomFieldExtensionSchema;
|
||||
};
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
export * from './components';
|
||||
export * from './extensions';
|
||||
export * from './types';
|
||||
export * from './lib';
|
||||
export * from './hooks';
|
||||
|
||||
Reference in New Issue
Block a user