diff --git a/packages/api/src/providers/ActivityAcknowledgement/ActivityAcknowledgementComposer.tsx b/packages/api/src/providers/ActivityAcknowledgement/ActivityAcknowledgementComposer.tsx index 57381cbb65..a4f79eb752 100644 --- a/packages/api/src/providers/ActivityAcknowledgement/ActivityAcknowledgementComposer.tsx +++ b/packages/api/src/providers/ActivityAcknowledgement/ActivityAcknowledgementComposer.tsx @@ -1,6 +1,4 @@ -import React, { useCallback, useMemo, useState } from 'react'; - -import type { FC, PropsWithChildren } from 'react'; +import React, { useCallback, useMemo, useState, type PropsWithChildren, type ReactNode } from 'react'; import ActivityAcknowledgementContext, { ActivityAcknowledgementContextType } from './private/Context'; import findLastIndex from '../../utils/findLastIndex'; @@ -9,9 +7,9 @@ import useActivityKeys from '../ActivityKeyer/useActivityKeys'; import usePrevious from '../../hooks/internal/usePrevious'; import useValueRef from '../../hooks/internal/useValueRef'; -import type { ActivityAcknowledgement } from './private/types'; +import { type ActivityAcknowledgement } from './private/types'; -type ActivityAcknowledgementComposerProps = PropsWithChildren<{}>; +type ActivityAcknowledgementComposerProps = Readonly>; function findClosestActivityKeyIfNotExists( activityKey: string, @@ -42,7 +40,7 @@ function findClosestActivityKeyIfNotExists( // If nothing is found, return `undefined`. } -const ActivityAcknowledgementComposer: FC = ({ children }) => { +const ActivityAcknowledgementComposer = ({ children }: ActivityAcknowledgementComposerProps): ReactNode => { const [activities] = useActivities(); const [allActivityKeys] = useActivityKeys(); const [rawLastAcknowledgedActivityKey, setRawLastAcknowledgedActivityKey] = useState(); diff --git a/packages/api/src/providers/ActivityKeyer/ActivityKeyerComposer.tsx b/packages/api/src/providers/ActivityKeyer/ActivityKeyerComposer.tsx index 19208a7db2..de24620808 100644 --- a/packages/api/src/providers/ActivityKeyer/ActivityKeyerComposer.tsx +++ b/packages/api/src/providers/ActivityKeyer/ActivityKeyerComposer.tsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, { useCallback, useMemo, useRef } from 'react'; +import React, { useCallback, useMemo, useRef, type PropsWithChildren, type ReactNode } from 'react'; import ActivityKeyerContext from './private/Context'; import getActivityId from './private/getActivityId'; @@ -8,15 +8,16 @@ import uniqueId from './private/uniqueId'; import useActivities from '../../hooks/useActivities'; import useActivityKeyerContext from './private/useContext'; -import type { ActivityKeyerContextType } from './private/Context'; -import type { FC, PropsWithChildren } from 'react'; -import type { WebChatActivity } from 'botframework-webchat-core'; +import { type ActivityKeyerContextType } from './private/Context'; +import { type WebChatActivity } from 'botframework-webchat-core'; type ActivityIdToKeyMap = Map; type ActivityToKeyMap = Map; type ClientActivityIdToKeyMap = Map; type KeyToActivityMap = Map; +type ActivityKeyerComposerProps = Readonly>; + /** * React context composer component to assign a perma-key to every activity. * This will support both `useGetActivityByKey` and `useGetKeyByActivity` custom hooks. @@ -31,7 +32,7 @@ type KeyToActivityMap = Map; * * Local key are only persisted in memory. On refresh, they will be a new random key. */ -const ActivityKeyerComposer: FC> = ({ children }) => { +const ActivityKeyerComposer = ({ children }: ActivityKeyerComposerProps): ReactNode => { const existingContext = useActivityKeyerContext(false); if (existingContext) { diff --git a/packages/api/src/providers/ActivitySendStatus/ActivitySendStatusComposer.tsx b/packages/api/src/providers/ActivitySendStatus/ActivitySendStatusComposer.tsx index c2cfda5072..8fb1c39cf2 100644 --- a/packages/api/src/providers/ActivitySendStatus/ActivitySendStatusComposer.tsx +++ b/packages/api/src/providers/ActivitySendStatus/ActivitySendStatusComposer.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef } from 'react'; +import React, { useEffect, useMemo, useRef, type PropsWithChildren, type ReactNode } from 'react'; import { SENDING, SEND_FAILED, SENT } from '../../types/internal/SendStatus'; import ActivitySendStatusContext from './private/Context'; @@ -10,15 +10,16 @@ import useGetKeyByActivity from '../ActivityKeyer/useGetKeyByActivity'; import useGetSendTimeoutForActivity from '../../hooks/useGetSendTimeoutForActivity'; import usePonyfill from '../../hooks/usePonyfill'; -import type { ActivitySendStatusContextType } from './private/Context'; -import type { FC, PropsWithChildren } from 'react'; -import type { SendStatus } from '../../types/internal/SendStatus'; +import { type ActivitySendStatusContextType } from './private/Context'; +import { type SendStatus } from '../../types/internal/SendStatus'; // Magic numbers for `expiryByActivityKey`. const EXPIRY_SEND_FAILED = -Infinity; const EXPIRY_SENT = Infinity; -const ActivitySendStatusComposer: FC> = ({ children }) => { +type ActivitySendStatusComposerProps = Readonly>; + +const ActivitySendStatusComposer = ({ children }: ActivitySendStatusComposerProps): ReactNode => { const [activities] = useActivities(); const [{ clearTimeout, Date, setTimeout }] = usePonyfill(); const forceRender = useForceRender(); diff --git a/packages/bundle/src/AddFullBundle.tsx b/packages/bundle/src/AddFullBundle.tsx index c4a07950fc..c1d26ea491 100644 --- a/packages/bundle/src/AddFullBundle.tsx +++ b/packages/bundle/src/AddFullBundle.tsx @@ -1,7 +1,7 @@ import { AttachmentForScreenReaderMiddleware, AttachmentMiddleware, StyleOptions } from 'botframework-webchat-api'; import { OneOrMany, singleToArray, warnOnce } from 'botframework-webchat-core'; import PropTypes from 'prop-types'; -import React, { FC, ReactNode } from 'react'; +import React, { type ReactNode } from 'react'; import { StrictFullBundleStyleOptions } from './types/FullBundleStyleOptions'; import AdaptiveCardsComposer from './adaptiveCards/AdaptiveCardsComposer'; @@ -9,9 +9,9 @@ import AdaptiveCardsPackage from './types/AdaptiveCardsPackage'; import AdaptiveCardsStyleOptions from './adaptiveCards/AdaptiveCardsStyleOptions'; import useComposerProps from './useComposerProps'; -type AddFullBundleProps = { +type AddFullBundleProps = Readonly<{ adaptiveCardsHostConfig?: any; - adaptiveCardsPackage?: AdaptiveCardsPackage; + adaptiveCardsPackage?: Readonly; attachmentForScreenReaderMiddleware?: OneOrMany; attachmentMiddleware?: OneOrMany; children: ({ extraStyleSet }: { extraStyleSet: any }) => ReactNode; @@ -20,18 +20,18 @@ type AddFullBundleProps = { newLineOptions: { markdownRespectCRLF: boolean }, linkOptions: { externalLinkAlt: string } ) => string; - styleOptions?: StyleOptions & AdaptiveCardsStyleOptions; - styleSet?: any & { options: StrictFullBundleStyleOptions }; + styleOptions?: Readonly; + styleSet?: any & Readonly<{ options: StrictFullBundleStyleOptions }>; /** @deprecated Rename to "adaptiveCardsHostConfig" */ adaptiveCardHostConfig?: any; -}; +}>; const adaptiveCardHostConfigDeprecation = warnOnce( '"adaptiveCardHostConfig" is deprecated. Please use "adaptiveCardsHostConfig" instead. "adaptiveCardHostConfig" will be removed on or after 2022-01-01.' ); -const AddFullBundle: FC = ({ +const AddFullBundle = ({ adaptiveCardHostConfig, adaptiveCardsHostConfig, adaptiveCardsPackage, @@ -41,7 +41,7 @@ const AddFullBundle: FC = ({ renderMarkdown, styleOptions, styleSet -}) => { +}: AddFullBundleProps): ReactNode => { adaptiveCardHostConfig && adaptiveCardHostConfigDeprecation(); const patchedProps = useComposerProps({ diff --git a/packages/bundle/src/FullComposer.tsx b/packages/bundle/src/FullComposer.tsx index 7e66113069..9d18dbfbd9 100644 --- a/packages/bundle/src/FullComposer.tsx +++ b/packages/bundle/src/FullComposer.tsx @@ -1,18 +1,17 @@ import { Components } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React from 'react'; +import React, { type ReactNode } from 'react'; import AddFullBundle from './AddFullBundle'; -import type { AddFullBundleProps } from './AddFullBundle'; -import type { ComposerProps } from 'botframework-webchat-component'; -import type { FC } from 'react'; +import { type AddFullBundleProps } from './AddFullBundle'; +import { type ComposerProps } from 'botframework-webchat-component'; const { Composer } = Components; -type FullComposerProps = ComposerProps & AddFullBundleProps; +type FullComposerProps = Readonly; -const FullComposer: FC = props => ( +const FullComposer = (props: FullComposerProps): ReactNode => ( {extraProps => ( diff --git a/packages/bundle/src/adaptiveCards/AdaptiveCardsComposer.tsx b/packages/bundle/src/adaptiveCards/AdaptiveCardsComposer.tsx index 73e5ef3d80..6e8889cd43 100644 --- a/packages/bundle/src/adaptiveCards/AdaptiveCardsComposer.tsx +++ b/packages/bundle/src/adaptiveCards/AdaptiveCardsComposer.tsx @@ -1,21 +1,21 @@ import * as defaultAdaptiveCardsPackage from 'adaptivecards'; import PropTypes from 'prop-types'; -import React, { FC, ReactNode, useMemo } from 'react'; +import React, { type ReactNode, useMemo } from 'react'; import AdaptiveCardsContext from './AdaptiveCardsContext'; import AdaptiveCardsPackage from '../types/AdaptiveCardsPackage'; -type AdaptiveCardsComposerProps = { +type AdaptiveCardsComposerProps = Readonly<{ adaptiveCardsHostConfig: any; adaptiveCardsPackage: AdaptiveCardsPackage; children: ReactNode; -}; +}>; -const AdaptiveCardsComposer: FC = ({ +const AdaptiveCardsComposer = ({ adaptiveCardsHostConfig, adaptiveCardsPackage, children -}) => { +}: AdaptiveCardsComposerProps): ReactNode => { const patchedAdaptiveCardsPackage = useMemo( () => adaptiveCardsPackage || defaultAdaptiveCardsPackage, [adaptiveCardsPackage] diff --git a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardAttachment.tsx b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardAttachment.tsx index 1a4abb422a..6d0ecf1e43 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardAttachment.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardAttachment.tsx @@ -1,15 +1,15 @@ import PropTypes from 'prop-types'; -import React, { FC } from 'react'; -import type { DirectLineAttachment } from 'botframework-webchat-core'; +import React, { type ReactNode } from 'react'; +import { type DirectLineAttachment } from 'botframework-webchat-core'; import AdaptiveCardContent from './AdaptiveCardContent'; -type AdaptiveCardAttachmentProps = { +type AdaptiveCardAttachmentProps = Readonly<{ attachment: DirectLineAttachment; disabled?: boolean; -}; +}>; -const AdaptiveCardAttachment: FC = ({ attachment: { content }, disabled }) => ( +const AdaptiveCardAttachment = ({ attachment: { content }, disabled }: AdaptiveCardAttachmentProps): ReactNode => ( ); diff --git a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardContent.tsx index 8441149ce0..b707e9e4ad 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/AdaptiveCardContent.tsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, { FC, useMemo } from 'react'; +import React, { type ReactNode, useMemo } from 'react'; import AdaptiveCardRenderer from './AdaptiveCardRenderer'; import useParseAdaptiveCardJSON from '../hooks/internal/useParseAdaptiveCardJSON'; @@ -17,13 +17,13 @@ function stripSubmitAction(card) { return { ...card, nextActions }; } -type AdaptiveCardContentProps = { +type AdaptiveCardContentProps = Readonly<{ actionPerformedClassName?: string; content: any; disabled?: boolean; -}; +}>; -const AdaptiveCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const AdaptiveCardContent = ({ actionPerformedClassName, content, disabled }: AdaptiveCardContentProps): ReactNode => { const parseAdaptiveCardJSON = useParseAdaptiveCardJSON(); const card = useMemo( diff --git a/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx index 943d9300ce..9b428f6298 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/AnimationCardContent.tsx @@ -2,21 +2,25 @@ import { Components } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; -import type { DirectLineAnimationCard } from 'botframework-webchat-core'; +import React, { type ReactNode } from 'react'; +import { type DirectLineAnimationCard } from 'botframework-webchat-core'; import CommonCard from './CommonCard'; import useStyleSet from '../../hooks/useStyleSet'; const { ImageContent, VideoContent } = Components; -type AnimationCardContentProps = { +type AnimationCardContentProps = Readonly<{ actionPerformedClassName?: string; content: DirectLineAnimationCard; disabled?: boolean; -}; +}>; -const AnimationCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const AnimationCardContent = ({ + actionPerformedClassName, + content, + disabled +}: AnimationCardContentProps): ReactNode => { const { media = [] } = content; const [{ animationCardAttachment: animationCardAttachmentStyleSet }] = useStyleSet(); diff --git a/packages/bundle/src/adaptiveCards/Attachment/AudioCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/AudioCardContent.tsx index a280290e4b..d010348212 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/AudioCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/AudioCardContent.tsx @@ -2,21 +2,21 @@ import { Components } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; -import type { DirectLineAudioCard } from 'botframework-webchat-core'; +import React, { type ReactNode } from 'react'; +import { type DirectLineAudioCard } from 'botframework-webchat-core'; import CommonCard from './CommonCard'; import useStyleSet from '../../hooks/useStyleSet'; const { AudioContent } = Components; -type AudioCardContentProps = { +type AudioCardContentProps = Readonly<{ actionPerformedClassName?: string; content: DirectLineAudioCard; disabled?: boolean; -}; +}>; -const AudioCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const AudioCardContent = ({ actionPerformedClassName, content, disabled }: AudioCardContentProps): ReactNode => { const [{ audioCardAttachment: audioCardAttachmentStyleSet }] = useStyleSet(); const { autostart = false, autoloop = false, image: { url: imageURL = '' } = {}, media = [] } = content; diff --git a/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.tsx index 7cbfa47aca..3e050c9875 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/HeroCardContent.tsx @@ -1,7 +1,8 @@ import { hooks } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React, { FC, useMemo } from 'react'; -import type { DirectLineHeroCard } from 'botframework-webchat-core'; +import React, { type ReactNode, useMemo } from 'react'; + +import { type DirectLineHeroCard } from 'botframework-webchat-core'; import AdaptiveCardBuilder from './AdaptiveCardBuilder'; import AdaptiveCardRenderer from './AdaptiveCardRenderer'; @@ -10,13 +11,13 @@ import useStyleOptions from '../../hooks/useStyleOptions'; const { useDirection } = hooks; -type HeroCardContentProps = { +type HeroCardContentProps = Readonly<{ actionPerformedClassName?: string; content: DirectLineHeroCard; disabled?: boolean; -}; +}>; -const HeroCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const HeroCardContent = ({ actionPerformedClassName, content, disabled }: HeroCardContentProps): ReactNode => { const [adaptiveCardsPackage] = useAdaptiveCardsPackage(); const [styleOptions] = useStyleOptions(); const [direction] = useDirection(); diff --git a/packages/bundle/src/adaptiveCards/Attachment/OAuthCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/OAuthCardContent.tsx index 24b6b8fb18..886ca15e68 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/OAuthCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/OAuthCardContent.tsx @@ -1,7 +1,7 @@ import { hooks } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React, { FC, useMemo } from 'react'; -import type { DirectLineOAuthCard } from 'botframework-webchat-core'; +import React, { type ReactNode, useMemo } from 'react'; +import { type DirectLineOAuthCard } from 'botframework-webchat-core'; import AdaptiveCardBuilder from './AdaptiveCardBuilder'; import AdaptiveCardRenderer from './AdaptiveCardRenderer'; @@ -10,13 +10,13 @@ import useStyleOptions from '../../hooks/useStyleOptions'; const { useDirection } = hooks; -type OAuthCardContentProps = { +type OAuthCardContentProps = Readonly<{ actionPerformedClassName?: string; content: DirectLineOAuthCard; disabled?: boolean; -}; +}>; -const OAuthCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const OAuthCardContent = ({ actionPerformedClassName, content, disabled }: OAuthCardContentProps): ReactNode => { const [adaptiveCardsPackage] = useAdaptiveCardsPackage(); const [direction] = useDirection(); const [styleOptions] = useStyleOptions(); diff --git a/packages/bundle/src/adaptiveCards/Attachment/ReceiptCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/ReceiptCardContent.tsx index efc3a3266d..f289af6a1a 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/ReceiptCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/ReceiptCardContent.tsx @@ -2,8 +2,8 @@ import { hooks } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React, { FC, useMemo } from 'react'; -import type { DirectLineReceiptCard } from 'botframework-webchat-core'; +import React, { type ReactNode, useMemo } from 'react'; +import { type DirectLineReceiptCard } from 'botframework-webchat-core'; import AdaptiveCardBuilder from './AdaptiveCardBuilder'; import AdaptiveCardRenderer from './AdaptiveCardRenderer'; @@ -16,13 +16,13 @@ function nullOrUndefined(obj) { return obj === null || typeof obj === 'undefined'; } -type ReceiptCardContentProps = { +type ReceiptCardContentProps = Readonly<{ actionPerformedClassName?: string; content: DirectLineReceiptCard; disabled?: boolean; -}; +}>; -const ReceiptCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const ReceiptCardContent = ({ actionPerformedClassName, content, disabled }: ReceiptCardContentProps): ReactNode => { const [adaptiveCardsPackage] = useAdaptiveCardsPackage(); const [direction] = useDirection(); const [styleOptions] = useStyleOptions(); diff --git a/packages/bundle/src/adaptiveCards/Attachment/SignInCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/SignInCardContent.tsx index 637fd73981..49d875d11c 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/SignInCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/SignInCardContent.tsx @@ -1,17 +1,17 @@ import PropTypes from 'prop-types'; -import React, { FC } from 'react'; -import type { DirectLineSignInCard } from 'botframework-webchat-core'; +import React, { type ReactNode } from 'react'; +import { type DirectLineSignInCard } from 'botframework-webchat-core'; import CommonCard from './CommonCard'; import useStyleSet from '../../hooks/useStyleSet'; -type SignInCardContentProps = { +type SignInCardContentProps = Readonly<{ actionPerformedClassName?: string; content: DirectLineSignInCard; disabled?: boolean; -}; +}>; -const SignInCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const SignInCardContent = ({ actionPerformedClassName, content, disabled }: SignInCardContentProps): ReactNode => { const [{ animationCardAttachment: animationCardAttachmentStyleSet }] = useStyleSet(); return ( diff --git a/packages/bundle/src/adaptiveCards/Attachment/ThumbnailCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/ThumbnailCardContent.tsx index 085de2d2b2..07bd9fa765 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/ThumbnailCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/ThumbnailCardContent.tsx @@ -2,8 +2,8 @@ import { hooks } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React, { FC, useMemo } from 'react'; -import type { DirectLineThumbnailCard } from 'botframework-webchat-core'; +import React, { type ReactNode, useMemo } from 'react'; +import { type DirectLineThumbnailCard } from 'botframework-webchat-core'; import AdaptiveCardBuilder from './AdaptiveCardBuilder'; import AdaptiveCardRenderer from './AdaptiveCardRenderer'; @@ -12,13 +12,17 @@ import useStyleOptions from '../../hooks/useStyleOptions'; const { useDirection } = hooks; -type ThumbnailCardContentProps = { +type ThumbnailCardContentProps = Readonly<{ actionPerformedClassName?: string; content: DirectLineThumbnailCard; disabled?: boolean; -}; +}>; -const ThumbnailCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const ThumbnailCardContent = ({ + actionPerformedClassName, + content, + disabled +}: ThumbnailCardContentProps): ReactNode => { const [adaptiveCardsPackage] = useAdaptiveCardsPackage(); const [direction] = useDirection(); const [styleOptions] = useStyleOptions(); diff --git a/packages/bundle/src/adaptiveCards/Attachment/VideoCardContent.tsx b/packages/bundle/src/adaptiveCards/Attachment/VideoCardContent.tsx index d2e24cfbe6..fbc46d9de6 100644 --- a/packages/bundle/src/adaptiveCards/Attachment/VideoCardContent.tsx +++ b/packages/bundle/src/adaptiveCards/Attachment/VideoCardContent.tsx @@ -2,26 +2,28 @@ import { Components } from 'botframework-webchat-component'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; -import type { DirectLineVideoCard } from 'botframework-webchat-core'; +import React, { type ReactNode } from 'react'; +import { type DirectLineVideoCard } from 'botframework-webchat-core'; import CommonCard from './CommonCard'; import useStyleSet from '../../hooks/useStyleSet'; const { VideoContent } = Components; -type VideoCardContentProps = { +type VideoCardContentProps = Readonly<{ actionPerformedClassName?: string; - content: DirectLineVideoCard & { - autoloop?: boolean; - autostart?: boolean; - image?: { url?: string }; - media?: { profile?: string; url?: string }[]; - }; + content: Readonly< + DirectLineVideoCard & { + autoloop?: boolean; + autostart?: boolean; + image?: { url?: string }; + media?: { profile?: string; url?: string }[]; + } + >; disabled?: boolean; -}; +}>; -const VideoCardContent: FC = ({ actionPerformedClassName, content, disabled }) => { +const VideoCardContent = ({ actionPerformedClassName, content, disabled }: VideoCardContentProps): ReactNode => { const { autoloop, autostart, image: { url: imageURL } = { url: undefined }, media } = content; const [{ audioCardAttachment: audioCardAttachmentStyleSet }] = useStyleSet(); diff --git a/packages/component/src/Activity/Bubble.tsx b/packages/component/src/Activity/Bubble.tsx index 3c1539c3b8..ff76998505 100644 --- a/packages/component/src/Activity/Bubble.tsx +++ b/packages/component/src/Activity/Bubble.tsx @@ -3,7 +3,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC, ReactNode } from 'react'; +import React, { type PropsWithChildren, type ReactNode } from 'react'; import isZeroOrPositive from '../Utils/isZeroOrPositive'; import useStyleSet from '../hooks/useStyleSet'; @@ -29,7 +29,7 @@ const ROOT_STYLE = { } }; -function acuteNubSVG(nubSize, strokeWidth, side, upSideDown = false) { +function acuteNubSVG(nubSize, strokeWidth, side, upSideDown = false): ReactNode { if (typeof nubSize !== 'number') { return false; } @@ -62,15 +62,16 @@ function acuteNubSVG(nubSize, strokeWidth, side, upSideDown = false) { ); } -type BubbleProps = { - 'aria-hidden'?: boolean; - children?: ReactNode; - className?: string; - fromUser?: boolean; - nub?: boolean | 'hidden'; -}; +type BubbleProps = Readonly< + PropsWithChildren<{ + 'aria-hidden'?: boolean; + className?: string; + fromUser?: boolean; + nub?: boolean | 'hidden'; + }> +>; -const Bubble: FC = ({ 'aria-hidden': ariaHidden, children, className, fromUser, nub }) => { +const Bubble = ({ 'aria-hidden': ariaHidden, children, className, fromUser, nub }: BubbleProps): ReactNode => { const [{ bubble: bubbleStyleSet }] = useStyleSet(); const [direction] = useDirection(); const [ diff --git a/packages/component/src/Activity/Speak.tsx b/packages/component/src/Activity/Speak.tsx index 7d27721a56..3bd731dbf9 100644 --- a/packages/component/src/Activity/Speak.tsx +++ b/packages/component/src/Activity/Speak.tsx @@ -1,6 +1,6 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { FC, useCallback, useMemo } from 'react'; +import React, { type ReactNode, useCallback, useMemo } from 'react'; import Say, { SayUtterance } from 'react-say'; import type { WebChatActivity } from 'botframework-webchat-core'; @@ -23,11 +23,11 @@ const connectSpeakActivity = (...selectors) => ...selectors ); -type SpeakProps = { - activity: WebChatActivity; -}; +type SpeakProps = Readonly<{ + activity: Readonly; +}>; -const Speak: FC = ({ activity }) => { +const Speak = ({ activity }: SpeakProps): ReactNode => { const [{ showSpokenText }] = useStyleOptions(); const markActivityAsSpoken = useMarkActivityAsSpoken(); const selectVoice = useVoiceSelector(activity); diff --git a/packages/component/src/Activity/StackedLayout.tsx b/packages/component/src/Activity/StackedLayout.tsx index 64ebde8d7d..fa5273833c 100644 --- a/packages/component/src/Activity/StackedLayout.tsx +++ b/packages/component/src/Activity/StackedLayout.tsx @@ -3,7 +3,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React from 'react'; +import React, { type ReactNode } from 'react'; import Bubble from './Bubble'; import connectToWebChat from '../connectToWebChat'; @@ -14,9 +14,8 @@ import useStyleSet from '../hooks/useStyleSet'; import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject'; import useUniqueId from '../hooks/internal/useUniqueId'; -import type { FC, ReactNode } from 'react'; -import type { RenderAttachment } from 'botframework-webchat-api'; -import type { WebChatActivity } from 'botframework-webchat-core'; +import { type RenderAttachment } from 'botframework-webchat-api'; +import { type WebChatActivity } from 'botframework-webchat-core'; const { useAvatarForBot, useAvatarForUser, useLocalizer, useStyleOptions } = hooks; @@ -90,23 +89,23 @@ const connectStackedLayout = (...selectors) => ...selectors ); -type StackedLayoutProps = { - activity: WebChatActivity; +type StackedLayoutProps = Readonly<{ + activity: Readonly; hideTimestamp?: boolean; renderActivityStatus?: (options: { hideTimestamp: boolean }) => ReactNode; renderAttachment?: RenderAttachment; renderAvatar?: false | (() => Exclude); showCallout?: boolean; -}; +}>; -const StackedLayout: FC = ({ +const StackedLayout = ({ activity, hideTimestamp, renderActivityStatus, renderAttachment, renderAvatar, showCallout -}) => { +}: StackedLayoutProps): ReactNode => { const [styleOptions] = useStyleOptions(); const [{ initials: botInitials }] = useAvatarForBot(); const [{ initials: userInitials }] = useAvatarForUser(); diff --git a/packages/component/src/ActivityStatus/SendStatus/SendStatus.tsx b/packages/component/src/ActivityStatus/SendStatus/SendStatus.tsx index 0c11273b16..07e1accc26 100644 --- a/packages/component/src/ActivityStatus/SendStatus/SendStatus.tsx +++ b/packages/component/src/ActivityStatus/SendStatus/SendStatus.tsx @@ -1,7 +1,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC, useCallback } from 'react'; +import React, { type ReactNode, useCallback } from 'react'; import type { WebChatActivity } from 'botframework-webchat-core'; import { SENDING, SEND_FAILED, SENT } from '../../types/internal/SendStatus'; @@ -31,12 +31,12 @@ const connectSendStatus = (...selectors) => ...selectors ); -type SendStatusProps = { - activity: WebChatActivity; +type SendStatusProps = Readonly<{ + activity: Readonly; sendStatus: SendStatusType; -}; +}>; -const SendStatus: FC = ({ activity, sendStatus }) => { +const SendStatus = ({ activity, sendStatus }: SendStatusProps): ReactNode => { const [{ sendStatus: sendStatusStyleSet }] = useStyleSet(); const focus = useFocus(); const localize = useLocalizer(); diff --git a/packages/component/src/ActivityStatus/Timestamp.tsx b/packages/component/src/ActivityStatus/Timestamp.tsx index e811618976..41df0f9837 100644 --- a/packages/component/src/ActivityStatus/Timestamp.tsx +++ b/packages/component/src/ActivityStatus/Timestamp.tsx @@ -1,17 +1,17 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import AbsoluteTime from './AbsoluteTime'; import RelativeTime from './private/RelativeTime'; const { useStyleOptions } = hooks; -type TimestampProps = { +type TimestampProps = Readonly<{ timestamp: string; -}; +}>; -const Timestamp: FC = ({ timestamp }) => { +const Timestamp = ({ timestamp }: TimestampProps): ReactNode => { const [{ timestampFormat }] = useStyleOptions(); return timestampFormat === 'relative' ? : ; diff --git a/packages/component/src/Attachment/AudioContent.tsx b/packages/component/src/Attachment/AudioContent.tsx index 05c92a6450..07559fb716 100644 --- a/packages/component/src/Attachment/AudioContent.tsx +++ b/packages/component/src/Attachment/AudioContent.tsx @@ -1,17 +1,17 @@ import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import useStyleSet from '../hooks/useStyleSet'; -type AudioContentProps = { +type AudioContentProps = Readonly<{ alt?: string; autoPlay?: boolean; loop?: boolean; poster?: string; src: string; -}; +}>; -const AudioContent: FC = ({ alt, autoPlay, loop, src }) => { +const AudioContent = ({ alt, autoPlay, loop, src }: AudioContentProps): ReactNode => { const [{ audioContent: audioContentStyleSet }] = useStyleSet(); return ( diff --git a/packages/component/src/Attachment/FileContent.tsx b/packages/component/src/Attachment/FileContent.tsx index 20d7335098..3a49c77b1c 100644 --- a/packages/component/src/Attachment/FileContent.tsx +++ b/packages/component/src/Attachment/FileContent.tsx @@ -1,7 +1,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import DownloadIcon from './Assets/DownloadIcon'; import useStyleSet from '../hooks/useStyleSet'; @@ -34,7 +34,13 @@ function isAllowedProtocol(url) { } } -const FileContentBadge = ({ downloadIcon, fileName, size }) => { +type FileContentBadgeProps = Readonly<{ + downloadIcon?: boolean; + fileName: string; + size?: number; +}>; + +const FileContentBadge = ({ downloadIcon, fileName, size }: FileContentBadgeProps): ReactNode => { const [direction] = useDirection(); const formatByte = useByteFormatter(); @@ -77,7 +83,7 @@ type FileContentProps = { size?: number; }; -const FileContent: FC = ({ className, href, fileName, size }) => { +const FileContent = ({ className, href, fileName, size }: FileContentProps): ReactNode => { const [{ fileContent: fileContentStyleSet }] = useStyleSet(); const localize = useLocalizer(); const localizeBytes = useByteFormatter(); diff --git a/packages/component/src/Attachment/HTMLVideoContent.tsx b/packages/component/src/Attachment/HTMLVideoContent.tsx index dcd7e8aabc..b2609b4a8c 100644 --- a/packages/component/src/Attachment/HTMLVideoContent.tsx +++ b/packages/component/src/Attachment/HTMLVideoContent.tsx @@ -1,17 +1,17 @@ import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import useStyleSet from '../hooks/useStyleSet'; -type HTMLVideoContentProps = { +type HTMLVideoContentProps = Readonly<{ alt?: string; autoPlay?: boolean; loop?: boolean; poster?: string; src: string; -}; +}>; -const HTMLVideoContent: FC = ({ alt, autoPlay, loop, poster, src }) => { +const HTMLVideoContent = ({ alt, autoPlay, loop, poster, src }: HTMLVideoContentProps): ReactNode => { const [{ videoContent: videoContentStyleSet }] = useStyleSet(); return ( diff --git a/packages/component/src/Attachment/ImageContent.tsx b/packages/component/src/Attachment/ImageContent.tsx index 6a87ef0221..a66c37ac4c 100644 --- a/packages/component/src/Attachment/ImageContent.tsx +++ b/packages/component/src/Attachment/ImageContent.tsx @@ -1,17 +1,17 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import CroppedImage from '../Utils/CroppedImage'; const { useStyleOptions } = hooks; -type ImageContentProps = { +type ImageContentProps = Readonly<{ alt?: string; src: string; -}; +}>; -const ImageContent: FC = ({ alt, src }) => { +const ImageContent = ({ alt, src }: ImageContentProps): ReactNode => { const [{ bubbleImageHeight }] = useStyleOptions(); return ; diff --git a/packages/component/src/Attachment/Text/TextAttachment.tsx b/packages/component/src/Attachment/Text/TextAttachment.tsx index 21a96a4994..96eb5527de 100644 --- a/packages/component/src/Attachment/Text/TextAttachment.tsx +++ b/packages/component/src/Attachment/Text/TextAttachment.tsx @@ -1,5 +1,5 @@ import { type WebChatActivity } from 'botframework-webchat-core'; -import React, { type FC, memo } from 'react'; +import React, { type ReactNode, memo } from 'react'; import { type WebChatAttachment } from '../private/types/WebChatAttachment'; import TextContent from './TextContent'; @@ -11,9 +11,11 @@ type Props = Readonly<{ }; }>; -const TextAttachment: FC = memo(({ activity, attachment: { content, contentType } }: Props) => ( - -)); +const TextAttachment = memo( + ({ activity, attachment: { content, contentType } }: Props): ReactNode => ( + + ) +); TextAttachment.displayName = 'TextAttachment'; diff --git a/packages/component/src/Attachment/Text/TextContent.tsx b/packages/component/src/Attachment/Text/TextContent.tsx index acbc364bee..e7cf202c5b 100644 --- a/packages/component/src/Attachment/Text/TextContent.tsx +++ b/packages/component/src/Attachment/Text/TextContent.tsx @@ -1,4 +1,4 @@ -import React, { type FC, memo } from 'react'; +import React, { type ReactNode, memo } from 'react'; import MarkdownTextContent from './private/MarkdownTextContent'; import PlainTextContent from './private/PlainTextContent'; @@ -12,7 +12,7 @@ type Props = Readonly<{ text: string; }>; -const TextContent: FC = memo(({ contentType = 'text/plain', entities, text }: Props) => { +const TextContent = memo(({ contentType = 'text/plain', entities, text }: Props): ReactNode => { const supportMarkdown = !!useRenderMarkdownAsHTML(); return text ? ( @@ -24,7 +24,6 @@ const TextContent: FC = memo(({ contentType = 'text/plain', entities, tex ) : null; }); -TextContent.defaultProps = { contentType: 'text/plain' }; TextContent.displayName = 'TextContent'; export default TextContent; diff --git a/packages/component/src/Attachment/Text/private/PlainTextContent.tsx b/packages/component/src/Attachment/Text/private/PlainTextContent.tsx index feb2790083..5151e97f83 100644 --- a/packages/component/src/Attachment/Text/private/PlainTextContent.tsx +++ b/packages/component/src/Attachment/Text/private/PlainTextContent.tsx @@ -1,11 +1,11 @@ import classNames from 'classnames'; -import React, { type FC, Fragment, memo } from 'react'; +import React, { type ReactNode, Fragment, memo } from 'react'; import useStyleSet from '../../../hooks/useStyleSet'; type Props = Readonly<{ text: string }>; -const PlainTextContent: FC = memo(({ text }: Props) => { +const PlainTextContent = memo(({ text }: Props): ReactNode => { const [{ textContent: textContentStyleSet }] = useStyleSet(); return ( diff --git a/packages/component/src/Attachment/VideoContent.tsx b/packages/component/src/Attachment/VideoContent.tsx index 8872d91229..edb0c02102 100644 --- a/packages/component/src/Attachment/VideoContent.tsx +++ b/packages/component/src/Attachment/VideoContent.tsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import HTMLVideoContent from './HTMLVideoContent'; import VimeoContent from './VimeoContent'; @@ -30,15 +30,15 @@ function parseURL(url) { return { hostname, pathname, search }; } -type VideoContentProps = { +type VideoContentProps = Readonly<{ alt?: string; autoPlay?: boolean; loop?: boolean; poster?: string; src: string; -}; +}>; -const VideoContent: FC = ({ alt, autoPlay, loop, poster, src }) => { +const VideoContent = ({ alt, autoPlay, loop, poster, src }: VideoContentProps): ReactNode => { const { hostname, pathname, search } = parseURL(src); const lastSegment = pathname.split('/').pop(); const searchParams = new URLSearchParams(search); diff --git a/packages/component/src/Attachment/VimeoContent.tsx b/packages/component/src/Attachment/VimeoContent.tsx index 1a1dd474d2..d5a4d6274d 100644 --- a/packages/component/src/Attachment/VimeoContent.tsx +++ b/packages/component/src/Attachment/VimeoContent.tsx @@ -1,19 +1,19 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import useStyleSet from '../hooks/useStyleSet'; const { useLocalizer } = hooks; -type VimeoContentProps = { +type VimeoContentProps = Readonly<{ alt?: string; autoPlay?: boolean; embedID: string; loop?: boolean; -}; +}>; -const VimeoContent: FC = ({ alt, autoPlay, embedID, loop }) => { +const VimeoContent = ({ alt, autoPlay, embedID, loop }: VimeoContentProps): ReactNode => { const [{ vimeoContent: vimeoContentStyleSet }] = useStyleSet(); const localize = useLocalizer(); diff --git a/packages/component/src/Attachment/YouTubeContent.tsx b/packages/component/src/Attachment/YouTubeContent.tsx index e07c6a5f72..72ed3044d1 100644 --- a/packages/component/src/Attachment/YouTubeContent.tsx +++ b/packages/component/src/Attachment/YouTubeContent.tsx @@ -1,19 +1,19 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import useStyleSet from '../hooks/useStyleSet'; const { useLocalizer } = hooks; -type YouTubeContentProps = { +type YouTubeContentProps = Readonly<{ alt?: string; autoPlay?: boolean; embedID: string; loop?: boolean; -}; +}>; -const YouTubeContent: FC = ({ alt, autoPlay, embedID, loop }) => { +const YouTubeContent = ({ alt, autoPlay, embedID, loop }: YouTubeContentProps): ReactNode => { const [{ youTubeContent: youTubeContentStyleSet }] = useStyleSet(); const localize = useLocalizer(); diff --git a/packages/component/src/BasicSendBox.tsx b/packages/component/src/BasicSendBox.tsx index 93362c69a9..1ab8e1b029 100644 --- a/packages/component/src/BasicSendBox.tsx +++ b/packages/component/src/BasicSendBox.tsx @@ -2,7 +2,7 @@ import { Constants } from 'botframework-webchat-core'; import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import DictationInterims from './SendBox/DictationInterims'; import MicrophoneButton from './SendBox/MicrophoneButton'; @@ -48,11 +48,11 @@ function useSendBoxSpeechInterimsVisible(): [boolean] { ]; } -type BasicSendBoxProps = { +type BasicSendBoxProps = Readonly<{ className?: string; -}; +}>; -const BasicSendBox: FC = ({ className }) => { +const BasicSendBox = ({ className }: BasicSendBoxProps): ReactNode => { const [{ hideUploadButton, sendBoxButtonAlignment }] = useStyleOptions(); const [{ sendBox: sendBoxStyleSet }] = useStyleSet(); const [{ SpeechRecognition = undefined } = {}] = useWebSpeechPonyfill(); diff --git a/packages/component/src/BasicTranscript.tsx b/packages/component/src/BasicTranscript.tsx index c75da510c7..10549b3456 100644 --- a/packages/component/src/BasicTranscript.tsx +++ b/packages/component/src/BasicTranscript.tsx @@ -13,10 +13,10 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React, { forwardRef, Fragment, useCallback, useMemo, useRef } from 'react'; -import type { ActivityComponentFactory } from 'botframework-webchat-api'; -import type { ActivityElementMap } from './Transcript/types'; -import type { FC, KeyboardEventHandler, MutableRefObject, ReactNode } from 'react'; -import type { WebChatActivity } from 'botframework-webchat-core'; +import { type ActivityComponentFactory } from 'botframework-webchat-api'; +import { type ActivityElementMap } from './Transcript/types'; +import { type KeyboardEventHandler, type MutableRefObject, type ReactNode, type PropsWithChildren } from 'react'; +import { type WebChatActivity } from 'botframework-webchat-core'; import { android } from './Utils/detectBrowser'; import ActivityRow from './Transcript/ActivityRow'; @@ -600,18 +600,19 @@ InternalTranscript.propTypes = { className: PropTypes.string }; -type InternalTranscriptScrollableProps = { - children?: ReactNode; - onFocusFiller: () => void; - terminatorRef: MutableRefObject; -}; +type InternalTranscriptScrollableProps = Readonly< + PropsWithChildren<{ + onFocusFiller: () => void; + terminatorRef: MutableRefObject; + }> +>; // Separating high-frequency hooks to improve performance. -const InternalTranscriptScrollable: FC = ({ +const InternalTranscriptScrollable = ({ children, onFocusFiller, terminatorRef -}) => { +}: InternalTranscriptScrollableProps): ReactNode => { const [{ activities: activitiesStyleSet }] = useStyleSet(); const [animatingToEnd]: [boolean] = useAnimatingToEnd(); const [atEnd]: [boolean] = useAtEnd(); @@ -872,7 +873,7 @@ type BasicTranscriptProps = { className?: string; }; -const BasicTranscript: FC = ({ className }) => { +const BasicTranscript = ({ className }: BasicTranscriptProps): ReactNode => { const activityElementMapRef = useRef(new Map()); const containerRef = useRef(); diff --git a/packages/component/src/BasicWebChat.tsx b/packages/component/src/BasicWebChat.tsx index 97f80708f4..de0723c293 100644 --- a/packages/component/src/BasicWebChat.tsx +++ b/packages/component/src/BasicWebChat.tsx @@ -4,7 +4,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import AccessKeySinkSurface from './Utils/AccessKeySink/Surface'; import BasicConnectivityStatus from './BasicConnectivityStatus'; @@ -40,12 +40,12 @@ const TRANSCRIPT_STYLE = { // Subset of landmark roles: https://w3.org/TR/wai-aria/#landmark_roles const ARIA_LANDMARK_ROLES = ['complementary', 'contentinfo', 'form', 'main', 'region']; -type BasicWebChatProps = { +type BasicWebChatProps = Readonly<{ className?: string; role?: 'complementary' | 'contentinfo' | 'form' | 'main' | 'region'; -}; +}>; -const BasicWebChat: FC = ({ className, role }) => { +const BasicWebChat = ({ className, role }: BasicWebChatProps): ReactNode => { const [{ root: rootStyleSet }] = useStyleSet(); const [options] = useStyleOptions(); const styleToEmotionObject = useStyleToEmotionObject(); diff --git a/packages/component/src/Composer.tsx b/packages/component/src/Composer.tsx index e4a4508d51..9f1dae6eb0 100644 --- a/packages/component/src/Composer.tsx +++ b/packages/component/src/Composer.tsx @@ -6,7 +6,7 @@ import createEmotion from '@emotion/css/create-instance'; import createStyleSet from './Styles/createStyleSet'; import MarkdownIt from 'markdown-it'; import PropTypes from 'prop-types'; -import React, { memo, useCallback, useMemo, useRef, useState } from 'react'; +import React, { type ReactNode, type PropsWithChildren, memo, useCallback, useMemo, useRef, useState } from 'react'; import { speechSynthesis as bypassSpeechSynthesis, @@ -35,7 +35,6 @@ import useStyleSet from './hooks/useStyleSet'; import WebChatUIContext from './hooks/internal/WebChatUIContext'; import type { ComposerProps as APIComposerProps } from 'botframework-webchat-api'; -import type { FC, ReactNode } from 'react'; const { useGetActivityByKey, useReferenceGrammarID, useStyleOptions } = hooks; @@ -49,7 +48,7 @@ function styleSetToEmotionObjects(styleToEmotionObject, styleSet) { type ComposerCoreUIProps = Readonly<{ children?: ReactNode }>; -const ComposerCoreUI = memo(({ children }: ComposerCoreUIProps) => { +const ComposerCoreUI = memo(({ children }: ComposerCoreUIProps): ReactNode => { const [{ cssCustomProperties }] = useStyleSet(); const dictationOnError = useCallback(err => { @@ -71,21 +70,22 @@ const ComposerCoreUI = memo(({ children }: ComposerCoreUIProps) => { ComposerCoreUI.displayName = 'ComposerCoreUI'; -type ComposerCoreProps = Readonly<{ - children?: ReactNode; - extraStyleSet?: any; - nonce?: string; - renderMarkdown?: ( - markdown: string, - newLineOptions: { markdownRespectCRLF: boolean }, - linkOptions: { externalLinkAlt: string } - ) => string; - styleSet?: any; - suggestedActionsAccessKey?: boolean | string; - webSpeechPonyfillFactory?: WebSpeechPonyfillFactory; -}>; - -const ComposerCore: FC = ({ +type ComposerCoreProps = Readonly< + PropsWithChildren<{ + extraStyleSet?: any; + nonce?: string; + renderMarkdown?: ( + markdown: string, + newLineOptions: { markdownRespectCRLF: boolean }, + linkOptions: { externalLinkAlt: string } + ) => string; + styleSet?: any; + suggestedActionsAccessKey?: boolean | string; + webSpeechPonyfillFactory?: WebSpeechPonyfillFactory; + }> +>; + +const ComposerCore = ({ children, extraStyleSet, nonce, @@ -93,7 +93,7 @@ const ComposerCore: FC = ({ styleSet, suggestedActionsAccessKey, webSpeechPonyfillFactory -}) => { +}: ComposerCoreProps): ReactNode => { const [dictateAbortable, setDictateAbortable] = useState(); const [referenceGrammarID] = useReferenceGrammarID(); const [styleOptions] = useStyleOptions(); @@ -259,7 +259,6 @@ const ComposerCore: FC = ({ }; ComposerCore.defaultProps = { - children: undefined, extraStyleSet: undefined, nonce: undefined, renderMarkdown: undefined, @@ -279,7 +278,7 @@ ComposerCore.propTypes = { type ComposerProps = APIComposerProps & ComposerCoreProps; -const Composer: FC = ({ +const Composer = ({ activityMiddleware, activityStatusMiddleware, attachmentForScreenReaderMiddleware, @@ -296,7 +295,7 @@ const Composer: FC = ({ typingIndicatorMiddleware, webSpeechPonyfillFactory, ...composerProps -}) => { +}: ComposerProps): ReactNode => { const { nonce, onTelemetry } = composerProps; const patchedActivityMiddleware = useMemo( diff --git a/packages/component/src/ErrorBox.tsx b/packages/component/src/ErrorBox.tsx index 0c462d06c1..50912fc463 100644 --- a/packages/component/src/ErrorBox.tsx +++ b/packages/component/src/ErrorBox.tsx @@ -2,19 +2,19 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import ScreenReaderText from './ScreenReaderText'; import useStyleSet from './hooks/useStyleSet'; const { useLocalizer } = hooks; -type ErrorBoxProps = { +type ErrorBoxProps = Readonly<{ error: Error; type?: string; -}; +}>; -const ErrorBox: FC = ({ error, type }) => { +const ErrorBox = ({ error, type }: ErrorBoxProps): ReactNode => { const [{ errorBox: errorBoxStyleSet }] = useStyleSet(); const localize = useLocalizer(); diff --git a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx b/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx index 6572bee837..357461b93d 100644 --- a/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx +++ b/packages/component/src/Middleware/Avatar/createCoreMiddleware.tsx @@ -1,7 +1,7 @@ import { AvatarMiddleware } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import ImageAvatar from '../../Avatar/ImageAvatar'; import InitialsAvatar from '../../Avatar/InitialsAvatar'; @@ -19,13 +19,13 @@ const ROOT_STYLE = { } }; -type DefaultAvatarProps = { +type DefaultAvatarProps = Readonly<{ 'aria-hidden'?: boolean; className?: string; fromUser: boolean; -}; +}>; -const DefaultAvatar: FC = ({ 'aria-hidden': ariaHidden, className, fromUser }) => { +const DefaultAvatar = ({ 'aria-hidden': ariaHidden, className, fromUser }: DefaultAvatarProps): ReactNode => { const [{ avatar: avatarStyleSet }] = useStyleSet(); const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; diff --git a/packages/component/src/SendBox/DictationInterims.tsx b/packages/component/src/SendBox/DictationInterims.tsx index c5c2ec3a8a..514d1bf114 100644 --- a/packages/component/src/SendBox/DictationInterims.tsx +++ b/packages/component/src/SendBox/DictationInterims.tsx @@ -4,7 +4,7 @@ import { Constants } from 'botframework-webchat-core'; import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC } from 'react'; +import React, { type ReactNode } from 'react'; import connectToWebChat from '../connectToWebChat'; import useStyleSet from '../hooks/useStyleSet'; @@ -35,7 +35,7 @@ type DictationInterimsProps = { className?: string; }; -const DictationInterims: FC = ({ className }) => { +const DictationInterims = ({ className }: DictationInterimsProps): ReactNode => { const [dictateInterims] = useDictateInterims(); const [dictateState] = useDictateState(); const [{ dictationInterims: dictationInterimsStyleSet }] = useStyleSet(); diff --git a/packages/component/src/SendBox/IconButton.tsx b/packages/component/src/SendBox/IconButton.tsx index 4c1ee33960..577c8e07e7 100644 --- a/packages/component/src/SendBox/IconButton.tsx +++ b/packages/component/src/SendBox/IconButton.tsx @@ -1,7 +1,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC, MouseEventHandler, ReactNode, useRef } from 'react'; +import React, { type ReactNode, type PropsWithChildren, MouseEventHandler, useRef } from 'react'; import AccessibleButton from '../Utils/AccessibleButton'; import useFocusVisible from '../hooks/internal/useFocusVisible'; @@ -9,15 +9,16 @@ import useStyleSet from '../hooks/useStyleSet'; const { useStyleOptions } = hooks; -type IconButtonProps = { - alt?: string; - children?: ReactNode; - className?: string; - disabled?: boolean; - onClick?: MouseEventHandler; -}; +type IconButtonProps = Readonly< + PropsWithChildren<{ + alt?: string; + className?: string; + disabled?: boolean; + onClick?: MouseEventHandler; + }> +>; -const IconButton: FC = ({ alt, children, className, disabled, onClick }) => { +const IconButton = ({ alt, children, className, disabled, onClick }: IconButtonProps): ReactNode => { const [{ sendBoxButton: sendBoxButtonStyleSet }] = useStyleSet(); const [{ sendBoxButtonAlignment }] = useStyleOptions(); const buttonRef = useRef(); diff --git a/packages/component/src/SendBox/MicrophoneButton.tsx b/packages/component/src/SendBox/MicrophoneButton.tsx index ce4c1f40b9..8ef04baac6 100644 --- a/packages/component/src/SendBox/MicrophoneButton.tsx +++ b/packages/component/src/SendBox/MicrophoneButton.tsx @@ -6,7 +6,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import memoize from 'memoize-one'; import PropTypes from 'prop-types'; -import React, { FC, useCallback, useState } from 'react'; +import React, { type ReactNode, useCallback, useState } from 'react'; import connectToWebChat from '../connectToWebChat'; import IconButton from './IconButton'; @@ -155,11 +155,11 @@ function useMicrophoneButtonDisabled(): [boolean] { ]; } -type MicrophoneButtonProps = { +type MicrophoneButtonProps = Readonly<{ className?: string; -}; +}>; -const MicrophoneButton: FC = ({ className }) => { +const MicrophoneButton = ({ className }: MicrophoneButtonProps): ReactNode => { const [{ microphoneButton: microphoneButtonStyleSet }] = useStyleSet(); const [dictateState] = useDictateState(); const [disabled] = useMicrophoneButtonDisabled(); diff --git a/packages/component/src/SendBox/SendButton.tsx b/packages/component/src/SendBox/SendButton.tsx index b3409a3ce8..f6534165b2 100644 --- a/packages/component/src/SendBox/SendButton.tsx +++ b/packages/component/src/SendBox/SendButton.tsx @@ -1,15 +1,13 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { useCallback } from 'react'; +import React, { useCallback, type ReactNode } from 'react'; import connectToWebChat from '../connectToWebChat'; import IconButton from './IconButton'; import SendIcon from './Assets/SendIcon'; import useSubmit from '../providers/internal/SendBox/useSubmit'; -import type { FC } from 'react'; - const { useDisabled, useLocalizer } = hooks; const connectSendButton = (...selectors) => @@ -22,11 +20,11 @@ const connectSendButton = (...selectors) => ...selectors ); -type SendButtonProps = { +type SendButtonProps = Readonly<{ className?: string; -}; +}>; -const SendButton: FC = ({ className }) => { +const SendButton = ({ className }: SendButtonProps): ReactNode => { const [disabled] = useDisabled(); const localize = useLocalizer(); const submit = useSubmit(); diff --git a/packages/component/src/SendBox/SuggestedActions.tsx b/packages/component/src/SendBox/SuggestedActions.tsx index e397c6401a..cfaa461914 100644 --- a/packages/component/src/SendBox/SuggestedActions.tsx +++ b/packages/component/src/SendBox/SuggestedActions.tsx @@ -5,7 +5,7 @@ import { hooks } from 'botframework-webchat-api'; import BasicFilm, { createBasicStyleSet as createBasicStyleSetForReactFilm } from 'react-film'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC, useCallback, useMemo, useRef } from 'react'; +import React, { type ReactNode, type PropsWithChildren, useCallback, useMemo, useRef } from 'react'; import type { DirectLineCardAction } from 'botframework-webchat-core'; import computeSuggestedActionText from '../Utils/computeSuggestedActionText'; @@ -43,7 +43,20 @@ const connectSuggestedActions = (...selectors) => ...selectors ); -const SuggestedActionCarouselContainer = ({ children, className, label }) => { +type SuggestedContainerProps = Readonly< + PropsWithChildren<{ + className?: string; + label: string; + }> +>; + +type SuggestedActionCarouselContainerProps = SuggestedContainerProps; + +const SuggestedActionCarouselContainer = ({ + children, + className, + label +}: SuggestedActionCarouselContainerProps): ReactNode => { const [ { suggestedActionsCarouselFlipperBoxWidth, @@ -131,7 +144,9 @@ SuggestedActionCarouselContainer.propTypes = { label: PropTypes.string.isRequired }; -const SuggestedActionFlowContainer = ({ children, className, label }) => { +type SuggestedActionFlowContainerProps = SuggestedContainerProps; + +const SuggestedActionFlowContainer = ({ children, className, label }: SuggestedActionFlowContainerProps): ReactNode => { const [{ suggestedActions: suggestedActionsStyleSet }] = useStyleSet(); const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; @@ -209,12 +224,12 @@ SuggestedActionStackedContainer.propTypes = { label: PropTypes.string.isRequired }; -type SuggestedActionsProps = { +type SuggestedActionsProps = Readonly<{ className?: string; suggestedActions?: DirectLineCardAction[]; -}; +}>; -const SuggestedActions: FC = ({ className, suggestedActions = [] }) => { +const SuggestedActions = ({ className, suggestedActions = [] }: SuggestedActionsProps): ReactNode => { const [{ suggestedActionLayout, suggestedActionsStackedLayoutButtonTextWrap }] = useStyleOptions(); const localize = useLocalizer(); const focus = useFocus(); diff --git a/packages/component/src/SendBox/UploadButton.tsx b/packages/component/src/SendBox/UploadButton.tsx index 87bc821362..ffbc6c8c0b 100644 --- a/packages/component/src/SendBox/UploadButton.tsx +++ b/packages/component/src/SendBox/UploadButton.tsx @@ -1,7 +1,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { FC, useCallback, useRef } from 'react'; +import React, { type ReactNode, useCallback, useRef } from 'react'; import AttachmentIcon from './Assets/AttachmentIcon'; import connectToWebChat from '../connectToWebChat'; @@ -89,11 +89,11 @@ const connectUploadButton = (...selectors) => ...selectors ); -type UploadButtonProps = { +type UploadButtonProps = Readonly<{ className?: string; -}; +}>; -const UploadButton: FC = ({ className }) => { +const UploadButton = ({ className }: UploadButtonProps): ReactNode => { const [{ uploadButton: uploadButtonStyleSet }] = useStyleSet(); const [disabled] = useDisabled(); const inputRef = useRef(); diff --git a/packages/component/src/Transcript/FocusTrap.tsx b/packages/component/src/Transcript/FocusTrap.tsx index 11cbf1f4d3..751db661db 100644 --- a/packages/component/src/Transcript/FocusTrap.tsx +++ b/packages/component/src/Transcript/FocusTrap.tsx @@ -1,18 +1,25 @@ import PropTypes from 'prop-types'; -import React, { Fragment, useCallback, useRef } from 'react'; - -import type { FC, KeyboardEventHandler, PropsWithChildren } from 'react'; +import React, { + type KeyboardEventHandler, + type PropsWithChildren, + type ReactNode, + Fragment, + useCallback, + useRef +} from 'react'; import FocusRedirector from '../Utils/FocusRedirector'; import tabbableElements from '../Utils/tabbableElements'; import useValueRef from '../hooks/internal/useValueRef'; -type FocusTrapProps = PropsWithChildren<{ - onFocus: () => void; - onLeave: () => void; -}>; +type FocusTrapProps = Readonly< + PropsWithChildren<{ + onFocus: () => void; + onLeave: () => void; + }> +>; -const FocusTrap: FC = ({ children, onFocus, onLeave }) => { +const FocusTrap = ({ children, onFocus, onLeave }: FocusTrapProps): ReactNode => { const bodyRef = useRef(); const onLeaveRef = useValueRef<() => void>(onLeave); diff --git a/packages/component/src/Transcript/KeyboardHelp.tsx b/packages/component/src/Transcript/KeyboardHelp.tsx index dd80771f15..b938b3162f 100644 --- a/packages/component/src/Transcript/KeyboardHelp.tsx +++ b/packages/component/src/Transcript/KeyboardHelp.tsx @@ -1,9 +1,7 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { useCallback, useState } from 'react'; - -import type { FC } from 'react'; +import React, { type ReactNode, useCallback, useState } from 'react'; import useFocus from '../hooks/useFocus'; import useStyleSet from '../hooks/useStyleSet'; @@ -11,12 +9,12 @@ import useUniqueId from '../hooks/internal/useUniqueId'; const { useLocalizer } = hooks; -type NotesBodyProps = { +type NotesBodyProps = Readonly<{ header: string; text: string; -}; +}>; -const Notes: FC = ({ header, text }) => ( +const Notes = ({ header, text }: NotesBodyProps): ReactNode => (

{header}

{text.split('\n').map((line, index) => ( @@ -34,7 +32,7 @@ Notes.propTypes = { text: PropTypes.string.isRequired }; -const KeyboardHelp: FC<{}> = () => { +const KeyboardHelp = (): ReactNode => { const [{ keyboardHelp: keyboardHelpStyleSet }] = useStyleSet(); const [shown, setShown] = useState(false); const focus = useFocus(); diff --git a/packages/component/src/Transcript/LiveRegionTranscript.tsx b/packages/component/src/Transcript/LiveRegionTranscript.tsx index 17f40e1db3..d499a4339d 100644 --- a/packages/component/src/Transcript/LiveRegionTranscript.tsx +++ b/packages/component/src/Transcript/LiveRegionTranscript.tsx @@ -1,9 +1,8 @@ import { hooks } from 'botframework-webchat-api'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import React, { useEffect, useMemo, useRef } from 'react'; -import type { FC, RefObject, VFC } from 'react'; -import type { WebChatActivity } from 'botframework-webchat-core'; +import React, { type RefObject, type ReactNode, useEffect, useMemo, useRef } from 'react'; +import { type WebChatActivity } from 'botframework-webchat-core'; import isPresentational from './LiveRegion/isPresentational'; import LiveRegionActivity from '../LiveRegion/LiveRegionActivity'; @@ -41,7 +40,7 @@ type LiveRegionTranscriptCoreProps = Readonly<{ activityElementMapRef: RefObject; }>; -const LiveRegionTranscriptCore: FC = ({ activityElementMapRef }) => { +const LiveRegionTranscriptCore = ({ activityElementMapRef }: LiveRegionTranscriptCoreProps): ReactNode => { // We are looking for all activities instead of just those will be rendered. // This is because some activities that chosen not be rendered in the chat history, // we might still need to be read by screen reader. Such as, suggested actions without text content. @@ -158,7 +157,7 @@ type LiveRegionTranscriptProps = { activityElementMapRef: RefObject; }; -const LiveRegionTranscript: VFC = ({ activityElementMapRef }) => { +const LiveRegionTranscript = ({ activityElementMapRef }: LiveRegionTranscriptProps) => { const [{ internalLiveRegionFadeAfter }] = useStyleOptions(); const localize = useLocalizer(); const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + ''; diff --git a/packages/component/src/Utils/FocusRedirector.tsx b/packages/component/src/Utils/FocusRedirector.tsx index 170e749f2c..6c91b1f058 100644 --- a/packages/component/src/Utils/FocusRedirector.tsx +++ b/packages/component/src/Utils/FocusRedirector.tsx @@ -1,7 +1,5 @@ import PropTypes from 'prop-types'; -import React, { useCallback } from 'react'; - -import type { FC, MutableRefObject } from 'react'; +import React, { useCallback, type MutableRefObject, type ReactNode } from 'react'; // This is an element, when focused, will send the focus to the ref specified in "redirectRef". // Although the focus is being redirected, browser will scroll this redirector element into view. @@ -12,13 +10,13 @@ import type { FC, MutableRefObject } from 'react'; // When this focus redirector is put inside a scrollable container, you may want to resize or reposition // it to prevent unintentional scroll done by the browser default behavior. -type FocusRedirectorProps = { +type FocusRedirectorProps = Readonly<{ className?: string; onFocus?: () => void; redirectRef?: MutableRefObject; -}; +}>; -const FocusRedirector: FC = ({ className, onFocus, redirectRef }) => { +const FocusRedirector = ({ className, onFocus, redirectRef }: FocusRedirectorProps): ReactNode => { const handleFocus = useCallback(() => { redirectRef?.current?.focus(); onFocus && onFocus(); diff --git a/packages/component/src/providers/ActivityTree/ActivityTreeComposer.tsx b/packages/component/src/providers/ActivityTree/ActivityTreeComposer.tsx index 4d5640cf3c..8bf2f38539 100644 --- a/packages/component/src/providers/ActivityTree/ActivityTreeComposer.tsx +++ b/packages/component/src/providers/ActivityTree/ActivityTreeComposer.tsx @@ -1,9 +1,8 @@ import { hooks } from 'botframework-webchat-api'; -import React, { useMemo } from 'react'; +import React, { useMemo, type PropsWithChildren, type ReactNode } from 'react'; -import type { ActivityComponentFactory } from 'botframework-webchat-api'; -import type { FC, PropsWithChildren } from 'react'; -import type { WebChatActivity } from 'botframework-webchat-core'; +import { type ActivityComponentFactory } from 'botframework-webchat-api'; +import { type WebChatActivity } from 'botframework-webchat-core'; import { ActivityWithRenderer, ReadonlyActivityTree } from './private/types'; import ActivityTreeContext from './private/Context'; @@ -12,13 +11,13 @@ import useActivityTreeContext from './private/useContext'; import useActivityTreeWithRenderer from './private/useActivityTreeWithRenderer'; import useMemoWithPrevious from '../../hooks/internal/useMemoWithPrevious'; -import type { ActivityTreeContextType } from './private/Context'; +import { type ActivityTreeContextType } from './private/Context'; -type ActivityTreeComposerProps = PropsWithChildren<{}>; +type ActivityTreeComposerProps = Readonly>; const { useActivities, useCreateActivityRenderer } = hooks; -const ActivityTreeComposer: FC = ({ children }) => { +const ActivityTreeComposer = ({ children }: ActivityTreeComposerProps): ReactNode => { const existingContext = useActivityTreeContext(false); if (existingContext) { diff --git a/packages/component/src/providers/LiveRegionTwin/LiveRegionTwinComposer.tsx b/packages/component/src/providers/LiveRegionTwin/LiveRegionTwinComposer.tsx index 9ac6958554..1adfba48a4 100644 --- a/packages/component/src/providers/LiveRegionTwin/LiveRegionTwinComposer.tsx +++ b/packages/component/src/providers/LiveRegionTwin/LiveRegionTwinComposer.tsx @@ -1,48 +1,56 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; - -import type { FC, PropsWithChildren } from 'react'; +import React, { + type PropsWithChildren, + type ReactNode, + useCallback, + useEffect, + useMemo, + useRef, + useState +} from 'react'; import LiveRegionTwinContainer from './private/LiveRegionTwinContainer'; import LiveRegionTwinContext from './private/Context'; import useValueRef from '../../hooks/internal/useValueRef'; -import type { StaticElement, StaticElementEntry } from './private/types'; +import { type StaticElement, type StaticElementEntry } from './private/types'; const { usePonyfill } = hooks; const DEFAULT_ARIA_LIVE = 'polite'; const DEFAULT_FADE_AFTER = 1000; -type LiveRegionTwinComposerProps = PropsWithChildren<{ - /** Optional "aria-label" attribute for the live region twin container. */ - 'aria-label'?: string; +type LiveRegionTwinComposerProps = Readonly< + PropsWithChildren<{ + /** Optional "aria-label" attribute for the live region twin container. */ + 'aria-label'?: string; - /** "aria-live" attribute for the live region twin container, defaults to `'polite'`. */ - 'aria-live'?: 'assertive' | 'polite'; + /** "aria-live" attribute for the live region twin container, defaults to `'polite'`. */ + 'aria-live'?: 'assertive' | 'polite'; - /** Optional "aria-roledescription" attribute for the live region twin container. */ - 'aria-roledescription'?: string; + /** Optional "aria-roledescription" attribute for the live region twin container. */ + 'aria-roledescription'?: string; - /** Optional "className" attribute for the live region twin container. */ - className?: string; + /** Optional "className" attribute for the live region twin container. */ + className?: string; - /** - * Static elements will fade out after this timeout value specified in milliseconds, defaults to `1000`. - * - * When lowering this value, make sure screen reader can continue to pick up new static elements before fading out. - * - * If this prop is updated, it will be reflected in next queueing elements. - */ - fadeAfter?: number; + /** + * Static elements will fade out after this timeout value specified in milliseconds, defaults to `1000`. + * + * When lowering this value, make sure screen reader can continue to pick up new static elements before fading out. + * + * If this prop is updated, it will be reflected in next queueing elements. + */ + fadeAfter?: number; - /** Optional "role" attribute for the live region twin container. */ - role?: string; + /** Optional "role" attribute for the live region twin container. */ + role?: string; - /** Optional "className" attribute for static text element. */ - textElementClassName?: string; -}>; + /** Optional "className" attribute for static text element. */ + textElementClassName?: string; + }> +>; /** * Live region twin is an UI component for queueing texts or elements to the screen reader using @@ -55,7 +63,7 @@ type LiveRegionTwinComposerProps = PropsWithChildren<{ * By default, the live region is visible. If is is not desirable, the caller can use `className` prop to * hide its visuals. */ -const LiveRegionTwinComposer: FC = ({ +const LiveRegionTwinComposer = ({ 'aria-label': ariaLabel, 'aria-live': ariaLive = DEFAULT_ARIA_LIVE, 'aria-roledescription': ariaRoleDescription, @@ -64,7 +72,7 @@ const LiveRegionTwinComposer: FC = ({ fadeAfter = DEFAULT_FADE_AFTER, role, textElementClassName -}) => { +}: LiveRegionTwinComposerProps): ReactNode => { const [{ clearTimeout, setTimeout }] = usePonyfill(); const [staticElementEntries, setStaticElementEntries] = useState([]); const fadeAfterRef = useValueRef(fadeAfter); diff --git a/packages/component/src/providers/RovingTabIndex/RovingTabIndexComposer.tsx b/packages/component/src/providers/RovingTabIndex/RovingTabIndexComposer.tsx index 28c06db473..1cb4022969 100644 --- a/packages/component/src/providers/RovingTabIndex/RovingTabIndexComposer.tsx +++ b/packages/component/src/providers/RovingTabIndex/RovingTabIndexComposer.tsx @@ -1,21 +1,30 @@ /* eslint complexity: ["error", 50] */ import PropTypes from 'prop-types'; -import React, { useCallback, useEffect, useMemo, useRef } from 'react'; +import React, { + type MutableRefObject, + type PropsWithChildren, + type ReactNode, + useCallback, + useEffect, + useMemo, + useRef +} from 'react'; import RovingTabIndexContext from './private/Context'; -import type { FC, MutableRefObject, PropsWithChildren } from 'react'; -import type { RovingTabIndexContextType } from './private/Context'; +import { type RovingTabIndexContextType } from './private/Context'; type ItemRef = MutableRefObject; -type RovingTabIndexContextProps = PropsWithChildren<{ - onEscapeKey?: () => void; - orientation?: 'horizontal' | 'vertical'; -}>; +type RovingTabIndexContextProps = Readonly< + PropsWithChildren<{ + onEscapeKey?: () => void; + orientation?: 'horizontal' | 'vertical'; + }> +>; -const RovingTabIndexComposer: FC = ({ children, onEscapeKey, orientation }) => { +const RovingTabIndexComposer = ({ children, onEscapeKey, orientation }: RovingTabIndexContextProps): ReactNode => { const activeItemIndexRef = useRef(0); const itemRefsRef = useRef([]); diff --git a/packages/component/src/providers/TranscriptFocus/TranscriptFocusComposer.tsx b/packages/component/src/providers/TranscriptFocus/TranscriptFocusComposer.tsx index 5b410be65d..adfc79af7d 100644 --- a/packages/component/src/providers/TranscriptFocus/TranscriptFocusComposer.tsx +++ b/packages/component/src/providers/TranscriptFocus/TranscriptFocusComposer.tsx @@ -1,7 +1,7 @@ import { hooks } from 'botframework-webchat-api'; import PropTypes from 'prop-types'; import random from 'math-random'; -import React, { useCallback, useMemo } from 'react'; +import React, { type ReactNode, type MutableRefObject, type PropsWithChildren, useCallback, useMemo } from 'react'; import scrollIntoViewWithBlockNearest from '../../Utils/scrollIntoViewWithBlockNearest'; import TranscriptFocusContext from './private/Context'; @@ -10,14 +10,15 @@ import usePrevious from '../../hooks/internal/usePrevious'; import useStateRef from '../../hooks/internal/useStateRef'; import useValueRef from '../../hooks/internal/useValueRef'; -import type { FC, MutableRefObject, PropsWithChildren } from 'react'; -import type { TranscriptFocusContextType } from './private/Context'; +import { type TranscriptFocusContextType } from './private/Context'; const { useGetKeyByActivity } = hooks; -type TranscriptFocusComposerProps = PropsWithChildren<{ - containerRef: MutableRefObject; -}>; +type TranscriptFocusComposerProps = Readonly< + PropsWithChildren<{ + containerRef: MutableRefObject; + }> +>; function last(array: ArrayLike) { return array[array.length - 1]; @@ -33,7 +34,7 @@ function uniqueId(count = Infinity) { ); } -const TranscriptFocusComposer: FC = ({ children, containerRef }) => { +const TranscriptFocusComposer = ({ children, containerRef }: TranscriptFocusComposerProps): ReactNode => { const [flattenedActivityTree] = useActivityTreeWithRenderer({ flat: true }); const [_, setRawFocusedActivityKey, rawFocusedActivityKeyRef] = useStateRef(); const getKeyByActivity = useGetKeyByActivity();