diff --git a/packages/livechat/src/components/Messages/AudioAttachment/index.js b/packages/livechat/src/components/Messages/AudioAttachment/index.tsx similarity index 83% rename from packages/livechat/src/components/Messages/AudioAttachment/index.js rename to packages/livechat/src/components/Messages/AudioAttachment/index.tsx index c3dad7c80d6b0854b6779526cd6862290f3ebf83..78b6a6ee5923f4f86992b6e086763b8e570ed4ae 100644 --- a/packages/livechat/src/components/Messages/AudioAttachment/index.js +++ b/packages/livechat/src/components/Messages/AudioAttachment/index.tsx @@ -5,7 +5,13 @@ import { createClassName } from '../../../helpers/createClassName'; import { MessageBubble } from '../MessageBubble'; import styles from './styles.scss'; -const AudioAttachment = ({ url, className, t, ...messageBubbleProps }) => ( +type AudioAttachmentProps = { + url: string; + className?: string; + t: (key: string) => string; +}; + +const AudioAttachment = ({ url, className, t, ...messageBubbleProps }: AudioAttachmentProps) => ( <MessageBubble nude className={createClassName(styles, 'audio-attachment', {}, [className])} {...messageBubbleProps}> <audio src={url} controls className={createClassName(styles, 'audio-attachment__inner')}> {t('you_browser_doesn_t_support_audio_element')} diff --git a/packages/livechat/src/components/Messages/FileAttachment/index.js b/packages/livechat/src/components/Messages/FileAttachment/index.tsx similarity index 86% rename from packages/livechat/src/components/Messages/FileAttachment/index.js rename to packages/livechat/src/components/Messages/FileAttachment/index.tsx index 303c9fc371736739ee4ef8e492d02e210bf7c3eb..3f97ca6289452eb5dbc61f5bb03026a56c2b8ea0 100644 --- a/packages/livechat/src/components/Messages/FileAttachment/index.js +++ b/packages/livechat/src/components/Messages/FileAttachment/index.tsx @@ -6,7 +6,13 @@ import { FileAttachmentIcon } from '../FileAttachmentIcon'; import { MessageBubble } from '../MessageBubble'; import styles from './styles.scss'; -export const FileAttachment = memo(({ url, title, className, ...messageBubbleProps }) => ( +type FileAttachmentProps = { + url: string; + title: string; + className?: string; +}; + +export const FileAttachment = memo(({ url, title, className, ...messageBubbleProps }: FileAttachmentProps) => ( <MessageBubble className={createClassName(styles, 'file-attachment', {}, [className])} {...messageBubbleProps}> <a href={url} download target='_blank' rel='noopener noreferrer' className={createClassName(styles, 'file-attachment__inner')}> <FileAttachmentIcon url={url} /> diff --git a/packages/livechat/src/components/Messages/FileAttachmentIcon/index.js b/packages/livechat/src/components/Messages/FileAttachmentIcon/index.tsx similarity index 53% rename from packages/livechat/src/components/Messages/FileAttachmentIcon/index.js rename to packages/livechat/src/components/Messages/FileAttachmentIcon/index.tsx index 9099d1f4aaf1c560e91b7fcbd95385ee1c055ba2..1ccef44d8e9f216d3739e61de47b97a5861685b1 100644 --- a/packages/livechat/src/components/Messages/FileAttachmentIcon/index.js +++ b/packages/livechat/src/components/Messages/FileAttachmentIcon/index.tsx @@ -7,15 +7,16 @@ import PPTIcon from '../../../icons/ppt.svg'; import SheetIcon from '../../../icons/sheet.svg'; import ZipIcon from '../../../icons/zip.svg'; -export const FileAttachmentIcon = memo(({ url }) => { +export const FileAttachmentIcon = memo(({ url }: { url?: string }) => { const extension = url ? url.split('.').pop() : null; const Icon = - (/pdf/i.test(extension) && PDFIcon) || - (/doc|docx|rtf|txt|odt|pages|log/i.test(extension) && DocIcon) || - (/ppt|pptx|pps/i.test(extension) && PPTIcon) || - (/xls|xlsx|csv/i.test(extension) && SheetIcon) || - (/zip|rar|7z|gz/i.test(extension) && ZipIcon) || - FileIcon; + extension && + ((/pdf/i.test(extension) && PDFIcon) || + (/doc|docx|rtf|txt|odt|pages|log/i.test(extension) && DocIcon) || + (/ppt|pptx|pps/i.test(extension) && PPTIcon) || + (/xls|xlsx|csv/i.test(extension) && SheetIcon) || + (/zip|rar|7z|gz/i.test(extension) && ZipIcon) || + FileIcon); return <Icon width={32} />; }); diff --git a/packages/livechat/src/components/Messages/ImageAttachment/index.js b/packages/livechat/src/components/Messages/ImageAttachment/index.tsx similarity index 81% rename from packages/livechat/src/components/Messages/ImageAttachment/index.js rename to packages/livechat/src/components/Messages/ImageAttachment/index.tsx index 23c60e24bc477ac8471c00f2c2f4fe3cd55c5fdd..f62817ebffbca7a0a7a3d63bd6866214530e6704 100644 --- a/packages/livechat/src/components/Messages/ImageAttachment/index.js +++ b/packages/livechat/src/components/Messages/ImageAttachment/index.tsx @@ -4,7 +4,12 @@ import { createClassName } from '../../../helpers/createClassName'; import { MessageBubble } from '../MessageBubble'; import styles from './styles.scss'; -export const ImageAttachment = memo(({ url, className, ...messageBubbleProps }) => ( +type ImageAttachmentProps = { + url: string; + className?: string; +}; + +export const ImageAttachment = memo(({ url, className, ...messageBubbleProps }: ImageAttachmentProps) => ( <MessageBubble nude className={createClassName(styles, 'image-attachment', {}, [className])} {...messageBubbleProps}> <img src={url} className={createClassName(styles, 'image-attachment__inner')} /> </MessageBubble> diff --git a/packages/livechat/src/components/Messages/MessageAvatars/index.js b/packages/livechat/src/components/Messages/MessageAvatars/index.tsx similarity index 64% rename from packages/livechat/src/components/Messages/MessageAvatars/index.js rename to packages/livechat/src/components/Messages/MessageAvatars/index.tsx index aa25528be11b0430d51373061e18908d3f158c58..9a405efb8ff030e429c7c58e28bda56eaf29316b 100644 --- a/packages/livechat/src/components/Messages/MessageAvatars/index.js +++ b/packages/livechat/src/components/Messages/MessageAvatars/index.tsx @@ -4,7 +4,14 @@ import { createClassName } from '../../../helpers/createClassName'; import { Avatar } from '../../Avatar'; import styles from './styles.scss'; -export const MessageAvatars = memo(({ avatarResolver = () => null, usernames = [], className, style = {} }) => { +type MessageAvatarsProps = { + avatarResolver: (username: string) => string | undefined; + usernames: string[]; + className?: string; + style?: React.CSSProperties; +}; + +export const MessageAvatars = memo(({ avatarResolver = () => undefined, usernames = [], className, style = {} }: MessageAvatarsProps) => { const avatars = usernames.filter(Boolean); if (!avatars.length) { diff --git a/packages/livechat/src/components/Messages/MessageBlocks/index.js b/packages/livechat/src/components/Messages/MessageBlocks/index.tsx similarity index 82% rename from packages/livechat/src/components/Messages/MessageBlocks/index.js rename to packages/livechat/src/components/Messages/MessageBlocks/index.tsx index bccb1399b24b1295f9127e73123eefa3616e6185..d08b2360ebc2fdf0487df16ae746e7af8fc5674f 100644 --- a/packages/livechat/src/components/Messages/MessageBlocks/index.js +++ b/packages/livechat/src/components/Messages/MessageBlocks/index.tsx @@ -6,9 +6,15 @@ import { renderMessageBlocks } from '../../uiKit'; import Surface from '../../uiKit/message/Surface'; import styles from './styles.scss'; -const MessageBlocks = ({ blocks = [], mid = undefined, rid = undefined }) => { +type MessageBlocksProps = { + blocks?: unknown[]; + mid?: string; + rid?: string; +}; + +const MessageBlocks = ({ blocks = [], mid = undefined, rid = undefined }: MessageBlocksProps) => { const dispatchAction = useCallback( - ({ appId, actionId, payload }) => + ({ appId, actionId, payload }: { appId: string; actionId: string; payload: unknown }) => triggerAction({ appId, type: UIKitIncomingInteractionType.BLOCK, diff --git a/packages/livechat/src/components/Messages/MessageBubble/index.js b/packages/livechat/src/components/Messages/MessageBubble/index.tsx similarity index 59% rename from packages/livechat/src/components/Messages/MessageBubble/index.js rename to packages/livechat/src/components/Messages/MessageBubble/index.tsx index 56009164c170fad47304cb3227243fc5dedf789c..b46d28a8f8471e93b4186b5a2800e5a13aada93e 100644 --- a/packages/livechat/src/components/Messages/MessageBubble/index.js +++ b/packages/livechat/src/components/Messages/MessageBubble/index.tsx @@ -1,9 +1,20 @@ +import type { ComponentChildren } from 'preact'; import { memo } from 'preact/compat'; import { createClassName } from '../../../helpers/createClassName'; import styles from './styles.scss'; -export const MessageBubble = memo(({ inverse, nude, quoted, className, style = {}, children, system = false }) => ( +type MessageBubbleProps = { + inverse?: boolean; + nude?: boolean; + quoted?: boolean; + className?: string; + style?: React.CSSProperties; + system?: boolean; + children?: ComponentChildren; +}; + +export const MessageBubble = memo(({ inverse, nude, quoted, className, style = {}, children, system = false }: MessageBubbleProps) => ( <div data-qa='message-bubble' className={createClassName(styles, 'message-bubble', { inverse, nude, quoted, system }, [className])} diff --git a/packages/livechat/src/components/Messages/MessageContainer/index.js b/packages/livechat/src/components/Messages/MessageContainer/index.js deleted file mode 100644 index 23a30ca556684a2a78de1898c0c52e6adf9c4aa1..0000000000000000000000000000000000000000 --- a/packages/livechat/src/components/Messages/MessageContainer/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import { memo } from 'preact/compat'; - -import { createClassName } from '../../../helpers/createClassName'; -import styles from './styles.scss'; - -export const MessageContainer = memo(({ id, compact, reverse, use: Element = 'div', className, style = {}, children, system = false }) => ( - <Element id={id} className={createClassName(styles, 'message-container', { compact, reverse, system }, [className])} style={style}> - {children} - </Element> -)); diff --git a/packages/livechat/src/components/Messages/MessageContainer/index.tsx b/packages/livechat/src/components/Messages/MessageContainer/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..62e49f61480aba8758571f7d2429f8c86fa1f650 --- /dev/null +++ b/packages/livechat/src/components/Messages/MessageContainer/index.tsx @@ -0,0 +1,26 @@ +import type { ComponentChildren } from 'preact'; +import { memo } from 'preact/compat'; + +import { createClassName } from '../../../helpers/createClassName'; +import styles from './styles.scss'; + +type MessageContainerProps = { + id?: string; + compact?: boolean; + reverse?: boolean; + use?: any; + className?: string; + style?: React.CSSProperties; + system?: boolean; + children?: ComponentChildren; +}; + +export const MessageContainer = memo( + // TODO: find a better way to pass `use` and do not default to a string + // eslint-disable-next-line @typescript-eslint/naming-convention + ({ id, compact, reverse, use: Element = 'div', className, style = {}, children, system = false }: MessageContainerProps) => ( + <Element id={id} className={createClassName(styles, 'message-container', { compact, reverse, system }, [className])} style={style}> + {children} + </Element> + ), +); diff --git a/packages/livechat/src/components/Messages/MessageContent/index.js b/packages/livechat/src/components/Messages/MessageContent/index.tsx similarity index 59% rename from packages/livechat/src/components/Messages/MessageContent/index.js rename to packages/livechat/src/components/Messages/MessageContent/index.tsx index 251e942599b61d11289eea5d18fa6a3cbdb9fdaf..0cbad364e7d407ca0711bff34b1a14c4e6734615 100644 --- a/packages/livechat/src/components/Messages/MessageContent/index.js +++ b/packages/livechat/src/components/Messages/MessageContent/index.tsx @@ -1,9 +1,17 @@ +import type { ComponentChildren } from 'preact'; import { memo } from 'preact/compat'; import { createClassName } from '../../../helpers/createClassName'; import styles from './styles.scss'; -export const MessageContent = memo(({ reverse, className, style = {}, children }) => ( +type MessageContentProps = { + reverse?: boolean; + className?: string; + style?: React.CSSProperties; + children?: ComponentChildren; +}; + +export const MessageContent = memo(({ reverse, className, style = {}, children }: MessageContentProps) => ( <div className={createClassName(styles, 'message-content', { reverse }, [className])} style={style}> {children} </div> diff --git a/packages/livechat/src/components/Messages/MessageSeparator/index.js b/packages/livechat/src/components/Messages/MessageSeparator/index.tsx similarity index 69% rename from packages/livechat/src/components/Messages/MessageSeparator/index.js rename to packages/livechat/src/components/Messages/MessageSeparator/index.tsx index 0b19b50299034d1108640150cb6120f055136a6e..1cfdeb2fa93d16dadc00117fe83da3e2fa73a040 100644 --- a/packages/livechat/src/components/Messages/MessageSeparator/index.js +++ b/packages/livechat/src/components/Messages/MessageSeparator/index.tsx @@ -1,10 +1,23 @@ +import type { TFunction } from 'i18next'; +import type { CSSProperties } from 'preact/compat'; import { memo } from 'preact/compat'; import { withTranslation } from 'react-i18next'; import { createClassName } from '../../../helpers/createClassName'; import styles from './styles.scss'; -const MessageSeparator = ({ date, unread, use: Element = 'div', className, style = {}, t }) => ( +type MessageSeparatorProps = { + date?: string; + unread?: boolean; + className?: string; + style?: CSSProperties; + t: TFunction; + use?: any; +}; + +// TODO: find a better way to pass `use` and do not default to a string +// eslint-disable-next-line @typescript-eslint/naming-convention +const MessageSeparator = ({ date, unread, use: Element = 'div', className, style = {}, t }: MessageSeparatorProps) => ( <Element className={createClassName( styles, diff --git a/packages/livechat/src/components/Messages/MessageTime/index.js b/packages/livechat/src/components/Messages/MessageTime/index.tsx similarity index 53% rename from packages/livechat/src/components/Messages/MessageTime/index.js rename to packages/livechat/src/components/Messages/MessageTime/index.tsx index 1c44695478bbfd0d92aaa678212a51f88e536884..b4a675e019f42dc335017ab9fe5a47048e48ef2c 100644 --- a/packages/livechat/src/components/Messages/MessageTime/index.js +++ b/packages/livechat/src/components/Messages/MessageTime/index.tsx @@ -1,12 +1,13 @@ import { parseISO } from 'date-fns/fp'; import isToday from 'date-fns/isToday'; +import type { TFunction } from 'i18next'; import { memo } from 'preact/compat'; import { withTranslation } from 'react-i18next'; import { createClassName } from '../../../helpers/createClassName'; import styles from './styles.scss'; -const parseDate = (ts, t) => { +const parseDate = (ts: number, t: TFunction) => { const timestamp = new Date(ts).toISOString(); return t('message_time', { val: new Date(timestamp), @@ -16,16 +17,26 @@ const parseDate = (ts, t) => { }); }; -const MessageTime = ({ ts, normal, inverted, className, style = {}, t }) => ( - <div className={createClassName(styles, 'message-time-wrapper')}> - <time - dateTime={new Date(ts).toISOString()} - className={createClassName(styles, 'message-time', { normal, inverted }, [className])} - style={style} - > - {parseDate(ts, t)} - </time> - </div> -); +type MessageTimeProps = { + ts: number; + normal?: boolean; + inverted?: boolean; + className?: string; + style?: React.CSSProperties; + t: TFunction; +}; +const MessageTime = ({ ts, normal, inverted, className, style = {}, t }: MessageTimeProps) => { + return ( + <div className={createClassName(styles, 'message-time-wrapper')}> + <time + dateTime={new Date(ts).toISOString()} + className={createClassName(styles, 'message-time', { normal, inverted }, [className])} + style={style} + > + {parseDate(ts, t)} + </time> + </div> + ); +}; export default withTranslation()(memo(MessageTime)); diff --git a/packages/livechat/src/components/Messages/TypingDots/index.js b/packages/livechat/src/components/Messages/TypingDots/index.tsx similarity index 70% rename from packages/livechat/src/components/Messages/TypingDots/index.js rename to packages/livechat/src/components/Messages/TypingDots/index.tsx index 3efa46a2403ceb9ce8d94d5d9469340a5f6e7588..79c2227a9afeda86598dfb55bae3aca982c53dc7 100644 --- a/packages/livechat/src/components/Messages/TypingDots/index.js +++ b/packages/livechat/src/components/Messages/TypingDots/index.tsx @@ -1,7 +1,13 @@ import { createClassName } from '../../../helpers/createClassName'; import styles from './styles.scss'; -export const TypingDots = ({ text, className, style = {} }) => ( +type TypingDotsProps = { + text: string; + className?: string; + style?: React.CSSProperties; +}; + +export const TypingDots = ({ text, className, style = {} }: TypingDotsProps) => ( <div aria-label={text} className={createClassName(styles, 'typing-dots', {}, [className])} style={style}> <span class={createClassName(styles, 'typing-dots__dot')} /> <span class={createClassName(styles, 'typing-dots__dot')} /> diff --git a/packages/livechat/src/components/Messages/TypingIndicator/index.js b/packages/livechat/src/components/Messages/TypingIndicator/index.tsx similarity index 67% rename from packages/livechat/src/components/Messages/TypingIndicator/index.js rename to packages/livechat/src/components/Messages/TypingIndicator/index.tsx index 763caa1f247721afdfedb63ef363c02346f4fc3b..1018b2f7504e53bcd44b5c680b59c78c833f0f30 100644 --- a/packages/livechat/src/components/Messages/TypingIndicator/index.js +++ b/packages/livechat/src/components/Messages/TypingIndicator/index.tsx @@ -6,7 +6,13 @@ import { MessageContainer } from '../MessageContainer'; import { MessageContent } from '../MessageContent'; import { TypingDots } from '../TypingDots'; -export const TypingIndicator = memo(({ avatarResolver = () => null, usernames = [], text, ...containerProps }) => ( +type TypingIndicatorProps = { + avatarResolver: (username: string) => string | undefined; + usernames?: string[]; + text: string; +}; + +export const TypingIndicator = memo(({ avatarResolver, usernames = [], text, ...containerProps }: TypingIndicatorProps) => ( <MessageContainer {...containerProps}> <MessageAvatars avatarResolver={avatarResolver} usernames={usernames} /> <MessageContent> diff --git a/packages/livechat/src/components/Messages/VideoAttachment/index.js b/packages/livechat/src/components/Messages/VideoAttachment/index.tsx similarity index 80% rename from packages/livechat/src/components/Messages/VideoAttachment/index.js rename to packages/livechat/src/components/Messages/VideoAttachment/index.tsx index 811a88255cbe5692a3ae7d5045ad36d65c094043..e0d72ad12915fb4df8cd90ca6c48e7875e485dcf 100644 --- a/packages/livechat/src/components/Messages/VideoAttachment/index.js +++ b/packages/livechat/src/components/Messages/VideoAttachment/index.tsx @@ -1,3 +1,4 @@ +import type { TFunction } from 'i18next'; import { memo } from 'preact/compat'; import { withTranslation } from 'react-i18next'; @@ -5,7 +6,12 @@ import { createClassName } from '../../../helpers/createClassName'; import { MessageBubble } from '../MessageBubble'; import styles from './styles.scss'; -const VideoAttachment = ({ url, className, t, ...messageBubbleProps }) => ( +type VideoAttachmentProps = { + url: string; + className?: string; + t: TFunction; +}; +const VideoAttachment = ({ url, className, t, ...messageBubbleProps }: VideoAttachmentProps) => ( <MessageBubble nude className={createClassName(styles, 'video-attachment', {}, [className])} {...messageBubbleProps}> <video src={url} controls className={createClassName(styles, 'video-attachment__inner')}> {t('you_browser_doesn_t_support_video_element')} diff --git a/packages/livechat/src/components/Messages/index.js b/packages/livechat/src/components/Messages/index.ts similarity index 100% rename from packages/livechat/src/components/Messages/index.js rename to packages/livechat/src/components/Messages/index.ts