@convokitapp/vue-ui 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Conversation as Conversation$1, MessageListOptions, Message, SendMessageInput, MarkConversationReadOptions, RealtimeConnectionHandlers, RealtimeSubscription, MessageEvent, MessageDeletedEvent, ReadEvent, TypingEvent, ReadPosition, MessageMedia, ConvoKitClient } from '@convokitapp/sdk';
1
+ import { Conversation as Conversation$1, InboxPage, MessageListOptions, Message, SendMessageInput, MarkConversationReadOptions, ConversationPrivateState, ClearConversationUnreadOptions, ClearUnreadResult, RealtimeConnectionHandlers, RealtimeSubscription, MessageEvent, MessageDeletedEvent, ReadEvent, TypingEvent, ReadPosition, InboxSummary, MessageMedia, ConvoKitClient, InboxEntry } from '@convokitapp/sdk';
2
2
  import * as vue from 'vue';
3
3
  import { CSSProperties, HTMLAttributes, Ref, VNodeChild, PropType, MaybeRefOrGetter, TextareaHTMLAttributes } from 'vue';
4
4
 
@@ -11,17 +11,39 @@ interface ConvoKitUiClient {
11
11
  offset: number;
12
12
  archived: boolean;
13
13
  }): Promise<Conversation$1[]>;
14
+ /** Activity-ordered inbox pages with a preview, unread count and read state per row (core 0.6). Pass the previous
15
+ * `nextCursor` back as `cursor` (null for the head). Adapters without it, and custom page loaders, use the legacy
16
+ * `getConversations` path without summaries; a 404 from this endpoint falls back to that path for the store's life.
17
+ */
18
+ listInbox?(options: {
19
+ limit: number;
20
+ cursor: string | null;
21
+ archived: boolean;
22
+ }): Promise<InboxPage>;
23
+ /** The room and, from a 0.7 core and backend, the caller's own `membership`; the room store captures
24
+ * `membership.privateStateVersion` once per open for that open's acknowledgements.
25
+ */
14
26
  getConversation(conversationId: string): Promise<Conversation$1>;
15
27
  /** Newest first, with a paired value cursor; never derive an offset from rendered rows. */
16
28
  getMessages(options: MessageListOptions): Promise<Message[]>;
17
29
  /** Complete authorized message, including related media absent from raw row events. */
18
30
  getMessage(id: string): Promise<Message>;
19
31
  sendMessage(input: SendMessageInput): Promise<Message>;
20
- /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward it
21
- * and reject a missing target with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a
22
- * request without a target. Membership failures keep their error code, if any, so they surface as errors.
32
+ /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward the
33
+ * options unchanged (0.7 adds `privateStateVersion`, the version captured when the room opened; an adapter that
34
+ * drops it acknowledges the position but never clears the caller's unread marker) and reject a missing target
35
+ * with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a request without a target.
36
+ * Membership failures keep their error code, if any, so they surface as errors.
23
37
  */
24
38
  markConversationRead(conversationId: string, options?: MarkConversationReadOptions): Promise<void>;
39
+ /** Mark the room unread for the caller only (0.7.0). Optional: `markUnread` rejects without it. */
40
+ markConversationUnread?(conversationId: string): Promise<ConversationPrivateState>;
41
+ /** Remove the caller's unread marker, only while it still has `options.ifVersion` when given (0.7.0); a mismatch or
42
+ * an unmarked room answers `cleared: false`, never an error. Optional: `clearUnread` rejects without it, and a room
43
+ * opened with a marker that renders nothing leaves the marker in place (the room store clears it through this
44
+ * member, never through an untargeted acknowledgement).
45
+ */
46
+ clearConversationUnread?(conversationId: string, options?: ClearConversationUnreadOptions): Promise<ClearUnreadResult>;
25
47
  sendTyping(input: {
26
48
  conversationId: string;
27
49
  isTyping: boolean;
@@ -29,6 +51,11 @@ interface ConvoKitUiClient {
29
51
  onConnectionEvent(handlers: RealtimeConnectionHandlers): RealtimeSubscription;
30
52
  /** Notify on inbox mutations AND on initial subscription/reconnect. No room data in the signal. */
31
53
  onInboxChanged(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
54
+ /** Message inserts/edits, read-position advances and the caller's own unread-marker changes in the caller's
55
+ * rooms; never fires on join/rejoin. The list store throttles these (`activityRefreshWindowMs`); room stores
56
+ * ignore them.
57
+ */
58
+ onInboxActivity?(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
32
59
  onMessage(conversationId: string, handler: (event: MessageEvent) => void, onError?: (error: Error) => void): RealtimeSubscription;
33
60
  onMessageDeleted(conversationId: string, handler: (event: MessageDeletedEvent) => void, onError?: (error: Error) => void): RealtimeSubscription;
34
61
  onReadReceipt(conversationId: string, handler: (event: ReadEvent) => void, onError?: (error: Error) => void): RealtimeSubscription;
@@ -51,6 +78,12 @@ interface ConversationPageRequest {
51
78
  type ConversationPageLoader = (request: ConversationPageRequest) => Promise<Conversation$1[]>;
52
79
  interface ConversationListState {
53
80
  conversations: Readonly<Ref<Conversation$1[]>>;
81
+ /** Per-room preview, unread count, read state and private unread marker (`isUnread`, `unreadMarkedAt`,
82
+ * `privateStateVersion`, 0.7.0) by conversation ID; empty on the legacy `getConversations` path.
83
+ */
84
+ summaries: Readonly<Ref<ReadonlyMap<string, InboxSummary>>>;
85
+ /** The bound session's user; `''` without a session, on the legacy path and after disposal. */
86
+ currentUserId: Readonly<Ref<string>>;
54
87
  filter: Readonly<Ref<ConversationFilter>>;
55
88
  isInitialLoading: Readonly<Ref<boolean>>;
56
89
  isLoadingMore: Readonly<Ref<boolean>>;
@@ -89,6 +122,12 @@ interface ConversationItemSlotProps {
89
122
  index: number;
90
123
  selected: boolean;
91
124
  select: () => void;
125
+ /** Present when the list carries an inbox summary for this row (0.6.0); `summary.isUnread` (0.7.0) is the row's
126
+ * unread state including the viewer's private marker.
127
+ */
128
+ summary?: InboxSummary;
129
+ /** Present when the list knows the viewer (0.6.0); compare with `summary.latestMessage.senderId`. */
130
+ currentUserId?: string;
92
131
  }
93
132
  interface MessageSlotProps {
94
133
  message: Message;
@@ -979,6 +1018,8 @@ interface UseConversationListOptions {
979
1018
  initialFilter?: ConversationFilter;
980
1019
  pageSize?: number;
981
1020
  autoLoad?: boolean;
1021
+ /** Max-wait window (ms) that coalesces `inbox_activity` signals into one refresh; default 500, 0 = immediate. */
1022
+ activityRefreshWindowMs?: number;
982
1023
  }
983
1024
  interface ConversationListController extends ConversationListState {
984
1025
  loadInitial(): Promise<void>;
@@ -986,12 +1027,26 @@ interface ConversationListController extends ConversationListState {
986
1027
  loadMore(): Promise<void>;
987
1028
  setFilter(filter: ConversationFilter): Promise<void>;
988
1029
  setQuery(query: string): Promise<void>;
1030
+ /** Mark a room unread for the viewer only (0.7.0); its summary shows the marker at once. Rejects when the adapter
1031
+ * lacks `markConversationUnread`.
1032
+ */
1033
+ markUnread(conversationId: string): Promise<void>;
1034
+ /** Remove the viewer's marker, only while it still has `options.ifVersion` when given; resolves to whether this
1035
+ * request removed it. Rejects when the adapter lacks `clearConversationUnread`.
1036
+ */
1037
+ clearUnread(conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean>;
989
1038
  dispose(): Promise<void>;
990
1039
  }
991
1040
  declare function useConversationList(options: UseConversationListOptions): ConversationListController;
992
1041
 
993
1042
  interface ConversationListViewProps extends ConvoKitAppearanceProps {
994
1043
  conversations: readonly Conversation$1[];
1044
+ /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge: the count, or
1045
+ * a numberless dot when `isUnread` is set without one (0.7.0).
1046
+ */
1047
+ summaries?: ReadonlyMap<string, InboxSummary>;
1048
+ /** The viewer; a preview from them reads `You: …`. Absent → no prefix. */
1049
+ currentUserId?: string;
995
1050
  selectedConversationId?: string;
996
1051
  onConversationSelect?: (conversation: Conversation$1) => void;
997
1052
  onRefresh?: () => void | Promise<void>;
@@ -1012,6 +1067,14 @@ declare const ConversationListView: vue.DefineComponent<vue.ExtractPropTypes<{
1012
1067
  readonly type: PropType<readonly Conversation$1[]>;
1013
1068
  readonly required: true;
1014
1069
  };
1070
+ readonly summaries: {
1071
+ readonly type: PropType<ReadonlyMap<string, InboxSummary>>;
1072
+ readonly default: undefined;
1073
+ };
1074
+ readonly currentUserId: {
1075
+ readonly type: StringConstructor;
1076
+ readonly default: undefined;
1077
+ };
1015
1078
  readonly selectedConversationId: {
1016
1079
  readonly type: StringConstructor;
1017
1080
  readonly default: undefined;
@@ -1083,6 +1146,14 @@ declare const ConversationListView: vue.DefineComponent<vue.ExtractPropTypes<{
1083
1146
  readonly type: PropType<readonly Conversation$1[]>;
1084
1147
  readonly required: true;
1085
1148
  };
1149
+ readonly summaries: {
1150
+ readonly type: PropType<ReadonlyMap<string, InboxSummary>>;
1151
+ readonly default: undefined;
1152
+ };
1153
+ readonly currentUserId: {
1154
+ readonly type: StringConstructor;
1155
+ readonly default: undefined;
1156
+ };
1086
1157
  readonly selectedConversationId: {
1087
1158
  readonly type: StringConstructor;
1088
1159
  readonly default: undefined;
@@ -1149,6 +1220,7 @@ declare const ConversationListView: vue.DefineComponent<vue.ExtractPropTypes<{
1149
1220
  "onLoad-more"?: () => any;
1150
1221
  }>, {
1151
1222
  readonly isInitialLoading: boolean;
1223
+ readonly currentUserId: string;
1152
1224
  readonly scrollElement: Ref<HTMLElement | null, HTMLElement | null>;
1153
1225
  readonly paginationThreshold: number;
1154
1226
  readonly classNames: Partial<Record<ConvoKitUiPart, string>>;
@@ -1156,6 +1228,7 @@ declare const ConversationListView: vue.DefineComponent<vue.ExtractPropTypes<{
1156
1228
  readonly density: ConvoKitUiDensity;
1157
1229
  readonly unstyled: boolean;
1158
1230
  readonly onRefresh: () => void | Promise<void>;
1231
+ readonly summaries: ReadonlyMap<string, InboxSummary>;
1159
1232
  readonly isLoadingMore: boolean;
1160
1233
  readonly hasMore: boolean;
1161
1234
  readonly selectedConversationId: string;
@@ -1193,10 +1266,22 @@ declare const ConversationList: vue.DefineComponent<vue.ExtractPropTypes<{
1193
1266
  type: BooleanConstructor;
1194
1267
  default: boolean;
1195
1268
  };
1269
+ activityRefreshWindowMs: {
1270
+ type: NumberConstructor;
1271
+ default: undefined;
1272
+ };
1196
1273
  onControllerChange: {
1197
1274
  type: PropType<(controller: ConversationListController) => void>;
1198
1275
  default: undefined;
1199
1276
  };
1277
+ summaries: {
1278
+ readonly type: PropType<ReadonlyMap<string, InboxSummary>>;
1279
+ readonly default: undefined;
1280
+ };
1281
+ currentUserId: {
1282
+ readonly type: StringConstructor;
1283
+ readonly default: undefined;
1284
+ };
1200
1285
  selectedConversationId: {
1201
1286
  readonly type: StringConstructor;
1202
1287
  readonly default: undefined;
@@ -1284,10 +1369,22 @@ declare const ConversationList: vue.DefineComponent<vue.ExtractPropTypes<{
1284
1369
  type: BooleanConstructor;
1285
1370
  default: boolean;
1286
1371
  };
1372
+ activityRefreshWindowMs: {
1373
+ type: NumberConstructor;
1374
+ default: undefined;
1375
+ };
1287
1376
  onControllerChange: {
1288
1377
  type: PropType<(controller: ConversationListController) => void>;
1289
1378
  default: undefined;
1290
1379
  };
1380
+ summaries: {
1381
+ readonly type: PropType<ReadonlyMap<string, InboxSummary>>;
1382
+ readonly default: undefined;
1383
+ };
1384
+ currentUserId: {
1385
+ readonly type: StringConstructor;
1386
+ readonly default: undefined;
1387
+ };
1291
1388
  selectedConversationId: {
1292
1389
  readonly type: StringConstructor;
1293
1390
  readonly default: undefined;
@@ -1353,6 +1450,7 @@ declare const ConversationList: vue.DefineComponent<vue.ExtractPropTypes<{
1353
1450
  "onConversation-select"?: (...args: any[]) => any;
1354
1451
  }>, {
1355
1452
  isInitialLoading: boolean;
1453
+ currentUserId: string;
1356
1454
  scrollElement: Ref<HTMLElement | null, HTMLElement | null>;
1357
1455
  paginationThreshold: number;
1358
1456
  classNames: Partial<Record<ConvoKitUiPart, string>>;
@@ -1363,6 +1461,7 @@ declare const ConversationList: vue.DefineComponent<vue.ExtractPropTypes<{
1363
1461
  autoLoad: boolean;
1364
1462
  onControllerChange: (controller: ConversationListController) => void;
1365
1463
  conversations: readonly Conversation$1[];
1464
+ summaries: ReadonlyMap<string, InboxSummary>;
1366
1465
  isLoadingMore: boolean;
1367
1466
  hasMore: boolean;
1368
1467
  selectedConversationId: string;
@@ -1372,8 +1471,29 @@ declare const ConversationList: vue.DefineComponent<vue.ExtractPropTypes<{
1372
1471
  pageLoader: ConversationPageLoader;
1373
1472
  initialFilter: ConversationFilter;
1374
1473
  pageSize: number;
1474
+ activityRefreshWindowMs: number;
1375
1475
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
1376
1476
 
1477
+ /** Whether a message is an optimistic row awaiting server acknowledgement. */
1478
+ declare function isConvoKitPendingMessage(message: Message): boolean;
1479
+ declare function matchesConversation(conversation: Conversation$1, filter: ConversationFilter): boolean;
1480
+ declare function applyConversationFilter(conversations: readonly Conversation$1[], filter: ConversationFilter): Conversation$1[];
1481
+ declare function mergeConversations(current: readonly Conversation$1[], incoming: readonly Conversation$1[]): Conversation$1[];
1482
+ /** Merge inbox pages by conversation ID: a later entry replaces an earlier one (its room moved), and the result is
1483
+ * re-ordered by `(activityAt desc, id desc)`. Server order is authoritative within a page; this is the rule applied
1484
+ * whenever pages are combined (load more, refresh).
1485
+ */
1486
+ declare function mergeInboxEntries(current: readonly InboxEntry[], incoming: readonly InboxEntry[]): InboxEntry[];
1487
+ /** Device-zone clock time, shared by message rows and inbox rows. */
1488
+ declare function formatMessageTime(date: Date): string;
1489
+ declare function mergeMessages(current: readonly Message[], incoming: readonly Message[]): Message[];
1490
+ /** Readers of a message under the unified rule: a user's read position (createdAt, id) wins when present,
1491
+ * otherwise the acknowledgement time is compared with createdAt (legacy participants, empty-room acknowledgements).
1492
+ * The sender and pending rows never have readers.
1493
+ */
1494
+ declare function readerIdsFor(message: Message, readAtByUserId: ReadonlyMap<string, Date>, readPositionByUserId?: ReadonlyMap<string, ReadPosition>): ReadonlySet<string>;
1495
+ declare function formatFileSize(size: number | undefined): string | null;
1496
+
1377
1497
  interface MessageListViewProps extends ConvoKitAppearanceProps {
1378
1498
  conversation: Conversation$1;
1379
1499
  messages: readonly Message[];
@@ -1397,7 +1517,6 @@ interface MessageListViewProps extends ConvoKitAppearanceProps {
1397
1517
  class?: unknown;
1398
1518
  style?: unknown;
1399
1519
  }
1400
- declare function defaultFormatTime(date: Date): string;
1401
1520
  /** Controlled message history with read receipts, structured media, and older-page loading. */
1402
1521
  declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1403
1522
  conversation: {
@@ -1462,7 +1581,7 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1462
1581
  };
1463
1582
  formatTime: {
1464
1583
  type: PropType<(date: Date) => string>;
1465
- default: typeof defaultFormatTime;
1584
+ default: typeof formatMessageTime;
1466
1585
  };
1467
1586
  imageLoading: {
1468
1587
  type: PropType<"eager" | "lazy">;
@@ -1549,7 +1668,7 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1549
1668
  };
1550
1669
  formatTime: {
1551
1670
  type: PropType<(date: Date) => string>;
1552
- default: typeof defaultFormatTime;
1671
+ default: typeof formatMessageTime;
1553
1672
  };
1554
1673
  imageLoading: {
1555
1674
  type: PropType<"eager" | "lazy">;
@@ -1606,6 +1725,8 @@ interface ConvoKitTheme {
1606
1725
  incomingBubble: string;
1607
1726
  outgoingBubble: string;
1608
1727
  outgoingText: string;
1728
+ /** Unread badge and dot background (0.6.0); the badge label uses `outgoingText`. Defaults to the primary color. */
1729
+ badge: string;
1609
1730
  radius: string;
1610
1731
  avatarSize: string;
1611
1732
  fontFamily: string;
@@ -1646,17 +1767,4 @@ declare const ConvoKitThemeProvider: vue.DefineComponent<vue.ExtractPropTypes<{
1646
1767
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
1647
1768
  declare function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>>;
1648
1769
 
1649
- /** Whether a message is an optimistic row awaiting server acknowledgement. */
1650
- declare function isConvoKitPendingMessage(message: Message): boolean;
1651
- declare function matchesConversation(conversation: Conversation$1, filter: ConversationFilter): boolean;
1652
- declare function applyConversationFilter(conversations: readonly Conversation$1[], filter: ConversationFilter): Conversation$1[];
1653
- declare function mergeConversations(current: readonly Conversation$1[], incoming: readonly Conversation$1[]): Conversation$1[];
1654
- declare function mergeMessages(current: readonly Message[], incoming: readonly Message[]): Message[];
1655
- /** Readers of a message under the unified rule: a user's read position (createdAt, id) wins when present,
1656
- * otherwise the acknowledgement time is compared with createdAt (legacy participants, empty-room acknowledgements).
1657
- * The sender and pending rows never have readers.
1658
- */
1659
- declare function readerIdsFor(message: Message, readAtByUserId: ReadonlyMap<string, Date>, readPositionByUserId?: ReadonlyMap<string, ReadPosition>): ReadonlySet<string>;
1660
- declare function formatFileSize(size: number | undefined): string | null;
1661
-
1662
- 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 };
1770
+ 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, mergeInboxEntries, mergeMessages, readerIdsFor, useConversation, useConversationList, useConvoKitTheme };