@tencent-rtc/mcp 1.3.3 → 1.3.5

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 (105) hide show
  1. package/package.json +1 -1
  2. package/resource/doc/chatuikit/android/features/theme.md +363 -0
  3. package/resource/doc/chatuikit/{android/client_api_Android.md → faq/android_sdk/client-api.md} +0 -2
  4. package/resource/doc/chatuikit/faq/common/product.md +8 -0
  5. package/resource/doc/chatuikit/faq/flutter_sdk/faq.md +53 -0
  6. package/resource/doc/chatuikit/{iOS/client_api_iOS.md → faq/ios_sdk/client-api.md} +0 -2
  7. package/resource/doc/chatuikit/flutter/features/theme.md +379 -0
  8. package/resource/doc/chatuikit/flutter/integration.md +413 -0
  9. package/resource/doc/chatuikit/flutter/workflow.md +941 -0
  10. package/resource/doc/chatuikit/iOS/features/theme.md +416 -0
  11. package/resource/doc/chatuikit/iOS/workflow.md +0 -0
  12. package/resource/doc/chatuikit/react/components/chat-setting.md +86 -0
  13. package/resource/doc/chatuikit/react/components/contact-list.md +1093 -0
  14. package/resource/doc/chatuikit/react/components/search.md +745 -0
  15. package/resource/doc/chatuikit/vue/components/chat-setting.md +64 -0
  16. package/resource/doc/chatuikit/vue/components/contact-list.md +679 -0
  17. package/resource/doc/chatuikit/vue/components/search.md +1384 -0
  18. package/resource/doc/livekit/live/android/workflow.md +137 -6
  19. package/resource/doc/livekit/live/ios/live-audience-list.md +339 -0
  20. package/resource/doc/livekit/live/ios/live-audio-effect.md +370 -0
  21. package/resource/doc/livekit/live/ios/live-barrage.md +517 -0
  22. package/resource/doc/livekit/live/ios/live-base-beauty.md +247 -0
  23. package/resource/doc/livekit/live/ios/live-co-guest-interaction.md +518 -0
  24. package/resource/doc/livekit/live/ios/live-gift.md +783 -0
  25. package/resource/doc/livekit/live/ios/live-host-interaction.md +815 -0
  26. package/resource/doc/livekit/live/ios/live-integration.md +931 -0
  27. package/resource/doc/livekit/live/ios/live-live-list.md +485 -0
  28. package/resource/doc/livekit/live/ios/workflow.md +454 -0
  29. package/resource/doc/rtcengine/web/plugin/20-advanced-customized-capture-rendering.md +87 -0
  30. package/resource/doc/rtcengine/web/plugin/21-advanced-auto-play-policy.md +87 -0
  31. package/resource/doc/rtcengine/web/plugin/22-advanced-audio-mixer.md +175 -0
  32. package/resource/doc/rtcengine/web/plugin/23-advanced-support-detection.md +221 -0
  33. package/resource/doc/rtcengine/web/plugin/24-advanced-network-quality.md +140 -0
  34. package/resource/doc/rtcengine/web/plugin/25-advanced-device-change.md +99 -0
  35. package/resource/doc/rtcengine/web/plugin/26-advanced-publish-cdn-stream.md +451 -0
  36. package/resource/doc/rtcengine/web/plugin/27-advanced-small-stream.md +151 -0
  37. package/resource/doc/rtcengine/web/plugin/28-advanced-beauty.md +322 -0
  38. package/resource/doc/rtcengine/web/plugin/29-advanced-water-mark.md +149 -0
  39. package/resource/doc/rtcengine/web/plugin/30-advanced-cross-room-link.md +96 -0
  40. package/resource/doc/rtcengine/web/plugin/31-advanced-plugins-overview.md +330 -0
  41. package/resource/doc/rtcengine/web/plugin/34-advanced-proxy.md +248 -0
  42. package/resource/doc/rtcengine/web/plugin/35-advanced-ai-denoiser.md +81 -0
  43. package/resource/doc/rtcengine/web/plugin/36-advanced-virtual-background.md +242 -0
  44. package/resource/doc/rtcengine/web/plugin/37-advanced-voice-changer.md +99 -0
  45. package/resource/doc/rtcengine/web/plugin/39-advanced-video-decoder.md +33 -0
  46. package/resource/doc/rtcengine/web/plugin/40-advanced-video-mixer.md +379 -0
  47. package/resource/doc/rtcengine/web/plugin/41-advanced-small-stream-auto-switcher.md +91 -0
  48. package/resource/doc/rtcengine/web/plugin/42-advanced-realtime-transcriber.md +315 -0
  49. package/resource/doc/rtcengine/web/plugin/43-advanced-face-detection.md +180 -0
  50. package/tools/chat/get-native-chat-feature-detail.js +30 -0
  51. package/tools/chat/get-native-chat-feature-detail.js.map +1 -0
  52. package/tools/chat/get-native-chat-integration.js +30 -12
  53. package/tools/chat/get-native-chat-integration.js.map +1 -1
  54. package/tools/common/get-faq.js +2 -4
  55. package/tools/common/get-faq.js.map +1 -1
  56. package/tools/definitions/get_native_chat_feature_detail_def.js +32 -0
  57. package/tools/definitions/get_native_chat_feature_detail_def.js.map +1 -0
  58. package/tools/definitions/get_native_chat_uikit_integration_def.js +19 -7
  59. package/tools/definitions/get_native_chat_uikit_integration_def.js.map +1 -1
  60. package/tools/definitions/{get_native_live_extra_features_def.js → get_native_live_uikit_extra_features_def.js} +3 -3
  61. package/tools/definitions/get_native_live_uikit_extra_features_def.js.map +1 -0
  62. package/tools/definitions/{get_native_live_interaction_def.js → get_native_live_uikit_interaction_def.js} +3 -3
  63. package/tools/definitions/get_native_live_uikit_interaction_def.js.map +1 -0
  64. package/tools/definitions/get_web_chat_uikit_component_detail_def.js +49 -10
  65. package/tools/definitions/get_web_chat_uikit_component_detail_def.js.map +1 -1
  66. package/tools/definitions/record_prompt_def.js +42 -11
  67. package/tools/definitions/record_prompt_def.js.map +1 -1
  68. package/tools/definitions/record_result_def.js +1 -1
  69. package/tools/index.js +6 -4
  70. package/tools/index.js.map +1 -1
  71. package/tools/live/{get_native_live_extra_features.js → get_native_live_uikit_extra_features.js} +4 -4
  72. package/tools/live/get_native_live_uikit_extra_features.js.map +1 -0
  73. package/tools/live/{get_native_live_interaction.js → get_native_live_uikit_interaction.js} +4 -4
  74. package/tools/live/get_native_live_uikit_interaction.js.map +1 -0
  75. package/tools/rtcengine/get-rtcengine-web-sdk-integration.js.map +1 -1
  76. package/tools/rtcengine/get-trtc-sdk-faq.js +32 -0
  77. package/tools/rtcengine/get-trtc-sdk-faq.js.map +1 -0
  78. package/tools/rtcengine/get-trtc-web-sdk-faq.js +1 -1
  79. package/tools/rtcengine/get-trtc-web-sdk-integration.js.map +1 -1
  80. package/tools/rtcengine/get-trtc-web-sdk-plugin.js +45 -0
  81. package/tools/rtcengine/get-trtc-web-sdk-plugin.js.map +1 -0
  82. package/utils/handle-component-name.js +0 -16
  83. package/utils/handle-component-name.js.map +1 -1
  84. package/utils/report-cls-client.js +1 -1
  85. package/utils/report-es-client.js +1 -1
  86. package/resource/doc/chatuikit/android/generate_UserSig.md +0 -306
  87. package/resource/doc/chatuikit/android/integrarte_only_tuichat_Android.md +0 -290
  88. package/resource/doc/chatuikit/android/quick_start_Android.md +0 -138
  89. package/resource/doc/chatuikit/android/show_typing_Android.md +0 -43
  90. package/resource/doc/chatuikit/flutter/generate_UserSig.md +0 -306
  91. package/resource/doc/chatuikit/flutter/integrate_tuikit_Flutter.md +0 -133
  92. package/resource/doc/chatuikit/iOS/generate_UserSig.md +0 -306
  93. package/resource/doc/chatuikit/iOS/integrate_only_tuichat_iOS.md +0 -748
  94. package/resource/doc/chatuikit/iOS/quick_start_iOS.md +0 -163
  95. package/resource/doc/chatuikit/iOS/show_typing_iOS.md +0 -52
  96. package/tools/definitions/get_native_live_extra_features_def.js.map +0 -1
  97. package/tools/definitions/get_native_live_interaction_def.js.map +0 -1
  98. package/tools/live/get_native_live_extra_features.js.map +0 -1
  99. package/tools/live/get_native_live_interaction.js.map +0 -1
  100. /package/resource/doc/chatuikit/android/{integrate_tuikit_Android.md → integration.md} +0 -0
  101. /package/resource/doc/chatuikit/{faq/native_sdk/faq.md → android/workflow.md} +0 -0
  102. /package/resource/doc/chatuikit/{flutter/client_api_Flutter.md → faq/flutter_sdk/client-api.md} +0 -0
  103. /package/resource/doc/chatuikit/iOS/{integrate_tuikit_iOS.md → integration.md} +0 -0
  104. /package/resource/doc/chatuikit/react/components/{chatheader.md → chat-header.md} +0 -0
  105. /package/resource/doc/chatuikit/vue/components/{chatheader.md → chat-header.md} +0 -0
@@ -0,0 +1,1384 @@
1
+ ## Overview
2
+
3
+ Search is a complete search solution that includes a comprehensive component set for search box, search results display, advanced search, and more. It's suitable for user, group, and message search scenarios in instant messaging, online meetings, online education, and more.
4
+
5
+ > **Note:**
6
+ >
7
+
8
+ > This feature is a value-added service that requires you to purchase the Cloud Search Plugin. Please click [Purchase](https://console.trtc.io/chat/plugin/TUICloudSearch).
9
+ >
10
+
11
+
12
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027116646/a31b2bd2870911f0bd05525400454e06.png)
13
+
14
+
15
+ ## Search Modes
16
+ <table>
17
+ <tr>
18
+ <td rowspan="1" colSpan="1" >**Mini Mode (MINI)**</td>
19
+
20
+ <td rowspan="1" colSpan="1" >**Standard Mode (STANDARD)**</td>
21
+
22
+ <td rowspan="1" colSpan="1" >**Embedded Mode (EMBEDDED)**</td>
23
+ </tr>
24
+
25
+ <tr>
26
+ <td rowspan="1" colSpan="1" >Suitable for sidebar or small containers<br>Displays limited number of results<br>Supports expanding to view more</td>
27
+
28
+ <td rowspan="1" colSpan="1" >Suitable for full-screen search interface<br>Complete feature display<br>Supports advanced search</td>
29
+
30
+ <td rowspan="1" colSpan="1" >Suitable for chat interface<br>Focuses on message search<br>Optimized layout</td>
31
+ </tr>
32
+ </table>
33
+
34
+
35
+ ## Props
36
+ <table>
37
+ <tr>
38
+ <td rowspan="1" colSpan="1" >Property</td>
39
+
40
+ <td rowspan="1" colSpan="1" >Type</td>
41
+
42
+ <td rowspan="1" colSpan="1" >Default Value</td>
43
+
44
+ <td rowspan="1" colSpan="1" >Description</td>
45
+ </tr>
46
+
47
+ <tr>
48
+ <td rowspan="1" colSpan="1" >variant</td>
49
+
50
+ <td rowspan="1" colSpan="1" >VariantType</td>
51
+
52
+ <td rowspan="1" colSpan="1" >VariantType.MINI</td>
53
+
54
+ <td rowspan="1" colSpan="1" >Search mode: mini (Mini), standard (Standard), embedded (Embedded)</td>
55
+ </tr>
56
+
57
+ <tr>
58
+ <td rowspan="1" colSpan="1" >SearchBar</td>
59
+
60
+ <td rowspan="1" colSpan="1" >Component<SearchBarProps></td>
61
+
62
+ <td rowspan="1" colSpan="1" >DefaultSearchBar</td>
63
+
64
+ <td rowspan="1" colSpan="1" >Custom search bar component</td>
65
+ </tr>
66
+
67
+ <tr>
68
+ <td rowspan="1" colSpan="1" >SearchResults</td>
69
+
70
+ <td rowspan="1" colSpan="1" >Component<SearchResultsProps></td>
71
+
72
+ <td rowspan="1" colSpan="1" >DefaultSearchResults</td>
73
+
74
+ <td rowspan="1" colSpan="1" >Custom search results component</td>
75
+ </tr>
76
+
77
+ <tr>
78
+ <td rowspan="1" colSpan="1" >SearchAdvanced</td>
79
+
80
+ <td rowspan="1" colSpan="1" >Component<SearchAdvancedProps></td>
81
+
82
+ <td rowspan="1" colSpan="1" >DefaultSearchAdvanced</td>
83
+
84
+ <td rowspan="1" colSpan="1" >Custom advanced search component</td>
85
+ </tr>
86
+
87
+ <tr>
88
+ <td rowspan="1" colSpan="1" >SearchResultsPresearch</td>
89
+
90
+ <td rowspan="1" colSpan="1" >Component</td>
91
+
92
+ <td rowspan="1" colSpan="1" >-</td>
93
+
94
+ <td rowspan="1" colSpan="1" >Pre-search placeholder component</td>
95
+ </tr>
96
+
97
+ <tr>
98
+ <td rowspan="1" colSpan="1" >SearchResultsLoading</td>
99
+
100
+ <td rowspan="1" colSpan="1" >Component</td>
101
+
102
+ <td rowspan="1" colSpan="1" >-</td>
103
+
104
+ <td rowspan="1" colSpan="1" >Loading placeholder component</td>
105
+ </tr>
106
+
107
+ <tr>
108
+ <td rowspan="1" colSpan="1" >SearchResultsEmpty</td>
109
+
110
+ <td rowspan="1" colSpan="1" >Component</td>
111
+
112
+ <td rowspan="1" colSpan="1" >-</td>
113
+
114
+ <td rowspan="1" colSpan="1" >Empty results placeholder component</td>
115
+ </tr>
116
+
117
+ <tr>
118
+ <td rowspan="1" colSpan="1" >SearchResultItem</td>
119
+
120
+ <td rowspan="1" colSpan="1" >Component<ResultItemProps></td>
121
+
122
+ <td rowspan="1" colSpan="1" >-</td>
123
+
124
+ <td rowspan="1" colSpan="1" >Custom search result item component</td>
125
+ </tr>
126
+
127
+ <tr>
128
+ <td rowspan="1" colSpan="1" >debounceTime</td>
129
+
130
+ <td rowspan="1" colSpan="1" >number</td>
131
+
132
+ <td rowspan="1" colSpan="1" >300</td>
133
+
134
+ <td rowspan="1" colSpan="1" >Search debounce time (milliseconds)</td>
135
+ </tr>
136
+
137
+ <tr>
138
+ <td rowspan="1" colSpan="1" >autoFocus</td>
139
+
140
+ <td rowspan="1" colSpan="1" >boolean</td>
141
+
142
+ <td rowspan="1" colSpan="1" >false</td>
143
+
144
+ <td rowspan="1" colSpan="1" >Whether to auto-focus search box</td>
145
+ </tr>
146
+
147
+ <tr>
148
+ <td rowspan="1" colSpan="1" >className</td>
149
+
150
+ <td rowspan="1" colSpan="1" >string</td>
151
+
152
+ <td rowspan="1" colSpan="1" >-</td>
153
+
154
+ <td rowspan="1" colSpan="1" >Custom style class name</td>
155
+ </tr>
156
+
157
+ <tr>
158
+ <td rowspan="1" colSpan="1" >style</td>
159
+
160
+ <td rowspan="1" colSpan="1" >CSSProperties</td>
161
+
162
+ <td rowspan="1" colSpan="1" >-</td>
163
+
164
+ <td rowspan="1" colSpan="1" >Custom styles</td>
165
+ </tr>
166
+
167
+ <tr>
168
+ <td rowspan="1" colSpan="1" >onKeywordChange</td>
169
+
170
+ <td rowspan="1" colSpan="1" >(keyword: string) => void</td>
171
+
172
+ <td rowspan="1" colSpan="1" >-</td>
173
+
174
+ <td rowspan="1" colSpan="1" >Search keyword change callback</td>
175
+ </tr>
176
+
177
+ <tr>
178
+ <td rowspan="1" colSpan="1" >onSearchComplete</td>
179
+
180
+ <td rowspan="1" colSpan="1" >(results: Map<SearchType, SearchResult>) => void</td>
181
+
182
+ <td rowspan="1" colSpan="1" >-</td>
183
+
184
+ <td rowspan="1" colSpan="1" >Search complete callback</td>
185
+ </tr>
186
+
187
+ <tr>
188
+ <td rowspan="1" colSpan="1" >onResultItemClick</td>
189
+
190
+ <td rowspan="1" colSpan="1" >(data: SearchResultItem, type: SearchType) => void</td>
191
+
192
+ <td rowspan="1" colSpan="1" >-</td>
193
+
194
+ <td rowspan="1" colSpan="1" >Search result click callback</td>
195
+ </tr>
196
+
197
+ <tr>
198
+ <td rowspan="1" colSpan="1" >onError</td>
199
+
200
+ <td rowspan="1" colSpan="1" >(error: Error) => void</td>
201
+
202
+ <td rowspan="1" colSpan="1" >-</td>
203
+
204
+ <td rowspan="1" colSpan="1" >Search error callback</td>
205
+ </tr>
206
+ </table>
207
+
208
+
209
+ ## Basic Usage
210
+ ``` typescript
211
+ <template>
212
+ <div class="app">
213
+ <Search
214
+ :variant="VariantType.STANDARD"
215
+ @result-item-click="handleResultClick"
216
+ @keyword-change="handleKeywordChange"
217
+ @error="handleError"
218
+ />
219
+ </div>
220
+ </template>
221
+
222
+ <script setup lang="ts">
223
+ import { Search, VariantType } from '@tencentcloud/chat-uikit-vue3';
224
+ import type { SearchResultItemType, SearchType } from '@tencentcloud/chat-uikit-vue3';
225
+
226
+ const handleResultClick = (data: SearchResultItemType, type: SearchType) => {
227
+ console.log('Search result clicked:', data, type);
228
+ };
229
+
230
+ const handleKeywordChange = (keyword: string) => {
231
+ console.log('Search keyword changed:', keyword);
232
+ };
233
+
234
+ const handleError = (error: Error) => {
235
+ console.error('Search error:', error);
236
+ };
237
+ </script>
238
+ ```
239
+
240
+ ## Customization
241
+
242
+ The `Search` component provides multiple replaceable child components, allowing users to customize `SearchBar`, `SearchResults`, `SearchAdvanced`, `SearchResultItem`, `SearchResultsPresearch`, `SearchResultsLoading`, `SearchResultsEmpty`, etc. Users can also utilize default child components for further customization.
243
+
244
+
245
+
246
+ 【Custom SearchBar】
247
+
248
+ **Props**
249
+ <table>
250
+ <tr>
251
+ <td rowspan="1" colSpan="1" >Property</td>
252
+
253
+ <td rowspan="1" colSpan="1" >Type</td>
254
+
255
+ <td rowspan="1" colSpan="1" >Default Value</td>
256
+
257
+ <td rowspan="1" colSpan="1" >Description</td>
258
+ </tr>
259
+
260
+ <tr>
261
+ <td rowspan="1" colSpan="1" >value</td>
262
+
263
+ <td rowspan="1" colSpan="1" >string</td>
264
+
265
+ <td rowspan="1" colSpan="1" >-</td>
266
+
267
+ <td rowspan="1" colSpan="1" >Search box value</td>
268
+ </tr>
269
+
270
+ <tr>
271
+ <td rowspan="1" colSpan="1" >onChange</td>
272
+
273
+ <td rowspan="1" colSpan="1" >(e: Event) => void</td>
274
+
275
+ <td rowspan="1" colSpan="1" >-</td>
276
+
277
+ <td rowspan="1" colSpan="1" >Input change callback</td>
278
+ </tr>
279
+
280
+ <tr>
281
+ <td rowspan="1" colSpan="1" >onKeyDown</td>
282
+
283
+ <td rowspan="1" colSpan="1" >(e: KeyboardEvent) => void</td>
284
+
285
+ <td rowspan="1" colSpan="1" >-</td>
286
+
287
+ <td rowspan="1" colSpan="1" >Keyboard event callback</td>
288
+ </tr>
289
+
290
+ <tr>
291
+ <td rowspan="1" colSpan="1" >onClear</td>
292
+
293
+ <td rowspan="1" colSpan="1" >() => void</td>
294
+
295
+ <td rowspan="1" colSpan="1" >-</td>
296
+
297
+ <td rowspan="1" colSpan="1" >Clear callback</td>
298
+ </tr>
299
+
300
+ <tr>
301
+ <td rowspan="1" colSpan="1" >placeholder</td>
302
+
303
+ <td rowspan="1" colSpan="1" >string</td>
304
+
305
+ <td rowspan="1" colSpan="1" >-</td>
306
+
307
+ <td rowspan="1" colSpan="1" >Placeholder text</td>
308
+ </tr>
309
+
310
+ <tr>
311
+ <td rowspan="1" colSpan="1" >SearchIcon</td>
312
+
313
+ <td rowspan="1" colSpan="1" >Component</td>
314
+
315
+ <td rowspan="1" colSpan="1" >-</td>
316
+
317
+ <td rowspan="1" colSpan="1" >Custom search icon</td>
318
+ </tr>
319
+
320
+ <tr>
321
+ <td rowspan="1" colSpan="1" >ClearIcon</td>
322
+
323
+ <td rowspan="1" colSpan="1" >Component</td>
324
+
325
+ <td rowspan="1" colSpan="1" >-</td>
326
+
327
+ <td rowspan="1" colSpan="1" >Custom clear icon</td>
328
+ </tr>
329
+
330
+ <tr>
331
+ <td rowspan="1" colSpan="1" >className</td>
332
+
333
+ <td rowspan="1" colSpan="1" >string</td>
334
+
335
+ <td rowspan="1" colSpan="1" >-</td>
336
+
337
+ <td rowspan="1" colSpan="1" >Custom style class name</td>
338
+ </tr>
339
+
340
+ <tr>
341
+ <td rowspan="1" colSpan="1" >style</td>
342
+
343
+ <td rowspan="1" colSpan="1" >CSSProperties</td>
344
+
345
+ <td rowspan="1" colSpan="1" >-</td>
346
+
347
+ <td rowspan="1" colSpan="1" >Custom styles</td>
348
+ </tr>
349
+
350
+ <tr>
351
+ <td rowspan="1" colSpan="1" >onFocus</td>
352
+
353
+ <td rowspan="1" colSpan="1" >(e: FocusEvent) => void</td>
354
+
355
+ <td rowspan="1" colSpan="1" >-</td>
356
+
357
+ <td rowspan="1" colSpan="1" >Focus callback</td>
358
+ </tr>
359
+
360
+ <tr>
361
+ <td rowspan="1" colSpan="1" >onBlur</td>
362
+
363
+ <td rowspan="1" colSpan="1" >(e: FocusEvent) => void</td>
364
+
365
+ <td rowspan="1" colSpan="1" >-</td>
366
+
367
+ <td rowspan="1" colSpan="1" >Blur callback</td>
368
+ </tr>
369
+
370
+ <tr>
371
+ <td rowspan="1" colSpan="1" >autoFocus</td>
372
+
373
+ <td rowspan="1" colSpan="1" >boolean</td>
374
+
375
+ <td rowspan="1" colSpan="1" >false</td>
376
+
377
+ <td rowspan="1" colSpan="1" >Whether to auto-focus</td>
378
+ </tr>
379
+
380
+ <tr>
381
+ <td rowspan="1" colSpan="1" >variant</td>
382
+
383
+ <td rowspan="1" colSpan="1" >VariantType</td>
384
+
385
+ <td rowspan="1" colSpan="1" >-</td>
386
+
387
+ <td rowspan="1" colSpan="1" >Search mode</td>
388
+ </tr>
389
+ </table>
390
+
391
+
392
+ **Example**
393
+ ``` typescript
394
+ <template>
395
+ <div class="custom-search-bar">
396
+ <div class="search-bar-header">
397
+ <span class="search-icon">🔍</span>
398
+ <span class="search-title">Smart Search</span>
399
+ </div>
400
+ <div class="search-input-wrapper">
401
+ <input
402
+ type="text"
403
+ :value="value"
404
+ :placeholder="placeholder || 'Enter keywords to start searching...'"
405
+ @input="handleChange"
406
+ class="enhanced-search-input"
407
+ />
408
+ <button
409
+ v-if="value"
410
+ @click="handleClear"
411
+ class="enhanced-clear-btn"
412
+ >
413
+ ✕
414
+ </button>
415
+ </div>
416
+ </div>
417
+ </template>
418
+
419
+ <script setup lang="ts">
420
+ interface SearchBarProps {
421
+ value?: string;
422
+ onChange?: (event: Event) => void;
423
+ onClear?: () => void;
424
+ placeholder?: string;
425
+ variant?: string;
426
+ }
427
+
428
+ const props = defineProps<SearchBarProps>();
429
+
430
+ const emit = defineEmits<{
431
+ change: [event: Event];
432
+ clear: [];
433
+ }>();
434
+
435
+ const handleChange = (event: Event) => {
436
+ if (props.onChange) {
437
+ props.onChange(event);
438
+ }
439
+ emit('change', event);
440
+ };
441
+
442
+ const handleClear = () => {
443
+ if (props.onClear) {
444
+ props.onClear();
445
+ }
446
+ emit('clear');
447
+ };
448
+ </script>
449
+
450
+ <style scoped>
451
+ .custom-search-bar {
452
+ display: flex;
453
+ flex-direction: column;
454
+ gap: 8px;
455
+ }
456
+
457
+ .search-bar-header {
458
+ display: flex;
459
+ align-items: center;
460
+ gap: 8px;
461
+ }
462
+
463
+ .search-icon {
464
+ font-size: 16px;
465
+ }
466
+
467
+ .search-title {
468
+ font-weight: 500;
469
+ color: #333;
470
+ }
471
+
472
+ .search-input-wrapper {
473
+ position: relative;
474
+ display: flex;
475
+ align-items: center;
476
+ }
477
+
478
+ .enhanced-search-input {
479
+ width: 100%;
480
+ padding: 8px 12px;
481
+ border: 1px solid #ddd;
482
+ border-radius: 4px;
483
+ font-size: 14px;
484
+ outline: none;
485
+ }
486
+
487
+ .enhanced-search-input:focus {
488
+ border-color: #007bff;
489
+ }
490
+
491
+ .enhanced-clear-btn {
492
+ position: absolute;
493
+ right: 8px;
494
+ background: none;
495
+ border: none;
496
+ cursor: pointer;
497
+ color: #999;
498
+ font-size: 16px;
499
+ }
500
+
501
+ .enhanced-clear-btn:hover {
502
+ color: #666;
503
+ }
504
+ </style>
505
+
506
+ ```
507
+ ``` typescript
508
+ <template>
509
+ <Search :SearchBar="CustomSearchBar" />
510
+ </template>
511
+
512
+ <script setup lang="ts">
513
+ import { Search } from '@tencentcloud/chat-uikit-vue3';
514
+ import CustomSearchBar from './CustomSearchBar.vue';
515
+ </script>
516
+
517
+ ```
518
+
519
+ 【Custom SearchResults】
520
+
521
+ **Props**
522
+ <table>
523
+ <tr>
524
+ <td rowspan="1" colSpan="1" >Property</td>
525
+
526
+ <td rowspan="1" colSpan="1" >Type</td>
527
+
528
+ <td rowspan="1" colSpan="1" >Default Value</td>
529
+
530
+ <td rowspan="1" colSpan="1" >Description</td>
531
+ </tr>
532
+
533
+ <tr>
534
+ <td rowspan="1" colSpan="1" >results</td>
535
+
536
+ <td rowspan="1" colSpan="1" >Map<SearchType, SearchResult></td>
537
+
538
+ <td rowspan="1" colSpan="1" >-</td>
539
+
540
+ <td rowspan="1" colSpan="1" >Search result data</td>
541
+ </tr>
542
+
543
+ <tr>
544
+ <td rowspan="1" colSpan="1" >isLoading</td>
545
+
546
+ <td rowspan="1" colSpan="1" >boolean</td>
547
+
548
+ <td rowspan="1" colSpan="1" >-</td>
549
+
550
+ <td rowspan="1" colSpan="1" >Whether loading</td>
551
+ </tr>
552
+
553
+ <tr>
554
+ <td rowspan="1" colSpan="1" >error</td>
555
+
556
+ <td rowspan="1" colSpan="1" >Error \| null</td>
557
+
558
+ <td rowspan="1" colSpan="1" >-</td>
559
+
560
+ <td rowspan="1" colSpan="1" >Error information</td>
561
+ </tr>
562
+
563
+ <tr>
564
+ <td rowspan="1" colSpan="1" >keyword</td>
565
+
566
+ <td rowspan="1" colSpan="1" >string</td>
567
+
568
+ <td rowspan="1" colSpan="1" >-</td>
569
+
570
+ <td rowspan="1" colSpan="1" >Search keyword</td>
571
+ </tr>
572
+
573
+ <tr>
574
+ <td rowspan="1" colSpan="1" >typeLabels</td>
575
+
576
+ <td rowspan="1" colSpan="1" >Record<SearchType, string></td>
577
+
578
+ <td rowspan="1" colSpan="1" >-</td>
579
+
580
+ <td rowspan="1" colSpan="1" >Search type labels</td>
581
+ </tr>
582
+
583
+ <tr>
584
+ <td rowspan="1" colSpan="1" >onLoadMore</td>
585
+
586
+ <td rowspan="1" colSpan="1" >(type: SearchType) => void</td>
587
+
588
+ <td rowspan="1" colSpan="1" >-</td>
589
+
590
+ <td rowspan="1" colSpan="1" >Load more callback</td>
591
+ </tr>
592
+
593
+ <tr>
594
+ <td rowspan="1" colSpan="1" >onResultItemClick</td>
595
+
596
+ <td rowspan="1" colSpan="1" >(data: SearchResultItemType, type: SearchType) => void</td>
597
+
598
+ <td rowspan="1" colSpan="1" >-</td>
599
+
600
+ <td rowspan="1" colSpan="1" >Result item click callback</td>
601
+ </tr>
602
+
603
+ <tr>
604
+ <td rowspan="1" colSpan="1" >SearchResultsLoading</td>
605
+
606
+ <td rowspan="1" colSpan="1" >Component</td>
607
+
608
+ <td rowspan="1" colSpan="1" >Loading</td>
609
+
610
+ <td rowspan="1" colSpan="1" >Custom loading component</td>
611
+ </tr>
612
+
613
+ <tr>
614
+ <td rowspan="1" colSpan="1" >SearchResultsPresearch</td>
615
+
616
+ <td rowspan="1" colSpan="1" >Component</td>
617
+
618
+ <td rowspan="1" colSpan="1" >-</td>
619
+
620
+ <td rowspan="1" colSpan="1" >Pre-search placeholder component</td>
621
+ </tr>
622
+
623
+ <tr>
624
+ <td rowspan="1" colSpan="1" >SearchResultsEmpty</td>
625
+
626
+ <td rowspan="1" colSpan="1" >Component</td>
627
+
628
+ <td rowspan="1" colSpan="1" >EmptyResult</td>
629
+
630
+ <td rowspan="1" colSpan="1" >Empty results placeholder component</td>
631
+ </tr>
632
+
633
+ <tr>
634
+ <td rowspan="1" colSpan="1" >SearchResultItem</td>
635
+
636
+ <td rowspan="1" colSpan="1" >Component<ResultItemProps></td>
637
+
638
+ <td rowspan="1" colSpan="1" >DefaultSearchResultsItem</td>
639
+
640
+ <td rowspan="1" colSpan="1" >Custom result item component</td>
641
+ </tr>
642
+
643
+ <tr>
644
+ <td rowspan="1" colSpan="1" >variant</td>
645
+
646
+ <td rowspan="1" colSpan="1" >VariantType</td>
647
+
648
+ <td rowspan="1" colSpan="1" >VariantType.STANDARD</td>
649
+
650
+ <td rowspan="1" colSpan="1" >Display mode</td>
651
+ </tr>
652
+
653
+ <tr>
654
+ <td rowspan="1" colSpan="1" >searchType</td>
655
+
656
+ <td rowspan="1" colSpan="1" >SearchType \| 'all'</td>
657
+
658
+ <td rowspan="1" colSpan="1" >'all'</td>
659
+
660
+ <td rowspan="1" colSpan="1" >Current search type</td>
661
+ </tr>
662
+ </table>
663
+
664
+
665
+ **Example**
666
+ ``` typescript
667
+ <template>
668
+ <div class="custom-search-results">
669
+ <div class="search-results-header">
670
+ <span class="results-icon">📋</span>
671
+ <span class="results-title">Search Results</span>
672
+ </div>
673
+ <div class="search-results-content">
674
+ <div v-if="!results || results.size === 0" class="no-results">
675
+ No search results
676
+ </div>
677
+ <div v-else class="results-list">
678
+ <div
679
+ v-for="(item, key) in results.keys()"
680
+ :key="key"
681
+ class="result-item"
682
+ >
683
+ <div class="result-group">
684
+ <div class="result-title">
685
+ {{ item }}
686
+ </div>
687
+ <ul v-if="item === SearchType.MESSAGE" class="result-description">
688
+ <li
689
+ v-for="(data, index) in results.get(item)?.resultList"
690
+ :key="index"
691
+ @click="handleResultClick(data)"
692
+ >
693
+ {{ (data as SearchCloudMessagesResultItem).conversation?.getShowName() }}
694
+ </li>
695
+ </ul>
696
+ <ul v-if="item === SearchType.USER" class="result-description">
697
+ <li
698
+ v-for="(data, index) in results.get(item)?.resultList"
699
+ :key="index"
700
+ @click="handleResultClick(data)"
701
+ >
702
+ {{ (data as SearchCloudUsersResultItem).profile.nick
703
+ || (data as SearchCloudUsersResultItem).profile.userID }}
704
+ </li>
705
+ </ul>
706
+ <ul v-if="item === SearchType.GROUP" class="result-description">
707
+ <li
708
+ v-for="(data, index) in results.get(item)?.resultList"
709
+ :key="index"
710
+ @click="handleResultClick(data)"
711
+ >
712
+ {{ (data as SearchCloudGroupsResultItem).groupInfo.name
713
+ || (data as SearchCloudGroupsResultItem).groupInfo.groupID }}
714
+ </li>
715
+ </ul>
716
+ </div>
717
+ </div>
718
+ </div>
719
+ </div>
720
+ </div>
721
+ </template>
722
+
723
+ <script setup lang="ts">
724
+ import { SearchType } from '@tencentcloud/chat-uikit-vue3';
725
+ import type {
726
+ SearchCloudGroupsResultItem,
727
+ SearchCloudMessagesResultItem,
728
+ SearchCloudUsersResultItem,
729
+ SearchResult,
730
+ SearchResultItemType,
731
+ } from '@tencentcloud/chat-uikit-vue3';
732
+
733
+ interface SearchResultsProps {
734
+ results?: Map<SearchType, SearchResult<any>>;
735
+ loading?: boolean;
736
+ keyword?: string;
737
+ searchType?: SearchType;
738
+ }
739
+
740
+ const props = defineProps<SearchResultsProps>();
741
+
742
+ const emit = defineEmits<{
743
+ 'result-item-click': [data: SearchResultItemType, type: any];
744
+ }>();
745
+
746
+ const handleResultClick = (item: SearchResultItemType) => {
747
+ emit('result-item-click', item, props.searchType || 'ALL');
748
+ };
749
+ </script>
750
+
751
+ <style scoped>
752
+ .custom-search-results {
753
+ display: flex;
754
+ flex-direction: column;
755
+ gap: 8px;
756
+ }
757
+
758
+ .search-results-header {
759
+ display: flex;
760
+ align-items: center;
761
+ gap: 8px;
762
+ }
763
+
764
+ .results-icon {
765
+ font-size: 16px;
766
+ }
767
+
768
+ .results-title {
769
+ font-weight: 500;
770
+ color: #333;
771
+ }
772
+
773
+ .search-results-content {
774
+ max-height: 400px;
775
+ overflow-y: auto;
776
+ }
777
+
778
+ .no-results {
779
+ padding: 20px;
780
+ text-align: center;
781
+ color: #999;
782
+ font-size: 14px;
783
+ }
784
+
785
+ .results-list {
786
+ display: flex;
787
+ flex-direction: column;
788
+ gap: 4px;
789
+ }
790
+
791
+ .result-item {
792
+ padding: 12px;
793
+ border: 1px solid #eee;
794
+ border-radius: 4px;
795
+ cursor: pointer;
796
+ transition: background-color 0.2s;
797
+ }
798
+
799
+ .result-item:hover {
800
+ background-color: #f5f5f5;
801
+ }
802
+
803
+ .result-content {
804
+ display: flex;
805
+ flex-direction: column;
806
+ gap: 4px;
807
+ }
808
+
809
+ .result-title {
810
+ font-weight: 500;
811
+ color: #333;
812
+ font-size: 14px;
813
+ }
814
+
815
+ .result-description {
816
+ color: #666;
817
+ font-size: 12px;
818
+ line-height: 1.4;
819
+ }
820
+ </style>
821
+
822
+ ```
823
+ ``` typescript
824
+ <template>
825
+ <Search :SearchResults="CustomSearchResults" />
826
+ </template>
827
+
828
+ <script setup lang="ts">
829
+ import { Search } from '@tencentcloud/chat-uikit-vue3';
830
+ import CustomSearchResults from './CustomSearchResults.vue';
831
+ </script>
832
+ ```
833
+
834
+ 【Custom SearchAdvanced】
835
+
836
+ **Props**
837
+ <table>
838
+ <tr>
839
+ <td rowspan="1" colSpan="1" >Property</td>
840
+
841
+ <td rowspan="1" colSpan="1" >Type</td>
842
+
843
+ <td rowspan="1" colSpan="1" >Default Value</td>
844
+
845
+ <td rowspan="1" colSpan="1" >Description</td>
846
+ </tr>
847
+
848
+ <tr>
849
+ <td rowspan="1" colSpan="1" >variant</td>
850
+
851
+ <td rowspan="1" colSpan="1" >VariantType</td>
852
+
853
+ <td rowspan="1" colSpan="1" >-</td>
854
+
855
+ <td rowspan="1" colSpan="1" >Display mode</td>
856
+ </tr>
857
+
858
+ <tr>
859
+ <td rowspan="1" colSpan="1" >searchType</td>
860
+
861
+ <td rowspan="1" colSpan="1" >SearchTabType</td>
862
+
863
+ <td rowspan="1" colSpan="1" >-</td>
864
+
865
+ <td rowspan="1" colSpan="1" >Current search type</td>
866
+ </tr>
867
+
868
+ <tr>
869
+ <td rowspan="1" colSpan="1" >advancedParams</td>
870
+
871
+ <td rowspan="1" colSpan="1" >Map<SearchType, SearchParamsMap[SearchType]></td>
872
+
873
+ <td rowspan="1" colSpan="1" >-</td>
874
+
875
+ <td rowspan="1" colSpan="1" >Advanced search parameters</td>
876
+ </tr>
877
+
878
+ <tr>
879
+ <td rowspan="1" colSpan="1" >onAdvancedParamsChange</td>
880
+
881
+ <td rowspan="1" colSpan="1" >(type: SearchType, params: SearchParamsMap[SearchType]) => void</td>
882
+
883
+ <td rowspan="1" colSpan="1" >-</td>
884
+
885
+ <td rowspan="1" colSpan="1" >Parameter change callback</td>
886
+ </tr>
887
+ </table>
888
+
889
+
890
+ **Example**
891
+ ``` typescript
892
+ <template>
893
+ <div class="custom-search-advanced">
894
+ <div class="search-advanced-header">
895
+ <span class="advanced-icon">⚙️</span>
896
+ <span class="advanced-title">Advanced Search</span>
897
+ </div>
898
+ <div class="search-advanced-content">
899
+ <div class="search-type-section">
900
+ <div class="section-title">
901
+ Search Type
902
+ </div>
903
+ <div class="search-type-options">
904
+ <label
905
+ v-for="type in searchTypes"
906
+ :key="type.value"
907
+ class="type-option"
908
+ >
909
+ <input
910
+ type="radio"
911
+ :value="type.value"
912
+ :checked="searchType === type.value"
913
+ @change="handleSearchTypeChange(type.value as SearchType)"
914
+ >
915
+ <span class="type-label">{{ type.label }}</span>
916
+ </label>
917
+ </div>
918
+ </div>
919
+ </div>
920
+ </div>
921
+ </template>
922
+
923
+ <script setup lang="ts">
924
+ import { ref } from 'vue';
925
+ import { SearchType, useSearchState } from '@tencentcloud/chat-uikit-vue3';
926
+ import type { VariantType } from '@tencentcloud/chat-uikit-vue3';
927
+
928
+ interface CustomSearchAdvancedProps {
929
+ variant?: VariantType;
930
+ searchType?: SearchType;
931
+ }
932
+
933
+ const props = defineProps<CustomSearchAdvancedProps>();
934
+ const { setSelectedType } = useSearchState();
935
+
936
+ const emit = defineEmits<{
937
+ 'search-type-change': [type: SearchType | 'all'];
938
+ }>();
939
+
940
+ const searchTypes = [
941
+ { value: 'all', label: 'All' },
942
+ { value: SearchType.MESSAGE, label: 'Messages' },
943
+ { value: SearchType.USER, label: 'Users' },
944
+ { value: SearchType.GROUP, label: 'Groups' },
945
+ ];
946
+
947
+ const searchType = ref<SearchType | 'all'>(props.searchType || 'all');
948
+
949
+ const handleSearchTypeChange = (type: SearchType) => {
950
+ searchType.value = type;
951
+ setSelectedType(type);
952
+ emit('search-type-change', type);
953
+ };
954
+ </script>
955
+
956
+ <style scoped>
957
+ .custom-search-advanced {
958
+ display: flex;
959
+ flex-direction: column;
960
+ gap: 16px;
961
+ padding: 16px;
962
+ border: 1px solid #eee;
963
+ border-radius: 8px;
964
+ background-color: #fff;
965
+ }
966
+
967
+ .search-advanced-header {
968
+ display: flex;
969
+ align-items: center;
970
+ gap: 8px;
971
+ padding-bottom: 12px;
972
+ border-bottom: 1px solid #f0f0f0;
973
+ }
974
+
975
+ .advanced-icon {
976
+ font-size: 16px;
977
+ }
978
+
979
+ .advanced-title {
980
+ font-weight: 500;
981
+ color: #333;
982
+ font-size: 16px;
983
+ }
984
+
985
+ .search-advanced-content {
986
+ display: flex;
987
+ flex-direction: column;
988
+ gap: 16px;
989
+ }
990
+
991
+ .section-title {
992
+ font-weight: 500;
993
+ color: #333;
994
+ font-size: 14px;
995
+ margin-bottom: 8px;
996
+ }
997
+
998
+ .search-type-options {
999
+ display: flex;
1000
+ flex-wrap: wrap;
1001
+ gap: 12px;
1002
+ }
1003
+
1004
+ .type-option {
1005
+ display: flex;
1006
+ align-items: center;
1007
+ gap: 6px;
1008
+ cursor: pointer;
1009
+ }
1010
+
1011
+ .type-option input[type="radio"] {
1012
+ margin: 0;
1013
+ }
1014
+
1015
+ .type-label {
1016
+ font-size: 14px;
1017
+ color: #666;
1018
+ }
1019
+ </style>
1020
+
1021
+ ```
1022
+ ``` typescript
1023
+ <template>
1024
+ <Search :SearchAdvanced="CustomSearchAdvanced" />
1025
+ </template>
1026
+
1027
+ <script setup lang="ts">
1028
+ import { Search } from '@tencentcloud/chat-uikit-vue3';
1029
+ import CustomSearchAdvanced from './CustomSearchAdvanced.vue';
1030
+ </script>
1031
+ ```
1032
+
1033
+ 【Custom SearchResultItem】
1034
+
1035
+ **Props**
1036
+ <table>
1037
+ <tr>
1038
+ <td rowspan="1" colSpan="1" >Property</td>
1039
+
1040
+ <td rowspan="1" colSpan="1" >Type</td>
1041
+
1042
+ <td rowspan="1" colSpan="1" >Default Value</td>
1043
+
1044
+ <td rowspan="1" colSpan="1" >Description</td>
1045
+ </tr>
1046
+
1047
+ <tr>
1048
+ <td rowspan="1" colSpan="1" >data</td>
1049
+
1050
+ <td rowspan="1" colSpan="1" >SearchResultItem</td>
1051
+
1052
+ <td rowspan="1" colSpan="1" >-</td>
1053
+
1054
+ <td rowspan="1" colSpan="1" >Search result data</td>
1055
+ </tr>
1056
+
1057
+ <tr>
1058
+ <td rowspan="1" colSpan="1" >type</td>
1059
+
1060
+ <td rowspan="1" colSpan="1" >SearchType</td>
1061
+
1062
+ <td rowspan="1" colSpan="1" >-</td>
1063
+
1064
+ <td rowspan="1" colSpan="1" >Search result type</td>
1065
+ </tr>
1066
+
1067
+ <tr>
1068
+ <td rowspan="1" colSpan="1" >keyword</td>
1069
+
1070
+ <td rowspan="1" colSpan="1" >string</td>
1071
+
1072
+ <td rowspan="1" colSpan="1" >-</td>
1073
+
1074
+ <td rowspan="1" colSpan="1" >Search keyword</td>
1075
+ </tr>
1076
+
1077
+ <tr>
1078
+ <td rowspan="1" colSpan="1" >onClick</td>
1079
+
1080
+ <td rowspan="1" colSpan="1" >(data: SearchResultItem, type: SearchType) => void</td>
1081
+
1082
+ <td rowspan="1" colSpan="1" >-</td>
1083
+
1084
+ <td rowspan="1" colSpan="1" >Click callback</td>
1085
+ </tr>
1086
+
1087
+ <tr>
1088
+ <td rowspan="1" colSpan="1" >className</td>
1089
+
1090
+ <td rowspan="1" colSpan="1" >string</td>
1091
+
1092
+ <td rowspan="1" colSpan="1" >-</td>
1093
+
1094
+ <td rowspan="1" colSpan="1" >Custom style class name</td>
1095
+ </tr>
1096
+ </table>
1097
+
1098
+
1099
+ **Example**
1100
+ ``` java
1101
+ <template>
1102
+ <div class="custom-search-item">
1103
+ <div
1104
+ v-if="type === SearchType.USER"
1105
+ class="user-item"
1106
+ @click="handleClick"
1107
+ >
1108
+ <div class="user-avatar">
1109
+ <img :src="data.profile.avatar" :alt="data.profile.nick" />
1110
+ </div>
1111
+ <div class="user-info">
1112
+ <div class="user-name">{{ data.profile.nick }}</div>
1113
+ <div class="user-id">{{ data.profile.userID }}</div>
1114
+ </div>
1115
+ </div>
1116
+
1117
+ <div
1118
+ v-else-if="type === SearchType.GROUP"
1119
+ class="group-item"
1120
+ @click="handleClick"
1121
+ >
1122
+ <div class="group-avatar">👥</div>
1123
+ <div class="group-info">
1124
+ <div class="group-name">{{ data.groupInfo.name }}</div>
1125
+ <div class="group-id">{{ data.groupInfo.groupID }}</div>
1126
+ </div>
1127
+ </div>
1128
+
1129
+ <div
1130
+ v-else-if="type === SearchType.MESSAGE"
1131
+ class="message-item"
1132
+ @click="handleClick"
1133
+ >
1134
+ <div class="message-content">{{ data.conversation.getShowName() }}</div>
1135
+ <div class="message-num">{{ data.messageCount }}</div>
1136
+ </div>
1137
+ </div>
1138
+ </template>
1139
+
1140
+ <script setup lang="ts">
1141
+ import { SearchType } from '@tencentcloud/chat-uikit-vue3';
1142
+ import type { SearchResultItemType } from '@tencentcloud/chat-uikit-vue3';
1143
+
1144
+ interface CustomSearchItemProps {
1145
+ data: SearchResultItemType;
1146
+ type?: SearchType;
1147
+ onClick?: (data: SearchResultItemType, type: SearchType) => void;
1148
+ }
1149
+
1150
+ const props = defineProps<CustomSearchItemProps>();
1151
+
1152
+ console.warn('CustomSearchItem', props);
1153
+
1154
+ const handleClick = () => {
1155
+ if (props.onClick && props.type) {
1156
+ props.onClick(props.data, props.type);
1157
+ }
1158
+ };
1159
+
1160
+ const formatTime = (timestamp: number) => {
1161
+ return new Date(timestamp).toLocaleString();
1162
+ };
1163
+ </script>
1164
+
1165
+ <style scoped>
1166
+ .custom-search-item {
1167
+ cursor: pointer;
1168
+ padding: 12px;
1169
+ border-bottom: 1px solid #f0f0f0;
1170
+ transition: background-color 0.2s;
1171
+ }
1172
+
1173
+ .custom-search-item:hover {
1174
+ background-color: #f5f5f5;
1175
+ }
1176
+
1177
+ .user-item,
1178
+ .group-item,
1179
+ .message-item {
1180
+ display: flex;
1181
+ align-items: center;
1182
+ gap: 12px;
1183
+ }
1184
+
1185
+ .user-avatar img {
1186
+ width: 40px;
1187
+ height: 40px;
1188
+ border-radius: 50%;
1189
+ object-fit: cover;
1190
+ }
1191
+
1192
+ .group-avatar {
1193
+ width: 40px;
1194
+ height: 40px;
1195
+ border-radius: 8px;
1196
+ background-color: #e9ecef;
1197
+ display: flex;
1198
+ align-items: center;
1199
+ justify-content: center;
1200
+ font-size: 18px;
1201
+ }
1202
+
1203
+ .user-info,
1204
+ .group-info {
1205
+ flex: 1;
1206
+ }
1207
+
1208
+ .user-name,
1209
+ .group-name {
1210
+ font-weight: 500;
1211
+ color: #333;
1212
+ font-size: 14px;
1213
+ margin-bottom: 4px;
1214
+ }
1215
+
1216
+ .user-id,
1217
+ .group-id {
1218
+ color: #666;
1219
+ font-size: 12px;
1220
+ }
1221
+
1222
+ .message-content {
1223
+ flex: 1;
1224
+ color: #333;
1225
+ font-size: 14px;
1226
+ line-height: 1.4;
1227
+ }
1228
+
1229
+ .message-num {
1230
+ color: #666;
1231
+ font-size: 12px;
1232
+ white-space: nowrap;
1233
+ }
1234
+ </style>
1235
+ ```
1236
+ ``` typescript
1237
+ <template>
1238
+ <Search :SearchResultItem="CustomSearchItem" />
1239
+ </template>
1240
+
1241
+ <script setup lang="ts">
1242
+ import { Search } from '@tencentcloud/chat-uikit-vue3';
1243
+ import CustomSearchItem from './CustomSearchItem.vue';
1244
+ </script>
1245
+ ```
1246
+
1247
+ 【Custom Placeholders】
1248
+
1249
+ **Props**
1250
+ <table>
1251
+ <tr>
1252
+ <td rowspan="1" colSpan="1" >Property</td>
1253
+
1254
+ <td rowspan="1" colSpan="1" >Type</td>
1255
+
1256
+ <td rowspan="1" colSpan="1" >Default Value</td>
1257
+
1258
+ <td rowspan="1" colSpan="1" >Description</td>
1259
+ </tr>
1260
+
1261
+ <tr>
1262
+ <td rowspan="1" colSpan="1" >SearchResultsPresearch</td>
1263
+
1264
+ <td rowspan="1" colSpan="1" >Component</td>
1265
+
1266
+ <td rowspan="1" colSpan="1" >-</td>
1267
+
1268
+ <td rowspan="1" colSpan="1" >Pre-search placeholder component</td>
1269
+ </tr>
1270
+
1271
+ <tr>
1272
+ <td rowspan="1" colSpan="1" >SearchResultsLoading</td>
1273
+
1274
+ <td rowspan="1" colSpan="1" >Component</td>
1275
+
1276
+ <td rowspan="1" colSpan="1" >-</td>
1277
+
1278
+ <td rowspan="1" colSpan="1" >Loading placeholder component</td>
1279
+ </tr>
1280
+
1281
+ <tr>
1282
+ <td rowspan="1" colSpan="1" >SearchResultsEmpty</td>
1283
+
1284
+ <td rowspan="1" colSpan="1" >Component</td>
1285
+
1286
+ <td rowspan="1" colSpan="1" >-</td>
1287
+
1288
+ <td rowspan="1" colSpan="1" >Empty results placeholder component</td>
1289
+ </tr>
1290
+ </table>
1291
+
1292
+
1293
+ **Example**
1294
+ ``` typescript
1295
+ <template>
1296
+ <Search
1297
+ :search-results-presearch="PresearchComponent"
1298
+ :search-results-loading="LoadingComponent"
1299
+ :search-results-empty="EmptyComponent"
1300
+ />
1301
+ </template>
1302
+
1303
+ <script setup lang="ts">
1304
+ import { defineComponent, h } from 'vue';
1305
+ import { Search } from '@tencentcloud/chat-uikit-vue3';
1306
+
1307
+ const PresearchComponent = defineComponent({
1308
+ name: 'PresearchComponent',
1309
+ setup() {
1310
+ return () => h('div', { class: 'presearch-placeholder' }, [
1311
+ h('div', { class: 'placeholder-icon' }, '🔍'),
1312
+ h('div', { class: 'placeholder-text' }, 'Enter keywords to start searching')
1313
+ ]);
1314
+ }
1315
+ });
1316
+
1317
+ const LoadingComponent = defineComponent({
1318
+ name: 'LoadingComponent',
1319
+ setup() {
1320
+ return () => h('div', { class: 'loading-placeholder' }, [
1321
+ h('div', { class: 'loading-spinner' }),
1322
+ h('div', { class: 'loading-text' }, 'Searching...')
1323
+ ]);
1324
+ }
1325
+ });
1326
+
1327
+ const EmptyComponent = defineComponent({
1328
+ name: 'EmptyComponent',
1329
+ setup() {
1330
+ return () => h('div', { class: 'empty-placeholder' }, [
1331
+ h('div', { class: 'empty-icon' }, '😔'),
1332
+ h('div', { class: 'empty-text' }, 'No results found'),
1333
+ h('div', { class: 'empty-hint' }, 'Try searching with different keywords')
1334
+ ]);
1335
+ }
1336
+ });
1337
+ </script>
1338
+
1339
+ <style scoped>
1340
+ .presearch-placeholder,
1341
+ .loading-placeholder,
1342
+ .empty-placeholder {
1343
+ display: flex;
1344
+ flex-direction: column;
1345
+ align-items: center;
1346
+ justify-content: center;
1347
+ padding: 60px 20px;
1348
+ color: #999;
1349
+ }
1350
+
1351
+ .placeholder-icon,
1352
+ .empty-icon {
1353
+ font-size: 48px;
1354
+ margin-bottom: 16px;
1355
+ }
1356
+
1357
+ .loading-spinner {
1358
+ width: 32px;
1359
+ height: 32px;
1360
+ border: 3px solid #f3f3f3;
1361
+ border-top: 3px solid #1890ff;
1362
+ border-radius: 50%;
1363
+ animation: spin 1s linear infinite;
1364
+ margin-bottom: 16px;
1365
+ }
1366
+
1367
+ @keyframes spin {
1368
+ 0% { transform: rotate(0deg); }
1369
+ 100% { transform: rotate(360deg); }
1370
+ }
1371
+
1372
+ .placeholder-text,
1373
+ .loading-text,
1374
+ .empty-text {
1375
+ font-size: 16px;
1376
+ margin-bottom: 8px;
1377
+ }
1378
+
1379
+ .empty-hint {
1380
+ font-size: 14px;
1381
+ color: #bbb;
1382
+ }
1383
+ </style>
1384
+ ```