@tencent-rtc/mcp 1.0.7 → 1.0.9

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.
Files changed (48) hide show
  1. package/README.md +4 -4
  2. package/package.json +1 -1
  3. package/resource/doc/chatuikit/react/components/chat.md +44 -0
  4. package/resource/doc/chatuikit/react/components/chatheader.md +189 -0
  5. package/resource/doc/chatuikit/react/components/conversation-list.md +1017 -0
  6. package/resource/doc/chatuikit/react/components/message-input.md +950 -0
  7. package/resource/doc/chatuikit/react/components/message-list.md +485 -0
  8. package/resource/doc/chatuikit/react/components/tuikit.md +80 -0
  9. package/resource/doc/chatuikit/react/create-group.md +23 -0
  10. package/resource/doc/chatuikit/react/login.md +26 -0
  11. package/resource/doc/chatuikit/vue/components/avatar.md +137 -0
  12. package/resource/doc/chatuikit/vue/components/chat.md +42 -0
  13. package/resource/doc/chatuikit/vue/components/chatheader.md +189 -0
  14. package/resource/doc/chatuikit/vue/components/component-list.md +102 -0
  15. package/resource/doc/chatuikit/vue/components/conversation-list.md +765 -0
  16. package/resource/doc/chatuikit/vue/components/message-input.md +1272 -0
  17. package/resource/doc/chatuikit/vue/components/message-list.md +662 -0
  18. package/resource/doc/chatuikit/vue/components/tuikit.md +45 -0
  19. package/resource/doc/chatuikit/vue/components/userpicker.md +315 -0
  20. package/resource/doc/chatuikit/vue/create-group.md +25 -0
  21. package/resource/doc/chatuikit/vue/integration.md +256 -0
  22. package/resource/doc/chatuikit/vue/login.md +31 -0
  23. package/tools/call/get-native-call-integration.js +35 -0
  24. package/tools/call/get-native-call-integration.js.map +1 -0
  25. package/tools/call/get-web-call-integration.js +35 -0
  26. package/tools/call/get-web-call-integration.js.map +1 -0
  27. package/tools/chat/create-group.js +30 -0
  28. package/tools/chat/create-group.js.map +1 -0
  29. package/tools/chat/get-native-chat-integration.js +34 -0
  30. package/tools/chat/get-native-chat-integration.js.map +1 -0
  31. package/tools/chat/get-web-chat-component-detail.js +8 -5
  32. package/tools/chat/get-web-chat-component-detail.js.map +1 -1
  33. package/tools/chat/get-web-chat-integration.js +37 -0
  34. package/tools/chat/get-web-chat-integration.js.map +1 -0
  35. package/tools/chat/get-web-chat-uikit-login.js +30 -0
  36. package/tools/chat/get-web-chat-uikit-login.js.map +1 -0
  37. package/tools/common/present-framework-choice.js +9 -19
  38. package/tools/common/present-framework-choice.js.map +1 -1
  39. package/tools/common/record-prompt.js +3 -4
  40. package/tools/common/record-prompt.js.map +1 -1
  41. package/tools/common/record-result.js +7 -7
  42. package/tools/common/record-result.js.map +1 -1
  43. package/tools/index.js +12 -8
  44. package/tools/index.js.map +1 -1
  45. package/utils/handle-component-name.js +12 -0
  46. package/utils/handle-component-name.js.map +1 -0
  47. package/utils/handle-framework.js +9 -0
  48. package/utils/handle-framework.js.map +1 -0
@@ -0,0 +1,1272 @@
1
+ ## Overview
2
+
3
+
4
+ MessageInput is a complete message input component designed for Vue3 applications, providing core chat input features including text editing, emoji selection, file attachments, and a send button. It supports various custom options, such as input behavior configuration, toolbar customization, component replacement, and slot expansion, meeting the demands of different chat scenarios with personalized requirements.
5
+
6
+
7
+ ## Basic Usage
8
+
9
+
10
+ ```ts
11
+ <script>
12
+ import { MessageInput } from "@tencentcloud/chat-uikit-vue3";
13
+ </script>
14
+
15
+
16
+ <template>
17
+ <MessageInput />
18
+ </template>
19
+ ```
20
+
21
+
22
+ ## Props Configuration
23
+
24
+
25
+ | Field | Type | Default | Description |
26
+ |------|------|--------|------|
27
+ | autoFocus | boolean | true | Whether to auto-focus into the input box |
28
+ | disabled | boolean | false | Whether to disable the input component |
29
+ | hideSendButton | boolean | false | Whether to hide the send button |
30
+ | placeholder | string | '' | Placeholder text for the input box |
31
+ | attachmentPickerMode | 'collapsed' \| 'expanded' | 'collapsed' | Attachment selector display mode |
32
+ | actions | MessageInputActions | ['EmojiPicker', 'ImagePicker', 'FilePicker', 'VideoPicker'] | Toolbar action button configuration |
33
+
34
+
35
+
36
+
37
+ ## Slots configuration
38
+
39
+
40
+ | Field | Type | Default | Description |
41
+ |------|------|--------|------|
42
+ | headerToolbar | () => VNode[] | undefined | Header toolbar slot |
43
+ | footerToolbar | () => VNode[] | undefined | Footer toolbar slot |
44
+ | leftInline | () => VNode[] | undefined | Left inline slot |
45
+ | rightInline | () => VNode[] | undefined | Right inline slot |
46
+ | inputPrefix | () => VNode[] | undefined | Input box prefix slot |
47
+ | inputSuffix | () => VNode[] | undefined | Input box suffix slot |
48
+ | TextEditor | Component \| null | null | Custom text editor component configuration |
49
+
50
+
51
+
52
+
53
+ ### Type definition
54
+ ``` typescript
55
+ type BuiltInAction =
56
+ | 'EmojiPicker'
57
+ | 'ImagePicker'
58
+ | 'FilePicker'
59
+ | 'VideoPicker'
60
+ | 'AttachmentPicker';
61
+
62
+
63
+ export type CustomAction = {
64
+ key: string;
65
+ label?: string | undefined;
66
+ component?: Component | undefined;
67
+ className?: string | undefined;
68
+ style?: CSSProperties | undefined;
69
+ iconSize?: number | undefined;
70
+ };
71
+
72
+
73
+ export type MessageInputActions = Array<BuiltInAction | CustomAction>;
74
+
75
+
76
+ export type MessageInputAttachmentPickerMode = 'collapsed' | 'expanded';
77
+
78
+
79
+ export interface MessageInputSlots {
80
+ headerToolbar?: () => VNode[];
81
+ footerToolbar?: () => VNode[];
82
+ leftInline?: () => VNode[];
83
+ rightInline?: () => VNode[];
84
+ inputPrefix?: () => VNode[];
85
+ inputSuffix?: () => VNode[];
86
+ textEditor?: () => VNode[];
87
+ }
88
+
89
+
90
+ // MessageInputProps API definition
91
+ export interface MessageInputProps {
92
+ autoFocus?: boolean;
93
+ disabled?: boolean;
94
+ hideSendButton?: boolean;
95
+ placeholder?: string;
96
+ attachmentPickerMode?: MessageInputAttachmentPickerMode;
97
+ actions?: MessageInputActions;
98
+ slots?: MessageInputSlots;
99
+ TextEditor?: Component | null;
100
+ }
101
+ ```
102
+
103
+
104
+ ## Custom feature explanation
105
+
106
+
107
+ ### autoFocus
108
+ - `type`: `boolean`
109
+
110
+
111
+ - Details: autoFocus is used to set whether the component auto-focuses into the input box when mounting. The default is `true`.
112
+
113
+
114
+
115
+
116
+ ### disabled
117
+ - `type`: `boolean`
118
+
119
+
120
+ - Details: disabled is used to set whether to disable the entire input component, including text input and all buttons. The default is `false`.
121
+
122
+
123
+
124
+
125
+ ### hideSendButton
126
+ - `type`: `boolean`
127
+
128
+
129
+ - Details: hideSendButton is used to set whether to hide the send button, suitable for scenarios where the trigger mode needs to be customized. The default is `false`.
130
+
131
+
132
+
133
+
134
+ ### placeholder
135
+ - `type`: `string`.
136
+
137
+
138
+ - Details: placeholder is used to set the placeholder text for the input box. The default is an empty string.
139
+
140
+
141
+
142
+
143
+ ### attachmentPickerMode
144
+ - `type`: `'collapsed'` | `'expanded'`.
145
+
146
+
147
+ - Details: attachmentPickerMode is used to set the display mode of the attachment selector. Default is `'collapsed'`.
148
+
149
+
150
+ - **collapsed**: Collapse mode. Unfold options after clicking.
151
+
152
+
153
+ - **expanded**: Expand mode. Direct display of ALL options.
154
+
155
+
156
+
157
+
158
+ ### actions
159
+ - Type: MessageInputActions.
160
+
161
+
162
+ - Description: actions for configuration of buttons displayed in the toolbar. Default: `['EmojiPicker', 'ImagePicker', 'FilePicker', 'VideoPicker']`.
163
+
164
+
165
+
166
+
167
+ #### Example 1: Custom toolbar button sequence
168
+ ``` typescript
169
+ <template>
170
+ <MessageInput :actions="customActions" />
171
+ </template>
172
+
173
+
174
+ <script lang="ts" setup>
175
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
176
+
177
+
178
+ // Custom button sequence: file, image, video, emoji
179
+ const customActions = ['FilePicker', 'ImagePicker', 'VideoPicker', 'EmojiPicker'];
180
+ </script>
181
+ ```
182
+
183
+
184
+ #### Example 2: Add custom action button
185
+ ``` typescript
186
+ <template>
187
+ <MessageInput :actions="customActions" />
188
+ </template>
189
+
190
+
191
+ <script lang="ts" setup>
192
+ import { defineComponent, h } from 'vue';
193
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
194
+
195
+
196
+ Custom Position Sharing Button Component
197
+ const LocationPicker = defineComponent({
198
+ name: 'LocationPicker',
199
+ setup() {
200
+ const handleLocationShare = () => {
201
+ Get user location and send
202
+ if (navigator.geolocation) {
203
+ navigator.geolocation.getCurrentPosition((position) => {
204
+ const { latitude, longitude } = position.coords;
205
+ console.log(`Share location: ${latitude}, ${longitude}`);
206
+ alert(`Share location: ${latitude}, ${longitude}`); // For demonstration
207
+ });
208
+ } else {
209
+ alert('Browser not supported for geolocation.');
210
+ }
211
+ };
212
+
213
+
214
+ return () =>
215
+ h('button',
216
+ {
217
+ onClick: handleLocationShare,
218
+ style: { padding: '4px 8px', border: 'none', background: 'transparent' },
219
+ Share location
220
+ },
221
+ '📍',
222
+ );
223
+ },
224
+ });
225
+
226
+
227
+ const customActions = [
228
+ 'EmojiPicker',
229
+ 'ImagePicker',
230
+ {
231
+ key: 'location',
232
+ label: 'Location',
233
+ component: LocationPicker,
234
+ },
235
+ 'AttachmentPicker',
236
+ ];
237
+ </script>
238
+ ```
239
+
240
+
241
+ #### Example 3: Quick reply in customer service system
242
+ ``` typescript
243
+ <template>
244
+ <MessageInput :actions="actions" />
245
+ </template>
246
+
247
+
248
+ <script lang="ts" setup>
249
+ import { defineComponent, h, ref } from 'vue';
250
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
251
+ import { useMessageInputState } from '@tencentcloud/uikit-component-vue3/src/states/MessageInputState';
252
+
253
+
254
+ quick reply component
255
+ const QuickReplyPicker = defineComponent({
256
+ name: 'QuickReplyPicker',
257
+ setup() {
258
+ const { setContent } = useMessageInputState();
259
+ const showPicker = ref(false);
260
+
261
+
262
+ const quickReplies = [
263
+ Hello, glad to help you.
264
+ Please wait a moment, I'll check for you...
265
+ Thank you for your consultation. Also, any other issues?
266
+ The issue has been resolved. Have a pleasant life.
267
+ ];
268
+
269
+
270
+ const handleQuickReply = (text: string) => {
271
+ setContent(text);
272
+ showPicker.value = false;
273
+ };
274
+
275
+
276
+ return () =>
277
+ h('div', { style: { position: 'relative' } }, [
278
+ h('button',
279
+ {
280
+ title: 'Quick reply'
281
+ onClick: () => (showPicker.value = !showPicker.value),
282
+ },
283
+ '⚡',
284
+ ),
285
+ showPicker.value &&
286
+ h('div',
287
+ {
288
+ style: {
289
+ position: 'absolute',
290
+ bottom: '100%',
291
+ left: 0,
292
+ background: 'white',
293
+ border: '1px solid #ccc',
294
+ borderRadius: '4px',
295
+ padding: '8px',
296
+ minWidth: '200px',
297
+ zIndex: 100, // Ensure it's above other elements
298
+ },
299
+ },
300
+ quickReplies.map((reply, index) =>
301
+ h('div',
302
+ {
303
+ key: index,
304
+ onClick: () => handleQuickReply(reply),
305
+ style: {
306
+ padding: '4px 8px',
307
+ cursor: 'pointer',
308
+ borderRadius: '2px',
309
+ '&:hover': { backgroundColor: '#f0f0f0' },
310
+ },
311
+ },
312
+ reply,
313
+ ),
314
+ ),
315
+ ),
316
+ ]);
317
+ },
318
+ });
319
+
320
+
321
+ const actions = [
322
+ {
323
+ key: 'quickReply',
324
+ label: 'Quick reply'
325
+ component: QuickReplyPicker,
326
+ },
327
+ 'EmojiPicker',
328
+ 'FilePicker',
329
+ ];
330
+ </script>
331
+ ```
332
+
333
+
334
+
335
+
336
+ #### Example 4: Custom emoji panel
337
+ ``` typescript
338
+ <template>
339
+ <MessageInput :EmojiPicker="CustomEmojiPicker" />
340
+ </template>
341
+
342
+
343
+
344
+
345
+ <script lang="ts" setup>
346
+ import { defineComponent, h, ref } from 'vue';
347
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
348
+ import { useMessageInputState } from '@tencentcloud/uikit-component-vue3/src/states/MessageInputState';
349
+
350
+
351
+
352
+
353
+ const CustomEmojiPicker = defineComponent({
354
+ name: 'CustomEmojiPicker',
355
+ setup() {
356
+ const { insertContent } = useMessageInputState();
357
+ const showPicker = ref(false);
358
+ const activeCategory = ref('common');
359
+
360
+
361
+
362
+
363
+ const emojiCategories = {
364
+ 'common': ['😀', '😂', '🥰', '😍', '🤔', '😭', '😡', '👍'],
365
+ 'hand': ['👋', '🤝', '👏', '🙏', '✌️', '🤞', '🤟', '👌'],
366
+ 'animal': ['🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼'],
367
+ };
368
+
369
+
370
+
371
+
372
+ const insertEmoji = (emoji: string) => {
373
+ insertContent(emoji);
374
+ showPicker.value = false;
375
+ };
376
+
377
+
378
+
379
+
380
+ return () =>
381
+ h('div', { style: { position: 'relative' } }, [
382
+ h('button',
383
+ {
384
+ onClick: () => (showPicker.value = !showPicker.value),
385
+ style: { border: 'none', background: 'transparent', cursor: 'pointer' },
386
+ },
387
+ '😊',
388
+ ),
389
+ showPicker.value &&
390
+ h('div',
391
+ {
392
+ style: {
393
+ position: 'absolute',
394
+ bottom: '100%',
395
+ left: 0,
396
+ background: 'white',
397
+ border: '1px solid #ccc',
398
+ borderRadius: '8px',
399
+ padding: '12px',
400
+ width: '280px',
401
+ boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
402
+ zIndex: 100, // Ensure it's above other elements
403
+ },
404
+ },
405
+ [
406
+ category tag
407
+ h('div', { style: { display: 'flex', marginBottom: '8px' } },
408
+ Object.keys(emojiCategories).map((category) =>
409
+ h('button',
410
+ {
411
+ key: category,
412
+ onClick: () => (activeCategory.value = category),
413
+ style: {
414
+ padding: '4px 8px',
415
+ border: 'none',
416
+ background: activeCategory.value === category ? '#1890ff' : 'transparent',
417
+ color: activeCategory.value === category ? 'white' : '#666',
418
+ borderRadius: '4px',
419
+ cursor: 'pointer',
420
+ fontSize: '12px',
421
+ },
422
+ },
423
+ category,
424
+ ),
425
+ ),
426
+ ),
427
+ emoji grid
428
+ h('div',
429
+ {
430
+ style: {
431
+ display: 'grid',
432
+ gridTemplateColumns: 'repeat(8, 1fr)',
433
+ gap: '4px',
434
+ },
435
+ },
436
+ emojiCategories[activeCategory.value].map((emoji) =>
437
+ h('button',
438
+ {
439
+ key: emoji,
440
+ onClick: () => insertEmoji(emoji),
441
+ style: {
442
+ border: 'none',
443
+ background: 'transparent',
444
+ fontSize: '20px',
445
+ cursor: 'pointer',
446
+ padding: '4px',
447
+ borderRadius: '4px',
448
+ },
449
+ },
450
+ emoji,
451
+ ),
452
+ ),
453
+ ),
454
+ ],
455
+ ),
456
+ ]);
457
+ },
458
+ });
459
+ </script>
460
+ ```
461
+
462
+
463
+ ## Slots explanation
464
+ - Type: MessageInputSlots.
465
+
466
+
467
+ -Detailed instructions: Insert custom content at a specific location in the input component.
468
+
469
+
470
+ ``` typescript
471
+ interface MessageInputSlots {
472
+ headerToolbar?: () => VNode[];
473
+ footerToolbar?: () => VNode[];
474
+ leftInline?: () => VNode[];
475
+ rightInline?: () => VNode[];
476
+ inputPrefix?: () => VNode[];
477
+ inputSuffix?: () => VNode[];
478
+ textEditor?: () => VNode[];
479
+ }
480
+ ```
481
+
482
+
483
+
484
+
485
+ #### Example 1: Custom footerToolbar slot
486
+ ``` typescript
487
+ <template>
488
+ <MessageInput>
489
+ <template #footerToolbar>
490
+ <div style="padding: 4px 12px; font-size: 12px; color: #999; text-align: right;">
491
+ press Ctrl+Enter to wrap
492
+ </div>
493
+ </template>
494
+ </MessageInput>
495
+ </template>
496
+ ```
497
+
498
+
499
+
500
+
501
+ #### Example 2: Input box prefix/suffix feature
502
+ ``` typescript
503
+ <template>
504
+ <MessageInput>
505
+ <template #inputPrefix>
506
+
507
+ </template>
508
+ <template #inputSuffix>
509
+ <button
510
+ style="border: none; background: transparent; cursor: pointer;"
511
+ @click="handleVoiceInput"
512
+ >
513
+ 🎤
514
+ </button>
515
+ </template>
516
+ </MessageInput>
517
+ </template>
518
+
519
+
520
+ <script lang="ts" setup>
521
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
522
+
523
+
524
+ const handleAtUser = () => {
525
+ Trigger @user selection
526
+ console.log('Toggle on @user selection');
527
+ };
528
+
529
+
530
+ const handleVoiceInput = () => {
531
+ // Start voice input
532
+ console.log('Start voice input');
533
+ };
534
+ </script>
535
+ ```
536
+
537
+
538
+
539
+
540
+ ### TextEditor
541
+
542
+
543
+ Type: 'Component' | 'null'.
544
+
545
+
546
+ Detailed explanation: TextEditor is used to replace the default text editor component. Default: `null`.
547
+
548
+
549
+ #### Example: Custom text editor
550
+ ``` typescript
551
+ <template>
552
+ <MessageInput>
553
+ <template #textEditor>
554
+ <RichTextEditor />
555
+ </template>
556
+ </MessageInput>
557
+ </template>
558
+
559
+
560
+
561
+
562
+ <script lang="ts" setup>
563
+ import { defineComponent, h, ref, onMounted } from 'vue';
564
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
565
+ import { useMessageInputState } from '@tencentcloud/uikit-component-vue3/src/states/MessageInputState';
566
+
567
+
568
+
569
+
570
+ const RichTextEditor = defineComponent({
571
+ name: 'RichTextEditor',
572
+ setup() {
573
+ const { sendMessage } = useMessageInputState();
574
+ const editorRef = ref<HTMLDivElement | null>(null);
575
+ const inputRawValue = ref('');
576
+
577
+
578
+ const handleInput = (e: Event) => {
579
+ const target = e.target as HTMLDivElement;
580
+ inputRawValue.value = (e.target as HTMLDivElement).textContent || '';
581
+ };
582
+
583
+
584
+
585
+
586
+ const handleKeyDown = (e: KeyboardEvent) => {
587
+ if (e.key === 'Enter') {
588
+ sendMessage(inputRawValue.value);
589
+ if (editorRef.value) {
590
+ editorRef.value.textContent = '';
591
+ }
592
+ }
593
+ };
594
+
595
+
596
+
597
+
598
+ onMounted(() => {
599
+ if (editorRef.value) {
600
+ editorRef.value.textContent = inputRawValue.value || '';
601
+ }
602
+ });
603
+
604
+
605
+ return () =>
606
+ h('div',
607
+ {
608
+ style: {
609
+ flex: 1,
610
+ border: '1px solid #d9d9d9',
611
+ borderRadius: '6px',
612
+ padding: '8px 12px',
613
+ minHeight: '32px',
614
+ maxHeight: '120px',
615
+ overflow: 'auto',
616
+ },
617
+ },
618
+ h('div',
619
+ {
620
+ ref: editorRef,
621
+ contentEditable: true,
622
+ style: {
623
+ outline: 'none',
624
+ minHeight: '20px',
625
+ lineHeight: '20px',
626
+ },
627
+ onInput: handleInput,
628
+ onKeydown: handleKeyDown,
629
+ },
630
+ ),
631
+ );
632
+ },
633
+ });
634
+ </script>
635
+ ```
636
+ Overview
637
+
638
+
639
+ MessageInput is a complete message input component designed for Vue3 applications, providing core chat input features including text editing, emoji selection, file attachments, and a send button. It supports various custom options, such as input behavior configuration, toolbar customization, component replacement, and slot expansion, meeting the demands of different chat scenarios with personalized requirements.
640
+
641
+
642
+ Basic Usage
643
+
644
+
645
+ ```ts
646
+ <script>
647
+ import { MessageInput } from "@tencentcloud/chat-uikit-vue3";
648
+ </script>
649
+
650
+
651
+ <template>
652
+ <MessageInput />
653
+ </template>
654
+ ```
655
+
656
+
657
+ ## Props Configuration
658
+
659
+
660
+ | Field | Type | Default | Description |
661
+ |------|------|--------|------|
662
+ | autoFocus | boolean | true | Whether to auto-focus into the input box |
663
+ | disabled | boolean | false | Whether to disable the input component |
664
+ | hideSendButton | boolean | false | Whether to hide the send button |
665
+ | placeholder | string | '' | Placeholder text for the input box |
666
+ | attachmentPickerMode | 'collapsed' \| 'expanded' | 'collapsed' | Attachment selector display mode |
667
+ | actions | MessageInputActions | ['EmojiPicker', 'ImagePicker', 'FilePicker', 'VideoPicker'] | Toolbar action button configuration |
668
+
669
+
670
+
671
+
672
+ ## Slots configuration
673
+
674
+
675
+ | Field | Type | Default | Description |
676
+ |------|------|--------|------|
677
+ | headerToolbar | () => VNode[] | undefined | Header toolbar slot |
678
+ | footerToolbar | () => VNode[] | undefined | Footer toolbar slot |
679
+ | leftInline | () => VNode[] | undefined | Left inline slot |
680
+ | rightInline | () => VNode[] | undefined | Right inline slot |
681
+ | inputPrefix | () => VNode[] | undefined | Input box prefix slot |
682
+ | inputSuffix | () => VNode[] | undefined | Input box suffix slot |
683
+ | TextEditor | Component \| null | null | Custom text editor component configuration |
684
+
685
+
686
+
687
+
688
+ type definition
689
+ ``` typescript
690
+ type BuiltInAction =
691
+ | 'EmojiPicker'
692
+ | 'ImagePicker'
693
+ | 'FilePicker'
694
+ | 'VideoPicker'
695
+ | 'AttachmentPicker';
696
+
697
+
698
+ export type CustomAction = {
699
+ key: string;
700
+ label?: string | undefined;
701
+ component?: Component | undefined;
702
+ className?: string | undefined;
703
+ style?: CSSProperties | undefined;
704
+ iconSize?: number | undefined;
705
+ };
706
+
707
+
708
+ export type MessageInputActions = Array<BuiltInAction | CustomAction>;
709
+
710
+
711
+ export type MessageInputAttachmentPickerMode = 'collapsed' | 'expanded';
712
+
713
+
714
+ export interface MessageInputSlots {
715
+ headerToolbar?: () => VNode[];
716
+ footerToolbar?: () => VNode[];
717
+ leftInline?: () => VNode[];
718
+ rightInline?: () => VNode[];
719
+ inputPrefix?: () => VNode[];
720
+ inputSuffix?: () => VNode[];
721
+ textEditor?: () => VNode[];
722
+ }
723
+
724
+
725
+ // MessageInputProps API definition
726
+ export interface MessageInputProps {
727
+ autoFocus?: boolean;
728
+ disabled?: boolean;
729
+ hideSendButton?: boolean;
730
+ placeholder?: string;
731
+ attachmentPickerMode?: MessageInputAttachmentPickerMode;
732
+ actions?: MessageInputActions;
733
+ slots?: MessageInputSlots;
734
+ TextEditor?: Component | null;
735
+ }
736
+ ```
737
+
738
+
739
+ Custom Function Explanation
740
+
741
+
742
+ ### autoFocus
743
+ -boolean
744
+
745
+
746
+ - Details: autoFocus is used to set whether to auto-focus into the input box when mounting. Default: `true`.
747
+
748
+
749
+
750
+
751
+ ### disabled
752
+ -boolean
753
+
754
+
755
+ - Details: disabled is used to set whether to disable the entire input component, including text input and ALL buttons. Default: `false`.
756
+
757
+
758
+
759
+
760
+ ### hideSendButton
761
+ -boolean
762
+
763
+
764
+ - Details: hideSendButton is used to set whether to hide the send button, suitable for scenarios where the trigger mode needs to be customized. Default: `false`.
765
+
766
+
767
+
768
+
769
+ ### placeholder
770
+ - Type: string.
771
+
772
+
773
+ - Details: placeholder is used to set the placeholder text for the input box. Default is an empty string.
774
+
775
+
776
+
777
+
778
+ ### attachmentPickerMode
779
+ - Type: 'collapsed' | 'expanded'.
780
+
781
+
782
+ - Details: attachmentPickerMode is used to set the display mode of the attachment selector. Default is `'collapsed'`.
783
+
784
+
785
+ - **collapsed**: Collapse mode. Unfold options after clicking.
786
+
787
+
788
+ - **expanded**: Expand mode. Direct display of ALL options.
789
+
790
+
791
+
792
+
793
+ ### actions
794
+ - Type: MessageInputActions.
795
+
796
+
797
+ - Description: actions for configuration of buttons displayed in the toolbar. Default: `['EmojiPicker', 'ImagePicker', 'FilePicker', 'VideoPicker']`.
798
+
799
+
800
+
801
+
802
+ #### Example 1: Custom toolbar button sequence
803
+ ``` typescript
804
+ <template>
805
+ <MessageInput :actions="customActions" />
806
+ </template>
807
+
808
+
809
+ <script lang="ts" setup>
810
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
811
+
812
+
813
+ Custom button sequence: file, image, video, emoji
814
+ const customActions = ['FilePicker', 'ImagePicker', 'VideoPicker', 'EmojiPicker'];
815
+ </script>
816
+ ```
817
+
818
+
819
+ #### Example 2: Add custom action button
820
+ ``` typescript
821
+ <template>
822
+ <MessageInput :actions="customActions" />
823
+ </template>
824
+
825
+
826
+ <script lang="ts" setup>
827
+ import { defineComponent, h } from 'vue';
828
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
829
+
830
+
831
+ Custom Position Sharing Button Component
832
+ const LocationPicker = defineComponent({
833
+ name: 'LocationPicker',
834
+ setup() {
835
+ const handleLocationShare = () => {
836
+ Get user location and send
837
+ if (navigator.geolocation) {
838
+ navigator.geolocation.getCurrentPosition((position) => {
839
+ const { latitude, longitude } = position.coords;
840
+ console.log(`Share location: ${latitude}, ${longitude}`);
841
+ alert(`Share location: ${latitude}, ${longitude}`); // For demonstration
842
+ });
843
+ } else {
844
+ alert('Browser not supported for geolocation.');
845
+ }
846
+ };
847
+
848
+
849
+ return () =>
850
+ h('button',
851
+ {
852
+ onClick: handleLocationShare,
853
+ style: { padding: '4px 8px', border: 'none', background: 'transparent' },
854
+ Share location
855
+ },
856
+ '📍',
857
+ );
858
+ },
859
+ });
860
+
861
+
862
+ const customActions = [
863
+ 'EmojiPicker',
864
+ 'ImagePicker',
865
+ {
866
+ key: 'location',
867
+ label: 'Location',
868
+ component: LocationPicker,
869
+ },
870
+ 'AttachmentPicker',
871
+ ];
872
+ </script>
873
+ ```
874
+
875
+
876
+ #### Example 3: Quick reply in customer service system
877
+ ``` typescript
878
+ <template>
879
+ <MessageInput :actions="actions" />
880
+ </template>
881
+
882
+
883
+ <script lang="ts" setup>
884
+ import { defineComponent, h, ref } from 'vue';
885
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
886
+ import { useMessageInputState } from '@tencentcloud/uikit-component-vue3/src/states/MessageInputState';
887
+
888
+
889
+ quick reply component
890
+ const QuickReplyPicker = defineComponent({
891
+ name: 'QuickReplyPicker',
892
+ setup() {
893
+ const { setContent } = useMessageInputState();
894
+ const showPicker = ref(false);
895
+
896
+
897
+ const quickReplies = [
898
+ Hello, glad to help you.
899
+ Please wait a moment, I'll check for you...
900
+ Thank you for your consultation. Also, any other issues?
901
+ The issue has been resolved. Have a pleasant life.
902
+ ];
903
+
904
+
905
+ const handleQuickReply = (text: string) => {
906
+ setContent(text);
907
+ showPicker.value = false;
908
+ };
909
+
910
+
911
+ return () =>
912
+ h('div', { style: { position: 'relative' } }, [
913
+ h('button',
914
+ {
915
+ title: 'Quick reply',
916
+ onClick: () => (showPicker.value = !showPicker.value),
917
+ },
918
+ '⚡',
919
+ ),
920
+ showPicker.value &&
921
+ h('div',
922
+ {
923
+ style: {
924
+ position: 'absolute',
925
+ bottom: '100%',
926
+ left: 0,
927
+ background: 'white',
928
+ border: '1px solid #ccc',
929
+ borderRadius: '4px',
930
+ padding: '8px',
931
+ minWidth: '200px',
932
+ zIndex: 100, // Ensure it's above other elements
933
+ },
934
+ },
935
+ quickReplies.map((reply, index) =>
936
+ h('div',
937
+ {
938
+ key: index,
939
+ onClick: () => handleQuickReply(reply),
940
+ style: {
941
+ padding: '4px 8px',
942
+ cursor: 'pointer',
943
+ borderRadius: '2px',
944
+ '&:hover': { backgroundColor: '#f0f0f0' },
945
+ },
946
+ },
947
+ reply,
948
+ ),
949
+ ),
950
+ ),
951
+ ]);
952
+ },
953
+ });
954
+
955
+
956
+ const actions = [
957
+ {
958
+ key: 'quickReply',
959
+ label: 'Quick reply',
960
+ component: QuickReplyPicker,
961
+ },
962
+ 'EmojiPicker',
963
+ 'FilePicker',
964
+ ];
965
+ </script>
966
+ ```
967
+
968
+
969
+
970
+
971
+ #### Example 4: Custom emoji panel
972
+ ``` typescript
973
+ <template>
974
+ <MessageInput :EmojiPicker="CustomEmojiPicker" />
975
+ </template>
976
+
977
+
978
+
979
+
980
+ <script lang="ts" setup>
981
+ import { defineComponent, h, ref } from 'vue';
982
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
983
+ import { useMessageInputState } from '@tencentcloud/uikit-component-vue3/src/states/MessageInputState';
984
+
985
+
986
+
987
+
988
+ const CustomEmojiPicker = defineComponent({
989
+ name: 'CustomEmojiPicker',
990
+ setup() {
991
+ const { insertContent } = useMessageInputState();
992
+ const showPicker = ref(false);
993
+ const activeCategory = ref('common');
994
+
995
+
996
+
997
+
998
+ const emojiCategories = {
999
+ 'common': ['😀', '😂', '🥰', '😍', '🤔', '😭', '😡', '👍'],
1000
+ 'hand': ['👋', '🤝', '👏', '🙏', '✌️', '🤞', '🤟', '👌'],
1001
+ 'animal': ['🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼'],
1002
+ };
1003
+
1004
+
1005
+
1006
+
1007
+ const insertEmoji = (emoji: string) => {
1008
+ insertContent(emoji);
1009
+ showPicker.value = false;
1010
+ };
1011
+
1012
+
1013
+
1014
+
1015
+ return () =>
1016
+ h('div', { style: { position: 'relative' } }, [
1017
+ h('button',
1018
+ {
1019
+ onClick: () => (showPicker.value = !showPicker.value),
1020
+ style: { border: 'none', background: 'transparent', cursor: 'pointer' },
1021
+ },
1022
+ '😊',
1023
+ ),
1024
+ showPicker.value &&
1025
+ h('div',
1026
+ {
1027
+ style: {
1028
+ position: 'absolute',
1029
+ bottom: '100%',
1030
+ left: 0,
1031
+ background: 'white',
1032
+ border: '1px solid #ccc',
1033
+ borderRadius: '8px',
1034
+ padding: '12px',
1035
+ width: '280px',
1036
+ boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
1037
+ zIndex: 100, // Ensure it's above other elements
1038
+ },
1039
+ },
1040
+ [
1041
+ category tag
1042
+ h('div', { style: { display: 'flex', marginBottom: '8px' } },
1043
+ Object.keys(emojiCategories).map((category) =>
1044
+ h('button',
1045
+ {
1046
+ key: category,
1047
+ onClick: () => (activeCategory.value = category),
1048
+ style: {
1049
+ padding: '4px 8px',
1050
+ border: 'none',
1051
+ background: activeCategory.value === category ? '#1890ff' : 'transparent',
1052
+ color: activeCategory.value === category ? 'white' : '#666',
1053
+ borderRadius: '4px',
1054
+ cursor: 'pointer',
1055
+ fontSize: '12px',
1056
+ },
1057
+ },
1058
+ category,
1059
+ ),
1060
+ ),
1061
+ ),
1062
+ emoji grid
1063
+ h('div',
1064
+ {
1065
+ style: {
1066
+ display: 'grid',
1067
+ gridTemplateColumns: 'repeat(8, 1fr)',
1068
+ gap: '4px',
1069
+ },
1070
+ },
1071
+ emojiCategories[activeCategory.value].map((emoji) =>
1072
+ h('button',
1073
+ {
1074
+ key: emoji,
1075
+ onClick: () => insertEmoji(emoji),
1076
+ style: {
1077
+ border: 'none',
1078
+ background: 'transparent',
1079
+ fontSize: '20px',
1080
+ cursor: 'pointer',
1081
+ padding: '4px',
1082
+ borderRadius: '4px',
1083
+ },
1084
+ },
1085
+ emoji,
1086
+ ),
1087
+ ),
1088
+ ),
1089
+ ],
1090
+ ),
1091
+ ]);
1092
+ },
1093
+ });
1094
+ </script>
1095
+ ```
1096
+
1097
+
1098
+ ## Slots explanation
1099
+ - Type: MessageInputSlots.
1100
+
1101
+
1102
+ -Detailed instructions: Insert custom content at a specific location in the input component.
1103
+
1104
+
1105
+ ``` typescript
1106
+ interface MessageInputSlots {
1107
+ headerToolbar?: () => VNode[];
1108
+ footerToolbar?: () => VNode[];
1109
+ leftInline?: () => VNode[];
1110
+ rightInline?: () => VNode[];
1111
+ inputPrefix?: () => VNode[];
1112
+ inputSuffix?: () => VNode[];
1113
+ textEditor?: () => VNode[];
1114
+ }
1115
+ ```
1116
+
1117
+
1118
+
1119
+
1120
+ #### Example 1: Custom footerToolbar slot
1121
+ ``` typescript
1122
+ <template>
1123
+ <MessageInput>
1124
+ <template #footerToolbar>
1125
+ <div style="padding: 4px 12px; font-size: 12px; color: #999; text-align: right;">
1126
+ press Ctrl+Enter to wrap
1127
+ </div>
1128
+ </template>
1129
+ </MessageInput>
1130
+ </template>
1131
+ ```
1132
+
1133
+
1134
+
1135
+
1136
+ #### Example 2: Input box prefix/suffix feature
1137
+ ``` typescript
1138
+ <template>
1139
+ <MessageInput>
1140
+ <template #inputPrefix>
1141
+
1142
+ </template>
1143
+ <template #inputSuffix>
1144
+ <button
1145
+ style="border: none; background: transparent; cursor: pointer;"
1146
+ @click="handleVoiceInput"
1147
+ >
1148
+ 🎤
1149
+ </button>
1150
+ </template>
1151
+ </MessageInput>
1152
+ </template>
1153
+
1154
+
1155
+ <script lang="ts" setup>
1156
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
1157
+
1158
+
1159
+ const handleAtUser = () => {
1160
+ Trigger @user selection
1161
+ console.log('Toggle on @user selection');
1162
+ };
1163
+
1164
+
1165
+ const handleVoiceInput = () => {
1166
+ // Start voice input
1167
+ console.log('Start voice input');
1168
+ };
1169
+ </script>
1170
+ ```
1171
+
1172
+
1173
+
1174
+
1175
+ ### TextEditor
1176
+
1177
+
1178
+ Type: 'Component' | 'null'.
1179
+
1180
+
1181
+ Detailed explanation: TextEditor is used to replace the default text editor component. Default: `null`.
1182
+
1183
+
1184
+ #### Example: Custom text editor
1185
+ ``` typescript
1186
+ <template>
1187
+ <MessageInput>
1188
+ <template #textEditor>
1189
+ <RichTextEditor />
1190
+ </template>
1191
+ </MessageInput>
1192
+ </template>
1193
+
1194
+
1195
+
1196
+
1197
+ <script lang="ts" setup>
1198
+ import { defineComponent, h, ref, onMounted } from 'vue';
1199
+ import { MessageInput } from '@tencentcloud/uikit-component-vue3';
1200
+ import { useMessageInputState } from '@tencentcloud/uikit-component-vue3/src/states/MessageInputState';
1201
+
1202
+
1203
+
1204
+
1205
+ const RichTextEditor = defineComponent({
1206
+ name: 'RichTextEditor',
1207
+ setup() {
1208
+ const { sendMessage } = useMessageInputState();
1209
+ const editorRef = ref<HTMLDivElement | null>(null);
1210
+ const inputRawValue = ref('');
1211
+
1212
+
1213
+ const handleInput = (e: Event) => {
1214
+ const target = e.target as HTMLDivElement;
1215
+ inputRawValue.value = (e.target as HTMLDivElement).textContent || '';
1216
+ };
1217
+
1218
+
1219
+
1220
+
1221
+ const handleKeyDown = (e: KeyboardEvent) => {
1222
+ if (e.key === 'Enter') {
1223
+ sendMessage(inputRawValue.value);
1224
+ if (editorRef.value) {
1225
+ editorRef.value.textContent = '';
1226
+ }
1227
+ }
1228
+ };
1229
+
1230
+
1231
+
1232
+
1233
+ onMounted(() => {
1234
+ if (editorRef.value) {
1235
+ editorRef.value.textContent = inputRawValue.value || '';
1236
+ }
1237
+ });
1238
+
1239
+
1240
+ return () =>
1241
+ h('div',
1242
+ {
1243
+ style: {
1244
+ flex: 1,
1245
+ border: '1px solid #d9d9d9',
1246
+ borderRadius: '6px',
1247
+ padding: '8px 12px',
1248
+ minHeight: '32px',
1249
+ maxHeight: '120px',
1250
+ overflow: 'auto',
1251
+ },
1252
+ },
1253
+ h('div',
1254
+ {
1255
+ ref: editorRef,
1256
+ contentEditable: true,
1257
+ style: {
1258
+ outline: 'none',
1259
+ minHeight: '20px',
1260
+ lineHeight: '20px',
1261
+ },
1262
+ onInput: handleInput,
1263
+ onKeydown: handleKeyDown,
1264
+ },
1265
+ ),
1266
+ );
1267
+ },
1268
+ });
1269
+ </script>
1270
+ ```
1271
+
1272
+