@convokitapp/vue-ui 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Conversation as Conversation$1, InboxPage, MessageListOptions, Message, SendMessageInput, MarkConversationReadOptions, RealtimeConnectionHandlers, RealtimeSubscription, MessageEvent, MessageDeletedEvent, ReadEvent, TypingEvent, ReadPosition, InboxSummary, MessageMedia, ConvoKitClient, InboxEntry } from '@convokitapp/sdk';
1
+ import { Conversation as Conversation$1, InboxPage, MessageListOptions, Message, SendMessageInput, EditMessageInput, 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
 
@@ -20,17 +20,42 @@ interface ConvoKitUiClient {
20
20
  cursor: string | null;
21
21
  archived: boolean;
22
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
+ */
23
26
  getConversation(conversationId: string): Promise<Conversation$1>;
24
27
  /** Newest first, with a paired value cursor; never derive an offset from rendered rows. */
25
28
  getMessages(options: MessageListOptions): Promise<Message[]>;
26
29
  /** Complete authorized message, including related media absent from raw row events. */
27
30
  getMessage(id: string): Promise<Message>;
28
31
  sendMessage(input: SendMessageInput): Promise<Message>;
29
- /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward it
30
- * and reject a missing target with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a
31
- * request without a target. Membership failures keep their error code, if any, so they surface as errors.
32
+ /** Replace the text of one of the caller's own messages, or clear the caption of a message with attachments with
33
+ * `text: null` (0.8.0). `revision` is the row's `Message.revision` as the user saw it; a stale value must reject
34
+ * with `code: 'REVISION_CONFLICT'` (status 409) and a deleted or inaccessible message with `code: 'MESSAGE_NOT_FOUND'`
35
+ * (status 404). Attachments are never changed. Optional: without it the room store hides the edit affordance and
36
+ * `saveEdit` rejects.
37
+ */
38
+ editMessage?(messageId: string, input: EditMessageInput): Promise<Message>;
39
+ /** Delete one of the caller's own messages for every member (0.8.0); a message that is already gone must reject
40
+ * with `code: 'MESSAGE_NOT_FOUND'`. Optional: without it the room store hides the delete affordance and
41
+ * `deleteMessage` rejects.
42
+ */
43
+ deleteMessage?(messageId: string): Promise<void>;
44
+ /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward the
45
+ * options unchanged (0.7 adds `privateStateVersion`, the version captured when the room opened; an adapter that
46
+ * drops it acknowledges the position but never clears the caller's unread marker) and reject a missing target
47
+ * with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a request without a target.
48
+ * Membership failures keep their error code, if any, so they surface as errors.
32
49
  */
33
50
  markConversationRead(conversationId: string, options?: MarkConversationReadOptions): Promise<void>;
51
+ /** Mark the room unread for the caller only (0.7.0). Optional: `markUnread` rejects without it. */
52
+ markConversationUnread?(conversationId: string): Promise<ConversationPrivateState>;
53
+ /** Remove the caller's unread marker, only while it still has `options.ifVersion` when given (0.7.0); a mismatch or
54
+ * an unmarked room answers `cleared: false`, never an error. Optional: `clearUnread` rejects without it, and a room
55
+ * opened with a marker that renders nothing leaves the marker in place (the room store clears it through this
56
+ * member, never through an untargeted acknowledgement).
57
+ */
58
+ clearConversationUnread?(conversationId: string, options?: ClearConversationUnreadOptions): Promise<ClearUnreadResult>;
34
59
  sendTyping(input: {
35
60
  conversationId: string;
36
61
  isTyping: boolean;
@@ -38,8 +63,9 @@ interface ConvoKitUiClient {
38
63
  onConnectionEvent(handlers: RealtimeConnectionHandlers): RealtimeSubscription;
39
64
  /** Notify on inbox mutations AND on initial subscription/reconnect. No room data in the signal. */
40
65
  onInboxChanged(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
41
- /** Message inserts/edits and read-position advances in the caller's rooms; never fires on join/rejoin. The list
42
- * store throttles these (`activityRefreshWindowMs`); room stores ignore them.
66
+ /** Message inserts/edits, read-position advances and the caller's own unread-marker changes in the caller's
67
+ * rooms; never fires on join/rejoin. The list store throttles these (`activityRefreshWindowMs`); room stores
68
+ * ignore them.
43
69
  */
44
70
  onInboxActivity?(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
45
71
  onMessage(conversationId: string, handler: (event: MessageEvent) => void, onError?: (error: Error) => void): RealtimeSubscription;
@@ -64,7 +90,9 @@ interface ConversationPageRequest {
64
90
  type ConversationPageLoader = (request: ConversationPageRequest) => Promise<Conversation$1[]>;
65
91
  interface ConversationListState {
66
92
  conversations: Readonly<Ref<Conversation$1[]>>;
67
- /** Per-room preview, unread count and read state by conversation ID; empty on the legacy `getConversations` path. */
93
+ /** Per-room preview, unread count, read state and private unread marker (`isUnread`, `unreadMarkedAt`,
94
+ * `privateStateVersion`, 0.7.0) by conversation ID; empty on the legacy `getConversations` path.
95
+ */
68
96
  summaries: Readonly<Ref<ReadonlyMap<string, InboxSummary>>>;
69
97
  /** The bound session's user; `''` without a session, on the legacy path and after disposal. */
70
98
  currentUserId: Readonly<Ref<string>>;
@@ -91,6 +119,15 @@ interface ConversationState {
91
119
  hasLoaded: Readonly<Ref<boolean>>;
92
120
  error: Readonly<Ref<unknown>>;
93
121
  currentUserId: Readonly<Ref<string>>;
122
+ /** The row being edited as the user saw it when editing started (0.8.0); its `revision` is what `saveEdit`
123
+ * sends. Replaced by the current row on a conflict; null when not editing.
124
+ */
125
+ editingMessage: Readonly<Ref<Message | null>>;
126
+ /** Whether the adapter implements `editMessage` / `deleteMessage` (0.8.0). Without it the default rows render no
127
+ * actions and `startEditing` is a no-op.
128
+ */
129
+ canEditMessages: Readonly<Ref<boolean>>;
130
+ canDeleteMessages: Readonly<Ref<boolean>>;
94
131
  readerIdsFor(message: Message): ReadonlySet<string>;
95
132
  }
96
133
  type ConvoKitUiDensity = 'comfortable' | 'compact';
@@ -106,7 +143,9 @@ interface ConversationItemSlotProps {
106
143
  index: number;
107
144
  selected: boolean;
108
145
  select: () => void;
109
- /** Present when the list carries an inbox summary for this row (0.6.0). */
146
+ /** Present when the list carries an inbox summary for this row (0.6.0); `summary.isUnread` (0.7.0) is the row's
147
+ * unread state including the viewer's private marker.
148
+ */
110
149
  summary?: InboxSummary;
111
150
  /** Present when the list knows the viewer (0.6.0); compare with `summary.latestMessage.senderId`. */
112
151
  currentUserId?: string;
@@ -117,6 +156,20 @@ interface MessageSlotProps {
117
156
  isCurrentUser: boolean;
118
157
  sender: Conversation$1['participants'][number] | undefined;
119
158
  readerIds: ReadonlySet<string>;
159
+ /** `message.revision > 0` (0.8.0): the content changed after the send; never derived from `updatedAt`. */
160
+ isEdited: boolean;
161
+ /** Whether the default row would offer the action (0.8.0): the view has the callback and the row is the viewer's
162
+ * own, confirmed and not read-only (or `canEditMessage` says so).
163
+ */
164
+ canEdit: boolean;
165
+ canDelete: boolean;
166
+ /** Ask the view to start editing this message (`onEditMessage`); present while `canEdit`. */
167
+ edit?: () => void;
168
+ /** Ask the view to delete this message (`onDeleteMessage`) after `confirmDelete` when the view has one, otherwise
169
+ * at once (a custom row owns its own confirmation); resolves to whether the deletion was accepted. Present while
170
+ * `canDelete`.
171
+ */
172
+ remove?: () => Promise<boolean>;
120
173
  }
121
174
  interface MediaSlotProps {
122
175
  media: MessageMedia;
@@ -128,8 +181,13 @@ interface ComposerSlotProps {
128
181
  value: string;
129
182
  setValue: (value: string) => void;
130
183
  isSending: boolean;
184
+ /** Sends the draft, or saves the edit in progress while `editing` is present (0.8.0). */
131
185
  send: () => void;
132
186
  addAttachment?: () => void;
187
+ /** The message being edited (0.8.0); present while the view is in edit mode. The field already holds its text. */
188
+ editing?: Message;
189
+ /** Leave edit mode and restore the unsent draft (0.8.0); present while `editing` is. */
190
+ cancelEdit?: () => void;
133
191
  }
134
192
  interface TypingSlotProps {
135
193
  userIds: ReadonlySet<string>;
@@ -199,6 +257,21 @@ interface ConversationController extends ConversationState {
199
257
  text?: string;
200
258
  media?: MessageMedia[];
201
259
  }): Promise<Message | null>;
260
+ /** Enter edit mode on one of the caller's own confirmed messages (0.8.0); a no-op for other rows, for a `READ`
261
+ * role and for adapters without `editMessage`. Sends nothing (no typing update either).
262
+ */
263
+ startEditing(messageId: string): void;
264
+ /** Leave edit mode without a request. */
265
+ cancelEditing(): void;
266
+ /** Save the edit in progress with the snapshot's revision; resolves true when the server accepted it. A stale
267
+ * revision reloads the row, refreshes `editingMessage` and reports `REVISION_CONFLICT` through `error` (edit mode
268
+ * and draft kept); see the README for the other outcomes. Rejects when the adapter lacks `editMessage`.
269
+ */
270
+ saveEdit(text: string): Promise<boolean>;
271
+ /** Delete one of the caller's own confirmed messages; resolves true once the row is gone (accepted, or already
272
+ * unknown to the server). No optimistic removal. Rejects when the adapter lacks `deleteMessage`.
273
+ */
274
+ deleteMessage(messageId: string): Promise<boolean>;
202
275
  /** Acknowledge through the newest rendered message now; no request is sent while nothing is rendered. */
203
276
  markRead(): Promise<void>;
204
277
  /** Automatic acknowledgements pause while hidden and resume when the view becomes visible again. */
@@ -224,6 +297,27 @@ interface ConversationViewProps extends ConvoKitAppearanceProps {
224
297
  onTypingChange?: (isTyping: boolean) => void | Promise<void>;
225
298
  onAddAttachment?: () => void;
226
299
  onAttachmentClick?: (media: MessageMedia, message: Message) => void;
300
+ /** The message being edited (0.8.0), or null. Entering edit mode stashes the unsent draft and prefills the field
301
+ * with the message text without a typing update; the composer then saves instead of sending.
302
+ */
303
+ editingMessage?: Message | null;
304
+ /** Start editing a message (0.8.0): set `editingMessage` in response. Without it rows offer no edit action. */
305
+ onEditMessage?: (message: Message) => void;
306
+ /** Save the edit in progress (0.8.0); the composer's submit calls it instead of `onSendMessage` while
307
+ * `editingMessage` is set. `false` keeps edit mode and the draft (like `onSendMessage`); any other result
308
+ * restores the stashed unsent draft. Clear `editingMessage` when the edit is done.
309
+ */
310
+ onSaveEdit?: (message: Message, text: string) => boolean | void | Promise<boolean | void>;
311
+ /** Leave edit mode (0.8.0): clear `editingMessage` in response; the view restores the unsent draft. */
312
+ onCancelEdit?: () => void;
313
+ /** Delete a message after confirmation (0.8.0); `false` means it was not accepted. Without it rows offer no
314
+ * delete action.
315
+ */
316
+ onDeleteMessage?: (message: Message) => boolean | void | Promise<boolean | void>;
317
+ /** Replaces the default row eligibility (own confirmed rows while the viewer's role is not `READ`). */
318
+ canEditMessage?: (message: Message) => boolean;
319
+ /** Replaces the inline "Delete this message?" prompt (and confirms `remove()` from custom rows). */
320
+ confirmDelete?: (message: Message) => boolean | Promise<boolean>;
227
321
  isInitialLoading?: boolean;
228
322
  isLoadingOlder?: boolean;
229
323
  isSending?: boolean;
@@ -303,6 +397,34 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
303
397
  readonly type: PropType<(media: MessageMedia, message: Message) => void>;
304
398
  readonly default: undefined;
305
399
  };
400
+ readonly editingMessage: {
401
+ readonly type: PropType<Message | null>;
402
+ readonly default: null;
403
+ };
404
+ readonly onEditMessage: {
405
+ readonly type: PropType<(message: Message) => void>;
406
+ readonly default: undefined;
407
+ };
408
+ readonly onSaveEdit: {
409
+ readonly type: PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>;
410
+ readonly default: undefined;
411
+ };
412
+ readonly onCancelEdit: {
413
+ readonly type: PropType<() => void>;
414
+ readonly default: undefined;
415
+ };
416
+ readonly onDeleteMessage: {
417
+ readonly type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
418
+ readonly default: undefined;
419
+ };
420
+ readonly canEditMessage: {
421
+ readonly type: PropType<(message: Message) => boolean>;
422
+ readonly default: undefined;
423
+ };
424
+ readonly confirmDelete: {
425
+ readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
426
+ readonly default: undefined;
427
+ };
306
428
  readonly isInitialLoading: {
307
429
  readonly type: BooleanConstructor;
308
430
  readonly default: false;
@@ -393,7 +515,7 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
393
515
  };
394
516
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
395
517
  [key: string]: any;
396
- }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "attachment-click" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue")[], "load-older" | "attachment-click" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
518
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "attachment-click" | "edit-message" | "delete-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit")[], "load-older" | "attachment-click" | "edit-message" | "delete-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
397
519
  readonly conversation: {
398
520
  readonly type: PropType<Conversation$1>;
399
521
  readonly required: true;
@@ -450,6 +572,34 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
450
572
  readonly type: PropType<(media: MessageMedia, message: Message) => void>;
451
573
  readonly default: undefined;
452
574
  };
575
+ readonly editingMessage: {
576
+ readonly type: PropType<Message | null>;
577
+ readonly default: null;
578
+ };
579
+ readonly onEditMessage: {
580
+ readonly type: PropType<(message: Message) => void>;
581
+ readonly default: undefined;
582
+ };
583
+ readonly onSaveEdit: {
584
+ readonly type: PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>;
585
+ readonly default: undefined;
586
+ };
587
+ readonly onCancelEdit: {
588
+ readonly type: PropType<() => void>;
589
+ readonly default: undefined;
590
+ };
591
+ readonly onDeleteMessage: {
592
+ readonly type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
593
+ readonly default: undefined;
594
+ };
595
+ readonly canEditMessage: {
596
+ readonly type: PropType<(message: Message) => boolean>;
597
+ readonly default: undefined;
598
+ };
599
+ readonly confirmDelete: {
600
+ readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
601
+ readonly default: undefined;
602
+ };
453
603
  readonly isInitialLoading: {
454
604
  readonly type: BooleanConstructor;
455
605
  readonly default: false;
@@ -541,12 +691,16 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
541
691
  }>> & Readonly<{
542
692
  "onLoad-older"?: (...args: any[]) => any;
543
693
  "onAttachment-click"?: (...args: any[]) => any;
694
+ "onEdit-message"?: (...args: any[]) => any;
695
+ "onDelete-message"?: (...args: any[]) => any;
544
696
  onBack?: (...args: any[]) => any;
545
697
  onRefresh?: (...args: any[]) => any;
546
698
  "onSend-message"?: (...args: any[]) => any;
547
699
  "onTyping-change"?: (...args: any[]) => any;
548
700
  "onAdd-attachment"?: (...args: any[]) => any;
549
701
  "onUpdate:modelValue"?: (...args: any[]) => any;
702
+ "onSave-edit"?: (...args: any[]) => any;
703
+ "onCancel-edit"?: (...args: any[]) => any;
550
704
  }>, {
551
705
  readonly typingUserIds: ReadonlySet<string>;
552
706
  readonly readAtByUserId: ReadonlyMap<string, Date>;
@@ -555,9 +709,14 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
555
709
  readonly isLoadingOlder: boolean;
556
710
  readonly isSending: boolean;
557
711
  readonly hasOlderMessages: boolean;
712
+ readonly editingMessage: Message | null;
558
713
  readonly readersResolver: (message: Message) => ReadonlySet<string>;
559
714
  readonly onLoadOlder: () => void | Promise<void>;
560
715
  readonly onAttachmentClick: (media: MessageMedia, message: Message) => void;
716
+ readonly onEditMessage: (message: Message) => void;
717
+ readonly onDeleteMessage: (message: Message) => boolean | void | Promise<boolean | void>;
718
+ readonly canEditMessage: (message: Message) => boolean;
719
+ readonly confirmDelete: (message: Message) => boolean | Promise<boolean>;
561
720
  readonly paginationThreshold: number;
562
721
  readonly stickToBottom: boolean;
563
722
  readonly formatTime: (date: Date) => string;
@@ -570,6 +729,8 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
570
729
  readonly onRefresh: () => void | Promise<void>;
571
730
  readonly onTypingChange: (isTyping: boolean) => void | Promise<void>;
572
731
  readonly onAddAttachment: () => void;
732
+ readonly onSaveEdit: (message: Message, text: string) => boolean | void | Promise<boolean | void>;
733
+ readonly onCancelEdit: () => void;
573
734
  readonly displayNameForUser: (userId: string) => string | null | undefined;
574
735
  readonly reverseMessages: boolean;
575
736
  readonly composerPlaceholder: string;
@@ -579,7 +740,7 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
579
740
  readonly defaultDraft: string;
580
741
  readonly onDraftChange: (value: string) => void;
581
742
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
582
- interface ConversationProps extends Omit<ConversationViewProps, 'conversation' | 'messages' | 'currentUserId' | 'onSendMessage' | 'typingUserIds' | 'readAtByUserId' | 'readPositionByUserId' | 'onRefresh' | 'onLoadOlder' | 'onTypingChange' | 'isInitialLoading' | 'isLoadingOlder' | 'isSending' | 'hasOlderMessages' | 'error'>, Omit<UseConversationOptions, 'client' | 'conversationId'> {
743
+ interface ConversationProps extends Omit<ConversationViewProps, 'conversation' | 'messages' | 'currentUserId' | 'onSendMessage' | 'typingUserIds' | 'readAtByUserId' | 'readPositionByUserId' | 'onRefresh' | 'onLoadOlder' | 'onTypingChange' | 'isInitialLoading' | 'isLoadingOlder' | 'isSending' | 'hasOlderMessages' | 'error' | 'editingMessage' | 'onEditMessage' | 'onSaveEdit' | 'onCancelEdit' | 'onDeleteMessage'>, Omit<UseConversationOptions, 'client' | 'conversationId'> {
583
744
  client: ConvoKitUiClient;
584
745
  conversationId: string;
585
746
  onControllerChange?: (controller: ConversationController) => void;
@@ -602,6 +763,26 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
602
763
  type: PropType<(text: string) => boolean | void | Promise<boolean | void>>;
603
764
  default: undefined;
604
765
  };
766
+ editingMessage: {
767
+ type: PropType<Message | null>;
768
+ default: undefined;
769
+ };
770
+ onEditMessage: {
771
+ type: PropType<(message: Message) => void>;
772
+ default: undefined;
773
+ };
774
+ onSaveEdit: {
775
+ type: PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>;
776
+ default: undefined;
777
+ };
778
+ onCancelEdit: {
779
+ type: PropType<() => void>;
780
+ default: undefined;
781
+ };
782
+ onDeleteMessage: {
783
+ type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
784
+ default: undefined;
785
+ };
605
786
  client: {
606
787
  type: PropType<ConvoKitUiClient>;
607
788
  required: true;
@@ -674,6 +855,14 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
674
855
  readonly type: PropType<(media: MessageMedia, message: Message) => void>;
675
856
  readonly default: undefined;
676
857
  };
858
+ canEditMessage: {
859
+ readonly type: PropType<(message: Message) => boolean>;
860
+ readonly default: undefined;
861
+ };
862
+ confirmDelete: {
863
+ readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
864
+ readonly default: undefined;
865
+ };
677
866
  isInitialLoading: {
678
867
  readonly type: BooleanConstructor;
679
868
  readonly default: false;
@@ -764,7 +953,7 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
764
953
  };
765
954
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
766
955
  [key: string]: any;
767
- }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "attachment-click" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "controller-change")[], "load-older" | "attachment-click" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "controller-change", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
956
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "attachment-click" | "edit-message" | "delete-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit" | "controller-change")[], "load-older" | "attachment-click" | "edit-message" | "delete-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit" | "controller-change", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
768
957
  conversation: {
769
958
  type: PropType<Conversation$1>;
770
959
  default: undefined;
@@ -781,6 +970,26 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
781
970
  type: PropType<(text: string) => boolean | void | Promise<boolean | void>>;
782
971
  default: undefined;
783
972
  };
973
+ editingMessage: {
974
+ type: PropType<Message | null>;
975
+ default: undefined;
976
+ };
977
+ onEditMessage: {
978
+ type: PropType<(message: Message) => void>;
979
+ default: undefined;
980
+ };
981
+ onSaveEdit: {
982
+ type: PropType<(message: Message, text: string) => boolean | void | Promise<boolean | void>>;
983
+ default: undefined;
984
+ };
985
+ onCancelEdit: {
986
+ type: PropType<() => void>;
987
+ default: undefined;
988
+ };
989
+ onDeleteMessage: {
990
+ type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
991
+ default: undefined;
992
+ };
784
993
  client: {
785
994
  type: PropType<ConvoKitUiClient>;
786
995
  required: true;
@@ -853,6 +1062,14 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
853
1062
  readonly type: PropType<(media: MessageMedia, message: Message) => void>;
854
1063
  readonly default: undefined;
855
1064
  };
1065
+ canEditMessage: {
1066
+ readonly type: PropType<(message: Message) => boolean>;
1067
+ readonly default: undefined;
1068
+ };
1069
+ confirmDelete: {
1070
+ readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
1071
+ readonly default: undefined;
1072
+ };
856
1073
  isInitialLoading: {
857
1074
  readonly type: BooleanConstructor;
858
1075
  readonly default: false;
@@ -944,12 +1161,16 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
944
1161
  }>> & Readonly<{
945
1162
  "onLoad-older"?: (...args: any[]) => any;
946
1163
  "onAttachment-click"?: (...args: any[]) => any;
1164
+ "onEdit-message"?: (...args: any[]) => any;
1165
+ "onDelete-message"?: (...args: any[]) => any;
947
1166
  onBack?: (...args: any[]) => any;
948
1167
  onRefresh?: (...args: any[]) => any;
949
1168
  "onSend-message"?: (...args: any[]) => any;
950
1169
  "onTyping-change"?: (...args: any[]) => any;
951
1170
  "onAdd-attachment"?: (...args: any[]) => any;
952
1171
  "onUpdate:modelValue"?: (...args: any[]) => any;
1172
+ "onSave-edit"?: (...args: any[]) => any;
1173
+ "onCancel-edit"?: (...args: any[]) => any;
953
1174
  "onController-change"?: (...args: any[]) => any;
954
1175
  }>, {
955
1176
  messages: readonly Message[];
@@ -962,9 +1183,14 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
962
1183
  isSending: boolean;
963
1184
  hasOlderMessages: boolean;
964
1185
  currentUserId: string;
1186
+ editingMessage: Message | null;
965
1187
  readersResolver: (message: Message) => ReadonlySet<string>;
966
1188
  onLoadOlder: () => void | Promise<void>;
967
1189
  onAttachmentClick: (media: MessageMedia, message: Message) => void;
1190
+ onEditMessage: (message: Message) => void;
1191
+ onDeleteMessage: (message: Message) => boolean | void | Promise<boolean | void>;
1192
+ canEditMessage: (message: Message) => boolean;
1193
+ confirmDelete: (message: Message) => boolean | Promise<boolean>;
968
1194
  paginationThreshold: number;
969
1195
  stickToBottom: boolean;
970
1196
  formatTime: (date: Date) => string;
@@ -978,6 +1204,8 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
978
1204
  onRefresh: () => void | Promise<void>;
979
1205
  onTypingChange: (isTyping: boolean) => void | Promise<void>;
980
1206
  onAddAttachment: () => void;
1207
+ onSaveEdit: (message: Message, text: string) => boolean | void | Promise<boolean | void>;
1208
+ onCancelEdit: () => void;
981
1209
  displayNameForUser: (userId: string) => string | null | undefined;
982
1210
  reverseMessages: boolean;
983
1211
  composerPlaceholder: string;
@@ -1009,13 +1237,23 @@ interface ConversationListController extends ConversationListState {
1009
1237
  loadMore(): Promise<void>;
1010
1238
  setFilter(filter: ConversationFilter): Promise<void>;
1011
1239
  setQuery(query: string): Promise<void>;
1240
+ /** Mark a room unread for the viewer only (0.7.0); its summary shows the marker at once. Rejects when the adapter
1241
+ * lacks `markConversationUnread`.
1242
+ */
1243
+ markUnread(conversationId: string): Promise<void>;
1244
+ /** Remove the viewer's marker, only while it still has `options.ifVersion` when given; resolves to whether this
1245
+ * request removed it. Rejects when the adapter lacks `clearConversationUnread`.
1246
+ */
1247
+ clearUnread(conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean>;
1012
1248
  dispose(): Promise<void>;
1013
1249
  }
1014
1250
  declare function useConversationList(options: UseConversationListOptions): ConversationListController;
1015
1251
 
1016
1252
  interface ConversationListViewProps extends ConvoKitAppearanceProps {
1017
1253
  conversations: readonly Conversation$1[];
1018
- /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge. */
1254
+ /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge: the count, or
1255
+ * a numberless dot when `isUnread` is set without one (0.7.0).
1256
+ */
1019
1257
  summaries?: ReadonlyMap<string, InboxSummary>;
1020
1258
  /** The viewer; a preview from them reads `You: …`. Absent → no prefix. */
1021
1259
  currentUserId?: string;
@@ -1480,6 +1718,18 @@ interface MessageListViewProps extends ConvoKitAppearanceProps {
1480
1718
  isLoadingOlder?: boolean;
1481
1719
  error?: unknown;
1482
1720
  onAttachmentClick?: (media: MessageMedia, message: Message) => void;
1721
+ /** Start editing a message (0.8.0). Without it no row offers an edit action and the markup is unchanged. */
1722
+ onEditMessage?: (message: Message) => void;
1723
+ /** Delete a message after confirmation (0.8.0); `false` means the deletion was not accepted. Without it no row
1724
+ * offers a delete action.
1725
+ */
1726
+ onDeleteMessage?: (message: Message) => boolean | void | Promise<boolean | void>;
1727
+ /** Replaces the default eligibility (the viewer's own confirmed rows while the viewer's role is not `READ`) for
1728
+ * both actions; pending rows are never eligible.
1729
+ */
1730
+ canEditMessage?: (message: Message) => boolean;
1731
+ /** Replaces the row's inline "Delete this message?" prompt (and confirms `remove()` from custom rows). */
1732
+ confirmDelete?: (message: Message) => boolean | Promise<boolean>;
1483
1733
  scrollElement?: Ref<HTMLElement | null>;
1484
1734
  paginationThreshold?: number;
1485
1735
  reverse?: boolean;
@@ -1535,6 +1785,22 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1535
1785
  type: PropType<(media: MessageMedia, message: Message) => void>;
1536
1786
  default: undefined;
1537
1787
  };
1788
+ onEditMessage: {
1789
+ type: PropType<(message: Message) => void>;
1790
+ default: undefined;
1791
+ };
1792
+ onDeleteMessage: {
1793
+ type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
1794
+ default: undefined;
1795
+ };
1796
+ canEditMessage: {
1797
+ type: PropType<(message: Message) => boolean>;
1798
+ default: undefined;
1799
+ };
1800
+ confirmDelete: {
1801
+ type: PropType<(message: Message) => boolean | Promise<boolean>>;
1802
+ default: undefined;
1803
+ };
1538
1804
  scrollElement: {
1539
1805
  type: PropType<Ref<HTMLElement | null>>;
1540
1806
  default: undefined;
@@ -1577,7 +1843,7 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1577
1843
  };
1578
1844
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
1579
1845
  [key: string]: any;
1580
- }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "attachment-click")[], "load-older" | "attachment-click", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
1846
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "attachment-click" | "edit-message" | "delete-message")[], "load-older" | "attachment-click" | "edit-message" | "delete-message", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
1581
1847
  conversation: {
1582
1848
  type: PropType<Conversation$1>;
1583
1849
  required: true;
@@ -1622,6 +1888,22 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1622
1888
  type: PropType<(media: MessageMedia, message: Message) => void>;
1623
1889
  default: undefined;
1624
1890
  };
1891
+ onEditMessage: {
1892
+ type: PropType<(message: Message) => void>;
1893
+ default: undefined;
1894
+ };
1895
+ onDeleteMessage: {
1896
+ type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
1897
+ default: undefined;
1898
+ };
1899
+ canEditMessage: {
1900
+ type: PropType<(message: Message) => boolean>;
1901
+ default: undefined;
1902
+ };
1903
+ confirmDelete: {
1904
+ type: PropType<(message: Message) => boolean | Promise<boolean>>;
1905
+ default: undefined;
1906
+ };
1625
1907
  scrollElement: {
1626
1908
  type: PropType<Ref<HTMLElement | null>>;
1627
1909
  default: undefined;
@@ -1665,6 +1947,8 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1665
1947
  }>> & Readonly<{
1666
1948
  "onLoad-older"?: (...args: any[]) => any;
1667
1949
  "onAttachment-click"?: (...args: any[]) => any;
1950
+ "onEdit-message"?: (...args: any[]) => any;
1951
+ "onDelete-message"?: (...args: any[]) => any;
1668
1952
  }>, {
1669
1953
  reverse: boolean;
1670
1954
  readAtByUserId: ReadonlyMap<string, Date>;
@@ -1674,6 +1958,10 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1674
1958
  readersResolver: (message: Message) => ReadonlySet<string>;
1675
1959
  onLoadOlder: () => void | Promise<void>;
1676
1960
  onAttachmentClick: (media: MessageMedia, message: Message) => void;
1961
+ onEditMessage: (message: Message) => void;
1962
+ onDeleteMessage: (message: Message) => boolean | void | Promise<boolean | void>;
1963
+ canEditMessage: (message: Message) => boolean;
1964
+ confirmDelete: (message: Message) => boolean | Promise<boolean>;
1677
1965
  scrollElement: Ref<HTMLElement | null, HTMLElement | null>;
1678
1966
  paginationThreshold: number;
1679
1967
  stickToBottom: boolean;
@@ -1697,7 +1985,7 @@ interface ConvoKitTheme {
1697
1985
  incomingBubble: string;
1698
1986
  outgoingBubble: string;
1699
1987
  outgoingText: string;
1700
- /** Unread badge background (0.6.0); its label uses `outgoingText`. Defaults to the primary color. */
1988
+ /** Unread badge and dot background (0.6.0); the badge label uses `outgoingText`. Defaults to the primary color. */
1701
1989
  badge: string;
1702
1990
  radius: string;
1703
1991
  avatarSize: string;