@meistrari/chat-nuxt 1.7.0 → 1.8.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 +2 -0
- package/dist/runtime/components/MeistrariChatEmbed.vue +5 -1
- package/dist/runtime/components/chat/bash-widget.vue +3 -3
- package/dist/runtime/components/chat/doc-sdk-widget.vue +3 -3
- package/dist/runtime/components/chat/files-view.vue +3 -64
- package/dist/runtime/components/chat/generic-tool-widget.vue +3 -3
- package/dist/runtime/components/chat/grep-widget.vue +3 -3
- package/dist/runtime/components/chat/message-bubble.vue +1 -1
- package/dist/runtime/components/chat/message-input.d.vue.ts +2 -0
- package/dist/runtime/components/chat/message-input.vue +21 -5
- package/dist/runtime/components/chat/message-input.vue.d.ts +2 -0
- package/dist/runtime/components/chat/message-list.vue +1 -1
- package/dist/runtime/components/chat/mobile/files/file-preview.d.vue.ts +11 -0
- package/dist/runtime/components/chat/mobile/files/file-preview.vue +112 -0
- package/dist/runtime/components/chat/mobile/files/file-preview.vue.d.ts +11 -0
- package/dist/runtime/components/chat/mobile/files/files-view.d.vue.ts +10 -0
- package/dist/runtime/components/chat/mobile/files/files-view.vue +384 -0
- package/dist/runtime/components/chat/mobile/files/files-view.vue.d.ts +10 -0
- package/dist/runtime/components/chat/mobile/home/header.d.vue.ts +19 -0
- package/dist/runtime/components/chat/mobile/home/header.vue +55 -0
- package/dist/runtime/components/chat/mobile/home/header.vue.d.ts +19 -0
- package/dist/runtime/components/chat/mobile/home/recents.d.vue.ts +14 -0
- package/dist/runtime/components/chat/mobile/home/recents.vue +48 -0
- package/dist/runtime/components/chat/mobile/home/recents.vue.d.ts +14 -0
- package/dist/runtime/components/chat/mobile/home/suggestions.d.vue.ts +7 -0
- package/dist/runtime/components/chat/mobile/home/suggestions.vue +31 -0
- package/dist/runtime/components/chat/mobile/home/suggestions.vue.d.ts +7 -0
- package/dist/runtime/components/chat/mobile/primitives/bottom-sheet.d.vue.ts +21 -0
- package/dist/runtime/components/chat/mobile/primitives/bottom-sheet.vue +48 -0
- package/dist/runtime/components/chat/mobile/primitives/bottom-sheet.vue.d.ts +21 -0
- package/dist/runtime/components/chat/mobile/primitives/info-bubble.d.vue.ts +6 -0
- package/dist/runtime/components/chat/mobile/primitives/info-bubble.vue +50 -0
- package/dist/runtime/components/chat/mobile/primitives/info-bubble.vue.d.ts +6 -0
- package/dist/runtime/components/chat/mobile/shell/drawer.d.vue.ts +22 -0
- package/dist/runtime/components/chat/mobile/shell/drawer.vue +143 -0
- package/dist/runtime/components/chat/mobile/shell/drawer.vue.d.ts +22 -0
- package/dist/runtime/components/chat/mobile/shell/header.d.vue.ts +40 -0
- package/dist/runtime/components/chat/mobile/shell/header.vue +139 -0
- package/dist/runtime/components/chat/mobile/shell/header.vue.d.ts +40 -0
- package/dist/runtime/components/chat/mobile/shell/outdated-settings-sheet.d.vue.ts +14 -0
- package/dist/runtime/components/chat/mobile/shell/outdated-settings-sheet.vue +47 -0
- package/dist/runtime/components/chat/mobile/shell/outdated-settings-sheet.vue.d.ts +14 -0
- package/dist/runtime/components/chat/mobile/shell/shell.d.vue.ts +122 -0
- package/dist/runtime/components/chat/mobile/shell/shell.vue +283 -0
- package/dist/runtime/components/chat/mobile/shell/shell.vue.d.ts +122 -0
- package/dist/runtime/components/chat/mobile/shell/workspace-sheet.d.vue.ts +19 -0
- package/dist/runtime/components/chat/mobile/shell/workspace-sheet.vue +51 -0
- package/dist/runtime/components/chat/mobile/shell/workspace-sheet.vue.d.ts +19 -0
- package/dist/runtime/components/chat/mobile/usage/usage-view.d.vue.ts +8 -0
- package/dist/runtime/components/chat/mobile/usage/usage-view.vue +243 -0
- package/dist/runtime/components/chat/mobile/usage/usage-view.vue.d.ts +8 -0
- package/dist/runtime/components/chat/model-selector.vue +6 -0
- package/dist/runtime/components/chat/read-widget.vue +3 -3
- package/dist/runtime/components/chat/reasoning-step-item.vue +1 -1
- package/dist/runtime/components/chat/reasoning-steps.vue +1 -1
- package/dist/runtime/components/chat/reasoning-thought.vue +2 -3
- package/dist/runtime/components/chat/tela-skill-widget.vue +3 -3
- package/dist/runtime/components/chat/thinking-widget.vue +3 -3
- package/dist/runtime/components/chat/usage-view.vue +20 -101
- package/dist/runtime/components/chat/web-search-widget.vue +3 -3
- package/dist/runtime/components/chat/workstation-query-widget.vue +6 -6
- package/dist/runtime/components/chat/write-widget.vue +3 -3
- package/dist/runtime/composables/useConversationFileDownloads.d.ts +6 -0
- package/dist/runtime/composables/useConversationFileDownloads.js +50 -0
- package/dist/runtime/composables/useConversationUsage.d.ts +13 -0
- package/dist/runtime/composables/useConversationUsage.js +121 -0
- package/dist/runtime/composables/useEmbedConfig.d.ts +2 -0
- package/dist/runtime/composables/useEmbedConfig.js +4 -0
- package/dist/runtime/composables/useMentionAutocomplete.d.ts +6 -0
- package/dist/runtime/composables/useMentionAutocomplete.js +71 -23
- package/dist/runtime/composables/useWorkspaceSwitchModal.d.ts +5 -0
- package/dist/runtime/composables/useWorkspaceSwitchModal.js +14 -0
- package/dist/runtime/embed/components/ChatConfigurationModal.vue +119 -13
- package/dist/runtime/embed/components/ChatEmbed.vue +4 -0
- package/dist/runtime/embed/components/ChatEmbedInner.d.vue.ts +2 -0
- package/dist/runtime/embed/components/ChatEmbedInner.vue +201 -11
- package/dist/runtime/embed/components/ChatEmbedInner.vue.d.ts +2 -0
- package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.d.vue.ts +34 -0
- package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.vue +95 -0
- package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.vue.d.ts +34 -0
- package/dist/runtime/server/api/conversations/[id]/messages/[messageId]/retry.post.js +3 -1
- package/dist/runtime/server/api/conversations/[id]/messages/index.get.js +29 -5
- package/dist/runtime/server/utils/conversation-message-sync.d.ts +8 -2
- package/dist/runtime/server/utils/conversation-message-sync.js +52 -6
- package/dist/runtime/types/chat-auth.d.ts +1 -0
- package/dist/runtime/types/embed.d.ts +2 -0
- package/dist/runtime/utils/breakpoints.d.ts +1 -0
- package/dist/runtime/utils/breakpoints.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { onKeyStroke } from "@vueuse/core";
|
|
3
|
+
const props = defineProps({
|
|
4
|
+
open: { type: Boolean, required: true },
|
|
5
|
+
title: { type: String, required: false }
|
|
6
|
+
});
|
|
7
|
+
const emit = defineEmits(["close"]);
|
|
8
|
+
onKeyStroke("Escape", () => {
|
|
9
|
+
if (props.open) {
|
|
10
|
+
emit("close");
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<Transition name="sheet-scrim">
|
|
17
|
+
<div
|
|
18
|
+
v-if="open"
|
|
19
|
+
class="sheet-scrim"
|
|
20
|
+
@click="emit('close')"
|
|
21
|
+
/>
|
|
22
|
+
</Transition>
|
|
23
|
+
|
|
24
|
+
<Transition name="sheet">
|
|
25
|
+
<div
|
|
26
|
+
v-if="open"
|
|
27
|
+
class="sheet"
|
|
28
|
+
role="dialog"
|
|
29
|
+
aria-modal="true"
|
|
30
|
+
>
|
|
31
|
+
<div class="sheet__grabber-area">
|
|
32
|
+
<div class="sheet__grabber" />
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div v-if="title" class="sheet__title-row">
|
|
36
|
+
<span class="sheet__title">{{ title }}</span>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div class="sheet__body">
|
|
40
|
+
<slot />
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</Transition>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<style scoped>
|
|
47
|
+
.sheet-scrim{background:rgba(0,0,0,.32);inset:0;position:absolute;z-index:40}.sheet-scrim-enter-active,.sheet-scrim-leave-active{transition:opacity .2s linear}.sheet-scrim-enter-from,.sheet-scrim-leave-to{opacity:0}.sheet{background:#fff;border-radius:18px 18px 0 0;bottom:0;box-shadow:0 3px 12px rgba(103,127,148,.08),0 12px 52px rgba(103,127,148,.16);display:flex;flex-direction:column;left:0;max-height:70%;position:absolute;right:0;z-index:41}.sheet-enter-active,.sheet-leave-active{transition:transform .26s cubic-bezier(.2,.8,.2,1)}.sheet-enter-from,.sheet-leave-to{transform:translateY(100%)}.sheet__grabber-area{display:flex;justify-content:center;padding:8px 0 4px}.sheet__grabber{background:#e8e8e8;border-radius:999px;height:4px;width:36px}.sheet__title-row{border-bottom:.5px solid #f5f5f5;padding:4px 16px 10px}.sheet__title{color:#171717;font-size:16px;font-weight:500;letter-spacing:-.2px;line-height:20px}.sheet__body{flex:1;overflow-y:auto;padding:4px 0 8px}
|
|
48
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
title?: string;
|
|
4
|
+
};
|
|
5
|
+
declare var __VLS_13: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_13) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
10
|
+
close: () => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
onClose?: (() => any) | undefined;
|
|
13
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
18
|
+
new (): {
|
|
19
|
+
$slots: S;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
text: string;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
5
|
+
declare const _default: typeof __VLS_export;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { onClickOutside, onKeyStroke } from "@vueuse/core";
|
|
3
|
+
defineProps({
|
|
4
|
+
text: { type: String, required: true }
|
|
5
|
+
});
|
|
6
|
+
const open = ref(false);
|
|
7
|
+
const wrapper = ref(null);
|
|
8
|
+
onClickOutside(wrapper, () => {
|
|
9
|
+
if (open.value) {
|
|
10
|
+
open.value = false;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
onKeyStroke("Escape", () => {
|
|
14
|
+
if (open.value) {
|
|
15
|
+
open.value = false;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
function toggle() {
|
|
19
|
+
open.value = !open.value;
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<span ref="wrapper" class="info-wrapper">
|
|
25
|
+
<button
|
|
26
|
+
type="button"
|
|
27
|
+
class="info-trigger"
|
|
28
|
+
aria-label="Mais informações"
|
|
29
|
+
:aria-expanded="open"
|
|
30
|
+
@click.stop="toggle"
|
|
31
|
+
>
|
|
32
|
+
i
|
|
33
|
+
</button>
|
|
34
|
+
|
|
35
|
+
<Transition name="info">
|
|
36
|
+
<div
|
|
37
|
+
v-if="open"
|
|
38
|
+
role="tooltip"
|
|
39
|
+
class="info-tooltip"
|
|
40
|
+
@click.stop
|
|
41
|
+
>
|
|
42
|
+
{{ text }}
|
|
43
|
+
</div>
|
|
44
|
+
</Transition>
|
|
45
|
+
</span>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<style scoped>
|
|
49
|
+
.info-wrapper{margin-left:4px;position:relative}.info-trigger,.info-wrapper{align-items:center;display:inline-flex}.info-trigger{background:transparent;border:1px solid #a3a3a3;border-radius:14px;color:#a3a3a3;cursor:pointer;font-family:inherit;font-size:9px;font-style:normal;font-weight:600;height:14px;justify-content:center;line-height:1;width:14px}.info-trigger[aria-expanded=true]{border-color:#171717;color:#171717}.info-tooltip{background:#171717;border-radius:8px;box-shadow:0 3px 12px rgba(103,127,148,.08);color:#fff;font-size:12px;font-weight:400;left:50%;line-height:1.4;padding:8px 10px;position:absolute;text-align:left;top:20px;transform:translateX(-50%);width:200px;z-index:5}.info-enter-active,.info-leave-active{transition:opacity .12s,transform .12s}.info-enter-from,.info-leave-to{opacity:0;transform:translateX(-50%) translateY(-2px)}
|
|
50
|
+
</style>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
text: string;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
5
|
+
declare const _default: typeof __VLS_export;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DeepReadonly } from 'vue';
|
|
2
|
+
import type { Conversation } from '../../../../types/chat.js';
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
open: boolean;
|
|
5
|
+
conversations: DeepReadonly<Conversation[]>;
|
|
6
|
+
activeId: string | null;
|
|
7
|
+
loading?: boolean;
|
|
8
|
+
userName?: string;
|
|
9
|
+
userEmail?: string;
|
|
10
|
+
userImage?: string;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
13
|
+
select: (id: string) => any;
|
|
14
|
+
close: () => any;
|
|
15
|
+
newConvo: () => any;
|
|
16
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
|
+
onSelect?: ((id: string) => any) | undefined;
|
|
18
|
+
onClose?: (() => any) | undefined;
|
|
19
|
+
onNewConvo?: (() => any) | undefined;
|
|
20
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { formatRelativeTime } from "../../../../utils/format-time";
|
|
3
|
+
import { conversationListSkeletonRows } from "../../../../utils/conversation-list-skeleton";
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
open: { type: Boolean, required: true },
|
|
6
|
+
conversations: { type: null, required: true },
|
|
7
|
+
activeId: { type: [String, null], required: true },
|
|
8
|
+
loading: { type: Boolean, required: false },
|
|
9
|
+
userName: { type: String, required: false },
|
|
10
|
+
userEmail: { type: String, required: false },
|
|
11
|
+
userImage: { type: String, required: false }
|
|
12
|
+
});
|
|
13
|
+
const emit = defineEmits(["close", "select", "newConvo"]);
|
|
14
|
+
const initial = computed(() => {
|
|
15
|
+
const source = props.userName ?? props.userEmail ?? "U";
|
|
16
|
+
return source.charAt(0).toUpperCase();
|
|
17
|
+
});
|
|
18
|
+
function handleSelect(id) {
|
|
19
|
+
emit("select", id);
|
|
20
|
+
emit("close");
|
|
21
|
+
}
|
|
22
|
+
function handleNew() {
|
|
23
|
+
emit("newConvo");
|
|
24
|
+
emit("close");
|
|
25
|
+
}
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<template>
|
|
29
|
+
<Transition name="scrim">
|
|
30
|
+
<div
|
|
31
|
+
v-if="open"
|
|
32
|
+
absolute inset-0 z-30
|
|
33
|
+
bg="black/32"
|
|
34
|
+
@click="emit('close')"
|
|
35
|
+
/>
|
|
36
|
+
</Transition>
|
|
37
|
+
|
|
38
|
+
<div
|
|
39
|
+
absolute top-0 bottom-0 left-0 z-31
|
|
40
|
+
flex="~ col"
|
|
41
|
+
bg-white
|
|
42
|
+
class="mobile-drawer"
|
|
43
|
+
:class="open ? 'mobile-drawer--open' : ''"
|
|
44
|
+
>
|
|
45
|
+
<div
|
|
46
|
+
flex items-center gap-8px
|
|
47
|
+
pt-14px pr-14px pb-14px pl-14px
|
|
48
|
+
b-b=".5px solid"
|
|
49
|
+
style="border-bottom-color: #F5F5F5"
|
|
50
|
+
>
|
|
51
|
+
<div w-28px h-28px rounded-full overflow-hidden flex-shrink-0>
|
|
52
|
+
<img
|
|
53
|
+
v-if="userImage"
|
|
54
|
+
:src="userImage"
|
|
55
|
+
:alt="userName ?? 'Usu\xE1rio'"
|
|
56
|
+
w-full h-full object-cover
|
|
57
|
+
>
|
|
58
|
+
<div v-else w-full h-full bg-purple-500 flex items-center justify-center>
|
|
59
|
+
<span text-12px text-white font-semibold>{{ initial }}</span>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
<span flex-1 text-14px font-580 text-neutral-900 truncate tracking="-.15px">
|
|
63
|
+
{{ userName ?? userEmail ?? "Usu\xE1rio" }}
|
|
64
|
+
</span>
|
|
65
|
+
<button
|
|
66
|
+
flex items-center justify-center
|
|
67
|
+
w-32px h-32px rounded-8px
|
|
68
|
+
class="hover:bg-neutral-100 active:scale-94"
|
|
69
|
+
transition-all
|
|
70
|
+
aria-label="Fechar menu"
|
|
71
|
+
@click="emit('close')"
|
|
72
|
+
>
|
|
73
|
+
<span i-ph-x text-18px text-neutral-700 />
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div p-12px>
|
|
78
|
+
<button
|
|
79
|
+
flex items-center justify-center gap-6px
|
|
80
|
+
w-full px-12px py-10px rounded-10px
|
|
81
|
+
bg-white b=".5px neutral-300" shadow-sm
|
|
82
|
+
class="hover:bg-neutral-50"
|
|
83
|
+
transition-colors cursor-pointer
|
|
84
|
+
@click="handleNew"
|
|
85
|
+
>
|
|
86
|
+
<span i-ph-chat-circle text-16px text-neutral-900 />
|
|
87
|
+
<span text-14px font-580 text-neutral-900 leading-18px tracking="-.15px">
|
|
88
|
+
Nova conversa
|
|
89
|
+
</span>
|
|
90
|
+
</button>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div px-14px pt-4px pb-4px>
|
|
94
|
+
<span
|
|
95
|
+
text-12px font-medium uppercase text-neutral-400
|
|
96
|
+
style="letter-spacing: 0.5px"
|
|
97
|
+
>
|
|
98
|
+
Recentes
|
|
99
|
+
</span>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div flex-1 overflow-y-auto px-8px pb-8px>
|
|
103
|
+
<div v-if="loading && conversations.length === 0" flex="~ col" gap-1px py-4px>
|
|
104
|
+
<div
|
|
105
|
+
v-for="row in conversationListSkeletonRows"
|
|
106
|
+
:key="row.id"
|
|
107
|
+
flex items-center h-44px px-12px rounded-10px
|
|
108
|
+
>
|
|
109
|
+
<TelaSkeleton rounded-6px bg-neutral-200 :style="{ width: row.width, height: '13px' }" />
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
<div v-else-if="conversations.length === 0" p-16px text-center>
|
|
113
|
+
<p text-14px text-neutral-400>
|
|
114
|
+
Nenhuma conversa ainda
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
<div v-else flex="~ col" gap-1px>
|
|
118
|
+
<button
|
|
119
|
+
v-for="conv in conversations"
|
|
120
|
+
:key="conv.id"
|
|
121
|
+
flex="~ col" gap-2px
|
|
122
|
+
w-full px-12px py-10px rounded-10px text-left
|
|
123
|
+
transition-colors cursor-pointer
|
|
124
|
+
:class="conv.id === activeId ? 'bg-neutral-100' : 'hover:bg-neutral-50'"
|
|
125
|
+
@click="handleSelect(conv.id)"
|
|
126
|
+
>
|
|
127
|
+
<div flex items-center gap-8px w-full>
|
|
128
|
+
<span flex-1 text-14px font-medium text-neutral-900 leading-18px truncate>
|
|
129
|
+
{{ conv.title || "Nova conversa" }}
|
|
130
|
+
</span>
|
|
131
|
+
<span text-12px text-neutral-400 leading-16px shrink-0>
|
|
132
|
+
{{ formatRelativeTime(conv.updatedAt) }}
|
|
133
|
+
</span>
|
|
134
|
+
</div>
|
|
135
|
+
</button>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</template>
|
|
140
|
+
|
|
141
|
+
<style scoped>
|
|
142
|
+
.mobile-drawer{box-shadow:0 3px 12px rgba(103,127,148,.08),0 12px 52px rgba(103,127,148,.16);transform:translateX(-100%);transition:transform .26s cubic-bezier(.2,.8,.2,1);width:82%}.mobile-drawer--open{transform:translateX(0)}.scrim-enter-active,.scrim-leave-active{transition:opacity .2s linear}.scrim-enter-from,.scrim-leave-to{opacity:0}
|
|
143
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DeepReadonly } from 'vue';
|
|
2
|
+
import type { Conversation } from '../../../../types/chat.js';
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
open: boolean;
|
|
5
|
+
conversations: DeepReadonly<Conversation[]>;
|
|
6
|
+
activeId: string | null;
|
|
7
|
+
loading?: boolean;
|
|
8
|
+
userName?: string;
|
|
9
|
+
userEmail?: string;
|
|
10
|
+
userImage?: string;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
13
|
+
select: (id: string) => any;
|
|
14
|
+
close: () => any;
|
|
15
|
+
newConvo: () => any;
|
|
16
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
|
+
onSelect?: ((id: string) => any) | undefined;
|
|
18
|
+
onClose?: (() => any) | undefined;
|
|
19
|
+
onNewConvo?: (() => any) | undefined;
|
|
20
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TopbarTab } from '../../../../types/chat.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
title: string;
|
|
4
|
+
creatorName?: string;
|
|
5
|
+
creatorEmail?: string;
|
|
6
|
+
creatorImage?: string;
|
|
7
|
+
updatedAt: string | Date;
|
|
8
|
+
generatingTitle?: boolean;
|
|
9
|
+
filesCount?: number;
|
|
10
|
+
activeTab?: TopbarTab;
|
|
11
|
+
showOutdatedBadge?: boolean;
|
|
12
|
+
showUsageTab?: boolean;
|
|
13
|
+
showDebugOption?: boolean;
|
|
14
|
+
showDrawerButton?: boolean;
|
|
15
|
+
};
|
|
16
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
17
|
+
delete: () => any;
|
|
18
|
+
rename: () => any;
|
|
19
|
+
duplicate: () => any;
|
|
20
|
+
export: () => any;
|
|
21
|
+
copyLink: () => any;
|
|
22
|
+
debug: () => any;
|
|
23
|
+
tabChange: (tab: TopbarTab) => any;
|
|
24
|
+
openDrawer: () => any;
|
|
25
|
+
openOutdatedSettings: () => any;
|
|
26
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
27
|
+
onDelete?: (() => any) | undefined;
|
|
28
|
+
onRename?: (() => any) | undefined;
|
|
29
|
+
onDuplicate?: (() => any) | undefined;
|
|
30
|
+
onExport?: (() => any) | undefined;
|
|
31
|
+
onCopyLink?: (() => any) | undefined;
|
|
32
|
+
onDebug?: (() => any) | undefined;
|
|
33
|
+
onTabChange?: ((tab: TopbarTab) => any) | undefined;
|
|
34
|
+
onOpenDrawer?: (() => any) | undefined;
|
|
35
|
+
onOpenOutdatedSettings?: (() => any) | undefined;
|
|
36
|
+
}>, {
|
|
37
|
+
showDrawerButton: boolean;
|
|
38
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
39
|
+
declare const _default: typeof __VLS_export;
|
|
40
|
+
export default _default;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { formatRelativeTime } from "../../../../utils/format-time";
|
|
3
|
+
import { capitalizeFirst } from "../../../../utils/string";
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
title: { type: String, required: true },
|
|
6
|
+
creatorName: { type: String, required: false },
|
|
7
|
+
creatorEmail: { type: String, required: false },
|
|
8
|
+
creatorImage: { type: String, required: false },
|
|
9
|
+
updatedAt: { type: [String, Date], required: true },
|
|
10
|
+
generatingTitle: { type: Boolean, required: false },
|
|
11
|
+
filesCount: { type: Number, required: false },
|
|
12
|
+
activeTab: { type: String, required: false },
|
|
13
|
+
showOutdatedBadge: { type: Boolean, required: false },
|
|
14
|
+
showUsageTab: { type: Boolean, required: false },
|
|
15
|
+
showDebugOption: { type: Boolean, required: false },
|
|
16
|
+
showDrawerButton: { type: Boolean, required: false, default: true }
|
|
17
|
+
});
|
|
18
|
+
const emit = defineEmits(["openDrawer", "openOutdatedSettings", "rename", "duplicate", "export", "copyLink", "debug", "delete", "tabChange"]);
|
|
19
|
+
const currentTab = computed(() => props.activeTab ?? "chat");
|
|
20
|
+
const tabItems = computed(() => {
|
|
21
|
+
const items = [
|
|
22
|
+
{ id: "chat", icon: "i-ph-chat-circle", label: "Chat" },
|
|
23
|
+
{ id: "files", icon: "i-ph-folder", label: "Arquivos" }
|
|
24
|
+
];
|
|
25
|
+
if (props.showUsageTab) {
|
|
26
|
+
items.push({ id: "usage", icon: "i-ph-chart-bar", label: "Uso" });
|
|
27
|
+
}
|
|
28
|
+
return items;
|
|
29
|
+
});
|
|
30
|
+
const headerMenuItems = computed(() => {
|
|
31
|
+
const items = [
|
|
32
|
+
{ label: "Renomear", icon: "i-ph-pencil-simple", click: () => emit("rename") },
|
|
33
|
+
{ label: "Duplicar", icon: "i-ph-copy", click: () => emit("duplicate") },
|
|
34
|
+
{ label: "Exportar", icon: "i-ph-download-simple", click: () => emit("export") },
|
|
35
|
+
{ label: "Copiar link", icon: "i-ph-link", click: () => emit("copyLink") }
|
|
36
|
+
];
|
|
37
|
+
if (props.showDebugOption) {
|
|
38
|
+
items.push({ label: "Debug", icon: "i-ph-bug", click: () => emit("debug") });
|
|
39
|
+
}
|
|
40
|
+
items.push({ label: "Excluir", icon: "i-ph-trash", color: "negative", click: () => emit("delete") });
|
|
41
|
+
return items;
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<div
|
|
47
|
+
flex items-center gap-8px
|
|
48
|
+
px-10px pt-10px pb-8px
|
|
49
|
+
b-b=".5px solid rgba(0,0,0,0.08)"
|
|
50
|
+
bg-white
|
|
51
|
+
absolute top-0 right-0 left-0 z-10
|
|
52
|
+
>
|
|
53
|
+
<button
|
|
54
|
+
v-if="showDrawerButton"
|
|
55
|
+
flex items-center justify-center
|
|
56
|
+
w-32px h-32px rounded-8px
|
|
57
|
+
class="hover:bg-neutral-100 active:scale-94"
|
|
58
|
+
transition-all
|
|
59
|
+
aria-label="Abrir menu"
|
|
60
|
+
@click="emit('openDrawer')"
|
|
61
|
+
>
|
|
62
|
+
<span i-ph-list text-20px text-neutral-700 />
|
|
63
|
+
</button>
|
|
64
|
+
|
|
65
|
+
<div flex="~ col 1" gap-2px min-w-0>
|
|
66
|
+
<p
|
|
67
|
+
text-14px font-580 text-neutral-900 leading-18px tracking="-.15px"
|
|
68
|
+
truncate
|
|
69
|
+
>
|
|
70
|
+
{{ capitalizeFirst(title) }}<span v-if="generatingTitle" class="typing-cursor">|</span>
|
|
71
|
+
</p>
|
|
72
|
+
<div flex items-center gap-4px text-11px text-secondary leading-14px truncate>
|
|
73
|
+
<div w-12px h-12px rounded-full overflow-hidden flex-shrink-0>
|
|
74
|
+
<img
|
|
75
|
+
v-if="creatorImage"
|
|
76
|
+
:src="creatorImage"
|
|
77
|
+
:alt="creatorName ?? 'Usu\xE1rio'"
|
|
78
|
+
w-full h-full object-cover
|
|
79
|
+
>
|
|
80
|
+
<div v-else w-full h-full bg-purple-500 flex items-center justify-center>
|
|
81
|
+
<span text-7px text-white font-semibold>
|
|
82
|
+
{{ (creatorName ?? creatorEmail ?? "U").charAt(0).toUpperCase() }}
|
|
83
|
+
</span>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
<span truncate>
|
|
87
|
+
{{ creatorName ?? creatorEmail ?? "Usu\xE1rio" }} · {{ formatRelativeTime(updatedAt) }}
|
|
88
|
+
</span>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<div
|
|
93
|
+
inline-flex items-center shrink-0
|
|
94
|
+
p-2px rounded-8px bg-neutral-100
|
|
95
|
+
>
|
|
96
|
+
<button
|
|
97
|
+
v-for="tab in tabItems"
|
|
98
|
+
:key="tab.id"
|
|
99
|
+
class="segmented-tab"
|
|
100
|
+
:class="{ 'segmented-tab--active': currentTab === tab.id }"
|
|
101
|
+
:aria-label="tab.label"
|
|
102
|
+
:title="tab.label"
|
|
103
|
+
@click="emit('tabChange', tab.id)"
|
|
104
|
+
>
|
|
105
|
+
<span :class="tab.icon" />
|
|
106
|
+
</button>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<button
|
|
110
|
+
v-if="showOutdatedBadge"
|
|
111
|
+
flex items-center justify-center shrink-0
|
|
112
|
+
w-28px h-28px rounded-8px
|
|
113
|
+
bg="#FFF1D8"
|
|
114
|
+
class="hover:bg-[#FFE9BE] active:scale-94"
|
|
115
|
+
transition-transform
|
|
116
|
+
aria-label="Configurações do workspace atualizadas"
|
|
117
|
+
title="Configurações do workspace atualizadas"
|
|
118
|
+
@click="emit('openOutdatedSettings')"
|
|
119
|
+
>
|
|
120
|
+
<span i-ph-warning text-14px text-neutral-800 />
|
|
121
|
+
</button>
|
|
122
|
+
|
|
123
|
+
<TelaDropdownMenu :items="headerMenuItems" align="end">
|
|
124
|
+
<button
|
|
125
|
+
flex items-center justify-center
|
|
126
|
+
w-32px h-32px rounded-8px
|
|
127
|
+
class="hover:bg-neutral-100"
|
|
128
|
+
transition-colors
|
|
129
|
+
aria-label="Mais opções"
|
|
130
|
+
>
|
|
131
|
+
<span i-ph-dots-three text-18px text-neutral-700 />
|
|
132
|
+
</button>
|
|
133
|
+
</TelaDropdownMenu>
|
|
134
|
+
</div>
|
|
135
|
+
</template>
|
|
136
|
+
|
|
137
|
+
<style scoped>
|
|
138
|
+
.segmented-tab{align-items:center;background:transparent;border:.5px solid transparent;border-radius:6px;box-sizing:border-box;color:#a3a3a3;display:inline-flex;font-size:16px;height:24px;justify-content:center;line-height:0;padding:0;transition:background .15s,border-color .15s,box-shadow .15s,color .15s;width:28px}.segmented-tab--active{background:#fff;border-color:rgba(0,0,0,.06);box-shadow:0 1px 2px rgba(64,64,64,.04);color:#171717}.typing-cursor{animation:blink .7s infinite;color:#6b7280;font-weight:400}@keyframes blink{0%,50%{opacity:1}51%,to{opacity:0}}
|
|
139
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TopbarTab } from '../../../../types/chat.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
title: string;
|
|
4
|
+
creatorName?: string;
|
|
5
|
+
creatorEmail?: string;
|
|
6
|
+
creatorImage?: string;
|
|
7
|
+
updatedAt: string | Date;
|
|
8
|
+
generatingTitle?: boolean;
|
|
9
|
+
filesCount?: number;
|
|
10
|
+
activeTab?: TopbarTab;
|
|
11
|
+
showOutdatedBadge?: boolean;
|
|
12
|
+
showUsageTab?: boolean;
|
|
13
|
+
showDebugOption?: boolean;
|
|
14
|
+
showDrawerButton?: boolean;
|
|
15
|
+
};
|
|
16
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
17
|
+
delete: () => any;
|
|
18
|
+
rename: () => any;
|
|
19
|
+
duplicate: () => any;
|
|
20
|
+
export: () => any;
|
|
21
|
+
copyLink: () => any;
|
|
22
|
+
debug: () => any;
|
|
23
|
+
tabChange: (tab: TopbarTab) => any;
|
|
24
|
+
openDrawer: () => any;
|
|
25
|
+
openOutdatedSettings: () => any;
|
|
26
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
27
|
+
onDelete?: (() => any) | undefined;
|
|
28
|
+
onRename?: (() => any) | undefined;
|
|
29
|
+
onDuplicate?: (() => any) | undefined;
|
|
30
|
+
onExport?: (() => any) | undefined;
|
|
31
|
+
onCopyLink?: (() => any) | undefined;
|
|
32
|
+
onDebug?: (() => any) | undefined;
|
|
33
|
+
onTabChange?: ((tab: TopbarTab) => any) | undefined;
|
|
34
|
+
onOpenDrawer?: (() => any) | undefined;
|
|
35
|
+
onOpenOutdatedSettings?: (() => any) | undefined;
|
|
36
|
+
}>, {
|
|
37
|
+
showDrawerButton: boolean;
|
|
38
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
39
|
+
declare const _default: typeof __VLS_export;
|
|
40
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
5
|
+
close: () => any;
|
|
6
|
+
dismiss: () => any;
|
|
7
|
+
newConversation: () => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
9
|
+
onClose?: (() => any) | undefined;
|
|
10
|
+
onDismiss?: (() => any) | undefined;
|
|
11
|
+
onNewConversation?: (() => any) | undefined;
|
|
12
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import ChatMobileBottomSheet from "../primitives/bottom-sheet.vue";
|
|
3
|
+
defineProps({
|
|
4
|
+
open: { type: Boolean, required: true }
|
|
5
|
+
});
|
|
6
|
+
const emit = defineEmits(["close", "dismiss", "newConversation"]);
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<ChatMobileBottomSheet
|
|
11
|
+
:open="open"
|
|
12
|
+
@close="emit('close')"
|
|
13
|
+
>
|
|
14
|
+
<div class="outdated-sheet">
|
|
15
|
+
<div class="outdated-sheet__icon">
|
|
16
|
+
<span i-ph-warning text-20px />
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="outdated-sheet__copy">
|
|
20
|
+
<h2>Configurações do workspace mudaram</h2>
|
|
21
|
+
<p>Esta conversa usa configurações antigas. Inicie uma nova conversa para aplicar as atualizações.</p>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="outdated-sheet__actions">
|
|
25
|
+
<button
|
|
26
|
+
type="button"
|
|
27
|
+
class="outdated-sheet__button outdated-sheet__button--primary"
|
|
28
|
+
@click="emit('newConversation')"
|
|
29
|
+
>
|
|
30
|
+
<span i-ph-plus text-16px />
|
|
31
|
+
<span>Iniciar nova conversa</span>
|
|
32
|
+
</button>
|
|
33
|
+
<button
|
|
34
|
+
type="button"
|
|
35
|
+
class="outdated-sheet__button outdated-sheet__button--ghost"
|
|
36
|
+
@click="emit('dismiss')"
|
|
37
|
+
>
|
|
38
|
+
Agora não
|
|
39
|
+
</button>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</ChatMobileBottomSheet>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<style scoped>
|
|
46
|
+
.outdated-sheet{display:flex;flex-direction:column;gap:16px;padding:16px 18px 18px}.outdated-sheet__icon{align-items:center;background:#fff1d8;border-radius:14px;color:#171717;display:flex;height:40px;justify-content:center;width:40px}.outdated-sheet__copy{display:flex;flex-direction:column;gap:6px}.outdated-sheet__copy h2{color:#171717;font-size:18px;font-weight:580;letter-spacing:-.2px;line-height:22px;margin:0}.outdated-sheet__copy p{color:#737373;font-size:14px;line-height:19px;margin:0}.outdated-sheet__actions{display:flex;flex-direction:column;gap:8px}.outdated-sheet__button{align-items:center;border-radius:12px;display:flex;font-size:15px;font-weight:580;gap:8px;justify-content:center;line-height:20px;min-height:44px;padding:12px 14px;transition:background .15s,opacity .15s;width:100%}.outdated-sheet__button--primary{background:#171717;color:#fff}.outdated-sheet__button--primary:active{opacity:.88}.outdated-sheet__button--ghost{background:transparent;color:#404040}.outdated-sheet__button--ghost:active{background:#f5f5f5}
|
|
47
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
5
|
+
close: () => any;
|
|
6
|
+
dismiss: () => any;
|
|
7
|
+
newConversation: () => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
9
|
+
onClose?: (() => any) | undefined;
|
|
10
|
+
onDismiss?: (() => any) | undefined;
|
|
11
|
+
onNewConversation?: (() => any) | undefined;
|
|
12
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|