@meistrari/chat-nuxt 4.1.0-rc.2 → 4.1.0-rc.3
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/README.md +2 -0
- package/dist/module.json +1 -1
- package/dist/runtime/embed/components/chat-embed-inner.vue +8 -2
- package/dist/runtime/embed/composables/conversation-browser-state.d.ts +2 -0
- package/dist/runtime/embed/composables/conversation-browser-state.js +18 -0
- package/dist/runtime/embed/conversation-share-url.d.ts +1 -0
- package/dist/runtime/embed/conversation-share-url.js +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,8 @@ bunx --bun typedoc --entryPoints typedoc.ts --out /tmp/chat-nuxt-api --skipError
|
|
|
45
45
|
|
|
46
46
|
The table below is a quick index for reading in-repo. **When you change a prop, update its JSDoc and this row together.**
|
|
47
47
|
|
|
48
|
+
The embed automatically sets the browser tab title to the active conversation title and synchronizes its ID to `?conversationId=` using router replacement, preserving other query parameters and the URL fragment. Starting a new conversation removes the conversation parameter. Opening or reloading that URL restores the conversation; existing `?conversation=` links are also accepted and converted to `?conversationId=`. Explicit `conversationId` and `initialConversationId` props take precedence over the URL on mount. Without a conversation title, the host application controls the tab title.
|
|
49
|
+
|
|
48
50
|
### `<MeistrariChatEmbed>` props
|
|
49
51
|
|
|
50
52
|
Declared in `src/runtime/embed/types.ts`; prop, feature-flag, and event payload types are importable from the package root or `@meistrari/chat-nuxt/types/embed`.
|
package/dist/module.json
CHANGED
|
@@ -13,7 +13,8 @@ import ChatMessageInput from "../../messages/components/chat-message-input.vue";
|
|
|
13
13
|
import { normalizeConversationId } from "../../conversations/scope";
|
|
14
14
|
import { resolveChatFeatures } from "../feature-config";
|
|
15
15
|
import { resolveConversationCreator } from "../../conversations/creator";
|
|
16
|
-
import { buildConversationShareUrl } from "../conversation-share-url";
|
|
16
|
+
import { buildConversationShareUrl, getSharedConversationId } from "../conversation-share-url";
|
|
17
|
+
import { useConversationBrowserState } from "../composables/conversation-browser-state";
|
|
17
18
|
import {
|
|
18
19
|
resolveTelaAgentInputs,
|
|
19
20
|
useChat
|
|
@@ -133,7 +134,7 @@ const {
|
|
|
133
134
|
closePreview
|
|
134
135
|
} = useFilePreviewPanel();
|
|
135
136
|
const { isOpen: isCitationPanelOpen } = useCitationPanel();
|
|
136
|
-
const sharedConversationId =
|
|
137
|
+
const sharedConversationId = getSharedConversationId(route.query);
|
|
137
138
|
const activeConversationId = ref(
|
|
138
139
|
normalizeConversationId(props.conversationId) ?? normalizeConversationId(props.initialConversationId) ?? normalizeConversationId(sharedConversationId)
|
|
139
140
|
);
|
|
@@ -492,6 +493,11 @@ function dismissOutdatedBanner() {
|
|
|
492
493
|
}
|
|
493
494
|
}
|
|
494
495
|
const optimisticTitle = ref(null);
|
|
496
|
+
useConversationBrowserState(activeConversationId, computed(() => {
|
|
497
|
+
if (currentConversation.value?.id !== activeConversationId.value)
|
|
498
|
+
return null;
|
|
499
|
+
return optimisticTitle.value ?? currentConversation.value?.title ?? null;
|
|
500
|
+
}));
|
|
495
501
|
const displayTitle = computed(() => {
|
|
496
502
|
if (optimisticTitle.value !== null)
|
|
497
503
|
return optimisticTitle.value;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function useConversationBrowserState(conversationId, title) {
|
|
2
|
+
const route = useRoute();
|
|
3
|
+
const router = useRouter();
|
|
4
|
+
useHead(computed(() => title.value ? { title: title.value } : {}));
|
|
5
|
+
onMounted(() => {
|
|
6
|
+
watch(conversationId, async (id) => {
|
|
7
|
+
if (route.query.conversationId === (id ?? void 0) && route.query.conversation === void 0)
|
|
8
|
+
return;
|
|
9
|
+
const query = { ...route.query };
|
|
10
|
+
delete query.conversation;
|
|
11
|
+
if (id)
|
|
12
|
+
query.conversationId = id;
|
|
13
|
+
else
|
|
14
|
+
delete query.conversationId;
|
|
15
|
+
await router.replace({ path: route.path, query, hash: route.hash });
|
|
16
|
+
}, { immediate: true });
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { normalizeConversationId } from "../conversations/scope.js";
|
|
2
|
+
export function getSharedConversationId(query) {
|
|
3
|
+
return normalizeConversationId(typeof query.conversationId === "string" ? query.conversationId : null) ?? normalizeConversationId(typeof query.conversation === "string" ? query.conversation : null);
|
|
4
|
+
}
|
|
1
5
|
export function buildConversationShareUrl(currentHref, conversationId) {
|
|
2
6
|
const shareUrl = new URL(currentHref);
|
|
3
|
-
shareUrl.searchParams.
|
|
7
|
+
shareUrl.searchParams.delete("conversation");
|
|
8
|
+
shareUrl.searchParams.set("conversationId", conversationId);
|
|
4
9
|
return shareUrl.href;
|
|
5
10
|
}
|