@talkjs/core 1.0.1 → 1.1.1

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.
@@ -114,11 +114,11 @@ export declare interface AudioFileMetadata {
114
114
  *
115
115
  * This means that the following AutoLink is valid:
116
116
  *
117
- * ```
117
+ * ```json
118
118
  * {
119
119
  * type: "autoLink",
120
120
  * text: "talkjs.com"
121
- * url: "https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#AutoLinkNode"
121
+ * url: "https://talkjs.com/docs/Reference/JavaScript_Data_API/Message_Content/#AutoLinkNode"
122
122
  * }
123
123
  * ```
124
124
  *
@@ -218,8 +218,8 @@ export declare interface ConversationActiveState {
218
218
  * References the conversation with a given conversation ID, from the perspective of the current user.
219
219
  *
220
220
  * @remarks
221
- * Used in all Realtime API operations affecting that conversation, such as fetching or updating conversation attributes.
222
- * Created via {@link Session.conversation}.
221
+ * Used in all Data API operations affecting that conversation, such as fetching or updating conversation attributes.
222
+ * Created via {@link Session.conversation|Session.conversation()}.
223
223
  *
224
224
  * @public
225
225
  */
@@ -234,13 +234,41 @@ export declare interface ConversationRef {
234
234
  /**
235
235
  * Get a reference to a participant in this conversation
236
236
  *
237
- * @param user - the user's ID or a reference to the user
237
+ * @remarks
238
+ * Note that `Participant` is not the same as `User`.
239
+ * A `Participant` represents a user's settings related to a specific conversation.
240
+ *
241
+ * Calling {@link ConversationRef.createIfNotExists|ConversationRef.createIfNotExists} or {@link ConversationRef.set|ConversationRef.set} will automatically add the current user as a participant.
242
+ *
243
+ * @example To add "Alice" to the conversation "Cats"
244
+ * ```ts
245
+ * session.conversation("Cats").participant("Alice").createIfNotExists();
246
+ * ```
247
+ *
248
+ * The user "Alice" must exist before you do this.
249
+ *
250
+ * @example To remove "Alice" from the conversation "Cats"
251
+ * ```ts
252
+ * session.conversation("Cats").participant("Alice").delete();
253
+ * ```
254
+ *
255
+ * The user "Alice" will still exist after you do this. This deletes the participant, not the user.
256
+ *
257
+ * @param user - Specifies which participant in the conversation you want to reference. Either the user's ID, or a reference to that user.
258
+ * @returns A {@linkcode ParticipantRef} for that user's participation in this conversation
259
+ * @public
238
260
  */
239
261
  participant(user: string | UserRef): ParticipantRef;
240
262
  /**
241
263
  * Get a reference to a message in this conversation
242
264
  *
243
- * @param user - the message ID
265
+ * @remarks
266
+ * Use this if you need to fetch, delete, or edit a specific message in this conversation, and you know its message ID.
267
+ * To fetch the most recent messages in this conversation, use {@link ConversationRef.subscribeMessages} instead.
268
+ *
269
+ * @param id - The ID of the user that you want to reference
270
+ * @returns A {@linkcode UserRef} for the user with that ID
271
+ * @public
244
272
  */
245
273
  message(id: string): MessageRef;
246
274
  /**
@@ -260,7 +288,7 @@ export declare interface ConversationRef {
260
288
  * You are added as a participant if you are not already a participant in the conversation.
261
289
  *
262
290
  * @returns A promise that resolves when the operation completes.
263
- * When client-side conversation syncing is disabled, you may only set your `notify` property, when you are already a participant.
291
+ * When client-side conversation syncing is disabled, you must already be a participant and you cannot set anything except the `notify` property.
264
292
  * Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.
265
293
  */
266
294
  set(params: SetConversationParams): Promise<void>;
@@ -289,6 +317,54 @@ export declare interface ConversationRef {
289
317
  /**
290
318
  * Sends a message in the conversation
291
319
  *
320
+ * @example Send a simple message with markup (bold in this example)
321
+ * ```ts
322
+ * conversationRef.send("*Hello*");
323
+ * ```
324
+ *
325
+ * @example Reply to a message and set custom message data
326
+ * ```ts
327
+ * conversationRef.send({
328
+ * text: "Agreed",
329
+ * referencedMessageId: "...",
330
+ * custom: { priority: "HIGH" }
331
+ * });
332
+ * ```
333
+ *
334
+ * @example Send pre-formatted text with {@link TextBlock}
335
+ * ```ts
336
+ * conversationRef.send({
337
+ * content: [{
338
+ * type: "text",
339
+ * children: [{
340
+ * type: "bold",
341
+ * children: ["Hello"]
342
+ * }]
343
+ * }]
344
+ * });
345
+ * ```
346
+ *
347
+ * @example Send a file with {@link SendFileBlock}
348
+ * ```ts
349
+ * // `file` is a File object from `<input type="file">`
350
+ * const fileToken = await session.uploadImage(
351
+ * file, { filename: file.name, width: 640, height: 480 }
352
+ * );
353
+ *
354
+ * conversationRef.send({
355
+ * content: [{ type: "file", fileToken }]
356
+ * });
357
+ * ```
358
+ *
359
+ * @example Send a location with {@link LocationBlock}
360
+ * ```ts
361
+ * // You can get the user's location with the browser's geolocation API
362
+ * const [latitude, longitude] = [42.43, -83.99];
363
+ * conversationRef.send({
364
+ * content: [{ type: "location", latitude, longitude }]
365
+ * });
366
+ * ```
367
+ *
292
368
  * @returns A promise that resolves with a reference to the newly created message. The promise will reject if you do not have permission to send the message.
293
369
  */
294
370
  send(params: string | SendTextMessageParams | SendMessageParams): Promise<MessageRef>;
@@ -310,11 +386,64 @@ export declare interface ConversationRef {
310
386
  *
311
387
  * @remarks
312
388
  * Whenever `Subscription.state.type` is "active" and something about the conversation changes, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
313
- * This includes changes to nested data. As an extreme example, `onSnapshot` would be called if `snapshot.lastMessage.referencedMessage.sender.name` changes.
389
+ * This includes changes to nested data. As an extreme example, `onSnapshot` would be called when `snapshot.lastMessage.referencedMessage.sender.name` changes.
314
390
  *
315
391
  * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
316
392
  */
317
393
  subscribe(onSnapshot?: (snapshot: ConversationSnapshot | null) => void): ConversationSubscription;
394
+ /**
395
+ * Subscribes to the typing status of the conversation.
396
+ *
397
+ * @remarks
398
+ * Whenever `Subscription.state.type` is "active" and the typing status changes, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
399
+ * This includes changes to nested data, such as when a user who is typing changes their name.
400
+ *
401
+ * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
402
+ *
403
+ * Note that if there are "many" people typing and another person starts to type, `onSnapshot` will not be called.
404
+ * This is because your existing {@link ManyTypingSnapshot} is still valid and did not change when the new person started to type.
405
+ */
406
+ subscribeTyping(onSnapshot?: (snapshot: TypingSnapshot | null) => void): TypingSubscription;
407
+ /**
408
+ * Marks the current user as typing in this conversation for 10 seconds.
409
+ *
410
+ * @remarks
411
+ * This means that other users will see a typing indicator in the UI, from the current user.
412
+ *
413
+ * The user will automatically stop typing after 10 seconds. You cannot manually mark a user as "not typing".
414
+ * Users are also considered "not typing" when they send a message, even if that message was sent from a different tab or using the REST API.
415
+ *
416
+ * To keep the typing indicator visible for longer, call this function again to reset the 10s timer.
417
+ *
418
+ * @example Example implementation
419
+ * ```ts
420
+ * let lastMarkedAsTyping = 0;
421
+ *
422
+ * inputElement.addEventListener("change", event => {
423
+ * const text = event.target.value;
424
+ *
425
+ * // Deleting your draft never counts as typing
426
+ * if (text.length === 0) {
427
+ * return;
428
+ * }
429
+ *
430
+ * const now = Date.now();
431
+ *
432
+ * // Don't mark as typing more than once every 5s
433
+ * if (now - lastMarkedAsTyping > 5000) {
434
+ * lastMarkedAsTyping = now;
435
+ * convRef.markAsTyping();
436
+ * }
437
+ * });
438
+ *
439
+ * // When you send a message, you are no longer considered typing
440
+ * // So we need to send markAsTyping as soon as you type something
441
+ * function onSendMessage() {
442
+ * lastMarkedAsTyping = 0;
443
+ * }
444
+ * ```
445
+ */
446
+ markAsTyping(): Promise<void>;
318
447
  }
319
448
 
320
449
  /**
@@ -333,11 +462,11 @@ export declare interface ConversationSnapshot {
333
462
  */
334
463
  id: string;
335
464
  /**
336
- * Contains the conversation subject if it was set using {@link ConversationBuilder.subject}.
465
+ * Contains the conversation subject, or `null` if the conversation does not have a subject specified.
337
466
  */
338
467
  subject: string | null;
339
468
  /**
340
- * Contains the URL of a photo was set using {@link ConversationBuilder.subject}.
469
+ * Contains the URL of a photo to represent the topic of the conversation or `null` if the conversation does not have a photo specified.
341
470
  */
342
471
  photoUrl: string | null;
343
472
  /**
@@ -365,9 +494,25 @@ export declare interface ConversationSnapshot {
365
494
  */
366
495
  unreadMessageCount: number;
367
496
  /**
368
- * Timestamp of when the current user read a message
497
+ * The most recent date that the current user read the conversation.
498
+ *
499
+ * @remarks
500
+ * This value is updated whenever you read a message in a chat UI, open an email notification, or mark the conversation as read using an API like {@link ConversationRef.markAsRead}.
501
+ *
502
+ * Any messages sent after this timestamp are unread messages.
369
503
  */
370
504
  readUntil: number;
505
+ /**
506
+ * Everyone in the conversation has read any messages sent on or before this date.
507
+ *
508
+ * @remarks
509
+ * This is the minimum of all the participants' `readUntil` values.
510
+ * Any messages sent on or before this timestamp should show a "read" indicator in the UI.
511
+ *
512
+ * This value will rarely change in very large conversations.
513
+ * If just one person stops checking their messages, `everyoneReadUntil` will never update.
514
+ */
515
+ everyoneReadUntil: number;
371
516
  /**
372
517
  * Whether the conversation should be considered unread.
373
518
  *
@@ -643,6 +788,27 @@ export declare interface ErrorState {
643
788
  error: Error;
644
789
  }
645
790
 
791
+ /**
792
+ * The {@link TypingSnapshot} variant used when only a few people are typing.
793
+ */
794
+ export declare interface FewTypingSnapshot {
795
+ /**
796
+ * Check this to differentiate between FewTypingSnapshot (`false`) and ManyTypingSnapshot (`true`).
797
+ *
798
+ * @remarks
799
+ * When `false`, you can see the list of users who are typing in the `users` property.
800
+ */
801
+ many: false;
802
+ /**
803
+ * The users who are currently typing in this conversation.
804
+ *
805
+ * @remarks
806
+ * The list is in chronological order, starting with the users who have been typing the longest.
807
+ * The current user is never contained in the list, only other users.
808
+ */
809
+ users: UserSnapshot[];
810
+ }
811
+
646
812
  /**
647
813
  * A file attachment received in a message's content.
648
814
  *
@@ -671,35 +837,34 @@ export declare type FileBlock = VideoBlock | ImageBlock | AudioBlock | VoiceBloc
671
837
  *
672
838
  * @remarks
673
839
  * You cannot create a FileToken yourself. Get a file token by uploading your file to TalkJS with {@link Session.uploadFile}, or one of the subtype-specific variants like {@link Session.uploadImage}.
840
+ * Alternatively, take a file token from an existing {@link FileBlock} to re-send an attachment you received, without having to download and re-upload the file.
841
+ * You can also upload files using the {@link https://talkjs.com/docs/Reference/REST_API/Messages/#1-upload-a-file| REST API}.
842
+ * This system ensures that all files must be uploaded to TalkJS before being sent to users, limiting the risk of malware.
674
843
  *
675
- * For example:
844
+ * Passed in {@link SendFileBlock} when you send a message containing a file attachment.
676
845
  *
677
- * ```
846
+ * We may change the FileToken format in the future.
847
+ * Do not store old file tokens for future use, as these may stop working.
848
+ *
849
+ * @example Using a file input
850
+ * ```ts
678
851
  * // From `<input type="file">`
679
852
  * const file: File = fileInputElement.files[0];
680
853
  * const myFileToken = await session.uploadFile(file, { filename: file.name });
681
- * ```
682
- *
683
- * Alternatively, take a file token from an existing {@link FileBlock} to re-send an attachment you received, without having to download and re-upload the file.
684
854
  *
685
- * You can also upload files using the {@link https://talkjs.com/docs/Reference/REST_API/Messages/#1-upload-a-file| REST API}.
686
- *
687
- * Passed in {@link SendFileBlock} when you send a message containing a file attachment:
688
- *
689
- * ```
690
- * const block: SendFileBlock = {
855
+ * const block = {
691
856
  * type: 'file',
692
857
  * fileToken: myFileToken,
693
858
  * };
694
- *
695
- * const convRef = session.conversation('example_conversation_id');
696
- * convRef.send({ content: [block] });
859
+ * session.conversation('example_conversation_id').send({ content: [block] });
697
860
  * ```
698
861
  *
699
- * We may change the FileToken format in the future.
700
- * Do not store old file tokens for future use, as these may stop working.
701
- *
702
- * This system ensures that all files must be uploaded to TalkJS before being sent to users, limiting the risk of malware.
862
+ * @example Re-sending a file from a previous message
863
+ * ```ts
864
+ * session.conversation('example_conversation_id').send({
865
+ * content: previousMessageSnapshot.content
866
+ * });
867
+ * ```
703
868
  *
704
869
  * @public
705
870
  */
@@ -715,7 +880,7 @@ export declare type FileToken = string & {
715
880
  *
716
881
  * Instead, treat GenericFileBlock as the default. For example:
717
882
  *
718
- * ```
883
+ * ```ts
719
884
  * if (block.subtype === "video") {
720
885
  * handleVideoBlock(block);
721
886
  * } else if (block.subtype === "image") {
@@ -763,7 +928,7 @@ export declare interface GenericFileMetadata {
763
928
  }
764
929
 
765
930
  /**
766
- * Returns a TalkSession option for the specified App ID and User ID.
931
+ * Returns a TalkSession for the specified App ID and User ID.
767
932
  *
768
933
  * @remarks
769
934
  * Backed by a registry, so calling this function twice with the same app and user returns the same session object both times.
@@ -879,6 +1044,20 @@ export declare interface LocationBlock {
879
1044
  longitude: number;
880
1045
  }
881
1046
 
1047
+ /**
1048
+ * The {@link TypingSnapshot} variant used when many people are typing.
1049
+ */
1050
+ export declare interface ManyTypingSnapshot {
1051
+ /**
1052
+ * Check this to differentiate between FewTypingSnapshot (`false`) and ManyTypingSnapshot (`true`).
1053
+ *
1054
+ * @remarks
1055
+ * When `true`, you do not receive a list of users who are typing.
1056
+ * You should show a message like "several people are typing" instead.
1057
+ */
1058
+ many: true;
1059
+ }
1060
+
882
1061
  /**
883
1062
  * A node in a {@link TextBlock} that renders its children with a specific style.
884
1063
  *
@@ -931,7 +1110,7 @@ export declare interface MessageActiveState {
931
1110
  latestSnapshot: MessageSnapshot[] | null;
932
1111
  /**
933
1112
  * True if `latestSnapshot` contains all messages in the conversation.
934
- * Use `MessageSubscription.loadMore` to load more.
1113
+ * Use {@link MessageSubscription.loadMore} to load more.
935
1114
  */
936
1115
  loadedAll: boolean;
937
1116
  }
@@ -940,8 +1119,8 @@ export declare interface MessageActiveState {
940
1119
  * References the message with a given message ID.
941
1120
  *
942
1121
  * @remarks
943
- * Used in all Realtime API operations affecting that message, such as fetching or editing the message attributes, or deleting the message.
944
- * Created via {@link ConversationRef.message}.
1122
+ * Used in all Data API operations affecting that message, such as fetching or editing the message attributes, or deleting the message.
1123
+ * Created via {@link ConversationRef.message} and {@link ConversationRef.send}.
945
1124
  *
946
1125
  * @public
947
1126
  */
@@ -964,7 +1143,7 @@ export declare interface MessageRef {
964
1143
  * Fetches a snapshot of the message.
965
1144
  *
966
1145
  * @remarks
967
- * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#cached-fetch | Cached Fetch}
1146
+ * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#cached-fetch | Cached Fetch}
968
1147
  *
969
1148
  * @returns A snapshot of the message's attributes, or null if the message doesn't exist, the conversation doesn't exist, or you're not a participant in the conversation.
970
1149
  */
@@ -1068,7 +1247,7 @@ export declare interface MessageSnapshot {
1068
1247
  * The subscription is 'windowed'. It includes all messages since a certain point in time.
1069
1248
  * By default, you subscribe to the 30 most recent messages, and any new messages are sent after you subscribe.
1070
1249
  *
1071
- * You can expand this window by calling `loadMore`, which extends the window further into the past.
1250
+ * You can expand this window by calling {@link MessageSubscription.loadMore}, which extends the window further into the past.
1072
1251
  *
1073
1252
  * @public
1074
1253
  */
@@ -1115,7 +1294,7 @@ export declare interface MessageSubscription {
1115
1294
  * @param count - The number of additional messages to load. Must be between 1 and 100
1116
1295
  * @returns A promise that resolves once the additional messages have loaded
1117
1296
  */
1118
- loadMore: (count?: number) => Promise<void>;
1297
+ loadMore(count?: number): Promise<void>;
1119
1298
  /**
1120
1299
  * Unsubscribe from this resource and stop receiving updates.
1121
1300
  *
@@ -1129,7 +1308,7 @@ export declare interface MessageSubscription {
1129
1308
  * References a given user's participation in a conversation.
1130
1309
  *
1131
1310
  * @remarks
1132
- * Used in all Realtime API operations affecting that participant, such as joining/leaving a conversation, or setting their access.
1311
+ * Used in all Data API operations affecting that participant, such as joining/leaving a conversation, or setting their access.
1133
1312
  * Created via {@link ConversationRef.participant}.
1134
1313
  *
1135
1314
  * @public
@@ -1162,10 +1341,10 @@ export declare interface ParticipantRef {
1162
1341
  * Sets properties of this participant. If the user is not already a participant in the conversation, they will be added.
1163
1342
  *
1164
1343
  * @remarks
1165
- * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#automatic-batching | Automatic Batching}
1344
+ * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching}
1166
1345
  *
1167
1346
  * @returns A promise that resolves when the operation completes.
1168
- * When client-side conversation syncing is disabled, you may only set your `notify` property, when you are already a participant.
1347
+ * When client-side conversation syncing is disabled, you must already be a participant and you cannot set anything except the `notify` property.
1169
1348
  * Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.
1170
1349
  */
1171
1350
  set(params: SetParticipantParams): Promise<void>;
@@ -1173,10 +1352,10 @@ export declare interface ParticipantRef {
1173
1352
  * Edits properties of a pre-existing participant. If the user is not already a participant in the conversation, the promise will reject.
1174
1353
  *
1175
1354
  * @remarks
1176
- * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#automatic-batching | Automatic Batching}
1355
+ * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching}
1177
1356
  *
1178
1357
  * @returns A promise that resolves when the operation completes.
1179
- * When client-side conversation syncing is disabled, you may only set your `notify` property, when you are already a participant.
1358
+ * When client-side conversation syncing is disabled, you must already be a participant and you cannot set anything except the `notify` property.
1180
1359
  * Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.
1181
1360
  */
1182
1361
  edit(params: SetParticipantParams): Promise<void>;
@@ -1186,7 +1365,7 @@ export declare interface ParticipantRef {
1186
1365
  * @remarks
1187
1366
  * If the participant already exists, this operation is still considered successful and the promise will still resolve.
1188
1367
  *
1189
- * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#automatic-batching | Automatic Batching}
1368
+ * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching}
1190
1369
  *
1191
1370
  * @returns A promise that resolves when the operation completes. The promise will reject if client-side conversation syncing is disabled and the user is not already a participant.
1192
1371
  */
@@ -1297,9 +1476,9 @@ export declare interface ReferencedMessageSnapshot {
1297
1476
  /**
1298
1477
  * Where this message originated from:
1299
1478
  *
1300
- * - "web" = Message sent via the UI or via `ConversationBuilder.sendMessage`
1479
+ * - "web" = Message sent via the UI or via {@link ConversationBuilder.sendMessage}
1301
1480
  *
1302
- * - "rest" = Message sent via the REST API's "send message" endpoint
1481
+ * - "rest" = Message sent via the REST API's "send message" endpoint or {@link ConversationRef.send}
1303
1482
  *
1304
1483
  * - "import" = Message sent via the REST API's "import messages" endpoint
1305
1484
  *
@@ -1330,7 +1509,7 @@ export declare function registerPolyfills({ WebSocket }: {
1330
1509
  * `SendContentBlock` is a subset of `ContentBlock`.
1331
1510
  * This means that you can re-send the `content` from an existing message without any issues:
1332
1511
  *
1333
- * ```
1512
+ * ```ts
1334
1513
  * const existingMessage: MessageSnapshot = ...;
1335
1514
  *
1336
1515
  * const convRef = session.conversation('example_conversation_id');
@@ -1352,7 +1531,7 @@ export declare type SendContentBlock = TextBlock | SendFileBlock | LocationBlock
1352
1531
  * The `SendFileBlock` interface is a subset of the `FileBlock` interface.
1353
1532
  * If you have an existing `FileBlock` received in a message, you can re-use that block to re-send the same attachment:
1354
1533
  *
1355
- * ```
1534
+ * ```ts
1356
1535
  * const existingFileBlock = ...;
1357
1536
  * const imageToShare = existingFileBlock.content[0] as ImageBlock
1358
1537
  *
@@ -1397,6 +1576,8 @@ export declare interface SendMessageParams {
1397
1576
  *
1398
1577
  * @remarks
1399
1578
  * By default users do not have permission to send {@link LinkNode}, {@link ActionLinkNode}, or {@link ActionButtonNode}, as they can be used to trick the recipient.
1579
+ *
1580
+ * Currently, each message can only contain a single {@link SendContentBlock}.
1400
1581
  */
1401
1582
  content: [SendContentBlock];
1402
1583
  }
@@ -1579,6 +1760,10 @@ export declare interface TalkSession {
1579
1760
  * @remarks
1580
1761
  * This is immutable. If you want to connect as a different user,
1581
1762
  * call `getTalkSession` again to get a new session.
1763
+ *
1764
+ * Equivalent to calling `Session.user` with the current user's ID.
1765
+ *
1766
+ * @see {@link Session.user} which lets you get a reference to any user.
1582
1767
  */
1583
1768
  readonly currentUser: UserRef;
1584
1769
  /**
@@ -1597,6 +1782,27 @@ export declare interface TalkSession {
1597
1782
  /**
1598
1783
  * Get a reference to a user
1599
1784
  *
1785
+ * @remarks
1786
+ * This is the entry-point for all operations that affect a user globally, such as editing their name.
1787
+ * For operations related to a user's participation in a conversation, do: `session.conversation(<convId>).participant(<userId>)`
1788
+ *
1789
+ * @see {@link Session.currentUser} which is a short-hand for `session.user(session.me.id)`.
1790
+ *
1791
+ * @example Initialising a user
1792
+ * ```
1793
+ * const userRef = session.user("test");
1794
+ * userRef.createIfNotExists({ name: "Alice" });
1795
+ * ```
1796
+ *
1797
+ * @example Subscribing to changes
1798
+ * ```
1799
+ * const userRef = session.user("test");
1800
+ * const sub = userRef.subscribe(snapshot => console.log(snapshot));
1801
+ * await sub.connected;
1802
+ *
1803
+ * // Changing the user's name emits a snapshot and triggers the `console.log`
1804
+ * await userRef.set({ name: "Bob" });
1805
+ *
1600
1806
  * @param id - The ID of the user that you want to reference
1601
1807
  * @returns A {@linkcode UserRef} for the user with that ID
1602
1808
  * @public
@@ -1605,6 +1811,30 @@ export declare interface TalkSession {
1605
1811
  /**
1606
1812
  * Get a reference to a conversation
1607
1813
  *
1814
+ * @remarks
1815
+ * This is the entry-point for all conversation-related operations.
1816
+ * This includes operations affecting conversation attributes, but also anything related to messages and participants.
1817
+ *
1818
+ * @example Ensure that the conversation exists and you are a participant
1819
+ * ```
1820
+ * session.conversation("test").createIfNotExists();
1821
+ * ```
1822
+ *
1823
+ * @example Set the conversation's subject
1824
+ * ```
1825
+ * session.conversation("test").set({ subject: "Power tools" });
1826
+ * ```
1827
+ *
1828
+ * @example Stop receiving notifications for this conversation
1829
+ * ```
1830
+ * session.conversation("test").set({ notify: false });
1831
+ * ```
1832
+ *
1833
+ * @example Send a message
1834
+ * ```
1835
+ * session.conversation("test").send("Hello");
1836
+ * ```
1837
+ *
1608
1838
  * @param id - The ID of the conversation that you want to reference
1609
1839
  * @returns A {@linkcode ConversationRef} for the conversation with that ID
1610
1840
  * @public
@@ -1692,7 +1922,7 @@ export declare interface TalkSessionOptions {
1692
1922
  *
1693
1923
  * Then this would become a Text Block with the structure:
1694
1924
  *
1695
- * ```
1925
+ * ```json
1696
1926
  * {
1697
1927
  * type: "text",
1698
1928
  * children: [
@@ -1730,7 +1960,7 @@ export declare interface TextBlock {
1730
1960
  * The simplest `TextNode` is a plain text string.
1731
1961
  * Using "hello" as an example message, the `TextBlock` would be:
1732
1962
  *
1733
- * ```typescript
1963
+ * ```ts
1734
1964
  * {
1735
1965
  * type: 'text';
1736
1966
  * children: ['hello'];
@@ -1739,7 +1969,7 @@ export declare interface TextBlock {
1739
1969
  *
1740
1970
  * Other than plain text, there are many different kinds of node which render some text in a specific way or with certain formatting.
1741
1971
  *
1742
- * ```
1972
+ * ```ts
1743
1973
  * type TextNode =
1744
1974
  * | string
1745
1975
  * | MarkupNode
@@ -1761,6 +1991,106 @@ export declare interface TextBlock {
1761
1991
  */
1762
1992
  export declare type TextNode = string | MarkupNode | BulletListNode | BulletPointNode | CodeSpanNode | LinkNode | AutoLinkNode | ActionLinkNode | ActionButtonNode | CustomEmojiNode | MentionNode;
1763
1993
 
1994
+ /**
1995
+ * The state of a typing subscription when it is actively listening for changes
1996
+ *
1997
+ * @public
1998
+ */
1999
+ export declare interface TypingActiveState {
2000
+ type: "active";
2001
+ /**
2002
+ * The most recently received typing indicator snapshot, or `null` if you are not a participant in the conversation (including when the conversation does not exist).
2003
+ */
2004
+ latestSnapshot: TypingSnapshot | null;
2005
+ }
2006
+
2007
+ /**
2008
+ * A snapshot of the typing indicators in a conversation at a given moment in time.
2009
+ * Will be either {@link FewTypingSnapshot} when only a few people are typing, or {@link ManyTypingSnapshot} when many people are typing.
2010
+ *
2011
+ * @remarks
2012
+ * Currently {@link FewTypingSnapshot} is used when there are 5 or less people typing in the conversation, and {@link ManyTypingSnapshot} is used when more than 5 people are typing.
2013
+ * This limit may change in the future, which will not be considered a breaking change.
2014
+ *
2015
+ * @example Converting a TypingSnapshot to text
2016
+ * ```ts
2017
+ * function formatTyping(snapshot: TypingSnapshot): string {
2018
+ * if (snapshot.many) {
2019
+ * return "Several people are typing";
2020
+ * }
2021
+ *
2022
+ * const names = snapshot.users.map(user => user.name);
2023
+ *
2024
+ * if (names.length === 0) {
2025
+ * return "";
2026
+ * }
2027
+ *
2028
+ * if (names.length === 1) {
2029
+ * return names[0] + " is typing";
2030
+ * }
2031
+ *
2032
+ * if (names.length === 2) {
2033
+ * return names.join(" and ") + " are typing";
2034
+ * }
2035
+ *
2036
+ * // Prefix last name with "and "
2037
+ * names.push("and " + names.pop());
2038
+ * return names.join(", ") + " are typing";
2039
+ * }
2040
+ * ```
2041
+ */
2042
+ export declare type TypingSnapshot = FewTypingSnapshot | ManyTypingSnapshot;
2043
+
2044
+ /**
2045
+ * A subscription to the typing status in a specific conversation
2046
+ *
2047
+ * @remarks
2048
+ * Get a TypingSubscription by calling {@link ConversationRef.subscribeTyping}.
2049
+ *
2050
+ * When there are "many" people typing (meaning you received {@link ManyTypingSnapshot}), the next update you receive will be {@link FewTypingSnapshot} once enough people stop typing.
2051
+ * Until then, your {@link ManyTypingSnapshot} is still valid and doesn not need to changed, so `onSnapshot` will not be called.
2052
+ *
2053
+ * @public
2054
+ */
2055
+ export declare interface TypingSubscription {
2056
+ /**
2057
+ * The current state of the subscription
2058
+ *
2059
+ * @remarks
2060
+ * An object with the following fields:
2061
+ *
2062
+ * `type` is one of "pending", "active", "unsubscribed", or "error".
2063
+ *
2064
+ * When `type` is "active", includes `latestSnapshot: TypingSnapshot | null`. It is the current state of the typing indicators, or null if you're not a participant in the conversation
2065
+ *
2066
+ * When `type` is "error", includes the `error: Error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
2067
+ */
2068
+ state: PendingState | TypingActiveState | UnsubscribedState | ErrorState;
2069
+ /**
2070
+ * Resolves when the subscription starts receiving updates from the server.
2071
+ *
2072
+ * @remarks
2073
+ * Wait for this promise if you want to perform some action as soon as the subscription is active.
2074
+ *
2075
+ * The promise rejects if the subscription is terminated before it connects.
2076
+ */
2077
+ connected: Promise<TypingActiveState>;
2078
+ /**
2079
+ * Resolves when the subscription permanently stops receiving updates from the server.
2080
+ *
2081
+ * @remarks
2082
+ * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
2083
+ */
2084
+ terminated: Promise<UnsubscribedState | ErrorState>;
2085
+ /**
2086
+ * Unsubscribe from this resource and stop receiving updates.
2087
+ *
2088
+ * @remarks
2089
+ * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
2090
+ */
2091
+ unsubscribe(): void;
2092
+ }
2093
+
1764
2094
  /**
1765
2095
  * The state of a subscription after you have manually unsubscribed
1766
2096
  *
@@ -1787,7 +2117,7 @@ export declare interface UserActiveState {
1787
2117
  * References the user with a given user ID.
1788
2118
  *
1789
2119
  * @remarks
1790
- * Used in all Realtime API operations affecting that user, such as creating the user, fetching or updating user data, or adding a user to a conversation.
2120
+ * Used in all Data API operations affecting that user, such as creating the user, fetching or updating user data, or adding a user to a conversation.
1791
2121
  * Created via {@link Session.user}.
1792
2122
  *
1793
2123
  * @public
@@ -1808,7 +2138,7 @@ export declare interface UserRef {
1808
2138
  * Fetching a user snapshot doesn't require any permissions. You can read the public information of any user.
1809
2139
  * Private information, such as email addresses and phone numbers, aren't included in the response.
1810
2140
  *
1811
- * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#automatic-batching | Automatic Batching} and {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#cached-fetch | Cached Fetch}
2141
+ * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching} and {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#cached-fetch | Cached Fetch}
1812
2142
  *
1813
2143
  * @returns A snapshot of the user's public attributes, or null if the user doesn't exist.
1814
2144
  */
@@ -1837,8 +2167,6 @@ export declare interface UserRef {
1837
2167
  * @remarks
1838
2168
  * Whenever `Subscription.state.type` is "active" and the user is created or their attributes change, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
1839
2169
  *
1840
- * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#subscription-sharing | Subscription Sharing} and {@link https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#debounced-unsubscribe | Debounced Unsubscribe}
1841
- *
1842
2170
  * @returns A subscription to the user
1843
2171
  */
1844
2172
  subscribe(onSnapshot?: (event: UserSnapshot | null) => void): UserSubscription;