@meistrari/chat-nuxt 4.4.0-rc.9 → 4.4.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.
- package/dist/module.json +1 -1
- package/dist/module.mjs +5 -0
- package/dist/runtime/conversations/components/chat-conversation-item.vue +50 -69
- package/dist/runtime/conversations/components/chat-conversation-list.vue +84 -61
- package/dist/runtime/conversations/composables/conversation-item.js +4 -0
- package/dist/runtime/conversations/composables/conversation-list.d.ts +2 -0
- package/dist/runtime/conversations/composables/conversation-list.js +33 -4
- package/dist/runtime/embed/components/chat-embed-inner.d.vue.ts +6 -2
- package/dist/runtime/embed/components/chat-embed-inner.vue +13 -2
- package/dist/runtime/embed/components/chat-embed-inner.vue.d.ts +6 -2
- package/dist/runtime/embed/components/chat-embed.d.vue.ts +4 -2
- package/dist/runtime/embed/components/chat-embed.vue +3 -0
- package/dist/runtime/embed/components/chat-embed.vue.d.ts +4 -2
- package/dist/runtime/embed/components/chat-topbar.d.vue.ts +11 -1
- package/dist/runtime/embed/components/chat-topbar.vue +7 -8
- package/dist/runtime/embed/components/chat-topbar.vue.d.ts +11 -1
- package/dist/runtime/embed/components/configuration/chat-configuration-mobile-shell.d.vue.ts +2 -2
- package/dist/runtime/embed/components/configuration/chat-configuration-mobile-shell.vue.d.ts +2 -2
- package/dist/runtime/embed/components/meistrari-chat-embed.d.vue.ts +2 -0
- package/dist/runtime/embed/components/meistrari-chat-embed.vue +3 -0
- package/dist/runtime/embed/components/meistrari-chat-embed.vue.d.ts +2 -0
- package/dist/runtime/embed/components/mobile/chat-mobile-drawer.vue +0 -1
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.d.vue.ts +2 -2
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue.d.ts +2 -2
- package/dist/runtime/messages/components/chat-message-input.vue +148 -138
- package/dist/runtime/messages/components/chat-message-list.d.vue.ts +2 -2
- package/dist/runtime/messages/components/chat-message-list.vue +6 -10
- package/dist/runtime/messages/components/chat-message-list.vue.d.ts +2 -2
- package/dist/runtime/messages/components/chat-reasoning-effort-selector.vue +11 -7
- package/dist/runtime/messages/components/reasoning/chat-reasoning-thought.vue +1 -1
- package/dist/runtime/messages/components/reasoning/chat-thinking-indicator.d.vue.ts +4 -1
- package/dist/runtime/messages/components/reasoning/chat-thinking-indicator.vue +15 -3
- package/dist/runtime/messages/components/reasoning/chat-thinking-indicator.vue.d.ts +4 -1
- package/dist/runtime/rendering/components/app-markdown-render.d.vue.ts +2 -2
- package/dist/runtime/rendering/components/app-markdown-render.vue.d.ts +2 -2
- package/package.json +2 -2
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -190,7 +190,12 @@ const FULL_NAME_COMPONENT_DIRS = ["citations", "conversations", "embed", "files"
|
|
|
190
190
|
const PATH_PREFIX_COMPONENT_DIRS = ["rendering", "shared"];
|
|
191
191
|
const DYNAMIC_ICON_SAFELIST = [
|
|
192
192
|
"i-ph-folder-minus",
|
|
193
|
+
// Folder actions menu (conversation-list.ts).
|
|
194
|
+
"i-ph-folder-minus-bold",
|
|
193
195
|
"i-ph-folder-open",
|
|
196
|
+
// Sidebar folder rows build their icon name in conversation-list.ts.
|
|
197
|
+
"i-ph-folder-notch",
|
|
198
|
+
"i-ph-folder-notch-open",
|
|
194
199
|
// Neutral pill icon for host-defined user mentions (user-mentions.ts).
|
|
195
200
|
"i-ph-paperclip"
|
|
196
201
|
];
|
|
@@ -33,23 +33,37 @@ function setRenameInputRef(element) {
|
|
|
33
33
|
</script>
|
|
34
34
|
|
|
35
35
|
<template>
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
<a
|
|
37
|
+
:href="conversationPath"
|
|
38
|
+
:draggable="draggable && !isRenamingInline"
|
|
39
|
+
block
|
|
40
|
+
pl-12px pr-4px
|
|
41
|
+
h-30px
|
|
42
|
+
rounded-8px
|
|
43
|
+
class="group data-[active=true]:bg-muted data-[active=false]:hover:bg-subtle"
|
|
44
|
+
:class="isRenamingInline ? '' : 'cursor-pointer'"
|
|
45
|
+
:data-active="active"
|
|
46
|
+
@click="handleConversationClick"
|
|
47
|
+
@dblclick.prevent.stop="startRename"
|
|
48
|
+
@dragstart="handleConversationDragStart"
|
|
49
|
+
@dragend="handleConversationDragEnd"
|
|
42
50
|
>
|
|
43
|
-
<div flex items-center justify-between
|
|
44
|
-
|
|
51
|
+
<div flex items-center justify-between h-full :class="props.itemClass">
|
|
52
|
+
<!-- User Avatar -->
|
|
53
|
+
<div
|
|
54
|
+
v-if="userImage"
|
|
55
|
+
translate-x--48px w-0 opacity-0 shrink-0 overflow-hidden
|
|
56
|
+
class="[transition:width_0.26s_cubic-bezier(0.22,1,0.36,1),transform_0.26s_cubic-bezier(0.22,1,0.36,1),opacity_0.2s] group-hover:w-22px group-hover:translate-x-0 group-hover:opacity-100"
|
|
57
|
+
>
|
|
45
58
|
<TelaAvatar
|
|
46
59
|
:image="userImage"
|
|
47
60
|
alt="Usuário"
|
|
48
61
|
size="2xs"
|
|
62
|
+
class="rounded-full!"
|
|
49
63
|
/>
|
|
50
64
|
</div>
|
|
51
65
|
|
|
52
|
-
<div relative flex-1 min-w-0 flex items-center>
|
|
66
|
+
<div v-if="isRenamingInline" relative flex-1 min-w-0 flex items-center>
|
|
53
67
|
<input
|
|
54
68
|
:ref="setRenameInputRef"
|
|
55
69
|
v-model="renameTitle"
|
|
@@ -58,7 +72,7 @@ function setRenameInputRef(element) {
|
|
|
58
72
|
aria-label="Nome da conversa"
|
|
59
73
|
w-full min-w-0
|
|
60
74
|
bg-transparent border-none outline-none
|
|
61
|
-
body-14-medium text-
|
|
75
|
+
body-14-medium text-taupe-600
|
|
62
76
|
p-0
|
|
63
77
|
@blur="handleRenameBlur"
|
|
64
78
|
@keydown.enter.prevent="submitRename"
|
|
@@ -66,69 +80,36 @@ function setRenameInputRef(element) {
|
|
|
66
80
|
>
|
|
67
81
|
<div aria-hidden="true" absolute inset-x-0 bottom--0.5px h-0.5px bg-border pointer-events-none />
|
|
68
82
|
</div>
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
83
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
:data-active="active"
|
|
83
|
-
@click="handleConversationClick"
|
|
84
|
-
@dblclick.prevent.stop="startRename"
|
|
85
|
-
@dragstart="handleConversationDragStart"
|
|
86
|
-
@dragend="handleConversationDragEnd"
|
|
87
|
-
>
|
|
88
|
-
<div flex items-center justify-between gap-8px h-full :class="props.itemClass">
|
|
89
|
-
<!-- User Avatar -->
|
|
90
|
-
<div v-if="userImage" w-16px h-16px flex items-center justify-center rounded-full overflow-hidden flex-shrink-0>
|
|
91
|
-
<TelaAvatar
|
|
92
|
-
:image="userImage"
|
|
93
|
-
alt="Usuário"
|
|
94
|
-
size="2xs"
|
|
95
|
-
/>
|
|
96
|
-
</div>
|
|
84
|
+
<template v-else>
|
|
85
|
+
<div flex-1 min-w-0 flex items-center>
|
|
86
|
+
<span
|
|
87
|
+
body-14-medium
|
|
88
|
+
text-taupe-700
|
|
89
|
+
truncate
|
|
90
|
+
>
|
|
91
|
+
{{ displayTitle }}
|
|
92
|
+
</span>
|
|
93
|
+
</div>
|
|
97
94
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
class="group-hover:text-primary group-data-[active=true]:text-primary"
|
|
103
|
-
truncate
|
|
95
|
+
<div
|
|
96
|
+
flex
|
|
97
|
+
items-center
|
|
98
|
+
class="opacity-0 group-hover:opacity-100 focus-within:opacity-100 [&:has([data-state=open])]:opacity-100"
|
|
104
99
|
>
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
>
|
|
115
|
-
<TelaDropdownMenu :items="menuItems" content-class="chat-sidebar-floating">
|
|
116
|
-
<button
|
|
117
|
-
p-4px
|
|
118
|
-
rounded-8px
|
|
119
|
-
hover:bg-lowered
|
|
120
|
-
cursor-pointer
|
|
121
|
-
class="group data-[state=open]:!bg-lowered"
|
|
122
|
-
@click.prevent.stop
|
|
123
|
-
>
|
|
124
|
-
<TelaIcon
|
|
125
|
-
name="i-ph-dots-three"
|
|
126
|
-
size="18px"
|
|
127
|
-
color="icon-subtle group-hover:icon-tertiary group-data-[state=open]:icon-tertiary"
|
|
100
|
+
<TelaDropdownMenu :items="menuItems" content-class="chat-sidebar-floating">
|
|
101
|
+
<TelaIconButton
|
|
102
|
+
icon="i-ph-dots-three"
|
|
103
|
+
color="secondary"
|
|
104
|
+
size="3xs"
|
|
105
|
+
aria-label="Ações da conversa"
|
|
106
|
+
class="group hover:!bg-lowered data-[state=open]:!bg-lowered"
|
|
107
|
+
icon-class="group-hover:icon-tertiary group-data-[state=open]:icon-tertiary"
|
|
108
|
+
@click.prevent.stop
|
|
128
109
|
/>
|
|
129
|
-
</
|
|
130
|
-
</
|
|
131
|
-
</
|
|
110
|
+
</TelaDropdownMenu>
|
|
111
|
+
</div>
|
|
112
|
+
</template>
|
|
132
113
|
</div>
|
|
133
114
|
</a>
|
|
134
115
|
|
|
@@ -47,29 +47,37 @@ const {
|
|
|
47
47
|
handleDragLeave,
|
|
48
48
|
getConversationItemProps,
|
|
49
49
|
handleConversationDrop,
|
|
50
|
-
startConversationInGroup
|
|
50
|
+
startConversationInGroup,
|
|
51
|
+
startUngroupedConversation,
|
|
52
|
+
createNewGroup
|
|
51
53
|
} = useConversationList(props);
|
|
54
|
+
const ROW_HEIGHT = 32;
|
|
55
|
+
const HEADING_HEIGHT = 28;
|
|
56
|
+
const ERROR_ROW_HEIGHT = 20;
|
|
57
|
+
const SECTION_GAP = 10;
|
|
52
58
|
const rows = computed(() => {
|
|
53
59
|
const result = [];
|
|
54
60
|
if (groupItems.value.length > 0)
|
|
55
|
-
result.push({ type: "folders", key: "folders", height:
|
|
61
|
+
result.push({ type: "folders", key: "folders", height: HEADING_HEIGHT, groupId: null });
|
|
56
62
|
for (const groupBucket of groupItems.value) {
|
|
57
63
|
const groupId = groupBucket.group.id;
|
|
58
|
-
result.push({ type: "group", key: `group:${groupId}`, height:
|
|
64
|
+
result.push({ type: "group", key: `group:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
|
|
59
65
|
if (groupBucket.isRenaming && renameGroupError.value)
|
|
60
|
-
result.push({ type: "error", key: `error:${groupId}`, height:
|
|
66
|
+
result.push({ type: "error", key: `error:${groupId}`, height: ERROR_ROW_HEIGHT, groupId, groupBucket });
|
|
61
67
|
if (!groupBucket.open)
|
|
62
68
|
continue;
|
|
63
69
|
for (const conversation of groupBucket.items)
|
|
64
|
-
result.push({ type: "conversation", key: conversation.id, height:
|
|
70
|
+
result.push({ type: "conversation", key: conversation.id, height: ROW_HEIGHT, groupId, conversation });
|
|
65
71
|
if (groupBucket.showNewConversationAction)
|
|
66
|
-
result.push({ type: "new", key: `new:${groupId}`, height:
|
|
72
|
+
result.push({ type: "new", key: `new:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
|
|
67
73
|
else if (groupBucket.showSearchEmpty)
|
|
68
|
-
result.push({ type: "empty", key: `empty:${groupId}`, height:
|
|
74
|
+
result.push({ type: "empty", key: `empty:${groupId}`, height: ROW_HEIGHT, groupId, groupBucket });
|
|
69
75
|
}
|
|
70
|
-
|
|
76
|
+
if (groupItems.value.length > 0)
|
|
77
|
+
result.push({ type: "spacer", key: "spacer", height: SECTION_GAP, groupId: null });
|
|
78
|
+
result.push({ type: "ungrouped", key: "ungrouped", height: HEADING_HEIGHT, groupId: null });
|
|
71
79
|
for (const conversation of ungroupedConversations.value)
|
|
72
|
-
result.push({ type: "conversation", key: conversation.id, height:
|
|
80
|
+
result.push({ type: "conversation", key: conversation.id, height: ROW_HEIGHT, groupId: null, conversation });
|
|
73
81
|
let offset = 0;
|
|
74
82
|
return result.map((row) => {
|
|
75
83
|
const positionedRow = { ...row, offset };
|
|
@@ -117,7 +125,7 @@ async function handleRowKeydown(event, index) {
|
|
|
117
125
|
return;
|
|
118
126
|
const direction = event.shiftKey ? -1 : 1;
|
|
119
127
|
let nextIndex = index + direction;
|
|
120
|
-
while (rows.value[nextIndex] && ["folders", "ungrouped", "empty", "error"].includes(rows.value[nextIndex].type))
|
|
128
|
+
while (rows.value[nextIndex] && ["folders", "spacer", "ungrouped", "empty", "error"].includes(rows.value[nextIndex].type))
|
|
121
129
|
nextIndex += direction;
|
|
122
130
|
const nextRow = rows.value[nextIndex];
|
|
123
131
|
if (!nextRow)
|
|
@@ -132,7 +140,7 @@ async function handleRowKeydown(event, index) {
|
|
|
132
140
|
}
|
|
133
141
|
watch(conversationSearch, () => scrollTo(0), { flush: "post" });
|
|
134
142
|
function acceptsDrops(row) {
|
|
135
|
-
return row.type !== "folders";
|
|
143
|
+
return row.type !== "folders" && row.type !== "spacer";
|
|
136
144
|
}
|
|
137
145
|
function dropListeners(row) {
|
|
138
146
|
if (!acceptsDrops(row))
|
|
@@ -153,6 +161,13 @@ function dropListeners(row) {
|
|
|
153
161
|
}
|
|
154
162
|
};
|
|
155
163
|
}
|
|
164
|
+
function isNestedRow(row) {
|
|
165
|
+
return Boolean(row.groupId) && (row.type === "conversation" || row.type === "new" || row.type === "empty");
|
|
166
|
+
}
|
|
167
|
+
function isLastNestedRow(index) {
|
|
168
|
+
const next = rows.value[index + 1];
|
|
169
|
+
return !next || !isNestedRow(next) || next.groupId !== rows.value[index].groupId;
|
|
170
|
+
}
|
|
156
171
|
function dropTargetClass(row) {
|
|
157
172
|
if (!acceptsDrops(row))
|
|
158
173
|
return "";
|
|
@@ -163,10 +178,9 @@ function dropTargetClass(row) {
|
|
|
163
178
|
</script>
|
|
164
179
|
|
|
165
180
|
<template>
|
|
166
|
-
<div flex="~ col" gap-
|
|
167
|
-
<div px-8px
|
|
181
|
+
<div flex="~ col" gap-6px h-full min-h-0 overflow-hidden>
|
|
182
|
+
<div px-8px shrink-0>
|
|
168
183
|
<ChatConversationSearch v-model="conversationSearch" />
|
|
169
|
-
<ChatConversationCreatorFilter />
|
|
170
184
|
</div>
|
|
171
185
|
|
|
172
186
|
<div v-if="shouldShowSkeleton" flex="~ col" gap-4px>
|
|
@@ -208,19 +222,41 @@ function dropTargetClass(row) {
|
|
|
208
222
|
@dragend.capture="draggedRowKey = null"
|
|
209
223
|
v-on="dropListeners(row)"
|
|
210
224
|
>
|
|
211
|
-
<
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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>
|
|
217
251
|
<div
|
|
218
252
|
v-if="row.type === 'group'"
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
253
|
+
pl-12px pr-4px
|
|
254
|
+
h-30px
|
|
255
|
+
rounded-8px
|
|
256
|
+
class="group hover:bg-subtle"
|
|
257
|
+
:data-active="row.groupBucket.open && !row.groupBucket.dropTarget"
|
|
222
258
|
>
|
|
223
|
-
<div
|
|
259
|
+
<div flex items-center justify-between h-full gap-8px>
|
|
224
260
|
<template v-if="row.groupBucket.isRenaming">
|
|
225
261
|
<TelaIcon
|
|
226
262
|
:name="row.groupBucket.folderIcon"
|
|
@@ -228,11 +264,7 @@ function dropTargetClass(row) {
|
|
|
228
264
|
color="icon-secondary"
|
|
229
265
|
shrink-0
|
|
230
266
|
/>
|
|
231
|
-
<div
|
|
232
|
-
relative
|
|
233
|
-
flex-1 min-w-0 flex items-center
|
|
234
|
-
mr-4px
|
|
235
|
-
>
|
|
267
|
+
<div relative flex-1 min-w-0 flex items-center>
|
|
236
268
|
<input
|
|
237
269
|
:ref="(element) => setRenameGroupInputRef(element, row.groupBucket.group.id)"
|
|
238
270
|
v-model="renameGroupName"
|
|
@@ -242,7 +274,7 @@ function dropTargetClass(row) {
|
|
|
242
274
|
aria-label="Nome da pasta"
|
|
243
275
|
w-full min-w-0
|
|
244
276
|
bg-transparent border-none outline-none
|
|
245
|
-
body-14-medium text-
|
|
277
|
+
body-14-medium text-taupe-600
|
|
246
278
|
p-0
|
|
247
279
|
:disabled="groupActionLoading"
|
|
248
280
|
@blur="handleRenameGroupBlur"
|
|
@@ -253,7 +285,7 @@ function dropTargetClass(row) {
|
|
|
253
285
|
>
|
|
254
286
|
<div
|
|
255
287
|
aria-hidden="true"
|
|
256
|
-
absolute inset-x-0 bottom--
|
|
288
|
+
absolute inset-x-0 bottom--0.5px h-0.5px pointer-events-none
|
|
257
289
|
:class="renameGroupError ? 'bg-red-500' : 'bg-border'"
|
|
258
290
|
/>
|
|
259
291
|
</div>
|
|
@@ -272,41 +304,31 @@ function dropTargetClass(row) {
|
|
|
272
304
|
<TelaIcon
|
|
273
305
|
:name="row.groupBucket.folderIcon"
|
|
274
306
|
size="16px"
|
|
275
|
-
color="icon-
|
|
307
|
+
color="icon-tertiary"
|
|
276
308
|
shrink-0
|
|
277
309
|
/>
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
</span>
|
|
282
|
-
<TelaAnimatedNumber v-if="row.groupBucket.conversationCountLabel" :value="row.groupBucket.conversationCountLabel" body-12-medium text-tertiary />
|
|
283
|
-
</div>
|
|
310
|
+
<span min-w-0 truncate body-14-medium text-taupe-700>
|
|
311
|
+
{{ row.groupBucket.group.name }}
|
|
312
|
+
</span>
|
|
284
313
|
</button>
|
|
285
314
|
|
|
286
315
|
<div
|
|
287
|
-
flex items-center
|
|
316
|
+
flex items-center
|
|
288
317
|
class="opacity-0 group-hover:opacity-100 focus-within:opacity-100 [&:has([data-state=open])]:opacity-100"
|
|
289
318
|
>
|
|
290
319
|
<TelaDropdownMenu
|
|
291
320
|
:items="row.groupBucket.menuItems"
|
|
292
321
|
content-class="chat-sidebar-floating"
|
|
293
322
|
>
|
|
294
|
-
<
|
|
295
|
-
|
|
323
|
+
<TelaIconButton
|
|
324
|
+
icon="i-ph-dots-three"
|
|
325
|
+
color="secondary"
|
|
326
|
+
size="3xs"
|
|
296
327
|
aria-label="Ações da pasta"
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
hover:bg-lowered
|
|
300
|
-
cursor-pointer
|
|
301
|
-
class="group data-[state=open]:!bg-lowered"
|
|
328
|
+
class="group hover:!bg-lowered data-[state=open]:!bg-lowered"
|
|
329
|
+
icon-class="group-hover:icon-tertiary group-data-[state=open]:icon-tertiary"
|
|
302
330
|
@click.prevent.stop
|
|
303
|
-
|
|
304
|
-
<TelaIcon
|
|
305
|
-
name="i-ph-dots-three"
|
|
306
|
-
size="18px"
|
|
307
|
-
color="icon-subtle group-hover:icon-tertiary group-data-[state=open]:icon-tertiary"
|
|
308
|
-
/>
|
|
309
|
-
</button>
|
|
331
|
+
/>
|
|
310
332
|
</TelaDropdownMenu>
|
|
311
333
|
</div>
|
|
312
334
|
</template>
|
|
@@ -332,25 +354,26 @@ function dropTargetClass(row) {
|
|
|
332
354
|
<button
|
|
333
355
|
v-if="row.type === 'new'"
|
|
334
356
|
type="button"
|
|
335
|
-
h-
|
|
336
|
-
flex items-center
|
|
337
|
-
rounded-
|
|
357
|
+
relative h-30px pl-12px w-full
|
|
358
|
+
flex items-center justify-between
|
|
359
|
+
rounded-8px
|
|
338
360
|
text-left
|
|
339
361
|
hover:bg-subtle
|
|
340
362
|
cursor-pointer
|
|
341
363
|
@click="startConversationInGroup(row.groupBucket.group.id)"
|
|
342
364
|
>
|
|
343
|
-
<span body-14-medium text-
|
|
365
|
+
<span body-14-medium text-taupe-500 ml-24px>
|
|
344
366
|
Nova conversa
|
|
345
367
|
</span>
|
|
346
|
-
<TelaIcon name="i-ph-plus" size="14px" color="icon-secondary" shrink-0 />
|
|
347
368
|
</button>
|
|
348
|
-
<div v-if="row.type === 'empty'" h-
|
|
369
|
+
<div v-if="row.type === 'empty'" h-full flex items-center ml-36px>
|
|
349
370
|
<span body-14-medium text-tertiary>Sem resultados</span>
|
|
350
371
|
</div>
|
|
351
372
|
<div
|
|
352
|
-
v-if="
|
|
353
|
-
aria-hidden="true"
|
|
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'"
|
|
354
377
|
/>
|
|
355
378
|
</div>
|
|
356
379
|
</div>
|
|
@@ -55,6 +55,10 @@ export function useConversationItem(options, emit) {
|
|
|
55
55
|
showDeleteModal.value = false;
|
|
56
56
|
}
|
|
57
57
|
function handleConversationClick(event) {
|
|
58
|
+
if (isRenamingInline.value) {
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
58
62
|
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
|
59
63
|
return;
|
|
60
64
|
event.preventDefault();
|
|
@@ -123,4 +123,6 @@ export declare function useConversationList(options: ConversationListOptions): {
|
|
|
123
123
|
};
|
|
124
124
|
handleConversationDrop: (event: DragEvent, groupId: string | null) => Promise<void>;
|
|
125
125
|
startConversationInGroup: (groupId: string) => void;
|
|
126
|
+
startUngroupedConversation: () => void;
|
|
127
|
+
createNewGroup: () => Promise<void>;
|
|
126
128
|
};
|
|
@@ -15,7 +15,7 @@ export function useConversationList(options) {
|
|
|
15
15
|
const embedConfig = useEmbedConfig();
|
|
16
16
|
const { activeOrganization } = useChatAuth();
|
|
17
17
|
const { deleteConversation, renameConversation, duplicateConversation, moveConversationToGroup } = useConversations();
|
|
18
|
-
const { groups, fetchGroups, deleteGroup, renameGroup, error: groupError, pendingRenameGroupId } = useConversationGroups();
|
|
18
|
+
const { groups, fetchGroups, createGroup, deleteGroup, renameGroup, error: groupError, pendingRenameGroupId } = useConversationGroups();
|
|
19
19
|
const { setConversation } = useChat();
|
|
20
20
|
const route = useRoute();
|
|
21
21
|
const router = useRouter();
|
|
@@ -239,7 +239,7 @@ export function useConversationList(options) {
|
|
|
239
239
|
...groupBucket,
|
|
240
240
|
open,
|
|
241
241
|
dropTarget,
|
|
242
|
-
folderIcon: open ? "i-ph-folder-notch-open
|
|
242
|
+
folderIcon: open ? "i-ph-folder-notch-open" : "i-ph-folder-notch",
|
|
243
243
|
isRenaming: renamingGroupId.value === groupBucket.group.id,
|
|
244
244
|
conversationCountLabel: groupBucket.items.length > 0 ? String(groupBucket.items.length) : null,
|
|
245
245
|
showNewConversationAction: !hasConversationSearchQuery.value,
|
|
@@ -249,7 +249,7 @@ export function useConversationList(options) {
|
|
|
249
249
|
}));
|
|
250
250
|
const ungroupedConversations = computed(() => groupedConversations.value.unfiled);
|
|
251
251
|
const ungroupedDropTarget = computed(() => isDropTarget(null));
|
|
252
|
-
const ungroupedConversationLabel = computed(() => `Conversas
|
|
252
|
+
const ungroupedConversationLabel = computed(() => `Conversas`);
|
|
253
253
|
const shouldShowUngroupedHeader = computed(() => groupItems.value.length > 0);
|
|
254
254
|
const showGroupCreationPrompt = computed(
|
|
255
255
|
() => groupsReady.value && !hasConversationSearchQuery.value && groups.value.length === 0
|
|
@@ -496,6 +496,33 @@ export function useConversationList(options) {
|
|
|
496
496
|
return;
|
|
497
497
|
await moveConversationToGroup(conversationId, groupId);
|
|
498
498
|
}
|
|
499
|
+
const DEFAULT_GROUP_NAME = "Nova pasta";
|
|
500
|
+
const isCreatingGroup = ref(false);
|
|
501
|
+
function nextGroupName() {
|
|
502
|
+
const names = new Set(groups.value.map((group) => group.name));
|
|
503
|
+
if (!names.has(DEFAULT_GROUP_NAME))
|
|
504
|
+
return DEFAULT_GROUP_NAME;
|
|
505
|
+
let index = 2;
|
|
506
|
+
while (names.has(`${DEFAULT_GROUP_NAME} ${index}`))
|
|
507
|
+
index += 1;
|
|
508
|
+
return `${DEFAULT_GROUP_NAME} ${index}`;
|
|
509
|
+
}
|
|
510
|
+
async function createNewGroup() {
|
|
511
|
+
if (isCreatingGroup.value)
|
|
512
|
+
return;
|
|
513
|
+
isCreatingGroup.value = true;
|
|
514
|
+
const group = await createGroup(nextGroupName());
|
|
515
|
+
isCreatingGroup.value = false;
|
|
516
|
+
if (group)
|
|
517
|
+
pendingRenameGroupId.value = group.id;
|
|
518
|
+
}
|
|
519
|
+
function startUngroupedConversation() {
|
|
520
|
+
if (options.startConversation) {
|
|
521
|
+
void options.startConversation(null);
|
|
522
|
+
} else if (options.resetConversation) {
|
|
523
|
+
void options.resetConversation();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
499
526
|
function startConversationInGroup(groupId) {
|
|
500
527
|
setGroupOpen(groupId, true);
|
|
501
528
|
if (options.startConversation) {
|
|
@@ -562,6 +589,8 @@ export function useConversationList(options) {
|
|
|
562
589
|
isDropTarget,
|
|
563
590
|
getConversationItemProps,
|
|
564
591
|
handleConversationDrop,
|
|
565
|
-
startConversationInGroup
|
|
592
|
+
startConversationInGroup,
|
|
593
|
+
startUngroupedConversation,
|
|
594
|
+
createNewGroup
|
|
566
595
|
};
|
|
567
596
|
}
|
|
@@ -19,7 +19,7 @@ type __VLS_Props = {
|
|
|
19
19
|
};
|
|
20
20
|
declare var __VLS_11: {}, __VLS_96: {
|
|
21
21
|
message: useChatAuth;
|
|
22
|
-
},
|
|
22
|
+
}, __VLS_127: {}, __VLS_129: {}, __VLS_210: {
|
|
23
23
|
message: useChatAuth;
|
|
24
24
|
};
|
|
25
25
|
type __VLS_Slots = {} & {
|
|
@@ -27,7 +27,11 @@ type __VLS_Slots = {} & {
|
|
|
27
27
|
} & {
|
|
28
28
|
'failed-message-actions'?: (props: typeof __VLS_96) => any;
|
|
29
29
|
} & {
|
|
30
|
-
'
|
|
30
|
+
'topbar-leading'?: (props: typeof __VLS_127) => any;
|
|
31
|
+
} & {
|
|
32
|
+
'topbar-leading'?: (props: typeof __VLS_129) => any;
|
|
33
|
+
} & {
|
|
34
|
+
'failed-message-actions'?: (props: typeof __VLS_210) => any;
|
|
31
35
|
};
|
|
32
36
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
33
37
|
"update:conversationId": (value: string | null) => any;
|
|
@@ -888,7 +888,7 @@ async function handleDelete() {
|
|
|
888
888
|
</script>
|
|
889
889
|
|
|
890
890
|
<template>
|
|
891
|
-
<div ref="dropZoneRef" h-full flex bg
|
|
891
|
+
<div ref="dropZoneRef" h-full flex bg relative>
|
|
892
892
|
<div
|
|
893
893
|
v-if="chatError"
|
|
894
894
|
role="alert"
|
|
@@ -1205,7 +1205,18 @@ async function handleDelete() {
|
|
|
1205
1205
|
@debug="showDebugModal = true"
|
|
1206
1206
|
@delete="showDeleteModal = true"
|
|
1207
1207
|
@tab-change="handleTabChange"
|
|
1208
|
-
|
|
1208
|
+
>
|
|
1209
|
+
<template v-if="$slots['topbar-leading']" #leading>
|
|
1210
|
+
<slot name="topbar-leading" />
|
|
1211
|
+
</template>
|
|
1212
|
+
</ChatTopbar>
|
|
1213
|
+
<div
|
|
1214
|
+
v-else-if="$slots['topbar-leading'] && !isMobile && !compact"
|
|
1215
|
+
absolute top-0 z-10 h-56px flex items-center pl-16px
|
|
1216
|
+
:style="{ left: 'var(--chat-panel-offset)' }"
|
|
1217
|
+
>
|
|
1218
|
+
<slot name="topbar-leading" />
|
|
1219
|
+
</div>
|
|
1209
1220
|
|
|
1210
1221
|
<div
|
|
1211
1222
|
v-if="!isMobile && showOutdatedBanner"
|
|
@@ -19,7 +19,7 @@ type __VLS_Props = {
|
|
|
19
19
|
};
|
|
20
20
|
declare var __VLS_11: {}, __VLS_96: {
|
|
21
21
|
message: useChatAuth;
|
|
22
|
-
},
|
|
22
|
+
}, __VLS_127: {}, __VLS_129: {}, __VLS_210: {
|
|
23
23
|
message: useChatAuth;
|
|
24
24
|
};
|
|
25
25
|
type __VLS_Slots = {} & {
|
|
@@ -27,7 +27,11 @@ type __VLS_Slots = {} & {
|
|
|
27
27
|
} & {
|
|
28
28
|
'failed-message-actions'?: (props: typeof __VLS_96) => any;
|
|
29
29
|
} & {
|
|
30
|
-
'
|
|
30
|
+
'topbar-leading'?: (props: typeof __VLS_127) => any;
|
|
31
|
+
} & {
|
|
32
|
+
'topbar-leading'?: (props: typeof __VLS_129) => any;
|
|
33
|
+
} & {
|
|
34
|
+
'failed-message-actions'?: (props: typeof __VLS_210) => any;
|
|
31
35
|
};
|
|
32
36
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
33
37
|
"update:conversationId": (value: string | null) => any;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
declare var __VLS_26: {}, __VLS_29: any;
|
|
1
|
+
declare var __VLS_26: {}, __VLS_29: {}, __VLS_32: any;
|
|
2
2
|
type __VLS_Slots = {} & {
|
|
3
3
|
'sidebar-bottom'?: (props: typeof __VLS_26) => any;
|
|
4
4
|
} & {
|
|
5
|
-
'
|
|
5
|
+
'topbar-leading'?: (props: typeof __VLS_29) => any;
|
|
6
|
+
} & {
|
|
7
|
+
'failed-message-actions'?: (props: typeof __VLS_32) => any;
|
|
6
8
|
};
|
|
7
9
|
declare const __VLS_base: import("vue").DefineSetupFnComponent<Record<string, any>, {}, {}, Record<string, any> & {}, import("vue").PublicProps>;
|
|
8
10
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -173,6 +173,9 @@ provideChatMessageTerminal((payload) => {
|
|
|
173
173
|
<template v-if="$slots['sidebar-bottom']" #sidebar-bottom>
|
|
174
174
|
<slot name="sidebar-bottom" />
|
|
175
175
|
</template>
|
|
176
|
+
<template v-if="$slots['topbar-leading']" #topbar-leading>
|
|
177
|
+
<slot name="topbar-leading" />
|
|
178
|
+
</template>
|
|
176
179
|
<template v-if="$slots['failed-message-actions']" #failed-message-actions="slotProps">
|
|
177
180
|
<slot name="failed-message-actions" v-bind="slotProps" />
|
|
178
181
|
</template>
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
declare var __VLS_26: {}, __VLS_29: any;
|
|
1
|
+
declare var __VLS_26: {}, __VLS_29: {}, __VLS_32: any;
|
|
2
2
|
type __VLS_Slots = {} & {
|
|
3
3
|
'sidebar-bottom'?: (props: typeof __VLS_26) => any;
|
|
4
4
|
} & {
|
|
5
|
-
'
|
|
5
|
+
'topbar-leading'?: (props: typeof __VLS_29) => any;
|
|
6
|
+
} & {
|
|
7
|
+
'failed-message-actions'?: (props: typeof __VLS_32) => any;
|
|
6
8
|
};
|
|
7
9
|
declare const __VLS_base: import("vue").DefineSetupFnComponent<Record<string, any>, {}, {}, Record<string, any> & {}, import("vue").PublicProps>;
|
|
8
10
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|