Merge pull request #6694 from backstage/dependabot/npm_and_yarn/react-hook-form-7.12.2

chore(deps): bump react-hook-form from 6.15.4 to 7.12.2
This commit is contained in:
Fredrik Adelöw
2021-08-30 17:12:54 +02:00
committed by GitHub
15 changed files with 159 additions and 101 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/core-components': patch
'@backstage/plugin-catalog-import': patch
'@backstage/plugin-shortcuts': patch
---
Bumped `react-hook-form` to `^7.12.2`
+1 -1
View File
@@ -58,7 +58,7 @@
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-helmet": "6.1.0",
"react-hook-form": "^6.15.4",
"react-hook-form": "^7.12.2",
"react-markdown": "^5.0.2",
"react-router": "6.0.0-beta.0",
"react-router-dom": "6.0.0-beta.0",
@@ -15,7 +15,7 @@
*/
import React from 'react';
import { useForm } from 'react-hook-form';
import { useForm, UseFormRegisterReturn } from 'react-hook-form';
import {
Typography,
Button,
@@ -48,12 +48,21 @@ type Data = {
idToken?: string;
};
const asInputRef = (renderResult: UseFormRegisterReturn) => {
const { ref, ...rest } = renderResult;
return {
inputRef: ref,
...rest,
};
};
const Component: ProviderComponent = ({ onResult }) => {
const classes = useFormStyles();
const { register, handleSubmit, errors, formState } = useForm<Data>({
const { register, handleSubmit, formState } = useForm<Data>({
mode: 'onChange',
});
const { errors } = formState;
const handleResult = ({ userId, idToken }: Data) => {
onResult({
userId,
@@ -76,11 +85,10 @@ const Component: ProviderComponent = ({ onResult }) => {
<form className={classes.form} onSubmit={handleSubmit(handleResult)}>
<FormControl>
<TextField
name="userId"
{...asInputRef(register('userId', { required: true }))}
label="User ID"
margin="normal"
error={Boolean(errors.userId)}
inputRef={register({ required: true })}
/>
{errors.userId && (
<FormHelperText error>{errors.userId.message}</FormHelperText>
@@ -88,18 +96,19 @@ const Component: ProviderComponent = ({ onResult }) => {
</FormControl>
<FormControl>
<TextField
name="idToken"
{...asInputRef(
register('idToken', {
required: false,
validate: token =>
!token ||
ID_TOKEN_REGEX.test(token) ||
'Token is not a valid OpenID Connect JWT Token',
}),
)}
label="ID Token (optional)"
margin="normal"
autoComplete="off"
error={Boolean(errors.idToken)}
inputRef={register({
required: false,
validate: token =>
!token ||
ID_TOKEN_REGEX.test(token) ||
'Token is not a valid OpenID Connect JWT Token',
})}
/>
{errors.idToken && (
<FormHelperText error>{errors.idToken.message}</FormHelperText>
+3 -5
View File
@@ -9,7 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { CatalogApi } from '@backstage/catalog-client';
import { ConfigApi } from '@backstage/core-plugin-api';
import { Control } from 'react-hook-form';
import { Controller } from 'react-hook-form';
import { DiscoveryApi } from '@backstage/core-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { EntityName } from '@backstage/catalog-model';
@@ -23,9 +23,8 @@ import { ScmIntegrationRegistry } from '@backstage/integration';
import { SubmitHandler } from 'react-hook-form';
import { TextFieldProps } from '@material-ui/core/TextField/TextField';
import { UnpackNestedValue } from 'react-hook-form';
import { UseControllerOptions } from 'react-hook-form';
import { UseFormMethods } from 'react-hook-form';
import { UseFormOptions } from 'react-hook-form';
import { UseFormProps } from 'react-hook-form';
import { UseFormReturn } from 'react-hook-form';
// Warning: (ae-missing-release-tag) "AnalyzeResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -53,7 +52,6 @@ export const AutocompleteTextField: <TFieldValue extends string>({
name,
options,
required,
control,
errors,
rules,
loading,
+1 -1
View File
@@ -47,7 +47,7 @@
"js-base64": "^3.6.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-hook-form": "^6.15.4",
"react-hook-form": "^7.12.2",
"react-router": "6.0.0-beta.0",
"react-router-dom": "6.0.0-beta.0",
"react-use": "^17.2.4",
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { ConfigApi } from '@backstage/core-plugin-api';
import {
Box,
Checkbox,
@@ -25,6 +26,7 @@ import {
} from '@material-ui/core';
import React from 'react';
import { BackButton } from '../Buttons';
import { asInputRef } from '../helpers';
import { StepFinishImportLocation } from '../StepFinishImportLocation';
import { StepInitAnalyzeUrl } from '../StepInitAnalyzeUrl';
import {
@@ -34,7 +36,6 @@ import {
import { StepPrepareSelectLocations } from '../StepPrepareSelectLocations';
import { StepReviewLocation } from '../StepReviewLocation';
import { ImportFlows, ImportState } from '../useImportState';
import { ConfigApi } from '@backstage/core-plugin-api';
export type StepperProviderOpts = {
pullRequest?: {
@@ -186,8 +187,8 @@ export function defaultGenerateStepper(
defaultBody={body}
renderFormFields={({
values,
control,
errors,
setValue,
formState,
groupsLoading,
groups,
register,
@@ -198,26 +199,32 @@ export function defaultGenerateStepper(
</Box>
<TextField
name="title"
{...asInputRef(
register('title', {
required: true,
}),
)}
label="Pull Request Title"
placeholder="Add Backstage catalog entity descriptor files"
margin="normal"
variant="outlined"
fullWidth
inputRef={register({ required: true })}
error={Boolean(errors.title)}
error={Boolean(formState.errors.title)}
required
/>
<TextField
name="body"
{...asInputRef(
register('body', {
required: true,
}),
)}
label="Pull Request Body"
placeholder="A describing text with Markdown support"
margin="normal"
variant="outlined"
fullWidth
inputRef={register({ required: true })}
error={Boolean(errors.body)}
error={Boolean(formState.errors.body)}
multiline
required
/>
@@ -227,22 +234,22 @@ export function defaultGenerateStepper(
</Box>
<TextField
name="componentName"
{...asInputRef(
register('componentName', { required: true }),
)}
label="Name of the created component"
placeholder="my-component"
margin="normal"
variant="outlined"
fullWidth
inputRef={register({ required: true })}
error={Boolean(errors.componentName)}
error={Boolean(formState.errors.componentName)}
required
/>
{!values.useCodeowners && (
<AutocompleteTextField
name="owner"
control={control}
errors={errors}
errors={formState.errors}
options={groups || []}
loading={groupsLoading}
loadingText="Loading groups…"
@@ -260,11 +267,10 @@ export function defaultGenerateStepper(
<FormControlLabel
control={
<Checkbox
name="useCodeowners"
inputRef={register}
{...asInputRef(register('useCodeowners'))}
onChange={(_, value) => {
if (value) {
control.setValue('owner', '');
setValue('owner', '');
}
}}
/>
@@ -14,13 +14,14 @@
* limitations under the License.
*/
import { errorApiRef, useApi } from '@backstage/core-plugin-api';
import { FormHelperText, Grid, TextField } from '@material-ui/core';
import React, { useCallback, useState } from 'react';
import { useForm } from 'react-hook-form';
import { AnalyzeResult, catalogImportApiRef } from '../../api';
import { NextButton } from '../Buttons';
import { asInputRef } from '../helpers';
import { ImportFlows, PrepareResult } from '../useImportState';
import { errorApiRef, useApi } from '@backstage/core-plugin-api';
type FormData = {
url: string;
@@ -52,7 +53,12 @@ export const StepInitAnalyzeUrl = ({
const errorApi = useApi(errorApiRef);
const catalogImportApi = useApi(catalogImportApiRef);
const { register, handleSubmit, errors, watch } = useForm<FormData>({
const {
register,
handleSubmit,
formState: { errors },
watch,
} = useForm<FormData>({
mode: 'onTouched',
defaultValues: {
url: analysisUrl,
@@ -118,24 +124,25 @@ export const StepInitAnalyzeUrl = ({
return (
<form onSubmit={handleSubmit(handleResult)}>
<TextField
{...asInputRef(
register('url', {
required: true,
validate: {
httpsValidator: (value: any) =>
(typeof value === 'string' &&
value.match(/^http[s]?:\/\//) !== null) ||
'Must start with http:// or https://.',
},
}),
)}
fullWidth
id="url"
name="url"
label="Repository URL"
placeholder="https://github.com/backstage/backstage/blob/master/catalog-info.yaml"
helperText="Enter the full path to your entity file to start tracking your component"
margin="normal"
variant="outlined"
error={Boolean(errors.url)}
inputRef={register({
required: true,
validate: {
httpsValidator: (value: any) =>
(typeof value === 'string' &&
value.match(/^http[s]?:\/\//) !== null) ||
'Must start with http:// or https://.',
},
})}
required
/>
@@ -18,21 +18,15 @@ import { CircularProgress, TextField } from '@material-ui/core';
import { TextFieldProps } from '@material-ui/core/TextField/TextField';
import { Autocomplete } from '@material-ui/lab';
import React from 'react';
import {
Control,
Controller,
FieldErrors,
UseControllerOptions,
} from 'react-hook-form';
import { Controller, FieldErrors } from 'react-hook-form';
type Props<TFieldValue extends string> = {
name: TFieldValue;
options: string[];
required?: boolean;
control?: Control<Record<string, any>>;
errors?: FieldErrors<Record<TFieldValue, string>>;
rules?: UseControllerOptions<Record<TFieldValue, any>>['rules'];
rules?: React.ComponentProps<typeof Controller>['rules'];
loading?: boolean;
loadingText?: string;
@@ -47,7 +41,6 @@ export const AutocompleteTextField = <TFieldValue extends string>({
name,
options,
required,
control,
errors,
rules,
loading = false,
@@ -59,18 +52,17 @@ export const AutocompleteTextField = <TFieldValue extends string>({
return (
<Controller
name={name}
control={control}
rules={rules}
render={({ value, onChange, onBlur }) => (
render={({ field: { onChange } }) => (
<Autocomplete
loading={loading}
loadingText={loadingText}
options={options || []}
onChange={(_: any, v: string | null) => onChange(v || '')}
onBlur={onBlur}
value={value}
autoSelect
freeSolo
onChange={(_event: React.ChangeEvent<{}>, value: string | null) =>
onChange(value)
}
renderInput={params => (
<TextField
{...params}
@@ -18,6 +18,7 @@ import { FormHelperText, TextField } from '@material-ui/core';
import { act, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { asInputRef } from '../helpers';
import { PreparePullRequestForm } from './PreparePullRequestForm';
describe('<PreparePullRequestForm />', () => {
@@ -29,7 +30,7 @@ describe('<PreparePullRequestForm />', () => {
defaultValues={{ main: 'default' }}
render={({ register }) => (
<>
<TextField name="main" inputRef={register()} />
<TextField {...asInputRef(register('main'))} />
<button type="submit">Submit</button>{' '}
</>
)}
@@ -54,10 +55,9 @@ describe('<PreparePullRequestForm />', () => {
render={({ register }) => (
<>
<TextField
{...asInputRef(register('main'))}
id="main"
name="main"
label="Main Field"
inputRef={register()}
/>
<button type="submit">Submit</button>
</>
@@ -82,14 +82,14 @@ describe('<PreparePullRequestForm />', () => {
const { queryByText, getByRole } = render(
<PreparePullRequestForm<{ main: string }>
defaultValues={{}}
render={({ errors, register }) => (
render={({ formState, register }) => (
<>
<TextField
{...asInputRef(register('main', { required: true }))}
name="main"
required
inputRef={register({ required: true })}
/>
{errors.main && (
{formState.errors.main && (
<FormHelperText error>
Error in required main field
</FormHelperText>
@@ -19,20 +19,20 @@ import {
SubmitHandler,
UnpackNestedValue,
useForm,
UseFormMethods,
UseFormOptions,
UseFormProps,
UseFormReturn,
} from 'react-hook-form';
type Props<TFieldValues extends Record<string, any>> = Pick<
UseFormOptions<TFieldValues>,
UseFormProps<TFieldValues>,
'defaultValues'
> & {
onSubmit: SubmitHandler<TFieldValues>;
render: (
props: Pick<
UseFormMethods<TFieldValues>,
'errors' | 'register' | 'control'
UseFormReturn<TFieldValues>,
'formState' | 'register' | 'control' | 'setValue'
> & {
values: UnpackNestedValue<TFieldValues>;
},
@@ -55,12 +55,12 @@ export const PreparePullRequestForm = <
onSubmit,
render,
}: Props<TFieldValues>) => {
const { handleSubmit, watch, control, register, errors } =
const { handleSubmit, watch, control, register, formState, setValue } =
useForm<TFieldValues>({ mode: 'onTouched', defaultValues });
return (
<form onSubmit={handleSubmit(onSubmit)}>
{render({ values: watch(), errors, register, control })}
{render({ values: watch(), formState, register, control, setValue })}
</form>
);
};
@@ -20,6 +20,7 @@ import { act, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { AnalyzeResult, catalogImportApiRef } from '../../api';
import { asInputRef } from '../helpers';
import {
generateEntities,
StepPrepareCreatePullRequest,
@@ -91,10 +92,10 @@ describe('<StepPrepareCreatePullRequest />', () => {
renderFormFields={({ register }) => {
return (
<>
<TextField name="title" inputRef={register()} />
<TextField name="body" inputRef={register()} />
<TextField name="componentName" inputRef={register()} />
<TextField name="owner" inputRef={register()} />
<TextField {...asInputRef(register('title'))} />
<TextField {...asInputRef(register('body'))} />
<TextField {...asInputRef(register('componentName'))} />
<TextField {...asInputRef(register('owner'))} />
</>
);
}}
@@ -132,19 +133,17 @@ describe('<StepPrepareCreatePullRequest />', () => {
renderFormFields={({ register }) => {
return (
<>
<TextField name="title" inputRef={register()} />
<TextField name="body" inputRef={register()} />
<TextField {...asInputRef(register('title'))} />
<TextField {...asInputRef(register('body'))} />
<TextField
{...asInputRef(register('componentName'))}
id="name"
label="name"
name="componentName"
inputRef={register()}
/>
<TextField
{...asInputRef(register('owner'))}
id="owner"
label="owner"
name="owner"
inputRef={register()}
/>
</>
);
@@ -222,10 +221,10 @@ spec:
renderFormFields={({ register }) => {
return (
<>
<TextField name="title" inputRef={register()} />
<TextField name="body" inputRef={register()} />
<TextField name="componentName" inputRef={register()} />
<TextField name="owner" inputRef={register()} />
<TextField {...asInputRef(register('title'))} />
<TextField {...asInputRef(register('body'))} />
<TextField {...asInputRef(register('componentName'))} />
<TextField {...asInputRef(register('owner'))} />
</>
);
}}
@@ -15,6 +15,7 @@
*/
import { Entity } from '@backstage/catalog-model';
import { useApi } from '@backstage/core-plugin-api';
import {
catalogApiRef,
formatEntityRefTitle,
@@ -22,7 +23,7 @@ import {
import { Box, FormHelperText, Grid, Typography } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import React, { useCallback, useState } from 'react';
import { UnpackNestedValue, UseFormMethods } from 'react-hook-form';
import { UnpackNestedValue, UseFormReturn } from 'react-hook-form';
import { useAsync } from 'react-use';
import YAML from 'yaml';
import { AnalyzeResult, catalogImportApiRef } from '../../api';
@@ -32,7 +33,6 @@ import { PrepareResult } from '../useImportState';
import { PreparePullRequestForm } from './PreparePullRequestForm';
import { PreviewCatalogInfoComponent } from './PreviewCatalogInfoComponent';
import { PreviewPullRequestComponent } from './PreviewPullRequestComponent';
import { useApi } from '@backstage/core-plugin-api';
const useStyles = makeStyles(theme => ({
previewCard: {
@@ -63,7 +63,10 @@ type Props = {
defaultBody: string;
renderFormFields: (
props: Pick<UseFormMethods<FormData>, 'errors' | 'register' | 'control'> & {
props: Pick<
UseFormReturn<FormData>,
'register' | 'setValue' | 'formState'
> & {
values: UnpackNestedValue<FormData>;
groups: string[];
groupsLoading: boolean;
@@ -192,13 +195,13 @@ export const StepPrepareCreatePullRequest = ({
analyzeResult.generatedEntities[0]?.metadata?.name || '',
useCodeowners: false,
}}
render={({ values, errors, control, register }) => (
render={({ values, formState, register, setValue }) => (
<>
{renderFormFields({
values,
errors,
formState,
register,
control,
setValue,
groups: groups ?? [],
groupsLoading,
})}
@@ -241,7 +244,11 @@ export const StepPrepareCreatePullRequest = ({
)}
<NextButton
type="submit"
disabled={Boolean(errors.title || errors.body || errors.owner)}
disabled={Boolean(
formState.errors.title ||
formState.errors.body ||
formState.errors.owner,
)}
loading={submitted}
>
Create PR
@@ -0,0 +1,33 @@
/*
* 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 { UseFormRegisterReturn } from 'react-hook-form';
/**
* A helper that converts the result of a render('name', opts) to make it compatible with material-ui.
*
* See also https://github.com/react-hook-form/react-hook-form/issues/4629#issuecomment-815840872
* TODO: remove when updating to material-ui v5 (https://github.com/mui-org/material-ui/pull/23174)
*
* @param renderResult - the result of a render('name', opts)
*/
export function asInputRef(renderResult: UseFormRegisterReturn) {
const { ref, ...rest } = renderResult;
return {
inputRef: ref,
...rest,
};
}
+1 -1
View File
@@ -29,7 +29,7 @@
"@types/zen-observable": "^0.8.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-hook-form": "^7.1.1",
"react-hook-form": "^7.12.2",
"react-router": "6.0.0-beta.0",
"react-use": "^17.2.4",
"uuid": "^8.3.2",
+4 -4
View File
@@ -22376,10 +22376,10 @@ react-hook-form@^6.15.4:
resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.15.4.tgz#328003e1ccc096cd158899ffe7e3b33735a9b024"
integrity sha512-K+Sw33DtTMengs8OdqFJI3glzNl1wBzSefD/ksQw/hJf9CnOHQAU6qy82eOrh0IRNt2G53sjr7qnnw1JDjvx1w==
react-hook-form@^7.1.1:
version "7.2.1"
resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.2.1.tgz#99b3540dd2314499df12e9a53c70587ad63a806c"
integrity sha512-QopAubhVofqQrwlWLr9aK0DF8tNU8fnU8sJIlw1Tb3tGkEvP9yeaA+cx1hlxYni8xBswtHruL1WcDEa6CYQDow==
react-hook-form@^7.12.2:
version "7.12.2"
resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.12.2.tgz#2660afbf03c4ef360a9314ebf46ce3d972296c77"
integrity sha512-cpxocjrgpMAJCMJQR51BQhMoEx80/EQqePNihMTgoTYTqCRbd2GExi+N4GJIr+cFqrmbwNj9wxk5oLWYQsUefg==
react-hot-loader@^4.12.21:
version "4.13.0"