stream-chat-react 13.3.0 → 13.4.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.
@@ -24,7 +24,7 @@ export const useChat = ({ client, defaultLanguage = 'en', i18nInstance, initialN
24
24
  useEffect(() => {
25
25
  if (!client)
26
26
  return;
27
- const version = "13.3.0";
27
+ const version = "13.4.0";
28
28
  const userAgent = client.getUserAgent();
29
29
  if (!userAgent.includes('stream-chat-react')) {
30
30
  // result looks like: 'stream-chat-react-2.3.2-stream-chat-javascript-client-browser-2.2.2'
@@ -16,4 +16,4 @@ export type RenderTextOptions = {
16
16
  getRehypePlugins?: RenderTextPluginConfigurator;
17
17
  getRemarkPlugins?: RenderTextPluginConfigurator;
18
18
  };
19
- export declare const renderText: (text?: string, mentionedUsers?: UserResponse[], { allowedTagNames, customMarkDownRenderers, getRehypePlugins, getRemarkPlugins, }?: RenderTextOptions) => React.JSX.Element | null | undefined;
19
+ export declare const renderText: (text?: string, mentionedUsers?: UserResponse[], { allowedTagNames, customMarkDownRenderers, getRehypePlugins, getRemarkPlugins, }?: RenderTextOptions) => React.JSX.Element | null;
@@ -83,7 +83,7 @@ export const renderText = (text, mentionedUsers, { allowedTagNames = defaultAllo
83
83
  return strippedHref.includes(strippedText) || strippedText.includes(strippedHref);
84
84
  });
85
85
  if (noParsingNeeded.length > 0 || linkIsInBlock)
86
- return;
86
+ continue;
87
87
  try {
88
88
  // special case for mentions:
89
89
  // it could happen that a user's name matches with an e-mail format pattern.
@@ -1,5 +1,6 @@
1
1
  export * from './AttachmentPreviewList';
2
2
  export type { FileAttachmentPreviewProps } from './FileAttachmentPreview';
3
+ export type { GeolocationPreviewProps } from './GeolocationPreview';
3
4
  export type { ImageAttachmentPreviewProps } from './ImageAttachmentPreview';
4
5
  export type { UploadAttachmentPreviewProps as AttachmentPreviewProps } from './types';
5
6
  export type { UnsupportedAttachmentPreviewProps } from './UnsupportedAttachmentPreview';
@@ -1,6 +1,6 @@
1
1
  export * from './AttachmentSelector';
2
2
  export { AttachmentPreviewList } from './AttachmentPreviewList';
3
- export type { AttachmentPreviewListProps, FileAttachmentPreviewProps, ImageAttachmentPreviewProps, AttachmentPreviewProps, UnsupportedAttachmentPreviewProps, VoiceRecordingPreviewProps, } from './AttachmentPreviewList';
3
+ export type { AttachmentPreviewListProps, FileAttachmentPreviewProps, GeolocationPreviewProps, ImageAttachmentPreviewProps, AttachmentPreviewProps, UnsupportedAttachmentPreviewProps, VoiceRecordingPreviewProps, } from './AttachmentPreviewList';
4
4
  export * from './CooldownTimer';
5
5
  export * from './EditMessageForm';
6
6
  export * from './hooks';
@@ -1,11 +1,16 @@
1
- import type { PropsWithChildren } from 'react';
1
+ import { type PropsWithChildren } from 'react';
2
2
  import React from 'react';
3
+ type CloseEvent = KeyboardEvent | React.KeyboardEvent | React.MouseEvent<HTMLButtonElement | HTMLDivElement>;
4
+ export type ModalCloseSource = 'overlay' | 'button' | 'escape';
3
5
  export type ModalProps = {
4
6
  /** If true, modal is opened or visible. */
5
7
  open: boolean;
6
8
  /** Custom class to be applied to the modal root div */
7
9
  className?: string;
8
10
  /** Callback handler for closing of modal. */
9
- onClose?: (event: React.KeyboardEvent | React.MouseEvent<HTMLButtonElement | HTMLDivElement>) => void;
11
+ onClose?: (event: CloseEvent) => void;
12
+ /** Optional handler to intercept closing logic. Return false to prevent onClose. */
13
+ onCloseAttempt?: (source: ModalCloseSource, event: CloseEvent) => boolean;
10
14
  };
11
- export declare const Modal: ({ children, className, onClose, open, }: PropsWithChildren<ModalProps>) => React.JSX.Element | null;
15
+ export declare const Modal: ({ children, className, onClose, onCloseAttempt, open, }: PropsWithChildren<ModalProps>) => React.JSX.Element | null;
16
+ export {};
@@ -1,34 +1,45 @@
1
1
  import clsx from 'clsx';
2
+ import { useCallback } from 'react';
2
3
  import React, { useEffect, useRef } from 'react';
3
4
  import { FocusScope } from '@react-aria/focus';
4
5
  import { CloseIconRound } from './icons';
5
6
  import { useTranslationContext } from '../../context';
6
- export const Modal = ({ children, className, onClose, open, }) => {
7
+ export const Modal = ({ children, className, onClose, onCloseAttempt, open, }) => {
7
8
  const { t } = useTranslationContext('Modal');
8
9
  const innerRef = useRef(null);
9
- const closeRef = useRef(null);
10
+ const closeButtonRef = useRef(null);
11
+ const maybeClose = useCallback((source, event) => {
12
+ const allow = onCloseAttempt?.(source, event);
13
+ if (allow !== false) {
14
+ onClose?.(event);
15
+ }
16
+ }, [onClose, onCloseAttempt]);
10
17
  const handleClick = (event) => {
11
18
  const target = event.target;
12
- if (!innerRef.current || !closeRef.current)
19
+ if (!innerRef.current || !closeButtonRef.current)
13
20
  return;
14
- if (!innerRef.current.contains(target) || closeRef.current.contains(target))
15
- onClose?.(event);
21
+ if (closeButtonRef.current.contains(target)) {
22
+ maybeClose('button', event);
23
+ }
24
+ else if (!innerRef.current.contains(target)) {
25
+ maybeClose('overlay', event);
26
+ }
16
27
  };
17
28
  useEffect(() => {
18
29
  if (!open)
19
30
  return;
20
31
  const handleKeyDown = (event) => {
21
32
  if (event.key === 'Escape')
22
- onClose?.(event);
33
+ maybeClose('escape', event);
23
34
  };
24
35
  document.addEventListener('keydown', handleKeyDown);
25
36
  return () => document.removeEventListener('keydown', handleKeyDown);
26
- }, [onClose, open]);
37
+ }, [maybeClose, open]);
27
38
  if (!open)
28
39
  return null;
29
40
  return (React.createElement("div", { className: clsx('str-chat__modal str-chat__modal--open', className), onClick: handleClick },
30
41
  React.createElement(FocusScope, { autoFocus: true, contain: true },
31
- React.createElement("button", { className: 'str-chat__modal__close-button', ref: closeRef, title: t('Close') },
42
+ React.createElement("button", { className: 'str-chat__modal__close-button', ref: closeButtonRef, title: t('Close') },
32
43
  React.createElement(CloseIconRound, null)),
33
44
  React.createElement("div", { className: 'str-chat__modal__inner str-chat-react__modal__inner', ref: innerRef }, children))));
34
45
  };
@@ -15,7 +15,10 @@ export const PollCreationDialogControls = ({ close, }) => {
15
15
  messageComposer
16
16
  .createPoll()
17
17
  .then(() => handleSubmitMessage())
18
- .then(close)
18
+ .then(() => {
19
+ messageComposer.pollComposer.initState();
20
+ close();
21
+ })
19
22
  .catch(console.error);
20
23
  }, type: 'submit' }, t('Create'))));
21
24
  };
@@ -245,6 +245,7 @@ export declare class Streami18n {
245
245
  "Poll results": string;
246
246
  Question: string;
247
247
  Quote: string;
248
+ "Reached the vote limit. Remove an existing vote first.": string;
248
249
  "Recording format is not supported and cannot be reproduced": string;
249
250
  "Remind Me": string;
250
251
  "Remove reminder": string;
@@ -1,10 +1,12 @@
1
1
  import { attachmentUploadBlockedNotificationTranslator, attachmentUploadFailedNotificationTranslator, } from './attachmentUpload';
2
2
  import { TranslationTopic } from '../../TranslationBuilder';
3
3
  import { pollCreationFailedNotificationTranslator } from './pollComposition';
4
+ import { pollVoteCountTrespass } from './pollVoteCountTrespass';
4
5
  export const defaultNotificationTranslators = {
5
6
  'api:attachment:upload:failed': attachmentUploadFailedNotificationTranslator,
6
7
  'api:poll:create:failed': pollCreationFailedNotificationTranslator,
7
8
  'validation:attachment:upload:blocked': attachmentUploadBlockedNotificationTranslator,
9
+ 'validation:poll:castVote:limit': pollVoteCountTrespass,
8
10
  };
9
11
  export class NotificationTranslationTopic extends TranslationTopic {
10
12
  constructor({ i18next, translators }) {
@@ -0,0 +1,3 @@
1
+ import type { Translator } from '../TranslationBuilder';
2
+ import type { NotificationTranslatorOptions } from './types';
3
+ export declare const pollVoteCountTrespass: Translator<NotificationTranslatorOptions>;
@@ -0,0 +1 @@
1
+ export const pollVoteCountTrespass = ({ t }) => t('Reached the vote limit. Remove an existing vote first.');
package/dist/i18n/de.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Umfrageergebnisse",
110
110
  "Question": "Frage",
111
111
  "Quote": "Zitieren",
112
+ "Reached the vote limit. Remove an existing vote first.": "Das Abstimmungslimit wurde erreicht. Entfernen Sie zuerst eine bestehende Stimme.",
112
113
  "Recording format is not supported and cannot be reproduced": "Aufnahmeformat wird nicht unterstützt und kann nicht wiedergegeben werden",
113
114
  "Remind Me": "Erinnern",
114
115
  "Remove reminder": "Erinnerung entfernen",
package/dist/i18n/en.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Poll results",
110
110
  "Question": "Question",
111
111
  "Quote": "Quote",
112
+ "Reached the vote limit. Remove an existing vote first.": "Reached the vote limit. Remove an existing vote first.",
112
113
  "Recording format is not supported and cannot be reproduced": "Recording format is not supported and cannot be reproduced",
113
114
  "Remind Me": "Remind Me",
114
115
  "Remove reminder": "Remove reminder",
package/dist/i18n/es.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Resultados de la encuesta",
110
110
  "Question": "Pregunta",
111
111
  "Quote": "Citar",
112
+ "Reached the vote limit. Remove an existing vote first.": "Se ha alcanzado el límite de votos. Elimina un voto existente primero.",
112
113
  "Recording format is not supported and cannot be reproduced": "El formato de grabación no es compatible y no se puede reproducir",
113
114
  "Remind Me": "Recordarme",
114
115
  "Remove reminder": "Eliminar recordatorio",
package/dist/i18n/fr.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Résultats du sondage",
110
110
  "Question": "Question",
111
111
  "Quote": "Citer",
112
+ "Reached the vote limit. Remove an existing vote first.": "La limite de votes a été atteinte. Supprimez d'abord un vote existant.",
112
113
  "Recording format is not supported and cannot be reproduced": "Le format d'enregistrement n'est pas pris en charge et ne peut pas être reproduit",
113
114
  "Remind Me": "Me rappeler",
114
115
  "Remove reminder": "Supprimer le rappel",
package/dist/i18n/hi.json CHANGED
@@ -110,6 +110,7 @@
110
110
  "Poll results": "मतदान परिणाम",
111
111
  "Question": "प्रश्न",
112
112
  "Quote": "उद्धरण",
113
+ "Reached the vote limit. Remove an existing vote first.": "मतदान सीमा तक पहुंच गया। पहले एक मौजूदा वोट हटाएं।",
113
114
  "Recording format is not supported and cannot be reproduced": "रेकॉर्डिंग फ़ॉर्मेट समर्थित नहीं है और पुनः उत्पन्न नहीं किया जा सकता",
114
115
  "Remind Me": "मुझे याद दिलाएं",
115
116
  "Remove reminder": "रिमाइंडर हटाएं",
package/dist/i18n/it.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Risultati del sondaggio",
110
110
  "Question": "Domanda",
111
111
  "Quote": "Citazione",
112
+ "Reached the vote limit. Remove an existing vote first.": "Raggiunto il limite di voti. Rimuovi prima un voto esistente.",
112
113
  "Recording format is not supported and cannot be reproduced": "Il formato di registrazione non è supportato e non può essere riprodotto",
113
114
  "Remind Me": "Ricordami",
114
115
  "Remove reminder": "Rimuovi promemoria",
package/dist/i18n/ja.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "投票結果",
110
110
  "Question": "質問",
111
111
  "Quote": "引用",
112
+ "Reached the vote limit. Remove an existing vote first.": "投票制限に達しました。既存の投票を先に削除してください。",
112
113
  "Recording format is not supported and cannot be reproduced": "録音形式はサポートされておらず、再生できません",
113
114
  "Remind Me": "リマインダー",
114
115
  "Remove reminder": "リマインダーを削除",
package/dist/i18n/ko.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "투표 결과",
110
110
  "Question": "질문",
111
111
  "Quote": "인용",
112
+ "Reached the vote limit. Remove an existing vote first.": "투표 한도에 도달했습니다. 기존 투표를 먼저 제거하세요.",
112
113
  "Recording format is not supported and cannot be reproduced": "녹음 형식이 지원되지 않으므로 재생할 수 없습니다",
113
114
  "Remind Me": "알림 설정",
114
115
  "Remove reminder": "알림 제거",
package/dist/i18n/nl.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Peiling resultaten",
110
110
  "Question": "Vraag",
111
111
  "Quote": "Citeer",
112
+ "Reached the vote limit. Remove an existing vote first.": "Stemlimiet bereikt. Verwijder eerst een bestaande stem.",
112
113
  "Recording format is not supported and cannot be reproduced": "Opnameformaat wordt niet ondersteund en kan niet worden gereproduceerd",
113
114
  "Remind Me": "Herinner mij",
114
115
  "Remove reminder": "Herinnering verwijderen",
package/dist/i18n/pt.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Resultados da pesquisa",
110
110
  "Question": "Pergunta",
111
111
  "Quote": "Citar",
112
+ "Reached the vote limit. Remove an existing vote first.": "Limite de votos atingido. Remova um voto existente primeiro.",
112
113
  "Recording format is not supported and cannot be reproduced": "Formato de gravação não é suportado e não pode ser reproduzido",
113
114
  "Remind Me": "Lembrar-me",
114
115
  "Remove reminder": "Remover lembrete",
package/dist/i18n/ru.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Результаты опроса",
110
110
  "Question": "Вопрос",
111
111
  "Quote": "Цитировать",
112
+ "Reached the vote limit. Remove an existing vote first.": "Достигнут лимит голосов. Сначала удалите существующий голос.",
112
113
  "Recording format is not supported and cannot be reproduced": "Формат записи не поддерживается и не может быть воспроизведен",
113
114
  "Remind Me": "Напомнить мне",
114
115
  "Remove reminder": "Удалить напоминание",
package/dist/i18n/tr.json CHANGED
@@ -109,6 +109,7 @@
109
109
  "Poll results": "Anket sonuçları",
110
110
  "Question": "Soru",
111
111
  "Quote": "Alıntı",
112
+ "Reached the vote limit. Remove an existing vote first.": "Oylama sınırına ulaşıldı. Önce mevcut bir oyu kaldırın.",
112
113
  "Recording format is not supported and cannot be reproduced": "Kayıt formatı desteklenmiyor ve çoğaltılamıyor",
113
114
  "Remind Me": "Hatırlat",
114
115
  "Remove reminder": "Hatırlatıcıyı kaldır",