@talkjs/react-components
Version:
Provides chat UI components for TalkJS.
551 lines (476 loc) • 17 kB
TypeScript
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;
}
}
}