Merge branch 'types-react' into 'develop'
Upgrade @types/react to v18 See merge request soapbox-pub/soapbox!2147
This commit is contained in:
commit
8b50afc128
53 changed files with 282 additions and 164 deletions
|
@ -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,
|
||||
|
|
|
@ -30,6 +30,7 @@ interface IAutosuggesteTextarea {
|
|||
onFocus: () => void,
|
||||
onBlur?: () => void,
|
||||
condensed?: boolean,
|
||||
children: React.ReactNode,
|
||||
}
|
||||
|
||||
class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea> {
|
||||
|
|
|
@ -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 }) => {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 }) => {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ interface IPullToRefresh {
|
|||
onRefresh?: () => Promise<any>;
|
||||
refreshingContent?: JSX.Element | string;
|
||||
pullingContent?: JSX.Element | string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -21,6 +21,7 @@ interface IAnimatedInterface {
|
|||
onChange(index: number): void,
|
||||
/** Default tab index. */
|
||||
defaultIndex: number
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
/** Tabs with a sliding active state. */
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(() => ({
|
||||
|
|
|
@ -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);
|
||||
}, []);
|
||||
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}, []);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}), []);
|
||||
|
|
|
@ -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 }));
|
||||
|
|
|
@ -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 }));
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
||||
|
|
|
@ -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 }));
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Layout } from '../../../components/ui';
|
|||
|
||||
interface IColumnsArea {
|
||||
layout: any,
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const ColumnsArea: React.FC<IColumnsArea> = (props) => {
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -21,6 +21,7 @@ const messages = defineMessages({
|
|||
|
||||
interface IProfileDropdown {
|
||||
account: AccountEntity
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
type IMenuItem = {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 }));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -21,6 +21,7 @@ interface IEventPage {
|
|||
params?: {
|
||||
statusId?: string,
|
||||
},
|
||||
children: React.ReactNode,
|
||||
}
|
||||
|
||||
const EventPage: React.FC<IEventPage> = ({ params, children }) => {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -23,6 +23,7 @@ interface IProfilePage {
|
|||
params?: {
|
||||
username?: string,
|
||||
},
|
||||
children: React.ReactNode,
|
||||
}
|
||||
|
||||
const getAccount = makeGetAccount();
|
||||
|
|
|
@ -16,6 +16,7 @@ interface IRemoteInstancePage {
|
|||
params?: {
|
||||
instance?: string,
|
||||
},
|
||||
children: React.ReactNode,
|
||||
}
|
||||
|
||||
/** Page for viewing a remote instance timeline. */
|
||||
|
|
|
@ -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"
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -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" "*"
|
||||
|
|
Loading…
Reference in a new issue