@talkjs/web-components
Version:
Provides chat UI components for TalkJS.
524 lines (436 loc) • 16.1 kB
TypeScript
import { AudioBlock } from '@talkjs/core';
import { ConversationSnapshot } from '@talkjs/core';
import { EditMessageParams } from '@talkjs/core';
import { EditTextMessageParams } 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 { SendMessageParams } from '@talkjs/core';
import { SendTextMessageParams } from '@talkjs/core';
import { TalkSession } 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;
}
export declare interface AvatarProps extends BaseChatboxProps {
photoUrl: string;
}
export declare interface BaseChatboxProps {
common: CommonChatboxProps;
}
/**
* 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>;
}
export declare interface Chatbox {
deleteMessage(messageId: string): Promise<void>;
setEditing(messageId: string | null): void;
editMessage(messageId: string, params: EditTextMessageParams | EditMessageParams): Promise<void>;
sendMessage(params: SendTextMessageParams | SendMessageParams): 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;
getMessageFieldText: () => string;
setMessageFieldText: (text: string) => void;
}
export declare interface ChatHeaderProps extends BaseChatboxProps {
isUserConnected: {
[userId: string]: boolean;
};
permissions: UserPermissions;
}
export declare interface CommonChatboxProps {
app: AppMetadata;
currentUser: UserSnapshot;
t: Translation;
chatbox: Chatbox;
themeCustom?: any;
device: DeviceFeatures;
theme: Theme;
conversation: ConversationSnapshot;
participants: ParticipantSnapshot[];
typing: TypingSnapshot;
}
export declare interface ContentBlockProps extends BaseChatboxProps {
message: MessageSnapshot;
}
export declare interface ConversationImageProps extends BaseChatboxProps {
}
export { ConversationSnapshot }
export declare interface Coordinates {
latitude: number;
longitude: number;
}
export declare function daysBetween(from: number, to: number): number;
export declare interface DeviceFeatures {
/**
* True if the browser supports IndexedDB, which the emoji picker depends on.
*/
supportsEmojiPicker: boolean;
/**
* True if the user agents reports this device as mobile (incl tablets).
*/
isMobile: boolean;
}
export declare function Editor({ placeholder, disabled, className, characterLimit, spellcheck, }: EditorProps): JSX.Element;
export declare interface EditorController extends EditorState {
send(): void;
shareLocation(): void;
attachFile(): void;
toggleEmojiPicker(): 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;
showEmojiPicker: boolean;
}
export declare function EmojiPicker(props: EmojiPickerProps): JSX.Element;
export declare interface EmojiPickerProps {
colorScheme: "light" | "dark";
}
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 interface GroupChatImageProps extends BaseChatboxProps {
}
export declare function html(strings: TemplateStringsArray, ...args: any[]): ReactElement;
export declare interface IconProps extends BaseChatboxProps {
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;
}
export { ImageBlock }
export declare interface ImageBlockProps extends ContentBlockProps {
block: ImageBlock;
downloadUrl?: string;
}
export { LocationBlock }
export declare interface LocationBlockProps extends ContentBlockProps {
block: LocationBlock;
}
/**
* MenuButton component that renders a dropdown menu triggered by a button.
*
* Usage:
* <MenuButton
* menuComponent={YourMenuComponent}
* menuProps={{ prop1: value1, prop2: value2 }}
* aria-label="Message actions"
* >
* <Icon type="horizontalDots" />
* </MenuButton>
*
* All props except for menuComponent and menuProps are passed to the button element.
*
* The menuComponent should be a component that renders the dropdown content.
* The menuProps are passed to the menuComponent.
*
* The menu component shouod render the MenuItem component for each menu item it wants to include.
*
* This is meant as a reuseable and accessible dropdown menu. We're using Radix for this, because they fulli implement
* the ARIA Menu Button pattern, but without adding any styles, so we can completely customise the look and feel.
*/
export declare function MenuButton<T extends object>(props: MenuButtonProps<T>): JSX.Element;
export declare type MenuButtonProps<T extends object> = {
menuComponent: React.ComponentType<T>;
menuProps: T;
children: React.ReactNode;
} & React.HTMLAttributes<HTMLButtonElement>;
export declare function MenuItem(props: MenuItemProps): JSX.Element;
export declare type MenuItemProps = React.HTMLAttributes<HTMLDivElement> & {
onSelect?: () => void;
disabled?: boolean;
textValue?: string;
};
export declare interface MessageActionMenuProps extends BaseChatboxProps {
}
export declare function MessageContent(props: MessageContentProps): JSX.Element;
export declare interface MessageContentProps extends BaseChatboxProps {
message: MessageSnapshot;
messageStatus: MessageStatus;
className?: string;
}
export declare interface MessageDividerProps extends BaseChatboxProps {
isReadMarker: boolean;
isDayMarker: boolean;
timestamp?: number;
}
export declare interface MessageFieldProps extends BaseChatboxProps {
referencedMessage: MessageSnapshot | undefined;
permissions: UserPermissions;
editor?: EditorController;
editMessageId: string | undefined;
}
export declare interface MessageListFooterProps extends BaseChatboxProps {
}
export declare interface MessagePermissions extends UserPermissions {
canDeleteMessage: boolean;
canReplyToMessage: boolean;
canEditMessage: boolean;
}
export declare interface MessageProps extends BaseChatboxProps {
message: MessageSnapshot;
messageStatus: MessageStatus;
permissions: MessagePermissions;
}
export { MessageSnapshot }
export declare type MessageStatus = "sending" | "sent" | "everyoneRead";
export { ParticipantSnapshot }
export declare interface ReferencedMessageProps extends BaseChatboxProps {
referencedMessage: ReferencedMessageSnapshot;
}
export { ReferencedMessageSnapshot }
export declare interface ReplyBarProps extends BaseChatboxProps {
referencedMessage: MessageSnapshot;
}
export { TalkSession }
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 {
Avatar: React_2.ComponentType<AvatarProps>;
ConversationImage: React_2.ComponentType<ConversationImageProps>;
GroupChatImage: React_2.ComponentType<GroupChatImageProps>;
ReferencedMessage: React_2.ComponentType<ReferencedMessageProps>;
ReplyBar: React_2.ComponentType<ReplyBarProps>;
TimeAgo: React_2.ComponentType<TimeAgoProps>;
MessageActionMenu: React_2.ComponentType<MessageActionMenuProps>;
ChatHeader: React_2.ComponentType<ChatHeaderProps>;
Message: React_2.ComponentType<MessageProps>;
MessageField: React_2.ComponentType<MessageFieldProps>;
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 interface TimeAgoProps extends BaseChatboxProps {
timestamp: number;
}
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 {
namespace JSX {
interface IntrinsicElements {
"emoji-picker": {
class?: string;
ref: React.Ref<HTMLElement>;
};
}
}
interface HTMLElementEventMap {
"emoji-click": EmojiClickEvent;
"skin-tone-change": SkinToneChangeEvent;
}
}
declare global {
interface HTMLElementTagNameMap {
"t-chatbox": ChatboxHTMLElement;
}
}
declare global {
namespace JSX {
interface IntrinsicElements {
"t-chatbox": typeof UnthemedChatbox;
}
}
}