@aparte/vue 0.17.2 → 0.17.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.
@@ -1 +1 @@
1
- {"version":3,"file":"AparteChat.vue.d.ts","sourceRoot":"","sources":["../../src/components/AparteChat.vue"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AparteChat.vue.d.ts","sourceRoot":"","sources":["../../src/components/AparteChat.vue"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -49,6 +49,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
49
49
  const viewportRef = ref();
50
50
  const composerRef = ref();
51
51
  const internalMessages = ref([...props.messages]);
52
+ const emitted = /* @__PURE__ */ new WeakSet();
52
53
  const typingActive = ref(props.isTyping);
53
54
  let host = null;
54
55
  let teardown = null;
@@ -72,6 +73,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
72
73
  internalMessages.value = m;
73
74
  },
74
75
  onMessagesChange: (m) => {
76
+ emitted.add(m);
75
77
  emit("messagesChange", m);
76
78
  emit("update:messages", m);
77
79
  },
@@ -112,7 +114,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
112
114
  host = null;
113
115
  });
114
116
  watch(() => props.messages, (m) => {
115
- if (m === internalMessages.value) return;
117
+ const raw = toRaw(m);
118
+ if (raw === toRaw(internalMessages.value) || emitted.has(raw)) return;
116
119
  internalMessages.value = [...m];
117
120
  if (m.length === 0) host?.clearRenderCache();
118
121
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/components/AparteChat.vue","../src/composables/useAparteChat.ts","../src/composables/useAparteClient.ts","../src/composables/useConversationManager.ts","../src/components/AparteUi.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, useId, toRaw } from 'vue';\nimport { AparteChatHost, aparteGlobalConfig, isAwaitingReply, type AparteChatHostBinding, type AparteConfig, type AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteActionEventDetail } from '../types.js';\n\ninterface Props {\n /**\n * The host element's `id`, and therefore the `targetId` every event this chat\n * dispatches carries. Generated when omitted — but it used to be generated and\n * neither accepted nor exposed, which made `AparteClientOptions.scopeToTargetId`\n * unreachable from this component.\n */\n id?: string;\n /** Optional: omit for an uncontrolled chat (defaults to []); use `v-model:messages` to control. */\n messages?: AparteMessage[];\n placeholder?: string;\n disabled?: boolean;\n isTyping?: boolean;\n typingText?: string;\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n submitOnEnter?: boolean;\n /** Freeze viewport spacer recalculation for this many ms after a conv swap. */\n layoutTransitionMs?: number;\n /**\n * Opt in to the \"centered composer when empty\" layout: the composer sits\n * vertically centered with the `empty-state` slot above it while the list is\n * empty, then slides to the bottom on the first message (~0.3s). Off by\n * default — additive (adds the `--auto-center` modifier + a `data-aparte-empty`\n * attribute the shipped `aparte.css` recipe keys off).\n */\n centerWhenEmpty?: boolean;\n /**\n * The conversation is on its way: the viewport draws two skeleton turns, the empty\n * state stays off and the composer is disabled until it lands. The conversation\n * controller sets this itself while it fetches through your adapter's `loadFull()`;\n * the prop is for a wait of your own. Off by default.\n */\n loading?: boolean;\n /** Overlay the composer on the transcript: full-column scroll surface, edge-to-edge scrollbar, floating composer. Read when the viewport mounts. */\n overlayComposer?: boolean;\n /**\n * Add the file picker + chips strip to the default composer shell. **Off by\n * default**, because the capability needs a host that consumes the files: an\n * `AparteClient` inlines them per its `rawFileInject` option, but if you drive\n * your own loop you must read `event.files` on `messageSent` — otherwise the file\n * the user deliberately attached is dropped in silence. No effect when you fill\n * the `composer` slot (drop `<aparte-composer-add-attachment>` and\n * `<aparte-composer-attachments>` in it yourself).\n */\n attachments?: boolean;\n /**\n * Render the `<aparte-elicitation>` presenter inside the host — **on by default**,\n * as it is in `<aparte-chat>`: the built-in approval gate and `requestUserInput()`\n * ask through it, and it renders nothing until something asks. Pass `false` when\n * you mount a presenter of your own (`setElicitationPresenter`) or place the\n * element yourself.\n */\n elicitation?: boolean;\n /** Active conversation id (loads/persists via the registered AparteConversationManager). */\n conversationId?: string | null;\n /**\n * Instance {@link AparteConfig} for this chat. When set, aparté components\n * inside resolve THIS config instead of `aparteGlobalConfig`, so\n * several independently-configured chats can coexist on one page. Omit for the\n * global config. Read once when the host mounts.\n */\n config?: AparteConfig;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n messages: () => [],\n placeholder: 'Type a message...',\n disabled: false,\n isTyping: false,\n typingText: 'Assistant is thinking...',\n submitOnEnter: true,\n layoutTransitionMs: 0,\n centerWhenEmpty: false,\n loading: false,\n overlayComposer: false,\n attachments: false,\n elicitation: true,\n conversationId: null,\n});\n\nconst emit = defineEmits<{\n /**\n * User submitted a message from the composer. The message is **appended to\n * the thread automatically** (optimistic UI) before this fires — do NOT add\n * it again in the handler (uncontrolled → duplicates; controlled → mirror it\n * into your own `messages`). For side-effects: scroll, analytics, send.\n */\n messageSent: [event: AparteSendEventDetail];\n /** A custom bubble action (registerBubbleAction) was clicked — typed aparte-action. */\n action: [detail: AparteActionEventDetail];\n /** Active path changed (branch nav/edit/retry/streaming) — bind back to `messages`. */\n messagesChange: [messages: AparteMessage[]];\n /** Same payload as `messagesChange`, enabling `v-model:messages`. */\n 'update:messages': [messages: AparteMessage[]];\n messageAppended: [message: AparteMessage];\n /** The typing/\"thinking\" indicator toggled (the host flips it off on the first streamed token). */\n typingChange: [isTyping: boolean];\n conversationCreated: [id: string];\n}>();\n\n// useId() (Vue 3.5+) is SSR-stable — server and client agree, no hydration mismatch.\n// A caller-supplied `id` wins, so `scopeToTargetId` has something to match; the\n// generated one stays SSR-stable for the common case.\nconst hostId = props.id ?? `aparte-chat-${useId()}`;\nconst rootRef = ref<HTMLElement>();\nconst viewportRef = ref<HTMLElement>();\nconst composerRef = ref<HTMLElement>();\nconst internalMessages = ref<AparteMessage[]>([...props.messages]);\nconst typingActive = ref(props.isTyping);\n\nlet host: AparteChatHost | null = null;\nlet teardown: (() => void) | null = null;\n\nfunction onSend(e: Event) {\n (viewportRef.value as unknown as { requestSmoothScroll?: () => void })?.requestSmoothScroll?.();\n emit('messageSent', (e as CustomEvent<AparteSendEventDetail>).detail);\n}\n\n// Custom bubble actions bubble to the root as `aparte-action` — surface them typed.\nfunction onAction(e: Event) {\n emit('action', (e as CustomEvent<AparteActionEventDetail>).detail);\n}\n\n// The controller's wait (a conversation fetched through the adapter) OR the consumer's.\nconst hostLoading = ref(false);\nconst waiting = computed(() => props.loading || hostLoading.value);\nconst loadingText = computed(() => (props.config ?? aparteGlobalConfig).t('loadingConversation'));\n\nonMounted(() => {\n const binding: AparteChatHostBinding = {\n hostId,\n host: rootRef.value as HTMLElement,\n viewport: viewportRef.value ?? null,\n getMessages: () => internalMessages.value,\n setMessages: (m) => { internalMessages.value = m as AparteMessage[]; },\n onMessagesChange: (m) => { emit('messagesChange', m as AparteMessage[]); emit('update:messages', m as AparteMessage[]); },\n onMessageAppended: (m) => emit('messageAppended', m as AparteMessage),\n onTypingChange: (t) => { typingActive.value = t; emit('typingChange', t); },\n onStreamingChange: () => { /* exposed via isStreaming() */ },\n afterRender: (cb) => { void nextTick(cb); },\n resetComposer: () => (composerRef.value as unknown as { reset?: () => void })?.reset?.(),\n onLoadingChange: (on) => { hostLoading.value = on; },\n };\n host = new AparteChatHost(binding, {\n layoutTransitionMs: props.layoutTransitionMs,\n conversationId: props.conversationId ?? null,\n onConversationCreated: (id) => emit('conversationCreated', id),\n // Unwrap Vue's reactive proxy: the config is a plain class with internal\n // Map registries the host/components must operate on directly, not through a\n // deep reactive proxy (which would wrap those Maps and break lookups).\n config: props.config ? toRaw(props.config) : undefined,\n });\n teardown = host.bind();\n host.syncBubbles();\n composerRef.value?.addEventListener('aparte-send', onSend);\n rootRef.value?.addEventListener('aparte-action', onAction);\n});\n\nonBeforeUnmount(() => {\n composerRef.value?.removeEventListener('aparte-send', onSend);\n rootRef.value?.removeEventListener('aparte-action', onAction);\n teardown?.();\n teardown = null;\n host = null;\n});\n\n// Parent push → internal list (guarded against the host's own emit round-trip).\nwatch(() => props.messages, (m) => {\n if (m === internalMessages.value) return;\n internalMessages.value = [...m];\n if (m.length === 0) host?.clearRenderCache();\n});\n\n// Reconcile bubbles after the rendered list changes (host queries the DOM).\nwatch(internalMessages, () => { void nextTick(() => host?.syncBubbles()); });\n\nwatch(() => props.isTyping, (t) => { typingActive.value = t; });\nwatch(() => props.conversationId, (id) => { void host?.setConversationId(id ?? null); });\n\n// ── Imperative API (forwards to the host) ──\nconst appendMessage = (m: AparteMessage, o?: { historical?: boolean }) => host?.appendMessage(m, o);\nconst updateMessage = (id: string, u: Partial<AparteMessage>) => host?.updateMessage(id, u);\nconst updateLastMessage = (c: string, o?: { append?: boolean }) => host?.updateLastMessage(c, o);\nconst addSegment = (s: AparteSegment) => host?.addSegment(s);\nconst updateSegment = (id: string, u: Partial<AparteSegment>) => host?.updateSegment(id, u);\nconst removeSegment = (id: string) => host?.removeSegment(id);\nconst appendToSegment = (id: string, c: string) => host?.appendToSegment(id, c);\nconst getMessages = () => host?.getMessages() ?? internalMessages.value;\nconst clearMessages = (options?: { revokeAttachments?: boolean }) => host?.clearMessages(options);\nconst addBranch = (id: string) => host?.addBranch(id) ?? 0;\nconst addSiblingOf = (id: string, m: AparteMessage) => host?.addSiblingOf(id, m) ?? null;\nconst truncateFrom = (id: string) => host?.truncateFrom(id);\nconst truncateResponsesAfter = (id: string) => host?.truncateResponsesAfter(id);\nconst injectTokenStream = (id: string, tokens: AsyncIterable<string>) =>\n host?.streamTokens(id, tokens) ?? Promise.resolve();\nconst stopTokenStream = () => host?.stopTokenStream();\nconst setConversationId = (id: string | null) => host?.setConversationId(id) ?? Promise.resolve();\nconst scrollToBottom = () => (viewportRef.value as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.();\nconst focusInput = () => (composerRef.value as unknown as { focus?: () => void })?.focus?.();\nconst isStreaming = () => host?.isStreaming ?? false;\n\n// `getViewport()` (not a raw `viewport` ref): the same accessor on all four\n// wrappers — Svelte 4 can only expose functions, so the shared name is one.\nconst getViewport = () => viewportRef.value ?? null;\n\n// `satisfies` makes a dropped or mistyped method a compile error — the canonical\n// AparteChatImperativeApi is enforced here, not just aliased for consumers.\ndefineExpose({\n appendMessage, updateMessage, updateLastMessage, addSegment, updateSegment, removeSegment,\n appendToSegment, getMessages, clearMessages, addBranch, addSiblingOf, truncateFrom,\n truncateResponsesAfter, injectTokenStream, stopTokenStream, setConversationId,\n scrollToBottom, focusInput, isStreaming, getViewport,\n} satisfies AparteChatImperativeApi);\n</script>\n\n<template>\n <div\n :class=\"['aparte-chat-container', { 'aparte-chat-container--auto-center': centerWhenEmpty }]\"\n data-aparte-chat\n :overlay-composer=\"overlayComposer ? '' : null\"\n :data-aparte-empty=\"centerWhenEmpty && internalMessages.length === 0 && !waiting ? '' : null\"\n :id=\"hostId\"\n ref=\"rootRef\"\n >\n <aparte-chat-viewport ref=\"viewportRef\" framework-managed=\"\" :loading=\"waiting ? '' : null\">\n <!-- The wait, drawn here because this DOM is Vue's: the kit's skeleton recipe,\n and a line for a screen reader. -->\n <div v-if=\"waiting\" class=\"aparte-viewport-loading\" aria-hidden=\"true\">\n <span class=\"aparte-skeleton aparte-skeleton--rect aparte-viewport-loading__user\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text aparte-viewport-loading__last\"></span>\n </div>\n <span v-if=\"waiting\" class=\"aparte-viewport-loading-status aparte-sr-only\" role=\"status\">{{ loadingText }}</span>\n <!-- Welcome / placeholder shown inside the viewport while there are no\n messages (a real empty-state region). -->\n <slot v-if=\"internalMessages.length === 0 && !waiting\" name=\"empty-state\" />\n <!-- `bubble` scoped slot renders your OWN element per message in place of\n <aparte-chat-bubble>; driven by the reactive list so it streams live. -->\n <template v-for=\"m in internalMessages\" :key=\"m.id\">\n <slot name=\"bubble\" :message=\"m\">\n <aparte-chat-bubble\n :message-id=\"m.id\"\n :data-role=\"m.role\"\n :data-kind=\"m.compaction ? 'compaction' : undefined\"\n :timestamp=\"m.timestamp\"\n :content=\"m.content\"\n :streaming=\"isAwaitingReply(m) ? '' : null\"\n />\n </slot>\n </template>\n <aparte-chat-status :visible=\"typingActive ? '' : null\" :text=\"typingText\" />\n </aparte-chat-viewport>\n\n <!-- The presenter for a request to the human (approval gate, ask_user…). Renders\n nothing until something asks; on by default as in <aparte-chat>. -->\n <aparte-elicitation v-if=\"elicitation\"></aparte-elicitation>\n\n <!-- Content above the composer (banner, disclaimer, context chip). -->\n <slot name=\"above-composer\" />\n\n <!-- `.attr` forces attribute-setting, and stays: the attribute IS the state\n core's composer parts read (`getAttribute('placeholder')`, `hasAttribute\n ('disabled')`). Core gained the matching setters in 0.16.12 — before that\n they were getter-only and Vue's default property-set on a custom element\n threw — so this is now a direct write rather than a way around a crash. -->\n <aparte-composer\n ref=\"composerRef\"\n :target=\"hostId\"\n :placeholder.attr=\"placeholder\"\n :disabled.attr=\"disabled || waiting ? '' : null\"\n :submit-on-enter=\"submitOnEnter ? null : 'false'\"\n >\n <!-- Custom composer via the `composer` slot; falls back to the default\n shell (input · send, plus the attachment primitives when `attachments`\n is set). Compose the headless aparte-composer-* primitives freely for a\n skin-specific layout. -->\n <slot name=\"composer\">\n <div class=\"aparte-composer-shell\">\n <aparte-composer-attachments v-if=\"attachments\"></aparte-composer-attachments>\n <div class=\"aparte-composer-row\">\n <aparte-composer-add-attachment v-if=\"attachments\"></aparte-composer-add-attachment>\n <aparte-composer-input></aparte-composer-input>\n <aparte-composer-send></aparte-composer-send>\n </div>\n <!-- The composer's bottom row. ONE slot: placement is the DOM order, and\n `margin-inline-start: auto` pushes a control to the end (a logical\n property, so it reads correctly in RTL). Nothing is rendered at all when\n the slot is unused. -->\n <aparte-composer-toolbar v-if=\"$slots.toolbar\">\n <slot name=\"toolbar\" />\n </aparte-composer-toolbar>\n </div>\n </slot>\n </aparte-composer>\n </div>\n</template>\n","import { ref, type Ref } from 'vue';\nimport type { AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment } from '../types.js';\n\n/**\n * Idiomatic Vue ergonomics for `<AparteChat>`. Owns the `messages` ref and a\n * component template ref so the consumer skips the manual\n * `@messages-change` → `messages` round-trip.\n *\n * @example\n * const chat = useAparteChat();\n * // template:\n * // <AparteChat :ref=\"chat.chatRef\" :messages=\"chat.messages.value\"\n * // @messages-change=\"chat.onMessagesChange\" />\n */\nexport function useAparteChat(initial: AparteMessage[] = []) {\n const messages = ref<AparteMessage[]>([...initial]) as Ref<AparteMessage[]>;\n const chatRef = ref<AparteChatImperativeApi | null>(null);\n const c = () => chatRef.value;\n const onMessagesChange = (m: AparteMessage[]) => { messages.value = m; };\n\n return {\n messages,\n chatRef,\n onMessagesChange,\n appendMessage: (m: AparteMessage, o?: { historical?: boolean }) => c()?.appendMessage(m, o),\n updateMessage: (id: string, u: Partial<AparteMessage>) => c()?.updateMessage(id, u),\n updateLastMessage: (content: string, o?: { append?: boolean }) => c()?.updateLastMessage(content, o),\n addSegment: (s: AparteSegment) => c()?.addSegment(s),\n updateSegment: (id: string, u: Partial<AparteSegment>) => c()?.updateSegment(id, u),\n removeSegment: (id: string) => c()?.removeSegment(id),\n appendToSegment: (id: string, content: string) => c()?.appendToSegment(id, content),\n // The host's list — the authority, and mid-stream a frame ahead of the\n // `messages` ref, which is synced once per paint rather than per token.\n getMessages: (): AparteMessage[] => c()?.getMessages() ?? messages.value,\n clearMessages: (options?: { revokeAttachments?: boolean }) => c()?.clearMessages(options),\n addBranch: (id: string) => c()?.addBranch(id) ?? 0,\n addSiblingOf: (id: string, m: AparteMessage) => c()?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id: string) => c()?.truncateFrom(id),\n truncateResponsesAfter: (id: string) => c()?.truncateResponsesAfter(id),\n injectTokenStream: (id: string, tokens: AsyncIterable<string>) =>\n c()?.injectTokenStream(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => c()?.stopTokenStream(),\n setConversationId: (id: string | null) => c()?.setConversationId(id) ?? Promise.resolve(),\n isStreaming: () => c()?.isStreaming() ?? false,\n scrollToBottom: () => c()?.scrollToBottom(),\n focusInput: () => c()?.focusInput(),\n /** The `<aparte-chat-viewport>` element — same accessor on all four wrappers. */\n getViewport: (): HTMLElement | null => c()?.getViewport() ?? null,\n };\n}\n","import { onMounted, onBeforeUnmount } from 'vue';\nimport { AparteClient, type AparteClientOptions } from '@aparte/core';\n\n/**\n * Mounts an `AparteClient` that bridges `aparte-send` events to the configured AI\n * providers. Starts on mount, stops on unmount. Vue equivalent of Angular's\n * `AparteAiService`.\n */\nexport function useAparteClient(options?: AparteClientOptions) {\n const client = new AparteClient(options ?? {});\n onMounted(() => client.start());\n onBeforeUnmount(() => client.stop());\n return { client, abort: () => client.abort() };\n}\n","import { ref, computed, onBeforeUnmount, type Ref } from 'vue';\nimport {\n aparteGlobalConfig,\n type AparteConfig,\n AparteConversationManager,\n type AparteConversation,\n type AparteStorageAdapter,\n} from '@aparte/core';\nimport type { AparteMessage } from '../types.js';\n\n/**\n * Vue-reactive wrapper around the core `AparteConversationManager`. The active\n * conversation is owned by the chat component's controller; switch by binding\n * `conversationId` on `<AparteChat>`. Vue equivalent of Angular's\n * `ConversationManagerService`.\n */\nexport function useConversationManager() {\n let manager: AparteConversationManager | null = null;\n let unsub: (() => void) | null = null;\n\n const conversations = ref<AparteConversation[]>([]) as Ref<AparteConversation[]>;\n const activeId = ref<string | null>(null);\n\n const activeConversations = computed(() =>\n conversations.value.filter((c) => !c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const archivedConversations = computed(() =>\n conversations.value.filter((c) => !!c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const activeConversation = computed(() =>\n activeId.value ? conversations.value.find((c) => c.id === activeId.value) ?? null : null,\n );\n\n onBeforeUnmount(() => unsub?.());\n\n const assert = (): AparteConversationManager => {\n if (!manager) throw new Error('[useConversationManager] Not initialised. Call init(adapter) first.');\n return manager;\n };\n\n /**\n * Initialise with a storage adapter.\n *\n * `config` defaults to the global singleton. Pass the SAME config you gave\n * `<AparteChat config={…}>`: the controller resolves the config governing its\n * host element, so a manager registered on the global is invisible to a chat\n * with its own — persistence silently does nothing while the optimistic UI\n * keeps working.\n */\n const init = async (adapter: AparteStorageAdapter, config: AparteConfig = aparteGlobalConfig): Promise<void> => {\n const m = new AparteConversationManager(adapter);\n manager = m;\n unsub = m.subscribe((convs) => {\n conversations.value = [...convs];\n activeId.value = m.activeId;\n });\n await m.init();\n activeId.value = m.activeId;\n config.setConversationManager(m);\n };\n\n return {\n conversations,\n activeConversations,\n archivedConversations,\n activeId,\n activeConversation,\n init,\n createNew: (title?: string) => assert().createNew(title),\n addMessage: (convId: string, message: AparteMessage) => assert().addMessage(convId, message),\n updateMessages: (convId: string, messages: AparteMessage[]) => assert().updateMessages(convId, messages),\n delete: (id: string) => assert().delete(id),\n archive: (id: string) => assert().archive(id),\n unarchive: (id: string) => assert().unarchive(id),\n pin: (id: string) => assert().pin(id),\n unpin: (id: string) => assert().unpin(id),\n updateTitle: (id: string, title: string) => assert().updateTitle(id, title),\n };\n}\n","<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, toRaw } from 'vue';\nimport { applyElementProps, APARTE_DEFAULT_UI_EVENTS } from '@aparte/core';\nimport type { AparteUiHandle } from '../types.js';\n\nconst p = defineProps<{\n /** The custom element tag name (e.g. 'aparte-model-selector'). */\n name: string;\n /** Props to apply. Keys starting with `--` become CSS variables. */\n props?: Record<string, unknown>;\n /**\n * Which custom events to forward through `elementEvent`. Defaults to the\n * interactive aparté surface (APARTE_DEFAULT_UI_EVENTS); pass your own list to listen to\n * other events (e.g. ['aparte-composer-change'] for attachments).\n */\n events?: string[];\n}>();\n\nconst emit = defineEmits<{ elementEvent: [event: CustomEvent] }>();\n\n// A stable key so a fresh inline `:events` array doesn't thrash the element —\n// only a real change to the event names rebinds (mirrors React's evtsKey).\nconst evtsKey = computed(() => (p.events ?? APARTE_DEFAULT_UI_EVENTS).join('|'));\n\nconst hostRef = ref<HTMLElement>();\nlet el: HTMLElement | null = null;\nlet cleanups: Array<() => void> = [];\n\n// Vue passes `toRaw` so objects are unwrapped from the reactive proxy before\n// reaching the plain custom element (a deep proxy breaks Maps/class internals).\nfunction applyProps() {\n if (el) applyElementProps(el, p.props ?? {}, toRaw);\n}\n\nfunction create() {\n if (!hostRef.value) return;\n el = document.createElement(p.name);\n applyProps();\n for (const ev of evtsKey.value.split('|').filter(Boolean)) {\n const listener = (e: Event) => emit('elementEvent', e as CustomEvent);\n el.addEventListener(ev, listener);\n cleanups.push(() => el?.removeEventListener(ev, listener));\n }\n hostRef.value.appendChild(el);\n}\n\nfunction destroy() {\n for (const c of cleanups) c();\n cleanups = [];\n el?.remove();\n el = null;\n}\n\nonMounted(create);\nonBeforeUnmount(destroy);\nwatch(() => p.name, () => { destroy(); create(); });\nwatch(evtsKey, () => { destroy(); create(); });\nwatch(() => p.props, applyProps, { deep: true });\n\n/*\n * Typed as `AparteUiHandle`, the way React's `useImperativeHandle` already is.\n *\n * It used to be a bare object literal, so the exposed `getElement` returned\n * `HTMLElement | null` instead of the interface's `<T extends HTMLElement>() => T | null`\n * — and the barrel exports that interface with a docblock promising \"the same contract on\n * all four wrappers\". A consumer following the documented `ref` pattern got a type error\n * on Vue and Svelte and none on React or Angular. Found by a cold audit that compiled it\n * rather than read it.\n *\n * `as never` is the same bridge React uses at AparteUi.tsx:85: the value really is the\n * element, and only the caller knows which subtype it asked for.\n */\ndefineExpose<AparteUiHandle>({\n getElement: () => el as never,\n callMethod: (methodName: string, ...args: unknown[]) => {\n const fn = (el as unknown as Record<string, unknown>)?.[methodName];\n return (typeof fn === 'function' ? (fn as (...a: unknown[]) => unknown).apply(el, args) : undefined) as never;\n },\n});\n</script>\n\n<template>\n <span ref=\"hostRef\" style=\"display: contents\"></span>\n</template>\n"],"names":["_createElementBlock","_unref","_createElementVNode","_openBlock","_toDisplayString","_renderSlot","_Fragment","_renderList","$slots"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/components/AparteChat.vue","../src/composables/useAparteChat.ts","../src/composables/useAparteClient.ts","../src/composables/useConversationManager.ts","../src/components/AparteUi.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, useId, toRaw } from 'vue';\nimport { AparteChatHost, aparteGlobalConfig, isAwaitingReply, type AparteChatHostBinding, type AparteConfig, type AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteActionEventDetail } from '../types.js';\n\ninterface Props {\n /**\n * The host element's `id`, and therefore the `targetId` every event this chat\n * dispatches carries. Generated when omitted — but it used to be generated and\n * neither accepted nor exposed, which made `AparteClientOptions.scopeToTargetId`\n * unreachable from this component.\n */\n id?: string;\n /** Optional: omit for an uncontrolled chat (defaults to []); use `v-model:messages` to control. */\n messages?: AparteMessage[];\n placeholder?: string;\n disabled?: boolean;\n isTyping?: boolean;\n typingText?: string;\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n submitOnEnter?: boolean;\n /** Freeze viewport spacer recalculation for this many ms after a conv swap. */\n layoutTransitionMs?: number;\n /**\n * Opt in to the \"centered composer when empty\" layout: the composer sits\n * vertically centered with the `empty-state` slot above it while the list is\n * empty, then slides to the bottom on the first message (~0.3s). Off by\n * default — additive (adds the `--auto-center` modifier + a `data-aparte-empty`\n * attribute the shipped `aparte.css` recipe keys off).\n */\n centerWhenEmpty?: boolean;\n /**\n * The conversation is on its way: the viewport draws two skeleton turns, the empty\n * state stays off and the composer is disabled until it lands. The conversation\n * controller sets this itself while it fetches through your adapter's `loadFull()`;\n * the prop is for a wait of your own. Off by default.\n */\n loading?: boolean;\n /** Overlay the composer on the transcript: full-column scroll surface, edge-to-edge scrollbar, floating composer. Read when the viewport mounts. */\n overlayComposer?: boolean;\n /**\n * Add the file picker + chips strip to the default composer shell. **Off by\n * default**, because the capability needs a host that consumes the files: an\n * `AparteClient` inlines them per its `rawFileInject` option, but if you drive\n * your own loop you must read `event.files` on `messageSent` — otherwise the file\n * the user deliberately attached is dropped in silence. No effect when you fill\n * the `composer` slot (drop `<aparte-composer-add-attachment>` and\n * `<aparte-composer-attachments>` in it yourself).\n */\n attachments?: boolean;\n /**\n * Render the `<aparte-elicitation>` presenter inside the host — **on by default**,\n * as it is in `<aparte-chat>`: the built-in approval gate and `requestUserInput()`\n * ask through it, and it renders nothing until something asks. Pass `false` when\n * you mount a presenter of your own (`setElicitationPresenter`) or place the\n * element yourself.\n */\n elicitation?: boolean;\n /** Active conversation id (loads/persists via the registered AparteConversationManager). */\n conversationId?: string | null;\n /**\n * Instance {@link AparteConfig} for this chat. When set, aparté components\n * inside resolve THIS config instead of `aparteGlobalConfig`, so\n * several independently-configured chats can coexist on one page. Omit for the\n * global config. Read once when the host mounts.\n */\n config?: AparteConfig;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n messages: () => [],\n placeholder: 'Type a message...',\n disabled: false,\n isTyping: false,\n typingText: 'Assistant is thinking...',\n submitOnEnter: true,\n layoutTransitionMs: 0,\n centerWhenEmpty: false,\n loading: false,\n overlayComposer: false,\n attachments: false,\n elicitation: true,\n conversationId: null,\n});\n\nconst emit = defineEmits<{\n /**\n * User submitted a message from the composer. The message is **appended to\n * the thread automatically** (optimistic UI) before this fires — do NOT add\n * it again in the handler (uncontrolled → duplicates; controlled → mirror it\n * into your own `messages`). For side-effects: scroll, analytics, send.\n */\n messageSent: [event: AparteSendEventDetail];\n /** A custom bubble action (registerBubbleAction) was clicked — typed aparte-action. */\n action: [detail: AparteActionEventDetail];\n /** Active path changed (branch nav/edit/retry/streaming) — bind back to `messages`. */\n messagesChange: [messages: AparteMessage[]];\n /** Same payload as `messagesChange`, enabling `v-model:messages`. */\n 'update:messages': [messages: AparteMessage[]];\n messageAppended: [message: AparteMessage];\n /** The typing/\"thinking\" indicator toggled (the host flips it off on the first streamed token). */\n typingChange: [isTyping: boolean];\n conversationCreated: [id: string];\n}>();\n\n// useId() (Vue 3.5+) is SSR-stable — server and client agree, no hydration mismatch.\n// A caller-supplied `id` wins, so `scopeToTargetId` has something to match; the\n// generated one stays SSR-stable for the common case.\nconst hostId = props.id ?? `aparte-chat-${useId()}`;\nconst rootRef = ref<HTMLElement>();\nconst viewportRef = ref<HTMLElement>();\nconst composerRef = ref<HTMLElement>();\nconst internalMessages = ref<AparteMessage[]>([...props.messages]);\n// Every list the host emitted: the prop comes back as one of them, possibly an EARLIER\n// one when the parent lands late, and an echo is not the parent's word (see the watch).\nconst emitted = new WeakSet<AparteMessage[]>();\nconst typingActive = ref(props.isTyping);\n\nlet host: AparteChatHost | null = null;\nlet teardown: (() => void) | null = null;\n\nfunction onSend(e: Event) {\n (viewportRef.value as unknown as { requestSmoothScroll?: () => void })?.requestSmoothScroll?.();\n emit('messageSent', (e as CustomEvent<AparteSendEventDetail>).detail);\n}\n\n// Custom bubble actions bubble to the root as `aparte-action` — surface them typed.\nfunction onAction(e: Event) {\n emit('action', (e as CustomEvent<AparteActionEventDetail>).detail);\n}\n\n// The controller's wait (a conversation fetched through the adapter) OR the consumer's.\nconst hostLoading = ref(false);\nconst waiting = computed(() => props.loading || hostLoading.value);\nconst loadingText = computed(() => (props.config ?? aparteGlobalConfig).t('loadingConversation'));\n\nonMounted(() => {\n const binding: AparteChatHostBinding = {\n hostId,\n host: rootRef.value as HTMLElement,\n viewport: viewportRef.value ?? null,\n getMessages: () => internalMessages.value,\n setMessages: (m) => { internalMessages.value = m as AparteMessage[]; },\n onMessagesChange: (m) => {\n emitted.add(m as AparteMessage[]);\n emit('messagesChange', m as AparteMessage[]);\n emit('update:messages', m as AparteMessage[]);\n },\n onMessageAppended: (m) => emit('messageAppended', m as AparteMessage),\n onTypingChange: (t) => { typingActive.value = t; emit('typingChange', t); },\n onStreamingChange: () => { /* exposed via isStreaming() */ },\n afterRender: (cb) => { void nextTick(cb); },\n resetComposer: () => (composerRef.value as unknown as { reset?: () => void })?.reset?.(),\n onLoadingChange: (on) => { hostLoading.value = on; },\n };\n host = new AparteChatHost(binding, {\n layoutTransitionMs: props.layoutTransitionMs,\n conversationId: props.conversationId ?? null,\n onConversationCreated: (id) => emit('conversationCreated', id),\n // Unwrap Vue's reactive proxy: the config is a plain class with internal\n // Map registries the host/components must operate on directly, not through a\n // deep reactive proxy (which would wrap those Maps and break lookups).\n config: props.config ? toRaw(props.config) : undefined,\n });\n teardown = host.bind();\n host.syncBubbles();\n composerRef.value?.addEventListener('aparte-send', onSend);\n rootRef.value?.addEventListener('aparte-action', onAction);\n});\n\nonBeforeUnmount(() => {\n composerRef.value?.removeEventListener('aparte-send', onSend);\n rootRef.value?.removeEventListener('aparte-action', onAction);\n teardown?.();\n teardown = null;\n host = null;\n});\n\n// Parent push → internal list, unless it is the host's own emit coming back, current or\n// stale — applying a stale one rolled the list back under the host's next write. Raw, as\n// a parent's `ref` hands the emitted array back wrapped in a reactive proxy.\nwatch(() => props.messages, (m) => {\n const raw = toRaw(m);\n if (raw === toRaw(internalMessages.value) || emitted.has(raw)) return;\n internalMessages.value = [...m];\n if (m.length === 0) host?.clearRenderCache();\n});\n\n// Reconcile bubbles after the rendered list changes (host queries the DOM).\nwatch(internalMessages, () => { void nextTick(() => host?.syncBubbles()); });\n\nwatch(() => props.isTyping, (t) => { typingActive.value = t; });\nwatch(() => props.conversationId, (id) => { void host?.setConversationId(id ?? null); });\n\n// ── Imperative API (forwards to the host) ──\nconst appendMessage = (m: AparteMessage, o?: { historical?: boolean }) => host?.appendMessage(m, o);\nconst updateMessage = (id: string, u: Partial<AparteMessage>) => host?.updateMessage(id, u);\nconst updateLastMessage = (c: string, o?: { append?: boolean }) => host?.updateLastMessage(c, o);\nconst addSegment = (s: AparteSegment) => host?.addSegment(s);\nconst updateSegment = (id: string, u: Partial<AparteSegment>) => host?.updateSegment(id, u);\nconst removeSegment = (id: string) => host?.removeSegment(id);\nconst appendToSegment = (id: string, c: string) => host?.appendToSegment(id, c);\nconst getMessages = () => host?.getMessages() ?? internalMessages.value;\nconst clearMessages = (options?: { revokeAttachments?: boolean }) => host?.clearMessages(options);\nconst addBranch = (id: string) => host?.addBranch(id) ?? 0;\nconst addSiblingOf = (id: string, m: AparteMessage) => host?.addSiblingOf(id, m) ?? null;\nconst truncateFrom = (id: string) => host?.truncateFrom(id);\nconst truncateResponsesAfter = (id: string) => host?.truncateResponsesAfter(id);\nconst injectTokenStream = (id: string, tokens: AsyncIterable<string>) =>\n host?.streamTokens(id, tokens) ?? Promise.resolve();\nconst stopTokenStream = () => host?.stopTokenStream();\nconst setConversationId = (id: string | null) => host?.setConversationId(id) ?? Promise.resolve();\nconst scrollToBottom = () => (viewportRef.value as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.();\nconst focusInput = () => (composerRef.value as unknown as { focus?: () => void })?.focus?.();\nconst isStreaming = () => host?.isStreaming ?? false;\n\n// `getViewport()` (not a raw `viewport` ref): the same accessor on all four\n// wrappers — Svelte 4 can only expose functions, so the shared name is one.\nconst getViewport = () => viewportRef.value ?? null;\n\n// `satisfies` makes a dropped or mistyped method a compile error — the canonical\n// AparteChatImperativeApi is enforced here, not just aliased for consumers.\ndefineExpose({\n appendMessage, updateMessage, updateLastMessage, addSegment, updateSegment, removeSegment,\n appendToSegment, getMessages, clearMessages, addBranch, addSiblingOf, truncateFrom,\n truncateResponsesAfter, injectTokenStream, stopTokenStream, setConversationId,\n scrollToBottom, focusInput, isStreaming, getViewport,\n} satisfies AparteChatImperativeApi);\n</script>\n\n<template>\n <div\n :class=\"['aparte-chat-container', { 'aparte-chat-container--auto-center': centerWhenEmpty }]\"\n data-aparte-chat\n :overlay-composer=\"overlayComposer ? '' : null\"\n :data-aparte-empty=\"centerWhenEmpty && internalMessages.length === 0 && !waiting ? '' : null\"\n :id=\"hostId\"\n ref=\"rootRef\"\n >\n <aparte-chat-viewport ref=\"viewportRef\" framework-managed=\"\" :loading=\"waiting ? '' : null\">\n <!-- The wait, drawn here because this DOM is Vue's: the kit's skeleton recipe,\n and a line for a screen reader. -->\n <div v-if=\"waiting\" class=\"aparte-viewport-loading\" aria-hidden=\"true\">\n <span class=\"aparte-skeleton aparte-skeleton--rect aparte-viewport-loading__user\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text\"></span>\n <span class=\"aparte-skeleton aparte-skeleton--text aparte-viewport-loading__last\"></span>\n </div>\n <span v-if=\"waiting\" class=\"aparte-viewport-loading-status aparte-sr-only\" role=\"status\">{{ loadingText }}</span>\n <!-- Welcome / placeholder shown inside the viewport while there are no\n messages (a real empty-state region). -->\n <slot v-if=\"internalMessages.length === 0 && !waiting\" name=\"empty-state\" />\n <!-- `bubble` scoped slot renders your OWN element per message in place of\n <aparte-chat-bubble>; driven by the reactive list so it streams live. -->\n <template v-for=\"m in internalMessages\" :key=\"m.id\">\n <slot name=\"bubble\" :message=\"m\">\n <aparte-chat-bubble\n :message-id=\"m.id\"\n :data-role=\"m.role\"\n :data-kind=\"m.compaction ? 'compaction' : undefined\"\n :timestamp=\"m.timestamp\"\n :content=\"m.content\"\n :streaming=\"isAwaitingReply(m) ? '' : null\"\n />\n </slot>\n </template>\n <aparte-chat-status :visible=\"typingActive ? '' : null\" :text=\"typingText\" />\n </aparte-chat-viewport>\n\n <!-- The presenter for a request to the human (approval gate, ask_user…). Renders\n nothing until something asks; on by default as in <aparte-chat>. -->\n <aparte-elicitation v-if=\"elicitation\"></aparte-elicitation>\n\n <!-- Content above the composer (banner, disclaimer, context chip). -->\n <slot name=\"above-composer\" />\n\n <!-- `.attr` forces attribute-setting, and stays: the attribute IS the state\n core's composer parts read (`getAttribute('placeholder')`, `hasAttribute\n ('disabled')`). Core gained the matching setters in 0.16.12 — before that\n they were getter-only and Vue's default property-set on a custom element\n threw — so this is now a direct write rather than a way around a crash. -->\n <aparte-composer\n ref=\"composerRef\"\n :target=\"hostId\"\n :placeholder.attr=\"placeholder\"\n :disabled.attr=\"disabled || waiting ? '' : null\"\n :submit-on-enter=\"submitOnEnter ? null : 'false'\"\n >\n <!-- Custom composer via the `composer` slot; falls back to the default\n shell (input · send, plus the attachment primitives when `attachments`\n is set). Compose the headless aparte-composer-* primitives freely for a\n skin-specific layout. -->\n <slot name=\"composer\">\n <div class=\"aparte-composer-shell\">\n <aparte-composer-attachments v-if=\"attachments\"></aparte-composer-attachments>\n <div class=\"aparte-composer-row\">\n <aparte-composer-add-attachment v-if=\"attachments\"></aparte-composer-add-attachment>\n <aparte-composer-input></aparte-composer-input>\n <aparte-composer-send></aparte-composer-send>\n </div>\n <!-- The composer's bottom row. ONE slot: placement is the DOM order, and\n `margin-inline-start: auto` pushes a control to the end (a logical\n property, so it reads correctly in RTL). Nothing is rendered at all when\n the slot is unused. -->\n <aparte-composer-toolbar v-if=\"$slots.toolbar\">\n <slot name=\"toolbar\" />\n </aparte-composer-toolbar>\n </div>\n </slot>\n </aparte-composer>\n </div>\n</template>\n","import { ref, type Ref } from 'vue';\nimport type { AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSegment } from '../types.js';\n\n/**\n * Idiomatic Vue ergonomics for `<AparteChat>`. Owns the `messages` ref and a\n * component template ref so the consumer skips the manual\n * `@messages-change` → `messages` round-trip.\n *\n * @example\n * const chat = useAparteChat();\n * // template:\n * // <AparteChat :ref=\"chat.chatRef\" :messages=\"chat.messages.value\"\n * // @messages-change=\"chat.onMessagesChange\" />\n */\nexport function useAparteChat(initial: AparteMessage[] = []) {\n const messages = ref<AparteMessage[]>([...initial]) as Ref<AparteMessage[]>;\n const chatRef = ref<AparteChatImperativeApi | null>(null);\n const c = () => chatRef.value;\n const onMessagesChange = (m: AparteMessage[]) => { messages.value = m; };\n\n return {\n messages,\n chatRef,\n onMessagesChange,\n appendMessage: (m: AparteMessage, o?: { historical?: boolean }) => c()?.appendMessage(m, o),\n updateMessage: (id: string, u: Partial<AparteMessage>) => c()?.updateMessage(id, u),\n updateLastMessage: (content: string, o?: { append?: boolean }) => c()?.updateLastMessage(content, o),\n addSegment: (s: AparteSegment) => c()?.addSegment(s),\n updateSegment: (id: string, u: Partial<AparteSegment>) => c()?.updateSegment(id, u),\n removeSegment: (id: string) => c()?.removeSegment(id),\n appendToSegment: (id: string, content: string) => c()?.appendToSegment(id, content),\n // The host's list — the authority, and mid-stream a frame ahead of the\n // `messages` ref, which is synced once per paint rather than per token.\n getMessages: (): AparteMessage[] => c()?.getMessages() ?? messages.value,\n clearMessages: (options?: { revokeAttachments?: boolean }) => c()?.clearMessages(options),\n addBranch: (id: string) => c()?.addBranch(id) ?? 0,\n addSiblingOf: (id: string, m: AparteMessage) => c()?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id: string) => c()?.truncateFrom(id),\n truncateResponsesAfter: (id: string) => c()?.truncateResponsesAfter(id),\n injectTokenStream: (id: string, tokens: AsyncIterable<string>) =>\n c()?.injectTokenStream(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => c()?.stopTokenStream(),\n setConversationId: (id: string | null) => c()?.setConversationId(id) ?? Promise.resolve(),\n isStreaming: () => c()?.isStreaming() ?? false,\n scrollToBottom: () => c()?.scrollToBottom(),\n focusInput: () => c()?.focusInput(),\n /** The `<aparte-chat-viewport>` element — same accessor on all four wrappers. */\n getViewport: (): HTMLElement | null => c()?.getViewport() ?? null,\n };\n}\n","import { onMounted, onBeforeUnmount } from 'vue';\nimport { AparteClient, type AparteClientOptions } from '@aparte/core';\n\n/**\n * Mounts an `AparteClient` that bridges `aparte-send` events to the configured AI\n * providers. Starts on mount, stops on unmount. Vue equivalent of Angular's\n * `AparteAiService`.\n */\nexport function useAparteClient(options?: AparteClientOptions) {\n const client = new AparteClient(options ?? {});\n onMounted(() => client.start());\n onBeforeUnmount(() => client.stop());\n return { client, abort: () => client.abort() };\n}\n","import { ref, computed, onBeforeUnmount, type Ref } from 'vue';\nimport {\n aparteGlobalConfig,\n type AparteConfig,\n AparteConversationManager,\n type AparteConversation,\n type AparteStorageAdapter,\n} from '@aparte/core';\nimport type { AparteMessage } from '../types.js';\n\n/**\n * Vue-reactive wrapper around the core `AparteConversationManager`. The active\n * conversation is owned by the chat component's controller; switch by binding\n * `conversationId` on `<AparteChat>`. Vue equivalent of Angular's\n * `ConversationManagerService`.\n */\nexport function useConversationManager() {\n let manager: AparteConversationManager | null = null;\n let unsub: (() => void) | null = null;\n\n const conversations = ref<AparteConversation[]>([]) as Ref<AparteConversation[]>;\n const activeId = ref<string | null>(null);\n\n const activeConversations = computed(() =>\n conversations.value.filter((c) => !c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const archivedConversations = computed(() =>\n conversations.value.filter((c) => !!c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n );\n const activeConversation = computed(() =>\n activeId.value ? conversations.value.find((c) => c.id === activeId.value) ?? null : null,\n );\n\n onBeforeUnmount(() => unsub?.());\n\n const assert = (): AparteConversationManager => {\n if (!manager) throw new Error('[useConversationManager] Not initialised. Call init(adapter) first.');\n return manager;\n };\n\n /**\n * Initialise with a storage adapter.\n *\n * `config` defaults to the global singleton. Pass the SAME config you gave\n * `<AparteChat config={…}>`: the controller resolves the config governing its\n * host element, so a manager registered on the global is invisible to a chat\n * with its own — persistence silently does nothing while the optimistic UI\n * keeps working.\n */\n const init = async (adapter: AparteStorageAdapter, config: AparteConfig = aparteGlobalConfig): Promise<void> => {\n const m = new AparteConversationManager(adapter);\n manager = m;\n unsub = m.subscribe((convs) => {\n conversations.value = [...convs];\n activeId.value = m.activeId;\n });\n await m.init();\n activeId.value = m.activeId;\n config.setConversationManager(m);\n };\n\n return {\n conversations,\n activeConversations,\n archivedConversations,\n activeId,\n activeConversation,\n init,\n createNew: (title?: string) => assert().createNew(title),\n addMessage: (convId: string, message: AparteMessage) => assert().addMessage(convId, message),\n updateMessages: (convId: string, messages: AparteMessage[]) => assert().updateMessages(convId, messages),\n delete: (id: string) => assert().delete(id),\n archive: (id: string) => assert().archive(id),\n unarchive: (id: string) => assert().unarchive(id),\n pin: (id: string) => assert().pin(id),\n unpin: (id: string) => assert().unpin(id),\n updateTitle: (id: string, title: string) => assert().updateTitle(id, title),\n };\n}\n","<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount, toRaw } from 'vue';\nimport { applyElementProps, APARTE_DEFAULT_UI_EVENTS } from '@aparte/core';\nimport type { AparteUiHandle } from '../types.js';\n\nconst p = defineProps<{\n /** The custom element tag name (e.g. 'aparte-model-selector'). */\n name: string;\n /** Props to apply. Keys starting with `--` become CSS variables. */\n props?: Record<string, unknown>;\n /**\n * Which custom events to forward through `elementEvent`. Defaults to the\n * interactive aparté surface (APARTE_DEFAULT_UI_EVENTS); pass your own list to listen to\n * other events (e.g. ['aparte-composer-change'] for attachments).\n */\n events?: string[];\n}>();\n\nconst emit = defineEmits<{ elementEvent: [event: CustomEvent] }>();\n\n// A stable key so a fresh inline `:events` array doesn't thrash the element —\n// only a real change to the event names rebinds (mirrors React's evtsKey).\nconst evtsKey = computed(() => (p.events ?? APARTE_DEFAULT_UI_EVENTS).join('|'));\n\nconst hostRef = ref<HTMLElement>();\nlet el: HTMLElement | null = null;\nlet cleanups: Array<() => void> = [];\n\n// Vue passes `toRaw` so objects are unwrapped from the reactive proxy before\n// reaching the plain custom element (a deep proxy breaks Maps/class internals).\nfunction applyProps() {\n if (el) applyElementProps(el, p.props ?? {}, toRaw);\n}\n\nfunction create() {\n if (!hostRef.value) return;\n el = document.createElement(p.name);\n applyProps();\n for (const ev of evtsKey.value.split('|').filter(Boolean)) {\n const listener = (e: Event) => emit('elementEvent', e as CustomEvent);\n el.addEventListener(ev, listener);\n cleanups.push(() => el?.removeEventListener(ev, listener));\n }\n hostRef.value.appendChild(el);\n}\n\nfunction destroy() {\n for (const c of cleanups) c();\n cleanups = [];\n el?.remove();\n el = null;\n}\n\nonMounted(create);\nonBeforeUnmount(destroy);\nwatch(() => p.name, () => { destroy(); create(); });\nwatch(evtsKey, () => { destroy(); create(); });\nwatch(() => p.props, applyProps, { deep: true });\n\n/*\n * Typed as `AparteUiHandle`, the way React's `useImperativeHandle` already is.\n *\n * It used to be a bare object literal, so the exposed `getElement` returned\n * `HTMLElement | null` instead of the interface's `<T extends HTMLElement>() => T | null`\n * — and the barrel exports that interface with a docblock promising \"the same contract on\n * all four wrappers\". A consumer following the documented `ref` pattern got a type error\n * on Vue and Svelte and none on React or Angular. Found by a cold audit that compiled it\n * rather than read it.\n *\n * `as never` is the same bridge React uses at AparteUi.tsx:85: the value really is the\n * element, and only the caller knows which subtype it asked for.\n */\ndefineExpose<AparteUiHandle>({\n getElement: () => el as never,\n callMethod: (methodName: string, ...args: unknown[]) => {\n const fn = (el as unknown as Record<string, unknown>)?.[methodName];\n return (typeof fn === 'function' ? (fn as (...a: unknown[]) => unknown).apply(el, args) : undefined) as never;\n },\n});\n</script>\n\n<template>\n <span ref=\"hostRef\" style=\"display: contents\"></span>\n</template>\n"],"names":["_createElementBlock","_unref","_createElementVNode","_openBlock","_toDisplayString","_renderSlot","_Fragment","_renderList","$slots"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aparte/vue",
3
- "version": "0.17.2",
3
+ "version": "0.17.3",
4
4
  "homepage": "https://apartejs.dev/frameworks/vue/",
5
5
  "description": "Vue 3 wrapper for aparté — an ergonomic <AparteChat> component plus composables over the framework-agnostic web components.",
6
6
  "type": "module",
@@ -25,7 +25,7 @@
25
25
  "node": ">=18"
26
26
  },
27
27
  "peerDependencies": {
28
- "@aparte/core": ">=0.17.2 <1.0.0",
28
+ "@aparte/core": ">=0.17.3 <1.0.0",
29
29
  "vue": "^3.5.0"
30
30
  },
31
31
  "devDependencies": {
@@ -36,7 +36,7 @@
36
36
  "vite": "^6.0.0",
37
37
  "vue": "^3.5.0",
38
38
  "vue-tsc": "^2.0.0",
39
- "@aparte/core": "0.17.2"
39
+ "@aparte/core": "0.17.3"
40
40
  },
41
41
  "keywords": [
42
42
  "vue",