@meistrari/chat-nuxt 4.4.1-rc.0 → 4.5.0-rc.0

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 (30) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/conversations/components/chat-conversation-creator-filter.vue +22 -11
  3. package/dist/runtime/conversations/components/chat-conversation-list.vue +245 -159
  4. package/dist/runtime/embed/components/chat-embed-inner.d.vue.ts +18 -8
  5. package/dist/runtime/embed/components/chat-embed-inner.vue +44 -45
  6. package/dist/runtime/embed/components/chat-embed-inner.vue.d.ts +18 -8
  7. package/dist/runtime/embed/components/chat-embed.d.vue.ts +4 -2
  8. package/dist/runtime/embed/components/chat-embed.vue +6 -2
  9. package/dist/runtime/embed/components/chat-embed.vue.d.ts +4 -2
  10. package/dist/runtime/embed/components/chat-sidebar-toggle.d.vue.ts +10 -0
  11. package/dist/runtime/embed/components/chat-sidebar-toggle.vue +49 -0
  12. package/dist/runtime/embed/components/chat-sidebar-toggle.vue.d.ts +10 -0
  13. package/dist/runtime/embed/components/meistrari-chat-embed.d.vue.ts +2 -0
  14. package/dist/runtime/embed/components/meistrari-chat-embed.vue +3 -0
  15. package/dist/runtime/embed/components/meistrari-chat-embed.vue.d.ts +2 -0
  16. package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue +6 -2
  17. package/dist/runtime/embed/composables/agent-harness.d.ts +11 -1
  18. package/dist/runtime/embed/composables/agent-harness.js +32 -2
  19. package/dist/runtime/embed/empty-state-labels.d.ts +5 -0
  20. package/dist/runtime/embed/empty-state-labels.js +9 -0
  21. package/dist/runtime/embed/feature-config.d.ts +3 -0
  22. package/dist/runtime/embed/feature-config.js +2 -1
  23. package/dist/runtime/embed/loading-messages.d.ts +1 -1
  24. package/dist/runtime/embed/loading-messages.js +2 -2
  25. package/dist/runtime/embed/types.d.ts +13 -0
  26. package/dist/runtime/files/vault-links.js +3 -3
  27. package/dist/runtime/messages/components/chat-message-input.d.vue.ts +1 -0
  28. package/dist/runtime/messages/components/chat-message-input.vue +3 -2
  29. package/dist/runtime/messages/components/chat-message-input.vue.d.ts +1 -0
  30. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
3
  "configKey": "chatNuxt",
4
- "version": "4.4.1-rc.0",
4
+ "version": "4.5.0-rc.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -1,14 +1,13 @@
1
1
  <script setup>
2
2
  import { useConversations } from "../composables/conversations";
3
- import { conversationCreatorFilterOptions } from "../../types/schemas/chat/ui.js";
4
3
  import { hasConversationCreatorFilterResults } from "../creator-filter";
5
4
  import { useEmbedConfig } from "../../embed/composables/embed-config";
5
+ const FILTER_OPTIONS = [
6
+ { value: "all", label: "Todas" },
7
+ { value: "mine", label: "Minhas" }
8
+ ];
6
9
  const embedConfig = useEmbedConfig();
7
10
  const { conversationCreatorFilter, conversationCreatorFilterCounts } = useConversations();
8
- const filterOptions = computed(() => conversationCreatorFilterOptions.map((option) => ({
9
- value: option.value,
10
- label: `${option.label} ${conversationCreatorFilterCounts.value[option.value]}`
11
- })));
12
11
  const showConversationCreatorFilter = computed(
13
12
  () => !embedConfig?.hideConversationCreatorFilter.value && hasConversationCreatorFilterResults(conversationCreatorFilterCounts.value)
14
13
  );
@@ -23,13 +22,25 @@ function handleFilterUpdate(value) {
23
22
  </script>
24
23
 
25
24
  <template>
26
- <TelaSegmentToggle
25
+ <TelaSelectMenu
27
26
  v-if="showConversationCreatorFilter"
28
27
  :model-value="conversationCreatorFilter"
29
- :options="filterOptions"
30
- class="w-full"
31
- buttons-class="flex-1 min-w-0 px-8px"
32
- aria-label="Filtrar conversas por criador"
28
+ :options="FILTER_OPTIONS"
29
+ content-class="min-w-130px! rounded-16px!"
30
+ enable-portal
33
31
  @update:model-value="handleFilterUpdate"
34
- />
32
+ >
33
+ <template #trigger>
34
+ <!-- Styled to match the sibling "+" icon button; the caret is hidden. -->
35
+ <TelaSelectMenuTrigger
36
+ aria-label="Filtrar conversas por criador"
37
+ class="size-22px! p-3px! gap-0! justify-center! rounded-6px! border-0! bg-transparent! shadow-none! text-icon-tertiary hover:bg-muted! hover:text-primary data-[state=open]:bg-muted! data-[state=open]:text-primary [&>:last-child]:hidden"
38
+ >
39
+ <TelaIcon
40
+ name="i-ph-sliders-horizontal"
41
+ size="16px"
42
+ />
43
+ </TelaSelectMenuTrigger>
44
+ </template>
45
+ </TelaSelectMenu>
35
46
  </template>
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { useVirtualList } from "@vueuse/core";
2
+ import { usePreferredReducedMotion, useVirtualList } from "@vueuse/core";
3
3
  import { useConversationList } from "../composables/conversation-list";
4
4
  const props = defineProps({
5
5
  conversations: { type: null, required: true },
@@ -55,6 +55,46 @@ const ROW_HEIGHT = 32;
55
55
  const HEADING_HEIGHT = 28;
56
56
  const ERROR_ROW_HEIGHT = 20;
57
57
  const SECTION_GAP = 10;
58
+ const FOLDER_TOGGLE_DURATION = 270;
59
+ const togglingFolder = shallowRef(null);
60
+ const reducedMotion = usePreferredReducedMotion();
61
+ let togglingFrame = 0;
62
+ function easeOutCubic(t) {
63
+ return 1 - (1 - t) ** 3;
64
+ }
65
+ function stopFolderAnimation() {
66
+ if (togglingFrame)
67
+ cancelAnimationFrame(togglingFrame);
68
+ togglingFrame = 0;
69
+ togglingFolder.value = null;
70
+ }
71
+ function animateFolder(groupId, from, to) {
72
+ stopFolderAnimation();
73
+ if (typeof requestAnimationFrame === "undefined" || reducedMotion.value === "reduce")
74
+ return;
75
+ const startedAt = Date.now();
76
+ const tick = () => {
77
+ const t = Math.min((Date.now() - startedAt) / FOLDER_TOGGLE_DURATION, 1);
78
+ if (t >= 1) {
79
+ togglingFrame = 0;
80
+ togglingFolder.value = null;
81
+ return;
82
+ }
83
+ togglingFolder.value = { groupId, progress: from + (to - from) * easeOutCubic(t) };
84
+ togglingFrame = requestAnimationFrame(tick);
85
+ };
86
+ tick();
87
+ }
88
+ function folderProgress(groupId) {
89
+ return togglingFolder.value?.groupId === groupId ? togglingFolder.value.progress : null;
90
+ }
91
+ function handleToggleGroup(groupId) {
92
+ const wasOpen = groupItems.value.find((group) => group.group.id === groupId)?.open ?? false;
93
+ const from = folderProgress(groupId) ?? (wasOpen ? 1 : 0);
94
+ toggleGroup(groupId);
95
+ animateFolder(groupId, from, wasOpen ? 0 : 1);
96
+ }
97
+ onBeforeUnmount(stopFolderAnimation);
58
98
  const rows = computed(() => {
59
99
  const result = [];
60
100
  if (groupItems.value.length > 0)
@@ -64,14 +104,18 @@ const rows = computed(() => {
64
104
  result.push({ type: "group", key: `group:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
65
105
  if (groupBucket.isRenaming && renameGroupError.value)
66
106
  result.push({ type: "error", key: `error:${groupId}`, height: ERROR_ROW_HEIGHT, groupId, groupBucket });
67
- if (!groupBucket.open)
107
+ const progress = folderProgress(groupId);
108
+ if (!groupBucket.open && progress === null)
68
109
  continue;
69
- for (const conversation of groupBucket.items)
70
- result.push({ type: "conversation", key: conversation.id, height: ROW_HEIGHT, groupId, conversation });
110
+ const children = groupBucket.items.map((conversation) => ({ type: "conversation", key: conversation.id, height: ROW_HEIGHT, groupId, conversation }));
71
111
  if (groupBucket.showNewConversationAction)
72
- result.push({ type: "new", key: `new:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
112
+ children.push({ type: "new", key: `new:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
73
113
  else if (groupBucket.showSearchEmpty)
74
- result.push({ type: "empty", key: `empty:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
114
+ children.push({ type: "empty", key: `empty:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
115
+ const scale = progress ?? 1;
116
+ const clipHeight = children.length * ROW_HEIGHT * scale;
117
+ for (const child of children)
118
+ result.push({ ...child, height: ROW_HEIGHT * scale, layoutHeight: ROW_HEIGHT, clipHeight });
75
119
  }
76
120
  if (groupItems.value.length > 0)
77
121
  result.push({ type: "spacer", key: "spacer", height: SECTION_GAP, groupId: null });
@@ -79,8 +123,20 @@ const rows = computed(() => {
79
123
  for (const conversation of ungroupedConversations.value)
80
124
  result.push({ type: "conversation", key: conversation.id, height: ROW_HEIGHT, groupId: null, conversation });
81
125
  let offset = 0;
126
+ let clip = null;
82
127
  return result.map((row) => {
83
- const positionedRow = { ...row, offset };
128
+ let clipTop;
129
+ let localOffset = 0;
130
+ if (row.clipHeight !== void 0 && row.groupId) {
131
+ if (clip?.groupId !== row.groupId)
132
+ clip = { groupId: row.groupId, top: offset, localOffset: 0 };
133
+ clipTop = clip.top;
134
+ localOffset = clip.localOffset;
135
+ clip.localOffset += row.layoutHeight ?? row.height;
136
+ } else {
137
+ clip = null;
138
+ }
139
+ const positionedRow = { ...row, offset, clipTop, localOffset };
84
140
  offset += row.height;
85
141
  return positionedRow;
86
142
  });
@@ -100,6 +156,25 @@ const renderedRows = computed(() => {
100
156
  }
101
157
  return [...indexes].sort((a, b) => a - b).map((index) => ({ ...rows.value[index], index }));
102
158
  });
159
+ const renderedBlocks = computed(() => {
160
+ const blocks = [];
161
+ const clipBlocks = /* @__PURE__ */ new Map();
162
+ for (const row of renderedRows.value) {
163
+ if (row.clipTop === void 0 || !row.groupId) {
164
+ blocks.push({ key: row.key, top: row.offset, height: row.height, clip: false, opacity: 1, rows: [row] });
165
+ continue;
166
+ }
167
+ const existing = clipBlocks.get(row.groupId);
168
+ if (existing) {
169
+ existing.rows.push(row);
170
+ continue;
171
+ }
172
+ const block = { key: `clip:${row.groupId}`, top: row.clipTop, height: row.clipHeight ?? 0, clip: true, opacity: folderProgress(row.groupId) ?? 1, rows: [row] };
173
+ clipBlocks.set(row.groupId, block);
174
+ blocks.push(block);
175
+ }
176
+ return blocks;
177
+ });
103
178
  const totalHeight = computed(() => {
104
179
  const last = rows.value.at(-1);
105
180
  return last ? last.offset + last.height : 0;
@@ -205,176 +280,187 @@ function dropTargetClass(row) {
205
280
  </p>
206
281
  </div>
207
282
 
208
- <div v-else v-bind="containerProps" flex-1 min-h-0 mt-4px>
283
+ <div v-else v-bind="containerProps" flex-1 min-h-0 mt-4px no-scrollbar>
209
284
  <div relative :style="{ height: `${totalHeight}px` }">
210
285
  <div
211
- v-for="row in renderedRows"
212
- :key="row.key"
213
- :style="{ height: `${row.height}px`, top: `${row.offset}px` }"
286
+ v-for="block in renderedBlocks"
287
+ :key="block.key"
214
288
  absolute inset-x-0
215
- :data-row-index="row.index"
216
- rounded-8px
217
- :class="dropTargetClass(row)"
218
- @keydown="handleRowKeydown($event, row.index)"
219
- @focusin="retainedRowKey = row.key"
220
- @pointerdown="retainedRowKey = row.key"
221
- @dragstart.capture="draggedRowKey = row.key"
222
- @dragend.capture="draggedRowKey = null"
223
- v-on="dropListeners(row)"
289
+ :class="block.clip ? 'overflow-hidden' : ''"
290
+ :style="{ top: `${block.top}px`, height: `${block.height}px`, opacity: block.opacity }"
224
291
  >
225
- <div v-if="row.type === 'folders'" h-full flex items-center justify-between pl-12px pr-2px>
226
- <span body-12-medium text-tertiary>
227
- Pastas
228
- </span>
229
- <TelaIconButton
230
- icon="i-ph-plus"
231
- color="secondary"
232
- size="sm"
233
- button-class="p-3px! rounded-6px!"
234
- aria-label="Nova pasta"
235
- @click="createNewGroup"
236
- />
237
- </div>
238
- <div v-else-if="row.type === 'ungrouped'" h-full flex items-center justify-between pl-12px pr-2px>
239
- <span body-12-medium text-secondary>
240
- {{ ungroupedConversationLabel }}
241
- </span>
242
- <TelaIconButton
243
- icon="i-ph-plus"
244
- color="secondary"
245
- size="sm"
246
- button-class="p-3px! rounded-6px!"
247
- aria-label="Nova conversa"
248
- @click="startUngroupedConversation"
249
- />
250
- </div>
251
292
  <div
252
- v-if="row.type === 'group'"
253
- pl-12px pr-4px
254
- h-30px
293
+ v-for="row in block.rows"
294
+ :key="row.key"
295
+ :style="{ height: `${row.layoutHeight ?? row.height}px`, top: `${row.localOffset}px` }"
296
+ absolute inset-x-0
297
+ :data-row-index="row.index"
255
298
  rounded-8px
256
- class="group hover:bg-subtle"
257
- :data-active="row.groupBucket.open && !row.groupBucket.dropTarget"
299
+ :class="dropTargetClass(row)"
300
+ @keydown="handleRowKeydown($event, row.index)"
301
+ @focusin="retainedRowKey = row.key"
302
+ @pointerdown="retainedRowKey = row.key"
303
+ @dragstart.capture="draggedRowKey = row.key"
304
+ @dragend.capture="draggedRowKey = null"
305
+ v-on="dropListeners(row)"
258
306
  >
259
- <div flex items-center justify-between h-full gap-8px>
260
- <template v-if="row.groupBucket.isRenaming">
261
- <TelaIcon
262
- :name="row.groupBucket.folderIcon"
263
- size="16px"
264
- color="icon-secondary"
265
- shrink-0
307
+ <div v-if="row.type === 'folders'" h-full flex items-center justify-between pl-12px pr-2px>
308
+ <span body-12-medium text-tertiary>
309
+ Pastas
310
+ </span>
311
+ <TelaIconButton
312
+ icon="i-ph-plus"
313
+ color="secondary"
314
+ size="sm"
315
+ button-class="p-3px! rounded-6px!"
316
+ aria-label="Nova pasta"
317
+ @click="createNewGroup"
318
+ />
319
+ </div>
320
+ <div v-else-if="row.type === 'ungrouped'" h-full flex items-center justify-between pl-12px pr-2px>
321
+ <span body-12-medium text-tertiary>
322
+ {{ ungroupedConversationLabel }}
323
+ </span>
324
+ <div flex items-center gap-2px>
325
+ <ChatConversationCreatorFilter />
326
+ <TelaIconButton
327
+ icon="i-ph-plus"
328
+ color="secondary"
329
+ size="sm"
330
+ button-class="p-3px! rounded-6px!"
331
+ aria-label="Nova conversa"
332
+ @click="startUngroupedConversation"
266
333
  />
267
- <div relative flex-1 min-w-0 flex items-center>
268
- <input
269
- :ref="(element) => setRenameGroupInputRef(element, row.groupBucket.group.id)"
270
- v-model="renameGroupName"
271
- type="text"
272
- autocomplete="off"
273
- maxlength="80"
274
- aria-label="Nome da pasta"
275
- w-full min-w-0
276
- bg-transparent border-none outline-none
277
- body-14-medium text-taupe-600
278
- p-0
279
- :disabled="groupActionLoading"
280
- @blur="handleRenameGroupBlur"
281
- @keydown.enter.prevent="submitRenameGroup"
282
- @keydown.escape.prevent.stop="cancelRenameGroup"
283
- @click.stop
284
- @dblclick.stop
285
- >
286
- <div
287
- aria-hidden="true"
288
- absolute inset-x-0 bottom--0.5px h-0.5px pointer-events-none
289
- :class="renameGroupError ? 'bg-red-500' : 'bg-border'"
290
- />
291
- </div>
292
- </template>
293
-
294
- <template v-else>
295
- <button
296
- type="button"
297
- h-full flex-1 min-w-0
298
- flex items-center gap-8px
299
- text-left
300
- cursor-pointer
301
- :aria-expanded="row.groupBucket.open"
302
- @click="toggleGroup(row.groupBucket.group.id)"
303
- >
334
+ </div>
335
+ </div>
336
+ <div
337
+ v-if="row.type === 'group'"
338
+ pl-12px pr-4px
339
+ h-30px
340
+ rounded-8px
341
+ class="group hover:bg-subtle"
342
+ :data-active="row.groupBucket.open && !row.groupBucket.dropTarget"
343
+ >
344
+ <div flex items-center justify-between h-full gap-8px>
345
+ <template v-if="row.groupBucket.isRenaming">
304
346
  <TelaIcon
305
347
  :name="row.groupBucket.folderIcon"
306
- size="16px"
307
- color="icon-tertiary"
348
+ size="18px"
349
+ color="icon-secondary"
308
350
  shrink-0
309
351
  />
310
- <span min-w-0 truncate body-14-medium text-taupe-700>
311
- {{ row.groupBucket.group.name }}
312
- </span>
313
- </button>
352
+ <div relative flex-1 min-w-0 flex items-center>
353
+ <input
354
+ :ref="(element) => setRenameGroupInputRef(element, row.groupBucket.group.id)"
355
+ v-model="renameGroupName"
356
+ type="text"
357
+ autocomplete="off"
358
+ maxlength="80"
359
+ aria-label="Nome da pasta"
360
+ w-full min-w-0
361
+ bg-transparent border-none outline-none
362
+ body-14-medium text-taupe-600
363
+ p-0
364
+ :disabled="groupActionLoading"
365
+ @blur="handleRenameGroupBlur"
366
+ @keydown.enter.prevent="submitRenameGroup"
367
+ @keydown.escape.prevent.stop="cancelRenameGroup"
368
+ @click.stop
369
+ @dblclick.stop
370
+ >
371
+ <div
372
+ aria-hidden="true"
373
+ absolute inset-x-0 bottom--0.5px h-0.5px pointer-events-none
374
+ :class="renameGroupError ? 'bg-red-500' : 'bg-border'"
375
+ />
376
+ </div>
377
+ </template>
314
378
 
315
- <div
316
- flex items-center
317
- class="opacity-0 group-hover:opacity-100 focus-within:opacity-100 [&:has([data-state=open])]:opacity-100"
318
- >
319
- <TelaDropdownMenu
320
- :items="row.groupBucket.menuItems"
321
- content-class="chat-sidebar-floating"
379
+ <template v-else>
380
+ <button
381
+ type="button"
382
+ h-full flex-1 min-w-0
383
+ flex items-center gap-8px
384
+ text-left
385
+ cursor-pointer
386
+ :aria-expanded="row.groupBucket.open"
387
+ @click="handleToggleGroup(row.groupBucket.group.id)"
322
388
  >
323
- <TelaIconButton
324
- icon="i-ph-dots-three"
325
- color="secondary"
326
- size="3xs"
327
- aria-label="Ações da pasta"
328
- class="group hover:!bg-lowered data-[state=open]:!bg-lowered"
329
- icon-class="group-hover:icon-tertiary group-data-[state=open]:icon-tertiary"
330
- @click.prevent.stop
389
+ <TelaIcon
390
+ :name="row.groupBucket.folderIcon"
391
+ size="16px"
392
+ color="icon-tertiary"
393
+ shrink-0
331
394
  />
332
- </TelaDropdownMenu>
333
- </div>
334
- </template>
395
+ <span min-w-0 truncate body-14-medium text-taupe-700>
396
+ {{ row.groupBucket.group.name }}
397
+ </span>
398
+ </button>
399
+
400
+ <div
401
+ flex items-center
402
+ class="opacity-0 group-hover:opacity-100 focus-within:opacity-100 [&:has([data-state=open])]:opacity-100"
403
+ >
404
+ <TelaDropdownMenu
405
+ :items="row.groupBucket.menuItems"
406
+ content-class="chat-sidebar-floating"
407
+ >
408
+ <TelaIconButton
409
+ icon="i-ph-dots-three"
410
+ color="secondary"
411
+ size="3xs"
412
+ aria-label="Ações da pasta"
413
+ class="group hover:!bg-lowered data-[state=open]:!bg-lowered"
414
+ icon-class="group-hover:icon-tertiary group-data-[state=open]:icon-tertiary"
415
+ @click.prevent.stop
416
+ />
417
+ </TelaDropdownMenu>
418
+ </div>
419
+ </template>
420
+ </div>
335
421
  </div>
336
- </div>
337
422
 
338
- <div v-if="row.type === 'error'" ml-44px mr-8px>
339
- <span block truncate text-12px text-red-600 leading-16px aria-live="polite" :title="renameGroupError ?? void 0">
340
- {{ renameGroupError }}
341
- </span>
342
- </div>
343
- <ChatConversationItem
344
- v-if="row.type === 'conversation'"
345
- v-bind="getConversationItemProps(row.conversation)"
346
- :item-class="row.groupId ? 'ml-24px' : void 0"
347
- @delete="handleDelete"
348
- @rename="handleRename"
349
- @duplicate="handleDuplicate"
350
- @export="handleExport"
351
- @drag-start="handleConversationDragStart"
352
- @drag-end="clearDragState"
353
- />
354
- <button
355
- v-if="row.type === 'new'"
356
- type="button"
357
- relative h-30px pl-12px w-full
358
- flex items-center justify-between
359
- rounded-8px
360
- text-left
361
- hover:bg-subtle
362
- cursor-pointer
363
- @click="startConversationInGroup(row.groupBucket.group.id)"
364
- >
365
- <span body-14-medium text-taupe-500 ml-24px>
366
- Nova conversa
367
- </span>
368
- </button>
369
- <div v-if="row.type === 'empty'" h-full flex items-center ml-36px>
370
- <span body-14-medium text-tertiary>Sem resultados</span>
423
+ <div v-if="row.type === 'error'" ml-44px mr-8px>
424
+ <span block truncate text-12px text-red-600 leading-16px aria-live="polite" :title="renameGroupError ?? void 0">
425
+ {{ renameGroupError }}
426
+ </span>
427
+ </div>
428
+ <ChatConversationItem
429
+ v-if="row.type === 'conversation'"
430
+ v-bind="getConversationItemProps(row.conversation)"
431
+ :item-class="row.groupId ? 'ml-24px' : void 0"
432
+ @delete="handleDelete"
433
+ @rename="handleRename"
434
+ @duplicate="handleDuplicate"
435
+ @export="handleExport"
436
+ @drag-start="handleConversationDragStart"
437
+ @drag-end="clearDragState"
438
+ />
439
+ <button
440
+ v-if="row.type === 'new'"
441
+ type="button"
442
+ relative h-30px pl-12px w-full
443
+ flex items-center justify-between
444
+ rounded-8px
445
+ text-left
446
+ hover:bg-subtle
447
+ cursor-pointer
448
+ @click="startConversationInGroup(row.groupBucket.group.id)"
449
+ >
450
+ <span body-14-medium text-taupe-500 ml-24px>
451
+ Nova conversa
452
+ </span>
453
+ </button>
454
+ <div v-if="row.type === 'empty'" h-full flex items-center ml-36px>
455
+ <span body-14-medium text-tertiary>Sem resultados</span>
456
+ </div>
457
+ <div
458
+ v-if="isNestedRow(row)"
459
+ aria-hidden="true"
460
+ absolute top-0 left-19px w-0.5px bg-border pointer-events-none
461
+ :class="isLastNestedRow(row.index) ? 'h-30px' : 'h-full'"
462
+ />
371
463
  </div>
372
- <div
373
- v-if="isNestedRow(row)"
374
- aria-hidden="true"
375
- absolute top-0 left-19px w-0.5px bg-border pointer-events-none
376
- :class="isLastNestedRow(row.index) ? 'h-30px' : 'h-full'"
377
- />
378
464
  </div>
379
465
  </div>
380
466
  </div>
@@ -8,6 +8,8 @@ type __VLS_Props = {
8
8
  conversationId?: string | null;
9
9
  conversationEvents?: readonly ConversationEvent[] | null;
10
10
  composerDisabled?: boolean;
11
+ /** Keeps typing available while sending waits for the agent protocol to be confirmed. */
12
+ sendBlocked?: boolean;
11
13
  initialConversationId?: string | null;
12
14
  hideSidebar?: boolean;
13
15
  sidebar?: ChatSidebarConfig;
@@ -17,21 +19,29 @@ type __VLS_Props = {
17
19
  user?: EmbedUser | null;
18
20
  features?: Partial<ChatFeatureConfig>;
19
21
  };
20
- declare var __VLS_11: {}, __VLS_96: {
22
+ declare var __VLS_6: {}, __VLS_80: {}, __VLS_93: {
21
23
  message: useChatAuth;
22
- }, __VLS_127: {}, __VLS_129: {}, __VLS_210: {
24
+ }, __VLS_105: {}, __VLS_133: {}, __VLS_142: {}, __VLS_206: {}, __VLS_225: {
23
25
  message: useChatAuth;
24
- };
26
+ }, __VLS_237: {};
25
27
  type __VLS_Slots = {} & {
26
- 'sidebar-bottom'?: (props: typeof __VLS_11) => any;
28
+ 'sidebar-bottom'?: (props: typeof __VLS_6) => any;
29
+ } & {
30
+ 'composer-bottom'?: (props: typeof __VLS_80) => any;
31
+ } & {
32
+ 'failed-message-actions'?: (props: typeof __VLS_93) => any;
33
+ } & {
34
+ 'composer-bottom'?: (props: typeof __VLS_105) => any;
35
+ } & {
36
+ 'topbar-leading'?: (props: typeof __VLS_133) => any;
27
37
  } & {
28
- 'failed-message-actions'?: (props: typeof __VLS_96) => any;
38
+ 'topbar-leading'?: (props: typeof __VLS_142) => any;
29
39
  } & {
30
- 'topbar-leading'?: (props: typeof __VLS_127) => any;
40
+ 'composer-bottom'?: (props: typeof __VLS_206) => any;
31
41
  } & {
32
- 'topbar-leading'?: (props: typeof __VLS_129) => any;
42
+ 'failed-message-actions'?: (props: typeof __VLS_225) => any;
33
43
  } & {
34
- 'failed-message-actions'?: (props: typeof __VLS_210) => any;
44
+ 'composer-bottom'?: (props: typeof __VLS_237) => any;
35
45
  };
36
46
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
37
47
  "update:conversationId": (value: string | null) => any;