@convokitapp/vue-ui 0.8.0 → 0.9.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, EditMessageInput, MarkConversationReadOptions, ConversationPrivateState, ClearConversationUnreadOptions, ClearUnreadResult, 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, ReplyPreview, MessageContextOptions, MessageContextPage, 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
 
@@ -41,6 +41,21 @@ interface ConvoKitUiClient {
41
41
  * `deleteMessage` rejects.
42
42
  */
43
43
  deleteMessage?(messageId: string): Promise<void>;
44
+ /** Resolve the quoted parents of the rendered replies in one round trip (0.9.0). The room store calls this once
45
+ * per page load, reconcile and live-insert burst with the distinct `Message.replyToMessageId` values it cannot
46
+ * derive from the loaded window; the core SDK de-duplicates and chunks at 50 per request. An ID missing from a
47
+ * RESOLVED result is the only deletion signal (the store caches it as the terminal `'unavailable'`); a rejection
48
+ * says nothing about which IDs exist, so the store writes no entry for any of them. Optional: without it the
49
+ * store renders reply references with no quoted text.
50
+ */
51
+ getReplyPreviews?(conversationId: string, messageIds: string[]): Promise<ReplyPreview[]>;
52
+ /** One window of the room's history centred on `options.messageId`, or continued from a previous window's
53
+ * `olderCursor` / `newerCursor` (0.9.0); exactly one of the three, `limit` 1..100. Rows come back newest-first
54
+ * like `getMessages`, and both cursors are always present (null at that end of the history). An unknown or
55
+ * deleted `messageId` must reject with `code: 'MESSAGE_NOT_FOUND'`. Optional: without it the room store hides
56
+ * the jump affordance and `jumpToMessage` resolves false for rows outside the loaded window.
57
+ */
58
+ getMessageContext?(conversationId: string, options: MessageContextOptions): Promise<MessageContextPage>;
44
59
  /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward the
45
60
  * options unchanged (0.7 adds `privateStateVersion`, the version captured when the room opened; an adapter that
46
61
  * drops it acknowledges the position but never clears the caller's unread marker) and reject a missing target
@@ -74,6 +89,13 @@ interface ConvoKitUiClient {
74
89
  onTyping(conversationId: string, handler: (event: TypingEvent) => void, onError?: (error: Error) => void): RealtimeSubscription;
75
90
  }
76
91
 
92
+ /** A quoted parent as the room store holds it (0.9.0): the resolved preview, or the terminal `'unavailable'`
93
+ * once a call that resolved did not return it (deleted, or never in this room). A missing map entry is the
94
+ * distinct third state, "not resolved yet".
95
+ */
96
+ type ReplyPreviewEntry = ReplyPreview | 'unavailable';
97
+ /** Whether the room renders the live tail (`live`) or a historical window a jump loaded (`jumped`, 0.9.0). */
98
+ type ConvoKitWindowMode = 'live' | 'jumped';
77
99
  interface ConversationFilter {
78
100
  query?: string;
79
101
  archived?: boolean;
@@ -128,6 +150,26 @@ interface ConversationState {
128
150
  */
129
151
  canEditMessages: Readonly<Ref<boolean>>;
130
152
  canDeleteMessages: Readonly<Ref<boolean>>;
153
+ /** The message the composer is quoting (0.9.0), or null. Replying and editing are mutually exclusive. */
154
+ replyTarget: Readonly<Ref<Message | null>>;
155
+ /** Quoted parents by `Message.replyToMessageId` (0.9.0); a missing key means "not resolved yet". */
156
+ replyPreviews: Readonly<Ref<ReadonlyMap<string, ReplyPreviewEntry>>>;
157
+ /** The row the last jump landed on (0.9.0); cleared about two seconds later. */
158
+ highlightedMessageId: Readonly<Ref<string | null>>;
159
+ /** Set while a jump replaces the window and scrolls (0.9.0); the views suspend stick-to-bottom, the highlight
160
+ * clear and pagination while it is set.
161
+ */
162
+ jumpInFlight: Readonly<Ref<boolean>>;
163
+ /** `live` (the tail) or `jumped` (a window a jump loaded, 0.9.0). */
164
+ windowMode: Readonly<Ref<ConvoKitWindowMode>>;
165
+ /** Whether a jumped window has newer messages beyond it; always false in `live` mode (0.9.0). */
166
+ hasNewerMessages: Readonly<Ref<boolean>>;
167
+ isLoadingNewer: Readonly<Ref<boolean>>;
168
+ /** Whether the adapter implements `getMessageContext` / `getReplyPreviews` (0.9.0); either turns false for the
169
+ * store's life after the uncoded 404 a 0.8 backend answers, so the affordance disappears instead of failing.
170
+ */
171
+ canJumpToMessage: Readonly<Ref<boolean>>;
172
+ canResolveReplyPreviews: Readonly<Ref<boolean>>;
131
173
  readerIdsFor(message: Message): ReadonlySet<string>;
132
174
  }
133
175
  type ConvoKitUiDensity = 'comfortable' | 'compact';
@@ -170,6 +212,22 @@ interface MessageSlotProps {
170
212
  * `canDelete`.
171
213
  */
172
214
  remove?: () => Promise<boolean>;
215
+ /** Whether the default row would offer the reply action (0.9.0): the view has `onReplyToMessage`, the row is
216
+ * confirmed and the viewer's role (when known) is not `READ` — or `canReplyToMessage` says so. Unlike `canEdit`
217
+ * it does not require the row to be the viewer's own: any member may quote any row.
218
+ */
219
+ canReply: boolean;
220
+ /** Ask the view to quote this message (`onReplyToMessage`); present exactly while `canReply`. */
221
+ reply?: () => void;
222
+ /** The quoted parent of this row (0.9.0); present only while `message.replyToMessageId` is set. `'unavailable'`
223
+ * means the quoted message is gone; the key being absent from `replyPreviewByMessageId` leaves this undefined,
224
+ * which is "not resolved yet" — render the reference without quoted text, never the unavailable copy.
225
+ */
226
+ replyPreview?: ReplyPreviewEntry;
227
+ /** Bring the quoted parent into view (`onJumpToMessage`); present only while `message.replyToMessageId` is set
228
+ * and the view can jump.
229
+ */
230
+ jumpToReplyTarget?: () => void;
173
231
  }
174
232
  interface MediaSlotProps {
175
233
  media: MessageMedia;
@@ -188,6 +246,19 @@ interface ComposerSlotProps {
188
246
  editing?: Message;
189
247
  /** Leave edit mode and restore the unsent draft (0.8.0); present while `editing` is. */
190
248
  cancelEdit?: () => void;
249
+ /** The message being quoted (0.9.0); present while the view is replying and not editing. The field keeps the
250
+ * draft — replying never replaces it, unlike edit mode.
251
+ */
252
+ replying?: Message;
253
+ /** Drop the reply target (0.9.0); present while `replying` is. */
254
+ cancelReply?: () => void;
255
+ }
256
+ /** The payload of the `#jump-to-latest` slot (0.9.0): the control renders only while the view is jumped, so
257
+ * the slot is only ever called with a live return in hand.
258
+ */
259
+ interface JumpToLatestSlotProps {
260
+ /** Drop the historical window and render the live tail again (the view's `onReturnToLatest`). */
261
+ returnToLatest: () => void | Promise<void>;
191
262
  }
192
263
  interface TypingSlotProps {
193
264
  userIds: ReadonlySet<string>;
@@ -272,7 +343,25 @@ interface ConversationController extends ConversationState {
272
343
  * unknown to the server). No optimistic removal. Rejects when the adapter lacks `deleteMessage`.
273
344
  */
274
345
  deleteMessage(messageId: string): Promise<boolean>;
275
- /** Acknowledge through the newest rendered message now; no request is sent while nothing is rendered. */
346
+ /** Quote a rendered, confirmed message in the composer (0.9.0); a no-op for pending, tombstoned and unknown
347
+ * rows and for a `READ` role. Any member may quote any row, own or not. Leaves edit mode. Sends nothing.
348
+ */
349
+ startReply(messageId: string): void;
350
+ /** Drop the reply target without a request; the draft is untouched. */
351
+ cancelReply(): void;
352
+ /** Bring a message into view (0.9.0): a rendered row is only highlighted, otherwise the window is replaced by
353
+ * a context window centred on it (`windowMode` becomes `jumped`). Resolves true once the target is
354
+ * highlighted; false when the quoted message is gone (its preview becomes `'unavailable'`), when a send is in
355
+ * flight, or when the adapter cannot fetch a context window.
356
+ */
357
+ jumpToMessage(messageId: string): Promise<boolean>;
358
+ /** Page a jumped window towards the newest messages; a no-op while `live` or already at the end. */
359
+ loadNewerMessages(): Promise<void>;
360
+ /** Leave a jumped window and render the live tail again; resolves true once it is rendered. */
361
+ returnToLatest(): Promise<boolean>;
362
+ /** Acknowledge through the newest rendered message now; no request is sent while nothing is rendered, and a
363
+ * jumped window acknowledges nothing at all (0.9.0).
364
+ */
276
365
  markRead(): Promise<void>;
277
366
  /** Automatic acknowledgements pause while hidden and resume when the view becomes visible again. */
278
367
  setVisible(visible: boolean): void;
@@ -318,6 +407,35 @@ interface ConversationViewProps extends ConvoKitAppearanceProps {
318
407
  canEditMessage?: (message: Message) => boolean;
319
408
  /** Replaces the inline "Delete this message?" prompt (and confirms `remove()` from custom rows). */
320
409
  confirmDelete?: (message: Message) => boolean | Promise<boolean>;
410
+ /** The message being quoted (0.9.0), or null. The composer shows a cancellable strip and keeps the draft —
411
+ * replying never replaces it, unlike edit mode. Editing wins while both are set.
412
+ */
413
+ replyTarget?: Message | null;
414
+ /** Quote a message (0.9.0): set `replyTarget` in response. Without it rows offer no reply action. */
415
+ onReplyToMessage?: (message: Message) => void;
416
+ /** Drop the reply target (0.9.0): clear `replyTarget` in response. */
417
+ onCancelReply?: () => void;
418
+ /** Replaces the default reply eligibility (any confirmed row while the viewer's role is not `READ`, 0.9.0). */
419
+ canReplyToMessage?: (message: Message) => boolean;
420
+ /** Quoted parents by `Message.replyToMessageId` (0.9.0); a missing key renders the reference with no quoted
421
+ * text, `'unavailable'` the deleted-parent copy.
422
+ */
423
+ replyPreviewByMessageId?: ReadonlyMap<string, ReplyPreviewEntry>;
424
+ /** Bring a message into view (0.9.0). Without it quoted blocks are inert and no row is focusable. */
425
+ onJumpToMessage?: (messageId: string) => void;
426
+ /** The row a jump landed on (0.9.0); it is centred, focused and highlighted. */
427
+ highlightedMessageId?: string | null;
428
+ /** Set while a jump lands (0.9.0): the list is `aria-busy` and suspends stick-to-bottom and pagination. */
429
+ jumpInFlight?: boolean;
430
+ /** Whether newer messages exist past the window (0.9.0); only ever true in a jumped window. */
431
+ hasNewerMessages?: boolean;
432
+ isLoadingNewer?: boolean;
433
+ /** Load the page immediately newer than a jumped window (0.9.0); the newer-edge scroll trigger. */
434
+ onLoadNewer?: () => void | Promise<void>;
435
+ /** Leave a jumped window for the live tail (0.9.0). Present only while the window IS jumped: it is what
436
+ * renders the "Jump to latest" control.
437
+ */
438
+ onReturnToLatest?: () => void | Promise<void>;
321
439
  isInitialLoading?: boolean;
322
440
  isLoadingOlder?: boolean;
323
441
  isSending?: boolean;
@@ -425,6 +543,54 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
425
543
  readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
426
544
  readonly default: undefined;
427
545
  };
546
+ readonly replyTarget: {
547
+ readonly type: PropType<Message | null>;
548
+ readonly default: null;
549
+ };
550
+ readonly onReplyToMessage: {
551
+ readonly type: PropType<(message: Message) => void>;
552
+ readonly default: undefined;
553
+ };
554
+ readonly onCancelReply: {
555
+ readonly type: PropType<() => void>;
556
+ readonly default: undefined;
557
+ };
558
+ readonly canReplyToMessage: {
559
+ readonly type: PropType<(message: Message) => boolean>;
560
+ readonly default: undefined;
561
+ };
562
+ readonly replyPreviewByMessageId: {
563
+ readonly type: PropType<ReadonlyMap<string, ReplyPreviewEntry>>;
564
+ readonly default: undefined;
565
+ };
566
+ readonly onJumpToMessage: {
567
+ readonly type: PropType<(messageId: string) => void>;
568
+ readonly default: undefined;
569
+ };
570
+ readonly highlightedMessageId: {
571
+ readonly type: PropType<string | null>;
572
+ readonly default: null;
573
+ };
574
+ readonly jumpInFlight: {
575
+ readonly type: BooleanConstructor;
576
+ readonly default: false;
577
+ };
578
+ readonly hasNewerMessages: {
579
+ readonly type: BooleanConstructor;
580
+ readonly default: false;
581
+ };
582
+ readonly isLoadingNewer: {
583
+ readonly type: BooleanConstructor;
584
+ readonly default: false;
585
+ };
586
+ readonly onLoadNewer: {
587
+ readonly type: PropType<() => void | Promise<void>>;
588
+ readonly default: undefined;
589
+ };
590
+ readonly onReturnToLatest: {
591
+ readonly type: PropType<() => void | Promise<void>>;
592
+ readonly default: undefined;
593
+ };
428
594
  readonly isInitialLoading: {
429
595
  readonly type: BooleanConstructor;
430
596
  readonly default: false;
@@ -515,7 +681,7 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
515
681
  };
516
682
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
517
683
  [key: string]: any;
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<{
684
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "load-newer" | "attachment-click" | "edit-message" | "delete-message" | "reply-to-message" | "jump-to-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit" | "cancel-reply" | "return-to-latest")[], "load-older" | "load-newer" | "attachment-click" | "edit-message" | "delete-message" | "reply-to-message" | "jump-to-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit" | "cancel-reply" | "return-to-latest", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
519
685
  readonly conversation: {
520
686
  readonly type: PropType<Conversation$1>;
521
687
  readonly required: true;
@@ -600,6 +766,54 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
600
766
  readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
601
767
  readonly default: undefined;
602
768
  };
769
+ readonly replyTarget: {
770
+ readonly type: PropType<Message | null>;
771
+ readonly default: null;
772
+ };
773
+ readonly onReplyToMessage: {
774
+ readonly type: PropType<(message: Message) => void>;
775
+ readonly default: undefined;
776
+ };
777
+ readonly onCancelReply: {
778
+ readonly type: PropType<() => void>;
779
+ readonly default: undefined;
780
+ };
781
+ readonly canReplyToMessage: {
782
+ readonly type: PropType<(message: Message) => boolean>;
783
+ readonly default: undefined;
784
+ };
785
+ readonly replyPreviewByMessageId: {
786
+ readonly type: PropType<ReadonlyMap<string, ReplyPreviewEntry>>;
787
+ readonly default: undefined;
788
+ };
789
+ readonly onJumpToMessage: {
790
+ readonly type: PropType<(messageId: string) => void>;
791
+ readonly default: undefined;
792
+ };
793
+ readonly highlightedMessageId: {
794
+ readonly type: PropType<string | null>;
795
+ readonly default: null;
796
+ };
797
+ readonly jumpInFlight: {
798
+ readonly type: BooleanConstructor;
799
+ readonly default: false;
800
+ };
801
+ readonly hasNewerMessages: {
802
+ readonly type: BooleanConstructor;
803
+ readonly default: false;
804
+ };
805
+ readonly isLoadingNewer: {
806
+ readonly type: BooleanConstructor;
807
+ readonly default: false;
808
+ };
809
+ readonly onLoadNewer: {
810
+ readonly type: PropType<() => void | Promise<void>>;
811
+ readonly default: undefined;
812
+ };
813
+ readonly onReturnToLatest: {
814
+ readonly type: PropType<() => void | Promise<void>>;
815
+ readonly default: undefined;
816
+ };
603
817
  readonly isInitialLoading: {
604
818
  readonly type: BooleanConstructor;
605
819
  readonly default: false;
@@ -690,9 +904,12 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
690
904
  };
691
905
  }>> & Readonly<{
692
906
  "onLoad-older"?: (...args: any[]) => any;
907
+ "onLoad-newer"?: (...args: any[]) => any;
693
908
  "onAttachment-click"?: (...args: any[]) => any;
694
909
  "onEdit-message"?: (...args: any[]) => any;
695
910
  "onDelete-message"?: (...args: any[]) => any;
911
+ "onReply-to-message"?: (...args: any[]) => any;
912
+ "onJump-to-message"?: (...args: any[]) => any;
696
913
  onBack?: (...args: any[]) => any;
697
914
  onRefresh?: (...args: any[]) => any;
698
915
  "onSend-message"?: (...args: any[]) => any;
@@ -701,6 +918,8 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
701
918
  "onUpdate:modelValue"?: (...args: any[]) => any;
702
919
  "onSave-edit"?: (...args: any[]) => any;
703
920
  "onCancel-edit"?: (...args: any[]) => any;
921
+ "onCancel-reply"?: (...args: any[]) => any;
922
+ "onReturn-to-latest"?: (...args: any[]) => any;
704
923
  }>, {
705
924
  readonly typingUserIds: ReadonlySet<string>;
706
925
  readonly readAtByUserId: ReadonlyMap<string, Date>;
@@ -710,6 +929,11 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
710
929
  readonly isSending: boolean;
711
930
  readonly hasOlderMessages: boolean;
712
931
  readonly editingMessage: Message | null;
932
+ readonly replyTarget: Message | null;
933
+ readonly highlightedMessageId: string | null;
934
+ readonly jumpInFlight: boolean;
935
+ readonly hasNewerMessages: boolean;
936
+ readonly isLoadingNewer: boolean;
713
937
  readonly readersResolver: (message: Message) => ReadonlySet<string>;
714
938
  readonly onLoadOlder: () => void | Promise<void>;
715
939
  readonly onAttachmentClick: (media: MessageMedia, message: Message) => void;
@@ -717,6 +941,11 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
717
941
  readonly onDeleteMessage: (message: Message) => boolean | void | Promise<boolean | void>;
718
942
  readonly canEditMessage: (message: Message) => boolean;
719
943
  readonly confirmDelete: (message: Message) => boolean | Promise<boolean>;
944
+ readonly onReplyToMessage: (message: Message) => void;
945
+ readonly canReplyToMessage: (message: Message) => boolean;
946
+ readonly replyPreviewByMessageId: ReadonlyMap<string, ReplyPreviewEntry>;
947
+ readonly onJumpToMessage: (messageId: string) => void;
948
+ readonly onLoadNewer: () => void | Promise<void>;
720
949
  readonly paginationThreshold: number;
721
950
  readonly stickToBottom: boolean;
722
951
  readonly formatTime: (date: Date) => string;
@@ -731,6 +960,8 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
731
960
  readonly onAddAttachment: () => void;
732
961
  readonly onSaveEdit: (message: Message, text: string) => boolean | void | Promise<boolean | void>;
733
962
  readonly onCancelEdit: () => void;
963
+ readonly onCancelReply: () => void;
964
+ readonly onReturnToLatest: () => void | Promise<void>;
734
965
  readonly displayNameForUser: (userId: string) => string | null | undefined;
735
966
  readonly reverseMessages: boolean;
736
967
  readonly composerPlaceholder: string;
@@ -740,7 +971,7 @@ declare const ConversationView: vue.DefineComponent<vue.ExtractPropTypes<{
740
971
  readonly defaultDraft: string;
741
972
  readonly onDraftChange: (value: string) => void;
742
973
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
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'> {
974
+ 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' | 'replyTarget' | 'onReplyToMessage' | 'onCancelReply' | 'replyPreviewByMessageId' | 'onJumpToMessage' | 'highlightedMessageId' | 'jumpInFlight' | 'hasNewerMessages' | 'isLoadingNewer' | 'onLoadNewer' | 'onReturnToLatest'>, Omit<UseConversationOptions, 'client' | 'conversationId'> {
744
975
  client: ConvoKitUiClient;
745
976
  conversationId: string;
746
977
  onControllerChange?: (controller: ConversationController) => void;
@@ -783,6 +1014,22 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
783
1014
  type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
784
1015
  default: undefined;
785
1016
  };
1017
+ replyTarget: {
1018
+ type: PropType<Message | null>;
1019
+ default: undefined;
1020
+ };
1021
+ onReplyToMessage: {
1022
+ type: PropType<(message: Message) => void>;
1023
+ default: undefined;
1024
+ };
1025
+ onCancelReply: {
1026
+ type: PropType<() => void>;
1027
+ default: undefined;
1028
+ };
1029
+ onJumpToMessage: {
1030
+ type: PropType<(messageId: string) => void>;
1031
+ default: undefined;
1032
+ };
786
1033
  client: {
787
1034
  type: PropType<ConvoKitUiClient>;
788
1035
  required: true;
@@ -863,6 +1110,38 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
863
1110
  readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
864
1111
  readonly default: undefined;
865
1112
  };
1113
+ canReplyToMessage: {
1114
+ readonly type: PropType<(message: Message) => boolean>;
1115
+ readonly default: undefined;
1116
+ };
1117
+ replyPreviewByMessageId: {
1118
+ readonly type: PropType<ReadonlyMap<string, ReplyPreviewEntry>>;
1119
+ readonly default: undefined;
1120
+ };
1121
+ highlightedMessageId: {
1122
+ readonly type: PropType<string | null>;
1123
+ readonly default: null;
1124
+ };
1125
+ jumpInFlight: {
1126
+ readonly type: BooleanConstructor;
1127
+ readonly default: false;
1128
+ };
1129
+ hasNewerMessages: {
1130
+ readonly type: BooleanConstructor;
1131
+ readonly default: false;
1132
+ };
1133
+ isLoadingNewer: {
1134
+ readonly type: BooleanConstructor;
1135
+ readonly default: false;
1136
+ };
1137
+ onLoadNewer: {
1138
+ readonly type: PropType<() => void | Promise<void>>;
1139
+ readonly default: undefined;
1140
+ };
1141
+ onReturnToLatest: {
1142
+ readonly type: PropType<() => void | Promise<void>>;
1143
+ readonly default: undefined;
1144
+ };
866
1145
  isInitialLoading: {
867
1146
  readonly type: BooleanConstructor;
868
1147
  readonly default: false;
@@ -953,7 +1232,7 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
953
1232
  };
954
1233
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
955
1234
  [key: string]: any;
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<{
1235
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "load-newer" | "attachment-click" | "edit-message" | "delete-message" | "reply-to-message" | "jump-to-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit" | "cancel-reply" | "return-to-latest" | "controller-change")[], "load-older" | "load-newer" | "attachment-click" | "edit-message" | "delete-message" | "reply-to-message" | "jump-to-message" | "send-message" | "typing-change" | "back" | "refresh" | "add-attachment" | "update:modelValue" | "save-edit" | "cancel-edit" | "cancel-reply" | "return-to-latest" | "controller-change", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
957
1236
  conversation: {
958
1237
  type: PropType<Conversation$1>;
959
1238
  default: undefined;
@@ -990,6 +1269,22 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
990
1269
  type: PropType<(message: Message) => boolean | void | Promise<boolean | void>>;
991
1270
  default: undefined;
992
1271
  };
1272
+ replyTarget: {
1273
+ type: PropType<Message | null>;
1274
+ default: undefined;
1275
+ };
1276
+ onReplyToMessage: {
1277
+ type: PropType<(message: Message) => void>;
1278
+ default: undefined;
1279
+ };
1280
+ onCancelReply: {
1281
+ type: PropType<() => void>;
1282
+ default: undefined;
1283
+ };
1284
+ onJumpToMessage: {
1285
+ type: PropType<(messageId: string) => void>;
1286
+ default: undefined;
1287
+ };
993
1288
  client: {
994
1289
  type: PropType<ConvoKitUiClient>;
995
1290
  required: true;
@@ -1070,6 +1365,38 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
1070
1365
  readonly type: PropType<(message: Message) => boolean | Promise<boolean>>;
1071
1366
  readonly default: undefined;
1072
1367
  };
1368
+ canReplyToMessage: {
1369
+ readonly type: PropType<(message: Message) => boolean>;
1370
+ readonly default: undefined;
1371
+ };
1372
+ replyPreviewByMessageId: {
1373
+ readonly type: PropType<ReadonlyMap<string, ReplyPreviewEntry>>;
1374
+ readonly default: undefined;
1375
+ };
1376
+ highlightedMessageId: {
1377
+ readonly type: PropType<string | null>;
1378
+ readonly default: null;
1379
+ };
1380
+ jumpInFlight: {
1381
+ readonly type: BooleanConstructor;
1382
+ readonly default: false;
1383
+ };
1384
+ hasNewerMessages: {
1385
+ readonly type: BooleanConstructor;
1386
+ readonly default: false;
1387
+ };
1388
+ isLoadingNewer: {
1389
+ readonly type: BooleanConstructor;
1390
+ readonly default: false;
1391
+ };
1392
+ onLoadNewer: {
1393
+ readonly type: PropType<() => void | Promise<void>>;
1394
+ readonly default: undefined;
1395
+ };
1396
+ onReturnToLatest: {
1397
+ readonly type: PropType<() => void | Promise<void>>;
1398
+ readonly default: undefined;
1399
+ };
1073
1400
  isInitialLoading: {
1074
1401
  readonly type: BooleanConstructor;
1075
1402
  readonly default: false;
@@ -1160,9 +1487,12 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
1160
1487
  };
1161
1488
  }>> & Readonly<{
1162
1489
  "onLoad-older"?: (...args: any[]) => any;
1490
+ "onLoad-newer"?: (...args: any[]) => any;
1163
1491
  "onAttachment-click"?: (...args: any[]) => any;
1164
1492
  "onEdit-message"?: (...args: any[]) => any;
1165
1493
  "onDelete-message"?: (...args: any[]) => any;
1494
+ "onReply-to-message"?: (...args: any[]) => any;
1495
+ "onJump-to-message"?: (...args: any[]) => any;
1166
1496
  onBack?: (...args: any[]) => any;
1167
1497
  onRefresh?: (...args: any[]) => any;
1168
1498
  "onSend-message"?: (...args: any[]) => any;
@@ -1171,6 +1501,8 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
1171
1501
  "onUpdate:modelValue"?: (...args: any[]) => any;
1172
1502
  "onSave-edit"?: (...args: any[]) => any;
1173
1503
  "onCancel-edit"?: (...args: any[]) => any;
1504
+ "onCancel-reply"?: (...args: any[]) => any;
1505
+ "onReturn-to-latest"?: (...args: any[]) => any;
1174
1506
  "onController-change"?: (...args: any[]) => any;
1175
1507
  }>, {
1176
1508
  messages: readonly Message[];
@@ -1184,6 +1516,11 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
1184
1516
  hasOlderMessages: boolean;
1185
1517
  currentUserId: string;
1186
1518
  editingMessage: Message | null;
1519
+ replyTarget: Message | null;
1520
+ highlightedMessageId: string | null;
1521
+ jumpInFlight: boolean;
1522
+ hasNewerMessages: boolean;
1523
+ isLoadingNewer: boolean;
1187
1524
  readersResolver: (message: Message) => ReadonlySet<string>;
1188
1525
  onLoadOlder: () => void | Promise<void>;
1189
1526
  onAttachmentClick: (media: MessageMedia, message: Message) => void;
@@ -1191,6 +1528,11 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
1191
1528
  onDeleteMessage: (message: Message) => boolean | void | Promise<boolean | void>;
1192
1529
  canEditMessage: (message: Message) => boolean;
1193
1530
  confirmDelete: (message: Message) => boolean | Promise<boolean>;
1531
+ onReplyToMessage: (message: Message) => void;
1532
+ canReplyToMessage: (message: Message) => boolean;
1533
+ replyPreviewByMessageId: ReadonlyMap<string, ReplyPreviewEntry>;
1534
+ onJumpToMessage: (messageId: string) => void;
1535
+ onLoadNewer: () => void | Promise<void>;
1194
1536
  paginationThreshold: number;
1195
1537
  stickToBottom: boolean;
1196
1538
  formatTime: (date: Date) => string;
@@ -1206,6 +1548,8 @@ declare const Conversation: vue.DefineComponent<vue.ExtractPropTypes<{
1206
1548
  onAddAttachment: () => void;
1207
1549
  onSaveEdit: (message: Message, text: string) => boolean | void | Promise<boolean | void>;
1208
1550
  onCancelEdit: () => void;
1551
+ onCancelReply: () => void;
1552
+ onReturnToLatest: () => void | Promise<void>;
1209
1553
  displayNameForUser: (userId: string) => string | null | undefined;
1210
1554
  reverseMessages: boolean;
1211
1555
  composerPlaceholder: string;
@@ -1730,6 +2074,32 @@ interface MessageListViewProps extends ConvoKitAppearanceProps {
1730
2074
  canEditMessage?: (message: Message) => boolean;
1731
2075
  /** Replaces the row's inline "Delete this message?" prompt (and confirms `remove()` from custom rows). */
1732
2076
  confirmDelete?: (message: Message) => boolean | Promise<boolean>;
2077
+ /** Quote a message (0.9.0). Without it no row offers a reply action and the markup is unchanged. */
2078
+ onReplyToMessage?: (message: Message) => void;
2079
+ /** Replaces the default reply eligibility (any confirmed row while the viewer's role is not `READ`, 0.9.0).
2080
+ * Deliberately separate from `canEditMessage`: an edit-eligibility override must not suppress Reply on rows
2081
+ * the viewer does not own.
2082
+ */
2083
+ canReplyToMessage?: (message: Message) => boolean;
2084
+ /** Quoted parents by `Message.replyToMessageId` (0.9.0). A row whose id is missing from the map renders its
2085
+ * reference with no quoted text ("not resolved yet"); `'unavailable'` renders the deleted-parent copy.
2086
+ */
2087
+ replyPreviewByMessageId?: ReadonlyMap<string, ReplyPreviewEntry>;
2088
+ /** Bring a message into view (0.9.0). Without it quoted blocks are inert and no row is focusable. */
2089
+ onJumpToMessage?: (messageId: string) => void;
2090
+ /** The row a jump landed on (0.9.0): it is scrolled to the centre, focused and highlighted until the host
2091
+ * clears the prop or the viewer scrolls.
2092
+ */
2093
+ highlightedMessageId?: string | null;
2094
+ /** Set by the store while a jump lands (0.9.0): the list is `aria-busy`, stick-to-bottom, pagination and the
2095
+ * highlight clear are suspended, and the attribute is omitted entirely while it is false.
2096
+ */
2097
+ jumpInFlight?: boolean;
2098
+ /** Whether newer messages exist past the top of the window (0.9.0); only ever true in a jumped window. */
2099
+ hasNewerMessages?: boolean;
2100
+ isLoadingNewer?: boolean;
2101
+ /** Load the page of messages immediately newer than the window (0.9.0); the newer-edge scroll trigger. */
2102
+ onLoadNewer?: () => void | Promise<void>;
1733
2103
  scrollElement?: Ref<HTMLElement | null>;
1734
2104
  paginationThreshold?: number;
1735
2105
  reverse?: boolean;
@@ -1801,6 +2171,42 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1801
2171
  type: PropType<(message: Message) => boolean | Promise<boolean>>;
1802
2172
  default: undefined;
1803
2173
  };
2174
+ onReplyToMessage: {
2175
+ type: PropType<(message: Message) => void>;
2176
+ default: undefined;
2177
+ };
2178
+ canReplyToMessage: {
2179
+ type: PropType<(message: Message) => boolean>;
2180
+ default: undefined;
2181
+ };
2182
+ replyPreviewByMessageId: {
2183
+ type: PropType<ReadonlyMap<string, ReplyPreviewEntry>>;
2184
+ default: undefined;
2185
+ };
2186
+ onJumpToMessage: {
2187
+ type: PropType<(messageId: string) => void>;
2188
+ default: undefined;
2189
+ };
2190
+ highlightedMessageId: {
2191
+ type: PropType<string | null>;
2192
+ default: null;
2193
+ };
2194
+ jumpInFlight: {
2195
+ type: BooleanConstructor;
2196
+ default: boolean;
2197
+ };
2198
+ hasNewerMessages: {
2199
+ type: BooleanConstructor;
2200
+ default: boolean;
2201
+ };
2202
+ isLoadingNewer: {
2203
+ type: BooleanConstructor;
2204
+ default: boolean;
2205
+ };
2206
+ onLoadNewer: {
2207
+ type: PropType<() => void | Promise<void>>;
2208
+ default: undefined;
2209
+ };
1804
2210
  scrollElement: {
1805
2211
  type: PropType<Ref<HTMLElement | null>>;
1806
2212
  default: undefined;
@@ -1843,7 +2249,7 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1843
2249
  };
1844
2250
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
1845
2251
  [key: string]: any;
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<{
2252
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("load-older" | "load-newer" | "attachment-click" | "edit-message" | "delete-message" | "reply-to-message" | "jump-to-message")[], "load-older" | "load-newer" | "attachment-click" | "edit-message" | "delete-message" | "reply-to-message" | "jump-to-message", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
1847
2253
  conversation: {
1848
2254
  type: PropType<Conversation$1>;
1849
2255
  required: true;
@@ -1904,6 +2310,42 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1904
2310
  type: PropType<(message: Message) => boolean | Promise<boolean>>;
1905
2311
  default: undefined;
1906
2312
  };
2313
+ onReplyToMessage: {
2314
+ type: PropType<(message: Message) => void>;
2315
+ default: undefined;
2316
+ };
2317
+ canReplyToMessage: {
2318
+ type: PropType<(message: Message) => boolean>;
2319
+ default: undefined;
2320
+ };
2321
+ replyPreviewByMessageId: {
2322
+ type: PropType<ReadonlyMap<string, ReplyPreviewEntry>>;
2323
+ default: undefined;
2324
+ };
2325
+ onJumpToMessage: {
2326
+ type: PropType<(messageId: string) => void>;
2327
+ default: undefined;
2328
+ };
2329
+ highlightedMessageId: {
2330
+ type: PropType<string | null>;
2331
+ default: null;
2332
+ };
2333
+ jumpInFlight: {
2334
+ type: BooleanConstructor;
2335
+ default: boolean;
2336
+ };
2337
+ hasNewerMessages: {
2338
+ type: BooleanConstructor;
2339
+ default: boolean;
2340
+ };
2341
+ isLoadingNewer: {
2342
+ type: BooleanConstructor;
2343
+ default: boolean;
2344
+ };
2345
+ onLoadNewer: {
2346
+ type: PropType<() => void | Promise<void>>;
2347
+ default: undefined;
2348
+ };
1907
2349
  scrollElement: {
1908
2350
  type: PropType<Ref<HTMLElement | null>>;
1909
2351
  default: undefined;
@@ -1946,15 +2388,22 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1946
2388
  };
1947
2389
  }>> & Readonly<{
1948
2390
  "onLoad-older"?: (...args: any[]) => any;
2391
+ "onLoad-newer"?: (...args: any[]) => any;
1949
2392
  "onAttachment-click"?: (...args: any[]) => any;
1950
2393
  "onEdit-message"?: (...args: any[]) => any;
1951
2394
  "onDelete-message"?: (...args: any[]) => any;
2395
+ "onReply-to-message"?: (...args: any[]) => any;
2396
+ "onJump-to-message"?: (...args: any[]) => any;
1952
2397
  }>, {
1953
2398
  reverse: boolean;
1954
2399
  readAtByUserId: ReadonlyMap<string, Date>;
1955
2400
  readPositionByUserId: ReadonlyMap<string, ReadPosition>;
1956
2401
  isLoadingOlder: boolean;
1957
2402
  hasOlderMessages: boolean;
2403
+ highlightedMessageId: string | null;
2404
+ jumpInFlight: boolean;
2405
+ hasNewerMessages: boolean;
2406
+ isLoadingNewer: boolean;
1958
2407
  readersResolver: (message: Message) => ReadonlySet<string>;
1959
2408
  onLoadOlder: () => void | Promise<void>;
1960
2409
  onAttachmentClick: (media: MessageMedia, message: Message) => void;
@@ -1962,6 +2411,11 @@ declare const MessageListView: vue.DefineComponent<vue.ExtractPropTypes<{
1962
2411
  onDeleteMessage: (message: Message) => boolean | void | Promise<boolean | void>;
1963
2412
  canEditMessage: (message: Message) => boolean;
1964
2413
  confirmDelete: (message: Message) => boolean | Promise<boolean>;
2414
+ onReplyToMessage: (message: Message) => void;
2415
+ canReplyToMessage: (message: Message) => boolean;
2416
+ replyPreviewByMessageId: ReadonlyMap<string, ReplyPreviewEntry>;
2417
+ onJumpToMessage: (messageId: string) => void;
2418
+ onLoadNewer: () => void | Promise<void>;
1965
2419
  scrollElement: Ref<HTMLElement | null, HTMLElement | null>;
1966
2420
  paginationThreshold: number;
1967
2421
  stickToBottom: boolean;
@@ -1987,6 +2441,8 @@ interface ConvoKitTheme {
1987
2441
  outgoingText: string;
1988
2442
  /** Unread badge and dot background (0.6.0); the badge label uses `outgoingText`. Defaults to the primary color. */
1989
2443
  badge: string;
2444
+ /** The fading tint on the row a jump landed on (0.9.0). Defaults to the primary color at low opacity. */
2445
+ highlight: string;
1990
2446
  radius: string;
1991
2447
  avatarSize: string;
1992
2448
  fontFamily: string;
@@ -2027,4 +2483,4 @@ declare const ConvoKitThemeProvider: vue.DefineComponent<vue.ExtractPropTypes<{
2027
2483
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
2028
2484
  declare function useConvoKitTheme(): Readonly<Ref<ConvoKitTheme>>;
2029
2485
 
2030
- 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 };
2486
+ 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 ConvoKitWindowMode, type ErrorSlot, type ErrorSlotProps, type JumpToLatestSlotProps, type MediaSlotProps, MessageListView, type MessageListViewProps, type MessageSlotProps, type ReadReceiptSlotProps, type ReplyPreviewEntry, type ScrollOptions, type StateSlot, type TypingSlotProps, type UseConversationListOptions, type UseConversationOptions, applyConversationFilter, createConvoKitUiClient, defaultConvoKitTheme, defaultReadersResolver, formatFileSize, isConvoKitPendingMessage, matchesConversation, mergeConversations, mergeInboxEntries, mergeMessages, readerIdsFor, useConversation, useConversationList, useConvoKitTheme };