Merge branch 'types-react' into 'develop'

Upgrade @types/react to v18

See merge request soapbox-pub/soapbox!2147
This commit is contained in:
Alex Gleason 2023-01-13 18:05:59 +00:00
commit 8b50afc128
53 changed files with 282 additions and 164 deletions

View file

@ -47,11 +47,17 @@ const InstanceFavicon: React.FC<IInstanceFavicon> = ({ account, disabled }) => {
interface IProfilePopper {
condition: boolean,
wrapper: (children: any) => React.ReactElement<any, any>
wrapper: (children: React.ReactNode) => React.ReactNode
children: React.ReactNode
}
const ProfilePopper: React.FC<IProfilePopper> = ({ condition, wrapper, children }): any =>
condition ? wrapper(children) : children;
const ProfilePopper: React.FC<IProfilePopper> = ({ condition, wrapper, children }) => {
return (
<>
{condition ? wrapper(children) : children}
</>
);
};
export interface IAccount {
account: AccountEntity,

View file

@ -30,6 +30,7 @@ interface IAutosuggesteTextarea {
onFocus: () => void,
onBlur?: () => void,
condensed?: boolean,
children: React.ReactNode,
}
class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea> {

View file

@ -16,6 +16,7 @@ interface IDisplayName {
account: Account
withSuffix?: boolean
withDate?: boolean
children?: React.ReactNode
}
const DisplayName: React.FC<IDisplayName> = ({ account, children, withSuffix = true, withDate = false }) => {

View file

@ -26,7 +26,9 @@ const mapStateToProps = (state: RootState) => {
};
};
type Props = ReturnType<typeof mapStateToProps>;
interface Props extends ReturnType<typeof mapStateToProps> {
children: React.ReactNode
}
type State = {
hasError: boolean,
@ -213,4 +215,4 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
}
export default connect(mapStateToProps)(ErrorBoundary as any);
export default connect(mapStateToProps)(ErrorBoundary);

View file

@ -15,7 +15,11 @@ const getNotifTotals = (state: RootState): number => {
return notifications + reports + approvals;
};
const Helmet: React.FC = ({ children }) => {
interface IHelmet {
children: React.ReactNode
}
const Helmet: React.FC<IHelmet> = ({ children }) => {
const instance = useInstance();
const { unreadChatsCount } = useStatContext();
const unreadCount = useAppSelector((state) => getNotifTotals(state) + unreadChatsCount);

View file

@ -18,6 +18,7 @@ interface IHoverRefWrapper {
accountId: string,
inline?: boolean,
className?: string,
children: React.ReactNode,
}
/** Makes a profile hover card appear when the wrapped element is hovered. */

View file

@ -17,6 +17,7 @@ interface IHoverStatusWrapper {
statusId: any,
inline: boolean,
className?: string,
children: React.ReactNode,
}
/** Makes a status hover card appear when the wrapped element is hovered. */

View file

@ -7,7 +7,11 @@ import { SelectDropdown } from '../features/forms';
import Icon from './icon';
import { HStack, Select } from './ui';
const List: React.FC = ({ children }) => (
interface IList {
children: React.ReactNode
}
const List: React.FC<IList> = ({ children }) => (
<div className='space-y-0.5'>{children}</div>
);
@ -17,6 +21,7 @@ interface IListItem {
onClick?(): void,
onSelect?(): void
isSelected?: boolean
children?: React.ReactNode
}
const ListItem: React.FC<IListItem> = ({ label, hint, children, onClick, onSelect, isSelected }) => {

View file

@ -42,6 +42,7 @@ interface IModalRoot {
onCancel?: () => void,
onClose: (type?: ModalType) => void,
type: ModalType,
children: React.ReactNode,
}
const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type }) => {
@ -128,10 +129,10 @@ const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type })
});
};
const handleKeyDown = useCallback((e) => {
const handleKeyDown = useCallback((e: KeyboardEvent) => {
if (e.key === 'Tab') {
const focusable = Array.from(ref.current!.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter((x) => window.getComputedStyle(x).display !== 'none');
const index = focusable.indexOf(e.target);
const index = focusable.indexOf(e.target as Element);
let element;

View file

@ -7,6 +7,7 @@ interface IPullToRefresh {
onRefresh?: () => Promise<any>;
refreshingContent?: JSX.Element | string;
pullingContent?: JSX.Element | string;
children: React.ReactNode;
}
/**

View file

@ -79,6 +79,7 @@ const StatusReplyMentions: React.FC<IStatusReplyMentions> = ({ status, hoverable
defaultMessage='<hover>Replying to</hover> {accounts}'
values={{
accounts: <FormattedList type='conjunction' value={accounts} />,
// @ts-ignore wtf?
hover: (children: React.ReactNode) => {
if (hoverable) {
return (

View file

@ -252,8 +252,10 @@ const Status: React.FC<IStatus> = (props) => {
if (hidden) {
return (
<div ref={node}>
{actualStatus.getIn(['account', 'display_name']) || actualStatus.getIn(['account', 'username'])}
{actualStatus.content}
<>
{actualStatus.getIn(['account', 'display_name']) || actualStatus.getIn(['account', 'username'])}
{actualStatus.content}
</>
</div>
);
}

View file

@ -66,7 +66,7 @@ const Button = React.forwardRef<HTMLButtonElement, IButton>((props, ref): JSX.El
return <Icon src={icon} className='w-4 h-4' />;
};
const handleClick = React.useCallback((event) => {
const handleClick: React.MouseEventHandler<HTMLButtonElement> = React.useCallback((event) => {
if (onClick && !disabled) {
onClick(event);
}

View file

@ -45,6 +45,7 @@ interface ICardHeader {
backHref?: string,
onBackClick?: (event: React.MouseEvent) => void
className?: string
children?: React.ReactNode
}
/**
@ -91,6 +92,8 @@ const CardTitle: React.FC<ICardTitle> = ({ title }): JSX.Element => (
interface ICardBody {
/** Classnames for the <div> element. */
className?: string
/** Children to appear inside the card. */
children: React.ReactNode
}
/** A card's body. */

View file

@ -46,6 +46,8 @@ export interface IColumn {
className?: string,
/** Ref forwarded to column. */
ref?: React.Ref<HTMLDivElement>
/** Children to display in the column. */
children?: React.ReactNode
}
/** A backdrop for the main section of the UI. */

View file

@ -2,8 +2,12 @@ import React from 'react';
import HStack from '../hstack/hstack';
interface IFormActions {
children: React.ReactNode
}
/** Container element to house form actions. */
const FormActions: React.FC = ({ children }) => (
const FormActions: React.FC<IFormActions> = ({ children }) => (
<HStack space={2} justifyContent='end'>
{children}
</HStack>

View file

@ -14,6 +14,8 @@ interface IFormGroup {
hintText?: React.ReactNode,
/** Input errors. */
errors?: string[]
/** Elements to display within the FormGroup. */
children: React.ReactNode
}
/** Input container with label. Renders the child. */

View file

@ -5,11 +5,13 @@ interface IForm {
onSubmit?: (event: React.FormEvent) => void,
/** Class name override for the <form> element. */
className?: string,
/** Elements to display within the Form. */
children: React.ReactNode,
}
/** Form element with custom styles. */
const Form: React.FC<IForm> = ({ onSubmit, children, ...filteredProps }) => {
const handleSubmit = React.useCallback((event) => {
const handleSubmit: React.FormEventHandler = React.useCallback((event) => {
event.preventDefault();
if (onSubmit) {

View file

@ -2,10 +2,21 @@ import classNames from 'clsx';
import React from 'react';
import StickyBox from 'react-sticky-box';
interface LayoutComponent extends React.FC {
Sidebar: React.FC,
interface ISidebar {
children: React.ReactNode
}
interface IAside {
children?: React.ReactNode
}
interface ILayout {
children: React.ReactNode
}
interface LayoutComponent extends React.FC<ILayout> {
Sidebar: React.FC<ISidebar>,
Main: React.FC<React.HTMLAttributes<HTMLDivElement>>,
Aside: React.FC,
Aside: React.FC<IAside>,
}
/** Layout container, to hold Sidebar, Main, and Aside. */
@ -18,7 +29,7 @@ const Layout: LayoutComponent = ({ children }) => (
);
/** Left sidebar container in the UI. */
const Sidebar: React.FC = ({ children }) => (
const Sidebar: React.FC<ISidebar> = ({ children }) => (
<div className='hidden lg:block lg:col-span-3'>
<StickyBox offsetTop={80} className='pb-4'>
{children}
@ -38,7 +49,7 @@ const Main: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({ children, classN
);
/** Right sidebar container in the UI. */
const Aside: React.FC = ({ children }) => (
const Aside: React.FC<IAside> = ({ children }) => (
<aside className='hidden xl:block xl:col-span-3'>
<StickyBox offsetTop={80} className='space-y-6 pb-12'>
{children}

View file

@ -52,6 +52,7 @@ interface IModal {
/** Title text for the modal. */
title?: React.ReactNode,
width?: keyof typeof widths,
children?: React.ReactNode,
}
/** Displays a modal dialog box. */

View file

@ -21,6 +21,7 @@ interface IAnimatedInterface {
onChange(index: number): void,
/** Default tab index. */
defaultIndex: number
children: React.ReactNode
}
/** Tabs with a sliding active state. */

View file

@ -7,6 +7,8 @@ import './tooltip.css';
interface ITooltip {
/** Text to display in the tooltip. */
text: string,
/** Element to display the tooltip around. */
children: React.ReactNode,
}
const centered = (triggerRect: any, tooltipRect: any) => {

View file

@ -12,8 +12,12 @@ const WidgetTitle = ({ title }: IWidgetTitle): JSX.Element => (
<Text size='xl' weight='bold' tag='h1'>{title}</Text>
);
interface IWidgetBody {
children: React.ReactNode
}
/** Body of a widget. */
const WidgetBody: React.FC = ({ children }): JSX.Element => (
const WidgetBody: React.FC<IWidgetBody> = ({ children }): JSX.Element => (
<Stack space={3}>{children}</Stack>
);
@ -27,6 +31,7 @@ interface IWidget {
/** Text for the action. */
actionTitle?: string,
action?: JSX.Element,
children?: React.ReactNode,
}
/** Sidebar widget. */

View file

@ -19,7 +19,11 @@ enum ChatWidgetScreens {
CHAT_SETTINGS = 'CHAT_SETTINGS'
}
const ChatProvider: React.FC = ({ children }) => {
interface IChatProvider {
children: React.ReactNode
}
const ChatProvider: React.FC<IChatProvider> = ({ children }) => {
const history = useHistory();
const dispatch = useAppDispatch();
const settings = useSettings();

View file

@ -9,7 +9,11 @@ const StatContext = createContext<any>({
unreadChatsCount: 0,
});
const StatProvider: React.FC = ({ children }) => {
interface IStatProvider {
children: React.ReactNode
}
const StatProvider: React.FC<IStatProvider> = ({ children }) => {
const [unreadChatsCount, setUnreadChatsCount] = useState<number>(0);
const value = useMemo(() => ({

View file

@ -32,7 +32,7 @@ const PasswordResetConfirm = () => {
const isLoading = status === Statuses.LOADING;
const handleSubmit = React.useCallback((event) => {
const handleSubmit: React.FormEventHandler = React.useCallback((event) => {
event.preventDefault();
setStatus(Statuses.LOADING);
@ -41,7 +41,7 @@ const PasswordResetConfirm = () => {
.catch(() => setStatus(Statuses.FAIL));
}, [password]);
const onChange = React.useCallback((event) => {
const onChange: React.ChangeEventHandler<HTMLInputElement> = React.useCallback((event) => {
setPassword(event.target.value);
}, []);

View file

@ -224,124 +224,126 @@ const RegistrationForm: React.FC<IRegistrationForm> = ({ inviteToken }) => {
return (
<Form onSubmit={onSubmit} data-testid='registrations-open'>
<fieldset disabled={isLoading} className='space-y-3'>
<FormGroup
hintText={intl.formatMessage(messages.username_hint)}
errors={usernameUnavailable ? [intl.formatMessage(messages.usernameUnavailable)] : undefined}
>
<Input
type='text'
name='username'
placeholder={intl.formatMessage(messages.username)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
pattern='^[a-zA-Z\d_-]+'
onChange={onUsernameChange}
value={params.get('username', '')}
required
/>
</FormGroup>
<Input
type='email'
name='email'
placeholder={intl.formatMessage(messages.email)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onInputChange}
value={params.get('email', '')}
required
/>
<Input
type='password'
name='password'
placeholder={intl.formatMessage(messages.password)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onPasswordChange}
value={params.get('password', '')}
required
/>
<FormGroup
errors={passwordMismatch ? [intl.formatMessage(messages.passwordMismatch)] : undefined}
>
<Input
type='password'
name='password_confirmation'
placeholder={intl.formatMessage(messages.confirm)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onPasswordConfirmChange}
onBlur={onPasswordConfirmBlur}
value={passwordConfirmation}
required
/>
</FormGroup>
{birthdayRequired && (
<BirthdayInput
value={params.get('birthday')}
onChange={onBirthdayChange}
required
/>
)}
{needsApproval && (
<>
<FormGroup
labelText={<FormattedMessage id='registration.reason' defaultMessage='Why do you want to join?' />}
hintText={<FormattedMessage id='registration.reason_hint' defaultMessage='This will help us review your application' />}
hintText={intl.formatMessage(messages.username_hint)}
errors={usernameUnavailable ? [intl.formatMessage(messages.usernameUnavailable)] : undefined}
>
<Textarea
name='reason'
maxLength={500}
onChange={onInputChange}
value={params.get('reason', '')}
<Input
type='text'
name='username'
placeholder={intl.formatMessage(messages.username)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
pattern='^[a-zA-Z\d_-]+'
onChange={onUsernameChange}
value={params.get('username', '')}
required
/>
</FormGroup>
)}
<CaptchaField
onFetch={onFetchCaptcha}
onFetchFail={onFetchCaptchaFail}
onChange={onInputChange}
onClick={onCaptchaClick}
idempotencyKey={captchaIdempotencyKey}
name='captcha_solution'
value={params.get('captcha_solution', '')}
/>
<FormGroup
labelText={intl.formatMessage(messages.agreement, { tos: <Link to='/about/tos' target='_blank' key={0}>{intl.formatMessage(messages.tos)}</Link> })}
>
<Checkbox
name='agreement'
onChange={onCheckboxChange}
checked={params.get('agreement', false)}
<Input
type='email'
name='email'
placeholder={intl.formatMessage(messages.email)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onInputChange}
value={params.get('email', '')}
required
/>
</FormGroup>
{supportsEmailList && (
<FormGroup labelText={intl.formatMessage(messages.newsletter)}>
<Checkbox
name='accepts_email_list'
onChange={onCheckboxChange}
checked={params.get('accepts_email_list', false)}
<Input
type='password'
name='password'
placeholder={intl.formatMessage(messages.password)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onPasswordChange}
value={params.get('password', '')}
required
/>
<FormGroup
errors={passwordMismatch ? [intl.formatMessage(messages.passwordMismatch)] : undefined}
>
<Input
type='password'
name='password_confirmation'
placeholder={intl.formatMessage(messages.confirm)}
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
onChange={onPasswordConfirmChange}
onBlur={onPasswordConfirmBlur}
value={passwordConfirmation}
required
/>
</FormGroup>
)}
<FormActions>
<Button type='submit'>
<FormattedMessage id='registration.sign_up' defaultMessage='Sign up' />
</Button>
</FormActions>
{birthdayRequired && (
<BirthdayInput
value={params.get('birthday')}
onChange={onBirthdayChange}
required
/>
)}
{needsApproval && (
<FormGroup
labelText={<FormattedMessage id='registration.reason' defaultMessage='Why do you want to join?' />}
hintText={<FormattedMessage id='registration.reason_hint' defaultMessage='This will help us review your application' />}
>
<Textarea
name='reason'
maxLength={500}
onChange={onInputChange}
value={params.get('reason', '')}
required
/>
</FormGroup>
)}
<CaptchaField
onFetch={onFetchCaptcha}
onFetchFail={onFetchCaptchaFail}
onChange={onInputChange}
onClick={onCaptchaClick}
idempotencyKey={captchaIdempotencyKey}
name='captcha_solution'
value={params.get('captcha_solution', '')}
/>
<FormGroup
labelText={intl.formatMessage(messages.agreement, { tos: <Link to='/about/tos' target='_blank' key={0}>{intl.formatMessage(messages.tos)}</Link> })}
>
<Checkbox
name='agreement'
onChange={onCheckboxChange}
checked={params.get('agreement', false)}
required
/>
</FormGroup>
{supportsEmailList && (
<FormGroup labelText={intl.formatMessage(messages.newsletter)}>
<Checkbox
name='accepts_email_list'
onChange={onCheckboxChange}
checked={params.get('accepts_email_list', false)}
/>
</FormGroup>
)}
<FormActions>
<Button type='submit'>
<FormattedMessage id='registration.sign_up' defaultMessage='Sign up' />
</Button>
</FormActions>
</>
</fieldset>
</Form>
);

View file

@ -6,6 +6,8 @@ import { Avatar, HStack, Stack, Text } from 'soapbox/components/ui';
import VerificationBadge from 'soapbox/components/verification-badge';
import useAccountSearch from 'soapbox/queries/search';
import type { Account } from 'soapbox/types/entities';
interface IResults {
accountSearchResult: ReturnType<typeof useAccountSearch>
onSelect(id: string): void
@ -23,7 +25,7 @@ const Results = ({ accountSearchResult, onSelect }: IResults) => {
}
};
const renderAccount = useCallback((_index, account) => (
const renderAccount = useCallback((_index: number, account: Account) => (
<button
key={account.id}
type='button'

View file

@ -72,8 +72,8 @@ const EmojiPickerMenu: React.FC<IEmojiPickerMenu> = ({
categoriesSort.splice(1, 0, ...Array.from(categoriesFromEmojis(customEmojis) as Set<string>).sort());
const handleDocumentClick = useCallback(e => {
if (node.current && !node.current.contains(e.target)) {
const handleDocumentClick = useCallback((e: MouseEvent | TouchEvent) => {
if (node.current && !node.current.contains(e.target as Node)) {
onClose();
}
}, []);

View file

@ -19,8 +19,8 @@ const ModifierPickerMenu: React.FC<IModifierPickerMenu> = ({ active, onSelect, o
onSelect(+e.currentTarget.getAttribute('data-index')! * 1);
};
const handleDocumentClick = useCallback((e => {
if (node.current && !node.current.contains(e.target)) {
const handleDocumentClick = useCallback(((e: MouseEvent | TouchEvent) => {
if (node.current && !node.current.contains(e.target as Node)) {
onClose();
}
}), []);

View file

@ -28,7 +28,7 @@ const EditEmail = () => {
const { email, password } = state;
const handleInputChange = React.useCallback((event) => {
const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = React.useCallback((event) => {
event.persist();
setState((prevState) => ({ ...prevState, [event.target.name]: event.target.value }));

View file

@ -34,7 +34,7 @@ const EditPassword = () => {
const resetState = () => setState(initialState);
const handleInputChange = React.useCallback((event) => {
const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = React.useCallback((event) => {
event.persist();
setState((prevState) => ({ ...prevState, [event.target.name]: event.target.value }));

View file

@ -11,6 +11,7 @@ interface IInputContainer {
type?: string,
extraClass?: string,
error?: boolean,
children: React.ReactNode,
}
export const InputContainer: React.FC<IInputContainer> = (props) => {
@ -32,6 +33,7 @@ export const InputContainer: React.FC<IInputContainer> = (props) => {
interface ILabelInputContainer {
label?: React.ReactNode,
hint?: React.ReactNode,
children: React.ReactNode,
}
export const LabelInputContainer: React.FC<ILabelInputContainer> = ({ label, hint, children }) => {
@ -128,6 +130,7 @@ interface ISimpleForm {
onSubmit?: React.FormEventHandler,
acceptCharset?: string,
style?: React.CSSProperties,
children: React.ReactNode,
}
export const SimpleForm: React.FC<ISimpleForm> = (props) => {
@ -157,7 +160,11 @@ export const SimpleForm: React.FC<ISimpleForm> = (props) => {
);
};
export const FieldsGroup: React.FC = ({ children }) => (
interface IFieldsGroup {
children: React.ReactNode,
}
export const FieldsGroup: React.FC<IFieldsGroup> = ({ children }) => (
<div className='fields-group'>{children}</div>
);

View file

@ -42,7 +42,7 @@ const OtpConfirmForm: React.FC = () => {
});
}, []);
const handleInputChange = useCallback((event) => {
const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = useCallback((event) => {
event.persist();
setState((prevState) => ({ ...prevState, [event.target.name]: event.target.value }));

View file

@ -4,6 +4,7 @@ import { Layout } from '../../../components/ui';
interface IColumnsArea {
layout: any,
children: React.ReactNode
}
const ColumnsArea: React.FC<IColumnsArea> = (props) => {

View file

@ -13,6 +13,7 @@ interface IFooterLink {
to: string,
className?: string,
onClick?: React.EventHandler<React.MouseEvent>,
children: React.ReactNode,
}
const FooterLink: React.FC<IFooterLink> = ({ children, className, ...rest }): JSX.Element => {

View file

@ -21,6 +21,7 @@ const messages = defineMessages({
interface IProfileDropdown {
account: AccountEntity
children: React.ReactNode
}
type IMenuItem = {

View file

@ -149,7 +149,11 @@ const keyMap = {
openMedia: 'a',
};
const SwitchingColumnsArea: React.FC = ({ children }) => {
interface ISwitchingColumnsArea {
children: React.ReactNode
}
const SwitchingColumnsArea: React.FC<ISwitchingColumnsArea> = ({ children }) => {
const features = useFeatures();
const { search } = useLocation();
@ -314,7 +318,11 @@ const SwitchingColumnsArea: React.FC = ({ children }) => {
);
};
const UI: React.FC = ({ children }) => {
interface IUI {
children?: React.ReactNode
}
const UI: React.FC<IUI> = ({ children }) => {
const intl = useIntl();
const history = useHistory();
const dispatch = useAppDispatch();

View file

@ -43,7 +43,7 @@ const Registration = () => {
const [hasValidPassword, setHasValidPassword] = React.useState<boolean>(false);
const { username, password } = state;
const handleSubmit = React.useCallback((event) => {
const handleSubmit: React.FormEventHandler = React.useCallback((event) => {
event.preventDefault();
dispatch(createAccount(username, password))
@ -69,7 +69,7 @@ const Registration = () => {
});
}, [username, password]);
const handleInputChange = React.useCallback((event) => {
const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = React.useCallback((event) => {
event.persist();
setState((prevState) => ({ ...prevState, [event.target.name]: event.target.value }));

View file

@ -29,15 +29,15 @@ const AgeVerification = () => {
const isLoading = useAppSelector((state) => state.verification.isLoading) as boolean;
const ageMinimum = useAppSelector((state) => state.verification.ageMinimum) as any;
const [date, setDate] = React.useState('');
const [date, setDate] = React.useState<Date>();
const isValid = typeof date === 'object';
const onChange = React.useCallback((date) => setDate(date), []);
const onChange = React.useCallback((date: Date) => setDate(date), []);
const handleSubmit = React.useCallback((event) => {
const handleSubmit: React.FormEventHandler = React.useCallback((event) => {
event.preventDefault();
const birthday = new Date(date);
const birthday = new Date(date!);
if (meetsAgeMinimum(birthday, ageMinimum)) {
dispatch(verifyAge(birthday));

View file

@ -69,7 +69,9 @@ const EmailVerification = () => {
const isValid = email.length > 0 && EMAIL_REGEX.test(email);
const onChange = React.useCallback((event) => setEmail(event.target.value), []);
const onChange: React.ChangeEventHandler<HTMLInputElement> = React.useCallback((event) => {
setEmail(event.target.value);
}, []);
const handleSubmit: React.FormEventHandler = React.useCallback((event) => {
event.preventDefault();

View file

@ -39,7 +39,7 @@ const SmsVerification = () => {
setPhone(phone);
}, []);
const handleSubmit = React.useCallback((event) => {
const handleSubmit: React.FormEventHandler = React.useCallback((event) => {
event.preventDefault();
if (!isValid) {
@ -59,7 +59,7 @@ const SmsVerification = () => {
});
}, [phone, isValid]);
const resendVerificationCode = React.useCallback((event) => {
const resendVerificationCode: React.MouseEventHandler = React.useCallback((event) => {
setAlreadyRequestedAnother(true);
handleSubmit(event);
}, [isValid]);

View file

@ -80,7 +80,7 @@ const customRender = (
});
/** Like renderHook, but with access to the Redux store. */
const customRenderHook = <T extends {}>(
const customRenderHook = <T extends { children?: React.ReactNode }>(
callback: (props?: any) => any,
options?: Omit<RenderHookOptions<T>, 'wrapper'>,
store?: any,

View file

@ -8,7 +8,11 @@ import {
import LinkFooter from '../features/ui/components/link-footer';
const AdminPage: React.FC = ({ children }) => {
interface IAdminPage {
children: React.ReactNode
}
const AdminPage: React.FC<IAdminPage> = ({ children }) => {
return (
<>
<Layout.Main>

View file

@ -1,7 +1,11 @@
import React from 'react';
interface IChatsPage {
children: React.ReactNode
}
/** Custom layout for chats on desktop. */
const ChatsPage: React.FC = ({ children }) => {
const ChatsPage: React.FC<IChatsPage> = ({ children }) => {
return (
<div className='md:col-span-12 lg:col-span-9'>
{children}

View file

@ -12,7 +12,11 @@ import { useAppSelector, useFeatures } from 'soapbox/hooks';
import { Layout } from '../components/ui';
const DefaultPage: React.FC = ({ children }) => {
interface IDefaultPage {
children: React.ReactNode
}
const DefaultPage: React.FC<IDefaultPage> = ({ children }) => {
const me = useAppSelector(state => state.me);
const features = useFeatures();

View file

@ -2,7 +2,11 @@ import React from 'react';
import { Layout } from '../components/ui';
const EmptyPage: React.FC = ({ children }) => {
interface IEmptyPage {
children: React.ReactNode
}
const EmptyPage: React.FC<IEmptyPage> = ({ children }) => {
return (
<>
<Layout.Main>

View file

@ -21,6 +21,7 @@ interface IEventPage {
params?: {
statusId?: string,
},
children: React.ReactNode,
}
const EventPage: React.FC<IEventPage> = ({ params, children }) => {

View file

@ -20,7 +20,11 @@ import { Avatar, Card, CardBody, HStack, Layout } from '../components/ui';
import ComposeForm from '../features/compose/components/compose-form';
import BundleContainer from '../features/ui/containers/bundle-container';
const HomePage: React.FC = ({ children }) => {
interface IHomePage {
children: React.ReactNode
}
const HomePage: React.FC<IHomePage> = ({ children }) => {
const me = useAppSelector(state => state.me);
const account = useOwnAccount();
const features = useFeatures();

View file

@ -23,6 +23,7 @@ interface IProfilePage {
params?: {
username?: string,
},
children: React.ReactNode,
}
const getAccount = makeGetAccount();

View file

@ -16,6 +16,7 @@ interface IRemoteInstancePage {
params?: {
instance?: string,
},
children: React.ReactNode,
}
/** Page for viewing a remote instance timeline. */

View file

@ -80,8 +80,10 @@
"@types/lodash": "^4.14.180",
"@types/object-assign": "^4.0.30",
"@types/qrcode.react": "^1.0.2",
"@types/react": "^18.0.26",
"@types/react-color": "^3.0.6",
"@types/react-datepicker": "^4.4.2",
"@types/react-dom": "^18.0.10",
"@types/react-helmet": "^6.1.5",
"@types/react-motion": "^0.0.33",
"@types/react-router-dom": "^5.3.3",
@ -233,6 +235,8 @@
"yargs": "^17.6.2"
},
"resolutions": {
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"glob-parent": "^6.0.1",
"jsonwebtoken": "^9.0.0",
"loader-utils": "^2.0.3"

View file

@ -2850,7 +2850,7 @@
date-fns "^2.0.1"
react-popper "^2.2.5"
"@types/react-dom@^18.0.0":
"@types/react-dom@^18.0.0", "@types/react-dom@^18.0.10":
version "18.0.10"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.10.tgz#3b66dec56aa0f16a6cc26da9e9ca96c35c0b4352"
integrity sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==
@ -2881,9 +2881,9 @@
"@types/react-router" "*"
"@types/react-router@*":
version "5.1.18"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.18.tgz#c8851884b60bc23733500d86c1266e1cfbbd9ef3"
integrity sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==
version "5.1.20"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c"
integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==
dependencies:
"@types/history" "^4.7.11"
"@types/react" "*"
@ -2909,10 +2909,10 @@
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@17":
version "17.0.21"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.21.tgz#069c43177cd419afaab5ce26bb4e9056549f7ea6"
integrity sha512-GzzXCpOthOjXvrAUFQwU/svyxu658cwu00Q9ugujS4qc1zXgLFaO0kS2SLOaMWLt2Jik781yuHCWB7UcYdGAeQ==
"@types/react@*", "@types/react@17", "@types/react@^18.0.26":
version "18.0.26"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917"
integrity sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"