UNPKG

@talkjs/react-components

Version:

Provides chat UI components for TalkJS.

551 lines (476 loc) 17 kB
import { AudioBlock } from '@talkjs/core'; import { ConversationSnapshot } from '@talkjs/core'; import { FileBlock } from '@talkjs/core'; import { FileToken } from '@talkjs/core'; import { ImageBlock } from '@talkjs/core'; import { LocationBlock } from '@talkjs/core'; import { MessageSnapshot } from '@talkjs/core'; import { ParticipantSnapshot } from '@talkjs/core'; import type * as React_2 from 'react'; import { ReactElement } from 'react'; import { ReferencedMessageSnapshot } from '@talkjs/core'; import { TextBlock } from '@talkjs/core'; import { TypingSnapshot } from '@talkjs/core'; import { UserSnapshot } from '@talkjs/core'; import { VideoBlock } from '@talkjs/core'; import { VoiceBlock } from '@talkjs/core'; declare type AppId = Brand<string, "App ID">; declare interface AppMetadata { id: AppId; name: string; defaultLocale: string; custom: Record<string, string>; } export { AudioBlock } export declare interface AudioBlockProps extends ContentBlockProps { block: AudioBlock; downloadUrl?: string; } /** * Audio player based on wavesurfer. * * @remarks * Wavesurfer is designed to make SoundCloud-style sound wave players. It has no * UI elements other than the actual sound waves, but it does abstract away all * the audio playing browser internals very nicely. * * Also, it has some additional settings that let us turn the sound wave display * into a series of nice rounded bars. Less signal, but also less distraction. I * kinda like it! */ export declare function AudioPlayer({ src, onError, filename, className, }: AudioPlayerProps): JSX.Element; export declare interface AudioPlayerProps { src: string; filename: string; onError?: () => void; className?: string; } /** * Brands a base type `T`. * * @example * ```ts * type UserId = Brand<string, "UserId">; * type MessageId = Brand<string, "MessageId">; * * const a: UserId = "abc" as UserId; // works * const b: UserId = "abc"; // error * const c: UserId = "abc" as MessageId; // error * ``` */ declare type Brand<T, B extends string> = T & Branding<B>; declare interface Branding<B extends string> { __tag: Record<B, true>; } /** * @public * * A string that is one of `"notifications" | "microphone" | "geolocation"`. * * @remarks * Note that more possible values may be added in the future, so make sure your * handler can deal with unknown permission types gracefully. */ export declare type BrowserPermission = "notifications" | "microphone" | "geolocation"; /** * Passed to `chatbox.beforeBrowserPermissionPrompt` when a browser permission * dialog needs to be shown to the user. * * @public */ export declare interface BrowserPermissionRequest { /** * The type of permission requested. * * @remarks * Note that more possible values may be added in the future, so make sure your * handler can deal with unknown permission types gracefully. */ type: BrowserPermission; /** * Cancel whatever user action caused the permission to be requested. * * @remarks * For example, if a user wants to share their location for the first time so * that this event is triggered, then if you call `cancel()`, no permission * will be requested from the browser, the location sharing will be cancelled, * and TalkJS will continue as if the location sharing button had not been * clicked at all. * * This may be useful if you're using this event to show custom UI elements * that nudge users towards granting permission, and this UI has a "cancel" * button. */ cancel(): void; /** * Show the browser permission prompt that lets the user allow or deny this * permission. * * @remarks * When the user clicks "Allow", then the user action that triggered the * browser permission request will proceed and the return value resolves to * `"granted"`. * * When the user clicks "Deny", then the user action is cancelled, the * `onMissingBrowserPermission` event is triggered, and the return value * resolves to `"denied"`. */ showPrompt(): Promise<"granted" | "denied">; } export declare interface Chatbox { deleteMessage(messageId: string): Promise<void>; editMessage(messageId: string, text: string): Promise<void>; sendMessage(message: { text: string; custom?: Record<string, string>; referencedMessageId?: string; }): Promise<void>; sendFileMessage(message: { fileToken: FileToken; custom?: Record<string, string>; }): Promise<void>; sendLocationMessage(message: { location: Coordinates; custom?: Record<string, string>; }): Promise<void>; setReferencedMessage(messageId: string | null): void; openMessageActionMenu(messageId: string): void; closeMessageActionMenu(): void; getMessageFieldText: () => string; setMessageFieldText: (text: string) => void; } export declare interface ChatHeaderProps { conversation: ConversationSnapshot; participants: ParticipantSnapshot[]; currentUser: UserSnapshot; t: Translation; chatbox: Chatbox; themeCustom?: any; isUserConnected: { [userId: string]: boolean; }; permissions: UserPermissions; } export declare interface ContentBlockProps { message: MessageSnapshot; currentUser: UserSnapshot; t: Translation; themeCustom?: any; } export { ConversationSnapshot } export declare interface Coordinates { latitude: number; longitude: number; } export declare interface DeleteMessageEvent { currentUser: UserSnapshot; message: MessageSnapshot; conversation: ConversationSnapshot; } export declare function Editor({ placeholder, disabled, className, characterLimit, spellcheck, }: EditorProps): JSX.Element; export declare interface EditorController extends EditorState { send(): void; shareLocation(): void; attachFile(): void; } export declare interface EditorProps { characterLimit?: number; disabled?: boolean; placeholder?: string; className?: string; spellcheck?: boolean; } declare interface EditorState { isTyping: boolean; atTextLimit: boolean; isEmpty: boolean; characterCount: number; } export { FileBlock } export declare interface FileBlockProps extends ContentBlockProps { block: FileBlock; downloadUrl?: string; } export declare function formatDuration(seconds: number): string; export declare function formatFilesize(bytes: number): string; export declare function getFilename(block: FileBlock): string | undefined; export declare function getGoogleMapsUrls({ latitude, longitude }: Coordinates): { imageUrl: string; linkUrl: string; }; export declare function getPhotoUrlWithFallback(user: UserSnapshot): string; export declare function getRandomColor(id: string): string; export declare function html(strings: TemplateStringsArray, ...args: any[]): ReactElement; /** * Finds the best-matching translation set for the given locale `code`. */ export declare function i18n(code: string): Translation; export declare interface IconProps { type: "attach" | "chevronLeft" | "left" | "chevronRight" | "right" | "chevronUp" | "up" | "chevronDown" | "down" | "close" | "emoji" | "locationPin" | "more" | "plus" | "search" | "send" | "spinner" | "play" | "pause" | "updown" | "addEmoji" | "microphone" | "mic" | "stop" | "download" | "location" | "email" | "movie" | "image" | "attachment" | "horizontalDots" | "verticalDots" | "reply" | "back"; className?: string; themeCustom?: any; } export { ImageBlock } export declare interface ImageBlockProps extends ContentBlockProps { block: ImageBlock; downloadUrl?: string; } export { LocationBlock } export declare interface LocationBlockProps extends ContentBlockProps { block: LocationBlock; } export declare interface MessageActionMenuProps { currentUser: UserSnapshot; permissions: MessagePermissions; conversation: ConversationSnapshot; message: MessageSnapshot; chatbox: Chatbox; t: Translation; themeCustom?: any; } export declare function MessageContent(props: MessageContentProps): JSX.Element; export declare interface MessageContentProps { currentUser: UserSnapshot; message: MessageSnapshot; t: Translation; messageStatus: MessageStatus; themeCustom?: any; className?: string; } export declare interface MessageDividerProps { isReadMarker: boolean; isDayMarker: boolean; timestamp?: number; currentUser: UserSnapshot; conversation: ConversationSnapshot; app: AppMetadata; t: Translation; themeCustom?: any; } export declare interface MessageFieldProps { conversation: ConversationSnapshot; participants: ParticipantSnapshot[]; referencedMessage: MessageSnapshot; currentUser: UserSnapshot; permissions: UserPermissions; t: Translation; chatbox: Chatbox; editor?: EditorController; themeCustom?: any; } export declare interface MessageListFooterProps { typing: TypingSnapshot; conversation: ConversationSnapshot; participants: ParticipantSnapshot[]; currentUser: UserSnapshot; t: Translation; chatbox: Chatbox; themeCustom?: any; } export declare interface MessagePermissions extends UserPermissions { canDeleteMessage: boolean; canReplyToMessage: boolean; } export declare interface MessageProps { app: AppMetadata; currentUser: UserSnapshot; message: MessageSnapshot; messageStatus: MessageStatus; conversation: ConversationSnapshot; participants: ParticipantSnapshot[]; permissions: MessagePermissions; t: Translation; chatbox: Chatbox; messageActionMenuAnchorRef: React_2.RefObject<HTMLElement | undefined>; themeCustom?: any; } export { MessageSnapshot } export declare type MessageStatus = "sending" | "sent" | "everyoneRead"; /** * Sent by `onMissingBrowserPermission` when the user tried to do an action that * require explicit browser permission, but that permission has been denied. * * @remarks * This event is meant to let you show a message to the user if an action (eg * sharing a location, or enabling notifications) can't proceed because the * browser permission for that has been denied. * * If you want to control when to show the browser permissions prompt, use * `beforeBrowserPermissionPrompt`. * * This event is emitted both when the user has denied this permission in the * past, and when a user action just triggered a browser permissions prompt * which the user then denied. If you need to differentiate between these two * cases, use `beforeBrowserPermissionPrompt`, and inspect the return value of * {@link BrowserPermissionRequest.showPrompt}. * * @public */ export declare interface MissingBrowserPermissionEvent { /** * The type of permission that was denied. * * @remarks * Note that more possible values may be added in the future, so make sure your * handler can deal with unknown permission types gracefully. */ type: BrowserPermission; } export { ParticipantSnapshot } export { ReferencedMessageSnapshot } export declare interface SendMessageEvent { currentUser: UserSnapshot; message: MessageSnapshot; conversation: ConversationSnapshot; } declare function Text_2({ block, className }: TextProps): ReactElement; export { Text_2 as Text } export { TextBlock } export declare interface TextBlockProps extends ContentBlockProps { block: TextBlock; } export declare interface TextProps { block: TextBlock; className?: string; } export declare interface Theme { ChatHeader: React_2.ComponentType<ChatHeaderProps>; Message: React_2.ComponentType<MessageProps>; MessageField: React_2.ComponentType<MessageFieldProps>; MessageActionMenu: React_2.ComponentType<MessageActionMenuProps>; Icon: React_2.ComponentType<IconProps>; MessageDivider: React_2.ComponentType<MessageDividerProps>; MessageListFooter: React_2.ComponentType<MessageListFooterProps>; TextBlock: React_2.ComponentType<TextBlockProps>; FileBlock: React_2.ComponentType<FileBlockProps>; LocationBlock: React_2.ComponentType<LocationBlockProps>; ImageBlock: React_2.ComponentType<ImageBlockProps>; AudioBlock: React_2.ComponentType<AudioBlockProps>; VoiceBlock: React_2.ComponentType<VoiceBlockProps>; VideoBlock: React_2.ComponentType<VideoBlockProps>; } export declare interface TimeAgo { /** * An amount of milliseconds after which the values in `long` and `short` _may_ have changed. * If undefined, the values will not change within any meaningful period. */ changeTimeout?: number | undefined; long: string; short: string; } export declare type Translation = TranslationData & TranslationStrings; declare interface TranslationData { locale: string; } declare interface TranslationStrings { YESTERDAY: string; TODAY: string; DAYS: string; HOURS: string; MINUTES: string; JUST_NOW: string; LOCATION: string; CANCEL: string; INBOX: string; DESKTOP_NOTIFICATIONS: string; DESKTOP_NOTIFICATIONS_ERROR: string; DESKTOP_NOTIFICATIONS_DEMO_TITLE: (appName: string) => string; DESKTOP_NOTIFICATIONS_DEMO_BODY: string; SEND_BUTTON_TEXT: string; ENTRYBOX_TEXT_LIMIT: string; ENTRYBOX_PLACEHOLDER: string; ENTRYBOX_PLACEHOLDER_CHAT_CLOSED: string; ENTRYBOX_PLACEHOLDER_CHAT_READONLY: string; MESSAGELIST_LOADING_OLDER: string; MESSAGELIST_SHOW_OLDER: string; MESSAGELIST_NEW_MARKER: string; MESSAGE_SENT_VIA_EMAIL: string; YOU_MARKER: string; UPLOAD_IN_PROGRESS: string; UPLOAD_SEND_FILE: string; UPLOAD_SHARE_LOCATION: string; UPLOAD_ERROR: string; SHARE_LOCATION_ERROR: string; LOADING: string; HUB_EMPTY: string; HUB_SHOW_EARLIER: string; INBOX_NO_CHATS_TITLE: string; INBOX_NO_CHATS_BODY: string; ENABLE_TRANSLATION: string; DISABLE_TRANSLATION: string; SEARCH_PLACEHOLDER_TEXT: string; SEARCH_SEARCHING: string; SEARCH_NO_RESULTS: string; SEARCH_NO_MORE_RESULTS: string; CHAT_NOT_FOUND: string; DELETE_MESSAGE: string; DELETION_EXPLANATION: string; EDIT_MESSAGE: string; SAVE: string; EDITED_INDICATOR: string; REPLY_TO_MESSAGE: string; REPLY_TO_ARIA_LABEL: (senderName: string, content: string) => string; REPLY_MODE_LEAVE_ARIA_LABEL: string; ADD_REACTION: string; AUTH_EXPIRED_OVERLAY_TITLE: string; AUTH_EXPIRED_OVERLAY_DESCRIPTION: string; VOICE_MESSAGE: string; LEAVE_CONVERSATION: string; MARK_CONVERSATION_AS_UNREAD: string; STATUS_INDICATOR_ONLINE: string; STATUS_INDICATOR_OFFLINE: string; CONTACT_INFORMATION_HIDDEN: string; } /** * Formats a time in the past in a twitter-like fashion. */ export declare function twitterAgo(now: number, ts: number, t: Translation): TimeAgo; export { TypingSnapshot } /** * returns "Yesterday", "Last Monday", "Tuesday, March 31" or "Monday, March 31 2014", depending on which is most appropriate. * @param ts number - unix timestamp (milliseconds) */ export declare function userFriendlyDate(ts: number, t: Translation): string; export declare interface UserPermissions { showTypingIndicator: boolean; canShareFile: boolean; canShareLocation: boolean; canMention: boolean; showOnlineStatus: boolean; canSendVoiceMessage: boolean; canLeaveConversation: boolean; canMarkConversationAsUnread: boolean; } export { UserSnapshot } /** * * This hooks triggers only when a human-readable timestamp needs to be updated. * For example, you could use it to display that a messages was updated X * minutes or Y hours ago. * * @public */ export declare function useTimeAgo(timestamp: number, t: Translation): TimeAgo; export { VideoBlock } export declare interface VideoBlockProps extends ContentBlockProps { block: VideoBlock; downloadUrl?: string; } export { VoiceBlock } export declare interface VoiceBlockProps extends ContentBlockProps { block: VoiceBlock; downloadUrl?: string; } export { } declare global { interface HTMLElementTagNameMap { "t-chatbox": ChatboxHTMLElement; } } declare global { namespace JSX { interface IntrinsicElements { "t-chatbox": typeof Chatbox; } } }