diff --git a/package.json b/package.json index 5976379ab2e..086cc8b255d 100644 --- a/package.json +++ b/package.json @@ -71,9 +71,13 @@ "update:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js" }, "resolutions": { + "@types/react": "19.0.0", + "@types/react-dom": "19.0.0", "oidc-client-ts": "3.1.0", "jwt-decode": "4.0.0", "caniuse-lite": "1.0.30001684", + "react": "19.0.0", + "react-dom": "19.0.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi": "npm:wrap-ansi@^7.0.0" }, @@ -135,10 +139,10 @@ "posthog-js": "1.157.2", "qrcode": "1.5.4", "re-resizable": "6.10.1", - "react": "^18.3.1", + "react": "^19", "react-beautiful-dnd": "^13.1.0", "react-blurhash": "^0.3.0", - "react-dom": "^18.3.1", + "react-dom": "^19", "react-focus-lock": "^2.5.1", "react-transition-group": "^4.4.1", "rfc4648": "^1.4.0", @@ -179,7 +183,7 @@ "@svgr/webpack": "^8.0.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.4.8", - "@testing-library/react": "^16.0.0", + "@testing-library/react": "^16.1.0", "@testing-library/user-event": "^14.5.2", "@types/commonmark": "^0.27.4", "@types/counterpart": "^0.18.1", @@ -201,9 +205,9 @@ "@types/node-fetch": "^2.6.2", "@types/pako": "^2.0.0", "@types/qrcode": "^1.3.5", - "@types/react": "18.3.3", + "@types/react": "^19", "@types/react-beautiful-dnd": "^13.0.0", - "@types/react-dom": "18.3.1", + "@types/react-dom": "^19", "@types/react-transition-group": "^4.4.0", "@types/sanitize-html": "2.13.0", "@types/semver": "^7.5.8", diff --git a/src/@types/common.ts b/src/@types/common.ts index f80b66a6322..07c0881b494 100644 --- a/src/@types/common.ts +++ b/src/@types/common.ts @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import { JSXElementConstructor } from "react"; +import { JSXElementConstructor, type JSX } from "react"; export type { NonEmptyArray, XOR, Writeable } from "matrix-js-sdk/src/matrix"; diff --git a/src/@types/react.d.ts b/src/@types/react.d.ts index ba97b2bba6f..3c2395971d4 100644 --- a/src/@types/react.d.ts +++ b/src/@types/react.d.ts @@ -11,9 +11,14 @@ import React, { PropsWithChildren } from "react"; declare module "react" { // Fix forwardRef types for Generic components - https://stackoverflow.com/a/58473012 function forwardRef( - render: (props: PropsWithChildren

, ref: React.ForwardedRef) => React.ReactElement | null, - ): (props: P & React.RefAttributes) => React.ReactElement | null; + render: (props: PropsWithChildren

, ref: React.ForwardedRef) => React.ReactElement | null, + ): (props: P & React.RefAttributes) => React.ReactElement | null; // Fix lazy types - https://stackoverflow.com/a/71017028 - function lazy>(factory: () => Promise<{ default: T }>): T; + // function lazy>(factory: () => Promise<{ default: T }>): T; + + // Workaround for generics in React 19 + interface FunctionComponent { + defaultProps?: {}; + } } diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index 3146a9eb078..61343899bef 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { LegacyRef, ReactNode } from "react"; +import React, { Ref, ReactNode, type JSX } from "react"; import sanitizeHtml from "sanitize-html"; import classNames from "classnames"; import katex from "katex"; @@ -503,7 +503,7 @@ export function bodyToHtml(content: IContent, highlights: Optional, op export function topicToHtml( topic?: string, htmlTopic?: string, - ref?: LegacyRef, + ref?: Ref, allowExtendedHtml = false, ): ReactNode { if (!SettingsStore.getValue("feature_html_topic")) { diff --git a/src/Linkify.tsx b/src/Linkify.tsx index d980c496c4f..f0ba3a44506 100644 --- a/src/Linkify.tsx +++ b/src/Linkify.tsx @@ -205,7 +205,7 @@ export const sanitizeHtmlParams: IExtendedSanitizeOptions = { }; /* Wrapper around linkify-react merging in our default linkify options */ -export function Linkify({ as, options, children }: React.ComponentProps): ReactElement { +export function Linkify({ as, options, children }: React.ComponentProps): ReactElement { return ( <_Linkify as={as} options={merge({}, linkifyMatrixOptions, options)}> {children} diff --git a/src/NodeAnimator.tsx b/src/NodeAnimator.tsx index 3ca098311fc..d723b989140 100644 --- a/src/NodeAnimator.tsx +++ b/src/NodeAnimator.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { Key, MutableRefObject, ReactElement, RefCallback } from "react"; +import React, { HTMLAttributes, Key, MutableRefObject, ReactElement, RefCallback } from "react"; interface IChildProps { style: React.CSSProperties; @@ -23,7 +23,7 @@ interface IProps { innerRef?: MutableRefObject; } -function isReactElement(c: ReturnType<(typeof React.Children)["toArray"]>[number]): c is ReactElement { +function isReactElement(c: ReturnType<(typeof React.Children)["toArray"]>[number]): c is ReactElement { return typeof c === "object" && "type" in c; } @@ -36,7 +36,7 @@ function isReactElement(c: ReturnType<(typeof React.Children)["toArray"]>[number */ export default class NodeAnimator extends React.Component { private nodes: Record = {}; - private children: { [key: string]: ReactElement } = {}; + private children: { [key: string]: ReactElement } = {}; public static defaultProps: Partial = { startStyles: [], }; @@ -68,21 +68,22 @@ export default class NodeAnimator extends React.Component { this.children = {}; React.Children.toArray(newChildren).forEach((c) => { if (!isReactElement(c)) return; + const props = c.props as HTMLAttributes; if (oldChildren[c.key!]) { const old = oldChildren[c.key!]; const oldNode = this.nodes[old.key!]; - if (oldNode && oldNode.style.left !== c.props.style.left) { - this.applyStyles(oldNode, { left: c.props.style.left }); + if (oldNode && oldNode.style.left !== props.style!.left) { + this.applyStyles(oldNode, { left: props.style!.left }); } // clone the old element with the props (and children) of the new element // so prop updates are still received by the children. - this.children[c.key!] = React.cloneElement(old, c.props, c.props.children); + this.children[c.key!] = React.cloneElement(old, props, props.children); } else { // new element. If we have a startStyle, use that as the style and go through // the enter animations const newProps: Partial = {}; - const restingStyle = c.props.style; + const restingStyle = props.style!; const startStyles = this.props.startStyles; if (startStyles.length > 0) { diff --git a/src/accessibility/RovingTabIndex.tsx b/src/accessibility/RovingTabIndex.tsx index d35a0291c3e..7ad04c37cac 100644 --- a/src/accessibility/RovingTabIndex.tsx +++ b/src/accessibility/RovingTabIndex.tsx @@ -212,7 +212,7 @@ export const RovingTabIndexProvider: React.FC = ({ scrollIntoView, onKeyDown, }) => { - const [state, dispatch] = useReducer>(reducer, { + const [state, dispatch] = useReducer(reducer, { nodes: [], }); @@ -354,7 +354,7 @@ export const RovingTabIndexProvider: React.FC = ({ * nodeRef = inputRef when inputRef argument is provided. */ export const useRovingTabIndex = ( - inputRef?: RefObject, + inputRef?: RefObject, ): [FocusHandler, boolean, RefCallback, RefObject] => { const context = useContext(RovingTabIndexContext); diff --git a/src/accessibility/context_menu/ContextMenuButton.tsx b/src/accessibility/context_menu/ContextMenuButton.tsx index d8c7d912c1b..64c8b11d3c1 100644 --- a/src/accessibility/context_menu/ContextMenuButton.tsx +++ b/src/accessibility/context_menu/ContextMenuButton.tsx @@ -12,21 +12,21 @@ import React, { ComponentProps, forwardRef, Ref } from "react"; import AccessibleButton from "../../components/views/elements/AccessibleButton"; -type Props = ComponentProps> & { +type Props = ComponentProps> & { label?: string; // whether the context menu is currently open isExpanded: boolean; }; // Semantic component for representing the AccessibleButton which launches a -export const ContextMenuButton = forwardRef(function ( +export const ContextMenuButton = forwardRef(function ( { label, isExpanded, children, onClick, onContextMenu, element, ...props }: Props, ref: Ref, ) { return ( = ComponentProps> & { +type Props = ComponentProps> & { // whether the context menu is currently open isExpanded: boolean; }; // Semantic component for representing the AccessibleButton which launches a -export const ContextMenuTooltipButton = forwardRef(function ( +export const ContextMenuTooltipButton = forwardRef(function ( { isExpanded, children, onClick, onContextMenu, element, ...props }: Props, ref: Ref, ) { return ( { +type IProps = React.ComponentProps> & { label?: string; -} +}; // Semantic component for representing a role=menuitem -export const MenuItem: React.FC = ({ children, label, ...props }) => { +export const MenuItem = ({ + children, + label, + ...props +}: IProps): JSX.Element => { const ariaLabel = props["aria-label"] || label; return ( diff --git a/src/accessibility/roving/RovingAccessibleButton.tsx b/src/accessibility/roving/RovingAccessibleButton.tsx index f50fb010ae3..432b8a9bc2f 100644 --- a/src/accessibility/roving/RovingAccessibleButton.tsx +++ b/src/accessibility/roving/RovingAccessibleButton.tsx @@ -6,22 +6,19 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps } from "react"; +import React, { ComponentProps, type JSX } from "react"; import AccessibleButton from "../../components/views/elements/AccessibleButton"; import { useRovingTabIndex } from "../RovingTabIndex"; import { Ref } from "./types"; -type Props = Omit< - ComponentProps>, - "inputRef" | "tabIndex" -> & { +type Props = Omit>, "inputRef" | "tabIndex"> & { inputRef?: Ref; focusOnMouseOver?: boolean; }; // Wrapper to allow use of useRovingTabIndex for simple AccessibleButtons outside of React Functional Components. -export const RovingAccessibleButton = ({ +export const RovingAccessibleButton = ({ inputRef, onFocus, onMouseOver, @@ -33,7 +30,7 @@ export const RovingAccessibleButton = ({ return ( { onFocusInternal(); onFocus?.(event); diff --git a/src/accessibility/roving/types.ts b/src/accessibility/roving/types.ts index 98b498844b3..748912521c2 100644 --- a/src/accessibility/roving/types.ts +++ b/src/accessibility/roving/types.ts @@ -8,6 +8,6 @@ Please see LICENSE files in the repository root for full details. import { RefObject } from "react"; -export type Ref = RefObject; +export type Ref = RefObject; export type FocusHandler = () => void; diff --git a/src/async-components/structures/ErrorView.tsx b/src/async-components/structures/ErrorView.tsx index 5e60b8e67cb..4b8a743eead 100644 --- a/src/async-components/structures/ErrorView.tsx +++ b/src/async-components/structures/ErrorView.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { Text, Heading, Button, Separator } from "@vector-im/compound-web"; import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out"; diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx index 9608abc4bcd..f9829d6fcc8 100644 --- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx +++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx index 932f6d7fcf8..1154ea510ca 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { createRef, type JSX } from "react"; import FileSaver from "file-saver"; import { logger } from "matrix-js-sdk/src/logger"; import { AuthDict, CrossSigningKeys, MatrixError, UIAFlow, UIAResponse } from "matrix-js-sdk/src/matrix"; diff --git a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.tsx b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.tsx index 673ff5e3990..9d6dadb0f35 100644 --- a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.tsx +++ b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.tsx @@ -178,7 +178,9 @@ export default class ExportE2eKeysDialog extends React.Component type="password" disabled={disableForm} autoComplete="new-password" - fieldRef={(field) => (this.fieldPassword = field)} + fieldRef={(field) => { + this.fieldPassword = field; + }} />

@@ -195,7 +197,9 @@ export default class ExportE2eKeysDialog extends React.Component type="password" disabled={disableForm} autoComplete="new-password" - fieldRef={(field) => (this.fieldPasswordConfirm = field)} + fieldRef={(field) => { + this.fieldPasswordConfirm = field; + }} />
diff --git a/src/autocomplete/Autocompleter.ts b/src/autocomplete/Autocompleter.ts index b2a2b1e13e3..fd5fac499b1 100644 --- a/src/autocomplete/Autocompleter.ts +++ b/src/autocomplete/Autocompleter.ts @@ -30,7 +30,7 @@ export interface ICompletion { type?: "at-room" | "command" | "community" | "room" | "user"; completion: string; completionId?: string; - component: ReactElement; + component: ReactElement; range: ISelectionRange; command?: string; suffix?: string; diff --git a/src/components/structures/AutoHideScrollbar.tsx b/src/components/structures/AutoHideScrollbar.tsx index 549fbf4592b..a5f98b6048d 100644 --- a/src/components/structures/AutoHideScrollbar.tsx +++ b/src/components/structures/AutoHideScrollbar.tsx @@ -8,16 +8,11 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { HTMLAttributes, ReactHTML, ReactNode, WheelEvent } from "react"; +import React, { ReactNode, WheelEvent } from "react"; -type DynamicHtmlElementProps = - JSX.IntrinsicElements[T] extends HTMLAttributes<{}> ? DynamicElementProps : DynamicElementProps<"div">; -type DynamicElementProps = Partial>; - -export type IProps = Omit, "onScroll"> & { - element: T; +export type IProps = React.ComponentPropsWithoutRef & { + element?: T; className?: string; - onScroll?: (event: Event) => void; onWheel?: (event: WheelEvent) => void; style?: React.CSSProperties; tabIndex?: number; @@ -25,12 +20,8 @@ export type IProps = Omit extends React.Component> { - public static defaultProps = { - element: "div" as keyof ReactHTML, - }; - - public readonly containerRef: React.RefObject = React.createRef(); +export default class AutoHideScrollbar extends React.Component> { + public readonly containerRef: React.RefObject = React.createRef(); public componentDidMount(): void { if (this.containerRef.current && this.props.onScroll) { @@ -55,7 +46,7 @@ export default class AutoHideScrollbar ex const { element, className, onScroll, tabIndex, wrappedRef, children, ...otherProps } = this.props; return React.createElement( - element, + element ?? "div", { ...otherProps, ref: this.containerRef, diff --git a/src/components/structures/AutocompleteInput.tsx b/src/components/structures/AutocompleteInput.tsx index 5e930d5f1b0..283826e1357 100644 --- a/src/components/structures/AutocompleteInput.tsx +++ b/src/components/structures/AutocompleteInput.tsx @@ -22,8 +22,8 @@ interface AutocompleteInputProps { selection: ICompletion[]; onSelectionChange: (selection: ICompletion[]) => void; maxSuggestions?: number; - renderSuggestion?: (s: ICompletion) => ReactElement; - renderSelection?: (m: ICompletion) => ReactElement; + renderSuggestion?: (s: ICompletion) => ReactElement; + renderSelection?: (m: ICompletion) => ReactElement; additionalFilter?: (suggestion: ICompletion) => boolean; } @@ -163,11 +163,11 @@ export const AutocompleteInput: React.FC = ({ type SelectionItemProps = { item: ICompletion; onClick: (completion: ICompletion) => void; - render?: (completion: ICompletion) => ReactElement; + render?: (completion: ICompletion) => ReactElement; }; const SelectionItem: React.FC = ({ item, onClick, render }) => { - const withContainer = (children: ReactNode): ReactElement => ( + const withContainer = (children: ReactNode): ReactElement => ( void; - render?: (completion: ICompletion) => ReactElement; + render?: (completion: ICompletion) => ReactElement; }; const SuggestionItem: React.FC = ({ item, selection, onClick, render }) => { @@ -204,7 +204,7 @@ const SuggestionItem: React.FC = ({ item, selection, onClic "mx_AutocompleteInput_suggestion--selected": isSelected, }); - const withContainer = (children: ReactNode): ReactElement => ( + const withContainer = (children: ReactNode): ReactElement => (
= [ boolean, - RefObject, + RefObject, (ev?: SyntheticEvent) => void, (ev?: SyntheticEvent) => void, (val: boolean) => void, ]; // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint -export const useContextMenu = (inputRef?: RefObject): ContextMenuTuple => { +export const useContextMenu = (inputRef?: RefObject): ContextMenuTuple => { let button = useRef(null); if (inputRef) { // if we are given a ref, use it instead of ours diff --git a/src/components/structures/EmbeddedPage.tsx b/src/components/structures/EmbeddedPage.tsx index c471565d912..6773c44de48 100644 --- a/src/components/structures/EmbeddedPage.tsx +++ b/src/components/structures/EmbeddedPage.tsx @@ -40,8 +40,8 @@ export default class EmbeddedPage extends React.PureComponent { private unmounted = false; private dispatcherRef?: string; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { page: "", diff --git a/src/components/structures/GenericDropdownMenu.tsx b/src/components/structures/GenericDropdownMenu.tsx index b323d9b8ade..02a88bd5565 100644 --- a/src/components/structures/GenericDropdownMenu.tsx +++ b/src/components/structures/GenericDropdownMenu.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { FunctionComponent, Key, PropsWithChildren, ReactNode } from "react"; +import React, { FunctionComponent, Key, PropsWithChildren, ReactNode, type JSX } from "react"; import { MenuItemRadio } from "../../accessibility/context_menu/MenuItemRadio"; import { ButtonEvent } from "../views/elements/AccessibleButton"; diff --git a/src/components/structures/HomePage.tsx b/src/components/structures/HomePage.tsx index 31deb381ddd..5b169f640e1 100644 --- a/src/components/structures/HomePage.tsx +++ b/src/components/structures/HomePage.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import * as React from "react"; -import { useContext, useState } from "react"; +import { useContext, useState, type JSX } from "react"; import AutoHideScrollbar from "./AutoHideScrollbar"; import { getHomePageUrl } from "../../utils/pages"; diff --git a/src/components/structures/IndicatorScrollbar.tsx b/src/components/structures/IndicatorScrollbar.tsx index 2c1db504b1c..b64995e6d56 100644 --- a/src/components/structures/IndicatorScrollbar.tsx +++ b/src/components/structures/IndicatorScrollbar.tsx @@ -5,13 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { ComponentProps, createRef } from "react"; -import AutoHideScrollbar, { IProps as AutoHideScrollbarProps } from "./AutoHideScrollbar"; +import AutoHideScrollbar from "./AutoHideScrollbar"; import UIStore, { UI_EVENTS } from "../../stores/UIStore"; -export type IProps = Omit, "onWheel" | "element"> & { - element?: T; +export type IProps = Omit>, "onWheel"> & { // If true, the scrollbar will append mx_IndicatorScrollbar_leftOverflowIndicator // and mx_IndicatorScrollbar_rightOverflowIndicator elements to the list for positioning // by the parent element. @@ -30,10 +29,7 @@ interface IState { rightIndicatorOffset: string; } -export default class IndicatorScrollbar extends React.Component< - IProps, - IState -> { +export default class IndicatorScrollbar extends React.Component, IState> { private autoHideScrollbar = createRef>(); private scrollElement?: HTMLDivElement; private likelyTrackpadUser: boolean | null = null; diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index 49d0f570a5c..94e6e275007 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import * as React from "react"; -import { createRef } from "react"; +import { createRef, type JSX } from "react"; import classNames from "classnames"; import dis from "../../dispatcher/dispatcher"; diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 019f9cd1a84..975c5dc09ab 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -123,9 +123,9 @@ class LoggedInView extends React.Component { public static displayName = "LoggedInView"; protected readonly _matrixClient: MatrixClient; - protected readonly _roomView: React.RefObject; - protected readonly _resizeContainer: React.RefObject; - protected readonly resizeHandler: React.RefObject; + protected readonly _roomView: React.RefObject; + protected readonly _resizeContainer: React.RefObject; + protected readonly resizeHandler: React.RefObject; protected layoutWatcherRef?: string; protected compactLayoutWatcherRef?: string; protected backgroundImageWatcherRef?: string; diff --git a/src/components/structures/MainSplit.tsx b/src/components/structures/MainSplit.tsx index 54aa2203549..68b243c4149 100644 --- a/src/components/structures/MainSplit.tsx +++ b/src/components/structures/MainSplit.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { NumberSize, Resizable } from "re-resizable"; import { Direction } from "re-resizable/lib/resizer"; import { WebPanelResize } from "@matrix-org/analytics-events/types/typescript/WebPanelResize"; diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 548dbff983c..56daa6364b4 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, lazy } from "react"; +import React, { createRef, lazy, type JSX } from "react"; import { ClientEvent, createClient, diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index d2133f4f130..540f1f48d00 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, ReactNode, TransitionEvent } from "react"; +import React, { createRef, ReactNode, TransitionEvent, type JSX } from "react"; import classNames from "classnames"; import { Room, MatrixClient, RoomStateEvent, EventStatus, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; @@ -252,8 +252,8 @@ export default class MessagePanel extends React.Component { // A map to allow groupers to maintain consistent keys even if their first event is uprooted due to back-pagination. public grouperKeyMap = new WeakMap(); - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { // previous positions the read marker has been in, so we can diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index 236da25409b..a2d6042a99d 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import NotificationsIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications"; @@ -38,8 +38,8 @@ export default class NotificationPanel extends React.PureComponent(); - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { narrow: false, diff --git a/src/components/structures/PictureInPictureDragger.tsx b/src/components/structures/PictureInPictureDragger.tsx index fe8badd99d2..925c92f557c 100644 --- a/src/components/structures/PictureInPictureDragger.tsx +++ b/src/components/structures/PictureInPictureDragger.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { createRef, type JSX } from "react"; import UIStore, { UI_EVENTS } from "../../stores/UIStore"; import { lerp } from "../../utils/AnimationUtils"; diff --git a/src/components/structures/PipContainer.tsx b/src/components/structures/PipContainer.tsx index c9fabfe0c9e..f0204c0e4e2 100644 --- a/src/components/structures/PipContainer.tsx +++ b/src/components/structures/PipContainer.tsx @@ -280,7 +280,7 @@ class PipContainerInner extends React.Component { } export const PipContainer: React.FC = () => { - const movePersistedElement = useRef<() => void>(); + const movePersistedElement = useRef<() => void>(undefined); return ; }; diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index a1f20162430..d9e1ad3c5c7 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -65,8 +65,8 @@ export default class RightPanel extends React.Component { public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: Props, context: React.ContextType) { - super(props, context); + public constructor(props: Props) { + super(props); this.state = { searchQuery: "", diff --git a/src/components/structures/RoomSearchView.tsx b/src/components/structures/RoomSearchView.tsx index 82146bcc5e0..8c1d5e921e9 100644 --- a/src/components/structures/RoomSearchView.tsx +++ b/src/components/structures/RoomSearchView.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { forwardRef, useCallback, useContext, useEffect, useRef, useState } from "react"; +import React, { forwardRef, useCallback, useContext, useEffect, useRef, useState, type JSX } from "react"; import { ISearchResults, IThreadBundledRelationship, @@ -59,7 +59,7 @@ export const RoomSearchView = forwardRef( const aborted = useRef(false); // A map from room ID to permalink creator const permalinkCreators = useRef(new Map()).current; - const innerRef = useRef(); + const innerRef = useRef(undefined); useEffect(() => { return () => { diff --git a/src/components/structures/RoomStatusBar.tsx b/src/components/structures/RoomStatusBar.tsx index 3bd69148aee..7a032cfc33f 100644 --- a/src/components/structures/RoomStatusBar.tsx +++ b/src/components/structures/RoomStatusBar.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { ClientEvent, EventStatus, @@ -91,8 +91,8 @@ export default class RoomStatusBar extends React.PureComponent { public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { syncState: this.context.getSyncState(), diff --git a/src/components/structures/RoomStatusBarUnsentMessages.tsx b/src/components/structures/RoomStatusBarUnsentMessages.tsx index ab356405b25..0de52ff24ec 100644 --- a/src/components/structures/RoomStatusBarUnsentMessages.tsx +++ b/src/components/structures/RoomStatusBarUnsentMessages.tsx @@ -15,10 +15,10 @@ interface RoomStatusBarUnsentMessagesProps { title: ReactNode; description?: string; notificationState: StaticNotificationState; - buttons: ReactElement; + buttons: ReactElement; } -export const RoomStatusBarUnsentMessages = (props: RoomStatusBarUnsentMessagesProps): ReactElement => { +export const RoomStatusBarUnsentMessages = (props: RoomStatusBarUnsentMessagesProps): ReactElement => { return (
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 772d5698a30..0a904f73d60 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -251,7 +251,7 @@ interface LocalRoomViewProps { localRoom: LocalRoom; resizeNotifier: ResizeNotifier; permalinkCreator: RoomPermalinkCreator; - roomView: RefObject; + roomView: RefObject; onFileDrop: (dataTransfer: DataTransfer) => Promise; mainSplitContentType: MainSplitContentType; } @@ -262,7 +262,7 @@ interface LocalRoomViewProps { * @param {LocalRoomViewProps} props Room view props * @returns {ReactElement} */ -function LocalRoomView(props: LocalRoomViewProps): ReactElement { +function LocalRoomView(props: LocalRoomViewProps): ReactElement { const context = useScopedRoomContext("room"); const room = context.room as LocalRoom; const encryptionEvent = props.localRoom.currentState.getStateEvents(EventType.RoomEncryption)[0]; @@ -280,8 +280,8 @@ function LocalRoomView(props: LocalRoomViewProps): ReactElement { }); }; - let statusBar: ReactElement | null = null; - let composer: ReactElement | null = null; + let statusBar: ReactElement | null = null; + let composer: ReactElement | null = null; if (room.isError) { const buttons = ( @@ -340,7 +340,7 @@ interface ILocalRoomCreateLoaderProps { * @param {ILocalRoomCreateLoaderProps} props Room view props * @return {ReactElement} */ -function LocalRoomCreateLoader(props: ILocalRoomCreateLoaderProps): ReactElement { +function LocalRoomCreateLoader(props: ILocalRoomCreateLoaderProps): ReactElement { const text = _t("room|creating_room_text", { names: props.names }); return (
@@ -374,16 +374,16 @@ export class RoomView extends React.Component { public static contextType = SDKContext; declare public context: React.ContextType; - public constructor(props: IRoomProps, context: React.ContextType) { - super(props, context); + public constructor(props: IRoomProps) { + super(props); this.askToJoinEnabled = SettingsStore.getValue("feature_ask_to_join"); - if (!context.client) { + if (!this.context.client) { throw new Error("Unable to create RoomView without MatrixClient"); } - const llMembers = context.client.hasLazyLoadMembersEnabled(); + const llMembers = this.context.client.hasLazyLoadMembersEnabled(); this.state = { roomId: undefined, roomLoading: true, @@ -417,7 +417,7 @@ export class RoomView extends React.Component { showJoinLeaves: true, showAvatarChanges: true, showDisplaynameChanges: true, - matrixClientIsReady: context.client?.isInitialSyncComplete(), + matrixClientIsReady: this.context.client?.isInitialSyncComplete(), mainSplitContentType: MainSplitContentType.Timeline, timelineRenderingType: TimelineRenderingType.Room, liveTimeline: undefined, diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index 80193fd3383..a294b5ac5e8 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -19,6 +19,7 @@ import React, { useMemo, useRef, useState, + type JSX, } from "react"; import { Room, @@ -134,7 +135,7 @@ const Tile: React.FC = ({ } }; - let button: ReactElement; + let button: ReactElement; if (busy) { button = ( = ({ ); } - let checkbox: ReactElement | undefined; + let checkbox: ReactElement | undefined; if (onToggleClick) { if (hasPermissions) { checkbox = ; @@ -187,7 +188,7 @@ const Tile: React.FC = ({ } } - let avatar: ReactElement; + let avatar: ReactElement; if (joinedRoom) { avatar = ; } else { @@ -233,12 +234,12 @@ const Tile: React.FC = ({ ); } - let joinedSection: ReactElement | undefined; + let joinedSection: ReactElement | undefined; if (joinedRoom) { joinedSection =
{_t("common|joined")}
; } - let suggestedSection: ReactElement | undefined; + let suggestedSection: ReactElement | undefined; if (suggested && (!joinedRoom || hasPermissions)) { suggestedSection = {_t("space|suggested")}; } @@ -619,7 +620,7 @@ const useIntersectionObserver = (callback: () => void): ((element: HTMLDivElemen } }; - const observerRef = useRef(); + const observerRef = useRef(undefined); return (element: HTMLDivElement) => { if (observerRef.current) { observerRef.current.disconnect(); diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index bf0ddb1fe2a..cca8e025590 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details. import { EventType, RoomType, JoinRule, Preset, Room, RoomEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; -import React, { useCallback, useContext, useRef, useState } from "react"; +import React, { useCallback, useContext, useRef, useState, type JSX } from "react"; import MatrixClientContext from "../../contexts/MatrixClientContext"; import createRoom, { IOpts } from "../../createRoom"; @@ -601,13 +601,13 @@ export default class SpaceRoomView extends React.PureComponent { private dispatcherRef?: string; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); let phase = Phase.Landing; const creator = this.props.space.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender(); - const showSetup = this.props.justCreatedOpts && context.getSafeUserId() === creator; + const showSetup = this.props.justCreatedOpts && this.context.getSafeUserId() === creator; if (showSetup) { phase = diff --git a/src/components/structures/SplashPage.tsx b/src/components/structures/SplashPage.tsx index 6ca20fdb3cb..121f421129e 100644 --- a/src/components/structures/SplashPage.tsx +++ b/src/components/structures/SplashPage.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { DetailedHTMLProps, HTMLAttributes, ReactNode } from "react"; +import React, { DetailedHTMLProps, HTMLAttributes, ReactNode, type JSX } from "react"; interface Props extends DetailedHTMLProps, HTMLElement> { className?: string; diff --git a/src/components/structures/TabbedView.tsx b/src/components/structures/TabbedView.tsx index 7678dbf7845..f961f4232e4 100644 --- a/src/components/structures/TabbedView.tsx +++ b/src/components/structures/TabbedView.tsx @@ -18,6 +18,8 @@ import { NonEmptyArray } from "../../@types/common"; import { RovingAccessibleButton, RovingTabIndexProvider } from "../../accessibility/RovingTabIndex"; import { useWindowWidth } from "../../hooks/useWindowWidth"; +import type { JSX } from "react"; + /** * Represents a tab for the TabbedView. */ diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index bc1e26d087a..de2471e5ce3 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, KeyboardEvent } from "react"; +import React, { createRef, KeyboardEvent, type JSX } from "react"; import { Thread, THREAD_RELATION_TYPE, @@ -86,8 +86,8 @@ export default class ThreadView extends React.Component { // Set by setEventId in ctor. private eventId!: string; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.setEventId(this.props.mxEvent); const thread = this.props.room.getThread(this.eventId) ?? undefined; diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index a28089c9895..18f7c779081 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -259,8 +259,8 @@ class TimelinePanel extends React.Component { private callEventGroupers = new Map(); private initialReadMarkerId: string | null = null; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); debuglog("mounting"); diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index c5f8ef841d3..4d940ab4955 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, ReactNode } from "react"; +import React, { createRef, ReactNode, type JSX } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; import { MatrixClientPeg } from "../../MatrixClientPeg"; @@ -81,10 +81,10 @@ export default class UserMenu extends React.Component { private dispatcherRef?: string; private themeWatcherRef?: string; private readonly dndWatcherRef?: string; - private buttonRef: React.RefObject = createRef(); + private buttonRef: React.RefObject = createRef(); - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { contextMenuPosition: null, diff --git a/src/components/structures/UserView.tsx b/src/components/structures/UserView.tsx index ba905099ba5..205ab3dd49a 100644 --- a/src/components/structures/UserView.tsx +++ b/src/components/structures/UserView.tsx @@ -34,8 +34,8 @@ export default class UserView extends React.Component { public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { loading: true, }; diff --git a/src/components/structures/ViewSource.tsx b/src/components/structures/ViewSource.tsx index 3aba3be472f..b026c9b6c2a 100644 --- a/src/components/structures/ViewSource.tsx +++ b/src/components/structures/ViewSource.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import SyntaxHighlight from "../views/elements/SyntaxHighlight"; diff --git a/src/components/structures/WaitingForThirdPartyRoomView.tsx b/src/components/structures/WaitingForThirdPartyRoomView.tsx index cabe92a53d3..9bf6eb661be 100644 --- a/src/components/structures/WaitingForThirdPartyRoomView.tsx +++ b/src/components/structures/WaitingForThirdPartyRoomView.tsx @@ -21,7 +21,7 @@ import SdkConfig from "../../SdkConfig"; import { useScopedRoomContext } from "../../contexts/ScopedRoomContext.tsx"; interface Props { - roomView: RefObject; + roomView: RefObject; resizeNotifier: ResizeNotifier; inviteEvent: MatrixEvent; } diff --git a/src/components/structures/auth/ConfirmSessionLockTheftView.tsx b/src/components/structures/auth/ConfirmSessionLockTheftView.tsx index 38d0d4efcc5..43cc0155d2b 100644 --- a/src/components/structures/auth/ConfirmSessionLockTheftView.tsx +++ b/src/components/structures/auth/ConfirmSessionLockTheftView.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { _t } from "../../../languageHandler"; import SdkConfig from "../../../SdkConfig"; diff --git a/src/components/structures/auth/ForgotPassword.tsx b/src/components/structures/auth/ForgotPassword.tsx index 0cc6fbd04d0..ce5d01f3c53 100644 --- a/src/components/structures/auth/ForgotPassword.tsx +++ b/src/components/structures/auth/ForgotPassword.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { sleep } from "matrix-js-sdk/src/utils"; import { LockSolidIcon, CheckIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; @@ -388,7 +388,9 @@ export default class ForgotPassword extends React.Component { label={_td("auth|change_password_new_label")} value={this.state.password} minScore={PASSWORD_MIN_SCORE} - fieldRef={(field) => (this.fieldPassword = field)} + fieldRef={(field) => { + this.fieldPassword = field; + }} onChange={this.onInputChanged.bind(this, "password")} autoComplete="new-password" /> @@ -399,7 +401,9 @@ export default class ForgotPassword extends React.Component { labelInvalid={_td("auth|reset_password|passwords_mismatch")} value={this.state.password2} password={this.state.password} - fieldRef={(field) => (this.fieldPasswordConfirm = field)} + fieldRef={(field) => { + this.fieldPasswordConfirm = field; + }} onChange={this.onInputChanged.bind(this, "password2")} autoComplete="new-password" /> diff --git a/src/components/structures/auth/Login.tsx b/src/components/structures/auth/Login.tsx index 0a14450e63a..c96eefe298f 100644 --- a/src/components/structures/auth/Login.tsx +++ b/src/components/structures/auth/Login.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import classNames from "classnames"; import { logger } from "matrix-js-sdk/src/logger"; import { SSOFlow, SSOAction } from "matrix-js-sdk/src/matrix"; diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx index 0ae5c933460..5724cae71f9 100644 --- a/src/components/structures/auth/Registration.tsx +++ b/src/components/structures/auth/Registration.tsx @@ -20,7 +20,7 @@ import { SSOAction, RegisterResponse, } from "matrix-js-sdk/src/matrix"; -import React, { Fragment, ReactNode } from "react"; +import React, { Fragment, ReactNode, type JSX } from "react"; import classNames from "classnames"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/structures/auth/SessionLockStolenView.tsx b/src/components/structures/auth/SessionLockStolenView.tsx index edb20188a61..5ec11d73b10 100644 --- a/src/components/structures/auth/SessionLockStolenView.tsx +++ b/src/components/structures/auth/SessionLockStolenView.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import SplashPage from "../SplashPage"; import { _t } from "../../../languageHandler"; diff --git a/src/components/structures/auth/SetupEncryptionBody.tsx b/src/components/structures/auth/SetupEncryptionBody.tsx index 32528fc7e39..9f4eaabc2a9 100644 --- a/src/components/structures/auth/SetupEncryptionBody.tsx +++ b/src/components/structures/auth/SetupEncryptionBody.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { KeyBackupInfo, VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; import { SecretStorageKeyDescription } from "matrix-js-sdk/src/secret-storage"; diff --git a/src/components/structures/auth/SoftLogout.tsx b/src/components/structures/auth/SoftLogout.tsx index db72a0a04bb..00fb03feb0b 100644 --- a/src/components/structures/auth/SoftLogout.tsx +++ b/src/components/structures/auth/SoftLogout.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, SyntheticEvent } from "react"; +import React, { ChangeEvent, SyntheticEvent, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { Optional } from "matrix-events-sdk"; import { LoginFlow, MatrixError, SSOAction, SSOFlow } from "matrix-js-sdk/src/matrix"; @@ -66,8 +66,8 @@ export default class SoftLogout extends React.Component { public static contextType = SDKContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { loginView: LoginView.Loading, diff --git a/src/components/structures/auth/header/AuthHeaderContext.tsx b/src/components/structures/auth/header/AuthHeaderContext.tsx index 97d587f40bd..e407be0f436 100644 --- a/src/components/structures/auth/header/AuthHeaderContext.tsx +++ b/src/components/structures/auth/header/AuthHeaderContext.tsx @@ -6,13 +6,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import { createContext, Dispatch, ReducerAction, ReducerState } from "react"; +import { createContext, Dispatch, ReducerState } from "react"; -import type { AuthHeaderReducer } from "./AuthHeaderProvider"; +import type { AuthHeaderAction, AuthHeaderReducer } from "./AuthHeaderProvider"; interface AuthHeaderContextType { state: ReducerState; - dispatch: Dispatch>; + dispatch: Dispatch; } export const AuthHeaderContext = createContext(undefined); diff --git a/src/components/structures/auth/header/AuthHeaderDisplay.tsx b/src/components/structures/auth/header/AuthHeaderDisplay.tsx index 479e982c9b8..20c5a14284b 100644 --- a/src/components/structures/auth/header/AuthHeaderDisplay.tsx +++ b/src/components/structures/auth/header/AuthHeaderDisplay.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { Fragment, PropsWithChildren, ReactNode, useContext } from "react"; +import React, { Fragment, PropsWithChildren, ReactNode, useContext, type JSX } from "react"; import { AuthHeaderContext } from "./AuthHeaderContext"; diff --git a/src/components/structures/auth/header/AuthHeaderProvider.tsx b/src/components/structures/auth/header/AuthHeaderProvider.tsx index 0bf50282748..ceabb12e5fb 100644 --- a/src/components/structures/auth/header/AuthHeaderProvider.tsx +++ b/src/components/structures/auth/header/AuthHeaderProvider.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { isEqual } from "lodash"; -import React, { ComponentProps, PropsWithChildren, Reducer, useReducer } from "react"; +import React, { ComponentProps, PropsWithChildren, Reducer, useReducer, type JSX } from "react"; import { AuthHeaderContext } from "./AuthHeaderContext"; import { AuthHeaderModifier } from "./AuthHeaderModifier"; @@ -17,7 +17,7 @@ export enum AuthHeaderActionType { Remove, } -interface AuthHeaderAction { +export interface AuthHeaderAction { type: AuthHeaderActionType; value: ComponentProps; } @@ -25,7 +25,7 @@ interface AuthHeaderAction { export type AuthHeaderReducer = Reducer[], AuthHeaderAction>; export function AuthHeaderProvider({ children }: PropsWithChildren<{}>): JSX.Element { - const [state, dispatch] = useReducer( + const [state, dispatch] = useReducer( (state: ComponentProps[], action: AuthHeaderAction) => { switch (action.type) { case AuthHeaderActionType.Add: diff --git a/src/components/utils/Box.tsx b/src/components/utils/Box.tsx index b48b13aa0fb..8be88022563 100644 --- a/src/components/utils/Box.tsx +++ b/src/components/utils/Box.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef, type JSX } from "react"; type FlexProps = { /** @@ -71,7 +71,7 @@ export function Box({ children, ...props }: React.PropsWithChildren): JSX.Element { - const ref = useRef(); + const ref = useRef(undefined); useEffect(() => { addOrRemoveProperty(ref, `--mx-box-flex`, flex); diff --git a/src/components/utils/Flex.tsx b/src/components/utils/Flex.tsx index 852ebb7e40b..2f7ac4b6735 100644 --- a/src/components/utils/Flex.tsx +++ b/src/components/utils/Flex.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef, type JSX } from "react"; type FlexProps = { /** @@ -64,7 +64,7 @@ export function Flex({ children, ...props }: React.PropsWithChildren): JSX.Element { - const ref = useRef(); + const ref = useRef(undefined); useEffect(() => { ref.current!.style.setProperty(`--mx-flex-display`, display); diff --git a/src/components/views/audio_messages/AudioPlayerBase.tsx b/src/components/views/audio_messages/AudioPlayerBase.tsx index 601611e4223..16a45bafde4 100644 --- a/src/components/views/audio_messages/AudioPlayerBase.tsx +++ b/src/components/views/audio_messages/AudioPlayerBase.tsx @@ -31,8 +31,8 @@ interface IState { } export default abstract class AudioPlayerBase extends React.PureComponent { - protected seekRef: RefObject = createRef(); - protected playPauseRef: RefObject = createRef(); + protected seekRef: RefObject = createRef(); + protected playPauseRef: RefObject = createRef(); public constructor(props: T) { super(props); diff --git a/src/components/views/auth/AuthBody.tsx b/src/components/views/auth/AuthBody.tsx index ea4deb4f127..1c5e115a70d 100644 --- a/src/components/views/auth/AuthBody.tsx +++ b/src/components/views/auth/AuthBody.tsx @@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { PropsWithChildren } from "react"; +import React, { PropsWithChildren, type JSX } from "react"; interface Props { className?: string; diff --git a/src/components/views/auth/AuthFooter.tsx b/src/components/views/auth/AuthFooter.tsx index a792896a886..71f6151fb67 100644 --- a/src/components/views/auth/AuthFooter.tsx +++ b/src/components/views/auth/AuthFooter.tsx @@ -7,12 +7,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactElement } from "react"; +import React, { ReactElement, type JSX } from "react"; import SdkConfig from "../../../SdkConfig"; import { _t } from "../../../languageHandler"; -const AuthFooter = (): ReactElement => { +const AuthFooter = (): ReactElement => { const brandingConfig = SdkConfig.getObject("branding"); const links = brandingConfig?.get("auth_footer_links") ?? [ { text: "Blog", url: "https://element.io/blog" }, diff --git a/src/components/views/auth/AuthHeaderLogo.tsx b/src/components/views/auth/AuthHeaderLogo.tsx index 07cc2f978a1..c61ddfa1eaa 100644 --- a/src/components/views/auth/AuthHeaderLogo.tsx +++ b/src/components/views/auth/AuthHeaderLogo.tsx @@ -11,7 +11,7 @@ import React from "react"; import SdkConfig from "../../../SdkConfig"; export default class AuthHeaderLogo extends React.PureComponent { - public render(): React.ReactElement { + public render(): React.ReactElement { const brandingConfig = SdkConfig.getObject("branding"); const logoUrl = brandingConfig?.get("auth_header_logo_url") ?? "themes/element/img/logos/element-logo.svg"; diff --git a/src/components/views/auth/AuthPage.tsx b/src/components/views/auth/AuthPage.tsx index 2782d0a641b..ee83152a69c 100644 --- a/src/components/views/auth/AuthPage.tsx +++ b/src/components/views/auth/AuthPage.tsx @@ -35,7 +35,7 @@ export default class AuthPage extends React.PureComponent { const pageStyle = { background: `center/cover fixed url(${AuthPage.getWelcomeBackgroundUrl()})`, }; diff --git a/src/components/views/auth/CaptchaForm.tsx b/src/components/views/auth/CaptchaForm.tsx index f216f004fd4..fe2be910339 100644 --- a/src/components/views/auth/CaptchaForm.tsx +++ b/src/components/views/auth/CaptchaForm.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { createRef, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/auth/CountryDropdown.tsx b/src/components/views/auth/CountryDropdown.tsx index a4bf6592bf1..3a18b8aabac 100644 --- a/src/components/views/auth/CountryDropdown.tsx +++ b/src/components/views/auth/CountryDropdown.tsx @@ -149,7 +149,7 @@ export default class CountryDropdown extends React.Component { {country.name} (+{country.prefix})
); - }) as NonEmptyArray; + }) as NonEmptyArray & { key: string }>; // default value here too, otherwise we need to handle null / undefined // values between mounting and the initial value propagating diff --git a/src/components/views/auth/EmailField.tsx b/src/components/views/auth/EmailField.tsx index 1a72872b953..5f437b321f1 100644 --- a/src/components/views/auth/EmailField.tsx +++ b/src/components/views/auth/EmailField.tsx @@ -15,7 +15,7 @@ import * as Email from "../../../email"; interface IProps extends Omit { id?: string; - fieldRef?: RefCallback | RefObject; + fieldRef?: RefCallback | RefObject; value: string; autoFocus?: boolean; diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx index b1360f55604..4bb2eaf2186 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx +++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx @@ -10,7 +10,7 @@ import classNames from "classnames"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { AuthType, AuthDict, IInputs, IStageStatus } from "matrix-js-sdk/src/interactive-auth"; import { logger } from "matrix-js-sdk/src/logger"; -import React, { ChangeEvent, createRef, FormEvent, Fragment } from "react"; +import React, { ChangeEvent, createRef, FormEvent, Fragment, type JSX } from "react"; import { Button, Text } from "@vector-im/compound-web"; import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out"; diff --git a/src/components/views/auth/LanguageSelector.tsx b/src/components/views/auth/LanguageSelector.tsx index c15189b88d7..c2381460e20 100644 --- a/src/components/views/auth/LanguageSelector.tsx +++ b/src/components/views/auth/LanguageSelector.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import SdkConfig from "../../../SdkConfig"; import { getCurrentLanguage } from "../../../languageHandler"; diff --git a/src/components/views/auth/LoginWithQRFlow.tsx b/src/components/views/auth/LoginWithQRFlow.tsx index 33d51f6952a..84c8cadf47b 100644 --- a/src/components/views/auth/LoginWithQRFlow.tsx +++ b/src/components/views/auth/LoginWithQRFlow.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, ReactNode } from "react"; +import React, { createRef, ReactNode, type JSX } from "react"; import { ClientRendezvousFailureReason, MSC4108FailureReason } from "matrix-js-sdk/src/rendezvous"; import ChevronLeftIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-left"; import CheckCircleSolidIcon from "@vector-im/compound-design-tokens/assets/web/icons/check-circle-solid"; diff --git a/src/components/views/auth/PassphraseConfirmField.tsx b/src/components/views/auth/PassphraseConfirmField.tsx index 2b27d3ecaf9..4e46bd9ea2a 100644 --- a/src/components/views/auth/PassphraseConfirmField.tsx +++ b/src/components/views/auth/PassphraseConfirmField.tsx @@ -14,7 +14,7 @@ import { _t, _td, TranslationKey } from "../../../languageHandler"; interface IProps extends Omit { id?: string; - fieldRef?: RefCallback | RefObject; + fieldRef?: RefCallback | RefObject; autoComplete?: string; value: string; password: string; // The password we're confirming diff --git a/src/components/views/auth/PassphraseField.tsx b/src/components/views/auth/PassphraseField.tsx index 90201d1ec13..ac56402f2a0 100644 --- a/src/components/views/auth/PassphraseField.tsx +++ b/src/components/views/auth/PassphraseField.tsx @@ -22,7 +22,7 @@ interface IProps extends Omit { className?: string; minScore: 0 | 1 | 2 | 3 | 4; value: string; - fieldRef?: RefCallback | RefObject; + fieldRef?: RefCallback | RefObject; // Additional strings such as a username used to catch bad passwords userInputs?: string[]; diff --git a/src/components/views/auth/PasswordLogin.tsx b/src/components/views/auth/PasswordLogin.tsx index c2c1e9382df..227c9fb549f 100644 --- a/src/components/views/auth/PasswordLogin.tsx +++ b/src/components/views/auth/PasswordLogin.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { SyntheticEvent } from "react"; +import React, { SyntheticEvent, type JSX } from "react"; import classNames from "classnames"; import { _t } from "../../../languageHandler"; @@ -411,7 +411,7 @@ export default class PasswordLogin extends React.PureComponent { } return ( -
+ (
{loginType} {loginField} @@ -427,7 +427,9 @@ export default class PasswordLogin extends React.PureComponent { disabled={this.props.busy} autoFocus={autoFocusPassword} onValidate={this.onPasswordValidate} - ref={(field) => (this[LoginField.Password] = field)} + ref={field => { + (this[LoginField.Password] = field); + }} /> {forgotPasswordJsx} {!this.props.busy && ( @@ -439,7 +441,7 @@ export default class PasswordLogin extends React.PureComponent { /> )} -
+
) ); } } diff --git a/src/components/views/auth/RegistrationForm.tsx b/src/components/views/auth/RegistrationForm.tsx index 540e5905a35..b953d5883bc 100644 --- a/src/components/views/auth/RegistrationForm.tsx +++ b/src/components/views/auth/RegistrationForm.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { BaseSyntheticEvent, ComponentProps, ReactNode } from "react"; +import React, { BaseSyntheticEvent, ComponentProps, ReactNode, type JSX } from "react"; import { MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; @@ -456,7 +456,9 @@ export default class RegistrationForm extends React.PureComponent (this[RegistrationField.Email] = field)} + fieldRef={(field) => { + this[RegistrationField.Email] = field; + }} label={emailLabel} value={this.state.email} validationRules={this.validateEmailRules.bind(this)} @@ -471,7 +473,9 @@ export default class RegistrationForm extends React.PureComponent (this[RegistrationField.Password] = field)} + fieldRef={(field) => { + this[RegistrationField.Password] = field; + }} minScore={PASSWORD_MIN_SCORE} value={this.state.password} onChange={this.onPasswordChange} @@ -486,7 +490,9 @@ export default class RegistrationForm extends React.PureComponent (this[RegistrationField.PasswordConfirm] = field)} + fieldRef={(field) => { + this[RegistrationField.PasswordConfirm] = field; + }} autoComplete="new-password" value={this.state.passwordConfirm} password={this.state.password} @@ -514,7 +520,9 @@ export default class RegistrationForm extends React.PureComponent (this[RegistrationField.PhoneNumber] = field)} + ref={(field) => { + this[RegistrationField.PhoneNumber] = field; + }} type="text" label={phoneLabel} value={this.state.phoneNumber} @@ -529,7 +537,9 @@ export default class RegistrationForm extends React.PureComponent (this[RegistrationField.Username] = field)} + ref={(field) => { + this[RegistrationField.Username] = field; + }} type="text" autoFocus={true} label={_t("common|username")} diff --git a/src/components/views/avatars/DecoratedRoomAvatar.tsx b/src/components/views/avatars/DecoratedRoomAvatar.tsx index df8a6c00d80..11f0f668443 100644 --- a/src/components/views/avatars/DecoratedRoomAvatar.tsx +++ b/src/components/views/avatars/DecoratedRoomAvatar.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import { EventType, JoinRule, MatrixEvent, Room, RoomEvent, User, UserEvent } from "matrix-js-sdk/src/matrix"; import { UnstableValue } from "matrix-js-sdk/src/NamespacedValue"; diff --git a/src/components/views/avatars/MemberAvatar.tsx b/src/components/views/avatars/MemberAvatar.tsx index 19df06a249d..ed6e8015bd4 100644 --- a/src/components/views/avatars/MemberAvatar.tsx +++ b/src/components/views/avatars/MemberAvatar.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { forwardRef, ReactNode, Ref, useContext } from "react"; +import React, { forwardRef, ReactNode, Ref, useContext, type JSX } from "react"; import { RoomMember, ResizeMethod } from "matrix-js-sdk/src/matrix"; import dis from "../../../dispatcher/dispatcher"; diff --git a/src/components/views/avatars/SearchResultAvatar.tsx b/src/components/views/avatars/SearchResultAvatar.tsx index ad2b3dd6681..ba2513770f0 100644 --- a/src/components/views/avatars/SearchResultAvatar.tsx +++ b/src/components/views/avatars/SearchResultAvatar.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { RoomMember } from "matrix-js-sdk/src/matrix"; import emailPillAvatar from "../../../../res/img/icon-email-pill-avatar.svg"; diff --git a/src/components/views/avatars/WithPresenceIndicator.tsx b/src/components/views/avatars/WithPresenceIndicator.tsx index 519575d0d5b..ea8033f262d 100644 --- a/src/components/views/avatars/WithPresenceIndicator.tsx +++ b/src/components/views/avatars/WithPresenceIndicator.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode, useEffect, useState } from "react"; +import React, { ReactNode, useEffect, useState, type JSX } from "react"; import { ClientEvent, Room, RoomMember, RoomStateEvent, UserEvent } from "matrix-js-sdk/src/matrix"; import { Tooltip } from "@vector-im/compound-web"; diff --git a/src/components/views/beacon/index.tsx b/src/components/views/beacon/index.tsx index 782a69f98eb..0b9eb3fa472 100644 --- a/src/components/views/beacon/index.tsx +++ b/src/components/views/beacon/index.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. // Exports beacon components which touch maplibre-gs wrapped in React Suspense to enable code splitting -import React, { ComponentProps, lazy, Suspense } from "react"; +import React, { ComponentProps, lazy, Suspense, type JSX } from "react"; import Spinner from "../elements/Spinner"; diff --git a/src/components/views/context_menus/DialpadContextMenu.tsx b/src/components/views/context_menus/DialpadContextMenu.tsx index 72e7e048175..e924bee595a 100644 --- a/src/components/views/context_menus/DialpadContextMenu.tsx +++ b/src/components/views/context_menus/DialpadContextMenu.tsx @@ -24,7 +24,7 @@ interface IState { } export default class DialpadContextMenu extends React.Component { - private numberEntryFieldRef: React.RefObject = createRef(); + private numberEntryFieldRef: React.RefObject = createRef(); public constructor(props: IProps) { super(props); diff --git a/src/components/views/context_menus/IconizedContextMenu.tsx b/src/components/views/context_menus/IconizedContextMenu.tsx index f621d8af87f..092ff8c58a8 100644 --- a/src/components/views/context_menus/IconizedContextMenu.tsx +++ b/src/components/views/context_menus/IconizedContextMenu.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import classNames from "classnames"; import ContextMenu, { @@ -17,6 +17,7 @@ import ContextMenu, { MenuItemRadio, } from "../../structures/ContextMenu"; import { _t } from "../../../languageHandler"; +import AccessibleButton from "../elements/AccessibleButton.tsx"; interface IProps extends IContextMenuProps { className?: string; @@ -31,10 +32,10 @@ interface IOptionListProps { children: ReactNode; } -interface IOptionProps extends React.ComponentProps { +type IOptionProps = React.ComponentProps> & { iconClassName?: string; isDestructive?: boolean; -} +}; interface ICheckboxProps extends React.ComponentProps { iconClassName: string; @@ -110,18 +111,19 @@ export const IconizedContextMenuCheckbox: React.FC = ({ ); }; -export const IconizedContextMenuOption: React.FC = ({ +export const IconizedContextMenuOption = ({ + element, label, className, iconClassName, children, isDestructive, ...props -}) => { +}: IOptionProps): JSX.Element => { return ( private reactButtonRef = createRef(); // XXX Ref to a functional component - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { canRedact: false, @@ -396,7 +396,6 @@ export default class MessageContextMenu extends React.Component openInMapSiteButton = ( = ({ title, spac {space.name || getDisplayAliasForRoom(space) || space.roomId}
); - }) as NonEmptyArray + }) as NonEmptyArray & { key: string }> } ); diff --git a/src/components/views/dialogs/AskInviteAnywayDialog.tsx b/src/components/views/dialogs/AskInviteAnywayDialog.tsx index de8fc5eb3c2..4d33db446aa 100644 --- a/src/components/views/dialogs/AskInviteAnywayDialog.tsx +++ b/src/components/views/dialogs/AskInviteAnywayDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useCallback } from "react"; +import React, { useCallback, type JSX } from "react"; import { _t } from "../../../languageHandler"; import SettingsStore from "../../../settings/SettingsStore"; diff --git a/src/components/views/dialogs/BaseDialog.tsx b/src/components/views/dialogs/BaseDialog.tsx index ccb162e1cba..6d17f0a8878 100644 --- a/src/components/views/dialogs/BaseDialog.tsx +++ b/src/components/views/dialogs/BaseDialog.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import FocusLock from "react-focus-lock"; import classNames from "classnames"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; diff --git a/src/components/views/dialogs/BugReportDialog.tsx b/src/components/views/dialogs/BugReportDialog.tsx index 373f30d3aeb..56503482137 100644 --- a/src/components/views/dialogs/BugReportDialog.tsx +++ b/src/components/views/dialogs/BugReportDialog.tsx @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import SdkConfig from "../../../SdkConfig"; import Modal from "../../../Modal"; @@ -46,7 +46,7 @@ interface IState { export default class BugReportDialog extends React.Component { private unmounted: boolean; - private issueRef: React.RefObject; + private issueRef: React.RefObject; public constructor(props: IProps) { super(props); diff --git a/src/components/views/dialogs/ChangelogDialog.tsx b/src/components/views/dialogs/ChangelogDialog.tsx index ae3c157c788..2be730f8be8 100644 --- a/src/components/views/dialogs/ChangelogDialog.tsx +++ b/src/components/views/dialogs/ChangelogDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { _t } from "../../../languageHandler"; import QuestionDialog from "./QuestionDialog"; diff --git a/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx index cb79f27a2f3..7a119f9d076 100644 --- a/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx +++ b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, useMemo, useState } from "react"; +import React, { ComponentProps, useMemo, useState, type JSX } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; import ConfirmUserActionDialog from "./ConfirmUserActionDialog"; diff --git a/src/components/views/dialogs/CreateRoomDialog.tsx b/src/components/views/dialogs/CreateRoomDialog.tsx index 4d36d016235..51d50786c97 100644 --- a/src/components/views/dialogs/CreateRoomDialog.tsx +++ b/src/components/views/dialogs/CreateRoomDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, createRef, KeyboardEvent, SyntheticEvent } from "react"; +import React, { ChangeEvent, createRef, KeyboardEvent, SyntheticEvent, type JSX } from "react"; import { Room, RoomType, JoinRule, Preset, Visibility } from "matrix-js-sdk/src/matrix"; import SdkConfig from "../../../SdkConfig"; diff --git a/src/components/views/dialogs/CreateSubspaceDialog.tsx b/src/components/views/dialogs/CreateSubspaceDialog.tsx index 6add8127931..9ac3fa71211 100644 --- a/src/components/views/dialogs/CreateSubspaceDialog.tsx +++ b/src/components/views/dialogs/CreateSubspaceDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useRef, useState } from "react"; +import React, { useRef, useState, type JSX } from "react"; import { Room, JoinRule } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/dialogs/DeactivateAccountDialog.tsx b/src/components/views/dialogs/DeactivateAccountDialog.tsx index d68c931cc16..eecf8c007cd 100644 --- a/src/components/views/dialogs/DeactivateAccountDialog.tsx +++ b/src/components/views/dialogs/DeactivateAccountDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { AuthType, IAuthData } from "matrix-js-sdk/src/interactive-auth"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; diff --git a/src/components/views/dialogs/DevtoolsDialog.tsx b/src/components/views/dialogs/DevtoolsDialog.tsx index 7dc683469a8..b8800f2ee6a 100644 --- a/src/components/views/dialogs/DevtoolsDialog.tsx +++ b/src/components/views/dialogs/DevtoolsDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useState } from "react"; +import React, { useState, type JSX } from "react"; import { _t, _td, TranslationKey } from "../../../languageHandler"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; diff --git a/src/components/views/dialogs/ExportDialog.tsx b/src/components/views/dialogs/ExportDialog.tsx index 54c58fe2e4a..1d369a9551d 100644 --- a/src/components/views/dialogs/ExportDialog.tsx +++ b/src/components/views/dialogs/ExportDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useRef, useState, Dispatch, SetStateAction } from "react"; +import React, { useRef, useState, Dispatch, SetStateAction, type JSX } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/dialogs/FeedbackDialog.tsx b/src/components/views/dialogs/FeedbackDialog.tsx index 1e391d80026..6dd6a203f7e 100644 --- a/src/components/views/dialogs/FeedbackDialog.tsx +++ b/src/components/views/dialogs/FeedbackDialog.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useState, type JSX } from "react"; import QuestionDialog from "./QuestionDialog"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/dialogs/ForwardDialog.tsx b/src/components/views/dialogs/ForwardDialog.tsx index 0a0a70d1b5b..eba6da78c89 100644 --- a/src/components/views/dialogs/ForwardDialog.tsx +++ b/src/components/views/dialogs/ForwardDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useEffect, useMemo, useState } from "react"; +import React, { useEffect, useMemo, useState, type JSX } from "react"; import classnames from "classnames"; import { IContent, diff --git a/src/components/views/dialogs/InteractiveAuthDialog.tsx b/src/components/views/dialogs/InteractiveAuthDialog.tsx index 305534e6db8..a2b5548f189 100644 --- a/src/components/views/dialogs/InteractiveAuthDialog.tsx +++ b/src/components/views/dialogs/InteractiveAuthDialog.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixClient, UIAResponse } from "matrix-js-sdk/src/matrix"; import { AuthType } from "matrix-js-sdk/src/interactive-auth"; diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 35e04fb12e2..f90cfe068e9 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, ReactNode, SyntheticEvent } from "react"; +import React, { createRef, ReactNode, SyntheticEvent, type JSX } from "react"; import classNames from "classnames"; import { RoomMember, Room, MatrixError, EventType } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; @@ -343,7 +343,7 @@ export default class InviteDialog extends React.PureComponent(); - private numberEntryFieldRef: React.RefObject = createRef(); + private numberEntryFieldRef: React.RefObject = createRef(); private unmounted = false; private encryptionByDefault = false; private profilesStore: UserProfilesStore; diff --git a/src/components/views/dialogs/MessageEditHistoryDialog.tsx b/src/components/views/dialogs/MessageEditHistoryDialog.tsx index 48564e2411a..3f852c394f9 100644 --- a/src/components/views/dialogs/MessageEditHistoryDialog.tsx +++ b/src/components/views/dialogs/MessageEditHistoryDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent, EventType, RelationType, MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix"; import { defer } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/dialogs/ModalWidgetDialog.tsx b/src/components/views/dialogs/ModalWidgetDialog.tsx index 7df9130a7aa..06a9485dcaa 100644 --- a/src/components/views/dialogs/ModalWidgetDialog.tsx +++ b/src/components/views/dialogs/ModalWidgetDialog.tsx @@ -53,7 +53,7 @@ const MAX_BUTTONS = 3; export default class ModalWidgetDialog extends React.PureComponent { private readonly widget: Widget; private readonly possibleButtons: ModalButtonID[]; - private appFrame: React.RefObject = React.createRef(); + private appFrame: React.RefObject = React.createRef(); public state: IState = { disabledButtonIds: (this.props.widgetDefinition.buttons || []).filter((b) => b.disabled).map((b) => b.id), diff --git a/src/components/views/dialogs/ModuleUiDialog.tsx b/src/components/views/dialogs/ModuleUiDialog.tsx index 7cdb0190d0c..f9f02f42bac 100644 --- a/src/components/views/dialogs/ModuleUiDialog.tsx +++ b/src/components/views/dialogs/ModuleUiDialog.tsx @@ -16,7 +16,7 @@ import ScrollableBaseModal, { IScrollableBaseState } from "./ScrollableBaseModal import { _t } from "../../../languageHandler"; interface IProps

> { - contentFactory: (props: P, ref: React.RefObject) => React.ReactNode; + contentFactory: (props: P, ref: React.RefObject) => React.ReactNode; additionalContentProps: Omit | undefined; initialOptions: ModuleUiDialogOptions; moduleApi: ModuleApi; diff --git a/src/components/views/dialogs/ReportEventDialog.tsx b/src/components/views/dialogs/ReportEventDialog.tsx index 3234c2be35b..73722a62008 100644 --- a/src/components/views/dialogs/ReportEventDialog.tsx +++ b/src/components/views/dialogs/ReportEventDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent } from "react"; +import React, { ChangeEvent, type JSX } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/dialogs/RoomUpgradeDialog.tsx b/src/components/views/dialogs/RoomUpgradeDialog.tsx index 337c1a334ca..30cdc5d0791 100644 --- a/src/components/views/dialogs/RoomUpgradeDialog.tsx +++ b/src/components/views/dialogs/RoomUpgradeDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; import Modal from "../../../Modal"; diff --git a/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx b/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx index 48d0bef28cf..f20b88a1929 100644 --- a/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx +++ b/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode, SyntheticEvent } from "react"; +import React, { ReactNode, SyntheticEvent, type JSX } from "react"; import { EventType, JoinRule } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/dialogs/ShareDialog.tsx b/src/components/views/dialogs/ShareDialog.tsx index 1796b79239e..93f298c5b0c 100644 --- a/src/components/views/dialogs/ShareDialog.tsx +++ b/src/components/views/dialogs/ShareDialog.tsx @@ -103,7 +103,7 @@ export function ShareDialog({ target, customTitle, onFinished, permalinkCreator const showQrCode = useSettingValue(UIFeature.ShareQRCode); const showSocials = useSettingValue(UIFeature.ShareSocial); - const timeoutIdRef = useRef(); + const timeoutIdRef = useRef(undefined); const [isCopied, setIsCopied] = useState(false); const [linkToSpecificEvent, setLinkToSpecificEvent] = useState(target instanceof MatrixEvent); diff --git a/src/components/views/dialogs/TermsDialog.tsx b/src/components/views/dialogs/TermsDialog.tsx index 4d66e41b5a6..2dfd4d8732c 100644 --- a/src/components/views/dialogs/TermsDialog.tsx +++ b/src/components/views/dialogs/TermsDialog.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { SERVICE_TYPES } from "matrix-js-sdk/src/matrix"; import { _t, pickBestLanguage } from "../../../languageHandler"; diff --git a/src/components/views/dialogs/UploadConfirmDialog.tsx b/src/components/views/dialogs/UploadConfirmDialog.tsx index 7fdb601c44b..df24101388c 100644 --- a/src/components/views/dialogs/UploadConfirmDialog.tsx +++ b/src/components/views/dialogs/UploadConfirmDialog.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { FilesIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx index 8ae7a302ac4..6eea846f0a3 100644 --- a/src/components/views/dialogs/UserSettingsDialog.tsx +++ b/src/components/views/dialogs/UserSettingsDialog.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. */ import { Toast } from "@vector-im/compound-web"; -import React, { useState } from "react"; +import React, { useState, type JSX } from "react"; import UserProfileIcon from "@vector-im/compound-design-tokens/assets/web/icons/user-profile"; import DevicesIcon from "@vector-im/compound-design-tokens/assets/web/icons/devices"; import VisibilityOnIcon from "@vector-im/compound-design-tokens/assets/web/icons/visibility-on"; @@ -221,7 +221,7 @@ export default function UserSettingsDialog(props: IProps): JSX.Element { // XXX: SDKContext is provided within the LoggedInView subtree. // Modals function outside the MatrixChat React tree, so sdkContext is reprovided here to simulate that. // The longer term solution is to move our ModalManager into the React tree to inherit contexts properly. - + ( - + ) ); } diff --git a/src/components/views/dialogs/devtools/FilteredList.tsx b/src/components/views/dialogs/devtools/FilteredList.tsx index 400c646958c..cf52770c804 100644 --- a/src/components/views/dialogs/devtools/FilteredList.tsx +++ b/src/components/views/dialogs/devtools/FilteredList.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, useEffect, useState } from "react"; +import React, { ChangeEvent, useEffect, useState, type JSX } from "react"; import { _t } from "../../../../languageHandler"; import Field from "../../elements/Field"; @@ -17,14 +17,14 @@ const INITIAL_LOAD_TILES = 20; const LOAD_TILES_STEP_SIZE = 50; interface IProps { - children: React.ReactElement[]; + children: React.ReactElement[]; query: string; onChange(value: string): void; } const FilteredList: React.FC = ({ children, query, onChange }) => { const [truncateAt, setTruncateAt] = useState(INITIAL_LOAD_TILES); - const [filteredChildren, setFilteredChildren] = useState(children); + const [filteredChildren, setFilteredChildren] = useState[]>(children); useEffect(() => { let filteredChildren = children; @@ -36,7 +36,7 @@ const FilteredList: React.FC = ({ children, query, onChange }) => { setTruncateAt(INITIAL_LOAD_TILES); }, [children, query]); - const getChildren = (start: number, end: number): React.ReactElement[] => { + const getChildren = (start: number, end: number): React.ReactElement[] => { return filteredChildren.slice(start, end); }; diff --git a/src/components/views/dialogs/devtools/RoomNotifications.tsx b/src/components/views/dialogs/devtools/RoomNotifications.tsx index 1bcff784879..d25eda080c4 100644 --- a/src/components/views/dialogs/devtools/RoomNotifications.tsx +++ b/src/components/views/dialogs/devtools/RoomNotifications.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { NotificationCountType, Room, Thread, ReceiptType } from "matrix-js-sdk/src/matrix"; -import React, { useContext } from "react"; +import React, { useContext, type JSX } from "react"; import { ReadReceipt } from "matrix-js-sdk/src/models/read-receipt"; import MatrixClientContext from "../../../../contexts/MatrixClientContext"; diff --git a/src/components/views/dialogs/devtools/ServerInfo.tsx b/src/components/views/dialogs/devtools/ServerInfo.tsx index 337ed421770..2214cd108b9 100644 --- a/src/components/views/dialogs/devtools/ServerInfo.tsx +++ b/src/components/views/dialogs/devtools/ServerInfo.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useContext } from "react"; +import React, { useContext, type JSX } from "react"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; import BaseTool, { IDevtoolsProps } from "./BaseTool"; diff --git a/src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx b/src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx index d2003473b9f..1e0f59d1a99 100644 --- a/src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx +++ b/src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { IPublicRoomsChunkRoom } from "matrix-js-sdk/src/matrix"; import { linkifyAndSanitizeHtml } from "../../../../HtmlUtils"; diff --git a/src/components/views/dialogs/spotlight/RoomResultContextMenus.tsx b/src/components/views/dialogs/spotlight/RoomResultContextMenus.tsx index 667cc7980a7..adf7298096d 100644 --- a/src/components/views/dialogs/spotlight/RoomResultContextMenus.tsx +++ b/src/components/views/dialogs/spotlight/RoomResultContextMenus.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import classNames from "classnames"; import { Room } from "matrix-js-sdk/src/matrix"; -import React, { Fragment, useState } from "react"; +import React, { Fragment, useState, type JSX } from "react"; import { ContextMenuTooltipButton } from "../../../../accessibility/context_menu/ContextMenuTooltipButton"; import { useNotificationState } from "../../../../hooks/useRoomNotificationState"; diff --git a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx index 20d6825b9b7..bbd1071c5d5 100644 --- a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx +++ b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx @@ -20,7 +20,16 @@ import { } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { normalize } from "matrix-js-sdk/src/utils"; -import React, { ChangeEvent, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; +import React, { + ChangeEvent, + useCallback, + useContext, + useEffect, + useMemo, + useRef, + useState, + type JSX, +} from "react"; import sanitizeHtml from "sanitize-html"; import { KeyBindingAction } from "../../../../accessibility/KeyboardShortcuts"; diff --git a/src/components/views/dialogs/spotlight/TooltipOption.tsx b/src/components/views/dialogs/spotlight/TooltipOption.tsx index 1d60fed5b30..64bb1d79773 100644 --- a/src/components/views/dialogs/spotlight/TooltipOption.tsx +++ b/src/components/views/dialogs/spotlight/TooltipOption.tsx @@ -7,18 +7,18 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { useRovingTabIndex } from "../../../../accessibility/RovingTabIndex"; import AccessibleButton, { ButtonProps } from "../../elements/AccessibleButton"; import { Ref } from "../../../../accessibility/roving/types"; -type TooltipOptionProps = ButtonProps & { +type TooltipOptionProps = ButtonProps & { endAdornment?: ReactNode; inputRef?: Ref; }; -export const TooltipOption = ({ +export const TooltipOption = ({ inputRef, className, element, @@ -34,7 +34,7 @@ export const TooltipOption = ({ tabIndex={-1} aria-selected={isActive} role="option" - element={element as keyof JSX.IntrinsicElements} + element={element as React.ElementType} /> ); }; diff --git a/src/components/views/elements/AccessibleButton.tsx b/src/components/views/elements/AccessibleButton.tsx index b8b5297384c..ca7fa7856ae 100644 --- a/src/components/views/elements/AccessibleButton.tsx +++ b/src/components/views/elements/AccessibleButton.tsx @@ -6,14 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, forwardRef, FunctionComponent, HTMLAttributes, InputHTMLAttributes, Ref } from "react"; +import React, { ComponentProps, ComponentPropsWithRef, FunctionComponent, type JSX, PropsWithChildren } from "react"; import classnames from "classnames"; import { Tooltip } from "@vector-im/compound-web"; import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; -export type ButtonEvent = React.MouseEvent | React.KeyboardEvent | React.FormEvent; +export type ButtonEvent = React.MouseEvent | React.KeyboardEvent | React.FormEvent; /** * The kind of button, similar to how Bootstrap works. @@ -46,25 +46,11 @@ export type AccessibleButtonKind = * * To remain compatible with existing code, we’ll continue to support InputHTMLAttributes */ -type DynamicHtmlElementProps = - JSX.IntrinsicElements[T] extends HTMLAttributes<{}> ? DynamicElementProps : DynamicElementProps<"div">; -type DynamicElementProps = Partial< - Omit -> & - Omit, "onClick">; - -type TooltipProps = ComponentProps; - -/** - * Type of props accepted by {@link AccessibleButton}. - * - * Extends props accepted by the underlying element specified using the `element` prop. - */ -type Props = DynamicHtmlElementProps & { +type ButtonOwnProps = PropsWithChildren<{ /** * The base element type. "div" by default. */ - element?: T; + element?: C; /** * The kind of button, similar to how Bootstrap works. */ @@ -80,7 +66,7 @@ type Props = DynamicHtmlElementProps & /** * Event handler for button activation. Should be implemented exactly like a normal `onClick` handler. */ - onClick: ((e: ButtonEvent) => void | Promise) | null; + onClick: ((e: ButtonEvent) => void | Promise) | null; /** * The tooltip to show on hover or focus. */ @@ -103,16 +89,46 @@ type Props = DynamicHtmlElementProps & * Whether the tooltip should be disabled. */ disableTooltip?: TooltipProps["disabled"]; -}; +}>; + +// type UnstyledButtonPropsFor = React.ComponentPropsWithoutRef & { +// ref?: React.Ref>; +// }; -export type ButtonProps = Props; +type ButtonPropsFor = ButtonOwnProps & ComponentProps; + +// type DynamicHtmlElementProps = +// JSX.IntrinsicElements[T] extends HTMLAttributes<{}> ? DynamicElementProps : DynamicElementProps<"div">; +// type DynamicElementProps = Partial< +// Omit +// > & +// Omit, "onClick">; + +type TooltipProps = ComponentProps; + +/** + * Type of props accepted by {@link AccessibleButton}. + * + * Extends props accepted by the underlying element specified using the `element` prop. + */ +type Props = ButtonPropsFor; + +export type ButtonProps = Props; + +type SupportedElement = "div"; // | "a" | "button"; /** * Type of the props passed to the element that is rendered by AccessibleButton. */ -interface RenderedElementProps extends React.InputHTMLAttributes { - ref?: React.Ref; -} +type RenderedElementProps = ComponentPropsWithRef & { + // TODO + disabled?: boolean; + + /** + * Event handler for button activation. Should be implemented exactly like a normal `onClick` handler. + */ + onClick: ((e: ButtonEvent) => void | Promise) | null; +}; /** * AccessibleButton is a generic wrapper for any element that should be treated @@ -124,27 +140,27 @@ interface RenderedElementProps extends React.InputHTMLAttributes { * @param {Object} props react element properties * @returns {Object} rendered react */ -const AccessibleButton = forwardRef(function ( - { - element = "div" as T, - onClick, - children, - kind, - disabled, - className, - onKeyDown, - onKeyUp, - triggerOnMouseDown, - title, - caption, - placement = "right", - onTooltipOpenChange, - disableTooltip, - ...restProps - }: Props, - ref: Ref, -): JSX.Element { - const newProps: RenderedElementProps = restProps; +const AccessibleButton = function ({ + element = "div" as T, + onClick, + children, + kind, + disabled, + className, + onKeyDown, + onKeyUp, + triggerOnMouseDown, + title, + caption, + placement = "right", + onTooltipOpenChange, + disableTooltip, + role = "button", + tabIndex = 0, + ref, + ...restProps +}: Props): JSX.Element { + const newProps: RenderedElementProps = { ...restProps, role, tabIndex }; newProps["aria-label"] = newProps["aria-label"] ?? title; if (disabled) { newProps["aria-disabled"] = true; @@ -162,7 +178,7 @@ const AccessibleButton = forwardRef(function { + newProps.onKeyDown = (e: React.KeyboardEvent) => { const action = getKeyBindingsManager().getAccessibilityAction(e); switch (action) { @@ -224,13 +240,9 @@ const AccessibleButton = forwardRef(function { private dispatcherRef?: string; private unmounted = false; - public constructor(props: IProps, context: ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); // The key used for PersistedElement this.persistKey = getPersistKey(WidgetUtils.getWidgetUid(this.props.app)); diff --git a/src/components/views/elements/DialogButtons.tsx b/src/components/views/elements/DialogButtons.tsx index 7b49c9af5ab..7aa1aba59c2 100644 --- a/src/components/views/elements/DialogButtons.tsx +++ b/src/components/views/elements/DialogButtons.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/elements/Dropdown.tsx b/src/components/views/elements/Dropdown.tsx index a7ce84163c7..1eca03d8aa9 100644 --- a/src/components/views/elements/Dropdown.tsx +++ b/src/components/views/elements/Dropdown.tsx @@ -7,7 +7,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, createRef, CSSProperties, ReactElement, ReactNode, Ref } from "react"; +import React, { + ChangeEvent, + createRef, + CSSProperties, + ReactElement, + ReactNode, + Ref, + type JSX, +} from "react"; import classnames from "classnames"; import AccessibleButton, { ButtonEvent } from "./AccessibleButton"; @@ -18,7 +26,7 @@ import { objectHasDiff } from "../../../utils/objects"; import { NonEmptyArray } from "../../../@types/common"; interface IMenuOptionProps { - children: ReactElement; + children: ReactElement; highlighted?: boolean; dropdownKey: string; id?: string; @@ -71,7 +79,7 @@ export interface DropdownProps { value?: string; className?: string; autoComplete?: string; - children: NonEmptyArray; + children: NonEmptyArray & { key: string }>; // negative for consistency with HTML disabled?: boolean; // The width that the dropdown should be. If specified, @@ -149,7 +157,7 @@ export default class Dropdown extends React.Component { document.removeEventListener("click", this.onDocumentClick, false); } - private reindexChildren(children: ReactElement[]): void { + private reindexChildren(children: ReactElement[]): void { this.childrenByKey = {}; React.Children.forEach(children, (child) => { this.childrenByKey[(child as DropdownProps["children"][number]).key] = child; @@ -295,7 +303,7 @@ export default class Dropdown extends React.Component { } private getMenuOptions(): JSX.Element[] { - const options = React.Children.map(this.props.children, (child: ReactElement) => { + const options = React.Children.map(this.props.children, (child: ReactElement) => { const highlighted = this.state.highlightedOption === child.key; return ( { return valid; } - private get inputRef(): RefObject { + private get inputRef(): RefObject { const inputRef = this.props.inputRef; if (typeof inputRef === "function") { // This is a callback ref, so return _inputRef which will point to the actual DOM element. return this._inputRef; } - return (inputRef ?? this._inputRef) as RefObject; + return (inputRef ?? this._inputRef) as RefObject; } private onTooltipOpenChange = (open: boolean): void => { diff --git a/src/components/views/elements/FilterDropdown.tsx b/src/components/views/elements/FilterDropdown.tsx index 9a66ffcea14..f99480006af 100644 --- a/src/components/views/elements/FilterDropdown.tsx +++ b/src/components/views/elements/FilterDropdown.tsx @@ -50,7 +50,7 @@ export const FilterDropdown = ({ ...restProps }: FilterDropdownProps): React.ReactElement> => { return ( - ({ {label} {!!description && {description}}

- )) as NonEmptyArray + )) as NonEmptyArray & { key: string }> } - + ) ); }; diff --git a/src/components/views/elements/FilterTabGroup.tsx b/src/components/views/elements/FilterTabGroup.tsx index 6129cd12195..fba82a57cbb 100644 --- a/src/components/views/elements/FilterTabGroup.tsx +++ b/src/components/views/elements/FilterTabGroup.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { FieldsetHTMLAttributes, ReactNode } from "react"; +import React, { FieldsetHTMLAttributes, ReactNode, type JSX } from "react"; export type FilterTab = { label: string | ReactNode; diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 711a221994f..fc23184f9f8 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, CSSProperties, useRef, useState } from "react"; +import React, { createRef, CSSProperties, useRef, useState, type JSX } from "react"; import FocusLock from "react-focus-lock"; import { MatrixEvent, parseErrorResponse } from "matrix-js-sdk/src/matrix"; @@ -585,7 +585,7 @@ export default class ImageView extends React.Component { function DownloadButton({ url, fileName }: { url: string; fileName?: string }): JSX.Element { const downloader = useRef(new FileDownloader()).current; const [loading, setLoading] = useState(false); - const blobRef = useRef(); + const blobRef = useRef(undefined); function showError(e: unknown): void { Modal.createDialog(ErrorDialog, { diff --git a/src/components/views/elements/JoinRuleDropdown.tsx b/src/components/views/elements/JoinRuleDropdown.tsx index 19afdc828c9..9b277a90ed8 100644 --- a/src/components/views/elements/JoinRuleDropdown.tsx +++ b/src/components/views/elements/JoinRuleDropdown.tsx @@ -41,7 +41,7 @@ const JoinRuleDropdown: React.FC = ({
{labelPublic}
, - ] as NonEmptyArray; + ] as NonEmptyArray & { key: string }>; if (labelKnock) { options.unshift( @@ -50,7 +50,7 @@ const JoinRuleDropdown: React.FC = ({ {labelKnock}
- ) as ReactElement & { key: string }, + ) as ReactElement & { key: string }, ); } @@ -60,7 +60,7 @@ const JoinRuleDropdown: React.FC = ({
{labelRestricted}
- ) as ReactElement & { key: string }, + ) as ReactElement & { key: string }, ); } diff --git a/src/components/views/elements/LanguageDropdown.tsx b/src/components/views/elements/LanguageDropdown.tsx index 27b4b2b31ce..e13406e8fed 100644 --- a/src/components/views/elements/LanguageDropdown.tsx +++ b/src/components/views/elements/LanguageDropdown.tsx @@ -101,7 +101,7 @@ export default class LanguageDropdown extends React.Component { const options = displayedLanguages.map((language) => { return
{language.labelInTargetLanguage}
; - }) as NonEmptyArray; + }) as NonEmptyArray & { key: string }>; // default value here too, otherwise we need to handle null / undefined // values between mounting and the initial value propagating diff --git a/src/components/views/elements/LazyRenderList.tsx b/src/components/views/elements/LazyRenderList.tsx index 996a3981cec..3372a2ec2c4 100644 --- a/src/components/views/elements/LazyRenderList.tsx +++ b/src/components/views/elements/LazyRenderList.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; class ItemRange { public constructor( diff --git a/src/components/views/elements/PersistentApp.tsx b/src/components/views/elements/PersistentApp.tsx index 5f720dc85e8..ae1feb764cf 100644 --- a/src/components/views/elements/PersistentApp.tsx +++ b/src/components/views/elements/PersistentApp.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ContextType, CSSProperties, MutableRefObject, ReactNode } from "react"; +import React, { ContextType, CSSProperties, MutableRefObject, ReactNode, type JSX } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; import WidgetUtils from "../../../utils/WidgetUtils"; @@ -28,9 +28,9 @@ export default class PersistentApp extends React.Component { declare public context: ContextType; private room: Room; - public constructor(props: IProps, context: ContextType) { - super(props, context); - this.room = context.getRoom(this.props.persistentRoomId)!; + public constructor(props: IProps) { + super(props); + this.room = this.context.getRoom(this.props.persistentRoomId)!; } public render(): JSX.Element | null { diff --git a/src/components/views/elements/Pill.tsx b/src/components/views/elements/Pill.tsx index 14093587ad3..02e4004b3e5 100644 --- a/src/components/views/elements/Pill.tsx +++ b/src/components/views/elements/Pill.tsx @@ -98,7 +98,7 @@ export const Pill: React.FC = ({ type: propType, url, inMessage, room mx_EventPill: type === PillType.EventInOtherRoom || type === PillType.EventInSameRoom, }); - let avatar: ReactElement | null = null; + let avatar: ReactElement | null = null; let pillText: string | null = text; switch (type) { diff --git a/src/components/views/elements/ReplyChain.tsx b/src/components/views/elements/ReplyChain.tsx index 8e10ca3af90..ee92b2f37a3 100644 --- a/src/components/views/elements/ReplyChain.tsx +++ b/src/components/views/elements/ReplyChain.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import { MatrixEvent, Room, MatrixClient } from "matrix-js-sdk/src/matrix"; @@ -71,8 +71,8 @@ export default class ReplyChain extends React.Component { private room: Room; private blockquoteRef = React.createRef(); - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { events: [], diff --git a/src/components/views/elements/ResizeHandle.tsx b/src/components/views/elements/ResizeHandle.tsx index 48909216636..1a19a84e8a8 100644 --- a/src/components/views/elements/ResizeHandle.tsx +++ b/src/components/views/elements/ResizeHandle.tsx @@ -13,7 +13,7 @@ interface IResizeHandleProps { vertical?: boolean; reverse?: boolean; id?: string; - passRef?: React.RefObject; + passRef?: React.RefObject; } const ResizeHandle: React.FC = ({ vertical, reverse, id, passRef }) => { diff --git a/src/components/views/elements/RoomAliasField.tsx b/src/components/views/elements/RoomAliasField.tsx index faa0ccf1a64..3feac450e7e 100644 --- a/src/components/views/elements/RoomAliasField.tsx +++ b/src/components/views/elements/RoomAliasField.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, KeyboardEventHandler } from "react"; +import React, { createRef, KeyboardEventHandler, type JSX } from "react"; import { MatrixError } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../languageHandler"; @@ -37,8 +37,8 @@ export default class RoomAliasField extends React.PureComponent private fieldRef = createRef(); - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { isValid: true, diff --git a/src/components/views/elements/RoomName.tsx b/src/components/views/elements/RoomName.tsx index 169671f0571..d299357d7cb 100644 --- a/src/components/views/elements/RoomName.tsx +++ b/src/components/views/elements/RoomName.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, type JSX } from "react"; import { Room, RoomEvent } from "matrix-js-sdk/src/matrix"; import { useTypedEventEmitter } from "../../../hooks/useEventEmitter"; diff --git a/src/components/views/elements/RoomTopic.tsx b/src/components/views/elements/RoomTopic.tsx index a23f396be51..502aa117b5e 100644 --- a/src/components/views/elements/RoomTopic.tsx +++ b/src/components/views/elements/RoomTopic.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useCallback, useContext, useState } from "react"; +import React, { useCallback, useContext, useState, type JSX } from "react"; import { Room, EventType } from "matrix-js-sdk/src/matrix"; import classNames from "classnames"; import { Tooltip } from "@vector-im/compound-web"; diff --git a/src/components/views/elements/SSOButtons.tsx b/src/components/views/elements/SSOButtons.tsx index e2fd92e97bd..54ff91328aa 100644 --- a/src/components/views/elements/SSOButtons.tsx +++ b/src/components/views/elements/SSOButtons.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { chunk } from "lodash"; import classNames from "classnames"; import { diff --git a/src/components/views/elements/SearchWarning.tsx b/src/components/views/elements/SearchWarning.tsx index e7c651c8020..4b6eb09cc89 100644 --- a/src/components/views/elements/SearchWarning.tsx +++ b/src/components/views/elements/SearchWarning.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import EventIndexPeg from "../../../indexing/EventIndexPeg"; diff --git a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx index ce521c959a1..42c301b5296 100644 --- a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx +++ b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx @@ -103,7 +103,7 @@ export default class SpellCheckLanguagesDropdown extends React.Component< const options = displayedLanguages.map((language) => { return
{language.label}
; - }) as NonEmptyArray; + }) as NonEmptyArray & { key: string }>; // default value here too, otherwise we need to handle null / undefined; // values between mounting and the initial value propagating diff --git a/src/components/views/elements/StyledRadioGroup.tsx b/src/components/views/elements/StyledRadioGroup.tsx index 7e527aade57..5e119db03f7 100644 --- a/src/components/views/elements/StyledRadioGroup.tsx +++ b/src/components/views/elements/StyledRadioGroup.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, ReactNode } from "react"; +import React, { ChangeEvent, ReactNode, type JSX } from "react"; import classNames from "classnames"; import StyledRadioButton from "./StyledRadioButton"; diff --git a/src/components/views/elements/SyntaxHighlight.tsx b/src/components/views/elements/SyntaxHighlight.tsx index 7570ea22ed4..3ae0d8bcd41 100644 --- a/src/components/views/elements/SyntaxHighlight.tsx +++ b/src/components/views/elements/SyntaxHighlight.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { useAsyncMemo } from "../../../hooks/useAsyncMemo"; diff --git a/src/components/views/elements/Tag.tsx b/src/components/views/elements/Tag.tsx index b9f87806281..4d3e79c2045 100644 --- a/src/components/views/elements/Tag.tsx +++ b/src/components/views/elements/Tag.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { DetailedHTMLProps, HTMLAttributes } from "react"; +import React, { DetailedHTMLProps, HTMLAttributes, type JSX } from "react"; import CloseIcon from "@vector-im/compound-design-tokens/assets/web/icons/close"; import AccessibleButton from "./AccessibleButton"; diff --git a/src/components/views/elements/ToggleSwitch.tsx b/src/components/views/elements/ToggleSwitch.tsx index a6ed4fb4f1c..783cbbac60c 100644 --- a/src/components/views/elements/ToggleSwitch.tsx +++ b/src/components/views/elements/ToggleSwitch.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import AccessibleButton from "./AccessibleButton"; diff --git a/src/components/views/elements/UseCaseSelection.tsx b/src/components/views/elements/UseCaseSelection.tsx index 2c64c2903af..452dd302ab9 100644 --- a/src/components/views/elements/UseCaseSelection.tsx +++ b/src/components/views/elements/UseCaseSelection.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, type JSX } from "react"; import { _t } from "../../../languageHandler"; import { UseCase } from "../../../settings/enums/UseCase"; diff --git a/src/components/views/elements/UseCaseSelectionButton.tsx b/src/components/views/elements/UseCaseSelectionButton.tsx index 2899a1ee502..a5413ccb98a 100644 --- a/src/components/views/elements/UseCaseSelectionButton.tsx +++ b/src/components/views/elements/UseCaseSelectionButton.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React from "react"; +import React, { type JSX } from "react"; import { _t } from "../../../languageHandler"; import { UseCase } from "../../../settings/enums/UseCase"; diff --git a/src/components/views/elements/Validation.tsx b/src/components/views/elements/Validation.tsx index f859c00bebf..9361a259b4a 100644 --- a/src/components/views/elements/Validation.tsx +++ b/src/components/views/elements/Validation.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import classNames from "classnames"; import memoizeOne from "memoize-one"; diff --git a/src/components/views/emojipicker/Category.tsx b/src/components/views/emojipicker/Category.tsx index 4c9fbc2d89e..7566f81f2e7 100644 --- a/src/components/views/emojipicker/Category.tsx +++ b/src/components/views/emojipicker/Category.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { RefObject } from "react"; +import React, { RefObject, type JSX } from "react"; import { DATA_BY_CATEGORY, Emoji as IEmoji } from "@matrix-org/emojibase-bindings"; import { CATEGORY_HEADER_HEIGHT, EMOJI_HEIGHT, EMOJIS_PER_ROW } from "./EmojiPicker"; @@ -24,7 +24,7 @@ export interface ICategory { name: string; enabled: boolean; visible: boolean; - ref: RefObject; + ref: RefObject; } interface IProps { diff --git a/src/components/views/emojipicker/ReactionPicker.tsx b/src/components/views/emojipicker/ReactionPicker.tsx index bd166344904..9f1fa4ebd4e 100644 --- a/src/components/views/emojipicker/ReactionPicker.tsx +++ b/src/components/views/emojipicker/ReactionPicker.tsx @@ -31,8 +31,8 @@ class ReactionPicker extends React.Component { public static contextType = RoomContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { selectedEmojis: new Set(Object.keys(this.getReactions())), diff --git a/src/components/views/emojipicker/Search.tsx b/src/components/views/emojipicker/Search.tsx index bce045cb8c6..0d131a7f754 100644 --- a/src/components/views/emojipicker/Search.tsx +++ b/src/components/views/emojipicker/Search.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { _t } from "../../../languageHandler"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; diff --git a/src/components/views/location/LiveDurationDropdown.tsx b/src/components/views/location/LiveDurationDropdown.tsx index f0a85b842a7..d0232e167e6 100644 --- a/src/components/views/location/LiveDurationDropdown.tsx +++ b/src/components/views/location/LiveDurationDropdown.tsx @@ -53,7 +53,7 @@ const LiveDurationDropdown: React.FC = ({ timeout, onChange }) => { }; return ( - = ({ timeout, onChange }) => {
{label}
- )) as NonEmptyArray + )) as NonEmptyArray & { key: string }> } -
+ ) ); }; diff --git a/src/components/views/location/LocationPicker.tsx b/src/components/views/location/LocationPicker.tsx index e812f1c6bd9..c41444a570b 100644 --- a/src/components/views/location/LocationPicker.tsx +++ b/src/components/views/location/LocationPicker.tsx @@ -47,8 +47,8 @@ class LocationPicker extends React.Component { private geolocate?: maplibregl.GeolocateControl; private marker?: maplibregl.Marker; - public constructor(props: ILocationPickerProps, context: React.ContextType) { - super(props, context); + public constructor(props: ILocationPickerProps) { + super(props); this.state = { position: undefined, diff --git a/src/components/views/location/MapFallback.tsx b/src/components/views/location/MapFallback.tsx index 101a5d80663..cbb1abf2952 100644 --- a/src/components/views/location/MapFallback.tsx +++ b/src/components/views/location/MapFallback.tsx @@ -16,7 +16,7 @@ import Spinner from "../elements/Spinner"; interface Props extends React.HTMLAttributes { className?: string; isLoading?: boolean; - children?: React.ReactNode | React.ReactNodeArray; + children?: React.ReactNode | ReadonlyArray; } const MapFallback: React.FC = ({ className, isLoading, children, ...rest }) => { diff --git a/src/components/views/location/ShareType.tsx b/src/components/views/location/ShareType.tsx index 0aa31b7bd4b..6f88f23ac53 100644 --- a/src/components/views/location/ShareType.tsx +++ b/src/components/views/location/ShareType.tsx @@ -45,7 +45,7 @@ type ShareTypeOptionProps = HTMLAttributes & { onClick?: ((e: ButtonEvent) => void | Promise) | null; }; const ShareTypeOption: React.FC = ({ onClick, label, shareType, ...rest }) => ( - + {shareType === LocationShareType.Own && } {shareType === LocationShareType.Pin && ( diff --git a/src/components/views/location/index.tsx b/src/components/views/location/index.tsx index d51d6c58f36..1dbcb07c80f 100644 --- a/src/components/views/location/index.tsx +++ b/src/components/views/location/index.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. // Exports location components which touch maplibre-gs wrapped in React Suspense to enable code splitting -import React, { ComponentProps, lazy, Suspense } from "react"; +import React, { ComponentProps, lazy, Suspense, type JSX } from "react"; import Spinner from "../elements/Spinner"; diff --git a/src/components/views/messages/CodeBlock.tsx b/src/components/views/messages/CodeBlock.tsx index 80619914058..6b6ab31ae8d 100644 --- a/src/components/views/messages/CodeBlock.tsx +++ b/src/components/views/messages/CodeBlock.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useState } from "react"; +import React, { useState, type JSX } from "react"; import classNames from "classnames"; import { TooltipProvider } from "@vector-im/compound-web"; @@ -119,7 +119,9 @@ const CodeBlock: React.FC = ({ children, onHeightChanged }) => {
{ + highlightCode(div); + }} /> {expandCollapseButton} diff --git a/src/components/views/messages/DateSeparator.tsx b/src/components/views/messages/DateSeparator.tsx index 98f397eb459..c7c27ca5515 100644 --- a/src/components/views/messages/DateSeparator.tsx +++ b/src/components/views/messages/DateSeparator.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { Direction, ConnectionError, MatrixError, HTTPError } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { capitalize } from "lodash"; @@ -265,7 +265,7 @@ export default class DateSeparator extends React.Component { this.closeMenu(); }; - private renderJumpToDateMenu(): React.ReactElement { + private renderJumpToDateMenu(): React.ReactElement { let contextMenu: JSX.Element | undefined; if (this.state.contextMenuPosition) { const relativeTimeFormat = this.relativeTimeFormat; diff --git a/src/components/views/messages/DownloadActionButton.tsx b/src/components/views/messages/DownloadActionButton.tsx index 2940dab2922..f0a05ac6030 100644 --- a/src/components/views/messages/DownloadActionButton.tsx +++ b/src/components/views/messages/DownloadActionButton.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { MatrixEvent } from "matrix-js-sdk/src/matrix"; -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import { DownloadIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; diff --git a/src/components/views/messages/EditHistoryMessage.tsx b/src/components/views/messages/EditHistoryMessage.tsx index fb6f04c08f0..da077b31b4c 100644 --- a/src/components/views/messages/EditHistoryMessage.tsx +++ b/src/components/views/messages/EditHistoryMessage.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { createRef, type JSX } from "react"; import { EventStatus, IContent, MatrixEvent, MatrixEventEvent, MsgType } from "matrix-js-sdk/src/matrix"; import classNames from "classnames"; @@ -51,8 +51,8 @@ export default class EditHistoryMessage extends React.PureComponent) { - super(props, context); + public constructor(props: IProps) { + super(props); const cli = this.context; const userId = cli.getSafeUserId(); diff --git a/src/components/views/messages/EncryptionEvent.tsx b/src/components/views/messages/EncryptionEvent.tsx index bc6680d3000..6ec15f4354b 100644 --- a/src/components/views/messages/EncryptionEvent.tsx +++ b/src/components/views/messages/EncryptionEvent.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { forwardRef } from "react"; +import React, { forwardRef, type JSX } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import type { RoomEncryptionEventContent } from "matrix-js-sdk/src/types"; diff --git a/src/components/views/messages/EventTileBubble.tsx b/src/components/views/messages/EventTileBubble.tsx index 05c8a66f995..a90f2f1e110 100644 --- a/src/components/views/messages/EventTileBubble.tsx +++ b/src/components/views/messages/EventTileBubble.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { forwardRef, ReactNode, ReactChild } from "react"; +import React, { forwardRef, ReactNode, ReactElement, type JSX } from "react"; import classNames from "classnames"; interface IProps { @@ -14,7 +14,7 @@ interface IProps { title: string; timestamp?: JSX.Element; subtitle?: ReactNode; - children?: ReactChild; + children?: ReactElement | number | string; } const EventTileBubble = forwardRef( diff --git a/src/components/views/messages/IBodyProps.ts b/src/components/views/messages/IBodyProps.ts index e48ba96b56f..eb897635198 100644 --- a/src/components/views/messages/IBodyProps.ts +++ b/src/components/views/messages/IBodyProps.ts @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { LegacyRef } from "react"; +import React, { Ref } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { MediaEventHelper } from "../../../utils/MediaEventHelper"; @@ -46,9 +46,12 @@ export interface IBodyProps { // helper function to access relations for this event getRelationsForEvent?: GetRelationsForEvent; - ref?: React.RefObject | LegacyRef; + ref?: React.RefObject | Ref; // Set to `true` to disable interactions (e.g. video controls) and to remove controls from the tab order. // This may be useful when displaying a preview of the event. inhibitInteraction?: boolean; + + /* Whether to show the default placeholder for files. Defaults to true. */ + showGenericPlaceholder?: boolean; } diff --git a/src/components/views/messages/LegacyCallEvent.tsx b/src/components/views/messages/LegacyCallEvent.tsx index 3f24459b5b6..ed871617a1d 100644 --- a/src/components/views/messages/LegacyCallEvent.tsx +++ b/src/components/views/messages/LegacyCallEvent.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { createRef, type JSX } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { CallErrorCode, CallState } from "matrix-js-sdk/src/webrtc/call"; import classNames from "classnames"; diff --git a/src/components/views/messages/MBeaconBody.tsx b/src/components/views/messages/MBeaconBody.tsx index 8b250fa0d50..e5b4aa4b597 100644 --- a/src/components/views/messages/MBeaconBody.tsx +++ b/src/components/views/messages/MBeaconBody.tsx @@ -6,7 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ForwardRefExoticComponent, useCallback, useContext, useEffect, useState } from "react"; +import React, { + ForwardRefExoticComponent, + useCallback, + useContext, + useEffect, + useState, + type JSX, +} from "react"; import { Beacon, BeaconEvent, diff --git a/src/components/views/messages/MFileBody.tsx b/src/components/views/messages/MFileBody.tsx index 1235b73b4bd..28ec202afe4 100644 --- a/src/components/views/messages/MFileBody.tsx +++ b/src/components/views/messages/MFileBody.tsx @@ -91,16 +91,11 @@ export function computedStyle(element: HTMLElement | null): string { return cssText; } -interface IProps extends IBodyProps { - /* whether or not to show the default placeholder for the file. Defaults to true. */ - showGenericPlaceholder: boolean; -} - interface IState { decryptedBlob?: Blob; } -export default class MFileBody extends React.Component { +export default class MFileBody extends React.Component { public static contextType = RoomContext; declare public context: React.ContextType; @@ -110,8 +105,8 @@ export default class MFileBody extends React.Component { showGenericPlaceholder: true, }; - private iframe: React.RefObject = createRef(); - private dummyLink: React.RefObject = createRef(); + private iframe: React.RefObject = createRef(); + private dummyLink: React.RefObject = createRef(); private userDidClick = false; private fileDownloader: FileDownloader = new FileDownloader(() => this.iframe.current); @@ -147,7 +142,7 @@ export default class MFileBody extends React.Component { }); } - public componentDidUpdate(prevProps: IProps, prevState: IState): void { + public componentDidUpdate(prevProps: IBodyProps, prevState: IState): void { if (this.props.onHeightChanged && !prevState.decryptedBlob && this.state.decryptedBlob) { this.props.onHeightChanged(); } diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index c3aeee1a54a..b2071c9341f 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, createRef, ReactNode } from "react"; +import React, { ComponentProps, createRef, ReactNode, type JSX } from "react"; import { Blurhash } from "react-blurhash"; import classNames from "classnames"; import { CSSTransition, SwitchTransition } from "react-transition-group"; diff --git a/src/components/views/messages/MImageReplyBody.tsx b/src/components/views/messages/MImageReplyBody.tsx index c1ba78fbf75..3afe514c397 100644 --- a/src/components/views/messages/MImageReplyBody.tsx +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { ImageContent } from "matrix-js-sdk/src/types"; import MImageBody from "./MImageBody"; diff --git a/src/components/views/messages/MJitsiWidgetEvent.tsx b/src/components/views/messages/MJitsiWidgetEvent.tsx index bec4f56164b..0919eee36d7 100644 --- a/src/components/views/messages/MJitsiWidgetEvent.tsx +++ b/src/components/views/messages/MJitsiWidgetEvent.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/messages/MKeyVerificationRequest.tsx b/src/components/views/messages/MKeyVerificationRequest.tsx index 56e7b1c39c4..9bf58fc2dcd 100644 --- a/src/components/views/messages/MKeyVerificationRequest.tsx +++ b/src/components/views/messages/MKeyVerificationRequest.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/messages/MLocationBody.tsx b/src/components/views/messages/MLocationBody.tsx index 7735e64b031..14b55c034d3 100644 --- a/src/components/views/messages/MLocationBody.tsx +++ b/src/components/views/messages/MLocationBody.tsx @@ -36,8 +36,8 @@ export default class MLocationBody extends React.Component { private mapId: string; private reconnectedListener: ClientEventHandlerMap[ClientEvent.Sync]; - public constructor(props: IBodyProps, context: React.ContextType) { - super(props, context); + public constructor(props: IBodyProps) { + super(props); // multiple instances of same map might be in document // eg thread and main timeline, reply diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index ba3962779f3..6dd65e1e047 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -142,8 +142,8 @@ export default class MPollBody extends React.Component { declare public context: React.ContextType; private seenEventIds: string[] = []; // Events we have already seen - public constructor(props: IBodyProps, context: React.ContextType) { - super(props, context); + public constructor(props: IBodyProps) { + super(props); this.state = { selected: null, diff --git a/src/components/views/messages/MStickerBody.tsx b/src/components/views/messages/MStickerBody.tsx index b1638d5b314..ec156cbfc74 100644 --- a/src/components/views/messages/MStickerBody.tsx +++ b/src/components/views/messages/MStickerBody.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, ReactNode } from "react"; +import React, { ComponentProps, ReactNode, type JSX } from "react"; import { Tooltip } from "@vector-im/compound-web"; import { MediaEventContent } from "matrix-js-sdk/src/types"; diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 9d21b8fa45a..f5305876bad 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactElement, useCallback, useContext, useEffect } from "react"; +import React, { ReactElement, useCallback, useContext, useEffect, type JSX } from "react"; import { EventStatus, MatrixEvent, @@ -99,7 +99,7 @@ const OptionsButton: React.FC = ({ [openMenu, onFocus], ); - let contextMenu: ReactElement | undefined; + let contextMenu: ReactElement | undefined; if (menuDisplayed && button.current) { const tile = getTile?.(); const replyChain = getReplyChain(); diff --git a/src/components/views/messages/MessageEvent.tsx b/src/components/views/messages/MessageEvent.tsx index d1a1c59141d..7c53c711de6 100644 --- a/src/components/views/messages/MessageEvent.tsx +++ b/src/components/views/messages/MessageEvent.tsx @@ -58,7 +58,7 @@ export interface IOperableEventTile { getEventTileOps(): IEventTileOps | null; } -const baseBodyTypes = new Map([ +const baseBodyTypes = new Map>([ [MsgType.Text, TextualBody], [MsgType.Notice, TextualBody], [MsgType.Emote, TextualBody], @@ -78,16 +78,16 @@ const baseEvTypes = new Map>([ ]); export default class MessageEvent extends React.Component implements IMediaBody, IOperableEventTile { - private body: React.RefObject = createRef(); + private body: React.RefObject = createRef(); private mediaHelper?: MediaEventHelper; - private bodyTypes = new Map(baseBodyTypes.entries()); - private evTypes = new Map>(baseEvTypes.entries()); + private bodyTypes = new Map(baseBodyTypes.entries()); + private evTypes = new Map(baseEvTypes.entries()); public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); if (MediaEventHelper.isEligible(this.props.mxEvent)) { this.mediaHelper = new MediaEventHelper(this.props.mxEvent); @@ -115,12 +115,12 @@ export default class MessageEvent extends React.Component implements IMe } private updateComponentMaps(): void { - this.bodyTypes = new Map(baseBodyTypes.entries()); + this.bodyTypes = new Map(baseBodyTypes.entries()); for (const [bodyType, bodyComponent] of Object.entries(this.props.overrideBodyTypes ?? {})) { this.bodyTypes.set(bodyType, bodyComponent); } - this.evTypes = new Map>(baseEvTypes.entries()); + this.evTypes = new Map(baseEvTypes.entries()); for (const [evType, evComponent] of Object.entries(this.props.overrideEventTypes ?? {})) { this.evTypes.set(evType, evComponent); } diff --git a/src/components/views/messages/ReactionsRow.tsx b/src/components/views/messages/ReactionsRow.tsx index 605e6a7dfe0..82e5d74ff9f 100644 --- a/src/components/views/messages/ReactionsRow.tsx +++ b/src/components/views/messages/ReactionsRow.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { SyntheticEvent } from "react"; +import React, { SyntheticEvent, type JSX } from "react"; import classNames from "classnames"; import { MatrixEvent, MatrixEventEvent, Relations, RelationsEvent } from "matrix-js-sdk/src/matrix"; import { uniqBy } from "lodash"; @@ -77,8 +77,8 @@ export default class ReactionsRow extends React.PureComponent { public static contextType = RoomContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { myReactions: this.getMyReactions(), diff --git a/src/components/views/messages/RoomPredecessorTile.tsx b/src/components/views/messages/RoomPredecessorTile.tsx index afc81422345..7f0957fe388 100644 --- a/src/components/views/messages/RoomPredecessorTile.tsx +++ b/src/components/views/messages/RoomPredecessorTile.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useCallback } from "react"; +import React, { useCallback, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixEvent, Room, RoomState } from "matrix-js-sdk/src/matrix"; diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx index 7c239d0500a..f393fb86a65 100644 --- a/src/components/views/messages/SenderProfile.tsx +++ b/src/components/views/messages/SenderProfile.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent, MsgType } from "matrix-js-sdk/src/matrix"; import DisambiguatedProfile from "./DisambiguatedProfile"; diff --git a/src/components/views/messages/TextualBody.tsx b/src/components/views/messages/TextualBody.tsx index ae99754cbad..7e5127bacce 100644 --- a/src/components/views/messages/TextualBody.tsx +++ b/src/components/views/messages/TextualBody.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, SyntheticEvent, MouseEvent, StrictMode } from "react"; +import React, { createRef, SyntheticEvent, MouseEvent, StrictMode, type JSX } from "react"; import { MsgType } from "matrix-js-sdk/src/matrix"; import { TooltipProvider } from "@vector-im/compound-web"; diff --git a/src/components/views/right_panel/EncryptionInfo.tsx b/src/components/views/right_panel/EncryptionInfo.tsx index 588d2d910ed..98eaedaa8b4 100644 --- a/src/components/views/right_panel/EncryptionInfo.tsx +++ b/src/components/views/right_panel/EncryptionInfo.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { RoomMember, User } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/right_panel/ExtensionsCard.tsx b/src/components/views/right_panel/ExtensionsCard.tsx index 0c6b3ecde09..b681b186659 100644 --- a/src/components/views/right_panel/ExtensionsCard.tsx +++ b/src/components/views/right_panel/ExtensionsCard.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useEffect, useMemo, useState } from "react"; +import React, { useEffect, useMemo, useState, type JSX } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; import classNames from "classnames"; import { Button, Link, Separator, Text } from "@vector-im/compound-web"; diff --git a/src/components/views/right_panel/RoomSummaryCard.tsx b/src/components/views/right_panel/RoomSummaryCard.tsx index c8dd0b97387..5f4020d3bab 100644 --- a/src/components/views/right_panel/RoomSummaryCard.tsx +++ b/src/components/views/right_panel/RoomSummaryCard.tsx @@ -6,7 +6,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, SyntheticEvent, useContext, useEffect, useRef, useState } from "react"; +import React, { + ChangeEvent, + SyntheticEvent, + useContext, + useEffect, + useRef, + useState, + type JSX, +} from "react"; import classNames from "classnames"; import { MenuItem, diff --git a/src/components/views/right_panel/TimelineCard.tsx b/src/components/views/right_panel/TimelineCard.tsx index f62319f3cda..aec5245cdd0 100644 --- a/src/components/views/right_panel/TimelineCard.tsx +++ b/src/components/views/right_panel/TimelineCard.tsx @@ -77,8 +77,8 @@ export default class TimelineCard extends React.Component { private card = React.createRef(); private readReceiptsSettingWatcher: string | undefined; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { showReadReceipts: SettingsStore.getValue("showReadReceipts", props.room.roomId), layout: SettingsStore.getValue("layout"), diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 591e2327ae4..45d381232a9 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode, useCallback, useContext, useEffect, useMemo, useState } from "react"; +import React, { ReactNode, useCallback, useContext, useEffect, useMemo, useState, type JSX } from "react"; import classNames from "classnames"; import { ClientEvent, diff --git a/src/components/views/right_panel/VerificationPanel.tsx b/src/components/views/right_panel/VerificationPanel.tsx index 6f8295dece2..f6b68a4ea65 100644 --- a/src/components/views/right_panel/VerificationPanel.tsx +++ b/src/components/views/right_panel/VerificationPanel.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { ShowQrCodeCallbacks, ShowSasCallbacks, diff --git a/src/components/views/right_panel/WidgetCard.tsx b/src/components/views/right_panel/WidgetCard.tsx index 887ecb61908..7b0e56929eb 100644 --- a/src/components/views/right_panel/WidgetCard.tsx +++ b/src/components/views/right_panel/WidgetCard.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useContext, useEffect } from "react"; +import React, { useContext, useEffect, type JSX } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; diff --git a/src/components/views/room_settings/AliasSettings.tsx b/src/components/views/room_settings/AliasSettings.tsx index 0bb29b7f895..318069f3db1 100644 --- a/src/components/views/room_settings/AliasSettings.tsx +++ b/src/components/views/room_settings/AliasSettings.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, ContextType, createRef, SyntheticEvent } from "react"; +import React, { ChangeEvent, ToggleEvent, ContextType, createRef, SyntheticEvent, type JSX } from "react"; import { MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { RoomCanonicalAliasEventContent } from "matrix-js-sdk/src/types"; @@ -101,8 +101,8 @@ export default class AliasSettings extends React.Component { canSetCanonicalAlias: false, }; - public constructor(props: IProps, context: ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); const state: IState = { altAliases: [], @@ -278,9 +278,9 @@ export default class AliasSettings extends React.Component { }); }; - private onLocalAliasesToggled = (event: ChangeEvent): void => { + private onLocalAliasesToggled = (event: ToggleEvent): void => { // expanded - if (event.target.open) { + if (event.currentTarget.open) { // if local aliases haven't been preloaded yet at component mount if (!this.props.canSetCanonicalAlias && this.state.localAliases.length === 0) { this.loadLocalAliases(); diff --git a/src/components/views/rooms/Autocomplete.tsx b/src/components/views/rooms/Autocomplete.tsx index 3ffd6648ea8..871c065ebc3 100644 --- a/src/components/views/rooms/Autocomplete.tsx +++ b/src/components/views/rooms/Autocomplete.tsx @@ -46,13 +46,13 @@ export default class Autocomplete extends React.PureComponent { public queryRequested?: string; public debounceCompletionsRequest?: number; private containerRef = createRef(); - private completionRefs: Record> = {}; + private completionRefs: Record> = {}; public static contextType = RoomContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { // list of completionResults, each containing completions diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 5f033de2380..d2f7620fe99 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { createRef, ClipboardEvent, SyntheticEvent } from "react"; +import React, { createRef, ClipboardEvent, SyntheticEvent, type JSX } from "react"; import { Room, MatrixEvent } from "matrix-js-sdk/src/matrix"; import EMOTICON_REGEX from "emojibase-regex/emoticon"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/rooms/E2EIcon.tsx b/src/components/views/rooms/E2EIcon.tsx index 29899e85ba9..51fa89291f9 100644 --- a/src/components/views/rooms/E2EIcon.tsx +++ b/src/components/views/rooms/E2EIcon.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, CSSProperties } from "react"; +import React, { ComponentProps, CSSProperties, type JSX } from "react"; import classNames from "classnames"; import { Tooltip } from "@vector-im/compound-web"; diff --git a/src/components/views/rooms/EditMessageComposer.tsx b/src/components/views/rooms/EditMessageComposer.tsx index f4b5c3698eb..d7712e6afdd 100644 --- a/src/components/views/rooms/EditMessageComposer.tsx +++ b/src/components/views/rooms/EditMessageComposer.tsx @@ -99,8 +99,8 @@ class EditMessageComposer extends React.Component) { - super(props, context); + public constructor(props: IEditMessageComposerProps) { + super(props); const isRestored = this.createEditorModel(); const ev = this.props.editState.getEvent(); diff --git a/src/components/views/rooms/EmojiButton.tsx b/src/components/views/rooms/EmojiButton.tsx index de64b3d42c7..75e5f827ded 100644 --- a/src/components/views/rooms/EmojiButton.tsx +++ b/src/components/views/rooms/EmojiButton.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { useContext } from "react"; +import React, { useContext, type JSX } from "react"; import { _t } from "../../../languageHandler"; import ContextMenu, { aboveLeftOf, MenuProps, useContextMenu } from "../../structures/ContextMenu"; @@ -25,7 +25,7 @@ export function EmojiButton({ addEmoji, menuPosition, className }: IEmojiButtonP const overflowMenuCloser = useContext(OverflowMenuContext); const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); - let contextMenu: React.ReactElement | null = null; + let contextMenu: React.ReactElement | null = null; if (menuDisplayed && button.current) { const position = menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect()); const onFinished = (): void => { diff --git a/src/components/views/rooms/EntityTile.tsx b/src/components/views/rooms/EntityTile.tsx index 946a5cd46b4..51bfcb7a57f 100644 --- a/src/components/views/rooms/EntityTile.tsx +++ b/src/components/views/rooms/EntityTile.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import AccessibleButton from "../elements/AccessibleButton"; diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 8c755f00bda..78812c8f266 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -300,8 +300,8 @@ export class UnwrappedEventTile extends React.Component private unmounted = false; - public constructor(props: EventTileProps, context: React.ContextType) { - super(props, context); + public constructor(props: EventTileProps) { + super(props); const thread = this.thread; diff --git a/src/components/views/rooms/EventTile/EventTileThreadToolbar.tsx b/src/components/views/rooms/EventTile/EventTileThreadToolbar.tsx index ad1a6ce9a61..fe990675105 100644 --- a/src/components/views/rooms/EventTile/EventTileThreadToolbar.tsx +++ b/src/components/views/rooms/EventTile/EventTileThreadToolbar.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import LinkIcon from "@vector-im/compound-design-tokens/assets/web/icons/link"; import { RovingAccessibleButton } from "../../../../accessibility/RovingTabIndex"; diff --git a/src/components/views/rooms/ExtraTile.tsx b/src/components/views/rooms/ExtraTile.tsx index 8f94264623c..8a7cff267dd 100644 --- a/src/components/views/rooms/ExtraTile.tsx +++ b/src/components/views/rooms/ExtraTile.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import { RovingAccessibleButton } from "../../../accessibility/RovingTabIndex"; @@ -19,7 +19,7 @@ interface ExtraTileProps { isMinimized: boolean; isSelected: boolean; displayName: string; - avatar: React.ReactElement; + avatar: React.ReactElement; notificationState?: NotificationState; onClick: (ev: ButtonEvent) => void; } diff --git a/src/components/views/rooms/LinkPreviewGroup.tsx b/src/components/views/rooms/LinkPreviewGroup.tsx index cbbd2a3d7bf..a93bfb0abb8 100644 --- a/src/components/views/rooms/LinkPreviewGroup.tsx +++ b/src/components/views/rooms/LinkPreviewGroup.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useContext, useEffect } from "react"; +import React, { useContext, useEffect, type JSX } from "react"; import { MatrixEvent, MatrixError, IPreviewUrlResponse, MatrixClient } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import CloseIcon from "@vector-im/compound-design-tokens/assets/web/icons/close"; diff --git a/src/components/views/rooms/LinkPreviewWidget.tsx b/src/components/views/rooms/LinkPreviewWidget.tsx index 91fb0608aaf..f1e677ffc4a 100644 --- a/src/components/views/rooms/LinkPreviewWidget.tsx +++ b/src/components/views/rooms/LinkPreviewWidget.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, createRef, ReactNode } from "react"; +import React, { ComponentProps, createRef, ReactNode, type JSX } from "react"; import { decode } from "html-entities"; import { MatrixEvent, IPreviewUrlResponse } from "matrix-js-sdk/src/matrix"; diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx index 5587b56bf82..6ec40a76f57 100644 --- a/src/components/views/rooms/MemberList.tsx +++ b/src/components/views/rooms/MemberList.tsx @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent, Room, @@ -78,10 +78,10 @@ export default class MemberList extends React.Component { declare public context: React.ContextType; private tiles: Map = new Map(); - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = this.getMembersState([], []); - this.showPresence = context?.memberListStore.isPresenceEnabled() ?? true; + this.showPresence = this.context?.memberListStore.isPresenceEnabled() ?? true; } private listenForMembersChanges(): void { diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index f5716d728b6..44581686a8a 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef, ReactNode } from "react"; +import React, { createRef, ReactNode, type JSX } from "react"; import classNames from "classnames"; import { IEventRelation, @@ -111,7 +111,7 @@ export class MessageComposer extends React.Component { private dispatcherRef?: string; private messageComposerInput = createRef(); private voiceRecordingButton = createRef(); - private ref: React.RefObject = createRef(); + private ref: React.RefObject = createRef(); private instanceId: number; private _voiceRecording: Optional; @@ -124,9 +124,8 @@ export class MessageComposer extends React.Component { isRichTextEnabled: true, }; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); - this.context = context; // otherwise React will only set it prior to render due to type def above + public constructor(props: IProps) { + super(props); const isWysiwygLabEnabled = SettingsStore.getValue("feature_wysiwyg_composer"); let isRichTextEnabled = true; diff --git a/src/components/views/rooms/MessageComposerButtons.tsx b/src/components/views/rooms/MessageComposerButtons.tsx index 19b86834dd7..eb10e50b07c 100644 --- a/src/components/views/rooms/MessageComposerButtons.tsx +++ b/src/components/views/rooms/MessageComposerButtons.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import classNames from "classnames"; import { IEventRelation, Room, MatrixClient, THREAD_RELATION_TYPE, M_POLL_START } from "matrix-js-sdk/src/matrix"; -import React, { createContext, ReactElement, ReactNode, useContext, useRef } from "react"; +import React, { createContext, ReactElement, ReactNode, useContext, useRef, type JSX } from "react"; import { _t } from "../../../languageHandler"; import { CollapsibleButton } from "./CollapsibleButton"; @@ -137,7 +137,7 @@ const MessageComposerButtons: React.FC = (props: IProps) => { ); }; -function emojiButton(props: IProps): ReactElement { +function emojiButton(props: IProps): ReactElement { return ( { return ; } @@ -237,7 +237,7 @@ const UploadButton: React.FC = () => { ); }; -function showStickersButton(props: IProps): ReactElement | null { +function showStickersButton(props: IProps): ReactElement | null { return props.showStickersButton ? ( | null { // XXX: recording UI does not work well in narrow mode, so hide for now return narrow ? null : ( { return ; } @@ -319,7 +319,7 @@ class PollButton extends React.PureComponent { } } -function showLocationButton(props: IProps, room: Room, matrixClient: MatrixClient): ReactElement | null { +function showLocationButton(props: IProps, room: Room, matrixClient: MatrixClient): ReactElement | null { const sender = room.getMember(matrixClient.getSafeUserId()); return props.showLocationButton && sender ? ( diff --git a/src/components/views/rooms/NewRoomIntro.tsx b/src/components/views/rooms/NewRoomIntro.tsx index a5577ee372f..ce40c6b6a03 100644 --- a/src/components/views/rooms/NewRoomIntro.tsx +++ b/src/components/views/rooms/NewRoomIntro.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useContext } from "react"; +import React, { useContext, type JSX } from "react"; import { EventType, Room, User, MatrixClient } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; diff --git a/src/components/views/rooms/NotificationBadge.tsx b/src/components/views/rooms/NotificationBadge.tsx index 6825ea8e43f..442912be711 100644 --- a/src/components/views/rooms/NotificationBadge.tsx +++ b/src/components/views/rooms/NotificationBadge.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { Tooltip } from "@vector-im/compound-web"; import SettingsStore from "../../../settings/SettingsStore"; diff --git a/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx b/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx index dee861f11c2..5e989b065f7 100644 --- a/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx +++ b/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { Room } from "matrix-js-sdk/src/matrix"; -import React from "react"; +import React, { type JSX } from "react"; import { useUnreadNotifications } from "../../../../hooks/useUnreadNotifications"; import { StatelessNotificationBadge } from "./StatelessNotificationBadge"; diff --git a/src/components/views/rooms/ReadReceiptGroup.tsx b/src/components/views/rooms/ReadReceiptGroup.tsx index ea60518f4b2..fee076a105f 100644 --- a/src/components/views/rooms/ReadReceiptGroup.tsx +++ b/src/components/views/rooms/ReadReceiptGroup.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { PropsWithChildren } from "react"; +import React, { PropsWithChildren, type JSX } from "react"; import { User } from "matrix-js-sdk/src/matrix"; import { Tooltip } from "@vector-im/compound-web"; diff --git a/src/components/views/rooms/ReplyPreview.tsx b/src/components/views/rooms/ReplyPreview.tsx index 7851f7914d6..573c373d113 100644 --- a/src/components/views/rooms/ReplyPreview.tsx +++ b/src/components/views/rooms/ReplyPreview.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import dis from "../../../dispatcher/dispatcher"; diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 6841d984dea..13021803b49 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -26,6 +26,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { renderReplyTile } from "../../../events/EventTileFactory"; import { GetRelationsForEvent } from "../rooms/EventTile"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { IBodyProps } from "../messages/IBodyProps.ts"; interface IProps { mxEvent: MatrixEvent; @@ -139,13 +140,13 @@ export default class ReplyTile extends React.PureComponent { ); } - const msgtypeOverrides: Record = { + const msgtypeOverrides: Record> = { [MsgType.Image]: MImageReplyBody, // Override audio and video body with file body. We also hide the download/decrypt button using CSS [MsgType.Audio]: isVoiceMessage(mxEvent) ? MVoiceMessageBody : MFileBody, [MsgType.Video]: MFileBody, }; - const evOverrides: Record = { + const evOverrides: Record> = { // Use MImageReplyBody so that the sticker isn't taking up a lot of space [EventType.Sticker]: MImageReplyBody, }; diff --git a/src/components/views/rooms/RoomBreadcrumbs.tsx b/src/components/views/rooms/RoomBreadcrumbs.tsx index bb787d509a9..270fc27e6dc 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.tsx +++ b/src/components/views/rooms/RoomBreadcrumbs.tsx @@ -105,7 +105,7 @@ export default class RoomBreadcrumbs extends React.PureComponent }); }; - public render(): React.ReactElement { + public render(): React.ReactElement { const tiles = BreadcrumbsStore.instance.rooms.map((r, i) => ( = HTMLAttributes & { +type Props = HTMLAttributes & { component?: T; room: Room; }; -export function RoomContextDetails({ room, component, ...other }: Props): JSX.Element { +export function RoomContextDetails({ room, component, ...other }: Props): JSX.Element { const contextDetails = roomContextDetails(room); if (contextDetails) { return React.createElement( diff --git a/src/components/views/rooms/RoomHeader.tsx b/src/components/views/rooms/RoomHeader.tsx index d133587fc92..e3d682a3dea 100644 --- a/src/components/views/rooms/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useCallback, useMemo, useState } from "react"; +import React, { useCallback, useMemo, useState, type JSX } from "react"; import { Body as BodyText, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web"; import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid"; import VoiceCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/voice-call"; diff --git a/src/components/views/rooms/RoomInfoLine.tsx b/src/components/views/rooms/RoomInfoLine.tsx index 1487bfe15b7..2da4d0c42e6 100644 --- a/src/components/views/rooms/RoomInfoLine.tsx +++ b/src/components/views/rooms/RoomInfoLine.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { FC } from "react"; +import React, { FC, type JSX } from "react"; import { Room, JoinRule, MatrixClient } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; diff --git a/src/components/views/rooms/RoomKnocksBar.tsx b/src/components/views/rooms/RoomKnocksBar.tsx index 0ff9ce3e275..e7d5330a027 100644 --- a/src/components/views/rooms/RoomKnocksBar.tsx +++ b/src/components/views/rooms/RoomKnocksBar.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import { EventTimeline, JoinRule, MatrixError, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; -import React, { ReactElement, ReactNode, useCallback, useState, VFC } from "react"; +import React, { ReactElement, ReactNode, useCallback, useState, FC } from "react"; import { CloseIcon, CheckIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import dis from "../../../dispatcher/dispatcher"; @@ -22,7 +22,7 @@ import AccessibleButton from "../elements/AccessibleButton"; import Heading from "../typography/Heading"; import { formatList } from "../../../utils/FormattingUtils"; -export const RoomKnocksBar: VFC<{ room: Room }> = ({ room }) => { +export const RoomKnocksBar: FC<{ room: Room }> = ({ room }) => { const [disabled, setDisabled] = useState(false); const knockMembers = useTypedEventEmitterState( room, @@ -65,7 +65,7 @@ export const RoomKnocksBar: VFC<{ room: Room }> = ({ room }) => { const handleOpenRoomSettings = (): void => dis.dispatch({ action: "open_room_settings", room_id: room.roomId, initial_tab_id: RoomSettingsTab.People }); - let buttons: ReactElement = ( + let buttons: ReactElement = ( { public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { sublists: {}, @@ -575,7 +575,7 @@ export default class RoomList extends React.PureComponent { }); } - private renderSublists(): React.ReactElement[] { + private renderSublists(): React.ReactElement[] { // show a skeleton UI if the user is in no rooms and they are not filtering and have no suggested rooms const showSkeleton = !this.state.suggestedRooms?.length && diff --git a/src/components/views/rooms/RoomListHeader.tsx b/src/components/views/rooms/RoomListHeader.tsx index 9ce1d7524fb..6b5b4de48a6 100644 --- a/src/components/views/rooms/RoomListHeader.tsx +++ b/src/components/views/rooms/RoomListHeader.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { EventType, RoomType, Room, RoomEvent, ClientEvent } from "matrix-js-sdk/src/matrix"; -import React, { useContext, useEffect, useState } from "react"; +import React, { useContext, useEffect, useState, type JSX } from "react"; import { Tooltip } from "@vector-im/compound-web"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; diff --git a/src/components/views/rooms/RoomPreviewBar.tsx b/src/components/views/rooms/RoomPreviewBar.tsx index b69b01177e3..200b989db75 100644 --- a/src/components/views/rooms/RoomPreviewBar.tsx +++ b/src/components/views/rooms/RoomPreviewBar.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, ReactNode } from "react"; +import React, { ChangeEvent, ReactNode, type JSX } from "react"; import { Room, RoomMember, EventType, RoomType, JoinRule, MatrixError } from "matrix-js-sdk/src/matrix"; import { KnownMembership, RoomJoinRulesEventContent } from "matrix-js-sdk/src/types"; import classNames from "classnames"; diff --git a/src/components/views/rooms/RoomPreviewCard.tsx b/src/components/views/rooms/RoomPreviewCard.tsx index 2c816e4743e..5346495391f 100644 --- a/src/components/views/rooms/RoomPreviewCard.tsx +++ b/src/components/views/rooms/RoomPreviewCard.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { FC, useContext, useState } from "react"; +import React, { FC, useContext, useState, type JSX } from "react"; import { Room, JoinRule } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx index 34961c08530..b132bda07d1 100644 --- a/src/components/views/rooms/RoomSublist.tsx +++ b/src/components/views/rooms/RoomSublist.tsx @@ -13,7 +13,7 @@ import classNames from "classnames"; import { Enable, Resizable } from "re-resizable"; import { Direction } from "re-resizable/lib/resizer"; import * as React from "react"; -import { ComponentType, createRef, ReactComponentElement, ReactNode } from "react"; +import { ComponentType, createRef, ReactComponentElement, ReactNode, type JSX } from "react"; import { polyfillTouchEvent } from "../../../@types/polyfill"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; @@ -506,13 +506,13 @@ export default class RoomSublist extends React.Component { } }; - private renderVisibleTiles(): React.ReactElement[] { + private renderVisibleTiles(): React.ReactElement[] { if (!this.state.isExpanded && !this.props.forceExpanded) { // don't waste time on rendering return []; } - const tiles: React.ReactElement[] = []; + const tiles: React.ReactElement[] = []; if (this.state.rooms) { let visibleRooms = this.state.rooms; @@ -635,7 +635,7 @@ export default class RoomSublist extends React.Component { ); } - private renderHeader(): React.ReactElement { + private renderHeader(): React.ReactElement { return ( {({ onFocus, isActive, ref }) => { @@ -726,7 +726,7 @@ export default class RoomSublist extends React.Component { (e.target as HTMLDivElement).scrollTop = 0; } - public render(): React.ReactElement { + public render(): React.ReactElement { const visibleTiles = this.renderVisibleTiles(); const hidden = !this.state.rooms.length && !this.props.extraTiles?.length && this.props.alwaysVisible !== true; const classes = classNames({ diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 7953c5068db..9f56914f3f4 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -278,7 +278,7 @@ class RoomTile extends React.PureComponent { this.setState({ generalMenuPosition: null }); }; - private renderNotificationsMenu(isActive: boolean): React.ReactElement | null { + private renderNotificationsMenu(isActive: boolean): React.ReactElement | null { if ( MatrixClientPeg.safeGet().isGuest() || this.props.tag === DefaultTagID.Archived || @@ -323,7 +323,7 @@ class RoomTile extends React.PureComponent { ); } - private renderGeneralMenu(): React.ReactElement | null { + private renderGeneralMenu(): React.ReactElement | null { if (!this.showContextMenu) return null; // no menu to show return ( @@ -371,7 +371,7 @@ class RoomTile extends React.PureComponent { return !!this.state.call || (this.props.showMessagePreview && !!this.state.messagePreview); } - public render(): React.ReactElement { + public render(): React.ReactElement { const classes = classNames({ mx_RoomTile: true, mx_RoomTile_sticky: diff --git a/src/components/views/rooms/RoomUpgradeWarningBar.tsx b/src/components/views/rooms/RoomUpgradeWarningBar.tsx index e92be96cb20..5e7d1e372af 100644 --- a/src/components/views/rooms/RoomUpgradeWarningBar.tsx +++ b/src/components/views/rooms/RoomUpgradeWarningBar.tsx @@ -27,8 +27,8 @@ export default class RoomUpgradeWarningBar extends React.PureComponent; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); const tombstone = this.props.room.currentState.getStateEvents("m.room.tombstone", ""); this.state = { diff --git a/src/components/views/rooms/SearchResultTile.tsx b/src/components/views/rooms/SearchResultTile.tsx index 94f5e6da9db..a885fbf8599 100644 --- a/src/components/views/rooms/SearchResultTile.tsx +++ b/src/components/views/rooms/SearchResultTile.tsx @@ -41,8 +41,8 @@ export default class SearchResultTile extends React.Component { // A map of private callEventGroupers = new Map(); - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.buildLegacyCallEventGroupers(this.props.timeline); } diff --git a/src/components/views/rooms/SendMessageComposer.tsx b/src/components/views/rooms/SendMessageComposer.tsx index b3767cbd2a0..0ccef46a91c 100644 --- a/src/components/views/rooms/SendMessageComposer.tsx +++ b/src/components/views/rooms/SendMessageComposer.tsx @@ -249,8 +249,8 @@ export class SendMessageComposer extends React.Component) { - super(props, context); + public constructor(props: ISendMessageComposerProps) { + super(props); if (this.props.mxClient.getCrypto() && this.props.mxClient.isRoomEncrypted(this.props.room.roomId)) { this.prepareToEncrypt = throttle( diff --git a/src/components/views/rooms/Stickerpicker.tsx b/src/components/views/rooms/Stickerpicker.tsx index ad1b11f3688..58f04965c62 100644 --- a/src/components/views/rooms/Stickerpicker.tsx +++ b/src/components/views/rooms/Stickerpicker.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { Room, ClientEvent } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { IWidget } from "matrix-widget-api"; diff --git a/src/components/views/rooms/ThirdPartyMemberInfo.tsx b/src/components/views/rooms/ThirdPartyMemberInfo.tsx index df008199cdf..017514dcdf2 100644 --- a/src/components/views/rooms/ThirdPartyMemberInfo.tsx +++ b/src/components/views/rooms/ThirdPartyMemberInfo.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { EventType, MatrixEvent, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { Button, Text } from "@vector-im/compound-web"; diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index a8335a9902b..9805fed2c4a 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -56,8 +56,8 @@ export default class VoiceRecordComposerTile extends React.PureComponent; private voiceRecordingId: string; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = {}; diff --git a/src/components/views/rooms/WhoIsTypingTile.tsx b/src/components/views/rooms/WhoIsTypingTile.tsx index 85cf4f6dd67..67876047def 100644 --- a/src/components/views/rooms/WhoIsTypingTile.tsx +++ b/src/components/views/rooms/WhoIsTypingTile.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { Room, RoomEvent, RoomMember, RoomMemberEvent, MatrixEvent } from "matrix-js-sdk/src/matrix"; import * as WhoIsTyping from "../../../WhoIsTyping"; diff --git a/src/components/views/rooms/wysiwyg_composer/DynamicImportWysiwygComposer.tsx b/src/components/views/rooms/wysiwyg_composer/DynamicImportWysiwygComposer.tsx index 46210949f5c..e77f5617770 100644 --- a/src/components/views/rooms/wysiwyg_composer/DynamicImportWysiwygComposer.tsx +++ b/src/components/views/rooms/wysiwyg_composer/DynamicImportWysiwygComposer.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, lazy, Suspense } from "react"; +import React, { ComponentProps, lazy, Suspense, type JSX } from "react"; import { ISendEventResponse } from "matrix-js-sdk/src/matrix"; // we need to import the types for TS, but do not import the sendMessage diff --git a/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx b/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx index 98597c73609..6f1691332f6 100644 --- a/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx +++ b/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ForwardedRef, forwardRef, MutableRefObject, useRef } from "react"; +import React, { ForwardedRef, forwardRef, MutableRefObject, useRef, type JSX } from "react"; import classNames from "classnames"; import EditorStateTransfer from "../../../../utils/EditorStateTransfer"; diff --git a/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx b/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx index 7f790978f63..a6f1feb0aeb 100644 --- a/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx +++ b/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ForwardedRef, forwardRef, MutableRefObject, useRef } from "react"; +import React, { ForwardedRef, forwardRef, MutableRefObject, useRef, type JSX } from "react"; import { IEventRelation } from "matrix-js-sdk/src/matrix"; import { useWysiwygSendActionHandler } from "./hooks/useWysiwygSendActionHandler"; diff --git a/src/components/views/rooms/wysiwyg_composer/components/EditionButtons.tsx b/src/components/views/rooms/wysiwyg_composer/components/EditionButtons.tsx index fccd4b7f242..c6dfa958782 100644 --- a/src/components/views/rooms/wysiwyg_composer/components/EditionButtons.tsx +++ b/src/components/views/rooms/wysiwyg_composer/components/EditionButtons.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { _t } from "../../../../../languageHandler"; import AccessibleButton, { ButtonEvent } from "../../../elements/AccessibleButton"; diff --git a/src/components/views/rooms/wysiwyg_composer/components/Emoji.tsx b/src/components/views/rooms/wysiwyg_composer/components/Emoji.tsx index 9ab3d210abc..19f11bc113f 100644 --- a/src/components/views/rooms/wysiwyg_composer/components/Emoji.tsx +++ b/src/components/views/rooms/wysiwyg_composer/components/Emoji.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MenuProps } from "../../../../structures/ContextMenu"; import { EmojiButton } from "../../EmojiButton"; diff --git a/src/components/views/rooms/wysiwyg_composer/components/FormattingButtons.tsx b/src/components/views/rooms/wysiwyg_composer/components/FormattingButtons.tsx index f02f1a4c6b1..453ee0ff590 100644 --- a/src/components/views/rooms/wysiwyg_composer/components/FormattingButtons.tsx +++ b/src/components/views/rooms/wysiwyg_composer/components/FormattingButtons.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { MouseEventHandler, ReactNode } from "react"; +import React, { MouseEventHandler, ReactNode, type JSX } from "react"; import { FormattingFunctions, AllActionStates, ActionState } from "@vector-im/matrix-wysiwyg"; import classNames from "classnames"; import BoldIcon from "@vector-im/compound-design-tokens/assets/web/icons/bold"; diff --git a/src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer.tsx b/src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer.tsx index 787f0dd889d..ad675f9ed11 100644 --- a/src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer.tsx +++ b/src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import classNames from "classnames"; import { IEventRelation } from "matrix-js-sdk/src/matrix"; -import React, { MutableRefObject, ReactNode } from "react"; +import React, { MutableRefObject, ReactNode, type JSX } from "react"; import { useComposerFunctions } from "../hooks/useComposerFunctions"; import { useIsFocused } from "../hooks/useIsFocused"; diff --git a/src/components/views/rooms/wysiwyg_composer/components/WysiwygAutocomplete.tsx b/src/components/views/rooms/wysiwyg_composer/components/WysiwygAutocomplete.tsx index 4d06adcd4e7..e07cb63d184 100644 --- a/src/components/views/rooms/wysiwyg_composer/components/WysiwygAutocomplete.tsx +++ b/src/components/views/rooms/wysiwyg_composer/components/WysiwygAutocomplete.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ForwardedRef, forwardRef, FunctionComponent } from "react"; +import React, { ForwardedRef, forwardRef, FunctionComponent, type JSX } from "react"; import { FormattingFunctions, MappedSuggestion } from "@vector-im/matrix-wysiwyg"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useComposerFunctions.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useComposerFunctions.ts index aa7c672af3a..ab6637f1763 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useComposerFunctions.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useComposerFunctions.ts @@ -11,7 +11,7 @@ import { RefObject, useMemo } from "react"; import { setSelection } from "../utils/selection"; export function useComposerFunctions( - ref: RefObject, + ref: RefObject, setContent: (content: string) => void, ): { clear(): void; diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts index cab3bdefb85..ec7ee36c010 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts @@ -29,7 +29,7 @@ import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext. export function useInputEventProcessor( onSend: () => void, - autocompleteRef: React.RefObject, + autocompleteRef: React.RefObject, initialContent?: string, eventRelation?: IEventRelation, ): (event: WysiwygEvent, composer: Wysiwyg, editor: HTMLElement) => WysiwygEvent | null { @@ -97,7 +97,7 @@ function handleKeyboardEvent( roomContext: Pick, composerContext: ComposerContextState, mxClient: MatrixClient | undefined, - autocompleteRef: React.RefObject, + autocompleteRef: React.RefObject, ): KeyboardEvent | null { const { editorStateTransfer } = composerContext; const isEditing = Boolean(editorStateTransfer); diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useIsFocused.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useIsFocused.ts index de9f758dc66..96f5ac98de5 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useIsFocused.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useIsFocused.ts @@ -13,7 +13,7 @@ export function useIsFocused(): { onFocus(event: FocusEvent): void; } { const [isFocused, setIsFocused] = useState(false); - const timeoutIDRef = useRef(); + const timeoutIDRef = useRef(undefined); useEffect(() => () => clearTimeout(timeoutIDRef.current), [timeoutIDRef]); const onFocus = useCallback( diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextInitialization.ts b/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextInitialization.ts index 6adf43d9a42..c2efa2c65a7 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextInitialization.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextInitialization.ts @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import { RefObject, useEffect } from "react"; -export function usePlainTextInitialization(initialContent = "", ref: RefObject): void { +export function usePlainTextInitialization(initialContent = "", ref: RefObject): void { useEffect(() => { // always read and write the ref.current using .innerHTML for consistency in linebreak and HTML entity handling if (ref.current) { diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners.ts b/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners.ts index 1dc23cc274a..a8325e879cb 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners.ts @@ -49,8 +49,8 @@ export function usePlainTextListeners( eventRelation?: IEventRelation, isAutoReplaceEmojiEnabled?: boolean, ): { - ref: RefObject; - autocompleteRef: React.RefObject; + ref: RefObject; + autocompleteRef: React.RefObject; content?: string; onBeforeInput(event: SyntheticEvent): void; onInput(event: SyntheticEvent): void; diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts index 01d42378a8a..1c6ab4fd127 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useSetCursorPosition.ts @@ -10,7 +10,7 @@ import { RefObject, useEffect } from "react"; import { setCursorPositionAtTheEnd } from "./utils"; -export function useSetCursorPosition(disabled: boolean, ref: RefObject): void { +export function useSetCursorPosition(disabled: boolean, ref: RefObject): void { useEffect(() => { if (ref.current && !disabled) { setCursorPositionAtTheEnd(ref.current); diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts index 5b4957a9c58..15ac18e7f54 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts @@ -45,7 +45,7 @@ type SuggestionState = Suggestion | null; * this will be an object representing that command or mention, otherwise it is null */ export function useSuggestion( - editorRef: React.RefObject, + editorRef: React.RefObject, setText: (text?: string) => void, isAutoReplaceEmojiEnabled?: boolean, ): { @@ -105,7 +105,7 @@ export function useSuggestion( * @param isAutoReplaceEmojiEnabled - whether plain text emoticons should be auto replaced with emojis */ export function processSelectionChange( - editorRef: React.RefObject, + editorRef: React.RefObject, setSuggestionData: React.Dispatch>, isAutoReplaceEmojiEnabled?: boolean, ): void { diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygEditActionHandler.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygEditActionHandler.ts index eb76d77af5d..81b88aa009d 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygEditActionHandler.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygEditActionHandler.ts @@ -22,7 +22,7 @@ import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext. export function useWysiwygEditActionHandler( disabled: boolean, - composerElement: RefObject, + composerElement: RefObject, composerFunctions: ComposerFunctions, ): void { const roomContext = useScopedRoomContext("timelineRenderingType"); diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/utils.ts b/src/components/views/rooms/wysiwyg_composer/hooks/utils.ts index 3345c9f474a..c4af09fb109 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/utils.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/utils.ts @@ -62,7 +62,7 @@ export function setCursorPositionAtTheEnd(element: HTMLElement): void { * @returns boolean - whether or not the autocomplete has handled the event */ export function handleEventWithAutocomplete( - autocompleteRef: RefObject, + autocompleteRef: RefObject, // we get a React Keyboard event from plain text composer, a Keyboard Event from the rich text composer event: KeyboardEvent | React.KeyboardEvent, ): boolean { @@ -80,19 +80,19 @@ export function handleEventWithAutocomplete( switch (autocompleteAction) { case KeyBindingAction.ForceCompleteAutocomplete: case KeyBindingAction.CompleteAutocomplete: - autocompleteRef.current.onConfirmCompletion(); + component.onConfirmCompletion(); handled = true; break; case KeyBindingAction.PrevSelectionInAutocomplete: - autocompleteRef.current.moveSelection(-1); + component.moveSelection(-1); handled = true; break; case KeyBindingAction.NextSelectionInAutocomplete: - autocompleteRef.current.moveSelection(1); + component.moveSelection(1); handled = true; break; case KeyBindingAction.CancelAutocomplete: - autocompleteRef.current.onEscape(event as {} as React.KeyboardEvent); + component.onEscape(event as {} as React.KeyboardEvent); handled = true; break; default: diff --git a/src/components/views/settings/AddRemoveThreepids.tsx b/src/components/views/settings/AddRemoveThreepids.tsx index 8b2b61bb9ac..47406d3fe22 100644 --- a/src/components/views/settings/AddRemoveThreepids.tsx +++ b/src/components/views/settings/AddRemoveThreepids.tsx @@ -40,7 +40,7 @@ interface ExistingThreepidProps { const ExistingThreepid: React.FC = ({ mode, threepid, onChange, disabled }) => { const [isConfirming, setIsConfirming] = useState(false); const client = useMatrixClientContext(); - const bindTask = useRef(); + const bindTask = useRef(undefined); const [isVerifyingBind, setIsVerifyingBind] = useState(false); const [continueDisabled, setContinueDisabled] = useState(false); @@ -289,7 +289,7 @@ const AddThreepidSection: React.FC<{ medium: "email" | "msisdn"; disabled?: bool disabled, onChange, }) => { - const addTask = useRef(); + const addTask = useRef(undefined); const [newThreepidInput, setNewThreepidInput] = useState(""); const [phoneCountryInput, setPhoneCountryInput] = useState(""); const [verificationCodeInput, setVerificationCodeInput] = useState(""); diff --git a/src/components/views/settings/AvatarSetting.tsx b/src/components/views/settings/AvatarSetting.tsx index ee47094cf93..46048cff279 100644 --- a/src/components/views/settings/AvatarSetting.tsx +++ b/src/components/views/settings/AvatarSetting.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode, createRef, useCallback, useEffect, useState, useId } from "react"; +import React, { ReactNode, createRef, useCallback, useEffect, useState, useId, type JSX } from "react"; import EditIcon from "@vector-im/compound-design-tokens/assets/web/icons/edit"; import UploadIcon from "@vector-im/compound-design-tokens/assets/web/icons/share"; import DeleteIcon from "@vector-im/compound-design-tokens/assets/web/icons/delete"; diff --git a/src/components/views/settings/BridgeTile.tsx b/src/components/views/settings/BridgeTile.tsx index 6ae860aa0aa..533904cf9a9 100644 --- a/src/components/views/settings/BridgeTile.tsx +++ b/src/components/views/settings/BridgeTile.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/settings/ChangePassword.tsx b/src/components/views/settings/ChangePassword.tsx index 9461f20d8a0..4ca156bee67 100644 --- a/src/components/views/settings/ChangePassword.tsx +++ b/src/components/views/settings/ChangePassword.tsx @@ -330,7 +330,9 @@ export default class ChangePassword extends React.Component {
(this[FIELD_OLD_PASSWORD] = field)} + ref={(field) => { + this[FIELD_OLD_PASSWORD] = field; + }} type="password" label={_t("auth|change_password_current_label")} value={this.state.oldPassword} @@ -340,7 +342,9 @@ export default class ChangePassword extends React.Component {
(this[FIELD_NEW_PASSWORD] = field)} + fieldRef={(field) => { + this[FIELD_NEW_PASSWORD] = field; + }} type="password" label={_td("auth|change_password_new_label")} minScore={PASSWORD_MIN_SCORE} @@ -353,7 +357,9 @@ export default class ChangePassword extends React.Component {
(this[FIELD_NEW_PASSWORD_CONFIRM] = field)} + ref={(field) => { + this[FIELD_NEW_PASSWORD_CONFIRM] = field; + }} type="password" label={_t("auth|change_password_confirm_label")} value={this.state.newPasswordConfirm} diff --git a/src/components/views/settings/CrossSigningPanel.tsx b/src/components/views/settings/CrossSigningPanel.tsx index a91238848e9..e1b68b5eca8 100644 --- a/src/components/views/settings/CrossSigningPanel.tsx +++ b/src/components/views/settings/CrossSigningPanel.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { ClientEvent, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { CryptoEvent } from "matrix-js-sdk/src/crypto-api"; diff --git a/src/components/views/settings/CryptographyPanel.tsx b/src/components/views/settings/CryptographyPanel.tsx index fbd696f243f..eeffdc78ef8 100644 --- a/src/components/views/settings/CryptographyPanel.tsx +++ b/src/components/views/settings/CryptographyPanel.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { lazy } from "react"; +import React, { lazy, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../languageHandler"; @@ -34,10 +34,10 @@ export default class CryptographyPanel extends React.Component { public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { + public constructor(props: IProps) { super(props); - if (!context.getCrypto()) { + if (!this.context.getCrypto()) { this.state = { deviceIdentityKey: null }; } else { this.state = { deviceIdentityKey: undefined }; diff --git a/src/components/views/settings/EventIndexPanel.tsx b/src/components/views/settings/EventIndexPanel.tsx index 0051c4dc3a0..8ff8fb3b518 100644 --- a/src/components/views/settings/EventIndexPanel.tsx +++ b/src/components/views/settings/EventIndexPanel.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { lazy } from "react"; +import React, { lazy, type JSX } from "react"; import { _t } from "../../../languageHandler"; import SdkConfig from "../../../SdkConfig"; diff --git a/src/components/views/settings/JoinRuleSettings.tsx b/src/components/views/settings/JoinRuleSettings.tsx index a6c1e91241c..94e7b247ad9 100644 --- a/src/components/views/settings/JoinRuleSettings.tsx +++ b/src/components/views/settings/JoinRuleSettings.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode, useEffect, useState } from "react"; +import React, { ReactNode, useEffect, useState, type JSX } from "react"; import { JoinRule, RestrictedAllowType, Room, EventType, Visibility } from "matrix-js-sdk/src/matrix"; import { RoomJoinRulesEventContent } from "matrix-js-sdk/src/types"; diff --git a/src/components/views/settings/KeyboardShortcut.tsx b/src/components/views/settings/KeyboardShortcut.tsx index 4f0973b1027..d35f88f40e2 100644 --- a/src/components/views/settings/KeyboardShortcut.tsx +++ b/src/components/views/settings/KeyboardShortcut.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { ALTERNATE_KEY_NAME, KEY_ICON } from "../../../accessibility/KeyboardShortcuts"; import { KeyCombo } from "../../../KeyBindingsManager"; diff --git a/src/components/views/settings/Notifications.tsx b/src/components/views/settings/Notifications.tsx index 4ac5e2069b0..85586872178 100644 --- a/src/components/views/settings/Notifications.tsx +++ b/src/components/views/settings/Notifications.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { IAnnotatedPushRule, IPusher, diff --git a/src/components/views/settings/SecureBackupPanel.tsx b/src/components/views/settings/SecureBackupPanel.tsx index 05c78296441..ca9a1667893 100644 --- a/src/components/views/settings/SecureBackupPanel.tsx +++ b/src/components/views/settings/SecureBackupPanel.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { lazy, ReactNode } from "react"; +import React, { lazy, ReactNode, type JSX } from "react"; import { CryptoEvent, BackupTrustInfo, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/settings/SetIdServer.tsx b/src/components/views/settings/SetIdServer.tsx index 8ed6461d0a3..be4774dd204 100644 --- a/src/components/views/settings/SetIdServer.tsx +++ b/src/components/views/settings/SetIdServer.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { IThreepid } from "matrix-js-sdk/src/matrix"; diff --git a/src/components/views/settings/UpdateCheckButton.tsx b/src/components/views/settings/UpdateCheckButton.tsx index 3b2c9bfa681..3973ef44516 100644 --- a/src/components/views/settings/UpdateCheckButton.tsx +++ b/src/components/views/settings/UpdateCheckButton.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode, useState } from "react"; +import React, { ReactNode, useState, type JSX } from "react"; import { UpdateCheckStatus } from "../../../BasePlatform"; import PlatformPeg from "../../../PlatformPeg"; diff --git a/src/components/views/settings/UserProfileSettings.tsx b/src/components/views/settings/UserProfileSettings.tsx index 83a00c122d4..23e5b9fa944 100644 --- a/src/components/views/settings/UserProfileSettings.tsx +++ b/src/components/views/settings/UserProfileSettings.tsx @@ -59,7 +59,6 @@ interface ManageAccountButtonProps { const ManageAccountButton: React.FC = ({ externalAccountManagementUrl }) => ( = Omit< +type Props = Omit< ComponentProps>, "aria-label" | "title" | "kind" | "className" | "onClick" | "element" > & { @@ -21,7 +21,7 @@ type Props = Omit< onClick: () => void; }; -export const DeviceExpandDetailsButton = ({ +export const DeviceExpandDetailsButton = ({ isExpanded, onClick, ...rest diff --git a/src/components/views/settings/notifications/NotificationPusherSettings.tsx b/src/components/views/settings/notifications/NotificationPusherSettings.tsx index 9e17e7b829d..d54fce41582 100644 --- a/src/components/views/settings/notifications/NotificationPusherSettings.tsx +++ b/src/components/views/settings/notifications/NotificationPusherSettings.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { ThreepidMedium, IPusher } from "matrix-js-sdk/src/matrix"; -import React, { useCallback, useMemo } from "react"; +import React, { useCallback, useMemo, type JSX } from "react"; import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext"; import { Action } from "../../../../dispatcher/actions"; diff --git a/src/components/views/settings/notifications/NotificationSettings2.tsx b/src/components/views/settings/notifications/NotificationSettings2.tsx index 5f91c3874c7..53c84957625 100644 --- a/src/components/views/settings/notifications/NotificationSettings2.tsx +++ b/src/components/views/settings/notifications/NotificationSettings2.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useState } from "react"; +import React, { useState, type JSX } from "react"; import NewAndImprovedIcon from "../../../../../res/img/element-icons/new-and-improved.svg"; import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext"; diff --git a/src/components/views/settings/shared/SettingsBanner.tsx b/src/components/views/settings/shared/SettingsBanner.tsx index c35703bf16a..fc99860d500 100644 --- a/src/components/views/settings/shared/SettingsBanner.tsx +++ b/src/components/views/settings/shared/SettingsBanner.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { PropsWithChildren, ReactNode } from "react"; +import React, { PropsWithChildren, ReactNode, type JSX } from "react"; import AccessibleButton from "../../elements/AccessibleButton"; diff --git a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx index 5798771e678..0098531721e 100644 --- a/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/AdvancedRoomSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { EventType, Room } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../../../languageHandler"; diff --git a/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx b/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx index 0da257607ee..23ceb06ddac 100644 --- a/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { Room, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../../../languageHandler"; diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx index 31c361de1bd..05b0a6d8b85 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx @@ -35,8 +35,8 @@ export default class GeneralRoomSettingsTab extends React.Component; - public constructor(props: IProps, context: ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { isRoomPublished: false, // loaded async diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx index 9aabf1edb0d..0dc627247d0 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { createRef, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../../../languageHandler"; @@ -44,10 +44,10 @@ export default class NotificationsSettingsTab extends React.Component; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); - this.roomProps = EchoChamber.forRoom(context.getRoom(this.props.roomId)!); + this.roomProps = EchoChamber.forRoom(this.context.getRoom(this.props.roomId)!); let currentSound = "default"; const soundData = Notifier.getSoundForRoom(this.props.roomId); diff --git a/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx index 768d35890a2..488efe37024 100644 --- a/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import { EventTimeline, MatrixError, Room, RoomMember, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; -import React, { useCallback, useState, VFC } from "react"; +import React, { useCallback, useState, FC } from "react"; import { CloseIcon, CheckIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { formatRelativeTime } from "../../../../../DateUtils"; @@ -22,13 +22,13 @@ import SettingsFieldset from "../../SettingsFieldset"; import { SettingsSection } from "../../shared/SettingsSection"; import SettingsTab from "../SettingsTab"; -const Timestamp: VFC<{ roomMember: RoomMember }> = ({ roomMember }) => { +const Timestamp: FC<{ roomMember: RoomMember }> = ({ roomMember }) => { const timestamp = roomMember.events.member?.event.origin_server_ts; if (!timestamp) return null; return ; }; -const SeeMoreOrLess: VFC<{ roomMember: RoomMember }> = ({ roomMember }) => { +const SeeMoreOrLess: FC<{ roomMember: RoomMember }> = ({ roomMember }) => { const [seeMore, setSeeMore] = useState(false); const reason = roomMember.events.member?.getContent().reason; @@ -51,7 +51,7 @@ const SeeMoreOrLess: VFC<{ roomMember: RoomMember }> = ({ roomMember }) => { ); }; -const Knock: VFC<{ +const Knock: FC<{ canInvite: boolean; canKick: boolean; onApprove: (userId: string) => Promise; @@ -103,7 +103,7 @@ const Knock: VFC<{ ); }; -export const PeopleRoomSettingsTab: VFC<{ room: Room }> = ({ room }) => { +export const PeopleRoomSettingsTab: FC<{ room: Room }> = ({ room }) => { const client = room.client; const userId = client.getUserId() || ""; const canInvite = room.canInvite(userId); diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index baf4b412539..852a577c233 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { EventType, RoomMember, RoomState, RoomStateEvent, Room, IContent } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { throttle, get } from "lodash"; diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index ece6a7deafc..7afcf8fc57a 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { GuestAccess, HistoryVisibility, @@ -62,8 +62,8 @@ export default class SecurityRoomSettingsTab extends React.Component; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); const state = this.props.room.currentState; diff --git a/src/components/views/settings/tabs/user/AccountUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AccountUserSettingsTab.tsx index cd52b2a76b2..303ba37cdd6 100644 --- a/src/components/views/settings/tabs/user/AccountUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AccountUserSettingsTab.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useCallback, useContext, useEffect } from "react"; +import React, { useCallback, useContext, useEffect, type JSX } from "react"; import { HTTPError } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index f19343be206..b521eeef9cb 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import AccessibleButton from "../../../elements/AccessibleButton"; @@ -34,8 +34,8 @@ export default class HelpUserSettingsTab extends React.Component public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { - super(props, context); + public constructor(props: IProps) { + super(props); this.state = { appVersion: null, diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx index 54995415e2e..afce03b5670 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { sortBy } from "lodash"; import { _t } from "../../../../../languageHandler"; diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx index 9ad7df31e98..c7550b6ac10 100644 --- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ChangeEvent, SyntheticEvent } from "react"; +import React, { ChangeEvent, SyntheticEvent, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../../../languageHandler"; diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index 8cb662a9f02..24b97dc5dc6 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -220,7 +220,7 @@ export default class PreferencesUserSettingsTab extends React.Component { return settingIds.map((i) => ); } @@ -248,7 +248,7 @@ export default class PreferencesUserSettingsTab extends React.Component{browserTimezoneLabel}
); return ( - + ( {/* The heading string is still 'general' from where it was moved, but this section should become 'general' */} @@ -297,7 +297,7 @@ export default class PreferencesUserSettingsTab extends React.Component - {timezones as NonEmptyArray} + {timezones as NonEmptyArray & { key: string }>}
@@ -368,7 +368,7 @@ export default class PreferencesUserSettingsTab extends React.Component - + ) ); } } diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index 7d5e27580cc..7cf37eb389a 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { sleep } from "matrix-js-sdk/src/utils"; import { Room, RoomEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership, Membership } from "matrix-js-sdk/src/types"; diff --git a/src/components/views/settings/tabs/user/SessionManagerTab.tsx b/src/components/views/settings/tabs/user/SessionManagerTab.tsx index 5e9445bb995..39132f12fe4 100644 --- a/src/components/views/settings/tabs/user/SessionManagerTab.tsx +++ b/src/components/views/settings/tabs/user/SessionManagerTab.tsx @@ -166,7 +166,7 @@ const SessionManagerTab: React.FC<{ const [expandedDeviceIds, setExpandedDeviceIds] = useState([]); const [selectedDeviceIds, setSelectedDeviceIds] = useState([]); const filteredDeviceListRef = useRef(null); - const scrollIntoViewTimeoutRef = useRef(); + const scrollIntoViewTimeoutRef = useRef(undefined); const sdkContext = useContext(SDKContext); const matrixClient = sdkContext.client!; diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx index 9711159a10e..71cece31a12 100644 --- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { FALLBACK_ICE_SERVER } from "matrix-js-sdk/src/webrtc/call"; @@ -53,8 +53,8 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> { public static contextType = MatrixClientContext; declare public context: React.ContextType; - public constructor(props: {}, context: React.ContextType) { - super(props, context); + public constructor(props: {}) { + super(props); this.state = { mediaDevices: null, diff --git a/src/components/views/spaces/QuickSettingsButton.tsx b/src/components/views/spaces/QuickSettingsButton.tsx index 161290fca88..85c6369ff22 100644 --- a/src/components/views/spaces/QuickSettingsButton.tsx +++ b/src/components/views/spaces/QuickSettingsButton.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import { OverflowHorizontalIcon, diff --git a/src/components/views/spaces/QuickThemeSwitcher.tsx b/src/components/views/spaces/QuickThemeSwitcher.tsx index 195fcb98991..9a53c1c87f4 100644 --- a/src/components/views/spaces/QuickThemeSwitcher.tsx +++ b/src/components/views/spaces/QuickThemeSwitcher.tsx @@ -71,7 +71,7 @@ const QuickThemeSwitcher: React.FC = ({ requestClose }) => { }; return ( -
+ (

{_t("common|theme")}

= ({ requestClose }) => { > { themeOptions.map((theme) =>
{theme.name}
) as NonEmptyArray< - ReactElement & { key: string } + ReactElement & { key: string } > }
-
+
) ); }; diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index 764417e0b2c..ca3c136543a 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -119,8 +119,8 @@ type BProps = Omit, "nameDisabled" | " interface ISpaceCreateFormProps extends BProps { busy: boolean; alias: string; - nameFieldRef: RefObject; - aliasFieldRef: RefObject; + nameFieldRef: RefObject; + aliasFieldRef: RefObject; showAliasField?: boolean; children?: ReactNode; onSubmit(e: SyntheticEvent): void; diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx index af484445b42..53b8207d694 100644 --- a/src/components/views/spaces/SpacePanel.tsx +++ b/src/components/views/spaces/SpacePanel.tsx @@ -17,6 +17,7 @@ import React, { useLayoutEffect, useRef, useState, + type JSX, } from "react"; import { DragDropContext, Draggable, Droppable, DroppableProvidedProps } from "react-beautiful-dnd"; import classNames from "classnames"; diff --git a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx index 47f4fe8ce9f..e4179cf3e7d 100644 --- a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx +++ b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useState } from "react"; +import React, { useState, type JSX } from "react"; import { Room, EventType, GuestAccess, HistoryVisibility, JoinRule, MatrixClient } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../languageHandler"; diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index cee4cf54ecd..cfff57c910c 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -12,8 +12,9 @@ import React, { ComponentType, createRef, InputHTMLAttributes, - LegacyRef, + Ref, RefObject, + type JSX, } from "react"; import classNames from "classnames"; import { Room, RoomEvent } from "matrix-js-sdk/src/matrix"; @@ -39,7 +40,7 @@ import SpaceContextMenu from "../context_menus/SpaceContextMenu"; import { useRovingTabIndex } from "../../../accessibility/RovingTabIndex"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; -type ButtonProps = Omit< +type ButtonProps = Omit< ComponentProps>, "title" | "onClick" | "size" | "element" > & { @@ -52,12 +53,12 @@ type ButtonProps = Omit< notificationState?: NotificationState; isNarrow?: boolean; size: string; - innerRef?: RefObject; + innerRef?: RefObject; ContextMenuComponent?: ComponentType>; onClick?(ev?: ButtonEvent): void; }; -export const SpaceButton = ({ +export const SpaceButton = ({ space, spaceKey: _spaceKey, className, @@ -178,7 +179,7 @@ interface IItemProps extends InputHTMLAttributes { isPanelCollapsed?: boolean; onExpand?: () => void; parents?: Set; - innerRef?: LegacyRef; + innerRef?: Ref; dragHandleProps?: DraggableProvidedDragHandleProps | null; } diff --git a/src/components/views/terms/InlineTermsAgreement.tsx b/src/components/views/terms/InlineTermsAgreement.tsx index 350c408d750..b7dae1d1c9b 100644 --- a/src/components/views/terms/InlineTermsAgreement.tsx +++ b/src/components/views/terms/InlineTermsAgreement.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { _t, pickBestLanguage } from "../../../languageHandler"; import { objectClone } from "../../../utils/objects"; diff --git a/src/components/views/user-onboarding/UserOnboardingButton.tsx b/src/components/views/user-onboarding/UserOnboardingButton.tsx index d1e420d4ac7..a8941fc5ae4 100644 --- a/src/components/views/user-onboarding/UserOnboardingButton.tsx +++ b/src/components/views/user-onboarding/UserOnboardingButton.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { useCallback } from "react"; +import React, { useCallback, type JSX } from "react"; import { Action } from "../../../dispatcher/actions"; import defaultDispatcher from "../../../dispatcher/dispatcher"; diff --git a/src/components/views/user-onboarding/UserOnboardingHeader.tsx b/src/components/views/user-onboarding/UserOnboardingHeader.tsx index 1f6edbff1da..70b7b43d398 100644 --- a/src/components/views/user-onboarding/UserOnboardingHeader.tsx +++ b/src/components/views/user-onboarding/UserOnboardingHeader.tsx @@ -16,6 +16,8 @@ import { UseCase } from "../../../settings/enums/UseCase"; import AccessibleButton, { ButtonEvent } from "../../views/elements/AccessibleButton"; import Heading from "../../views/typography/Heading"; +import type { JSX } from "react"; + const onClickSendDm = (ev: ButtonEvent): void => { PosthogTrackers.trackInteraction("WebUserOnboardingHeaderSendDm", ev); defaultDispatcher.dispatch({ action: "view_create_chat" }); diff --git a/src/components/views/user-onboarding/UserOnboardingList.tsx b/src/components/views/user-onboarding/UserOnboardingList.tsx index c6c03527cb5..48f12c96809 100644 --- a/src/components/views/user-onboarding/UserOnboardingList.tsx +++ b/src/components/views/user-onboarding/UserOnboardingList.tsx @@ -15,6 +15,8 @@ import ProgressBar from "../../views/elements/ProgressBar"; import Heading from "../../views/typography/Heading"; import { UserOnboardingTask } from "./UserOnboardingTask"; +import type { JSX } from "react"; + export const getUserOnboardingCounters = ( tasks: UserOnboardingTaskWithResolvedCompletion[], ): { diff --git a/src/components/views/user-onboarding/UserOnboardingPage.tsx b/src/components/views/user-onboarding/UserOnboardingPage.tsx index ebb9b9565e3..f8faea4285c 100644 --- a/src/components/views/user-onboarding/UserOnboardingPage.tsx +++ b/src/components/views/user-onboarding/UserOnboardingPage.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import { useEffect, useState } from "react"; +import { useEffect, useState, type JSX } from "react"; import * as React from "react"; import { useInitialSyncComplete } from "../../../hooks/useIsInitialSyncComplete"; diff --git a/src/components/views/user-onboarding/UserOnboardingTask.tsx b/src/components/views/user-onboarding/UserOnboardingTask.tsx index add9db1b35e..dee68172c06 100644 --- a/src/components/views/user-onboarding/UserOnboardingTask.tsx +++ b/src/components/views/user-onboarding/UserOnboardingTask.tsx @@ -13,6 +13,8 @@ import { UserOnboardingTaskWithResolvedCompletion } from "../../../hooks/useUser import AccessibleButton from "../../views/elements/AccessibleButton"; import Heading from "../../views/typography/Heading"; +import type { JSX } from "react"; + interface Props { task: UserOnboardingTaskWithResolvedCompletion; completed?: boolean; diff --git a/src/components/views/voip/AudioFeedArrayForLegacyCall.tsx b/src/components/views/voip/AudioFeedArrayForLegacyCall.tsx index b135bb02798..d025b488532 100644 --- a/src/components/views/voip/AudioFeedArrayForLegacyCall.tsx +++ b/src/components/views/voip/AudioFeedArrayForLegacyCall.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { CallEvent, MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import { CallFeed } from "matrix-js-sdk/src/webrtc/callFeed"; diff --git a/src/components/views/voip/DialPad.tsx b/src/components/views/voip/DialPad.tsx index 9dda9468d84..6100577aa15 100644 --- a/src/components/views/voip/DialPad.tsx +++ b/src/components/views/voip/DialPad.tsx @@ -12,6 +12,8 @@ import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import { _t } from "../../../languageHandler"; import { XOR } from "../../../@types/common"; +import type { JSX } from "react"; + export const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"]; export const BUTTON_LETTERS = ["", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ", "", "+", ""]; diff --git a/src/components/views/voip/DialPadModal.tsx b/src/components/views/voip/DialPadModal.tsx index b4b7cdf6472..651002e86f3 100644 --- a/src/components/views/voip/DialPadModal.tsx +++ b/src/components/views/voip/DialPadModal.tsx @@ -23,7 +23,7 @@ interface IState { } export default class DialpadModal extends React.PureComponent { - private numberEntryFieldRef: React.RefObject = createRef(); + private numberEntryFieldRef: React.RefObject = createRef(); public constructor(props: IProps) { super(props); diff --git a/src/components/views/voip/LegacyCallView.tsx b/src/components/views/voip/LegacyCallView.tsx index aba3d60743d..8da2985e7a2 100644 --- a/src/components/views/voip/LegacyCallView.tsx +++ b/src/components/views/voip/LegacyCallView.tsx @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { createRef } from "react"; +import React, { createRef, type JSX } from "react"; import { CallEvent, CallState, MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import classNames from "classnames"; import { CallFeed } from "matrix-js-sdk/src/webrtc/callFeed"; diff --git a/src/contexts/MatrixClientContext.tsx b/src/contexts/MatrixClientContext.tsx index ec804f881bc..559fa24fe02 100644 --- a/src/contexts/MatrixClientContext.tsx +++ b/src/contexts/MatrixClientContext.tsx @@ -28,7 +28,7 @@ const matrixHOC = ( ComposedComponent: ComponentClass, ): (( props: Omit & React.RefAttributes>, -) => React.ReactElement | null) => { +) => React.ReactElement | null) => { type ComposedComponentInstance = InstanceType; // eslint-disable-next-line react-hooks/rules-of-hooks diff --git a/src/contexts/ScopedRoomContext.tsx b/src/contexts/ScopedRoomContext.tsx index 1222443d290..a64dddf8eb4 100644 --- a/src/contexts/ScopedRoomContext.tsx +++ b/src/contexts/ScopedRoomContext.tsx @@ -7,7 +7,17 @@ Please see LICENSE files in the repository root for full details. */ import { TypedEventEmitter } from "matrix-js-sdk/src/matrix"; -import React, { ContextType, createContext, memo, ReactNode, useContext, useEffect, useRef, useState } from "react"; +import React, { + ContextType, + createContext, + memo, + ReactNode, + useContext, + useEffect, + useRef, + useState, + type JSX, +} from "react"; import { objectKeyChanges } from "../utils/objects.ts"; import { useTypedEventEmitter } from "../hooks/useEventEmitter.ts"; diff --git a/src/events/EventTileFactory.tsx b/src/events/EventTileFactory.tsx index ec1651872af..45abb107f6f 100644 --- a/src/events/EventTileFactory.tsx +++ b/src/events/EventTileFactory.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { MatrixEvent, EventType, @@ -42,6 +42,7 @@ import HiddenBody from "../components/views/messages/HiddenBody"; import ViewSourceEvent from "../components/views/messages/ViewSourceEvent"; import { shouldDisplayAsBeaconTile } from "../utils/beacon/timeline"; import { ElementCall } from "../models/Call"; +import { IBodyProps } from "../components/views/messages/IBodyProps.ts"; // Subset of EventTile's IProps plus some mixins export interface EventTileTypeProps @@ -64,8 +65,8 @@ export interface EventTileTypeProps ref?: React.RefObject; // `any` because it's effectively impossible to convince TS of a reasonable type timestamp?: JSX.Element; maxImageHeight?: number; // pixels - overrideBodyTypes?: Record; - overrideEventTypes?: Record; + overrideBodyTypes?: Record>; + overrideEventTypes?: Record>; } type FactoryProps = Omit; diff --git a/src/hooks/useTimeout.ts b/src/hooks/useTimeout.ts index c88de82c0f0..1c9760e8327 100644 --- a/src/hooks/useTimeout.ts +++ b/src/hooks/useTimeout.ts @@ -13,7 +13,7 @@ type Handler = () => void; // Hook to simplify timeouts in functional components export const useTimeout = (handler: Handler, timeoutMs: number): void => { // Create a ref that stores handler - const savedHandler = useRef(); + const savedHandler = useRef(undefined); // Update ref.current value if handler changes. useEffect(() => { @@ -32,7 +32,7 @@ export const useTimeout = (handler: Handler, timeoutMs: number): void => { // Hook to simplify intervals in functional components export const useInterval = (handler: Handler, intervalMs: number): void => { // Create a ref that stores handler - const savedHandler = useRef(); + const savedHandler = useRef(undefined); // Update ref.current value if handler changes. useEffect(() => { diff --git a/src/hooks/useTimeoutToggle.ts b/src/hooks/useTimeoutToggle.ts index 83f1bc333bb..78e88ced526 100644 --- a/src/hooks/useTimeoutToggle.ts +++ b/src/hooks/useTimeoutToggle.ts @@ -21,7 +21,7 @@ export const useTimeoutToggle = ( value: boolean; toggle(): void; } => { - const timeoutId = useRef(); + const timeoutId = useRef(undefined); const [value, setValue] = useState(defaultValue); const toggle = (): void => { diff --git a/src/modules/ProxiedModuleApi.ts b/src/modules/ProxiedModuleApi.ts index 34735afe0ff..9cdeaa5cdf0 100644 --- a/src/modules/ProxiedModuleApi.ts +++ b/src/modules/ProxiedModuleApi.ts @@ -10,7 +10,7 @@ import { ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi"; import { TranslationStringsObject, PlainSubstitution } from "@matrix-org/react-sdk-module-api/lib/types/translations"; import { Optional } from "matrix-events-sdk"; import { DialogContent, DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent"; -import React from "react"; +import React, { type JSX } from "react"; import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo"; import * as Matrix from "matrix-js-sdk/src/matrix"; import { IRegisterRequestParams } from "matrix-js-sdk/src/matrix"; @@ -78,7 +78,7 @@ export class ProxiedModuleApi implements ModuleApi { */ public openDialog>( initialTitleOrOptions: string | ModuleUiDialogOptions, - body: (props: P, ref: React.RefObject) => React.ReactNode, + body: (props: P, ref: React.RefObject) => JSX.Element, props?: Omit, ): Promise<{ didOkOrSubmit: boolean; model: M }> { const initialOptions: ModuleUiDialogOptions = diff --git a/src/toasts/AnalyticsToast.tsx b/src/toasts/AnalyticsToast.tsx index c9cd218b49e..91b8fdcb61f 100644 --- a/src/toasts/AnalyticsToast.tsx +++ b/src/toasts/AnalyticsToast.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { _t } from "../languageHandler"; import SdkConfig from "../SdkConfig"; diff --git a/src/toasts/IncomingCallToast.tsx b/src/toasts/IncomingCallToast.tsx index 58e6980733e..ca021ed77d8 100644 --- a/src/toasts/IncomingCallToast.tsx +++ b/src/toasts/IncomingCallToast.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState, type JSX } from "react"; import { MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix"; import { Button, Tooltip, TooltipProvider } from "@vector-im/compound-web"; import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid"; diff --git a/src/utils/FormattingUtils.ts b/src/utils/FormattingUtils.ts index d16ced944a5..ba911546254 100644 --- a/src/utils/FormattingUtils.ts +++ b/src/utils/FormattingUtils.ts @@ -85,7 +85,7 @@ export function getUserNameColorClass(userId: string): string { * between each item, but with the last item appended as " and [lastItem]". */ export function formatList(items: string[], itemLimit?: number, includeCount?: boolean): string; -export function formatList(items: ReactElement[], itemLimit?: number, includeCount?: boolean): ReactElement; +export function formatList(items: ReactElement[], itemLimit?: number, includeCount?: boolean): ReactElement; export function formatList(items: ReactNode[], itemLimit?: number, includeCount?: boolean): ReactNode; export function formatList(items: ReactNode[], itemLimit = items.length, includeCount = false): ReactNode { let remaining = Math.max(items.length - itemLimit, 0); diff --git a/src/utils/MessageDiffUtils.tsx b/src/utils/MessageDiffUtils.tsx index ff30b12cac1..dfcfe05325f 100644 --- a/src/utils/MessageDiffUtils.tsx +++ b/src/utils/MessageDiffUtils.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import classNames from "classnames"; import DiffMatchPatch from "diff-match-patch"; import { DiffDOM, IDiff } from "diff-dom"; diff --git a/src/utils/ReactUtils.tsx b/src/utils/ReactUtils.tsx index ee7469945a3..14ca1142707 100644 --- a/src/utils/ReactUtils.tsx +++ b/src/utils/ReactUtils.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactNode } from "react"; +import React, { ReactNode, type JSX } from "react"; /** * Joins an array into one value with a joiner. E.g. join(["hello", "world"], " ") -> hello world diff --git a/src/utils/exportUtils/HtmlExport.tsx b/src/utils/exportUtils/HtmlExport.tsx index e5b4667fc22..bb0382f998a 100644 --- a/src/utils/exportUtils/HtmlExport.tsx +++ b/src/utils/exportUtils/HtmlExport.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { createRoot } from "react-dom/client"; import { Room, MatrixEvent, EventType, MsgType } from "matrix-js-sdk/src/matrix"; import { renderToStaticMarkup } from "react-dom/server"; diff --git a/src/utils/react.tsx b/src/utils/react.tsx index b78f574fa97..4d2c8e12ca3 100644 --- a/src/utils/react.tsx +++ b/src/utils/react.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import { ReactNode } from "react"; +import { type JSX } from "react"; import { createRoot, Root } from "react-dom/client"; /** @@ -27,7 +27,7 @@ export class ReactRootManager { * @param rootElement the root element to render the component into * @param revertElement the element to replace the root element with when unmounting */ - public render(children: ReactNode, rootElement: Element, revertElement?: Element): void { + public render(children: JSX.Element, rootElement: Element, revertElement?: Element): void { const root = createRoot(rootElement); this.roots.push(root); this.rootElements.push(rootElement); diff --git a/src/vector/app.tsx b/src/vector/app.tsx index 426163db0bb..6486d117bfb 100644 --- a/src/vector/app.tsx +++ b/src/vector/app.tsx @@ -12,7 +12,7 @@ Please see LICENSE files in the repository root for full details. // To ensure we load the browser-matrix version first import "matrix-js-sdk/src/browser-index"; -import React, { ReactElement, StrictMode } from "react"; +import React, { type JSX, StrictMode } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { createClient, AutoDiscovery, ClientConfig } from "matrix-js-sdk/src/matrix"; import { WrapperLifecycle, WrapperOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/WrapperLifecycle"; @@ -54,7 +54,7 @@ function onTokenLoginCompleted(): void { window.history.replaceState(null, "", url.href); } -export async function loadApp(fragParams: {}, matrixChatRef: React.Ref): Promise { +export async function loadApp(fragParams: {}, matrixChatRef: React.Ref): Promise { initRouting(); const platform = PlatformPeg.get(); diff --git a/test/unit-tests/HtmlUtils-test.tsx b/test/unit-tests/HtmlUtils-test.tsx index a13c04af039..71635b66269 100644 --- a/test/unit-tests/HtmlUtils-test.tsx +++ b/test/unit-tests/HtmlUtils-test.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ReactElement } from "react"; +import React, { DOMAttributes, ReactElement } from "react"; import { mocked } from "jest-mock"; import { render, screen } from "jest-matrix-react"; import { IContent } from "matrix-js-sdk/src/matrix"; @@ -57,8 +57,9 @@ describe("topicToHtml", () => { }); describe("bodyToHtml", () => { - function getHtml(content: IContent, highlights?: string[]): string { - return (bodyToSpan(content, highlights, {}) as ReactElement).props.dangerouslySetInnerHTML.__html; + function getHtml(content: IContent, highlights?: string[]): string | TrustedHTML | undefined { + return ((bodyToSpan(content, highlights, {}) as ReactElement).props as DOMAttributes) + .dangerouslySetInnerHTML?.__html; } it("should apply highlights to HTML messages", () => { diff --git a/test/unit-tests/components/structures/FilePanel-test.tsx b/test/unit-tests/components/structures/FilePanel-test.tsx index 25bdd996768..974b8c6d024 100644 --- a/test/unit-tests/components/structures/FilePanel-test.tsx +++ b/test/unit-tests/components/structures/FilePanel-test.tsx @@ -65,7 +65,9 @@ describe("FilePanel", () => { roomId={room.roomId} onClose={jest.fn()} resizeNotifier={new ResizeNotifier()} - ref={(ref) => (filePanel = ref)} + ref={(ref) => { + filePanel = ref; + }} />, ); await screen.findByText("No files visible in this room"); diff --git a/test/unit-tests/components/structures/RoomView-test.tsx b/test/unit-tests/components/structures/RoomView-test.tsx index 385204c01b3..6cee3900695 100644 --- a/test/unit-tests/components/structures/RoomView-test.tsx +++ b/test/unit-tests/components/structures/RoomView-test.tsx @@ -118,7 +118,7 @@ describe("RoomView", () => { cleanup(); }); - const mountRoomView = async (ref?: RefObject): Promise => { + const mountRoomView = async (ref?: RefObject): Promise => { if (stores.roomViewStore.getRoomId() !== room.roomId) { const switchedRoom = new Promise((resolve) => { const subFn = () => { diff --git a/test/unit-tests/components/structures/TimelinePanel-test.tsx b/test/unit-tests/components/structures/TimelinePanel-test.tsx index 442ed1c1d28..1d4360b0131 100644 --- a/test/unit-tests/components/structures/TimelinePanel-test.tsx +++ b/test/unit-tests/components/structures/TimelinePanel-test.tsx @@ -204,7 +204,9 @@ describe("TimelinePanel", () => { timelineSet={timelineSet} manageReadMarkers={true} manageReadReceipts={true} - ref={(ref) => (timelinePanel = ref)} + ref={(ref) => { + timelinePanel = ref; + }} />, ); await flushPromises(); diff --git a/test/unit-tests/components/views/audio_messages/SeekBar-test.tsx b/test/unit-tests/components/views/audio_messages/SeekBar-test.tsx index 2ea445b499e..996d1d7d884 100644 --- a/test/unit-tests/components/views/audio_messages/SeekBar-test.tsx +++ b/test/unit-tests/components/views/audio_messages/SeekBar-test.tsx @@ -18,7 +18,7 @@ describe("SeekBar", () => { let playback: Playback; let renderResult: RenderResult; let frameRequestCallback: FrameRequestCallback; - let seekBarRef: RefObject; + let seekBarRef: RefObject; beforeEach(() => { seekBarRef = createRef(); diff --git a/test/unit-tests/components/views/rooms/VoiceRecordComposerTile-test.tsx b/test/unit-tests/components/views/rooms/VoiceRecordComposerTile-test.tsx index a8d4b022a6b..5f7ff56f9f0 100644 --- a/test/unit-tests/components/views/rooms/VoiceRecordComposerTile-test.tsx +++ b/test/unit-tests/components/views/rooms/VoiceRecordComposerTile-test.tsx @@ -34,7 +34,7 @@ jest.mock("../../../../../src/stores/VoiceRecordingStore", () => ({ })); describe("", () => { - let voiceRecordComposerTile: RefObject; + let voiceRecordComposerTile: RefObject; let mockRecorder: VoiceMessageRecording; let mockUpload: IUpload; let mockClient: MatrixClient; diff --git a/test/unit-tests/modules/ProxiedModuleApi-test.tsx b/test/unit-tests/modules/ProxiedModuleApi-test.tsx index 9a93a3c76cc..a554a32818d 100644 --- a/test/unit-tests/modules/ProxiedModuleApi-test.tsx +++ b/test/unit-tests/modules/ProxiedModuleApi-test.tsx @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type JSX } from "react"; import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations"; import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo"; import { DialogContent, DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent"; @@ -236,7 +236,7 @@ describe("ProxiedApiModule", () => { super(props); } trySubmit = async () => ({ result: true }); - render = () => ( + render = (): JSX.Element => ( diff --git a/yarn.lock b/yarn.lock index aa431c02049..967b828c28d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2702,10 +2702,10 @@ lodash "^4.17.21" redent "^3.0.0" -"@testing-library/react@^16.0.0": - version "16.0.1" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.1.tgz#29c0ee878d672703f5e7579f239005e4e0faa875" - integrity sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg== +"@testing-library/react@^16.1.0": + version "16.1.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.1.0.tgz#aa0c61398bac82eaf89776967e97de41ac742d71" + integrity sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg== dependencies: "@babel/runtime" "^7.12.5" @@ -3126,11 +3126,6 @@ resolved "https://registry.yarnpkg.com/@types/pbf/-/pbf-3.0.5.tgz#a9495a58d8c75be4ffe9a0bd749a307715c07404" integrity sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA== -"@types/prop-types@*": - version "15.7.13" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451" - integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA== - "@types/qrcode@^1.3.5": version "1.5.5" resolved "https://registry.yarnpkg.com/@types/qrcode/-/qrcode-1.5.5.tgz#993ff7c6b584277eee7aac0a20861eab682f9dac" @@ -3155,10 +3150,10 @@ dependencies: "@types/react" "*" -"@types/react-dom@18.3.1": - version "18.3.1" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.1.tgz#1e4654c08a9cdcfb6594c780ac59b55aad42fe07" - integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ== +"@types/react-dom@19.0.0", "@types/react-dom@^19": + version "19.0.0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.0.tgz#e7f5d618a080486eaf9952246dbf59eaa2c64130" + integrity sha512-1KfiQKsH1o00p9m5ag12axHQSb3FOU9H20UTrujVSkNhuCrRHiQWFqgEnTNK5ZNfnzZv8UWrnXVqCmCF9fgY3w== dependencies: "@types/react" "*" @@ -3179,12 +3174,11 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@18.3.3": - version "18.3.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" - integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== +"@types/react@*", "@types/react@19.0.0", "@types/react@^19": + version "19.0.0" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.0.tgz#fbbb53ce223f4e2b750ad5dd09580b2c43522bbf" + integrity sha512-MY3oPudxvMYyesqs/kW1Bh8y9VqSmf+tzqw3ae8a9DZW68pUe3zAdHeI1jc6iAysuRdACnVknHP8AhwD4/dxtg== dependencies: - "@types/prop-types" "*" csstype "^3.0.2" "@types/retry@0.12.0": @@ -8110,7 +8104,7 @@ long@^5.2.0: resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -9925,13 +9919,12 @@ react-clientside-effect@^1.2.6: dependencies: "@babel/runtime" "^7.12.13" -react-dom@^18.3.1: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" - integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== +react-dom@19.0.0, react-dom@^19: + version "19.0.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57" + integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.2" + scheduler "^0.25.0" react-focus-lock@^2.5.1: version "2.13.2" @@ -10010,12 +10003,10 @@ react-transition-group@^4.4.1: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^18.3.1: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" - integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== - dependencies: - loose-envify "^1.1.0" +react@19.0.0, react@^19: + version "19.0.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" + integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== read-cache@^1.0.0: version "1.0.0" @@ -10402,12 +10393,10 @@ saxes@^6.0.0: dependencies: xmlchars "^2.2.0" -scheduler@^0.23.2: - version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== - dependencies: - loose-envify "^1.1.0" +scheduler@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" + integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: version "3.3.0"