@convokitapp/vue-ui 0.2.1 → 0.2.2

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,"sources":["../src/index.ts","../src/client.ts","../src/components/avatar.ts","../src/utils.ts","../src/components/conversation.ts","../src/composables/use-conversation.ts","../src/components/message-list.ts","../src/components/conversation-list.ts","../src/composables/use-conversation-list.ts","../src/theme.ts"],"sourcesContent":["import './styles.css'\n\nexport { createConvoKitUiClient } from './client'\nexport { ConvoKitAvatar } from './components/avatar'\nexport { Conversation, ConversationView, type ConversationProps, type ConversationViewProps } from './components/conversation'\nexport { ConversationList, ConversationListView, type ConversationListProps, type ConversationListViewProps } from './components/conversation-list'\nexport { MessageListView, defaultReadersResolver, type MessageListViewProps } from './components/message-list'\nexport {\n useConversation,\n type ConversationController,\n type UseConversationOptions,\n} from './composables/use-conversation'\nexport {\n useConversationList,\n type ConversationListController,\n type UseConversationListOptions,\n} from './composables/use-conversation-list'\nexport {\n ConvoKitThemeProvider,\n defaultConvoKitTheme,\n useConvoKitTheme,\n type ConvoKitTheme,\n} from './theme'\nexport type {\n BaseViewProps,\n ComposerSlotProps,\n ConversationFilter,\n ConversationItemSlotProps,\n ConversationListState,\n ConversationPageLoader,\n ConversationPageRequest,\n ConversationState,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n ErrorSlot,\n ErrorSlotProps,\n MediaSlotProps,\n MessageSlotProps,\n ReadReceiptSlotProps,\n ScrollOptions,\n StateSlot,\n TypingSlotProps,\n} from './types'\nexport {\n applyConversationFilter,\n formatFileSize,\n matchesConversation,\n mergeConversations,\n mergeMessages,\n readerIdsFor,\n} from './utils'\n","import type { ConvoKitClient } from '@convokitapp/sdk'\nimport type { ConvoKitUiClient } from './types'\n\n/** Adapts a connected `@convokitapp/sdk` client to the replaceable UI boundary. */\nexport function createConvoKitUiClient(client: ConvoKitClient): ConvoKitUiClient {\n return {\n get currentUserId() { return client.currentUserId },\n getConversations: (options) => client.getConversations(options),\n getConversation: (conversationId) => client.getConversation(conversationId),\n getMessages: (options) => client.getMessages(options),\n sendMessage: (input) => client.sendMessage(input),\n markConversationRead: (conversationId) => client.markConversationRead(conversationId),\n sendTyping: (input) => client.sendTyping(input),\n onMessage: (conversationId, handler, onError) => client.realtime.onMessage(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onReadReceipt: (conversationId, handler, onError) => client.realtime.onReadReceipt(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onTyping: (conversationId, handler, onError) => client.realtime.onTyping(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n }\n}\n","import { AvatarFallback, AvatarImage, AvatarRoot } from 'reka-ui'\nimport { defineComponent, h, type PropType } from 'vue'\nimport { cx, initials } from '../utils'\n\n/** Accessible avatar built on Reka UI, the primitive layer used by shadcn-vue. */\nexport const ConvoKitAvatar = defineComponent({\n name: 'ConvoKitAvatar',\n inheritAttrs: false,\n props: {\n name: { type: String, required: true },\n src: { type: String as PropType<string | null>, default: null },\n },\n setup(props, { attrs }) {\n return () => h(AvatarRoot, {\n ...attrs,\n class: cx('ckui-avatar', attrs.class),\n }, {\n default: () => [\n props.src ? h(AvatarImage, { class: 'ckui-avatar__image', src: props.src, alt: '' }) : null,\n h(AvatarFallback, {\n class: 'ckui-avatar__fallback',\n ...(props.src ? { delayMs: 300 } : {}),\n }, () => initials(props.name)),\n ],\n })\n },\n})\n","import type { Conversation, Message } from '@convokitapp/sdk'\nimport { clsx, type ClassValue } from 'clsx'\nimport type { CSSProperties } from 'vue'\nimport type { ConversationFilter, ConvoKitAppearanceProps, ConvoKitUiPart } from './types'\n\nexport function cx(...values: ClassValue[]): string { return clsx(values) }\n\nfunction requestedParticipantIds(filter: ConversationFilter): ReadonlySet<string> {\n const values = filter.participantIds ?? []\n return values instanceof Set ? values : new Set(values)\n}\n\nexport function matchesConversation(conversation: Conversation, filter: ConversationFilter): boolean {\n const query = filter.query?.trim().toLocaleLowerCase() ?? ''\n if (query) {\n const haystack = [\n conversation.id,\n conversation.displayTitle,\n conversation.title ?? '',\n conversation.description ?? '',\n ...conversation.participants.flatMap((participant) => [participant.id, participant.appUserId, participant.name]),\n ].join(' ').toLocaleLowerCase()\n if (!haystack.includes(query)) return false\n }\n const requested = requestedParticipantIds(filter)\n if (requested.size > 0) {\n const available = new Set(conversation.participants.flatMap((participant) => [participant.id, participant.appUserId]))\n const values = [...requested]\n const matches = filter.requireAllParticipants\n ? values.every((id) => available.has(id))\n : values.some((id) => available.has(id))\n if (!matches) return false\n }\n return filter.predicate?.(conversation) ?? true\n}\n\nexport function applyConversationFilter(conversations: readonly Conversation[], filter: ConversationFilter): Conversation[] {\n const result = conversations.filter((conversation) => matchesConversation(conversation, filter))\n if (filter.comparator) result.sort(filter.comparator)\n return result\n}\n\nexport function mergeConversations(current: readonly Conversation[], incoming: readonly Conversation[]): Conversation[] {\n const byId = new Map(current.map((conversation) => [conversation.id, conversation]))\n for (const conversation of incoming) byId.set(conversation.id, conversation)\n return [...byId.values()]\n}\n\nexport function mergeMessages(current: readonly Message[], incoming: readonly Message[]): Message[] {\n const byId = new Map(current.map((message) => [message.id, message]))\n for (const message of incoming) byId.set(message.id, message)\n return [...byId.values()].sort((left, right) => {\n const byTime = left.createdAt.getTime() - right.createdAt.getTime()\n return byTime === 0 ? left.id.localeCompare(right.id) : byTime\n })\n}\n\nexport function readerIdsFor(message: Message, readAtByUserId: ReadonlyMap<string, Date>): ReadonlySet<string> {\n return new Set([...readAtByUserId.entries()]\n .filter(([userId, readAt]) => userId !== message.senderId && readAt.getTime() >= message.createdAt.getTime())\n .map(([userId]) => userId))\n}\n\nexport function partClass(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps, defaultClass: string): string {\n return cx(!appearance.unstyled && defaultClass, appearance.classNames?.[part])\n}\n\nexport function partStyle(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps): CSSProperties | undefined {\n return appearance.styles?.[part]\n}\n\nexport function errorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error) }\n\nexport function formatFileSize(size: number | undefined): string | null {\n if (size === undefined || !Number.isFinite(size) || size < 0) return null\n if (size < 1024) return `${Math.round(size)} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(size < 10 * 1024 ? 1 : 0)} KB`\n return `${(size / (1024 * 1024)).toFixed(size < 10 * 1024 * 1024 ? 1 : 0)} MB`\n}\n\nexport function initials(value: string): string {\n const words = value.trim().split(/\\s+/).filter(Boolean)\n return (words.length > 1 ? `${words[0]?.[0] ?? ''}${words.at(-1)?.[0] ?? ''}` : value[0] ?? '?').toLocaleUpperCase()\n}\n","import type { Conversation as ConversationModel, Message, MessageMedia } from '@convokitapp/sdk'\nimport { ArrowLeft, LoaderCircle, Paperclip, RefreshCw, Send } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n ref,\n watchEffect,\n type CSSProperties,\n type PropType,\n type TextareaHTMLAttributes,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationController, UseConversationOptions } from '../composables/use-conversation'\nimport { useConversation } from '../composables/use-conversation'\nimport type {\n ComposerSlotProps,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n TypingSlotProps,\n} from '../types'\nimport { cx, errorMessage, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\nimport { MessageListView } from './message-list'\n\nexport interface ConversationViewProps extends ConvoKitAppearanceProps {\n conversation: ConversationModel\n messages: readonly Message[]\n currentUserId: string\n onSendMessage: (text: string) => boolean | void | Promise<boolean | void>\n typingUserIds?: ReadonlySet<string>\n readAtByUserId?: ReadonlyMap<string, Date>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onBack?: () => void\n onRefresh?: () => void | Promise<void>\n onLoadOlder?: () => void | Promise<void>\n onTypingChange?: (isTyping: boolean) => void | Promise<void>\n onAddAttachment?: () => void\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n isInitialLoading?: boolean\n isLoadingOlder?: boolean\n isSending?: boolean\n hasOlderMessages?: boolean\n error?: unknown\n messageError?: unknown\n displayNameForUser?: (userId: string) => string | null | undefined\n reverseMessages?: boolean\n stickToBottom?: boolean\n paginationThreshold?: number\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n composerPlaceholder?: string\n composerAriaLabel?: string\n composerProps?: Omit<TextareaHTMLAttributes, 'value' | 'disabled'>\n modelValue?: string\n defaultDraft?: string\n onDraftChange?: (value: string) => void\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst viewProps = {\n ...appearanceProps,\n conversation: { type: Object as PropType<ConversationModel>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, required: true },\n typingUserIds: { type: Object as PropType<ReadonlySet<string>>, default: () => new Set() },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onBack: { type: Function as PropType<() => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onTypingChange: { type: Function as PropType<(isTyping: boolean) => void | Promise<void>>, default: undefined },\n onAddAttachment: { type: Function as PropType<() => void>, default: undefined },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n isSending: { type: Boolean, default: false },\n hasOlderMessages: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n messageError: { type: null as unknown as PropType<unknown>, required: false },\n displayNameForUser: { type: Function as PropType<(userId: string) => string | null | undefined>, default: undefined },\n reverseMessages: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n paginationThreshold: { type: Number, default: 240 },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: undefined },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n composerPlaceholder: { type: String, default: 'Write a message' },\n composerAriaLabel: { type: String, default: 'Message' },\n composerProps: { type: Object as PropType<Omit<TextareaHTMLAttributes, 'value' | 'disabled'>>, default: undefined },\n modelValue: { type: String, default: undefined },\n defaultDraft: { type: String, default: '' },\n onDraftChange: { type: Function as PropType<(value: string) => void>, default: undefined },\n} as const\n\nfunction typingLabel(userIds: ReadonlySet<string>, displayNameForUser: (userId: string) => string): string {\n const names = [...userIds].map(displayNameForUser)\n if (names.length === 0) return ''\n if (names.length === 1) return `${names[0]} is typing…`\n if (names.length === 2) return `${names[0]} and ${names[1]} are typing…`\n return `${names[0]} and ${names.length - 1} others are typing…`\n}\n\n/** Controlled, complete selected-conversation surface. */\nexport const ConversationView = defineComponent({\n name: 'ConversationView',\n inheritAttrs: false,\n props: viewProps,\n emits: [\n 'send-message', 'typing-change', 'back', 'refresh', 'load-older',\n 'add-attachment', 'attachment-click', 'update:modelValue',\n ],\n setup(props, { attrs, emit, slots }) {\n const internalDraft = ref(props.defaultDraft)\n const submitting = ref(false)\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n const draft = () => props.modelValue ?? internalDraft.value\n let latestDraft = draft()\n const setDraft = (value: string) => {\n latestDraft = value\n if (props.modelValue === undefined) internalDraft.value = value\n props.onDraftChange?.(value)\n emit('update:modelValue', value)\n const isTyping = value.trim().length > 0\n void props.onTypingChange?.(isTyping)\n }\n const submit = async () => {\n const originalDraft = draft()\n const text = originalDraft.trim()\n if (!text || props.isSending || submitting.value) return\n submitting.value = true\n setDraft('')\n try {\n const shouldClear = await props.onSendMessage(text)\n if (shouldClear === false && latestDraft.length === 0) setDraft(originalDraft)\n } finally {\n submitting.value = false\n }\n }\n const nameForUser = (userId: string) => {\n const custom = props.displayNameForUser?.(userId)?.trim()\n if (custom) return custom\n const participant = props.conversation.participants.find((value) => value.id === userId || value.appUserId === userId)\n return participant?.name.trim() || userId\n }\n const goBack = () => { props.onBack?.() }\n const refresh = () => props.onRefresh?.()\n const loadOlder = () => props.onLoadOlder?.()\n const addAttachment = () => { props.onAddAttachment?.() }\n\n const renderHeader = (): VNodeChild => {\n const slotProps = {\n conversation: props.conversation,\n ...(props.onBack ? { onBack: goBack } : {}),\n ...(props.onRefresh ? { onRefresh: refresh } : {}),\n }\n return slots.header?.(slotProps) ?? h('header', {\n class: partClass('header', appearance(), 'ckui-conversation-header'),\n style: partStyle('header', appearance()),\n }, [\n props.onBack ? h('button', {\n type: 'button', 'aria-label': 'Back', onClick: goBack,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(ArrowLeft, { size: 20, 'aria-hidden': 'true' })]) : null,\n h(ConvoKitAvatar, { name: props.conversation.displayTitle, src: props.conversation.imageUrl }),\n h('div', { class: 'ckui-conversation-header__body' }, [\n h('strong', props.conversation.displayTitle),\n h('span', `${props.conversation.participants.length} participant${props.conversation.participants.length === 1 ? '' : 's'}`),\n ]),\n props.onRefresh ? h('button', {\n type: 'button', 'aria-label': 'Refresh conversation', onClick: () => { void refresh() },\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(RefreshCw, { size: 18, 'aria-hidden': 'true' })]) : null,\n ])\n }\n\n const renderTyping = (): VNodeChild => {\n const slotProps: TypingSlotProps = { userIds: props.typingUserIds, displayNameForUser: nameForUser }\n return slots['typing-indicator']?.(slotProps) ?? h('div', {\n class: partClass('typing', appearance(), 'ckui-typing'),\n style: partStyle('typing', appearance()),\n 'aria-live': 'polite',\n }, typingLabel(props.typingUserIds, nameForUser))\n }\n\n const renderComposer = (): VNodeChild => {\n const slotProps: ComposerSlotProps = {\n value: draft(), setValue: setDraft, isSending: props.isSending || submitting.value,\n send: () => { void submit() },\n ...(props.onAddAttachment ? { addAttachment } : {}),\n }\n return slots.composer?.(slotProps) ?? h('form', {\n class: partClass('composer', appearance(), 'ckui-composer'),\n style: partStyle('composer', appearance()),\n onSubmit: (event: Event) => { event.preventDefault(); void submit() },\n }, [\n props.onAddAttachment ? h('button', {\n type: 'button', 'aria-label': 'Add attachment', onClick: addAttachment,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(Paperclip, { size: 20, 'aria-hidden': 'true' })]) : null,\n h('textarea', {\n ...props.composerProps,\n rows: props.composerProps?.rows ?? 1,\n placeholder: props.composerPlaceholder,\n 'aria-label': props.composerAriaLabel,\n class: cx(!props.unstyled && 'ckui-composer__input', props.classNames?.input, props.composerProps?.class),\n style: [props.styles?.input, props.composerProps?.style],\n value: draft(),\n onInput: (event: InputEvent) => {\n const handler = props.composerProps?.onInput\n if (typeof handler === 'function') handler(event)\n if (!event.defaultPrevented) setDraft((event.currentTarget as HTMLTextAreaElement).value)\n },\n onKeydown: (event: KeyboardEvent) => {\n const handler = props.composerProps?.onKeydown\n if (typeof handler === 'function') handler(event)\n if (event.defaultPrevented) return\n if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); void submit() }\n },\n }),\n h('button', {\n type: 'submit', 'aria-label': 'Send message', disabled: !draft().trim() || props.isSending || submitting.value,\n class: partClass('button', appearance(), 'ckui-send-button'),\n style: partStyle('button', appearance()),\n }, [props.isSending || submitting.value\n ? h(LoaderCircle, { class: 'ckui-spin', size: 18, 'aria-hidden': 'true' })\n : h(Send, { size: 18, 'aria-hidden': 'true' })]),\n ])\n }\n\n return () => {\n if (props.isInitialLoading && props.messages.length === 0) {\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, slots.loading?.() ?? h('div', {\n class: partClass('loading', appearance(), 'ckui-state'), style: partStyle('loading', appearance()), role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…']))\n }\n const children: VNodeChild[] = [renderHeader()]\n if (props.error) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', appearance(), 'ckui-conversation-error'),\n style: partStyle('error', appearance()), role: 'alert',\n }, [h('span', errorMessage(props.error)), retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null]))\n }\n const messageSlots = {\n ...(slots.message ? { message: slots.message } : {}),\n ...(slots.media ? { media: slots.media } : {}),\n ...(slots['read-receipt'] ? { 'read-receipt': slots['read-receipt'] } : {}),\n ...(slots.empty ? { empty: slots.empty } : {}),\n ...(slots['loading-older'] ? { 'loading-older': slots['loading-older'] } : {}),\n ...(slots['message-error'] ? { error: slots['message-error'] } : {}),\n }\n children.push(h(MessageListView, {\n conversation: props.conversation,\n messages: props.messages,\n currentUserId: props.currentUserId,\n readAtByUserId: props.readAtByUserId,\n ...(props.readersResolver ? { readersResolver: props.readersResolver } : {}),\n ...(props.onLoadOlder ? { onLoadOlder: loadOlder } : {}),\n hasOlderMessages: props.hasOlderMessages,\n isLoadingOlder: props.isLoadingOlder,\n ...(props.messageError == null ? {} : { error: props.messageError }),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n } } : {}),\n reverse: props.reverseMessages,\n stickToBottom: props.stickToBottom,\n paginationThreshold: props.paginationThreshold,\n ...(props.formatTime ? { formatTime: props.formatTime } : {}),\n imageLoading: props.imageLoading,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n density: props.density,\n unstyled: props.unstyled,\n }, messageSlots))\n children.push(renderTyping(), renderComposer())\n return h('section', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n 'aria-label': props.conversation.displayTitle,\n }, children)\n }\n },\n})\n\nexport interface ConversationProps extends Omit<ConversationViewProps,\n 'conversation' | 'messages' | 'currentUserId' | 'onSendMessage' | 'typingUserIds' |\n 'readAtByUserId' | 'onRefresh' | 'onLoadOlder' | 'onTypingChange' |\n 'isInitialLoading' | 'isLoadingOlder' | 'isSending' | 'hasOlderMessages' | 'error'>,\n Omit<UseConversationOptions, 'client' | 'conversationId'> {\n client: ConvoKitUiClient\n conversationId: string\n onControllerChange?: (controller: ConversationController) => void\n}\n\n/** Plug-and-play SDK-backed UI for one conversation. */\nexport const Conversation = defineComponent({\n name: 'Conversation',\n inheritAttrs: false,\n props: {\n ...viewProps,\n conversation: { type: Object as PropType<ConversationModel>, default: undefined },\n messages: { type: Array as PropType<readonly Message[]>, default: () => [] },\n currentUserId: { type: String, default: '' },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n conversationId: { type: String, required: true },\n messagePageSize: { type: Number, default: 30 },\n markReadOnLoad: { type: Boolean, default: true },\n markReadOnReceive: { type: Boolean, default: true },\n typingTimeoutMs: { type: Number, default: 3000 },\n autoLoad: { type: Boolean, default: true },\n onControllerChange: { type: Function as PropType<(controller: ConversationController) => void>, default: undefined },\n },\n emits: ['controller-change', 'send-message', 'typing-change', 'back', 'refresh', 'load-older', 'add-attachment', 'attachment-click', 'update:modelValue'],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversation({\n client: () => props.client,\n conversationId: () => props.conversationId,\n messagePageSize: props.messagePageSize,\n markReadOnLoad: props.markReadOnLoad,\n markReadOnReceive: props.markReadOnReceive,\n typingTimeoutMs: props.typingTimeoutMs,\n autoLoad: props.autoLoad,\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n return () => {\n const loadedConversation = controller.conversation.value\n if (!loadedConversation) {\n const retry = () => { void controller.refresh() }\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, controller.error.value\n ? slots.error?.({ error: controller.error.value, retry }) ?? h('div', { class: 'ckui-state ckui-state--error', role: 'alert' }, [\n h('span', errorMessage(controller.error.value)),\n h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again'),\n ])\n : slots.loading?.() ?? h('div', { class: 'ckui-state', role: 'status' }, [\n h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…',\n ]))\n }\n const {\n client: _client,\n conversationId: _conversationId,\n messagePageSize: _messagePageSize,\n markReadOnLoad: _markReadOnLoad,\n markReadOnReceive: _markReadOnReceive,\n typingTimeoutMs: _typingTimeoutMs,\n autoLoad: _autoLoad,\n onControllerChange: _onControllerChange,\n conversation: _conversation,\n messages: _messages,\n currentUserId: _currentUserId,\n onSendMessage: _onSendMessage,\n typingUserIds: _typingUserIds,\n readAtByUserId: _readAtByUserId,\n onRefresh: _onRefresh,\n onLoadOlder: _onLoadOlder,\n onTypingChange: _onTypingChange,\n isInitialLoading: _isInitialLoading,\n isLoadingOlder: _isLoadingOlder,\n isSending: _isSending,\n hasOlderMessages: _hasOlderMessages,\n error: _error,\n ...forwarded\n } = props\n return h(ConversationView, {\n ...attrs,\n ...forwarded,\n conversation: loadedConversation,\n messages: controller.messages.value,\n currentUserId: controller.currentUserId.value,\n onSendMessage: async (text: string) => {\n emit('send-message', text)\n return (await controller.sendMessage({ text })) !== null\n },\n typingUserIds: controller.typingUserIds.value,\n readAtByUserId: controller.readAtByUserId.value,\n onRefresh: controller.refresh,\n onLoadOlder: controller.loadOlderMessages,\n onTypingChange: controller.updateTyping,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingOlder: controller.isLoadingOlder.value,\n isSending: controller.isSending.value,\n hasOlderMessages: controller.hasOlderMessages.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n 'onUpdate:modelValue': (value: string) => emit('update:modelValue', value),\n ...(props.onBack ? { onBack: () => { props.onBack?.(); emit('back') } } : {}),\n ...(props.onAddAttachment ? { onAddAttachment: () => { props.onAddAttachment?.(); emit('add-attachment') } } : {}),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n emit('attachment-click', media, message)\n } } : {}),\n } as never, slots)\n }\n },\n})\n","import type { Message, MessageMedia, RealtimeSubscription } from '@convokitapp/sdk'\nimport {\n computed,\n getCurrentScope,\n onScopeDispose,\n ref,\n shallowRef,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from 'vue'\nimport type { ConversationState, ConvoKitUiClient } from '../types'\nimport { mergeMessages, readerIdsFor } from '../utils'\n\nexport interface UseConversationOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n conversationId: MaybeRefOrGetter<string>\n messagePageSize?: number\n markReadOnLoad?: boolean\n markReadOnReceive?: boolean\n typingTimeoutMs?: number\n autoLoad?: boolean\n}\n\nexport interface ConversationController extends ConversationState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadOlderMessages(): Promise<void>\n sendMessage(input: { text?: string; media?: MessageMedia[] }): Promise<Message | null>\n markRead(): Promise<void>\n updateTyping(isTyping: boolean): Promise<void>\n dispose(): Promise<void>\n}\n\n/** Owns one conversation's history, realtime state, sending, and read positions. */\nexport function useConversation(options: UseConversationOptions): ConversationController {\n const messagePageSize = options.messagePageSize ?? 30\n const typingTimeoutMs = options.typingTimeoutMs ?? 3000\n if (!toValue(options.conversationId).trim()) throw new TypeError('conversationId is required')\n if (!Number.isInteger(messagePageSize) || messagePageSize <= 0) throw new RangeError('messagePageSize must be a positive integer')\n if (!Number.isFinite(typingTimeoutMs) || typingTimeoutMs < 0) throw new RangeError('typingTimeoutMs must be non-negative')\n\n const conversation = shallowRef<ConversationState['conversation']['value']>(null)\n const messages = shallowRef<Message[]>([])\n const typingUserIds = shallowRef<ReadonlySet<string>>(new Set())\n const readAtByUserId = shallowRef<ReadonlyMap<string, Date>>(new Map())\n const isInitialLoading = ref(false)\n const isLoadingOlder = ref(false)\n const isSending = ref(false)\n const hasOlderMessages = ref(true)\n const hasLoaded = ref(false)\n const error = shallowRef<unknown>(null)\n const currentUserId = computed(() => toValue(options.client).currentUserId)\n\n let generation = 0\n let disposed = false\n let sentTyping = false\n let typingTimer: ReturnType<typeof setTimeout> | null = null\n let subscriptions: RealtimeSubscription[] = []\n const pendingIds = new Set<string>()\n let pendingSequence = 0\n\n const unsubscribe = async () => {\n const active = subscriptions\n subscriptions = []\n await Promise.all(active.map((subscription) => subscription.unsubscribe()))\n }\n\n const markRead = async () => {\n const client = toValue(options.client)\n const conversationId = toValue(options.conversationId)\n try {\n await client.markConversationRead(conversationId)\n if (disposed) return\n readAtByUserId.value = new Map(readAtByUserId.value).set(client.currentUserId, new Date())\n } catch (cause) {\n if (!disposed) error.value = cause\n }\n }\n\n const subscribe = (activeGeneration: number, client: ConvoKitUiClient, conversationId: string) => {\n const report = (cause: Error) => {\n if (!disposed && activeGeneration === generation) error.value = cause\n }\n subscriptions = [\n client.onMessage(conversationId, (message) => {\n if (disposed || activeGeneration !== generation) return\n const pending = messages.value.find((candidate) =>\n pendingIds.has(candidate.id) &&\n message.senderId === client.currentUserId &&\n candidate.text === message.text &&\n candidate.media.length === message.media.length)\n if (pending) pendingIds.delete(pending.id)\n messages.value = mergeMessages(\n pending ? messages.value.filter((candidate) => candidate.id !== pending.id) : messages.value,\n [message],\n )\n if ((options.markReadOnReceive ?? true) && message.senderId !== client.currentUserId) void markRead()\n }, report),\n client.onReadReceipt(conversationId, ({ userId, readAt }) => {\n if (disposed || activeGeneration !== generation) return\n readAtByUserId.value = new Map(readAtByUserId.value).set(userId, readAt)\n }, report),\n client.onTyping(conversationId, ({ userId, isTyping }) => {\n if (disposed || activeGeneration !== generation || userId === client.currentUserId) return\n const next = new Set(typingUserIds.value)\n if (isTyping) next.add(userId)\n else next.delete(userId)\n typingUserIds.value = next\n }, report),\n ]\n }\n\n const loadInitial = async () => {\n const client = toValue(options.client)\n const conversationId = toValue(options.conversationId).trim()\n if (!conversationId) throw new TypeError('conversationId is required')\n const activeGeneration = ++generation\n await unsubscribe()\n if (disposed || activeGeneration !== generation) return\n messages.value = []\n pendingIds.clear()\n conversation.value = null\n typingUserIds.value = new Set()\n readAtByUserId.value = new Map()\n hasOlderMessages.value = true\n error.value = null\n isInitialLoading.value = true\n isLoadingOlder.value = false\n subscribe(activeGeneration, client, conversationId)\n try {\n const [nextConversation, page] = await Promise.all([\n client.getConversation(conversationId),\n client.getMessages({ conversationId, limit: messagePageSize, offset: 0 }),\n ])\n if (disposed || activeGeneration !== generation) return\n conversation.value = nextConversation\n readAtByUserId.value = new Map(nextConversation.participants.flatMap((participant) =>\n participant.lastReadAt ? [[participant.appUserId, participant.lastReadAt] as const] : []))\n messages.value = mergeMessages([], page)\n hasOlderMessages.value = page.length === messagePageSize\n if (options.markReadOnLoad ?? true) await markRead()\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) {\n isInitialLoading.value = false\n hasLoaded.value = true\n }\n }\n }\n\n const loadOlderMessages = async () => {\n if (isInitialLoading.value || isLoadingOlder.value || !hasOlderMessages.value) return\n const activeGeneration = generation\n const client = toValue(options.client)\n const conversationId = toValue(options.conversationId)\n isLoadingOlder.value = true\n error.value = null\n try {\n const page = await client.getMessages({\n conversationId,\n limit: messagePageSize,\n offset: messages.value.filter((message) => !pendingIds.has(message.id)).length,\n })\n if (disposed || activeGeneration !== generation) return\n messages.value = mergeMessages(messages.value, page)\n hasOlderMessages.value = page.length === messagePageSize\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) isLoadingOlder.value = false\n }\n }\n\n const updateTyping = async (nextTyping: boolean) => {\n if (typingTimer) clearTimeout(typingTimer)\n if (nextTyping) typingTimer = setTimeout(() => { void updateTyping(false) }, typingTimeoutMs)\n if (sentTyping === nextTyping) return\n sentTyping = nextTyping\n try {\n await toValue(options.client).sendTyping({\n conversationId: toValue(options.conversationId),\n isTyping: nextTyping,\n })\n } catch (cause) {\n if (!disposed) error.value = cause\n }\n }\n\n const sendMessage = async ({ text, media }: { text?: string; media?: MessageMedia[] }) => {\n const normalizedText = text?.trim()\n if (!normalizedText && (!media || media.length === 0)) return null\n if (isSending.value) return null\n const pendingId = `convokit-pending-${Date.now()}-${++pendingSequence}`\n const pendingMessage: Message = {\n id: pendingId,\n conversationId: toValue(options.conversationId),\n senderId: toValue(options.client).currentUserId,\n text: normalizedText ?? null,\n media: media ?? [],\n createdAt: new Date(),\n updatedAt: null,\n }\n pendingIds.add(pendingId)\n messages.value = mergeMessages(messages.value, [pendingMessage])\n isSending.value = true\n error.value = null\n const activeGeneration = generation\n try {\n const message = await toValue(options.client).sendMessage({\n conversationId: toValue(options.conversationId),\n ...(normalizedText ? { text: normalizedText } : {}),\n ...(media?.length ? { media } : {}),\n })\n pendingIds.delete(pendingId)\n if (!disposed && activeGeneration === generation) {\n messages.value = mergeMessages(\n messages.value.filter((candidate) => candidate.id !== pendingId),\n [message],\n )\n }\n await updateTyping(false)\n return message\n } catch (cause) {\n pendingIds.delete(pendingId)\n if (!disposed) {\n messages.value = messages.value.filter((candidate) => candidate.id !== pendingId)\n error.value = cause\n }\n return null\n } finally {\n if (!disposed && activeGeneration === generation) isSending.value = false\n }\n }\n\n const dispose = async () => {\n disposed = true\n generation += 1\n if (typingTimer) clearTimeout(typingTimer)\n if (sentTyping) {\n await toValue(options.client).sendTyping({\n conversationId: toValue(options.conversationId),\n isTyping: false,\n }).catch(() => undefined)\n }\n await unsubscribe()\n }\n\n if (options.autoLoad ?? true) {\n watch(\n () => [toValue(options.client), toValue(options.conversationId)] as const,\n () => {\n disposed = false\n sentTyping = false\n void loadInitial()\n },\n { immediate: true },\n )\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n\n return {\n conversation,\n messages,\n typingUserIds,\n readAtByUserId,\n isInitialLoading,\n isLoadingOlder,\n isSending,\n hasOlderMessages,\n hasLoaded,\n error,\n currentUserId,\n readerIdsFor: (message) => readerIdsFor(message, readAtByUserId.value),\n loadInitial,\n refresh: loadInitial,\n loadOlderMessages,\n sendMessage,\n markRead,\n updateTyping,\n dispose,\n }\n}\n","import type { Conversation, Message, MessageMedia } from '@convokitapp/sdk'\nimport {\n Check,\n CheckCheck,\n ContactRound,\n Download,\n FileText,\n ImageOff,\n LoaderCircle,\n MapPin,\n MessageCircle,\n} from '@lucide/vue'\nimport {\n computed,\n defineComponent,\n h,\n nextTick,\n ref,\n watch,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type {\n ConvoKitAppearanceProps,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n MediaSlotProps,\n MessageSlotProps,\n ReadReceiptSlotProps,\n} from '../types'\nimport { cx, errorMessage, formatFileSize, partClass, partStyle, readerIdsFor } from '../utils'\n\nexport interface MessageListViewProps extends ConvoKitAppearanceProps {\n conversation: Conversation\n messages: readonly Message[]\n currentUserId: string\n readAtByUserId?: ReadonlyMap<string, Date>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onLoadOlder?: () => void | Promise<void>\n hasOlderMessages?: boolean\n isLoadingOlder?: boolean\n error?: unknown\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n reverse?: boolean\n stickToBottom?: boolean\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nfunction defaultFormatTime(date: Date): string {\n return new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: '2-digit' }).format(date)\n}\n\nfunction defaultMedia(\n media: MessageMedia,\n open: (() => void) | undefined,\n imageLoading: 'eager' | 'lazy',\n): VNodeChild {\n const tag = open ? 'button' : 'div'\n const interactive = open ? { type: 'button', onClick: open } : {}\n if (media.type === 'image') {\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--image' }, [\n media.url\n ? h('img', { src: media.url, alt: media.name ?? 'Shared image', loading: imageLoading })\n : h('span', { class: 'ckui-media-placeholder' }, [h(ImageOff, { 'aria-hidden': 'true' }), ' Image unavailable']),\n media.name ? h('span', { class: 'ckui-media-name' }, media.name) : null,\n ])\n }\n if (media.type === 'file') {\n const size = formatFileSize(media.size)\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--file' }, [\n h(FileText, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Attachment'), size ? h('small', size) : null]),\n open ? h(Download, { size: 18, 'aria-hidden': 'true' }) : null,\n ])\n }\n if (media.type === 'location') {\n const label = media.name || `${media.metadata.lat}, ${media.metadata.lng}`\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--location' }, [\n h(MapPin, { 'aria-hidden': 'true' }),\n h('span', [h('strong', label), h('small', `${media.metadata.lat}, ${media.metadata.lng}`)]),\n ])\n }\n const contact = media.metadata.email || media.metadata.phone || 'Contact details'\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--contact' }, [\n h(ContactRound, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Shared contact'), h('small', String(contact))]),\n ])\n}\n\n/** Controlled message history with read receipts, structured media, and older-page loading. */\nexport const MessageListView = defineComponent({\n name: 'MessageListView',\n inheritAttrs: false,\n props: {\n ...appearanceProps,\n conversation: { type: Object as PropType<Conversation>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n hasOlderMessages: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n reverse: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: defaultFormatTime },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n },\n emits: ['load-older', 'attachment-click'],\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n let previousMessageCount = 0\n const participants = computed(() => new Map(props.conversation.participants.flatMap((participant) => [\n [participant.id, participant] as const,\n [participant.appUserId, participant] as const,\n ])))\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestOlder = async () => {\n if (requestInFlight || lastRequestedLength === props.messages.length || props.isLoadingOlder || !props.hasOlderMessages || !props.onLoadOlder) return\n requestInFlight = true\n lastRequestedLength = props.messages.length\n try { await props.onLoadOlder() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n watch(() => [props.messages.length, props.hasOlderMessages] as const, async ([count, hasOlder]) => {\n const previous = previousMessageCount\n if (count !== previousMessageCount || !hasOlder) lastRequestedLength = null\n const appended = count > previous\n const element = internalElement.value\n previousMessageCount = count\n if (element && props.reverse && props.stickToBottom && appended) {\n const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight\n if (previous === 0 || distanceFromBottom < 320) {\n await nextTick()\n element.scrollTop = element.scrollHeight\n }\n }\n }, { flush: 'post', immediate: true })\n\n const renderMessage = (message: Message, index: number): VNodeChild => {\n const isCurrentUser = message.senderId === props.currentUserId\n const sender = participants.value.get(message.senderId)\n const readerIds = props.readersResolver ? props.readersResolver(message) : readerIdsFor(message, props.readAtByUserId)\n const slotProps: MessageSlotProps = { message, chronologicalIndex: index, isCurrentUser, sender, readerIds }\n const custom = slots.message?.(slotProps)\n if (custom) return h('div', { key: message.id, role: 'listitem' }, custom)\n const currentAppearance = appearance()\n const messagePart = isCurrentUser ? 'outgoingMessage' : 'incomingMessage'\n const mediaNodes = message.media.map((media, mediaIndex) => {\n const open = props.onAttachmentClick\n ? () => {\n props.onAttachmentClick?.(media, message)\n }\n : undefined\n const mediaSlotProps: MediaSlotProps = { media, message, isCurrentUser, ...(open ? { open } : {}) }\n return h('div', {\n key: media.id ?? `${media.type}-${mediaIndex}`,\n class: partClass('media', currentAppearance, 'ckui-media'),\n style: partStyle('media', currentAppearance),\n }, slots.media?.(mediaSlotProps) ?? [defaultMedia(media, open, props.imageLoading)])\n })\n const receiptSlotProps: ReadReceiptSlotProps = { message, readerIds }\n return h('div', { key: message.id, role: 'listitem' }, [\n h('article', {\n class: cx(\n !props.unstyled && 'ckui-message-row',\n isCurrentUser && !props.unstyled && 'ckui-message-row--outgoing',\n props.classNames?.message,\n props.classNames?.[messagePart],\n ),\n style: [props.styles?.message, props.styles?.[messagePart]],\n 'data-message-id': message.id,\n }, [\n h('div', { class: 'ckui-message-bubble' }, [\n !isCurrentUser ? h('strong', { class: 'ckui-message-sender' }, sender?.name || message.senderId) : null,\n message.text ? h('div', { class: 'ckui-message-text' }, message.text) : null,\n ...mediaNodes,\n h('time', { class: 'ckui-message-time', datetime: message.createdAt.toISOString() }, [\n props.formatTime(message.createdAt),\n isCurrentUser\n ? readerIds.size > 0\n ? h(CheckCheck, { size: 14, 'aria-label': 'Read' })\n : h(Check, { size: 14, 'aria-label': 'Delivered' })\n : null,\n ]),\n ]),\n isCurrentUser\n ? slots['read-receipt']?.(receiptSlotProps) ?? h('div', {\n class: partClass('receipt', currentAppearance, 'ckui-read-receipt'),\n style: partStyle('receipt', currentAppearance),\n }, readerIds.size > 0 ? `Read by ${readerIds.size}` : 'Delivered')\n : null,\n ]),\n ])\n }\n\n return () => {\n const currentAppearance = appearance()\n const children: VNodeChild[] = []\n if (props.isLoadingOlder) {\n children.push(slots['loading-older']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading older messages…']))\n }\n if (props.error) {\n const retry = props.onLoadOlder ? () => { void requestOlder() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null,\n ]))\n }\n if (props.messages.length === 0 && !props.isLoadingOlder) {\n children.push(slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(MessageCircle, { 'aria-hidden': 'true' }), ' No messages yet']))\n } else {\n children.push(...props.messages.map(renderMessage))\n }\n return h('div', {\n ...attrs,\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui ckui-message-list', props.classNames?.messages, attrs.class),\n style: [props.styles?.messages, attrs.style],\n 'data-density': props.density,\n role: 'log',\n 'aria-live': 'polite',\n 'aria-label': `Messages in ${props.conversation.displayTitle}`,\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n const element = event.currentTarget as HTMLElement\n const distanceFromOldest = props.reverse\n ? element.scrollTop\n : element.scrollHeight - element.scrollTop - element.clientHeight\n if (distanceFromOldest <= props.paginationThreshold) void requestOlder()\n },\n }, children)\n }\n },\n})\n\nexport function defaultReadersResolver(readAtByUserId: ReadonlyMap<string, Date>): (message: Message) => ReadonlySet<string> {\n return (message) => readerIdsFor(message, readAtByUserId)\n}\n","import type { Conversation } from '@convokitapp/sdk'\nimport { ChevronRight, Inbox, LoaderCircle, RefreshCw } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n ref,\n watchEffect,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationListController, UseConversationListOptions } from '../composables/use-conversation-list'\nimport { useConversationList } from '../composables/use-conversation-list'\nimport type {\n ConversationFilter,\n ConversationItemSlotProps,\n ConversationPageLoader,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n} from '../types'\nimport { cx, errorMessage, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\n\nexport interface ConversationListViewProps extends ConvoKitAppearanceProps {\n conversations: readonly Conversation[]\n selectedConversationId?: string\n onConversationSelect?: (conversation: Conversation) => void\n onRefresh?: () => void | Promise<void>\n onLoadMore?: () => void | Promise<void>\n isInitialLoading?: boolean\n isLoadingMore?: boolean\n hasMore?: boolean\n error?: unknown\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n ariaLabel?: string\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst listViewProps = {\n ...appearanceProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, required: true },\n selectedConversationId: { type: String, default: undefined },\n onConversationSelect: { type: Function as PropType<(conversation: Conversation) => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadMore: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingMore: { type: Boolean, default: false },\n hasMore: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n ariaLabel: { type: String, default: 'Conversations' },\n} as const\n\n/** Controlled conversation list. It can be used with any state-management layer. */\nexport const ConversationListView = defineComponent({\n name: 'ConversationListView',\n inheritAttrs: false,\n props: listViewProps,\n emits: {\n 'conversation-select': (_conversation: Conversation) => true,\n refresh: () => true,\n 'load-more': () => true,\n },\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestMore = async () => {\n if (requestInFlight || lastRequestedLength === props.conversations.length || props.isInitialLoading || props.isLoadingMore || !props.hasMore || !props.onLoadMore) return\n requestInFlight = true\n lastRequestedLength = props.conversations.length\n try { await props.onLoadMore() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n const selectConversation = (conversation: Conversation) => {\n props.onConversationSelect?.(conversation)\n }\n\n const refresh = () => {\n return props.onRefresh?.()\n }\n\n const renderContent = () => {\n const currentAppearance = appearance()\n if (props.isInitialLoading && props.conversations.length === 0) {\n return slots['initial-loading']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversations…'])\n }\n if (props.error && props.conversations.length === 0) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n return slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again') : null,\n ])\n }\n if (props.conversations.length === 0) {\n return slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(Inbox, { 'aria-hidden': 'true' }), ' No conversations yet'])\n }\n const children: VNodeChild[] = props.conversations.flatMap((conversation, index) => {\n const selected = props.selectedConversationId === conversation.id\n const select = () => selectConversation(conversation)\n const slotProps: ConversationItemSlotProps = { conversation, index, selected, select }\n const item = slots['conversation-item']?.(slotProps) ?? h('button', {\n type: 'button',\n 'data-selected': selected || undefined,\n 'aria-current': selected ? 'true' : undefined,\n onClick: select,\n class: partClass('listItem', currentAppearance, 'ckui-conversation-item'),\n style: partStyle('listItem', currentAppearance),\n }, [\n h(ConvoKitAvatar, {\n name: conversation.displayTitle,\n src: conversation.imageUrl,\n class: partClass('avatar', currentAppearance, ''),\n style: partStyle('avatar', currentAppearance),\n } as never),\n h('span', { class: 'ckui-conversation-item__body' }, [\n h('strong', conversation.displayTitle),\n h('span', conversation.participants.map((participant) => participant.name).join(', ') || conversation.description || 'No participants'),\n ]),\n h(ChevronRight, { size: 18, 'aria-hidden': 'true' }),\n ])\n const nodes = [h('div', { key: conversation.id, role: 'listitem' }, [item])]\n if (index < props.conversations.length - 1) {\n nodes.push(h('div', { key: `${conversation.id}-separator` }, slots.separator?.({ index }) ?? h('div', { class: 'ckui-separator' })))\n }\n return nodes\n })\n if (props.error) {\n children.push(slots.error?.({ error: props.error, retry: requestMore }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [h('span', errorMessage(props.error)), h('button', { type: 'button', class: 'ckui-link-button', onClick: () => { void requestMore() } }, 'Retry')]))\n } else if (props.isLoadingMore) {\n children.push(slots['load-more']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading more…']))\n }\n return h('div', {\n role: 'list',\n class: partClass('list', currentAppearance, 'ckui-conversation-list__items'),\n style: partStyle('list', currentAppearance),\n }, children)\n }\n\n return () => h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation-list', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, [\n props.onRefresh ? h('div', { class: 'ckui-conversation-list__toolbar' }, [\n h('span', props.ariaLabel),\n h('button', {\n type: 'button',\n 'aria-label': 'Refresh conversations',\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n onClick: () => { void refresh() },\n }, [h(RefreshCw, { size: 17, 'aria-hidden': 'true' })]),\n ]) : null,\n h('div', {\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui-scroll-area', props.classNames?.list),\n style: props.styles?.list,\n 'aria-label': props.ariaLabel,\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n const element = event.currentTarget as HTMLElement\n if (element.scrollHeight - element.scrollTop - element.clientHeight <= props.paginationThreshold) void requestMore()\n },\n }, [renderContent()]),\n ])\n },\n})\n\nexport interface ConversationListProps extends Omit<ConversationListViewProps,\n 'conversations' | 'onRefresh' | 'onLoadMore' | 'isInitialLoading' | 'isLoadingMore' | 'hasMore' | 'error'>,\n Omit<UseConversationListOptions, 'client'> {\n client: ConvoKitUiClient\n onControllerChange?: (controller: ConversationListController) => void\n}\n\n/** Plug-and-play SDK-backed conversation list. */\nexport const ConversationList = defineComponent({\n name: 'ConversationList',\n inheritAttrs: false,\n props: {\n ...listViewProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, default: () => [] },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n pageLoader: { type: Function as PropType<ConversationPageLoader>, default: undefined },\n initialFilter: { type: Object as PropType<ConversationFilter>, default: undefined },\n pageSize: { type: Number, default: 30 },\n autoLoad: { type: Boolean, default: true },\n onControllerChange: { type: Function as PropType<(controller: ConversationListController) => void>, default: undefined },\n },\n emits: ['conversation-select', 'controller-change'],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversationList({\n client: () => props.client,\n ...(props.pageLoader ? { pageLoader: props.pageLoader } : {}),\n ...(props.initialFilter ? { initialFilter: props.initialFilter } : {}),\n pageSize: props.pageSize,\n autoLoad: props.autoLoad,\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n return () => {\n const {\n client: _client,\n pageLoader: _pageLoader,\n initialFilter: _initialFilter,\n pageSize: _pageSize,\n autoLoad: _autoLoad,\n onControllerChange: _onControllerChange,\n conversations: _conversations,\n onRefresh: _onRefresh,\n onLoadMore: _onLoadMore,\n isInitialLoading: _isInitialLoading,\n isLoadingMore: _isLoadingMore,\n hasMore: _hasMore,\n error: _error,\n ...forwarded\n } = props\n return h(ConversationListView, {\n ...attrs,\n ...forwarded,\n conversations: controller.conversations.value,\n onRefresh: controller.refresh,\n onLoadMore: controller.loadMore,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingMore: controller.isLoadingMore.value,\n hasMore: controller.hasMore.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n onConversationSelect: (conversation: Conversation) => {\n emit('conversation-select', conversation)\n },\n } as never, slots)\n }\n },\n})\n","import type { Conversation } from '@convokitapp/sdk'\nimport {\n computed,\n getCurrentScope,\n onScopeDispose,\n ref,\n shallowRef,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from 'vue'\nimport type {\n ConversationFilter,\n ConversationListState,\n ConversationPageLoader,\n ConvoKitUiClient,\n} from '../types'\nimport { applyConversationFilter, mergeConversations } from '../utils'\n\nexport interface UseConversationListOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n pageLoader?: ConversationPageLoader\n initialFilter?: ConversationFilter\n pageSize?: number\n autoLoad?: boolean\n}\n\nexport interface ConversationListController extends ConversationListState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadMore(): Promise<void>\n setFilter(filter: ConversationFilter): Promise<void>\n setQuery(query: string): Promise<void>\n dispose(): Promise<void>\n}\n\n/** Loads, de-duplicates, filters, and paginates conversations. */\nexport function useConversationList(options: UseConversationListOptions): ConversationListController {\n const pageSize = options.pageSize ?? 30\n if (!Number.isInteger(pageSize) || pageSize <= 0) throw new RangeError('pageSize must be a positive integer')\n\n const source = shallowRef<Conversation[]>([])\n const filter = shallowRef<ConversationFilter>(options.initialFilter ?? {})\n const isInitialLoading = ref(false)\n const isLoadingMore = ref(false)\n const hasMore = ref(true)\n const hasLoaded = ref(false)\n const error = shallowRef<unknown>(null)\n const conversations = computed(() => applyConversationFilter(source.value, filter.value))\n let offset = 0\n let generation = 0\n let disposed = false\n\n const loadUntilVisible = async (activeGeneration: number, activeFilter: ConversationFilter) => {\n const visibleBefore = applyConversationFilter(source.value, activeFilter).length\n while (true) {\n const request = { limit: pageSize, offset, filter: activeFilter }\n const page = options.pageLoader\n ? await options.pageLoader(request)\n : await toValue(options.client).getConversations({\n limit: pageSize,\n offset: request.offset,\n archived: activeFilter.archived ?? false,\n })\n if (disposed || activeGeneration !== generation) return\n offset += page.length\n hasMore.value = page.length === pageSize\n source.value = mergeConversations(source.value, page)\n if (!hasMore.value || applyConversationFilter(source.value, activeFilter).length > visibleBefore) return\n }\n }\n\n const loadInitialFor = async (activeFilter: ConversationFilter = filter.value) => {\n const activeGeneration = ++generation\n source.value = []\n offset = 0\n hasMore.value = true\n isInitialLoading.value = true\n isLoadingMore.value = false\n error.value = null\n try {\n await loadUntilVisible(activeGeneration, activeFilter)\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) {\n isInitialLoading.value = false\n hasLoaded.value = true\n }\n }\n }\n\n const loadMore = async () => {\n if (isInitialLoading.value || isLoadingMore.value || !hasMore.value) return\n const activeGeneration = generation\n isLoadingMore.value = true\n error.value = null\n try {\n await loadUntilVisible(activeGeneration, filter.value)\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) isLoadingMore.value = false\n }\n }\n\n const setFilter = async (nextFilter: ConversationFilter) => {\n const previousArchived = filter.value.archived ?? false\n filter.value = nextFilter\n error.value = null\n if ((nextFilter.archived ?? false) !== previousArchived || !hasLoaded.value) {\n await loadInitialFor(nextFilter)\n } else if (applyConversationFilter(source.value, nextFilter).length === 0 && hasMore.value) {\n await loadMore()\n }\n }\n\n const setQuery = (query: string) => setFilter({ ...filter.value, query })\n const dispose = async () => {\n disposed = true\n generation += 1\n }\n\n if (options.autoLoad ?? true) {\n watch(() => toValue(options.client), () => {\n disposed = false\n void loadInitialFor(filter.value)\n }, { immediate: true })\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n\n return {\n conversations,\n filter,\n isInitialLoading,\n isLoadingMore,\n hasMore,\n hasLoaded,\n error,\n loadInitial: loadInitialFor,\n refresh: loadInitialFor,\n loadMore,\n setFilter,\n setQuery,\n dispose,\n }\n}\n","import {\n computed,\n defineComponent,\n h,\n inject,\n provide,\n type CSSProperties,\n type InjectionKey,\n type PropType,\n type Ref,\n} from 'vue'\nimport { cx } from './utils'\n\nexport interface ConvoKitTheme {\n background: string\n surface: string\n primary: string\n text: string\n mutedText: string\n border: string\n error: string\n incomingBubble: string\n outgoingBubble: string\n outgoingText: string\n radius: string\n avatarSize: string\n fontFamily: string\n}\n\nexport const defaultConvoKitTheme: ConvoKitTheme = {\n background: '#fafafa',\n surface: '#ffffff',\n primary: '#18181b',\n text: '#09090b',\n mutedText: '#71717a',\n border: '#e4e4e7',\n error: '#dc2626',\n incomingBubble: '#f4f4f5',\n outgoingBubble: '#18181b',\n outgoingText: '#fafafa',\n radius: '10px',\n avatarSize: '40px',\n fontFamily: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n}\n\nconst themeKey: InjectionKey<Readonly<Ref<ConvoKitTheme>>> = Symbol('ConvoKitTheme')\nconst defaultThemeRef = computed(() => defaultConvoKitTheme)\n\nexport const ConvoKitThemeProvider = defineComponent({\n name: 'ConvoKitThemeProvider',\n inheritAttrs: false,\n props: {\n theme: { type: Object as PropType<Partial<ConvoKitTheme>>, default: () => ({}) },\n class: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n style: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n },\n setup(props, { attrs, slots }) {\n const parent = inject(themeKey, defaultThemeRef)\n const value = computed(() => ({ ...parent.value, ...props.theme }))\n provide(themeKey, value)\n return () => {\n const theme = value.value\n const variables = {\n '--ckui-background': theme.background,\n '--ckui-surface': theme.surface,\n '--ckui-primary': theme.primary,\n '--ckui-text': theme.text,\n '--ckui-muted': theme.mutedText,\n '--ckui-border': theme.border,\n '--ckui-error': theme.error,\n '--ckui-incoming': theme.incomingBubble,\n '--ckui-outgoing': theme.outgoingBubble,\n '--ckui-outgoing-text': theme.outgoingText,\n '--ckui-radius': theme.radius,\n '--ckui-avatar-size': theme.avatarSize,\n '--ckui-font': theme.fontFamily,\n } as CSSProperties\n return h('div', {\n ...attrs,\n class: cx('ckui-theme', props.class, attrs.class),\n style: [variables, props.style, attrs.style],\n }, slots.default?.())\n }\n },\n})\n\nexport function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>> {\n return inject(themeKey, defaultThemeRef)\n}\n"],"mappings":"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","names":["import_vue","import_vue","import_vue","appearanceProps","import_vue","import_vue","appearanceProps","import_vue"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/components/avatar.ts","../src/utils.ts","../src/components/conversation.ts","../src/composables/use-conversation.ts","../src/components/message-list.ts","../src/components/conversation-list.ts","../src/composables/use-conversation-list.ts","../src/theme.ts"],"sourcesContent":["import './styles.css'\n\nexport { createConvoKitUiClient } from './client'\nexport { ConvoKitAvatar } from './components/avatar'\nexport { Conversation, ConversationView, type ConversationProps, type ConversationViewProps } from './components/conversation'\nexport { ConversationList, ConversationListView, type ConversationListProps, type ConversationListViewProps } from './components/conversation-list'\nexport { MessageListView, defaultReadersResolver, type MessageListViewProps } from './components/message-list'\nexport {\n useConversation,\n type ConversationController,\n type UseConversationOptions,\n} from './composables/use-conversation'\nexport {\n useConversationList,\n type ConversationListController,\n type UseConversationListOptions,\n} from './composables/use-conversation-list'\nexport {\n ConvoKitThemeProvider,\n defaultConvoKitTheme,\n useConvoKitTheme,\n type ConvoKitTheme,\n} from './theme'\nexport type {\n BaseViewProps,\n ComposerSlotProps,\n ConversationFilter,\n ConversationItemSlotProps,\n ConversationListState,\n ConversationPageLoader,\n ConversationPageRequest,\n ConversationState,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n ErrorSlot,\n ErrorSlotProps,\n MediaSlotProps,\n MessageSlotProps,\n ReadReceiptSlotProps,\n ScrollOptions,\n StateSlot,\n TypingSlotProps,\n} from './types'\nexport {\n applyConversationFilter,\n formatFileSize,\n isConvoKitPendingMessage,\n matchesConversation,\n mergeConversations,\n mergeMessages,\n readerIdsFor,\n} from './utils'\n","import type { ConvoKitClient } from '@convokitapp/sdk'\nimport type { ConvoKitUiClient } from './types'\n\n/** Adapts a connected `@convokitapp/sdk` client to the replaceable UI boundary. */\nexport function createConvoKitUiClient(client: ConvoKitClient): ConvoKitUiClient {\n return {\n get currentUserId() { return client.currentUserId },\n getConversations: (options) => client.getConversations(options),\n getConversation: (conversationId) => client.getConversation(conversationId),\n getMessages: (options) => client.getMessages(options),\n sendMessage: (input) => client.sendMessage(input),\n markConversationRead: (conversationId) => client.markConversationRead(conversationId),\n sendTyping: (input) => client.sendTyping(input),\n onMessage: (conversationId, handler, onError) => client.realtime.onMessage(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onReadReceipt: (conversationId, handler, onError) => client.realtime.onReadReceipt(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n onTyping: (conversationId, handler, onError) => client.realtime.onTyping(conversationId, {\n onEvent: handler,\n ...(onError ? { onError } : {}),\n }),\n }\n}\n","import { AvatarFallback, AvatarImage, AvatarRoot } from 'reka-ui'\nimport { defineComponent, h, type PropType } from 'vue'\nimport { cx, initials } from '../utils'\n\n/** Accessible avatar built on Reka UI, the primitive layer used by shadcn-vue. */\nexport const ConvoKitAvatar = defineComponent({\n name: 'ConvoKitAvatar',\n inheritAttrs: false,\n props: {\n name: { type: String, required: true },\n src: { type: String as PropType<string | null>, default: null },\n },\n setup(props, { attrs }) {\n return () => h(AvatarRoot, {\n ...attrs,\n class: cx('ckui-avatar', attrs.class),\n }, {\n default: () => [\n props.src ? h(AvatarImage, { class: 'ckui-avatar__image', src: props.src, alt: '' }) : null,\n h(AvatarFallback, {\n class: 'ckui-avatar__fallback',\n ...(props.src ? { delayMs: 300 } : {}),\n }, () => initials(props.name)),\n ],\n })\n },\n})\n","import type { Conversation, Message } from '@convokitapp/sdk'\nimport { clsx, type ClassValue } from 'clsx'\nimport type { CSSProperties } from 'vue'\nimport type { ConversationFilter, ConvoKitAppearanceProps, ConvoKitUiPart } from './types'\n\nconst pendingMessageIdPrefix = 'convokit-pending-'\n\n/** Whether a message is an optimistic row awaiting server acknowledgement. */\nexport function isConvoKitPendingMessage(message: Message): boolean {\n return message.id.startsWith(pendingMessageIdPrefix)\n}\n\nexport function cx(...values: ClassValue[]): string { return clsx(values) }\n\nfunction requestedParticipantIds(filter: ConversationFilter): ReadonlySet<string> {\n const values = filter.participantIds ?? []\n return values instanceof Set ? values : new Set(values)\n}\n\nexport function matchesConversation(conversation: Conversation, filter: ConversationFilter): boolean {\n const query = filter.query?.trim().toLocaleLowerCase() ?? ''\n if (query) {\n const haystack = [\n conversation.id,\n conversation.displayTitle,\n conversation.title ?? '',\n conversation.description ?? '',\n ...conversation.participants.flatMap((participant) => [participant.id, participant.appUserId, participant.name]),\n ].join(' ').toLocaleLowerCase()\n if (!haystack.includes(query)) return false\n }\n const requested = requestedParticipantIds(filter)\n if (requested.size > 0) {\n const available = new Set(conversation.participants.flatMap((participant) => [participant.id, participant.appUserId]))\n const values = [...requested]\n const matches = filter.requireAllParticipants\n ? values.every((id) => available.has(id))\n : values.some((id) => available.has(id))\n if (!matches) return false\n }\n return filter.predicate?.(conversation) ?? true\n}\n\nexport function applyConversationFilter(conversations: readonly Conversation[], filter: ConversationFilter): Conversation[] {\n const result = conversations.filter((conversation) => matchesConversation(conversation, filter))\n if (filter.comparator) result.sort(filter.comparator)\n return result\n}\n\nexport function mergeConversations(current: readonly Conversation[], incoming: readonly Conversation[]): Conversation[] {\n const byId = new Map(current.map((conversation) => [conversation.id, conversation]))\n for (const conversation of incoming) byId.set(conversation.id, conversation)\n return [...byId.values()]\n}\n\nexport function mergeMessages(current: readonly Message[], incoming: readonly Message[]): Message[] {\n const byId = new Map(current.map((message) => [message.id, message]))\n for (const message of incoming) byId.set(message.id, message)\n return [...byId.values()].sort((left, right) => {\n const leftPending = isConvoKitPendingMessage(left)\n const rightPending = isConvoKitPendingMessage(right)\n if (leftPending !== rightPending) return leftPending ? 1 : -1\n const byTime = left.createdAt.getTime() - right.createdAt.getTime()\n return byTime === 0 ? left.id.localeCompare(right.id) : byTime\n })\n}\n\nexport function readerIdsFor(message: Message, readAtByUserId: ReadonlyMap<string, Date>): ReadonlySet<string> {\n if (isConvoKitPendingMessage(message)) return new Set()\n return new Set([...readAtByUserId.entries()]\n .filter(([userId, readAt]) => userId !== message.senderId && readAt.getTime() >= message.createdAt.getTime())\n .map(([userId]) => userId))\n}\n\nexport function partClass(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps, defaultClass: string): string {\n return cx(!appearance.unstyled && defaultClass, appearance.classNames?.[part])\n}\n\nexport function partStyle(part: ConvoKitUiPart, appearance: ConvoKitAppearanceProps): CSSProperties | undefined {\n return appearance.styles?.[part]\n}\n\nexport function errorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error) }\n\nexport function formatFileSize(size: number | undefined): string | null {\n if (size === undefined || !Number.isFinite(size) || size < 0) return null\n if (size < 1024) return `${Math.round(size)} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(size < 10 * 1024 ? 1 : 0)} KB`\n return `${(size / (1024 * 1024)).toFixed(size < 10 * 1024 * 1024 ? 1 : 0)} MB`\n}\n\nexport function initials(value: string): string {\n const words = value.trim().split(/\\s+/).filter(Boolean)\n return (words.length > 1 ? `${words[0]?.[0] ?? ''}${words.at(-1)?.[0] ?? ''}` : value[0] ?? '?').toLocaleUpperCase()\n}\n","import type { Conversation as ConversationModel, Message, MessageMedia } from '@convokitapp/sdk'\nimport { ArrowLeft, LoaderCircle, Paperclip, RefreshCw, Send } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n ref,\n watchEffect,\n type CSSProperties,\n type PropType,\n type TextareaHTMLAttributes,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationController, UseConversationOptions } from '../composables/use-conversation'\nimport { useConversation } from '../composables/use-conversation'\nimport type {\n ComposerSlotProps,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n TypingSlotProps,\n} from '../types'\nimport { cx, errorMessage, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\nimport { MessageListView } from './message-list'\n\nexport interface ConversationViewProps extends ConvoKitAppearanceProps {\n conversation: ConversationModel\n messages: readonly Message[]\n currentUserId: string\n onSendMessage: (text: string) => boolean | void | Promise<boolean | void>\n typingUserIds?: ReadonlySet<string>\n readAtByUserId?: ReadonlyMap<string, Date>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onBack?: () => void\n onRefresh?: () => void | Promise<void>\n onLoadOlder?: () => void | Promise<void>\n onTypingChange?: (isTyping: boolean) => void | Promise<void>\n onAddAttachment?: () => void\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n isInitialLoading?: boolean\n isLoadingOlder?: boolean\n isSending?: boolean\n hasOlderMessages?: boolean\n error?: unknown\n messageError?: unknown\n displayNameForUser?: (userId: string) => string | null | undefined\n reverseMessages?: boolean\n stickToBottom?: boolean\n paginationThreshold?: number\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n composerPlaceholder?: string\n composerAriaLabel?: string\n composerProps?: Omit<TextareaHTMLAttributes, 'value' | 'disabled'>\n modelValue?: string\n defaultDraft?: string\n onDraftChange?: (value: string) => void\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst viewProps = {\n ...appearanceProps,\n conversation: { type: Object as PropType<ConversationModel>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, required: true },\n typingUserIds: { type: Object as PropType<ReadonlySet<string>>, default: () => new Set() },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onBack: { type: Function as PropType<() => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onTypingChange: { type: Function as PropType<(isTyping: boolean) => void | Promise<void>>, default: undefined },\n onAddAttachment: { type: Function as PropType<() => void>, default: undefined },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n isSending: { type: Boolean, default: false },\n hasOlderMessages: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n messageError: { type: null as unknown as PropType<unknown>, required: false },\n displayNameForUser: { type: Function as PropType<(userId: string) => string | null | undefined>, default: undefined },\n reverseMessages: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n paginationThreshold: { type: Number, default: 240 },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: undefined },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n composerPlaceholder: { type: String, default: 'Write a message' },\n composerAriaLabel: { type: String, default: 'Message' },\n composerProps: { type: Object as PropType<Omit<TextareaHTMLAttributes, 'value' | 'disabled'>>, default: undefined },\n modelValue: { type: String, default: undefined },\n defaultDraft: { type: String, default: '' },\n onDraftChange: { type: Function as PropType<(value: string) => void>, default: undefined },\n} as const\n\nfunction typingLabel(userIds: ReadonlySet<string>, displayNameForUser: (userId: string) => string): string {\n const names = [...userIds].map(displayNameForUser)\n if (names.length === 0) return ''\n if (names.length === 1) return `${names[0]} is typing…`\n if (names.length === 2) return `${names[0]} and ${names[1]} are typing…`\n return `${names[0]} and ${names.length - 1} others are typing…`\n}\n\n/** Controlled, complete selected-conversation surface. */\nexport const ConversationView = defineComponent({\n name: 'ConversationView',\n inheritAttrs: false,\n props: viewProps,\n emits: [\n 'send-message', 'typing-change', 'back', 'refresh', 'load-older',\n 'add-attachment', 'attachment-click', 'update:modelValue',\n ],\n setup(props, { attrs, emit, slots }) {\n const internalDraft = ref(props.defaultDraft)\n const submitting = ref(false)\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n const draft = () => props.modelValue ?? internalDraft.value\n let latestDraft = draft()\n const setDraft = (value: string) => {\n latestDraft = value\n if (props.modelValue === undefined) internalDraft.value = value\n props.onDraftChange?.(value)\n emit('update:modelValue', value)\n const isTyping = value.trim().length > 0\n void props.onTypingChange?.(isTyping)\n }\n const submit = async () => {\n const originalDraft = draft()\n const text = originalDraft.trim()\n if (!text || props.isSending || submitting.value) return\n submitting.value = true\n setDraft('')\n try {\n const shouldClear = await props.onSendMessage(text)\n if (shouldClear === false && latestDraft.length === 0) setDraft(originalDraft)\n } finally {\n submitting.value = false\n }\n }\n const nameForUser = (userId: string) => {\n const custom = props.displayNameForUser?.(userId)?.trim()\n if (custom) return custom\n const participant = props.conversation.participants.find((value) => value.id === userId || value.appUserId === userId)\n return participant?.name.trim() || userId\n }\n const goBack = () => { props.onBack?.() }\n const refresh = () => props.onRefresh?.()\n const loadOlder = () => props.onLoadOlder?.()\n const addAttachment = () => { props.onAddAttachment?.() }\n\n const renderHeader = (): VNodeChild => {\n const slotProps = {\n conversation: props.conversation,\n ...(props.onBack ? { onBack: goBack } : {}),\n ...(props.onRefresh ? { onRefresh: refresh } : {}),\n }\n return slots.header?.(slotProps) ?? h('header', {\n class: partClass('header', appearance(), 'ckui-conversation-header'),\n style: partStyle('header', appearance()),\n }, [\n props.onBack ? h('button', {\n type: 'button', 'aria-label': 'Back', onClick: goBack,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(ArrowLeft, { size: 20, 'aria-hidden': 'true' })]) : null,\n h(ConvoKitAvatar, { name: props.conversation.displayTitle, src: props.conversation.imageUrl }),\n h('div', { class: 'ckui-conversation-header__body' }, [\n h('strong', props.conversation.displayTitle),\n h('span', `${props.conversation.participants.length} participant${props.conversation.participants.length === 1 ? '' : 's'}`),\n ]),\n props.onRefresh ? h('button', {\n type: 'button', 'aria-label': 'Refresh conversation', onClick: () => { void refresh() },\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(RefreshCw, { size: 18, 'aria-hidden': 'true' })]) : null,\n ])\n }\n\n const renderTyping = (): VNodeChild => {\n const slotProps: TypingSlotProps = { userIds: props.typingUserIds, displayNameForUser: nameForUser }\n return slots['typing-indicator']?.(slotProps) ?? h('div', {\n class: partClass('typing', appearance(), 'ckui-typing'),\n style: partStyle('typing', appearance()),\n 'aria-live': 'polite',\n }, typingLabel(props.typingUserIds, nameForUser))\n }\n\n const renderComposer = (): VNodeChild => {\n const slotProps: ComposerSlotProps = {\n value: draft(), setValue: setDraft, isSending: props.isSending || submitting.value,\n send: () => { void submit() },\n ...(props.onAddAttachment ? { addAttachment } : {}),\n }\n return slots.composer?.(slotProps) ?? h('form', {\n class: partClass('composer', appearance(), 'ckui-composer'),\n style: partStyle('composer', appearance()),\n onSubmit: (event: Event) => { event.preventDefault(); void submit() },\n }, [\n props.onAddAttachment ? h('button', {\n type: 'button', 'aria-label': 'Add attachment', onClick: addAttachment,\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n }, [h(Paperclip, { size: 20, 'aria-hidden': 'true' })]) : null,\n h('textarea', {\n ...props.composerProps,\n rows: props.composerProps?.rows ?? 1,\n placeholder: props.composerPlaceholder,\n 'aria-label': props.composerAriaLabel,\n class: cx(!props.unstyled && 'ckui-composer__input', props.classNames?.input, props.composerProps?.class),\n style: [props.styles?.input, props.composerProps?.style],\n value: draft(),\n onInput: (event: InputEvent) => {\n const handler = props.composerProps?.onInput\n if (typeof handler === 'function') handler(event)\n if (!event.defaultPrevented) setDraft((event.currentTarget as HTMLTextAreaElement).value)\n },\n onKeydown: (event: KeyboardEvent) => {\n const handler = props.composerProps?.onKeydown\n if (typeof handler === 'function') handler(event)\n if (event.defaultPrevented) return\n if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); void submit() }\n },\n }),\n h('button', {\n type: 'submit', 'aria-label': 'Send message', disabled: !draft().trim() || props.isSending || submitting.value,\n class: partClass('button', appearance(), 'ckui-send-button'),\n style: partStyle('button', appearance()),\n }, [props.isSending || submitting.value\n ? h(LoaderCircle, { class: 'ckui-spin', size: 18, 'aria-hidden': 'true' })\n : h(Send, { size: 18, 'aria-hidden': 'true' })]),\n ])\n }\n\n return () => {\n if (props.isInitialLoading && props.messages.length === 0) {\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, slots.loading?.() ?? h('div', {\n class: partClass('loading', appearance(), 'ckui-state'), style: partStyle('loading', appearance()), role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…']))\n }\n const children: VNodeChild[] = [renderHeader()]\n if (props.error) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', appearance(), 'ckui-conversation-error'),\n style: partStyle('error', appearance()), role: 'alert',\n }, [h('span', errorMessage(props.error)), retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null]))\n }\n const messageSlots = {\n ...(slots.message ? { message: slots.message } : {}),\n ...(slots.media ? { media: slots.media } : {}),\n ...(slots['read-receipt'] ? { 'read-receipt': slots['read-receipt'] } : {}),\n ...(slots.empty ? { empty: slots.empty } : {}),\n ...(slots['loading-older'] ? { 'loading-older': slots['loading-older'] } : {}),\n ...(slots['message-error'] ? { error: slots['message-error'] } : {}),\n }\n children.push(h(MessageListView, {\n conversation: props.conversation,\n messages: props.messages,\n currentUserId: props.currentUserId,\n readAtByUserId: props.readAtByUserId,\n ...(props.readersResolver ? { readersResolver: props.readersResolver } : {}),\n ...(props.onLoadOlder ? { onLoadOlder: loadOlder } : {}),\n hasOlderMessages: props.hasOlderMessages,\n isLoadingOlder: props.isLoadingOlder,\n ...(props.messageError == null ? {} : { error: props.messageError }),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n } } : {}),\n reverse: props.reverseMessages,\n stickToBottom: props.stickToBottom,\n paginationThreshold: props.paginationThreshold,\n ...(props.formatTime ? { formatTime: props.formatTime } : {}),\n imageLoading: props.imageLoading,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n density: props.density,\n unstyled: props.unstyled,\n }, messageSlots))\n children.push(renderTyping(), renderComposer())\n return h('section', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n 'aria-label': props.conversation.displayTitle,\n }, children)\n }\n },\n})\n\nexport interface ConversationProps extends Omit<ConversationViewProps,\n 'conversation' | 'messages' | 'currentUserId' | 'onSendMessage' | 'typingUserIds' |\n 'readAtByUserId' | 'onRefresh' | 'onLoadOlder' | 'onTypingChange' |\n 'isInitialLoading' | 'isLoadingOlder' | 'isSending' | 'hasOlderMessages' | 'error'>,\n Omit<UseConversationOptions, 'client' | 'conversationId'> {\n client: ConvoKitUiClient\n conversationId: string\n onControllerChange?: (controller: ConversationController) => void\n}\n\n/** Plug-and-play SDK-backed UI for one conversation. */\nexport const Conversation = defineComponent({\n name: 'Conversation',\n inheritAttrs: false,\n props: {\n ...viewProps,\n conversation: { type: Object as PropType<ConversationModel>, default: undefined },\n messages: { type: Array as PropType<readonly Message[]>, default: () => [] },\n currentUserId: { type: String, default: '' },\n onSendMessage: { type: Function as PropType<(text: string) => boolean | void | Promise<boolean | void>>, default: undefined },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n conversationId: { type: String, required: true },\n messagePageSize: { type: Number, default: 30 },\n markReadOnLoad: { type: Boolean, default: true },\n markReadOnReceive: { type: Boolean, default: true },\n typingTimeoutMs: { type: Number, default: 3000 },\n autoLoad: { type: Boolean, default: true },\n onControllerChange: { type: Function as PropType<(controller: ConversationController) => void>, default: undefined },\n },\n emits: ['controller-change', 'send-message', 'typing-change', 'back', 'refresh', 'load-older', 'add-attachment', 'attachment-click', 'update:modelValue'],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversation({\n client: () => props.client,\n conversationId: () => props.conversationId,\n messagePageSize: props.messagePageSize,\n markReadOnLoad: props.markReadOnLoad,\n markReadOnReceive: props.markReadOnReceive,\n typingTimeoutMs: props.typingTimeoutMs,\n autoLoad: props.autoLoad,\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n return () => {\n const loadedConversation = controller.conversation.value\n if (!loadedConversation) {\n const retry = () => { void controller.refresh() }\n return h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, controller.error.value\n ? slots.error?.({ error: controller.error.value, retry }) ?? h('div', { class: 'ckui-state ckui-state--error', role: 'alert' }, [\n h('span', errorMessage(controller.error.value)),\n h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again'),\n ])\n : slots.loading?.() ?? h('div', { class: 'ckui-state', role: 'status' }, [\n h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversation…',\n ]))\n }\n const {\n client: _client,\n conversationId: _conversationId,\n messagePageSize: _messagePageSize,\n markReadOnLoad: _markReadOnLoad,\n markReadOnReceive: _markReadOnReceive,\n typingTimeoutMs: _typingTimeoutMs,\n autoLoad: _autoLoad,\n onControllerChange: _onControllerChange,\n conversation: _conversation,\n messages: _messages,\n currentUserId: _currentUserId,\n onSendMessage: _onSendMessage,\n typingUserIds: _typingUserIds,\n readAtByUserId: _readAtByUserId,\n onRefresh: _onRefresh,\n onLoadOlder: _onLoadOlder,\n onTypingChange: _onTypingChange,\n isInitialLoading: _isInitialLoading,\n isLoadingOlder: _isLoadingOlder,\n isSending: _isSending,\n hasOlderMessages: _hasOlderMessages,\n error: _error,\n ...forwarded\n } = props\n return h(ConversationView, {\n ...attrs,\n ...forwarded,\n conversation: loadedConversation,\n messages: controller.messages.value,\n currentUserId: controller.currentUserId.value,\n onSendMessage: async (text: string) => {\n emit('send-message', text)\n return (await controller.sendMessage({ text })) !== null\n },\n typingUserIds: controller.typingUserIds.value,\n readAtByUserId: controller.readAtByUserId.value,\n onRefresh: controller.refresh,\n onLoadOlder: controller.loadOlderMessages,\n onTypingChange: controller.updateTyping,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingOlder: controller.isLoadingOlder.value,\n isSending: controller.isSending.value,\n hasOlderMessages: controller.hasOlderMessages.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n 'onUpdate:modelValue': (value: string) => emit('update:modelValue', value),\n ...(props.onBack ? { onBack: () => { props.onBack?.(); emit('back') } } : {}),\n ...(props.onAddAttachment ? { onAddAttachment: () => { props.onAddAttachment?.(); emit('add-attachment') } } : {}),\n ...(props.onAttachmentClick ? { onAttachmentClick: (media: MessageMedia, message: Message) => {\n props.onAttachmentClick?.(media, message)\n emit('attachment-click', media, message)\n } } : {}),\n } as never, slots)\n }\n },\n})\n","import type { Message, MessageMedia, RealtimeSubscription } from '@convokitapp/sdk'\nimport {\n computed,\n getCurrentScope,\n onScopeDispose,\n ref,\n shallowRef,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from 'vue'\nimport type { ConversationState, ConvoKitUiClient } from '../types'\nimport { mergeMessages, readerIdsFor } from '../utils'\n\nexport interface UseConversationOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n conversationId: MaybeRefOrGetter<string>\n messagePageSize?: number\n markReadOnLoad?: boolean\n markReadOnReceive?: boolean\n typingTimeoutMs?: number\n autoLoad?: boolean\n}\n\nexport interface ConversationController extends ConversationState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadOlderMessages(): Promise<void>\n sendMessage(input: { text?: string; media?: MessageMedia[] }): Promise<Message | null>\n markRead(): Promise<void>\n updateTyping(isTyping: boolean): Promise<void>\n dispose(): Promise<void>\n}\n\n/** Owns one conversation's history, realtime state, sending, and read positions. */\nexport function useConversation(options: UseConversationOptions): ConversationController {\n const messagePageSize = options.messagePageSize ?? 30\n const typingTimeoutMs = options.typingTimeoutMs ?? 3000\n if (!toValue(options.conversationId).trim()) throw new TypeError('conversationId is required')\n if (!Number.isInteger(messagePageSize) || messagePageSize <= 0) throw new RangeError('messagePageSize must be a positive integer')\n if (!Number.isFinite(typingTimeoutMs) || typingTimeoutMs < 0) throw new RangeError('typingTimeoutMs must be non-negative')\n\n const conversation = shallowRef<ConversationState['conversation']['value']>(null)\n const messages = shallowRef<Message[]>([])\n const typingUserIds = shallowRef<ReadonlySet<string>>(new Set())\n const readAtByUserId = shallowRef<ReadonlyMap<string, Date>>(new Map())\n const isInitialLoading = ref(false)\n const isLoadingOlder = ref(false)\n const isSending = ref(false)\n const hasOlderMessages = ref(true)\n const hasLoaded = ref(false)\n const error = shallowRef<unknown>(null)\n const currentUserId = computed(() => toValue(options.client).currentUserId)\n\n let generation = 0\n let disposed = false\n let sentTyping = false\n let typingTimer: ReturnType<typeof setTimeout> | null = null\n let subscriptions: RealtimeSubscription[] = []\n const pendingIds = new Set<string>()\n let pendingSequence = 0\n\n const unsubscribe = async () => {\n const active = subscriptions\n subscriptions = []\n await Promise.all(active.map((subscription) => subscription.unsubscribe()))\n }\n\n const markRead = async () => {\n const client = toValue(options.client)\n const conversationId = toValue(options.conversationId)\n try {\n await client.markConversationRead(conversationId)\n if (disposed) return\n readAtByUserId.value = new Map(readAtByUserId.value).set(client.currentUserId, new Date())\n } catch (cause) {\n if (!disposed) error.value = cause\n }\n }\n\n const subscribe = (activeGeneration: number, client: ConvoKitUiClient, conversationId: string) => {\n const report = (cause: Error) => {\n if (!disposed && activeGeneration === generation) error.value = cause\n }\n subscriptions = [\n client.onMessage(conversationId, (message) => {\n if (disposed || activeGeneration !== generation) return\n const pending = messages.value.find((candidate) =>\n pendingIds.has(candidate.id) &&\n message.senderId === client.currentUserId &&\n candidate.text === message.text &&\n candidate.media.length === message.media.length)\n if (pending) pendingIds.delete(pending.id)\n messages.value = mergeMessages(\n pending ? messages.value.filter((candidate) => candidate.id !== pending.id) : messages.value,\n [message],\n )\n if ((options.markReadOnReceive ?? true) && message.senderId !== client.currentUserId) void markRead()\n }, report),\n client.onReadReceipt(conversationId, ({ userId, readAt }) => {\n if (disposed || activeGeneration !== generation) return\n readAtByUserId.value = new Map(readAtByUserId.value).set(userId, readAt)\n }, report),\n client.onTyping(conversationId, ({ userId, isTyping }) => {\n if (disposed || activeGeneration !== generation || userId === client.currentUserId) return\n const next = new Set(typingUserIds.value)\n if (isTyping) next.add(userId)\n else next.delete(userId)\n typingUserIds.value = next\n }, report),\n ]\n }\n\n const loadInitial = async () => {\n const client = toValue(options.client)\n const conversationId = toValue(options.conversationId).trim()\n if (!conversationId) throw new TypeError('conversationId is required')\n const activeGeneration = ++generation\n await unsubscribe()\n if (disposed || activeGeneration !== generation) return\n messages.value = []\n pendingIds.clear()\n conversation.value = null\n typingUserIds.value = new Set()\n readAtByUserId.value = new Map()\n hasOlderMessages.value = true\n error.value = null\n isInitialLoading.value = true\n isLoadingOlder.value = false\n subscribe(activeGeneration, client, conversationId)\n try {\n const [nextConversation, page] = await Promise.all([\n client.getConversation(conversationId),\n client.getMessages({ conversationId, limit: messagePageSize, offset: 0 }),\n ])\n if (disposed || activeGeneration !== generation) return\n conversation.value = nextConversation\n readAtByUserId.value = new Map(nextConversation.participants.flatMap((participant) =>\n participant.lastReadAt ? [[participant.appUserId, participant.lastReadAt] as const] : []))\n messages.value = mergeMessages([], page)\n hasOlderMessages.value = page.length === messagePageSize\n if (options.markReadOnLoad ?? true) await markRead()\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) {\n isInitialLoading.value = false\n hasLoaded.value = true\n }\n }\n }\n\n const loadOlderMessages = async () => {\n if (isInitialLoading.value || isLoadingOlder.value || !hasOlderMessages.value) return\n const activeGeneration = generation\n const client = toValue(options.client)\n const conversationId = toValue(options.conversationId)\n isLoadingOlder.value = true\n error.value = null\n try {\n const page = await client.getMessages({\n conversationId,\n limit: messagePageSize,\n offset: messages.value.filter((message) => !pendingIds.has(message.id)).length,\n })\n if (disposed || activeGeneration !== generation) return\n messages.value = mergeMessages(messages.value, page)\n hasOlderMessages.value = page.length === messagePageSize\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) isLoadingOlder.value = false\n }\n }\n\n const updateTyping = async (nextTyping: boolean) => {\n if (typingTimer) clearTimeout(typingTimer)\n if (nextTyping) typingTimer = setTimeout(() => { void updateTyping(false) }, typingTimeoutMs)\n if (sentTyping === nextTyping) return\n sentTyping = nextTyping\n try {\n await toValue(options.client).sendTyping({\n conversationId: toValue(options.conversationId),\n isTyping: nextTyping,\n })\n } catch (cause) {\n if (!disposed) error.value = cause\n }\n }\n\n const sendMessage = async ({ text, media }: { text?: string; media?: MessageMedia[] }) => {\n const normalizedText = text?.trim()\n if (!normalizedText && (!media || media.length === 0)) return null\n if (isSending.value) return null\n const pendingId = `convokit-pending-${Date.now()}-${++pendingSequence}`\n const pendingMessage: Message = {\n id: pendingId,\n conversationId: toValue(options.conversationId),\n senderId: toValue(options.client).currentUserId,\n text: normalizedText ?? null,\n media: media ?? [],\n createdAt: new Date(),\n updatedAt: null,\n }\n pendingIds.add(pendingId)\n messages.value = mergeMessages(messages.value, [pendingMessage])\n isSending.value = true\n error.value = null\n const activeGeneration = generation\n try {\n const message = await toValue(options.client).sendMessage({\n conversationId: toValue(options.conversationId),\n ...(normalizedText ? { text: normalizedText } : {}),\n ...(media?.length ? { media } : {}),\n })\n pendingIds.delete(pendingId)\n if (!disposed && activeGeneration === generation) {\n messages.value = mergeMessages(\n messages.value.filter((candidate) => candidate.id !== pendingId),\n [message],\n )\n }\n await updateTyping(false)\n return message\n } catch (cause) {\n pendingIds.delete(pendingId)\n if (!disposed) {\n messages.value = messages.value.filter((candidate) => candidate.id !== pendingId)\n error.value = cause\n }\n return null\n } finally {\n if (!disposed && activeGeneration === generation) isSending.value = false\n }\n }\n\n const dispose = async () => {\n disposed = true\n generation += 1\n if (typingTimer) clearTimeout(typingTimer)\n if (sentTyping) {\n await toValue(options.client).sendTyping({\n conversationId: toValue(options.conversationId),\n isTyping: false,\n }).catch(() => undefined)\n }\n await unsubscribe()\n }\n\n if (options.autoLoad ?? true) {\n watch(\n () => [toValue(options.client), toValue(options.conversationId)] as const,\n () => {\n disposed = false\n sentTyping = false\n void loadInitial()\n },\n { immediate: true },\n )\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n\n return {\n conversation,\n messages,\n typingUserIds,\n readAtByUserId,\n isInitialLoading,\n isLoadingOlder,\n isSending,\n hasOlderMessages,\n hasLoaded,\n error,\n currentUserId,\n readerIdsFor: (message) => readerIdsFor(message, readAtByUserId.value),\n loadInitial,\n refresh: loadInitial,\n loadOlderMessages,\n sendMessage,\n markRead,\n updateTyping,\n dispose,\n }\n}\n","import type { Conversation, Message, MessageMedia } from '@convokitapp/sdk'\nimport {\n Check,\n CheckCheck,\n ContactRound,\n Download,\n FileText,\n ImageOff,\n LoaderCircle,\n MapPin,\n MessageCircle,\n} from '@lucide/vue'\nimport {\n computed,\n defineComponent,\n h,\n nextTick,\n ref,\n watch,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type {\n ConvoKitAppearanceProps,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n MediaSlotProps,\n MessageSlotProps,\n ReadReceiptSlotProps,\n} from '../types'\nimport { cx, errorMessage, formatFileSize, isConvoKitPendingMessage, partClass, partStyle, readerIdsFor } from '../utils'\n\nexport interface MessageListViewProps extends ConvoKitAppearanceProps {\n conversation: Conversation\n messages: readonly Message[]\n currentUserId: string\n readAtByUserId?: ReadonlyMap<string, Date>\n readersResolver?: (message: Message) => ReadonlySet<string>\n onLoadOlder?: () => void | Promise<void>\n hasOlderMessages?: boolean\n isLoadingOlder?: boolean\n error?: unknown\n onAttachmentClick?: (media: MessageMedia, message: Message) => void\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n reverse?: boolean\n stickToBottom?: boolean\n formatTime?: (date: Date) => string\n imageLoading?: 'eager' | 'lazy'\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nfunction defaultFormatTime(date: Date): string {\n return new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: '2-digit' }).format(date)\n}\n\nfunction defaultMedia(\n media: MessageMedia,\n open: (() => void) | undefined,\n imageLoading: 'eager' | 'lazy',\n): VNodeChild {\n const tag = open ? 'button' : 'div'\n const interactive = open ? { type: 'button', onClick: open } : {}\n if (media.type === 'image') {\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--image' }, [\n media.url\n ? h('img', { src: media.url, alt: media.name ?? 'Shared image', loading: imageLoading })\n : h('span', { class: 'ckui-media-placeholder' }, [h(ImageOff, { 'aria-hidden': 'true' }), ' Image unavailable']),\n media.name ? h('span', { class: 'ckui-media-name' }, media.name) : null,\n ])\n }\n if (media.type === 'file') {\n const size = formatFileSize(media.size)\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--file' }, [\n h(FileText, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Attachment'), size ? h('small', size) : null]),\n open ? h(Download, { size: 18, 'aria-hidden': 'true' }) : null,\n ])\n }\n if (media.type === 'location') {\n const label = media.name || `${media.metadata.lat}, ${media.metadata.lng}`\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--location' }, [\n h(MapPin, { 'aria-hidden': 'true' }),\n h('span', [h('strong', label), h('small', `${media.metadata.lat}, ${media.metadata.lng}`)]),\n ])\n }\n const contact = media.metadata.email || media.metadata.phone || 'Contact details'\n return h(tag, { ...interactive, class: 'ckui-media-card ckui-media-card--contact' }, [\n h(ContactRound, { 'aria-hidden': 'true' }),\n h('span', [h('strong', media.name || 'Shared contact'), h('small', String(contact))]),\n ])\n}\n\n/** Controlled message history with read receipts, structured media, and older-page loading. */\nexport const MessageListView = defineComponent({\n name: 'MessageListView',\n inheritAttrs: false,\n props: {\n ...appearanceProps,\n conversation: { type: Object as PropType<Conversation>, required: true },\n messages: { type: Array as PropType<readonly Message[]>, required: true },\n currentUserId: { type: String, required: true },\n readAtByUserId: { type: Object as PropType<ReadonlyMap<string, Date>>, default: () => new Map() },\n readersResolver: { type: Function as PropType<(message: Message) => ReadonlySet<string>>, default: undefined },\n onLoadOlder: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n hasOlderMessages: { type: Boolean, default: false },\n isLoadingOlder: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n onAttachmentClick: { type: Function as PropType<(media: MessageMedia, message: Message) => void>, default: undefined },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n reverse: { type: Boolean, default: true },\n stickToBottom: { type: Boolean, default: true },\n formatTime: { type: Function as PropType<(date: Date) => string>, default: defaultFormatTime },\n imageLoading: { type: String as PropType<'eager' | 'lazy'>, default: 'lazy' },\n },\n emits: ['load-older', 'attachment-click'],\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n let previousMessageCount = 0\n const participants = computed(() => new Map(props.conversation.participants.flatMap((participant) => [\n [participant.id, participant] as const,\n [participant.appUserId, participant] as const,\n ])))\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestOlder = async () => {\n if (requestInFlight || lastRequestedLength === props.messages.length || props.isLoadingOlder || !props.hasOlderMessages || !props.onLoadOlder) return\n requestInFlight = true\n lastRequestedLength = props.messages.length\n try { await props.onLoadOlder() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n watch(() => [props.messages.length, props.hasOlderMessages] as const, async ([count, hasOlder]) => {\n const previous = previousMessageCount\n if (count !== previousMessageCount || !hasOlder) lastRequestedLength = null\n const appended = count > previous\n const element = internalElement.value\n previousMessageCount = count\n if (element && props.reverse && props.stickToBottom && appended) {\n const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight\n if (previous === 0 || distanceFromBottom < 320) {\n await nextTick()\n element.scrollTop = element.scrollHeight\n }\n }\n }, { flush: 'post', immediate: true })\n\n const renderMessage = (message: Message, index: number): VNodeChild => {\n const isCurrentUser = message.senderId === props.currentUserId\n const sender = participants.value.get(message.senderId)\n const isPending = isConvoKitPendingMessage(message)\n const readerIds = isPending\n ? new Set<string>()\n : props.readersResolver ? props.readersResolver(message) : readerIdsFor(message, props.readAtByUserId)\n const slotProps: MessageSlotProps = { message, chronologicalIndex: index, isCurrentUser, sender, readerIds }\n const custom = slots.message?.(slotProps)\n if (custom) return h('div', { key: message.id, role: 'listitem' }, custom)\n const currentAppearance = appearance()\n const messagePart = isCurrentUser ? 'outgoingMessage' : 'incomingMessage'\n const mediaNodes = message.media.map((media, mediaIndex) => {\n const open = props.onAttachmentClick\n ? () => {\n props.onAttachmentClick?.(media, message)\n }\n : undefined\n const mediaSlotProps: MediaSlotProps = { media, message, isCurrentUser, ...(open ? { open } : {}) }\n return h('div', {\n key: media.id ?? `${media.type}-${mediaIndex}`,\n class: partClass('media', currentAppearance, 'ckui-media'),\n style: partStyle('media', currentAppearance),\n }, slots.media?.(mediaSlotProps) ?? [defaultMedia(media, open, props.imageLoading)])\n })\n const receiptSlotProps: ReadReceiptSlotProps = { message, readerIds }\n return h('div', { key: message.id, role: 'listitem' }, [\n h('article', {\n class: cx(\n !props.unstyled && 'ckui-message-row',\n isCurrentUser && !props.unstyled && 'ckui-message-row--outgoing',\n props.classNames?.message,\n props.classNames?.[messagePart],\n ),\n style: [props.styles?.message, props.styles?.[messagePart]],\n 'data-message-id': message.id,\n }, [\n h('div', { class: 'ckui-message-bubble' }, [\n !isCurrentUser ? h('strong', { class: 'ckui-message-sender' }, sender?.name || message.senderId) : null,\n message.text ? h('div', { class: 'ckui-message-text' }, message.text) : null,\n ...mediaNodes,\n h('span', { class: 'ckui-message-time' }, [\n isPending ? 'Sending…' : props.formatTime(message.createdAt),\n isCurrentUser && !isPending\n ? readerIds.size > 0\n ? h(CheckCheck, { size: 14, 'aria-label': 'Read' })\n : h(Check, { size: 14, 'aria-label': 'Delivered' })\n : null,\n ]),\n ]),\n isCurrentUser && !isPending\n ? slots['read-receipt']?.(receiptSlotProps) ?? h('div', {\n class: partClass('receipt', currentAppearance, 'ckui-read-receipt'),\n style: partStyle('receipt', currentAppearance),\n }, readerIds.size > 0 ? `Read by ${readerIds.size}` : 'Delivered')\n : null,\n ]),\n ])\n }\n\n return () => {\n const currentAppearance = appearance()\n const children: VNodeChild[] = []\n if (props.isLoadingOlder) {\n children.push(slots['loading-older']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading older messages…']))\n }\n if (props.error) {\n const retry = props.onLoadOlder ? () => { void requestOlder() } : undefined\n children.push(slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Retry') : null,\n ]))\n }\n if (props.messages.length === 0 && !props.isLoadingOlder) {\n children.push(slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(MessageCircle, { 'aria-hidden': 'true' }), ' No messages yet']))\n } else {\n children.push(...props.messages.map(renderMessage))\n }\n return h('div', {\n ...attrs,\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui ckui-message-list', props.classNames?.messages, attrs.class),\n style: [props.styles?.messages, attrs.style],\n 'data-density': props.density,\n role: 'log',\n 'aria-live': 'polite',\n 'aria-label': `Messages in ${props.conversation.displayTitle}`,\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n const element = event.currentTarget as HTMLElement\n const distanceFromOldest = props.reverse\n ? element.scrollTop\n : element.scrollHeight - element.scrollTop - element.clientHeight\n if (distanceFromOldest <= props.paginationThreshold) void requestOlder()\n },\n }, children)\n }\n },\n})\n\nexport function defaultReadersResolver(readAtByUserId: ReadonlyMap<string, Date>): (message: Message) => ReadonlySet<string> {\n return (message) => readerIdsFor(message, readAtByUserId)\n}\n","import type { Conversation } from '@convokitapp/sdk'\nimport { ChevronRight, Inbox, LoaderCircle, RefreshCw } from '@lucide/vue'\nimport {\n defineComponent,\n h,\n ref,\n watchEffect,\n type CSSProperties,\n type PropType,\n type Ref,\n type VNodeChild,\n} from 'vue'\nimport type { ConversationListController, UseConversationListOptions } from '../composables/use-conversation-list'\nimport { useConversationList } from '../composables/use-conversation-list'\nimport type {\n ConversationFilter,\n ConversationItemSlotProps,\n ConversationPageLoader,\n ConvoKitAppearanceProps,\n ConvoKitUiClient,\n ConvoKitUiDensity,\n ConvoKitUiPart,\n} from '../types'\nimport { cx, errorMessage, partClass, partStyle } from '../utils'\nimport { ConvoKitAvatar } from './avatar'\n\nexport interface ConversationListViewProps extends ConvoKitAppearanceProps {\n conversations: readonly Conversation[]\n selectedConversationId?: string\n onConversationSelect?: (conversation: Conversation) => void\n onRefresh?: () => void | Promise<void>\n onLoadMore?: () => void | Promise<void>\n isInitialLoading?: boolean\n isLoadingMore?: boolean\n hasMore?: boolean\n error?: unknown\n scrollElement?: Ref<HTMLElement | null>\n paginationThreshold?: number\n ariaLabel?: string\n class?: unknown\n style?: unknown\n}\n\nconst appearanceProps = {\n classNames: { type: Object as PropType<Partial<Record<ConvoKitUiPart, string>>>, default: undefined },\n styles: { type: Object as PropType<Partial<Record<ConvoKitUiPart, CSSProperties>>>, default: undefined },\n density: { type: String as PropType<ConvoKitUiDensity>, default: 'comfortable' },\n unstyled: { type: Boolean, default: false },\n} as const\n\nconst listViewProps = {\n ...appearanceProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, required: true },\n selectedConversationId: { type: String, default: undefined },\n onConversationSelect: { type: Function as PropType<(conversation: Conversation) => void>, default: undefined },\n onRefresh: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n onLoadMore: { type: Function as PropType<() => void | Promise<void>>, default: undefined },\n isInitialLoading: { type: Boolean, default: false },\n isLoadingMore: { type: Boolean, default: false },\n hasMore: { type: Boolean, default: false },\n error: { type: null as unknown as PropType<unknown>, required: false },\n scrollElement: { type: Object as PropType<Ref<HTMLElement | null>>, default: undefined },\n paginationThreshold: { type: Number, default: 240 },\n ariaLabel: { type: String, default: 'Conversations' },\n} as const\n\n/** Controlled conversation list. It can be used with any state-management layer. */\nexport const ConversationListView = defineComponent({\n name: 'ConversationListView',\n inheritAttrs: false,\n props: listViewProps,\n emits: {\n 'conversation-select': (_conversation: Conversation) => true,\n refresh: () => true,\n 'load-more': () => true,\n },\n setup(props, { attrs, emit, slots }) {\n const internalElement = ref<HTMLElement | null>(null)\n let requestInFlight = false\n let lastRequestedLength: number | null = null\n\n const appearance = (): ConvoKitAppearanceProps => ({\n density: props.density,\n unstyled: props.unstyled,\n ...(props.classNames ? { classNames: props.classNames } : {}),\n ...(props.styles ? { styles: props.styles } : {}),\n })\n\n const requestMore = async () => {\n if (requestInFlight || lastRequestedLength === props.conversations.length || props.isInitialLoading || props.isLoadingMore || !props.hasMore || !props.onLoadMore) return\n requestInFlight = true\n lastRequestedLength = props.conversations.length\n try { await props.onLoadMore() }\n catch { lastRequestedLength = null }\n finally { requestInFlight = false }\n }\n\n const selectConversation = (conversation: Conversation) => {\n props.onConversationSelect?.(conversation)\n }\n\n const refresh = () => {\n return props.onRefresh?.()\n }\n\n const renderContent = () => {\n const currentAppearance = appearance()\n if (props.isInitialLoading && props.conversations.length === 0) {\n return slots['initial-loading']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading conversations…'])\n }\n if (props.error && props.conversations.length === 0) {\n const retry = props.onRefresh ? () => { void refresh() } : undefined\n return slots.error?.({ error: props.error, ...(retry ? { retry } : {}) }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [\n h('span', errorMessage(props.error)),\n retry ? h('button', { type: 'button', class: 'ckui-link-button', onClick: retry }, 'Try again') : null,\n ])\n }\n if (props.conversations.length === 0) {\n return slots.empty?.() ?? h('div', {\n class: partClass('empty', currentAppearance, 'ckui-state'),\n style: partStyle('empty', currentAppearance),\n }, [h(Inbox, { 'aria-hidden': 'true' }), ' No conversations yet'])\n }\n const children: VNodeChild[] = props.conversations.flatMap((conversation, index) => {\n const selected = props.selectedConversationId === conversation.id\n const select = () => selectConversation(conversation)\n const slotProps: ConversationItemSlotProps = { conversation, index, selected, select }\n const item = slots['conversation-item']?.(slotProps) ?? h('button', {\n type: 'button',\n 'data-selected': selected || undefined,\n 'aria-current': selected ? 'true' : undefined,\n onClick: select,\n class: partClass('listItem', currentAppearance, 'ckui-conversation-item'),\n style: partStyle('listItem', currentAppearance),\n }, [\n h(ConvoKitAvatar, {\n name: conversation.displayTitle,\n src: conversation.imageUrl,\n class: partClass('avatar', currentAppearance, ''),\n style: partStyle('avatar', currentAppearance),\n } as never),\n h('span', { class: 'ckui-conversation-item__body' }, [\n h('strong', conversation.displayTitle),\n h('span', conversation.participants.map((participant) => participant.name).join(', ') || conversation.description || 'No participants'),\n ]),\n h(ChevronRight, { size: 18, 'aria-hidden': 'true' }),\n ])\n const nodes = [h('div', { key: conversation.id, role: 'listitem' }, [item])]\n if (index < props.conversations.length - 1) {\n nodes.push(h('div', { key: `${conversation.id}-separator` }, slots.separator?.({ index }) ?? h('div', { class: 'ckui-separator' })))\n }\n return nodes\n })\n if (props.error) {\n children.push(slots.error?.({ error: props.error, retry: requestMore }) ?? h('div', {\n class: partClass('error', currentAppearance, 'ckui-inline-state ckui-state--error'),\n style: partStyle('error', currentAppearance),\n role: 'alert',\n }, [h('span', errorMessage(props.error)), h('button', { type: 'button', class: 'ckui-link-button', onClick: () => { void requestMore() } }, 'Retry')]))\n } else if (props.isLoadingMore) {\n children.push(slots['load-more']?.() ?? h('div', {\n class: partClass('loading', currentAppearance, 'ckui-inline-state'),\n style: partStyle('loading', currentAppearance),\n role: 'status',\n }, [h(LoaderCircle, { class: 'ckui-spin', 'aria-hidden': 'true' }), ' Loading more…']))\n }\n return h('div', {\n role: 'list',\n class: partClass('list', currentAppearance, 'ckui-conversation-list__items'),\n style: partStyle('list', currentAppearance),\n }, children)\n }\n\n return () => h('div', {\n ...attrs,\n class: cx(!props.unstyled && 'ckui ckui-conversation-list', props.classNames?.root, attrs.class),\n style: [props.styles?.root, attrs.style],\n 'data-density': props.density,\n }, [\n props.onRefresh ? h('div', { class: 'ckui-conversation-list__toolbar' }, [\n h('span', props.ariaLabel),\n h('button', {\n type: 'button',\n 'aria-label': 'Refresh conversations',\n class: partClass('button', appearance(), 'ckui-icon-button'),\n style: partStyle('button', appearance()),\n onClick: () => { void refresh() },\n }, [h(RefreshCw, { size: 17, 'aria-hidden': 'true' })]),\n ]) : null,\n h('div', {\n ref: (element: unknown) => {\n internalElement.value = element as HTMLElement | null\n if (props.scrollElement) props.scrollElement.value = element as HTMLElement | null\n },\n class: cx(!props.unstyled && 'ckui-scroll-area', props.classNames?.list),\n style: props.styles?.list,\n 'aria-label': props.ariaLabel,\n onScroll: (event: Event) => {\n const nativeHandler = attrs.onScroll\n if (typeof nativeHandler === 'function') nativeHandler(event)\n const element = event.currentTarget as HTMLElement\n if (element.scrollHeight - element.scrollTop - element.clientHeight <= props.paginationThreshold) void requestMore()\n },\n }, [renderContent()]),\n ])\n },\n})\n\nexport interface ConversationListProps extends Omit<ConversationListViewProps,\n 'conversations' | 'onRefresh' | 'onLoadMore' | 'isInitialLoading' | 'isLoadingMore' | 'hasMore' | 'error'>,\n Omit<UseConversationListOptions, 'client'> {\n client: ConvoKitUiClient\n onControllerChange?: (controller: ConversationListController) => void\n}\n\n/** Plug-and-play SDK-backed conversation list. */\nexport const ConversationList = defineComponent({\n name: 'ConversationList',\n inheritAttrs: false,\n props: {\n ...listViewProps,\n conversations: { type: Array as PropType<readonly Conversation[]>, default: () => [] },\n client: { type: Object as PropType<ConvoKitUiClient>, required: true },\n pageLoader: { type: Function as PropType<ConversationPageLoader>, default: undefined },\n initialFilter: { type: Object as PropType<ConversationFilter>, default: undefined },\n pageSize: { type: Number, default: 30 },\n autoLoad: { type: Boolean, default: true },\n onControllerChange: { type: Function as PropType<(controller: ConversationListController) => void>, default: undefined },\n },\n emits: ['conversation-select', 'controller-change'],\n setup(props, { attrs, emit, expose, slots }) {\n const controller = useConversationList({\n client: () => props.client,\n ...(props.pageLoader ? { pageLoader: props.pageLoader } : {}),\n ...(props.initialFilter ? { initialFilter: props.initialFilter } : {}),\n pageSize: props.pageSize,\n autoLoad: props.autoLoad,\n })\n expose({ controller })\n watchEffect(() => {\n emit('controller-change', controller)\n })\n return () => {\n const {\n client: _client,\n pageLoader: _pageLoader,\n initialFilter: _initialFilter,\n pageSize: _pageSize,\n autoLoad: _autoLoad,\n onControllerChange: _onControllerChange,\n conversations: _conversations,\n onRefresh: _onRefresh,\n onLoadMore: _onLoadMore,\n isInitialLoading: _isInitialLoading,\n isLoadingMore: _isLoadingMore,\n hasMore: _hasMore,\n error: _error,\n ...forwarded\n } = props\n return h(ConversationListView, {\n ...attrs,\n ...forwarded,\n conversations: controller.conversations.value,\n onRefresh: controller.refresh,\n onLoadMore: controller.loadMore,\n isInitialLoading: controller.isInitialLoading.value,\n isLoadingMore: controller.isLoadingMore.value,\n hasMore: controller.hasMore.value,\n ...(controller.error.value == null ? {} : { error: controller.error.value }),\n onConversationSelect: (conversation: Conversation) => {\n emit('conversation-select', conversation)\n },\n } as never, slots)\n }\n },\n})\n","import type { Conversation } from '@convokitapp/sdk'\nimport {\n computed,\n getCurrentScope,\n onScopeDispose,\n ref,\n shallowRef,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from 'vue'\nimport type {\n ConversationFilter,\n ConversationListState,\n ConversationPageLoader,\n ConvoKitUiClient,\n} from '../types'\nimport { applyConversationFilter, mergeConversations } from '../utils'\n\nexport interface UseConversationListOptions {\n client: MaybeRefOrGetter<ConvoKitUiClient>\n pageLoader?: ConversationPageLoader\n initialFilter?: ConversationFilter\n pageSize?: number\n autoLoad?: boolean\n}\n\nexport interface ConversationListController extends ConversationListState {\n loadInitial(): Promise<void>\n refresh(): Promise<void>\n loadMore(): Promise<void>\n setFilter(filter: ConversationFilter): Promise<void>\n setQuery(query: string): Promise<void>\n dispose(): Promise<void>\n}\n\n/** Loads, de-duplicates, filters, and paginates conversations. */\nexport function useConversationList(options: UseConversationListOptions): ConversationListController {\n const pageSize = options.pageSize ?? 30\n if (!Number.isInteger(pageSize) || pageSize <= 0) throw new RangeError('pageSize must be a positive integer')\n\n const source = shallowRef<Conversation[]>([])\n const filter = shallowRef<ConversationFilter>(options.initialFilter ?? {})\n const isInitialLoading = ref(false)\n const isLoadingMore = ref(false)\n const hasMore = ref(true)\n const hasLoaded = ref(false)\n const error = shallowRef<unknown>(null)\n const conversations = computed(() => applyConversationFilter(source.value, filter.value))\n let offset = 0\n let generation = 0\n let disposed = false\n\n const loadUntilVisible = async (activeGeneration: number, activeFilter: ConversationFilter) => {\n const visibleBefore = applyConversationFilter(source.value, activeFilter).length\n while (true) {\n const request = { limit: pageSize, offset, filter: activeFilter }\n const page = options.pageLoader\n ? await options.pageLoader(request)\n : await toValue(options.client).getConversations({\n limit: pageSize,\n offset: request.offset,\n archived: activeFilter.archived ?? false,\n })\n if (disposed || activeGeneration !== generation) return\n offset += page.length\n hasMore.value = page.length === pageSize\n source.value = mergeConversations(source.value, page)\n if (!hasMore.value || applyConversationFilter(source.value, activeFilter).length > visibleBefore) return\n }\n }\n\n const loadInitialFor = async (activeFilter: ConversationFilter = filter.value) => {\n const activeGeneration = ++generation\n source.value = []\n offset = 0\n hasMore.value = true\n isInitialLoading.value = true\n isLoadingMore.value = false\n error.value = null\n try {\n await loadUntilVisible(activeGeneration, activeFilter)\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) {\n isInitialLoading.value = false\n hasLoaded.value = true\n }\n }\n }\n\n const loadMore = async () => {\n if (isInitialLoading.value || isLoadingMore.value || !hasMore.value) return\n const activeGeneration = generation\n isLoadingMore.value = true\n error.value = null\n try {\n await loadUntilVisible(activeGeneration, filter.value)\n } catch (cause) {\n if (!disposed && activeGeneration === generation) error.value = cause\n } finally {\n if (!disposed && activeGeneration === generation) isLoadingMore.value = false\n }\n }\n\n const setFilter = async (nextFilter: ConversationFilter) => {\n const previousArchived = filter.value.archived ?? false\n filter.value = nextFilter\n error.value = null\n if ((nextFilter.archived ?? false) !== previousArchived || !hasLoaded.value) {\n await loadInitialFor(nextFilter)\n } else if (applyConversationFilter(source.value, nextFilter).length === 0 && hasMore.value) {\n await loadMore()\n }\n }\n\n const setQuery = (query: string) => setFilter({ ...filter.value, query })\n const dispose = async () => {\n disposed = true\n generation += 1\n }\n\n if (options.autoLoad ?? true) {\n watch(() => toValue(options.client), () => {\n disposed = false\n void loadInitialFor(filter.value)\n }, { immediate: true })\n }\n if (getCurrentScope()) onScopeDispose(() => { void dispose() })\n\n return {\n conversations,\n filter,\n isInitialLoading,\n isLoadingMore,\n hasMore,\n hasLoaded,\n error,\n loadInitial: loadInitialFor,\n refresh: loadInitialFor,\n loadMore,\n setFilter,\n setQuery,\n dispose,\n }\n}\n","import {\n computed,\n defineComponent,\n h,\n inject,\n provide,\n type CSSProperties,\n type InjectionKey,\n type PropType,\n type Ref,\n} from 'vue'\nimport { cx } from './utils'\n\nexport interface ConvoKitTheme {\n background: string\n surface: string\n primary: string\n text: string\n mutedText: string\n border: string\n error: string\n incomingBubble: string\n outgoingBubble: string\n outgoingText: string\n radius: string\n avatarSize: string\n fontFamily: string\n}\n\nexport const defaultConvoKitTheme: ConvoKitTheme = {\n background: '#fafafa',\n surface: '#ffffff',\n primary: '#18181b',\n text: '#09090b',\n mutedText: '#71717a',\n border: '#e4e4e7',\n error: '#dc2626',\n incomingBubble: '#f4f4f5',\n outgoingBubble: '#18181b',\n outgoingText: '#fafafa',\n radius: '10px',\n avatarSize: '40px',\n fontFamily: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n}\n\nconst themeKey: InjectionKey<Readonly<Ref<ConvoKitTheme>>> = Symbol('ConvoKitTheme')\nconst defaultThemeRef = computed(() => defaultConvoKitTheme)\n\nexport const ConvoKitThemeProvider = defineComponent({\n name: 'ConvoKitThemeProvider',\n inheritAttrs: false,\n props: {\n theme: { type: Object as PropType<Partial<ConvoKitTheme>>, default: () => ({}) },\n class: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n style: { type: [String, Array, Object] as PropType<unknown>, default: undefined },\n },\n setup(props, { attrs, slots }) {\n const parent = inject(themeKey, defaultThemeRef)\n const value = computed(() => ({ ...parent.value, ...props.theme }))\n provide(themeKey, value)\n return () => {\n const theme = value.value\n const variables = {\n '--ckui-background': theme.background,\n '--ckui-surface': theme.surface,\n '--ckui-primary': theme.primary,\n '--ckui-text': theme.text,\n '--ckui-muted': theme.mutedText,\n '--ckui-border': theme.border,\n '--ckui-error': theme.error,\n '--ckui-incoming': theme.incomingBubble,\n '--ckui-outgoing': theme.outgoingBubble,\n '--ckui-outgoing-text': theme.outgoingText,\n '--ckui-radius': theme.radius,\n '--ckui-avatar-size': theme.avatarSize,\n '--ckui-font': theme.fontFamily,\n } as CSSProperties\n return h('div', {\n ...attrs,\n class: cx('ckui-theme', props.class, attrs.class),\n style: [variables, props.style, attrs.style],\n }, slots.default?.())\n }\n },\n})\n\nexport function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>> {\n return inject(themeKey, defaultThemeRef)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIO,SAAS,uBAAuB,QAA0C;AAC/E,SAAO;AAAA,IACL,IAAI,gBAAgB;AAAE,aAAO,OAAO;AAAA,IAAc;AAAA,IAClD,kBAAkB,CAAC,YAAY,OAAO,iBAAiB,OAAO;AAAA,IAC9D,iBAAiB,CAAC,mBAAmB,OAAO,gBAAgB,cAAc;AAAA,IAC1E,aAAa,CAAC,YAAY,OAAO,YAAY,OAAO;AAAA,IACpD,aAAa,CAAC,UAAU,OAAO,YAAY,KAAK;AAAA,IAChD,sBAAsB,CAAC,mBAAmB,OAAO,qBAAqB,cAAc;AAAA,IACpF,YAAY,CAAC,UAAU,OAAO,WAAW,KAAK;AAAA,IAC9C,WAAW,CAAC,gBAAgB,SAAS,YAAY,OAAO,SAAS,UAAU,gBAAgB;AAAA,MACzF,SAAS;AAAA,MACT,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B,CAAC;AAAA,IACD,eAAe,CAAC,gBAAgB,SAAS,YAAY,OAAO,SAAS,cAAc,gBAAgB;AAAA,MACjG,SAAS;AAAA,MACT,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B,CAAC;AAAA,IACD,UAAU,CAAC,gBAAgB,SAAS,YAAY,OAAO,SAAS,SAAS,gBAAgB;AAAA,MACvF,SAAS;AAAA,MACT,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B,CAAC;AAAA,EACH;AACF;;;AC1BA,qBAAwD;AACxD,iBAAkD;;;ACAlD,kBAAsC;AAItC,IAAM,yBAAyB;AAGxB,SAAS,yBAAyB,SAA2B;AAClE,SAAO,QAAQ,GAAG,WAAW,sBAAsB;AACrD;AAEO,SAAS,MAAM,QAA8B;AAAE,aAAO,kBAAK,MAAM;AAAE;AAE1E,SAAS,wBAAwB,QAAiD;AAChF,QAAM,SAAS,OAAO,kBAAkB,CAAC;AACzC,SAAO,kBAAkB,MAAM,SAAS,IAAI,IAAI,MAAM;AACxD;AAEO,SAAS,oBAAoB,cAA4B,QAAqC;AACnG,QAAM,QAAQ,OAAO,OAAO,KAAK,EAAE,kBAAkB,KAAK;AAC1D,MAAI,OAAO;AACT,UAAM,WAAW;AAAA,MACf,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa,SAAS;AAAA,MACtB,aAAa,eAAe;AAAA,MAC5B,GAAG,aAAa,aAAa,QAAQ,CAAC,gBAAgB,CAAC,YAAY,IAAI,YAAY,WAAW,YAAY,IAAI,CAAC;AAAA,IACjH,EAAE,KAAK,GAAG,EAAE,kBAAkB;AAC9B,QAAI,CAAC,SAAS,SAAS,KAAK,EAAG,QAAO;AAAA,EACxC;AACA,QAAM,YAAY,wBAAwB,MAAM;AAChD,MAAI,UAAU,OAAO,GAAG;AACtB,UAAM,YAAY,IAAI,IAAI,aAAa,aAAa,QAAQ,CAAC,gBAAgB,CAAC,YAAY,IAAI,YAAY,SAAS,CAAC,CAAC;AACrH,UAAM,SAAS,CAAC,GAAG,SAAS;AAC5B,UAAM,UAAU,OAAO,yBACnB,OAAO,MAAM,CAAC,OAAO,UAAU,IAAI,EAAE,CAAC,IACtC,OAAO,KAAK,CAAC,OAAO,UAAU,IAAI,EAAE,CAAC;AACzC,QAAI,CAAC,QAAS,QAAO;AAAA,EACvB;AACA,SAAO,OAAO,YAAY,YAAY,KAAK;AAC7C;AAEO,SAAS,wBAAwB,eAAwC,QAA4C;AAC1H,QAAM,SAAS,cAAc,OAAO,CAAC,iBAAiB,oBAAoB,cAAc,MAAM,CAAC;AAC/F,MAAI,OAAO,WAAY,QAAO,KAAK,OAAO,UAAU;AACpD,SAAO;AACT;AAEO,SAAS,mBAAmB,SAAkC,UAAmD;AACtH,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,iBAAiB,CAAC,aAAa,IAAI,YAAY,CAAC,CAAC;AACnF,aAAW,gBAAgB,SAAU,MAAK,IAAI,aAAa,IAAI,YAAY;AAC3E,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;AAEO,SAAS,cAAc,SAA6B,UAAyC;AAClG,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;AACpE,aAAW,WAAW,SAAU,MAAK,IAAI,QAAQ,IAAI,OAAO;AAC5D,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,UAAU;AAC9C,UAAM,cAAc,yBAAyB,IAAI;AACjD,UAAM,eAAe,yBAAyB,KAAK;AACnD,QAAI,gBAAgB,aAAc,QAAO,cAAc,IAAI;AAC3D,UAAM,SAAS,KAAK,UAAU,QAAQ,IAAI,MAAM,UAAU,QAAQ;AAClE,WAAO,WAAW,IAAI,KAAK,GAAG,cAAc,MAAM,EAAE,IAAI;AAAA,EAC1D,CAAC;AACH;AAEO,SAAS,aAAa,SAAkB,gBAAgE;AAC7G,MAAI,yBAAyB,OAAO,EAAG,QAAO,oBAAI,IAAI;AACtD,SAAO,IAAI,IAAI,CAAC,GAAG,eAAe,QAAQ,CAAC,EACxC,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,WAAW,QAAQ,YAAY,OAAO,QAAQ,KAAK,QAAQ,UAAU,QAAQ,CAAC,EAC3G,IAAI,CAAC,CAAC,MAAM,MAAM,MAAM,CAAC;AAC9B;AAEO,SAAS,UAAU,MAAsB,YAAqC,cAA8B;AACjH,SAAO,GAAG,CAAC,WAAW,YAAY,cAAc,WAAW,aAAa,IAAI,CAAC;AAC/E;AAEO,SAAS,UAAU,MAAsB,YAAgE;AAC9G,SAAO,WAAW,SAAS,IAAI;AACjC;AAEO,SAAS,aAAa,OAAwB;AAAE,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAE;AAE9G,SAAS,eAAe,MAAyC;AACtE,MAAI,SAAS,UAAa,CAAC,OAAO,SAAS,IAAI,KAAK,OAAO,EAAG,QAAO;AACrE,MAAI,OAAO,KAAM,QAAO,GAAG,KAAK,MAAM,IAAI,CAAC;AAC3C,MAAI,OAAO,OAAO,KAAM,QAAO,IAAI,OAAO,MAAM,QAAQ,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC;AACjF,SAAO,IAAI,QAAQ,OAAO,OAAO,QAAQ,OAAO,KAAK,OAAO,OAAO,IAAI,CAAC,CAAC;AAC3E;AAEO,SAAS,SAAS,OAAuB;AAC9C,QAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACtD,UAAQ,MAAM,SAAS,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,MAAM,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,MAAM,CAAC,KAAK,KAAK,kBAAkB;AACrH;;;ADzFO,IAAM,qBAAiB,4BAAgB;AAAA,EAC5C,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,IACL,MAAM,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,IACrC,KAAK,EAAE,MAAM,QAAmC,SAAS,KAAK;AAAA,EAChE;AAAA,EACA,MAAM,OAAO,EAAE,MAAM,GAAG;AACtB,WAAO,UAAM,cAAE,2BAAY;AAAA,MACzB,GAAG;AAAA,MACH,OAAO,GAAG,eAAe,MAAM,KAAK;AAAA,IACtC,GAAG;AAAA,MACD,SAAS,MAAM;AAAA,QACb,MAAM,UAAM,cAAE,4BAAa,EAAE,OAAO,sBAAsB,KAAK,MAAM,KAAK,KAAK,GAAG,CAAC,IAAI;AAAA,YACvF,cAAE,+BAAgB;AAAA,UAChB,OAAO;AAAA,UACP,GAAI,MAAM,MAAM,EAAE,SAAS,IAAI,IAAI,CAAC;AAAA,QACtC,GAAG,MAAM,SAAS,MAAM,IAAI,CAAC;AAAA,MAC/B;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;;;AEzBD,IAAAA,cAAoE;AACpE,IAAAA,cASO;;;ACVP,IAAAC,cASO;AAyBA,SAAS,gBAAgB,SAAyD;AACvF,QAAM,kBAAkB,QAAQ,mBAAmB;AACnD,QAAM,kBAAkB,QAAQ,mBAAmB;AACnD,MAAI,KAAC,qBAAQ,QAAQ,cAAc,EAAE,KAAK,EAAG,OAAM,IAAI,UAAU,4BAA4B;AAC7F,MAAI,CAAC,OAAO,UAAU,eAAe,KAAK,mBAAmB,EAAG,OAAM,IAAI,WAAW,4CAA4C;AACjI,MAAI,CAAC,OAAO,SAAS,eAAe,KAAK,kBAAkB,EAAG,OAAM,IAAI,WAAW,sCAAsC;AAEzH,QAAM,mBAAe,wBAAuD,IAAI;AAChF,QAAM,eAAW,wBAAsB,CAAC,CAAC;AACzC,QAAM,oBAAgB,wBAAgC,oBAAI,IAAI,CAAC;AAC/D,QAAM,qBAAiB,wBAAsC,oBAAI,IAAI,CAAC;AACtE,QAAM,uBAAmB,iBAAI,KAAK;AAClC,QAAM,qBAAiB,iBAAI,KAAK;AAChC,QAAM,gBAAY,iBAAI,KAAK;AAC3B,QAAM,uBAAmB,iBAAI,IAAI;AACjC,QAAM,gBAAY,iBAAI,KAAK;AAC3B,QAAM,YAAQ,wBAAoB,IAAI;AACtC,QAAM,oBAAgB,sBAAS,UAAM,qBAAQ,QAAQ,MAAM,EAAE,aAAa;AAE1E,MAAI,aAAa;AACjB,MAAI,WAAW;AACf,MAAI,aAAa;AACjB,MAAI,cAAoD;AACxD,MAAI,gBAAwC,CAAC;AAC7C,QAAM,aAAa,oBAAI,IAAY;AACnC,MAAI,kBAAkB;AAEtB,QAAM,cAAc,YAAY;AAC9B,UAAM,SAAS;AACf,oBAAgB,CAAC;AACjB,UAAM,QAAQ,IAAI,OAAO,IAAI,CAAC,iBAAiB,aAAa,YAAY,CAAC,CAAC;AAAA,EAC5E;AAEA,QAAM,WAAW,YAAY;AAC3B,UAAM,aAAS,qBAAQ,QAAQ,MAAM;AACrC,UAAM,qBAAiB,qBAAQ,QAAQ,cAAc;AACrD,QAAI;AACF,YAAM,OAAO,qBAAqB,cAAc;AAChD,UAAI,SAAU;AACd,qBAAe,QAAQ,IAAI,IAAI,eAAe,KAAK,EAAE,IAAI,OAAO,eAAe,oBAAI,KAAK,CAAC;AAAA,IAC3F,SAAS,OAAO;AACd,UAAI,CAAC,SAAU,OAAM,QAAQ;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,YAAY,CAAC,kBAA0B,QAA0B,mBAA2B;AAChG,UAAM,SAAS,CAAC,UAAiB;AAC/B,UAAI,CAAC,YAAY,qBAAqB,WAAY,OAAM,QAAQ;AAAA,IAClE;AACA,oBAAgB;AAAA,MACd,OAAO,UAAU,gBAAgB,CAAC,YAAY;AAC5C,YAAI,YAAY,qBAAqB,WAAY;AACjD,cAAM,UAAU,SAAS,MAAM,KAAK,CAAC,cACnC,WAAW,IAAI,UAAU,EAAE,KAC3B,QAAQ,aAAa,OAAO,iBAC5B,UAAU,SAAS,QAAQ,QAC3B,UAAU,MAAM,WAAW,QAAQ,MAAM,MAAM;AACjD,YAAI,QAAS,YAAW,OAAO,QAAQ,EAAE;AACzC,iBAAS,QAAQ;AAAA,UACf,UAAU,SAAS,MAAM,OAAO,CAAC,cAAc,UAAU,OAAO,QAAQ,EAAE,IAAI,SAAS;AAAA,UACvF,CAAC,OAAO;AAAA,QACV;AACA,aAAK,QAAQ,qBAAqB,SAAS,QAAQ,aAAa,OAAO,cAAe,MAAK,SAAS;AAAA,MACtG,GAAG,MAAM;AAAA,MACT,OAAO,cAAc,gBAAgB,CAAC,EAAE,QAAQ,OAAO,MAAM;AAC3D,YAAI,YAAY,qBAAqB,WAAY;AACjD,uBAAe,QAAQ,IAAI,IAAI,eAAe,KAAK,EAAE,IAAI,QAAQ,MAAM;AAAA,MACzE,GAAG,MAAM;AAAA,MACT,OAAO,SAAS,gBAAgB,CAAC,EAAE,QAAQ,SAAS,MAAM;AACxD,YAAI,YAAY,qBAAqB,cAAc,WAAW,OAAO,cAAe;AACpF,cAAM,OAAO,IAAI,IAAI,cAAc,KAAK;AACxC,YAAI,SAAU,MAAK,IAAI,MAAM;AAAA,YACxB,MAAK,OAAO,MAAM;AACvB,sBAAc,QAAQ;AAAA,MACxB,GAAG,MAAM;AAAA,IACX;AAAA,EACF;AAEA,QAAM,cAAc,YAAY;AAC9B,UAAM,aAAS,qBAAQ,QAAQ,MAAM;AACrC,UAAM,qBAAiB,qBAAQ,QAAQ,cAAc,EAAE,KAAK;AAC5D,QAAI,CAAC,eAAgB,OAAM,IAAI,UAAU,4BAA4B;AACrE,UAAM,mBAAmB,EAAE;AAC3B,UAAM,YAAY;AAClB,QAAI,YAAY,qBAAqB,WAAY;AACjD,aAAS,QAAQ,CAAC;AAClB,eAAW,MAAM;AACjB,iBAAa,QAAQ;AACrB,kBAAc,QAAQ,oBAAI,IAAI;AAC9B,mBAAe,QAAQ,oBAAI,IAAI;AAC/B,qBAAiB,QAAQ;AACzB,UAAM,QAAQ;AACd,qBAAiB,QAAQ;AACzB,mBAAe,QAAQ;AACvB,cAAU,kBAAkB,QAAQ,cAAc;AAClD,QAAI;AACF,YAAM,CAAC,kBAAkB,IAAI,IAAI,MAAM,QAAQ,IAAI;AAAA,QACjD,OAAO,gBAAgB,cAAc;AAAA,QACrC,OAAO,YAAY,EAAE,gBAAgB,OAAO,iBAAiB,QAAQ,EAAE,CAAC;AAAA,MAC1E,CAAC;AACD,UAAI,YAAY,qBAAqB,WAAY;AACjD,mBAAa,QAAQ;AACrB,qBAAe,QAAQ,IAAI,IAAI,iBAAiB,aAAa,QAAQ,CAAC,gBACpE,YAAY,aAAa,CAAC,CAAC,YAAY,WAAW,YAAY,UAAU,CAAU,IAAI,CAAC,CAAC,CAAC;AAC3F,eAAS,QAAQ,cAAc,CAAC,GAAG,IAAI;AACvC,uBAAiB,QAAQ,KAAK,WAAW;AACzC,UAAI,QAAQ,kBAAkB,KAAM,OAAM,SAAS;AAAA,IACrD,SAAS,OAAO;AACd,UAAI,CAAC,YAAY,qBAAqB,WAAY,OAAM,QAAQ;AAAA,IAClE,UAAE;AACA,UAAI,CAAC,YAAY,qBAAqB,YAAY;AAChD,yBAAiB,QAAQ;AACzB,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBAAoB,YAAY;AACpC,QAAI,iBAAiB,SAAS,eAAe,SAAS,CAAC,iBAAiB,MAAO;AAC/E,UAAM,mBAAmB;AACzB,UAAM,aAAS,qBAAQ,QAAQ,MAAM;AACrC,UAAM,qBAAiB,qBAAQ,QAAQ,cAAc;AACrD,mBAAe,QAAQ;AACvB,UAAM,QAAQ;AACd,QAAI;AACF,YAAM,OAAO,MAAM,OAAO,YAAY;AAAA,QACpC;AAAA,QACA,OAAO;AAAA,QACP,QAAQ,SAAS,MAAM,OAAO,CAAC,YAAY,CAAC,WAAW,IAAI,QAAQ,EAAE,CAAC,EAAE;AAAA,MAC1E,CAAC;AACD,UAAI,YAAY,qBAAqB,WAAY;AACjD,eAAS,QAAQ,cAAc,SAAS,OAAO,IAAI;AACnD,uBAAiB,QAAQ,KAAK,WAAW;AAAA,IAC3C,SAAS,OAAO;AACd,UAAI,CAAC,YAAY,qBAAqB,WAAY,OAAM,QAAQ;AAAA,IAClE,UAAE;AACA,UAAI,CAAC,YAAY,qBAAqB,WAAY,gBAAe,QAAQ;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,eAAe,OAAO,eAAwB;AAClD,QAAI,YAAa,cAAa,WAAW;AACzC,QAAI,WAAY,eAAc,WAAW,MAAM;AAAE,WAAK,aAAa,KAAK;AAAA,IAAE,GAAG,eAAe;AAC5F,QAAI,eAAe,WAAY;AAC/B,iBAAa;AACb,QAAI;AACF,gBAAM,qBAAQ,QAAQ,MAAM,EAAE,WAAW;AAAA,QACvC,oBAAgB,qBAAQ,QAAQ,cAAc;AAAA,QAC9C,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,CAAC,SAAU,OAAM,QAAQ;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,cAAc,OAAO,EAAE,MAAM,MAAM,MAAiD;AACxF,UAAM,iBAAiB,MAAM,KAAK;AAClC,QAAI,CAAC,mBAAmB,CAAC,SAAS,MAAM,WAAW,GAAI,QAAO;AAC9D,QAAI,UAAU,MAAO,QAAO;AAC5B,UAAM,YAAY,oBAAoB,KAAK,IAAI,CAAC,IAAI,EAAE,eAAe;AACrE,UAAM,iBAA0B;AAAA,MAC9B,IAAI;AAAA,MACJ,oBAAgB,qBAAQ,QAAQ,cAAc;AAAA,MAC9C,cAAU,qBAAQ,QAAQ,MAAM,EAAE;AAAA,MAClC,MAAM,kBAAkB;AAAA,MACxB,OAAO,SAAS,CAAC;AAAA,MACjB,WAAW,oBAAI,KAAK;AAAA,MACpB,WAAW;AAAA,IACb;AACA,eAAW,IAAI,SAAS;AACxB,aAAS,QAAQ,cAAc,SAAS,OAAO,CAAC,cAAc,CAAC;AAC/D,cAAU,QAAQ;AAClB,UAAM,QAAQ;AACd,UAAM,mBAAmB;AACzB,QAAI;AACF,YAAM,UAAU,UAAM,qBAAQ,QAAQ,MAAM,EAAE,YAAY;AAAA,QACxD,oBAAgB,qBAAQ,QAAQ,cAAc;AAAA,QAC9C,GAAI,iBAAiB,EAAE,MAAM,eAAe,IAAI,CAAC;AAAA,QACjD,GAAI,OAAO,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,MACnC,CAAC;AACD,iBAAW,OAAO,SAAS;AAC3B,UAAI,CAAC,YAAY,qBAAqB,YAAY;AAChD,iBAAS,QAAQ;AAAA,UACf,SAAS,MAAM,OAAO,CAAC,cAAc,UAAU,OAAO,SAAS;AAAA,UAC/D,CAAC,OAAO;AAAA,QACV;AAAA,MACF;AACA,YAAM,aAAa,KAAK;AACxB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,iBAAW,OAAO,SAAS;AAC3B,UAAI,CAAC,UAAU;AACb,iBAAS,QAAQ,SAAS,MAAM,OAAO,CAAC,cAAc,UAAU,OAAO,SAAS;AAChF,cAAM,QAAQ;AAAA,MAChB;AACA,aAAO;AAAA,IACT,UAAE;AACA,UAAI,CAAC,YAAY,qBAAqB,WAAY,WAAU,QAAQ;AAAA,IACtE;AAAA,EACF;AAEA,QAAM,UAAU,YAAY;AAC1B,eAAW;AACX,kBAAc;AACd,QAAI,YAAa,cAAa,WAAW;AACzC,QAAI,YAAY;AACd,gBAAM,qBAAQ,QAAQ,MAAM,EAAE,WAAW;AAAA,QACvC,oBAAgB,qBAAQ,QAAQ,cAAc;AAAA,QAC9C,UAAU;AAAA,MACZ,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IAC1B;AACA,UAAM,YAAY;AAAA,EACpB;AAEA,MAAI,QAAQ,YAAY,MAAM;AAC5B;AAAA,MACE,MAAM,KAAC,qBAAQ,QAAQ,MAAM,OAAG,qBAAQ,QAAQ,cAAc,CAAC;AAAA,MAC/D,MAAM;AACJ,mBAAW;AACX,qBAAa;AACb,aAAK,YAAY;AAAA,MACnB;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACpB;AAAA,EACF;AACA,UAAI,6BAAgB,EAAG,iCAAe,MAAM;AAAE,SAAK,QAAQ;AAAA,EAAE,CAAC;AAE9D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,CAAC,YAAY,aAAa,SAAS,eAAe,KAAK;AAAA,IACrE;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC1RA,IAAAC,cAUO;AACP,IAAAA,cAWO;AAgCP,IAAM,kBAAkB;AAAA,EACtB,YAAY,EAAE,MAAM,QAA6D,SAAS,OAAU;AAAA,EACpG,QAAQ,EAAE,MAAM,QAAoE,SAAS,OAAU;AAAA,EACvG,SAAS,EAAE,MAAM,QAAuC,SAAS,cAAc;AAAA,EAC/E,UAAU,EAAE,MAAM,SAAS,SAAS,MAAM;AAC5C;AAEA,SAAS,kBAAkB,MAAoB;AAC7C,SAAO,IAAI,KAAK,eAAe,QAAW,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC,EAAE,OAAO,IAAI;AAC/F;AAEA,SAAS,aACP,OACA,MACA,cACY;AACZ,QAAM,MAAM,OAAO,WAAW;AAC9B,QAAM,cAAc,OAAO,EAAE,MAAM,UAAU,SAAS,KAAK,IAAI,CAAC;AAChE,MAAI,MAAM,SAAS,SAAS;AAC1B,eAAO,eAAE,KAAK,EAAE,GAAG,aAAa,OAAO,yCAAyC,GAAG;AAAA,MACjF,MAAM,UACF,eAAE,OAAO,EAAE,KAAK,MAAM,KAAK,KAAK,MAAM,QAAQ,gBAAgB,SAAS,aAAa,CAAC,QACrF,eAAE,QAAQ,EAAE,OAAO,yBAAyB,GAAG,KAAC,eAAE,sBAAU,EAAE,eAAe,OAAO,CAAC,GAAG,oBAAoB,CAAC;AAAA,MACjH,MAAM,WAAO,eAAE,QAAQ,EAAE,OAAO,kBAAkB,GAAG,MAAM,IAAI,IAAI;AAAA,IACrE,CAAC;AAAA,EACH;AACA,MAAI,MAAM,SAAS,QAAQ;AACzB,UAAM,OAAO,eAAe,MAAM,IAAI;AACtC,eAAO,eAAE,KAAK,EAAE,GAAG,aAAa,OAAO,wCAAwC,GAAG;AAAA,UAChF,eAAE,sBAAU,EAAE,eAAe,OAAO,CAAC;AAAA,UACrC,eAAE,QAAQ,KAAC,eAAE,UAAU,MAAM,QAAQ,YAAY,GAAG,WAAO,eAAE,SAAS,IAAI,IAAI,IAAI,CAAC;AAAA,MACnF,WAAO,eAAE,sBAAU,EAAE,MAAM,IAAI,eAAe,OAAO,CAAC,IAAI;AAAA,IAC5D,CAAC;AAAA,EACH;AACA,MAAI,MAAM,SAAS,YAAY;AAC7B,UAAM,QAAQ,MAAM,QAAQ,GAAG,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,GAAG;AACxE,eAAO,eAAE,KAAK,EAAE,GAAG,aAAa,OAAO,4CAA4C,GAAG;AAAA,UACpF,eAAE,oBAAQ,EAAE,eAAe,OAAO,CAAC;AAAA,UACnC,eAAE,QAAQ,KAAC,eAAE,UAAU,KAAK,OAAG,eAAE,SAAS,GAAG,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC;AAAA,IAC5F,CAAC;AAAA,EACH;AACA,QAAM,UAAU,MAAM,SAAS,SAAS,MAAM,SAAS,SAAS;AAChE,aAAO,eAAE,KAAK,EAAE,GAAG,aAAa,OAAO,2CAA2C,GAAG;AAAA,QACnF,eAAE,0BAAc,EAAE,eAAe,OAAO,CAAC;AAAA,QACzC,eAAE,QAAQ,KAAC,eAAE,UAAU,MAAM,QAAQ,gBAAgB,OAAG,eAAE,SAAS,OAAO,OAAO,CAAC,CAAC,CAAC;AAAA,EACtF,CAAC;AACH;AAGO,IAAM,sBAAkB,6BAAgB;AAAA,EAC7C,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,IACL,GAAG;AAAA,IACH,cAAc,EAAE,MAAM,QAAkC,UAAU,KAAK;AAAA,IACvE,UAAU,EAAE,MAAM,OAAuC,UAAU,KAAK;AAAA,IACxE,eAAe,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC9C,gBAAgB,EAAE,MAAM,QAA+C,SAAS,MAAM,oBAAI,IAAI,EAAE;AAAA,IAChG,iBAAiB,EAAE,MAAM,UAAiE,SAAS,OAAU;AAAA,IAC7G,aAAa,EAAE,MAAM,UAAkD,SAAS,OAAU;AAAA,IAC1F,kBAAkB,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,IAClD,gBAAgB,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,IAChD,OAAO,EAAE,MAAM,MAAsC,UAAU,MAAM;AAAA,IACrE,mBAAmB,EAAE,MAAM,UAAuE,SAAS,OAAU;AAAA,IACrH,eAAe,EAAE,MAAM,QAA6C,SAAS,OAAU;AAAA,IACvF,qBAAqB,EAAE,MAAM,QAAQ,SAAS,IAAI;AAAA,IAClD,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IACxC,eAAe,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IAC9C,YAAY,EAAE,MAAM,UAA8C,SAAS,kBAAkB;AAAA,IAC7F,cAAc,EAAE,MAAM,QAAsC,SAAS,OAAO;AAAA,EAC9E;AAAA,EACA,OAAO,CAAC,cAAc,kBAAkB;AAAA,EACxC,MAAM,OAAO,EAAE,OAAO,MAAM,MAAM,GAAG;AACnC,UAAM,sBAAkB,iBAAwB,IAAI;AACpD,QAAI,kBAAkB;AACtB,QAAI,sBAAqC;AACzC,QAAI,uBAAuB;AAC3B,UAAM,mBAAe,sBAAS,MAAM,IAAI,IAAI,MAAM,aAAa,aAAa,QAAQ,CAAC,gBAAgB;AAAA,MACnG,CAAC,YAAY,IAAI,WAAW;AAAA,MAC5B,CAAC,YAAY,WAAW,WAAW;AAAA,IACrC,CAAC,CAAC,CAAC;AACH,UAAM,aAAa,OAAgC;AAAA,MACjD,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,MAChB,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC3D,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IACjD;AAEA,UAAM,eAAe,YAAY;AAC/B,UAAI,mBAAmB,wBAAwB,MAAM,SAAS,UAAU,MAAM,kBAAkB,CAAC,MAAM,oBAAoB,CAAC,MAAM,YAAa;AAC/I,wBAAkB;AAClB,4BAAsB,MAAM,SAAS;AACrC,UAAI;AAAE,cAAM,MAAM,YAAY;AAAA,MAAE,QAC1B;AAAE,8BAAsB;AAAA,MAAK,UACnC;AAAU,0BAAkB;AAAA,MAAM;AAAA,IACpC;AAEA,2BAAM,MAAM,CAAC,MAAM,SAAS,QAAQ,MAAM,gBAAgB,GAAY,OAAO,CAAC,OAAO,QAAQ,MAAM;AACjG,YAAM,WAAW;AACjB,UAAI,UAAU,wBAAwB,CAAC,SAAU,uBAAsB;AACvE,YAAM,WAAW,QAAQ;AACzB,YAAM,UAAU,gBAAgB;AAChC,6BAAuB;AACvB,UAAI,WAAW,MAAM,WAAW,MAAM,iBAAiB,UAAU;AAC/D,cAAM,qBAAqB,QAAQ,eAAe,QAAQ,YAAY,QAAQ;AAC9E,YAAI,aAAa,KAAK,qBAAqB,KAAK;AAC9C,oBAAM,sBAAS;AACf,kBAAQ,YAAY,QAAQ;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,GAAG,EAAE,OAAO,QAAQ,WAAW,KAAK,CAAC;AAErC,UAAM,gBAAgB,CAAC,SAAkB,UAA8B;AACrE,YAAM,gBAAgB,QAAQ,aAAa,MAAM;AACjD,YAAM,SAAS,aAAa,MAAM,IAAI,QAAQ,QAAQ;AACtD,YAAM,YAAY,yBAAyB,OAAO;AAClD,YAAM,YAAY,YACd,oBAAI,IAAY,IAChB,MAAM,kBAAkB,MAAM,gBAAgB,OAAO,IAAI,aAAa,SAAS,MAAM,cAAc;AACvG,YAAM,YAA8B,EAAE,SAAS,oBAAoB,OAAO,eAAe,QAAQ,UAAU;AAC3G,YAAM,SAAS,MAAM,UAAU,SAAS;AACxC,UAAI,OAAQ,YAAO,eAAE,OAAO,EAAE,KAAK,QAAQ,IAAI,MAAM,WAAW,GAAG,MAAM;AACzE,YAAM,oBAAoB,WAAW;AACrC,YAAM,cAAc,gBAAgB,oBAAoB;AACxD,YAAM,aAAa,QAAQ,MAAM,IAAI,CAAC,OAAO,eAAe;AAC1D,cAAM,OAAO,MAAM,oBACf,MAAM;AACJ,gBAAM,oBAAoB,OAAO,OAAO;AAAA,QAC1C,IACA;AACJ,cAAM,iBAAiC,EAAE,OAAO,SAAS,eAAe,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG;AAClG,mBAAO,eAAE,OAAO;AAAA,UACd,KAAK,MAAM,MAAM,GAAG,MAAM,IAAI,IAAI,UAAU;AAAA,UAC5C,OAAO,UAAU,SAAS,mBAAmB,YAAY;AAAA,UACzD,OAAO,UAAU,SAAS,iBAAiB;AAAA,QAC7C,GAAG,MAAM,QAAQ,cAAc,KAAK,CAAC,aAAa,OAAO,MAAM,MAAM,YAAY,CAAC,CAAC;AAAA,MACrF,CAAC;AACD,YAAM,mBAAyC,EAAE,SAAS,UAAU;AACpE,iBAAO,eAAE,OAAO,EAAE,KAAK,QAAQ,IAAI,MAAM,WAAW,GAAG;AAAA,YACrD,eAAE,WAAW;AAAA,UACX,OAAO;AAAA,YACL,CAAC,MAAM,YAAY;AAAA,YACnB,iBAAiB,CAAC,MAAM,YAAY;AAAA,YACpC,MAAM,YAAY;AAAA,YAClB,MAAM,aAAa,WAAW;AAAA,UAChC;AAAA,UACA,OAAO,CAAC,MAAM,QAAQ,SAAS,MAAM,SAAS,WAAW,CAAC;AAAA,UAC1D,mBAAmB,QAAQ;AAAA,QAC7B,GAAG;AAAA,cACD,eAAE,OAAO,EAAE,OAAO,sBAAsB,GAAG;AAAA,YACzC,CAAC,oBAAgB,eAAE,UAAU,EAAE,OAAO,sBAAsB,GAAG,QAAQ,QAAQ,QAAQ,QAAQ,IAAI;AAAA,YACnG,QAAQ,WAAO,eAAE,OAAO,EAAE,OAAO,oBAAoB,GAAG,QAAQ,IAAI,IAAI;AAAA,YACxE,GAAG;AAAA,gBACH,eAAE,QAAQ,EAAE,OAAO,oBAAoB,GAAG;AAAA,cACxC,YAAY,kBAAa,MAAM,WAAW,QAAQ,SAAS;AAAA,cAC3D,iBAAiB,CAAC,YACd,UAAU,OAAO,QACf,eAAE,wBAAY,EAAE,MAAM,IAAI,cAAc,OAAO,CAAC,QAChD,eAAE,mBAAO,EAAE,MAAM,IAAI,cAAc,YAAY,CAAC,IAClD;AAAA,YACN,CAAC;AAAA,UACH,CAAC;AAAA,UACD,iBAAiB,CAAC,YACd,MAAM,cAAc,IAAI,gBAAgB,SAAK,eAAE,OAAO;AAAA,YACpD,OAAO,UAAU,WAAW,mBAAmB,mBAAmB;AAAA,YAClE,OAAO,UAAU,WAAW,iBAAiB;AAAA,UAC/C,GAAG,UAAU,OAAO,IAAI,WAAW,UAAU,IAAI,KAAK,WAAW,IACjE;AAAA,QACN,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,MAAM;AACX,YAAM,oBAAoB,WAAW;AACrC,YAAM,WAAyB,CAAC;AAChC,UAAI,MAAM,gBAAgB;AACxB,iBAAS,KAAK,MAAM,eAAe,IAAI,SAAK,eAAE,OAAO;AAAA,UACnD,OAAO,UAAU,WAAW,mBAAmB,mBAAmB;AAAA,UAClE,OAAO,UAAU,WAAW,iBAAiB;AAAA,UAC7C,MAAM;AAAA,QACR,GAAG,KAAC,eAAE,0BAAc,EAAE,OAAO,aAAa,eAAe,OAAO,CAAC,GAAG,+BAA0B,CAAC,CAAC;AAAA,MAClG;AACA,UAAI,MAAM,OAAO;AACf,cAAM,QAAQ,MAAM,cAAc,MAAM;AAAE,eAAK,aAAa;AAAA,QAAE,IAAI;AAClE,iBAAS,KAAK,MAAM,QAAQ,EAAE,OAAO,MAAM,OAAO,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAG,CAAC,SAAK,eAAE,OAAO;AAAA,UAC3F,OAAO,UAAU,SAAS,mBAAmB,qCAAqC;AAAA,UAClF,OAAO,UAAU,SAAS,iBAAiB;AAAA,UAC3C,MAAM;AAAA,QACR,GAAG;AAAA,cACD,eAAE,QAAQ,aAAa,MAAM,KAAK,CAAC;AAAA,UACnC,YAAQ,eAAE,UAAU,EAAE,MAAM,UAAU,OAAO,oBAAoB,SAAS,MAAM,GAAG,OAAO,IAAI;AAAA,QAChG,CAAC,CAAC;AAAA,MACJ;AACA,UAAI,MAAM,SAAS,WAAW,KAAK,CAAC,MAAM,gBAAgB;AACxD,iBAAS,KAAK,MAAM,QAAQ,SAAK,eAAE,OAAO;AAAA,UACxC,OAAO,UAAU,SAAS,mBAAmB,YAAY;AAAA,UACzD,OAAO,UAAU,SAAS,iBAAiB;AAAA,QAC7C,GAAG,KAAC,eAAE,2BAAe,EAAE,eAAe,OAAO,CAAC,GAAG,kBAAkB,CAAC,CAAC;AAAA,MACvE,OAAO;AACL,iBAAS,KAAK,GAAG,MAAM,SAAS,IAAI,aAAa,CAAC;AAAA,MACpD;AACA,iBAAO,eAAE,OAAO;AAAA,QACd,GAAG;AAAA,QACH,KAAK,CAAC,YAAqB;AACzB,0BAAgB,QAAQ;AACxB,cAAI,MAAM,cAAe,OAAM,cAAc,QAAQ;AAAA,QACvD;AAAA,QACA,OAAO,GAAG,CAAC,MAAM,YAAY,0BAA0B,MAAM,YAAY,UAAU,MAAM,KAAK;AAAA,QAC9F,OAAO,CAAC,MAAM,QAAQ,UAAU,MAAM,KAAK;AAAA,QAC3C,gBAAgB,MAAM;AAAA,QACtB,MAAM;AAAA,QACN,aAAa;AAAA,QACb,cAAc,eAAe,MAAM,aAAa,YAAY;AAAA,QAC5D,UAAU,CAAC,UAAiB;AAC1B,gBAAM,gBAAgB,MAAM;AAC5B,cAAI,OAAO,kBAAkB,WAAY,eAAc,KAAK;AAC5D,gBAAM,UAAU,MAAM;AACtB,gBAAM,qBAAqB,MAAM,UAC7B,QAAQ,YACR,QAAQ,eAAe,QAAQ,YAAY,QAAQ;AACvD,cAAI,sBAAsB,MAAM,oBAAqB,MAAK,aAAa;AAAA,QACzE;AAAA,MACF,GAAG,QAAQ;AAAA,IACb;AAAA,EACF;AACF,CAAC;AAEM,SAAS,uBAAuB,gBAAsF;AAC3H,SAAO,CAAC,YAAY,aAAa,SAAS,cAAc;AAC1D;;;AF9NA,IAAMC,mBAAkB;AAAA,EACtB,YAAY,EAAE,MAAM,QAA6D,SAAS,OAAU;AAAA,EACpG,QAAQ,EAAE,MAAM,QAAoE,SAAS,OAAU;AAAA,EACvG,SAAS,EAAE,MAAM,QAAuC,SAAS,cAAc;AAAA,EAC/E,UAAU,EAAE,MAAM,SAAS,SAAS,MAAM;AAC5C;AAEA,IAAM,YAAY;AAAA,EAChB,GAAGA;AAAA,EACH,cAAc,EAAE,MAAM,QAAuC,UAAU,KAAK;AAAA,EAC5E,UAAU,EAAE,MAAM,OAAuC,UAAU,KAAK;AAAA,EACxE,eAAe,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,EAC9C,eAAe,EAAE,MAAM,UAAkF,UAAU,KAAK;AAAA,EACxH,eAAe,EAAE,MAAM,QAAyC,SAAS,MAAM,oBAAI,IAAI,EAAE;AAAA,EACzF,gBAAgB,EAAE,MAAM,QAA+C,SAAS,MAAM,oBAAI,IAAI,EAAE;AAAA,EAChG,iBAAiB,EAAE,MAAM,UAAiE,SAAS,OAAU;AAAA,EAC7G,QAAQ,EAAE,MAAM,UAAkC,SAAS,OAAU;AAAA,EACrE,WAAW,EAAE,MAAM,UAAkD,SAAS,OAAU;AAAA,EACxF,aAAa,EAAE,MAAM,UAAkD,SAAS,OAAU;AAAA,EAC1F,gBAAgB,EAAE,MAAM,UAAmE,SAAS,OAAU;AAAA,EAC9G,iBAAiB,EAAE,MAAM,UAAkC,SAAS,OAAU;AAAA,EAC9E,mBAAmB,EAAE,MAAM,UAAuE,SAAS,OAAU;AAAA,EACrH,kBAAkB,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,EAClD,gBAAgB,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,EAChD,WAAW,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,EAC3C,kBAAkB,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,EAClD,OAAO,EAAE,MAAM,MAAsC,UAAU,MAAM;AAAA,EACrE,cAAc,EAAE,MAAM,MAAsC,UAAU,MAAM;AAAA,EAC5E,oBAAoB,EAAE,MAAM,UAAqE,SAAS,OAAU;AAAA,EACpH,iBAAiB,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,EAChD,eAAe,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,EAC9C,qBAAqB,EAAE,MAAM,QAAQ,SAAS,IAAI;AAAA,EAClD,YAAY,EAAE,MAAM,UAA8C,SAAS,OAAU;AAAA,EACrF,cAAc,EAAE,MAAM,QAAsC,SAAS,OAAO;AAAA,EAC5E,qBAAqB,EAAE,MAAM,QAAQ,SAAS,kBAAkB;AAAA,EAChE,mBAAmB,EAAE,MAAM,QAAQ,SAAS,UAAU;AAAA,EACtD,eAAe,EAAE,MAAM,QAAwE,SAAS,OAAU;AAAA,EAClH,YAAY,EAAE,MAAM,QAAQ,SAAS,OAAU;AAAA,EAC/C,cAAc,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,EAC1C,eAAe,EAAE,MAAM,UAA+C,SAAS,OAAU;AAC3F;AAEA,SAAS,YAAY,SAA8B,oBAAwD;AACzG,QAAM,QAAQ,CAAC,GAAG,OAAO,EAAE,IAAI,kBAAkB;AACjD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,MAAM,WAAW,EAAG,QAAO,GAAG,MAAM,CAAC,CAAC;AAC1C,MAAI,MAAM,WAAW,EAAG,QAAO,GAAG,MAAM,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC;AAC1D,SAAO,GAAG,MAAM,CAAC,CAAC,QAAQ,MAAM,SAAS,CAAC;AAC5C;AAGO,IAAM,uBAAmB,6BAAgB;AAAA,EAC9C,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO;AAAA,IACL;AAAA,IAAgB;AAAA,IAAiB;AAAA,IAAQ;AAAA,IAAW;AAAA,IACpD;AAAA,IAAkB;AAAA,IAAoB;AAAA,EACxC;AAAA,EACA,MAAM,OAAO,EAAE,OAAO,MAAM,MAAM,GAAG;AACnC,UAAM,oBAAgB,iBAAI,MAAM,YAAY;AAC5C,UAAM,iBAAa,iBAAI,KAAK;AAC5B,UAAM,aAAa,OAAgC;AAAA,MACjD,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,MAChB,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC3D,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IACjD;AACA,UAAM,QAAQ,MAAM,MAAM,cAAc,cAAc;AACtD,QAAI,cAAc,MAAM;AACxB,UAAM,WAAW,CAAC,UAAkB;AAClC,oBAAc;AACd,UAAI,MAAM,eAAe,OAAW,eAAc,QAAQ;AAC1D,YAAM,gBAAgB,KAAK;AAC3B,WAAK,qBAAqB,KAAK;AAC/B,YAAM,WAAW,MAAM,KAAK,EAAE,SAAS;AACvC,WAAK,MAAM,iBAAiB,QAAQ;AAAA,IACtC;AACA,UAAM,SAAS,YAAY;AACzB,YAAM,gBAAgB,MAAM;AAC5B,YAAM,OAAO,cAAc,KAAK;AAChC,UAAI,CAAC,QAAQ,MAAM,aAAa,WAAW,MAAO;AAClD,iBAAW,QAAQ;AACnB,eAAS,EAAE;AACX,UAAI;AACF,cAAM,cAAc,MAAM,MAAM,cAAc,IAAI;AAClD,YAAI,gBAAgB,SAAS,YAAY,WAAW,EAAG,UAAS,aAAa;AAAA,MAC/E,UAAE;AACA,mBAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AACA,UAAM,cAAc,CAAC,WAAmB;AACtC,YAAM,SAAS,MAAM,qBAAqB,MAAM,GAAG,KAAK;AACxD,UAAI,OAAQ,QAAO;AACnB,YAAM,cAAc,MAAM,aAAa,aAAa,KAAK,CAAC,UAAU,MAAM,OAAO,UAAU,MAAM,cAAc,MAAM;AACrH,aAAO,aAAa,KAAK,KAAK,KAAK;AAAA,IACrC;AACA,UAAM,SAAS,MAAM;AAAE,YAAM,SAAS;AAAA,IAAE;AACxC,UAAM,UAAU,MAAM,MAAM,YAAY;AACxC,UAAM,YAAY,MAAM,MAAM,cAAc;AAC5C,UAAM,gBAAgB,MAAM;AAAE,YAAM,kBAAkB;AAAA,IAAE;AAExD,UAAM,eAAe,MAAkB;AACrC,YAAM,YAAY;AAAA,QAChB,cAAc,MAAM;AAAA,QACpB,GAAI,MAAM,SAAS,EAAE,QAAQ,OAAO,IAAI,CAAC;AAAA,QACzC,GAAI,MAAM,YAAY,EAAE,WAAW,QAAQ,IAAI,CAAC;AAAA,MAClD;AACA,aAAO,MAAM,SAAS,SAAS,SAAK,eAAE,UAAU;AAAA,QAC9C,OAAO,UAAU,UAAU,WAAW,GAAG,0BAA0B;AAAA,QACnE,OAAO,UAAU,UAAU,WAAW,CAAC;AAAA,MACzC,GAAG;AAAA,QACD,MAAM,aAAS,eAAE,UAAU;AAAA,UACzB,MAAM;AAAA,UAAU,cAAc;AAAA,UAAQ,SAAS;AAAA,UAC/C,OAAO,UAAU,UAAU,WAAW,GAAG,kBAAkB;AAAA,UAC3D,OAAO,UAAU,UAAU,WAAW,CAAC;AAAA,QACzC,GAAG,KAAC,eAAE,uBAAW,EAAE,MAAM,IAAI,eAAe,OAAO,CAAC,CAAC,CAAC,IAAI;AAAA,YAC1D,eAAE,gBAAgB,EAAE,MAAM,MAAM,aAAa,cAAc,KAAK,MAAM,aAAa,SAAS,CAAC;AAAA,YAC7F,eAAE,OAAO,EAAE,OAAO,iCAAiC,GAAG;AAAA,cACpD,eAAE,UAAU,MAAM,aAAa,YAAY;AAAA,cAC3C,eAAE,QAAQ,GAAG,MAAM,aAAa,aAAa,MAAM,eAAe,MAAM,aAAa,aAAa,WAAW,IAAI,KAAK,GAAG,EAAE;AAAA,QAC7H,CAAC;AAAA,QACD,MAAM,gBAAY,eAAE,UAAU;AAAA,UAC5B,MAAM;AAAA,UAAU,cAAc;AAAA,UAAwB,SAAS,MAAM;AAAE,iBAAK,QAAQ;AAAA,UAAE;AAAA,UACtF,OAAO,UAAU,UAAU,WAAW,GAAG,kBAAkB;AAAA,UAC3D,OAAO,UAAU,UAAU,WAAW,CAAC;AAAA,QACzC,GAAG,KAAC,eAAE,uBAAW,EAAE,MAAM,IAAI,eAAe,OAAO,CAAC,CAAC,CAAC,IAAI;AAAA,MAC5D,CAAC;AAAA,IACH;AAEA,UAAM,eAAe,MAAkB;AACrC,YAAM,YAA6B,EAAE,SAAS,MAAM,eAAe,oBAAoB,YAAY;AACnG,aAAO,MAAM,kBAAkB,IAAI,SAAS,SAAK,eAAE,OAAO;AAAA,QACxD,OAAO,UAAU,UAAU,WAAW,GAAG,aAAa;AAAA,QACtD,OAAO,UAAU,UAAU,WAAW,CAAC;AAAA,QACvC,aAAa;AAAA,MACf,GAAG,YAAY,MAAM,eAAe,WAAW,CAAC;AAAA,IAClD;AAEA,UAAM,iBAAiB,MAAkB;AACvC,YAAM,YAA+B;AAAA,QACnC,OAAO,MAAM;AAAA,QAAG,UAAU;AAAA,QAAU,WAAW,MAAM,aAAa,WAAW;AAAA,QAC7E,MAAM,MAAM;AAAE,eAAK,OAAO;AAAA,QAAE;AAAA,QAC5B,GAAI,MAAM,kBAAkB,EAAE,cAAc,IAAI,CAAC;AAAA,MACnD;AACA,aAAO,MAAM,WAAW,SAAS,SAAK,eAAE,QAAQ;AAAA,QAC9C,OAAO,UAAU,YAAY,WAAW,GAAG,eAAe;AAAA,QAC1D,OAAO,UAAU,YAAY,WAAW,CAAC;AAAA,QACzC,UAAU,CAAC,UAAiB;AAAE,gBAAM,eAAe;AAAG,eAAK,OAAO;AAAA,QAAE;AAAA,MACtE,GAAG;AAAA,QACD,MAAM,sBAAkB,eAAE,UAAU;AAAA,UAClC,MAAM;AAAA,UAAU,cAAc;AAAA,UAAkB,SAAS;AAAA,UACzD,OAAO,UAAU,UAAU,WAAW,GAAG,kBAAkB;AAAA,UAC3D,OAAO,UAAU,UAAU,WAAW,CAAC;AAAA,QACzC,GAAG,KAAC,eAAE,uBAAW,EAAE,MAAM,IAAI,eAAe,OAAO,CAAC,CAAC,CAAC,IAAI;AAAA,YAC1D,eAAE,YAAY;AAAA,UACZ,GAAG,MAAM;AAAA,UACT,MAAM,MAAM,eAAe,QAAQ;AAAA,UACnC,aAAa,MAAM;AAAA,UACnB,cAAc,MAAM;AAAA,UACpB,OAAO,GAAG,CAAC,MAAM,YAAY,wBAAwB,MAAM,YAAY,OAAO,MAAM,eAAe,KAAK;AAAA,UACxG,OAAO,CAAC,MAAM,QAAQ,OAAO,MAAM,eAAe,KAAK;AAAA,UACvD,OAAO,MAAM;AAAA,UACb,SAAS,CAAC,UAAsB;AAC9B,kBAAM,UAAU,MAAM,eAAe;AACrC,gBAAI,OAAO,YAAY,WAAY,SAAQ,KAAK;AAChD,gBAAI,CAAC,MAAM,iBAAkB,UAAU,MAAM,cAAsC,KAAK;AAAA,UAC1F;AAAA,UACA,WAAW,CAAC,UAAyB;AACnC,kBAAM,UAAU,MAAM,eAAe;AACrC,gBAAI,OAAO,YAAY,WAAY,SAAQ,KAAK;AAChD,gBAAI,MAAM,iBAAkB;AAC5B,gBAAI,MAAM,QAAQ,WAAW,CAAC,MAAM,UAAU;AAAE,oBAAM,eAAe;AAAG,mBAAK,OAAO;AAAA,YAAE;AAAA,UACxF;AAAA,QACF,CAAC;AAAA,YACD,eAAE,UAAU;AAAA,UACV,MAAM;AAAA,UAAU,cAAc;AAAA,UAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,KAAK,MAAM,aAAa,WAAW;AAAA,UACzG,OAAO,UAAU,UAAU,WAAW,GAAG,kBAAkB;AAAA,UAC3D,OAAO,UAAU,UAAU,WAAW,CAAC;AAAA,QACzC,GAAG,CAAC,MAAM,aAAa,WAAW,YAC9B,eAAE,0BAAc,EAAE,OAAO,aAAa,MAAM,IAAI,eAAe,OAAO,CAAC,QACvE,eAAE,kBAAM,EAAE,MAAM,IAAI,eAAe,OAAO,CAAC,CAAC,CAAC;AAAA,MACnD,CAAC;AAAA,IACH;AAEA,WAAO,MAAM;AACX,UAAI,MAAM,oBAAoB,MAAM,SAAS,WAAW,GAAG;AACzD,mBAAO,eAAE,OAAO;AAAA,UACd,GAAG;AAAA,UACH,OAAO,GAAG,CAAC,MAAM,YAAY,0BAA0B,MAAM,YAAY,MAAM,MAAM,KAAK;AAAA,UAC1F,OAAO,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,UACvC,gBAAgB,MAAM;AAAA,QACxB,GAAG,MAAM,UAAU,SAAK,eAAE,OAAO;AAAA,UAC/B,OAAO,UAAU,WAAW,WAAW,GAAG,YAAY;AAAA,UAAG,OAAO,UAAU,WAAW,WAAW,CAAC;AAAA,UAAG,MAAM;AAAA,QAC5G,GAAG,KAAC,eAAE,0BAAc,EAAE,OAAO,aAAa,eAAe,OAAO,CAAC,GAAG,6BAAwB,CAAC,CAAC;AAAA,MAChG;AACA,YAAM,WAAyB,CAAC,aAAa,CAAC;AAC9C,UAAI,MAAM,OAAO;AACf,cAAM,QAAQ,MAAM,YAAY,MAAM;AAAE,eAAK,QAAQ;AAAA,QAAE,IAAI;AAC3D,iBAAS,KAAK,MAAM,QAAQ,EAAE,OAAO,MAAM,OAAO,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAG,CAAC,SAAK,eAAE,OAAO;AAAA,UAC3F,OAAO,UAAU,SAAS,WAAW,GAAG,yBAAyB;AAAA,UACjE,OAAO,UAAU,SAAS,WAAW,CAAC;AAAA,UAAG,MAAM;AAAA,QACjD,GAAG,KAAC,eAAE,QAAQ,aAAa,MAAM,KAAK,CAAC,GAAG,YAAQ,eAAE,UAAU,EAAE,MAAM,UAAU,OAAO,oBAAoB,SAAS,MAAM,GAAG,OAAO,IAAI,IAAI,CAAC,CAAC;AAAA,MAChJ;AACA,YAAM,eAAe;AAAA,QACnB,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,QAClD,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC5C,GAAI,MAAM,cAAc,IAAI,EAAE,gBAAgB,MAAM,cAAc,EAAE,IAAI,CAAC;AAAA,QACzE,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC5C,GAAI,MAAM,eAAe,IAAI,EAAE,iBAAiB,MAAM,eAAe,EAAE,IAAI,CAAC;AAAA,QAC5E,GAAI,MAAM,eAAe,IAAI,EAAE,OAAO,MAAM,eAAe,EAAE,IAAI,CAAC;AAAA,MACpE;AACA,eAAS,SAAK,eAAE,iBAAiB;AAAA,QAC/B,cAAc,MAAM;AAAA,QACpB,UAAU,MAAM;AAAA,QAChB,eAAe,MAAM;AAAA,QACrB,gBAAgB,MAAM;AAAA,QACtB,GAAI,MAAM,kBAAkB,EAAE,iBAAiB,MAAM,gBAAgB,IAAI,CAAC;AAAA,QAC1E,GAAI,MAAM,cAAc,EAAE,aAAa,UAAU,IAAI,CAAC;AAAA,QACtD,kBAAkB,MAAM;AAAA,QACxB,gBAAgB,MAAM;AAAA,QACtB,GAAI,MAAM,gBAAgB,OAAO,CAAC,IAAI,EAAE,OAAO,MAAM,aAAa;AAAA,QAClE,GAAI,MAAM,oBAAoB,EAAE,mBAAmB,CAAC,OAAqB,YAAqB;AAC5F,gBAAM,oBAAoB,OAAO,OAAO;AAAA,QAC1C,EAAE,IAAI,CAAC;AAAA,QACP,SAAS,MAAM;AAAA,QACf,eAAe,MAAM;AAAA,QACrB,qBAAqB,MAAM;AAAA,QAC3B,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,QAC3D,cAAc,MAAM;AAAA,QACpB,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,QAC3D,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,QAC/C,SAAS,MAAM;AAAA,QACf,UAAU,MAAM;AAAA,MAClB,GAAG,YAAY,CAAC;AAChB,eAAS,KAAK,aAAa,GAAG,eAAe,CAAC;AAC9C,iBAAO,eAAE,WAAW;AAAA,QAClB,GAAG;AAAA,QACH,OAAO,GAAG,CAAC,MAAM,YAAY,0BAA0B,MAAM,YAAY,MAAM,MAAM,KAAK;AAAA,QAC1F,OAAO,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,QACvC,gBAAgB,MAAM;AAAA,QACtB,cAAc,MAAM,aAAa;AAAA,MACnC,GAAG,QAAQ;AAAA,IACb;AAAA,EACF;AACF,CAAC;AAaM,IAAM,mBAAe,6BAAgB;AAAA,EAC1C,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,IACL,GAAG;AAAA,IACH,cAAc,EAAE,MAAM,QAAuC,SAAS,OAAU;AAAA,IAChF,UAAU,EAAE,MAAM,OAAuC,SAAS,MAAM,CAAC,EAAE;AAAA,IAC3E,eAAe,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,IAC3C,eAAe,EAAE,MAAM,UAAkF,SAAS,OAAU;AAAA,IAC5H,QAAQ,EAAE,MAAM,QAAsC,UAAU,KAAK;AAAA,IACrE,gBAAgB,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC/C,iBAAiB,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,IAC7C,gBAAgB,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IAC/C,mBAAmB,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IAClD,iBAAiB,EAAE,MAAM,QAAQ,SAAS,IAAK;AAAA,IAC/C,UAAU,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IACzC,oBAAoB,EAAE,MAAM,UAAoE,SAAS,OAAU;AAAA,EACrH;AAAA,EACA,OAAO,CAAC,qBAAqB,gBAAgB,iBAAiB,QAAQ,WAAW,cAAc,kBAAkB,oBAAoB,mBAAmB;AAAA,EACxJ,MAAM,OAAO,EAAE,OAAO,MAAM,QAAQ,MAAM,GAAG;AAC3C,UAAM,aAAa,gBAAgB;AAAA,MACjC,QAAQ,MAAM,MAAM;AAAA,MACpB,gBAAgB,MAAM,MAAM;AAAA,MAC5B,iBAAiB,MAAM;AAAA,MACvB,gBAAgB,MAAM;AAAA,MACtB,mBAAmB,MAAM;AAAA,MACzB,iBAAiB,MAAM;AAAA,MACvB,UAAU,MAAM;AAAA,IAClB,CAAC;AACD,WAAO,EAAE,WAAW,CAAC;AACrB,iCAAY,MAAM;AAChB,WAAK,qBAAqB,UAAU;AAAA,IACtC,CAAC;AACD,WAAO,MAAM;AACX,YAAM,qBAAqB,WAAW,aAAa;AACnD,UAAI,CAAC,oBAAoB;AACvB,cAAM,QAAQ,MAAM;AAAE,eAAK,WAAW,QAAQ;AAAA,QAAE;AAChD,mBAAO,eAAE,OAAO;AAAA,UACd,GAAG;AAAA,UACH,OAAO,GAAG,CAAC,MAAM,YAAY,0BAA0B,MAAM,YAAY,MAAM,MAAM,KAAK;AAAA,UAC1F,OAAO,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,UACvC,gBAAgB,MAAM;AAAA,QACxB,GAAG,WAAW,MAAM,QAChB,MAAM,QAAQ,EAAE,OAAO,WAAW,MAAM,OAAO,MAAM,CAAC,SAAK,eAAE,OAAO,EAAE,OAAO,gCAAgC,MAAM,QAAQ,GAAG;AAAA,cAC5H,eAAE,QAAQ,aAAa,WAAW,MAAM,KAAK,CAAC;AAAA,cAC9C,eAAE,UAAU,EAAE,MAAM,UAAU,OAAO,oBAAoB,SAAS,MAAM,GAAG,WAAW;AAAA,QACxF,CAAC,IACD,MAAM,UAAU,SAAK,eAAE,OAAO,EAAE,OAAO,cAAc,MAAM,SAAS,GAAG;AAAA,cACrE,eAAE,0BAAc,EAAE,OAAO,aAAa,eAAe,OAAO,CAAC;AAAA,UAAG;AAAA,QAClE,CAAC,CAAC;AAAA,MACR;AACA,YAAM;AAAA,QACJ,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,QACjB,UAAU;AAAA,QACV,oBAAoB;AAAA,QACpB,cAAc;AAAA,QACd,UAAU;AAAA,QACV,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,kBAAkB;AAAA,QAClB,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,kBAAkB;AAAA,QAClB,OAAO;AAAA,QACP,GAAG;AAAA,MACL,IAAI;AACJ,iBAAO,eAAE,kBAAkB;AAAA,QACzB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,cAAc;AAAA,QACd,UAAU,WAAW,SAAS;AAAA,QAC9B,eAAe,WAAW,cAAc;AAAA,QACxC,eAAe,OAAO,SAAiB;AACrC,eAAK,gBAAgB,IAAI;AACzB,iBAAQ,MAAM,WAAW,YAAY,EAAE,KAAK,CAAC,MAAO;AAAA,QACtD;AAAA,QACA,eAAe,WAAW,cAAc;AAAA,QACxC,gBAAgB,WAAW,eAAe;AAAA,QAC1C,WAAW,WAAW;AAAA,QACtB,aAAa,WAAW;AAAA,QACxB,gBAAgB,WAAW;AAAA,QAC3B,kBAAkB,WAAW,iBAAiB;AAAA,QAC9C,gBAAgB,WAAW,eAAe;AAAA,QAC1C,WAAW,WAAW,UAAU;AAAA,QAChC,kBAAkB,WAAW,iBAAiB;AAAA,QAC9C,GAAI,WAAW,MAAM,SAAS,OAAO,CAAC,IAAI,EAAE,OAAO,WAAW,MAAM,MAAM;AAAA,QAC1E,uBAAuB,CAAC,UAAkB,KAAK,qBAAqB,KAAK;AAAA,QACzE,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM;AAAE,gBAAM,SAAS;AAAG,eAAK,MAAM;AAAA,QAAE,EAAE,IAAI,CAAC;AAAA,QAC3E,GAAI,MAAM,kBAAkB,EAAE,iBAAiB,MAAM;AAAE,gBAAM,kBAAkB;AAAG,eAAK,gBAAgB;AAAA,QAAE,EAAE,IAAI,CAAC;AAAA,QAChH,GAAI,MAAM,oBAAoB,EAAE,mBAAmB,CAAC,OAAqB,YAAqB;AAC5F,gBAAM,oBAAoB,OAAO,OAAO;AACxC,eAAK,oBAAoB,OAAO,OAAO;AAAA,QACzC,EAAE,IAAI,CAAC;AAAA,MACT,GAAY,KAAK;AAAA,IACnB;AAAA,EACF;AACF,CAAC;;;AGzaD,IAAAC,cAA6D;AAC7D,IAAAA,cASO;;;ACVP,IAAAC,cASO;AA2BA,SAAS,oBAAoB,SAAiE;AACnG,QAAM,WAAW,QAAQ,YAAY;AACrC,MAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,YAAY,EAAG,OAAM,IAAI,WAAW,qCAAqC;AAE5G,QAAM,aAAS,wBAA2B,CAAC,CAAC;AAC5C,QAAM,aAAS,wBAA+B,QAAQ,iBAAiB,CAAC,CAAC;AACzE,QAAM,uBAAmB,iBAAI,KAAK;AAClC,QAAM,oBAAgB,iBAAI,KAAK;AAC/B,QAAM,cAAU,iBAAI,IAAI;AACxB,QAAM,gBAAY,iBAAI,KAAK;AAC3B,QAAM,YAAQ,wBAAoB,IAAI;AACtC,QAAM,oBAAgB,sBAAS,MAAM,wBAAwB,OAAO,OAAO,OAAO,KAAK,CAAC;AACxF,MAAI,SAAS;AACb,MAAI,aAAa;AACjB,MAAI,WAAW;AAEf,QAAM,mBAAmB,OAAO,kBAA0B,iBAAqC;AAC7F,UAAM,gBAAgB,wBAAwB,OAAO,OAAO,YAAY,EAAE;AAC1E,WAAO,MAAM;AACX,YAAM,UAAU,EAAE,OAAO,UAAU,QAAQ,QAAQ,aAAa;AAChE,YAAM,OAAO,QAAQ,aACjB,MAAM,QAAQ,WAAW,OAAO,IAChC,UAAM,qBAAQ,QAAQ,MAAM,EAAE,iBAAiB;AAAA,QAC7C,OAAO;AAAA,QACP,QAAQ,QAAQ;AAAA,QAChB,UAAU,aAAa,YAAY;AAAA,MACrC,CAAC;AACL,UAAI,YAAY,qBAAqB,WAAY;AACjD,gBAAU,KAAK;AACf,cAAQ,QAAQ,KAAK,WAAW;AAChC,aAAO,QAAQ,mBAAmB,OAAO,OAAO,IAAI;AACpD,UAAI,CAAC,QAAQ,SAAS,wBAAwB,OAAO,OAAO,YAAY,EAAE,SAAS,cAAe;AAAA,IACpG;AAAA,EACF;AAEA,QAAM,iBAAiB,OAAO,eAAmC,OAAO,UAAU;AAChF,UAAM,mBAAmB,EAAE;AAC3B,WAAO,QAAQ,CAAC;AAChB,aAAS;AACT,YAAQ,QAAQ;AAChB,qBAAiB,QAAQ;AACzB,kBAAc,QAAQ;AACtB,UAAM,QAAQ;AACd,QAAI;AACF,YAAM,iBAAiB,kBAAkB,YAAY;AAAA,IACvD,SAAS,OAAO;AACd,UAAI,CAAC,YAAY,qBAAqB,WAAY,OAAM,QAAQ;AAAA,IAClE,UAAE;AACA,UAAI,CAAC,YAAY,qBAAqB,YAAY;AAChD,yBAAiB,QAAQ;AACzB,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,YAAY;AAC3B,QAAI,iBAAiB,SAAS,cAAc,SAAS,CAAC,QAAQ,MAAO;AACrE,UAAM,mBAAmB;AACzB,kBAAc,QAAQ;AACtB,UAAM,QAAQ;AACd,QAAI;AACF,YAAM,iBAAiB,kBAAkB,OAAO,KAAK;AAAA,IACvD,SAAS,OAAO;AACd,UAAI,CAAC,YAAY,qBAAqB,WAAY,OAAM,QAAQ;AAAA,IAClE,UAAE;AACA,UAAI,CAAC,YAAY,qBAAqB,WAAY,eAAc,QAAQ;AAAA,IAC1E;AAAA,EACF;AAEA,QAAM,YAAY,OAAO,eAAmC;AAC1D,UAAM,mBAAmB,OAAO,MAAM,YAAY;AAClD,WAAO,QAAQ;AACf,UAAM,QAAQ;AACd,SAAK,WAAW,YAAY,WAAW,oBAAoB,CAAC,UAAU,OAAO;AAC3E,YAAM,eAAe,UAAU;AAAA,IACjC,WAAW,wBAAwB,OAAO,OAAO,UAAU,EAAE,WAAW,KAAK,QAAQ,OAAO;AAC1F,YAAM,SAAS;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,UAAkB,UAAU,EAAE,GAAG,OAAO,OAAO,MAAM,CAAC;AACxE,QAAM,UAAU,YAAY;AAC1B,eAAW;AACX,kBAAc;AAAA,EAChB;AAEA,MAAI,QAAQ,YAAY,MAAM;AAC5B,2BAAM,UAAM,qBAAQ,QAAQ,MAAM,GAAG,MAAM;AACzC,iBAAW;AACX,WAAK,eAAe,OAAO,KAAK;AAAA,IAClC,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,EACxB;AACA,UAAI,6BAAgB,EAAG,iCAAe,MAAM;AAAE,SAAK,QAAQ;AAAA,EAAE,CAAC;AAE9D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ADvGA,IAAMC,mBAAkB;AAAA,EACtB,YAAY,EAAE,MAAM,QAA6D,SAAS,OAAU;AAAA,EACpG,QAAQ,EAAE,MAAM,QAAoE,SAAS,OAAU;AAAA,EACvG,SAAS,EAAE,MAAM,QAAuC,SAAS,cAAc;AAAA,EAC/E,UAAU,EAAE,MAAM,SAAS,SAAS,MAAM;AAC5C;AAEA,IAAM,gBAAgB;AAAA,EACpB,GAAGA;AAAA,EACH,eAAe,EAAE,MAAM,OAA4C,UAAU,KAAK;AAAA,EAClF,wBAAwB,EAAE,MAAM,QAAQ,SAAS,OAAU;AAAA,EAC3D,sBAAsB,EAAE,MAAM,UAA4D,SAAS,OAAU;AAAA,EAC7G,WAAW,EAAE,MAAM,UAAkD,SAAS,OAAU;AAAA,EACxF,YAAY,EAAE,MAAM,UAAkD,SAAS,OAAU;AAAA,EACzF,kBAAkB,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,EAClD,eAAe,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,EAC/C,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,EACzC,OAAO,EAAE,MAAM,MAAsC,UAAU,MAAM;AAAA,EACrE,eAAe,EAAE,MAAM,QAA6C,SAAS,OAAU;AAAA,EACvF,qBAAqB,EAAE,MAAM,QAAQ,SAAS,IAAI;AAAA,EAClD,WAAW,EAAE,MAAM,QAAQ,SAAS,gBAAgB;AACtD;AAGO,IAAM,2BAAuB,6BAAgB;AAAA,EAClD,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO;AAAA,IACL,uBAAuB,CAAC,kBAAgC;AAAA,IACxD,SAAS,MAAM;AAAA,IACf,aAAa,MAAM;AAAA,EACrB;AAAA,EACA,MAAM,OAAO,EAAE,OAAO,MAAM,MAAM,GAAG;AACnC,UAAM,sBAAkB,iBAAwB,IAAI;AACpD,QAAI,kBAAkB;AACtB,QAAI,sBAAqC;AAEzC,UAAM,aAAa,OAAgC;AAAA,MACjD,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,MAChB,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC3D,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IACjD;AAEA,UAAM,cAAc,YAAY;AAC9B,UAAI,mBAAmB,wBAAwB,MAAM,cAAc,UAAU,MAAM,oBAAoB,MAAM,iBAAiB,CAAC,MAAM,WAAW,CAAC,MAAM,WAAY;AACnK,wBAAkB;AAClB,4BAAsB,MAAM,cAAc;AAC1C,UAAI;AAAE,cAAM,MAAM,WAAW;AAAA,MAAE,QACzB;AAAE,8BAAsB;AAAA,MAAK,UACnC;AAAU,0BAAkB;AAAA,MAAM;AAAA,IACpC;AAEA,UAAM,qBAAqB,CAAC,iBAA+B;AACzD,YAAM,uBAAuB,YAAY;AAAA,IAC3C;AAEA,UAAM,UAAU,MAAM;AACpB,aAAO,MAAM,YAAY;AAAA,IAC3B;AAEA,UAAM,gBAAgB,MAAM;AAC1B,YAAM,oBAAoB,WAAW;AACrC,UAAI,MAAM,oBAAoB,MAAM,cAAc,WAAW,GAAG;AAC9D,eAAO,MAAM,iBAAiB,IAAI,SAAK,eAAE,OAAO;AAAA,UAC9C,OAAO,UAAU,WAAW,mBAAmB,YAAY;AAAA,UAC3D,OAAO,UAAU,WAAW,iBAAiB;AAAA,UAC7C,MAAM;AAAA,QACR,GAAG,KAAC,eAAE,0BAAc,EAAE,OAAO,aAAa,eAAe,OAAO,CAAC,GAAG,8BAAyB,CAAC;AAAA,MAChG;AACA,UAAI,MAAM,SAAS,MAAM,cAAc,WAAW,GAAG;AACnD,cAAM,QAAQ,MAAM,YAAY,MAAM;AAAE,eAAK,QAAQ;AAAA,QAAE,IAAI;AAC3D,eAAO,MAAM,QAAQ,EAAE,OAAO,MAAM,OAAO,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAG,CAAC,SAAK,eAAE,OAAO;AAAA,UACpF,OAAO,UAAU,SAAS,mBAAmB,8BAA8B;AAAA,UAC3E,OAAO,UAAU,SAAS,iBAAiB;AAAA,UAC3C,MAAM;AAAA,QACR,GAAG;AAAA,cACD,eAAE,QAAQ,aAAa,MAAM,KAAK,CAAC;AAAA,UACnC,YAAQ,eAAE,UAAU,EAAE,MAAM,UAAU,OAAO,oBAAoB,SAAS,MAAM,GAAG,WAAW,IAAI;AAAA,QACpG,CAAC;AAAA,MACH;AACA,UAAI,MAAM,cAAc,WAAW,GAAG;AACpC,eAAO,MAAM,QAAQ,SAAK,eAAE,OAAO;AAAA,UACjC,OAAO,UAAU,SAAS,mBAAmB,YAAY;AAAA,UACzD,OAAO,UAAU,SAAS,iBAAiB;AAAA,QAC7C,GAAG,KAAC,eAAE,mBAAO,EAAE,eAAe,OAAO,CAAC,GAAG,uBAAuB,CAAC;AAAA,MACnE;AACA,YAAM,WAAyB,MAAM,cAAc,QAAQ,CAAC,cAAc,UAAU;AAClF,cAAM,WAAW,MAAM,2BAA2B,aAAa;AAC/D,cAAM,SAAS,MAAM,mBAAmB,YAAY;AACpD,cAAM,YAAuC,EAAE,cAAc,OAAO,UAAU,OAAO;AACrF,cAAM,OAAO,MAAM,mBAAmB,IAAI,SAAS,SAAK,eAAE,UAAU;AAAA,UAClE,MAAM;AAAA,UACN,iBAAiB,YAAY;AAAA,UAC7B,gBAAgB,WAAW,SAAS;AAAA,UACpC,SAAS;AAAA,UACT,OAAO,UAAU,YAAY,mBAAmB,wBAAwB;AAAA,UACxE,OAAO,UAAU,YAAY,iBAAiB;AAAA,QAChD,GAAG;AAAA,cACD,eAAE,gBAAgB;AAAA,YAChB,MAAM,aAAa;AAAA,YACnB,KAAK,aAAa;AAAA,YAClB,OAAO,UAAU,UAAU,mBAAmB,EAAE;AAAA,YAChD,OAAO,UAAU,UAAU,iBAAiB;AAAA,UAC9C,CAAU;AAAA,cACV,eAAE,QAAQ,EAAE,OAAO,+BAA+B,GAAG;AAAA,gBACnD,eAAE,UAAU,aAAa,YAAY;AAAA,gBACrC,eAAE,QAAQ,aAAa,aAAa,IAAI,CAAC,gBAAgB,YAAY,IAAI,EAAE,KAAK,IAAI,KAAK,aAAa,eAAe,iBAAiB;AAAA,UACxI,CAAC;AAAA,cACD,eAAE,0BAAc,EAAE,MAAM,IAAI,eAAe,OAAO,CAAC;AAAA,QACrD,CAAC;AACD,cAAM,QAAQ,KAAC,eAAE,OAAO,EAAE,KAAK,aAAa,IAAI,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3E,YAAI,QAAQ,MAAM,cAAc,SAAS,GAAG;AAC1C,gBAAM,SAAK,eAAE,OAAO,EAAE,KAAK,GAAG,aAAa,EAAE,aAAa,GAAG,MAAM,YAAY,EAAE,MAAM,CAAC,SAAK,eAAE,OAAO,EAAE,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAAA,QACrI;AACA,eAAO;AAAA,MACT,CAAC;AACD,UAAI,MAAM,OAAO;AACf,iBAAS,KAAK,MAAM,QAAQ,EAAE,OAAO,MAAM,OAAO,OAAO,YAAY,CAAC,SAAK,eAAE,OAAO;AAAA,UAClF,OAAO,UAAU,SAAS,mBAAmB,qCAAqC;AAAA,UAClF,OAAO,UAAU,SAAS,iBAAiB;AAAA,UAC3C,MAAM;AAAA,QACR,GAAG,KAAC,eAAE,QAAQ,aAAa,MAAM,KAAK,CAAC,OAAG,eAAE,UAAU,EAAE,MAAM,UAAU,OAAO,oBAAoB,SAAS,MAAM;AAAE,eAAK,YAAY;AAAA,QAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;AAAA,MACxJ,WAAW,MAAM,eAAe;AAC9B,iBAAS,KAAK,MAAM,WAAW,IAAI,SAAK,eAAE,OAAO;AAAA,UAC/C,OAAO,UAAU,WAAW,mBAAmB,mBAAmB;AAAA,UAClE,OAAO,UAAU,WAAW,iBAAiB;AAAA,UAC7C,MAAM;AAAA,QACR,GAAG,KAAC,eAAE,0BAAc,EAAE,OAAO,aAAa,eAAe,OAAO,CAAC,GAAG,qBAAgB,CAAC,CAAC;AAAA,MACxF;AACA,iBAAO,eAAE,OAAO;AAAA,QACd,MAAM;AAAA,QACN,OAAO,UAAU,QAAQ,mBAAmB,+BAA+B;AAAA,QAC3E,OAAO,UAAU,QAAQ,iBAAiB;AAAA,MAC5C,GAAG,QAAQ;AAAA,IACb;AAEA,WAAO,UAAM,eAAE,OAAO;AAAA,MACpB,GAAG;AAAA,MACH,OAAO,GAAG,CAAC,MAAM,YAAY,+BAA+B,MAAM,YAAY,MAAM,MAAM,KAAK;AAAA,MAC/F,OAAO,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,MACvC,gBAAgB,MAAM;AAAA,IACxB,GAAG;AAAA,MACD,MAAM,gBAAY,eAAE,OAAO,EAAE,OAAO,kCAAkC,GAAG;AAAA,YACvE,eAAE,QAAQ,MAAM,SAAS;AAAA,YACzB,eAAE,UAAU;AAAA,UACV,MAAM;AAAA,UACN,cAAc;AAAA,UACd,OAAO,UAAU,UAAU,WAAW,GAAG,kBAAkB;AAAA,UAC3D,OAAO,UAAU,UAAU,WAAW,CAAC;AAAA,UACvC,SAAS,MAAM;AAAE,iBAAK,QAAQ;AAAA,UAAE;AAAA,QAClC,GAAG,KAAC,eAAE,uBAAW,EAAE,MAAM,IAAI,eAAe,OAAO,CAAC,CAAC,CAAC;AAAA,MACxD,CAAC,IAAI;AAAA,UACL,eAAE,OAAO;AAAA,QACP,KAAK,CAAC,YAAqB;AACzB,0BAAgB,QAAQ;AACxB,cAAI,MAAM,cAAe,OAAM,cAAc,QAAQ;AAAA,QACvD;AAAA,QACA,OAAO,GAAG,CAAC,MAAM,YAAY,oBAAoB,MAAM,YAAY,IAAI;AAAA,QACvE,OAAO,MAAM,QAAQ;AAAA,QACrB,cAAc,MAAM;AAAA,QACpB,UAAU,CAAC,UAAiB;AAC1B,gBAAM,gBAAgB,MAAM;AAC5B,cAAI,OAAO,kBAAkB,WAAY,eAAc,KAAK;AAC5D,gBAAM,UAAU,MAAM;AACtB,cAAI,QAAQ,eAAe,QAAQ,YAAY,QAAQ,gBAAgB,MAAM,oBAAqB,MAAK,YAAY;AAAA,QACrH;AAAA,MACF,GAAG,CAAC,cAAc,CAAC,CAAC;AAAA,IACtB,CAAC;AAAA,EACH;AACF,CAAC;AAUM,IAAM,uBAAmB,6BAAgB;AAAA,EAC9C,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,IACL,GAAG;AAAA,IACH,eAAe,EAAE,MAAM,OAA4C,SAAS,MAAM,CAAC,EAAE;AAAA,IACrF,QAAQ,EAAE,MAAM,QAAsC,UAAU,KAAK;AAAA,IACrE,YAAY,EAAE,MAAM,UAA8C,SAAS,OAAU;AAAA,IACrF,eAAe,EAAE,MAAM,QAAwC,SAAS,OAAU;AAAA,IAClF,UAAU,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,IACtC,UAAU,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IACzC,oBAAoB,EAAE,MAAM,UAAwE,SAAS,OAAU;AAAA,EACzH;AAAA,EACA,OAAO,CAAC,uBAAuB,mBAAmB;AAAA,EAClD,MAAM,OAAO,EAAE,OAAO,MAAM,QAAQ,MAAM,GAAG;AAC3C,UAAM,aAAa,oBAAoB;AAAA,MACrC,QAAQ,MAAM,MAAM;AAAA,MACpB,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC3D,GAAI,MAAM,gBAAgB,EAAE,eAAe,MAAM,cAAc,IAAI,CAAC;AAAA,MACpE,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,IAClB,CAAC;AACD,WAAO,EAAE,WAAW,CAAC;AACrB,iCAAY,MAAM;AAChB,WAAK,qBAAqB,UAAU;AAAA,IACtC,CAAC;AACD,WAAO,MAAM;AACX,YAAM;AAAA,QACJ,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,UAAU;AAAA,QACV,UAAU;AAAA,QACV,oBAAoB;AAAA,QACpB,eAAe;AAAA,QACf,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,kBAAkB;AAAA,QAClB,eAAe;AAAA,QACf,SAAS;AAAA,QACT,OAAO;AAAA,QACP,GAAG;AAAA,MACL,IAAI;AACJ,iBAAO,eAAE,sBAAsB;AAAA,QAC/B,GAAG;AAAA,QACH,GAAG;AAAA,QACH,eAAe,WAAW,cAAc;AAAA,QACxC,WAAW,WAAW;AAAA,QACtB,YAAY,WAAW;AAAA,QACvB,kBAAkB,WAAW,iBAAiB;AAAA,QAC9C,eAAe,WAAW,cAAc;AAAA,QACxC,SAAS,WAAW,QAAQ;AAAA,QAC5B,GAAI,WAAW,MAAM,SAAS,OAAO,CAAC,IAAI,EAAE,OAAO,WAAW,MAAM,MAAM;AAAA,QAC1E,sBAAsB,CAAC,iBAA+B;AACpD,eAAK,uBAAuB,YAAY;AAAA,QAC1C;AAAA,MACA,GAAY,KAAK;AAAA,IACnB;AAAA,EACF;AACF,CAAC;;;AE3RD,IAAAC,eAUO;AAmBA,IAAM,uBAAsC;AAAA,EACjD,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,YAAY;AACd;AAEA,IAAM,WAAuD,uBAAO,eAAe;AACnF,IAAM,sBAAkB,uBAAS,MAAM,oBAAoB;AAEpD,IAAM,4BAAwB,8BAAgB;AAAA,EACnD,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,IACL,OAAO,EAAE,MAAM,QAA4C,SAAS,OAAO,CAAC,GAAG;AAAA,IAC/E,OAAO,EAAE,MAAM,CAAC,QAAQ,OAAO,MAAM,GAAwB,SAAS,OAAU;AAAA,IAChF,OAAO,EAAE,MAAM,CAAC,QAAQ,OAAO,MAAM,GAAwB,SAAS,OAAU;AAAA,EAClF;AAAA,EACA,MAAM,OAAO,EAAE,OAAO,MAAM,GAAG;AAC7B,UAAM,aAAS,qBAAO,UAAU,eAAe;AAC/C,UAAM,YAAQ,uBAAS,OAAO,EAAE,GAAG,OAAO,OAAO,GAAG,MAAM,MAAM,EAAE;AAClE,8BAAQ,UAAU,KAAK;AACvB,WAAO,MAAM;AACX,YAAM,QAAQ,MAAM;AACpB,YAAM,YAAY;AAAA,QAChB,qBAAqB,MAAM;AAAA,QAC3B,kBAAkB,MAAM;AAAA,QACxB,kBAAkB,MAAM;AAAA,QACxB,eAAe,MAAM;AAAA,QACrB,gBAAgB,MAAM;AAAA,QACtB,iBAAiB,MAAM;AAAA,QACvB,gBAAgB,MAAM;AAAA,QACtB,mBAAmB,MAAM;AAAA,QACzB,mBAAmB,MAAM;AAAA,QACzB,wBAAwB,MAAM;AAAA,QAC9B,iBAAiB,MAAM;AAAA,QACvB,sBAAsB,MAAM;AAAA,QAC5B,eAAe,MAAM;AAAA,MACvB;AACA,iBAAO,gBAAE,OAAO;AAAA,QACd,GAAG;AAAA,QACH,OAAO,GAAG,cAAc,MAAM,OAAO,MAAM,KAAK;AAAA,QAChD,OAAO,CAAC,WAAW,MAAM,OAAO,MAAM,KAAK;AAAA,MAC7C,GAAG,MAAM,UAAU,CAAC;AAAA,IACtB;AAAA,EACF;AACF,CAAC;AAEM,SAAS,mBAAiD;AAC/D,aAAO,qBAAO,UAAU,eAAe;AACzC;","names":["import_vue","import_vue","import_vue","appearanceProps","import_vue","import_vue","appearanceProps","import_vue"]}
package/dist/index.d.cts CHANGED
@@ -1603,6 +1603,8 @@ declare const ConvoKitThemeProvider: vue.DefineComponent<vue.ExtractPropTypes<{
1603
1603
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
1604
1604
  declare function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>>;
1605
1605
 
1606
+ /** Whether a message is an optimistic row awaiting server acknowledgement. */
1607
+ declare function isConvoKitPendingMessage(message: Message): boolean;
1606
1608
  declare function matchesConversation(conversation: Conversation$1, filter: ConversationFilter): boolean;
1607
1609
  declare function applyConversationFilter(conversations: readonly Conversation$1[], filter: ConversationFilter): Conversation$1[];
1608
1610
  declare function mergeConversations(current: readonly Conversation$1[], incoming: readonly Conversation$1[]): Conversation$1[];
@@ -1610,4 +1612,4 @@ declare function mergeMessages(current: readonly Message[], incoming: readonly M
1610
1612
  declare function readerIdsFor(message: Message, readAtByUserId: ReadonlyMap<string, Date>): ReadonlySet<string>;
1611
1613
  declare function formatFileSize(size: number | undefined): string | null;
1612
1614
 
1613
- export { type BaseViewProps, type ComposerSlotProps, Conversation, type ConversationController, type ConversationFilter, type ConversationItemSlotProps, ConversationList, type ConversationListController, type ConversationListProps, type ConversationListState, ConversationListView, type ConversationListViewProps, type ConversationPageLoader, type ConversationPageRequest, type ConversationProps, type ConversationState, ConversationView, type ConversationViewProps, type ConvoKitAppearanceProps, ConvoKitAvatar, type ConvoKitTheme, ConvoKitThemeProvider, type ConvoKitUiClient, type ConvoKitUiDensity, type ConvoKitUiPart, type ErrorSlot, type ErrorSlotProps, type MediaSlotProps, MessageListView, type MessageListViewProps, type MessageSlotProps, type ReadReceiptSlotProps, type ScrollOptions, type StateSlot, type TypingSlotProps, type UseConversationListOptions, type UseConversationOptions, applyConversationFilter, createConvoKitUiClient, defaultConvoKitTheme, defaultReadersResolver, formatFileSize, matchesConversation, mergeConversations, mergeMessages, readerIdsFor, useConversation, useConversationList, useConvoKitTheme };
1615
+ export { type BaseViewProps, type ComposerSlotProps, Conversation, type ConversationController, type ConversationFilter, type ConversationItemSlotProps, ConversationList, type ConversationListController, type ConversationListProps, type ConversationListState, ConversationListView, type ConversationListViewProps, type ConversationPageLoader, type ConversationPageRequest, type ConversationProps, type ConversationState, ConversationView, type ConversationViewProps, type ConvoKitAppearanceProps, ConvoKitAvatar, type ConvoKitTheme, ConvoKitThemeProvider, type ConvoKitUiClient, type ConvoKitUiDensity, type ConvoKitUiPart, type ErrorSlot, type ErrorSlotProps, type MediaSlotProps, MessageListView, type MessageListViewProps, type MessageSlotProps, type ReadReceiptSlotProps, type ScrollOptions, type StateSlot, type TypingSlotProps, type UseConversationListOptions, type UseConversationOptions, applyConversationFilter, createConvoKitUiClient, defaultConvoKitTheme, defaultReadersResolver, formatFileSize, isConvoKitPendingMessage, matchesConversation, mergeConversations, mergeMessages, readerIdsFor, useConversation, useConversationList, useConvoKitTheme };
package/dist/index.d.ts CHANGED
@@ -1603,6 +1603,8 @@ declare const ConvoKitThemeProvider: vue.DefineComponent<vue.ExtractPropTypes<{
1603
1603
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
1604
1604
  declare function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>>;
1605
1605
 
1606
+ /** Whether a message is an optimistic row awaiting server acknowledgement. */
1607
+ declare function isConvoKitPendingMessage(message: Message): boolean;
1606
1608
  declare function matchesConversation(conversation: Conversation$1, filter: ConversationFilter): boolean;
1607
1609
  declare function applyConversationFilter(conversations: readonly Conversation$1[], filter: ConversationFilter): Conversation$1[];
1608
1610
  declare function mergeConversations(current: readonly Conversation$1[], incoming: readonly Conversation$1[]): Conversation$1[];
@@ -1610,4 +1612,4 @@ declare function mergeMessages(current: readonly Message[], incoming: readonly M
1610
1612
  declare function readerIdsFor(message: Message, readAtByUserId: ReadonlyMap<string, Date>): ReadonlySet<string>;
1611
1613
  declare function formatFileSize(size: number | undefined): string | null;
1612
1614
 
1613
- export { type BaseViewProps, type ComposerSlotProps, Conversation, type ConversationController, type ConversationFilter, type ConversationItemSlotProps, ConversationList, type ConversationListController, type ConversationListProps, type ConversationListState, ConversationListView, type ConversationListViewProps, type ConversationPageLoader, type ConversationPageRequest, type ConversationProps, type ConversationState, ConversationView, type ConversationViewProps, type ConvoKitAppearanceProps, ConvoKitAvatar, type ConvoKitTheme, ConvoKitThemeProvider, type ConvoKitUiClient, type ConvoKitUiDensity, type ConvoKitUiPart, type ErrorSlot, type ErrorSlotProps, type MediaSlotProps, MessageListView, type MessageListViewProps, type MessageSlotProps, type ReadReceiptSlotProps, type ScrollOptions, type StateSlot, type TypingSlotProps, type UseConversationListOptions, type UseConversationOptions, applyConversationFilter, createConvoKitUiClient, defaultConvoKitTheme, defaultReadersResolver, formatFileSize, matchesConversation, mergeConversations, mergeMessages, readerIdsFor, useConversation, useConversationList, useConvoKitTheme };
1615
+ export { type BaseViewProps, type ComposerSlotProps, Conversation, type ConversationController, type ConversationFilter, type ConversationItemSlotProps, ConversationList, type ConversationListController, type ConversationListProps, type ConversationListState, ConversationListView, type ConversationListViewProps, type ConversationPageLoader, type ConversationPageRequest, type ConversationProps, type ConversationState, ConversationView, type ConversationViewProps, type ConvoKitAppearanceProps, ConvoKitAvatar, type ConvoKitTheme, ConvoKitThemeProvider, type ConvoKitUiClient, type ConvoKitUiDensity, type ConvoKitUiPart, type ErrorSlot, type ErrorSlotProps, type MediaSlotProps, MessageListView, type MessageListViewProps, type MessageSlotProps, type ReadReceiptSlotProps, type ScrollOptions, type StateSlot, type TypingSlotProps, type UseConversationListOptions, type UseConversationOptions, applyConversationFilter, createConvoKitUiClient, defaultConvoKitTheme, defaultReadersResolver, formatFileSize, isConvoKitPendingMessage, matchesConversation, mergeConversations, mergeMessages, readerIdsFor, useConversation, useConversationList, useConvoKitTheme };