@talkjs/react-components 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import{createContext as n,useContext as e}from"react";import{tracking as r}from"@legendapp/state";class o extends Error{}function i(n,e){if(!n)throw new o(e??"Assertion failed")}const t=Object.assign(i,{is:function(n,e,r){return i(e,r)},unreachable:function(){throw new Error("Unreachable code")},keyNonNullable:function(n,e){if(!(e in n))throw new o(`Missing key "${e}"`);const r=n[e];if(null==r)throw new o(`Key "${e}" is null or undefined`)},insideObservingContext:function(){if(!r.current)throw new Error("You aren't inside an observing context")},never:function(n){throw new Error("Unreachable")},defined:function(n){if(null==n)throw new o("Value is not defined")}}),c=n(void 0),s=h(c),u=n(void 0),f=h(u),d=n(void 0),a=h(d),l=n(void 0),w=n(l);function h(n){return()=>{const r=e(n);return t(void 0!==r),r}}export{u as EditorInternalsContext,l as PermissionContext,d as StoreContext,c as ThemeContext,f as useEditorInternals,w as usePermission,a as useStore,s as useTheme};
3
+ //# sourceMappingURL=globalConstants.js.map
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@talkjs/react-components",
3
+ "version": "0.0.8",
4
+ "bugs": {
5
+ "url": "https://talkjs.com/?chat"
6
+ },
7
+ "homepage": "https://talkjs.com",
8
+ "type": "module",
9
+ "license": "SEE LICENSE IN LICENSE.md",
10
+ "description": "Provides chat UI components for TalkJS.",
11
+ "files": [
12
+ "default.d.ts",
13
+ "default.js",
14
+ "theming.d.ts",
15
+ "theming.js",
16
+ "globalConstants.js",
17
+ "default.css",
18
+ "base.css",
19
+ "LICENSE.md"
20
+ ],
21
+ "main": "default.js",
22
+ "module": "default.js",
23
+ "types": "default.d.ts",
24
+ "dependencies": {
25
+ "@floating-ui/dom": "^1.6.5",
26
+ "@legendapp/state": "3.0.0-alpha.9",
27
+ "@reach/menu-button": "^0.18.0",
28
+ "@talkjs/core": "~1.2.0",
29
+ "autolinker": "^4.0.0",
30
+ "htm": "^3.1.1",
31
+ "lodash.merge": "^4.6.2",
32
+ "onecolor": "^4.1.0",
33
+ "prosemirror-commands": "^1.5.2",
34
+ "prosemirror-history": "^1.4.0",
35
+ "prosemirror-keymap": "^1.2.2",
36
+ "prosemirror-model": "^1.21.1",
37
+ "prosemirror-state": "^1.4.3",
38
+ "prosemirror-transform": "^1.9.0",
39
+ "prosemirror-view": "^1.33.7",
40
+ "react-error-boundary": "^5.0.0",
41
+ "react-is": "^19.0.0",
42
+ "universal-base64": "^2.1.0",
43
+ "wavesurfer.js": "^7.7.7"
44
+ },
45
+ "peerDependencies": {
46
+ "react": "^18.2.0",
47
+ "react-dom": "^18.2.0"
48
+ },
49
+ "keywords": [
50
+ "chat",
51
+ "chat api",
52
+ "chat sdk",
53
+ "messaging",
54
+ "talk",
55
+ "talkjs",
56
+ "realtime",
57
+ "real-time messaging",
58
+ "real-time chat",
59
+ "direct messaging",
60
+ "user-to-user chat",
61
+ "private messaging",
62
+ "group chat",
63
+ "dm",
64
+ "pm",
65
+ "notification",
66
+ "notifications"
67
+ ]
68
+ }
package/theming.d.ts ADDED
@@ -0,0 +1,544 @@
1
+ import { AudioBlock } from '@talkjs/core';
2
+ import { ConversationSnapshot } from '@talkjs/core';
3
+ import { FileBlock } from '@talkjs/core';
4
+ import { FileToken } from '@talkjs/core';
5
+ import { ImageBlock } from '@talkjs/core';
6
+ import { LocationBlock } from '@talkjs/core';
7
+ import { MessageSnapshot } from '@talkjs/core';
8
+ import { ParticipantSnapshot } from '@talkjs/core';
9
+ import type * as React_2 from 'react';
10
+ import { ReactElement } from 'react';
11
+ import { TextBlock } from '@talkjs/core';
12
+ import { TypingSnapshot } from '@talkjs/core';
13
+ import { UserSnapshot } from '@talkjs/core';
14
+ import { VideoBlock } from '@talkjs/core';
15
+ import { VoiceBlock } from '@talkjs/core';
16
+
17
+ declare type AppId = Brand<string, "App ID">;
18
+
19
+ declare interface AppMetadata {
20
+ id: AppId;
21
+ name: string;
22
+ defaultLocale: string;
23
+ custom: Record<string, string>;
24
+ }
25
+
26
+ export { AudioBlock }
27
+
28
+ export declare interface AudioBlockProps extends ContentBlockProps {
29
+ block: AudioBlock;
30
+ downloadUrl?: string;
31
+ }
32
+
33
+ /**
34
+ * Audio player based on wavesurfer.
35
+ *
36
+ * @remarks
37
+ * Wavesurfer is designed to make SoundCloud-style sound wave players. It has no
38
+ * UI elements other than the actual sound waves, but it does abstract away all
39
+ * the audio playing browser internals very nicely.
40
+ *
41
+ * Also, it has some additional settings that let us turn the sound wave display
42
+ * into a series of nice rounded bars. Less signal, but also less distraction. I
43
+ * kinda like it!
44
+ */
45
+ export declare function AudioPlayer({ src, onError, filename, className, }: AudioPlayerProps): JSX.Element;
46
+
47
+ export declare interface AudioPlayerProps {
48
+ src: string;
49
+ filename: string;
50
+ onError?: () => void;
51
+ className?: string;
52
+ }
53
+
54
+ /**
55
+ * Brands a base type `T`.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * type UserId = Brand<string, "UserId">;
60
+ * type MessageId = Brand<string, "MessageId">;
61
+ *
62
+ * const a: UserId = "abc" as UserId; // works
63
+ * const b: UserId = "abc"; // error
64
+ * const c: UserId = "abc" as MessageId; // error
65
+ * ```
66
+ */
67
+ declare type Brand<T, B extends string> = T & Branding<B>;
68
+
69
+ declare interface Branding<B extends string> {
70
+ __tag: Record<B, true>;
71
+ }
72
+
73
+ /**
74
+ * @public
75
+ *
76
+ * A string that is one of `"notifications" | "microphone" | "geolocation"`.
77
+ *
78
+ * @remarks
79
+ * Note that more possible values may be added in the future, so make sure your
80
+ * handler can deal with unknown permission types gracefully.
81
+ */
82
+ export declare type BrowserPermission = "notifications" | "microphone" | "geolocation";
83
+
84
+ /**
85
+ * Passed to `chatbox.beforeBrowserPermissionPrompt` when a browser permission
86
+ * dialog needs to be shown to the user.
87
+ *
88
+ * @public
89
+ */
90
+ export declare interface BrowserPermissionRequest {
91
+ /**
92
+ * The type of permission requested.
93
+ *
94
+ * @remarks
95
+ * Note that more possible values may be added in the future, so make sure your
96
+ * handler can deal with unknown permission types gracefully.
97
+ */
98
+ type: BrowserPermission;
99
+ /**
100
+ * Cancel whatever user action caused the permission to be requested.
101
+ *
102
+ * @remarks
103
+ * For example, if a user wants to share their location for the first time so
104
+ * that this event is triggered, then if you call `cancel()`, no permission
105
+ * will be requested from the browser, the location sharing will be cancelled,
106
+ * and TalkJS will continue as if the location sharing button had not been
107
+ * clicked at all.
108
+ *
109
+ * This may be useful if you're using this event to show custom UI elements
110
+ * that nudge users towards granting permission, and this UI has a "cancel"
111
+ * button.
112
+ */
113
+ cancel(): void;
114
+ /**
115
+ * Show the browser permission prompt that lets the user allow or deny this
116
+ * permission.
117
+ *
118
+ * @remarks
119
+ * When the user clicks "Allow", then the user action that triggered the
120
+ * browser permission request will proceed and the return value resolves to
121
+ * `"granted"`.
122
+ *
123
+ * When the user clicks "Deny", then the user action is cancelled, the
124
+ * `onMissingBrowserPermission` event is triggered, and the return value
125
+ * resolves to `"denied"`.
126
+ */
127
+ showPrompt(): Promise<"granted" | "denied">;
128
+ }
129
+
130
+ export declare interface Chatbox {
131
+ deleteMessage(messageId: string): Promise<void>;
132
+ editMessage(messageId: string, text: string): Promise<void>;
133
+ sendMessage(message: {
134
+ text: string;
135
+ custom?: Record<string, string>;
136
+ referencedMessageId?: string;
137
+ }): Promise<void>;
138
+ sendFileMessage(message: {
139
+ fileToken: FileToken;
140
+ custom?: Record<string, string>;
141
+ }): Promise<void>;
142
+ sendLocationMessage(message: {
143
+ location: Coordinates;
144
+ custom?: Record<string, string>;
145
+ }): Promise<void>;
146
+ setReferencedMessage(messageId: string | null): void;
147
+ openMessageActionMenu(messageId: string): void;
148
+ closeMessageActionMenu(): void;
149
+ getMessageFieldText: () => string;
150
+ setMessageFieldText: (text: string) => void;
151
+ }
152
+
153
+ export declare interface ChatHeaderProps {
154
+ conversation: ConversationSnapshot;
155
+ participants: ParticipantSnapshot[];
156
+ currentUser: UserSnapshot;
157
+ t: Translation;
158
+ chatbox: Chatbox;
159
+ themeCustom: any;
160
+ }
161
+
162
+ export declare interface ContentBlockProps {
163
+ message: MessageSnapshot;
164
+ currentUser: UserSnapshot;
165
+ t: Translation;
166
+ themeCustom: any;
167
+ }
168
+
169
+ export { ConversationSnapshot }
170
+
171
+ export declare interface Coordinates {
172
+ latitude: number;
173
+ longitude: number;
174
+ }
175
+
176
+ export declare interface DeleteMessageEvent {
177
+ currentUser: UserSnapshot;
178
+ message: MessageSnapshot;
179
+ conversation: ConversationSnapshot;
180
+ }
181
+
182
+ export declare function Editor({ placeholder, disabled, className, characterLimit, spellcheck, }: EditorProps): JSX.Element;
183
+
184
+ export declare interface EditorController extends EditorState {
185
+ send(): void;
186
+ shareLocation(): void;
187
+ attachFile(): void;
188
+ }
189
+
190
+ export declare interface EditorProps {
191
+ characterLimit?: number;
192
+ disabled?: boolean;
193
+ placeholder?: string;
194
+ className?: string;
195
+ spellcheck?: boolean;
196
+ }
197
+
198
+ declare interface EditorState {
199
+ isTyping: boolean;
200
+ atTextLimit: boolean;
201
+ isEmpty: boolean;
202
+ characterCount: number;
203
+ }
204
+
205
+ export { FileBlock }
206
+
207
+ export declare interface FileBlockProps extends ContentBlockProps {
208
+ block: FileBlock;
209
+ downloadUrl?: string;
210
+ }
211
+
212
+ export declare function formatDuration(seconds: number): string;
213
+
214
+ export declare function formatFilesize(bytes: number): string;
215
+
216
+ export declare function getFilename(block: FileBlock): string | undefined;
217
+
218
+ export declare function getGoogleMapsUrls({ latitude, longitude }: Coordinates): {
219
+ imageUrl: string;
220
+ linkUrl: string;
221
+ };
222
+
223
+ export declare function getPhotoUrlWithFallback(user: UserSnapshot): string;
224
+
225
+ export declare function getRandomColor(id: string): string;
226
+
227
+ export declare function html(strings: TemplateStringsArray, ...args: any[]): ReactElement;
228
+
229
+ /**
230
+ * Finds the best-matching translation set for the given locale `code`.
231
+ */
232
+ export declare function i18n(code: string): Translation;
233
+
234
+ export declare interface IconProps {
235
+ type: "attach" | "chevronLeft" | "left" | "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";
236
+ className?: string;
237
+ themeCustom: any;
238
+ }
239
+
240
+ export { ImageBlock }
241
+
242
+ export declare interface ImageBlockProps extends ContentBlockProps {
243
+ block: ImageBlock;
244
+ downloadUrl?: string;
245
+ }
246
+
247
+ export { LocationBlock }
248
+
249
+ export declare interface LocationBlockProps extends ContentBlockProps {
250
+ block: LocationBlock;
251
+ }
252
+
253
+ export declare interface MessageActionMenuProps {
254
+ currentUser: UserSnapshot;
255
+ permissions: MessagePermissions;
256
+ conversation: ConversationSnapshot;
257
+ message: MessageSnapshot;
258
+ chatbox: Chatbox;
259
+ t: Translation;
260
+ themeCustom: any;
261
+ }
262
+
263
+ export declare function MessageContent(props: MessageContentProps): JSX.Element;
264
+
265
+ export declare interface MessageContentProps {
266
+ currentUser: UserSnapshot;
267
+ message: MessageSnapshot;
268
+ t: Translation;
269
+ themeCustom: any;
270
+ className?: string;
271
+ }
272
+
273
+ export declare interface MessageDividerProps {
274
+ isReadMarker: boolean;
275
+ isDayMarker: boolean;
276
+ timestamp?: number;
277
+ currentUser: UserSnapshot;
278
+ conversation: ConversationSnapshot;
279
+ app: AppMetadata;
280
+ t: Translation;
281
+ themeCustom: any;
282
+ }
283
+
284
+ export declare interface MessageFieldProps {
285
+ conversation: ConversationSnapshot;
286
+ participants: ParticipantSnapshot[];
287
+ referencedMessage: MessageSnapshot;
288
+ currentUser: UserSnapshot;
289
+ permissions: UserPermissions;
290
+ t: Translation;
291
+ chatbox: Chatbox;
292
+ editor?: EditorController;
293
+ themeCustom: any;
294
+ }
295
+
296
+ export declare interface MessageListFooterProps {
297
+ typing: TypingSnapshot;
298
+ conversation: ConversationSnapshot;
299
+ participants: ParticipantSnapshot[];
300
+ currentUser: UserSnapshot;
301
+ t: Translation;
302
+ chatbox: Chatbox;
303
+ themeCustom: any;
304
+ }
305
+
306
+ export declare interface MessagePermissions extends UserPermissions {
307
+ canDeleteMessage: boolean;
308
+ canReplyToMessage: boolean;
309
+ }
310
+
311
+ export declare interface MessageProps {
312
+ app: AppMetadata;
313
+ currentUser: UserSnapshot;
314
+ message: MessageSnapshot;
315
+ messageStatus: MessageStatus;
316
+ conversation: ConversationSnapshot;
317
+ participants: ParticipantSnapshot[];
318
+ permissions: MessagePermissions;
319
+ t: Translation;
320
+ chatbox: Chatbox;
321
+ messageActionMenuAnchorRef: React_2.RefObject<HTMLElement | undefined>;
322
+ themeCustom: any;
323
+ }
324
+
325
+ export { MessageSnapshot }
326
+
327
+ export declare type MessageStatus = "sending" | "sent" | "everyoneRead";
328
+
329
+ /**
330
+ * Sent by `onMissingBrowserPermission` when the user tried to do an action that
331
+ * require explicit browser permission, but that permission has been denied.
332
+ *
333
+ * @remarks
334
+ * This event is meant to let you show a message to the user if an action (eg
335
+ * sharing a location, or enabling notifications) can't proceed because the
336
+ * browser permission for that has been denied.
337
+ *
338
+ * If you want to control when to show the browser permissions prompt, use
339
+ * `beforeBrowserPermissionPrompt`.
340
+ *
341
+ * This event is emitted both when the user has denied this permission in the
342
+ * past, and when a user action just triggered a browser permissions prompt
343
+ * which the user then denied. If you need to differentiate between these two
344
+ * cases, use `beforeBrowserPermissionPrompt`, and inspect the return value of
345
+ * {@link BrowserPermissionRequest.showPrompt}.
346
+ *
347
+ * @public
348
+ */
349
+ export declare interface MissingBrowserPermissionEvent {
350
+ /**
351
+ * The type of permission that was denied.
352
+ *
353
+ * @remarks
354
+ * Note that more possible values may be added in the future, so make sure your
355
+ * handler can deal with unknown permission types gracefully.
356
+ */
357
+ type: BrowserPermission;
358
+ }
359
+
360
+ export declare interface SendMessageEvent {
361
+ currentUser: UserSnapshot;
362
+ message: MessageSnapshot;
363
+ conversation: ConversationSnapshot;
364
+ }
365
+
366
+ declare function Text_2({ block, className }: TextProps): ReactElement;
367
+ export { Text_2 as Text }
368
+
369
+ export { TextBlock }
370
+
371
+ export declare interface TextBlockProps extends ContentBlockProps {
372
+ block: TextBlock;
373
+ }
374
+
375
+ export declare interface TextProps {
376
+ block: TextBlock;
377
+ className?: string;
378
+ }
379
+
380
+ export declare interface Theme {
381
+ ChatHeader: React_2.ComponentType<ChatHeaderProps>;
382
+ Message: React_2.ComponentType<MessageProps>;
383
+ MessageField: React_2.ComponentType<MessageFieldProps>;
384
+ MessageActionMenu: React_2.ComponentType<MessageActionMenuProps>;
385
+ Icon: React_2.ComponentType<IconProps>;
386
+ MessageDivider: React_2.ComponentType<MessageDividerProps>;
387
+ MessageListFooter: React_2.ComponentType<MessageListFooterProps>;
388
+ TextBlock: React_2.ComponentType<TextBlockProps>;
389
+ FileBlock: React_2.ComponentType<FileBlockProps>;
390
+ LocationBlock: React_2.ComponentType<LocationBlockProps>;
391
+ ImageBlock: React_2.ComponentType<ImageBlockProps>;
392
+ AudioBlock: React_2.ComponentType<AudioBlockProps>;
393
+ VoiceBlock: React_2.ComponentType<VoiceBlockProps>;
394
+ VideoBlock: React_2.ComponentType<VideoBlockProps>;
395
+ }
396
+
397
+ export declare interface TimeAgo {
398
+ /**
399
+ * An amount of milliseconds after which the values in `long` and `short` _may_ have changed.
400
+ * If undefined, the values will not change within any meaningful period.
401
+ */
402
+ changeTimeout: number | undefined;
403
+ long: string;
404
+ short: string;
405
+ }
406
+
407
+ /**
408
+ *
409
+ * This timer triggers only when a human-readable timestamp needs to be updated.
410
+ * For example, you could use it to display that a messages was updated X
411
+ * minutes or Y hours ago.
412
+ *
413
+ * @public
414
+ */
415
+ export declare class TimeAgoTimer {
416
+ timestamp: number;
417
+ t: Translation;
418
+ constructor(timestamp: number, t: Translation);
419
+ onTick(callback: (timeAgo: TimeAgo) => void): () => void;
420
+ currentValue(): TimeAgo;
421
+ }
422
+
423
+ export declare type Translation = TranslationData & TranslationStrings;
424
+
425
+ declare interface TranslationData {
426
+ locale: string;
427
+ }
428
+
429
+ declare interface TranslationStrings {
430
+ YESTERDAY: string;
431
+ TODAY: string;
432
+ DAYS: string;
433
+ HOURS: string;
434
+ MINUTES: string;
435
+ JUST_NOW: string;
436
+ LOCATION: string;
437
+ CANCEL: string;
438
+ INBOX: string;
439
+ DESKTOP_NOTIFICATIONS: string;
440
+ DESKTOP_NOTIFICATIONS_ERROR: string;
441
+ DESKTOP_NOTIFICATIONS_DEMO_TITLE: (appName: string) => string;
442
+ DESKTOP_NOTIFICATIONS_DEMO_BODY: string;
443
+ SEND_BUTTON_TEXT: string;
444
+ ENTRYBOX_TEXT_LIMIT: string;
445
+ ENTRYBOX_PLACEHOLDER: string;
446
+ ENTRYBOX_PLACEHOLDER_CHAT_CLOSED: string;
447
+ ENTRYBOX_PLACEHOLDER_CHAT_READONLY: string;
448
+ MESSAGELIST_LOADING_OLDER: string;
449
+ MESSAGELIST_SHOW_OLDER: string;
450
+ MESSAGELIST_NEW_MARKER: string;
451
+ MESSAGE_SENT_VIA_EMAIL: string;
452
+ YOU_MARKER: string;
453
+ UPLOAD_IN_PROGRESS: string;
454
+ UPLOAD_SEND_FILE: string;
455
+ UPLOAD_SHARE_LOCATION: string;
456
+ UPLOAD_ERROR: string;
457
+ SHARE_LOCATION_ERROR: string;
458
+ LOADING: string;
459
+ HUB_EMPTY: string;
460
+ HUB_SHOW_EARLIER: string;
461
+ INBOX_NO_CHATS_TITLE: string;
462
+ INBOX_NO_CHATS_BODY: string;
463
+ ENABLE_TRANSLATION: string;
464
+ DISABLE_TRANSLATION: string;
465
+ SEARCH_PLACEHOLDER_TEXT: string;
466
+ SEARCH_SEARCHING: string;
467
+ SEARCH_NO_RESULTS: string;
468
+ SEARCH_NO_MORE_RESULTS: string;
469
+ CHAT_NOT_FOUND: string;
470
+ DELETE_MESSAGE: string;
471
+ DELETION_EXPLANATION: string;
472
+ EDIT_MESSAGE: string;
473
+ SAVE: string;
474
+ EDITED_INDICATOR: string;
475
+ REPLY_TO_MESSAGE: string;
476
+ REPLY_TO_ARIA_LABEL: (senderName: string, content: string) => string;
477
+ REPLY_MODE_LEAVE_ARIA_LABEL: string;
478
+ ADD_REACTION: string;
479
+ AUTH_EXPIRED_OVERLAY_TITLE: string;
480
+ AUTH_EXPIRED_OVERLAY_DESCRIPTION: string;
481
+ VOICE_MESSAGE: string;
482
+ LEAVE_CONVERSATION: string;
483
+ MARK_CONVERSATION_AS_UNREAD: string;
484
+ STATUS_INDICATOR_ONLINE: string;
485
+ STATUS_INDICATOR_OFFLINE: string;
486
+ CONTACT_INFORMATION_HIDDEN: string;
487
+ }
488
+
489
+ /**
490
+ * Formats a time in the past in a twitter-like fashion.
491
+ */
492
+ export declare function twitterAgo(now: number, ts: number, t: Translation): TimeAgo;
493
+
494
+ /**
495
+ * returns "Yesterday", "Last Monday", "Tuesday, March 31" or "Monday, March 31 2014", depending on which is most appropriate.
496
+ * @param ts number - unix timestamp (milliseconds)
497
+ */
498
+ export declare function userFriendlyDate(ts: number, t: Translation): string;
499
+
500
+ export declare interface UserPermissions {
501
+ showTypingIndicator: boolean;
502
+ canShareFile: boolean;
503
+ canShareLocation: boolean;
504
+ canMention: boolean;
505
+ showOnlineStatus: boolean;
506
+ canSendVoiceMessage: boolean;
507
+ canLeaveConversation: boolean;
508
+ canMarkConversationAsUnread: boolean;
509
+ }
510
+
511
+ export { UserSnapshot }
512
+
513
+ export { VideoBlock }
514
+
515
+ export declare interface VideoBlockProps extends ContentBlockProps {
516
+ block: VideoBlock;
517
+ downloadUrl?: string;
518
+ }
519
+
520
+ export { VoiceBlock }
521
+
522
+ export declare interface VoiceBlockProps extends ContentBlockProps {
523
+ block: VoiceBlock;
524
+ downloadUrl?: string;
525
+ }
526
+
527
+ export { }
528
+
529
+
530
+ declare global {
531
+ interface HTMLElementTagNameMap {
532
+ "t-chatbox": ChatboxHTMLElement;
533
+ }
534
+ }
535
+
536
+
537
+ declare global {
538
+ namespace JSX {
539
+ interface IntrinsicElements {
540
+ "t-chatbox": typeof Chatbox;
541
+ }
542
+ }
543
+ }
544
+