stream-chat-react 14.5.0 → 14.6.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/cjs/{ReactPlayerWrapper.963d6170.js → ReactPlayerWrapper.30240f76.js} +2 -2
- package/dist/cjs/{ReactPlayerWrapper.963d6170.js.map → ReactPlayerWrapper.30240f76.js.map} +1 -1
- package/dist/cjs/channel-detail.js +3007 -0
- package/dist/cjs/channel-detail.js.map +1 -0
- package/dist/cjs/emojis.js +5 -4
- package/dist/cjs/emojis.js.map +1 -1
- package/dist/cjs/index.js +1804 -4064
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/useChannelHeaderOnlineStatus.6546ac83.js +4143 -0
- package/dist/cjs/useChannelHeaderOnlineStatus.6546ac83.js.map +1 -0
- package/dist/cjs/useMessageComposerController.c0dad9bc.js +99 -0
- package/dist/cjs/useMessageComposerController.c0dad9bc.js.map +1 -0
- package/dist/cjs/{useNotificationApi.e9312774.js → useNotificationApi.eb753f31.js} +121 -166
- package/dist/cjs/useNotificationApi.eb753f31.js.map +1 -0
- package/dist/css/channel-detail.css +825 -0
- package/dist/css/channel-detail.css.map +1 -0
- package/dist/css/index.css +111 -31
- package/dist/css/index.css.map +1 -1
- package/dist/es/channel-detail.mjs +2950 -0
- package/dist/es/channel-detail.mjs.map +1 -0
- package/dist/es/emojis.mjs +2 -1
- package/dist/es/emojis.mjs.map +1 -1
- package/dist/es/index.mjs +1399 -3669
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/useChannelHeaderOnlineStatus.c5215b13.mjs +3600 -0
- package/dist/es/useChannelHeaderOnlineStatus.c5215b13.mjs.map +1 -0
- package/dist/es/useMessageComposerController.29f189b4.mjs +69 -0
- package/dist/es/useMessageComposerController.29f189b4.mjs.map +1 -0
- package/dist/es/{useNotificationApi.4be515a0.mjs → useNotificationApi.fa5cddf9.mjs} +104 -137
- package/dist/es/useNotificationApi.fa5cddf9.mjs.map +1 -0
- package/dist/types/components/AudioPlayback/components/index.d.ts +1 -0
- package/dist/types/components/AudioPlayback/components/index.d.ts.map +1 -1
- package/dist/types/components/Avatar/ChannelAvatar.d.ts.map +1 -1
- package/dist/types/components/ChannelHeader/hooks/useChannelHasMembersOnline.d.ts +7 -0
- package/dist/types/components/ChannelHeader/hooks/useChannelHasMembersOnline.d.ts.map +1 -0
- package/dist/types/components/ChannelHeader/hooks/useChannelHeaderOnlineStatus.d.ts +6 -1
- package/dist/types/components/ChannelHeader/hooks/useChannelHeaderOnlineStatus.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/hooks/index.d.ts +1 -0
- package/dist/types/components/ChannelListItem/hooks/index.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/hooks/useChannelPreviewInfo.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/hooks/useIsUserMuted.d.ts +2 -0
- package/dist/types/components/ChannelListItem/hooks/useIsUserMuted.d.ts.map +1 -0
- package/dist/types/components/Chat/Chat.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Prompt.d.ts +7 -4
- package/dist/types/components/Dialog/components/Prompt.d.ts.map +1 -1
- package/dist/types/components/Dialog/service/DialogPortal.d.ts +5 -1
- package/dist/types/components/Dialog/service/DialogPortal.d.ts.map +1 -1
- package/dist/types/components/FileIcon/iconMap.d.ts.map +1 -1
- package/dist/types/components/Form/Checkbox.d.ts +8 -0
- package/dist/types/components/Form/Checkbox.d.ts.map +1 -0
- package/dist/types/components/Form/SwitchField.d.ts +6 -0
- package/dist/types/components/Form/SwitchField.d.ts.map +1 -1
- package/dist/types/components/Form/index.d.ts +1 -0
- package/dist/types/components/Form/index.d.ts.map +1 -1
- package/dist/types/components/Icons/icons.d.ts +12 -0
- package/dist/types/components/Icons/icons.d.ts.map +1 -1
- package/dist/types/components/InfiniteScrollPaginator/index.d.ts +1 -0
- package/dist/types/components/InfiniteScrollPaginator/index.d.ts.map +1 -1
- package/dist/types/components/Message/hooks/useMessageTextStreaming.d.ts +1 -1
- package/dist/types/components/Message/hooks/useReactionsFetcher.d.ts +1 -1
- package/dist/types/components/Message/hooks/useReactionsFetcher.d.ts.map +1 -1
- package/dist/types/components/Modal/GlobalModal.d.ts +3 -1
- package/dist/types/components/Modal/GlobalModal.d.ts.map +1 -1
- package/dist/types/components/Notifications/hooks/useNotificationApi.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/MultipleAnswersField.d.ts.map +1 -1
- package/dist/types/components/Poll/PollOptionSelector.d.ts +0 -4
- package/dist/types/components/Poll/PollOptionSelector.d.ts.map +1 -1
- package/dist/types/context/DialogManagerContext.d.ts +3 -1
- package/dist/types/context/DialogManagerContext.d.ts.map +1 -1
- package/dist/types/i18n/Streami18n.d.ts +99 -0
- package/dist/types/i18n/Streami18n.d.ts.map +1 -1
- package/dist/types/plugins/ChannelDetail/AvatarWithChannelDetail.d.ts +9 -0
- package/dist/types/plugins/ChannelDetail/AvatarWithChannelDetail.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetail.d.ts +14 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetail.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailContext.d.ts +11 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailContext.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailEmptyList.d.ts +3 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailEmptyList.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailListLoadingIndicator.d.ts +6 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailListLoadingIndicator.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailNavButton.d.ts +15 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailNavButton.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailSearchInput.d.ts +8 -0
- package/dist/types/plugins/ChannelDetail/ChannelDetailSearchInput.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/SectionNavigator/SectionNavigator.d.ts +52 -0
- package/dist/types/plugins/ChannelDetail/SectionNavigator/SectionNavigator.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/SectionNavigator/SectionNavigatorHeader.d.ts +11 -0
- package/dist/types/plugins/ChannelDetail/SectionNavigator/SectionNavigatorHeader.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/SectionNavigator/index.d.ts +3 -0
- package/dist/types/plugins/ChannelDetail/SectionNavigator/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesEmptyList.d.ts +2 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesEmptyList.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesView.d.ts +5 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesView.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesView.utils.d.ts +40 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/ChannelFilesView.utils.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/index.d.ts +5 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/useChannelFilesSearch.d.ts +10 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelFilesView/useChannelFilesSearch.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementActions.defaults.d.ts +16 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementActions.defaults.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementView.d.ts +20 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/ChannelManagementView.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/index.d.ts +3 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelManagementView/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaEmptyList.d.ts +2 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaEmptyList.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaView.d.ts +8 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaView.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaView.utils.d.ts +22 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/ChannelMediaView.utils.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/index.d.ts +5 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/useChannelMediaSearch.d.ts +9 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMediaView/useChannelMediaSearch.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMemberDetailView/ChannelMemberActions.defaults.d.ts +26 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMemberDetailView/ChannelMemberActions.defaults.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMemberDetailView/ChannelMemberDetail.d.ts +12 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMemberDetailView/ChannelMemberDetail.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMemberDetailView/index.d.ts +3 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMemberDetailView/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersAddView.d.ts +7 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersAddView.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersBrowseView.d.ts +6 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersBrowseView.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersHeaderActions.defaults.d.ts +45 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersHeaderActions.defaults.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersView.d.ts +46 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersView.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersView.utils.d.ts +8 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/ChannelMembersView.utils.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/index.d.ts +6 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMemberCount.d.ts +4 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMemberCount.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMemberIds.d.ts +4 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMemberIds.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMembersSearch.d.ts +12 -0
- package/dist/types/plugins/ChannelDetail/Views/ChannelMembersView/useChannelMembersSearch.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/PinnedMessagesEmptyList.d.ts +2 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/PinnedMessagesEmptyList.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/PinnedMessagesView.d.ts +9 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/PinnedMessagesView.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/index.d.ts +4 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/usePinnedMessagesCount.d.ts +4 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/usePinnedMessagesCount.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/usePinnedMessagesSearch.d.ts +16 -0
- package/dist/types/plugins/ChannelDetail/Views/PinnedMessagesView/usePinnedMessagesSearch.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/VirtualizedList/VirtualizedList.d.ts +28 -0
- package/dist/types/plugins/ChannelDetail/VirtualizedList/VirtualizedList.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/VirtualizedList/index.d.ts +2 -0
- package/dist/types/plugins/ChannelDetail/VirtualizedList/index.d.ts.map +1 -0
- package/dist/types/plugins/ChannelDetail/index.d.ts +16 -0
- package/dist/types/plugins/ChannelDetail/index.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/isDmChannel.d.ts +6 -0
- package/dist/types/utils/isDmChannel.d.ts.map +1 -0
- package/package.json +11 -2
- package/dist/cjs/useNotificationApi.e9312774.js.map +0 -1
- package/dist/es/useNotificationApi.4be515a0.mjs.map +0 -1
|
@@ -0,0 +1,4143 @@
|
|
|
1
|
+
const require_useNotificationApi = require("./useNotificationApi.eb753f31.js");
|
|
2
|
+
let react = require("react");
|
|
3
|
+
react = require_useNotificationApi.__toESM(react);
|
|
4
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
let stream_chat = require("stream-chat");
|
|
6
|
+
let clsx = require("clsx");
|
|
7
|
+
clsx = require_useNotificationApi.__toESM(clsx);
|
|
8
|
+
let use_sync_external_store_shim = require("use-sync-external-store/shim");
|
|
9
|
+
let _react_aria_focus = require("@react-aria/focus");
|
|
10
|
+
let unist_util_visit = require("unist-util-visit");
|
|
11
|
+
let react_markdown = require("react-markdown");
|
|
12
|
+
react_markdown = require_useNotificationApi.__toESM(react_markdown);
|
|
13
|
+
let remark_gfm = require("remark-gfm");
|
|
14
|
+
remark_gfm = require_useNotificationApi.__toESM(remark_gfm);
|
|
15
|
+
let _braintree_sanitize_url = require("@braintree/sanitize-url");
|
|
16
|
+
//#region src/context/MessageContext.tsx
|
|
17
|
+
var MessageContext = react.default.createContext(void 0);
|
|
18
|
+
var MessageProvider = ({ children, value }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessageContext.Provider, {
|
|
19
|
+
value,
|
|
20
|
+
children
|
|
21
|
+
});
|
|
22
|
+
var useMessageContext = (_componentName) => {
|
|
23
|
+
const contextValue = (0, react.useContext)(MessageContext);
|
|
24
|
+
if (!contextValue) return {};
|
|
25
|
+
return contextValue;
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/context/MessageTranslationViewContext.tsx
|
|
29
|
+
/**
|
|
30
|
+
* Message translation view context: user-specific state for whether each message
|
|
31
|
+
* shows original text or a translation.
|
|
32
|
+
*
|
|
33
|
+
* ## Spec
|
|
34
|
+
*
|
|
35
|
+
* - **State**: Per message list (channel vs thread), we store a map
|
|
36
|
+
* `messageId → 'original' | 'translated'`. Default for messages with `message.i18n`
|
|
37
|
+
* is `'translated'`; otherwise `'original'`.
|
|
38
|
+
*
|
|
39
|
+
* - **Provider placement**: The provider is tied to the **message list**, not the channel.
|
|
40
|
+
* It is rendered inside `MessageList` and `VirtualizedMessageList`. That way the
|
|
41
|
+
* main channel list and the thread list each have their own translation view state
|
|
42
|
+
* (e.g. Thread.tsx gets correct behavior without sharing channel state).
|
|
43
|
+
*
|
|
44
|
+
* - **Multiple translations**: `message.i18n` can contain multiple languages, e.g.:
|
|
45
|
+
* `{ en_text: "Good morning", fr_text: "Bonjour", it_text: "Buongiorno", language: "en" }`.
|
|
46
|
+
* Which translation is shown is determined by the app’s **user language**
|
|
47
|
+
* (`useTranslationContext().userLanguage`). We use `message.i18n[userLanguage + '_text']`;
|
|
48
|
+
* if missing, we fall back to `message.text`. Only one translation is shown at a time.
|
|
49
|
+
*
|
|
50
|
+
* - **Source language**: When present, `message.i18n.language` is the original/source
|
|
51
|
+
* language of `message.text`. It can be used for the indicator label, e.g.
|
|
52
|
+
* "Translated from English · View original".
|
|
53
|
+
*
|
|
54
|
+
* - **Invariants**: The original message content, layout, grouping, and order stay
|
|
55
|
+
* unchanged. Removing or toggling translation only changes the annotation and which
|
|
56
|
+
* text is displayed. "View original" / "View translation" switch the displayed
|
|
57
|
+
* text and update the annotation (e.g. "Original · View translation" when showing
|
|
58
|
+
* original).
|
|
59
|
+
*
|
|
60
|
+
* - **Translation indicator visibility**: The translation indicator (e.g. "Translated ·
|
|
61
|
+
* View original") is **not** shown when the currently viewed text already corresponds
|
|
62
|
+
* to `userLanguage` — for example when viewing original and the original text is the
|
|
63
|
+
* user-language version (i.e. `getTranslatedMessageText({ language: userLanguage, message })`
|
|
64
|
+
* equals `message.text`). In that case there is no meaningful original/translated choice,
|
|
65
|
+
* so the indicator is hidden.
|
|
66
|
+
*/
|
|
67
|
+
/**
|
|
68
|
+
* Returns the translated message text for a given language from `message.i18n`, or
|
|
69
|
+
* undefined if not present. Used to resolve which of the multiple translations to show.
|
|
70
|
+
*/
|
|
71
|
+
var getTranslatedMessageText = ({ language, message }) => message?.i18n?.[`${language}_text`];
|
|
72
|
+
var defaultContextValue = {
|
|
73
|
+
getTranslationView: (_messageId, hasI18n) => hasI18n ? "translated" : "original",
|
|
74
|
+
setTranslationView: () => {}
|
|
75
|
+
};
|
|
76
|
+
var MessageTranslationViewContext = (0, react.createContext)(defaultContextValue);
|
|
77
|
+
var MessageTranslationViewProvider = ({ children }) => {
|
|
78
|
+
const [viewByMessageId, setViewByMessageId] = (0, react.useState)({});
|
|
79
|
+
const setTranslationView = (0, react.useCallback)((messageId, view) => {
|
|
80
|
+
setViewByMessageId((prev) => ({
|
|
81
|
+
...prev,
|
|
82
|
+
[messageId]: view
|
|
83
|
+
}));
|
|
84
|
+
}, []);
|
|
85
|
+
const getTranslationView = (0, react.useCallback)((messageId, hasI18n) => viewByMessageId[messageId] ?? (hasI18n ? "translated" : "original"), [viewByMessageId]);
|
|
86
|
+
const stableValue = react.default.useMemo(() => ({
|
|
87
|
+
getTranslationView,
|
|
88
|
+
setTranslationView
|
|
89
|
+
}), [getTranslationView, setTranslationView]);
|
|
90
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessageTranslationViewContext.Provider, {
|
|
91
|
+
value: stableValue,
|
|
92
|
+
children
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
var useMessageTranslationViewContext = () => {
|
|
96
|
+
return (0, react.useContext)(MessageTranslationViewContext) ?? defaultContextValue;
|
|
97
|
+
};
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/context/ModalContext.tsx
|
|
100
|
+
var ModalContext = react.default.createContext(void 0);
|
|
101
|
+
var ModalContextProvider = ({ children, value }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalContext.Provider, {
|
|
102
|
+
value,
|
|
103
|
+
children
|
|
104
|
+
});
|
|
105
|
+
var useModalContext = () => {
|
|
106
|
+
const contextValue = (0, react.useContext)(ModalContext);
|
|
107
|
+
if (!contextValue) {
|
|
108
|
+
console.warn(`The useModalContext hook was called outside of the ModalContext provider. Make sure this hook is called within a child of the GlobalModal.`);
|
|
109
|
+
return { close: () => null };
|
|
110
|
+
}
|
|
111
|
+
return contextValue;
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/components/Notifications/NotificationConfigurationContext.tsx
|
|
115
|
+
var defaultNotificationDisplayFilter = () => true;
|
|
116
|
+
var defaultNotificationConfigurationContextValue = { displayFilter: defaultNotificationDisplayFilter };
|
|
117
|
+
var NotificationConfigurationContext = react.default.createContext(defaultNotificationConfigurationContextValue);
|
|
118
|
+
var NotificationConfigurationProvider = ({ children, displayFilter }) => {
|
|
119
|
+
const parentConfiguration = (0, react.useContext)(NotificationConfigurationContext);
|
|
120
|
+
const value = (0, react.useMemo)(() => ({ displayFilter: displayFilter ?? parentConfiguration.displayFilter }), [displayFilter, parentConfiguration.displayFilter]);
|
|
121
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotificationConfigurationContext.Provider, {
|
|
122
|
+
value,
|
|
123
|
+
children
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
var useNotificationConfigurationContext = () => (0, react.useContext)(NotificationConfigurationContext);
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/components/Notifications/hooks/useNotifications.ts
|
|
129
|
+
/**
|
|
130
|
+
* Subscribes to client.notifications.store and returns the list of notifications.
|
|
131
|
+
* Optionally pass a filter so only notifications that match are returned (e.g. for a specific NotificationList).
|
|
132
|
+
*/
|
|
133
|
+
var useNotifications = (options) => {
|
|
134
|
+
const { client } = require_useNotificationApi.useChatContext();
|
|
135
|
+
const { displayFilter } = useNotificationConfigurationContext();
|
|
136
|
+
const { applyDisplayFilter, fallbackPanel, filter, panel } = options ?? {};
|
|
137
|
+
const selector = (0, react.useCallback)((state) => {
|
|
138
|
+
return { notifications: state.notifications.filter((notification) => {
|
|
139
|
+
if (panel && !require_useNotificationApi.isNotificationForPanel(notification, panel, { fallbackPanel })) return false;
|
|
140
|
+
if (applyDisplayFilter && !displayFilter({
|
|
141
|
+
fallbackPanel,
|
|
142
|
+
filter,
|
|
143
|
+
notification,
|
|
144
|
+
panel
|
|
145
|
+
})) return false;
|
|
146
|
+
return filter ? filter(notification) : true;
|
|
147
|
+
}) };
|
|
148
|
+
}, [
|
|
149
|
+
applyDisplayFilter,
|
|
150
|
+
displayFilter,
|
|
151
|
+
fallbackPanel,
|
|
152
|
+
filter,
|
|
153
|
+
panel
|
|
154
|
+
]);
|
|
155
|
+
const { notifications } = require_useNotificationApi.useStateStore(client.notifications.store, selector);
|
|
156
|
+
return notifications;
|
|
157
|
+
};
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/components/Loading/LoadingIndicator.tsx
|
|
160
|
+
var LoadingIndicator = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconLoading, {
|
|
161
|
+
...props,
|
|
162
|
+
className: "str-chat__loading-indicator"
|
|
163
|
+
});
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/components/MessageComposer/hooks/utils.ts
|
|
166
|
+
function prettifyFileSize(bytes, precision = 3) {
|
|
167
|
+
const units = [
|
|
168
|
+
"B",
|
|
169
|
+
"kB",
|
|
170
|
+
"MB",
|
|
171
|
+
"GB"
|
|
172
|
+
];
|
|
173
|
+
const exponent = bytes === 0 ? 0 : Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
174
|
+
const mantissa = bytes / 1024 ** exponent;
|
|
175
|
+
return `${precision === 0 ? Math.round(mantissa).toString() : mantissa.toPrecision(precision)} ${units[exponent]}`;
|
|
176
|
+
}
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/components/Attachment/components/FileSizeIndicator.tsx
|
|
179
|
+
var FileSizeIndicator = ({ fileSize, maximumFractionDigits }) => {
|
|
180
|
+
const actualFileSize = typeof fileSize === "string" ? parseFloat(fileSize) : fileSize;
|
|
181
|
+
if (typeof actualFileSize === "undefined" || !Number.isFinite(Number(actualFileSize))) return null;
|
|
182
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
183
|
+
className: "str-chat__message-attachment-file--item-size",
|
|
184
|
+
"data-testid": "file-size-indicator",
|
|
185
|
+
children: prettifyFileSize(actualFileSize, maximumFractionDigits)
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/utils/useStableCallback.ts
|
|
190
|
+
/**
|
|
191
|
+
* A utility hook implementing a stable callback. It takes in an unstable method that
|
|
192
|
+
* is supposed to be invoked somewhere deeper in the DOM tree without making it
|
|
193
|
+
* change its reference every time the parent component rerenders. It will also return
|
|
194
|
+
* the value of the callback if it does return one.
|
|
195
|
+
* A common use-case would be having a function whose invocation depends on state
|
|
196
|
+
* somewhere high up in the DOM tree and wanting to use the same function deeper
|
|
197
|
+
* down, for example in a leaf node and simply using useCallback results in
|
|
198
|
+
* cascading dependency hell. If we wrap it in useStableCallback, we would be able
|
|
199
|
+
* to:
|
|
200
|
+
* - Use the same function as a dependency of another hook (since it is stable)
|
|
201
|
+
* - Still invoke it and get the latest state
|
|
202
|
+
*
|
|
203
|
+
* **Caveats:**
|
|
204
|
+
* - Never wrap a function that is supposed to return a React.ReactElement in
|
|
205
|
+
* useStableCallback, since React will not know that the DOM needs to be updated
|
|
206
|
+
* whenever the callback value changes (for example, renderItem from FlatList must
|
|
207
|
+
* never be wrapped in this hook)
|
|
208
|
+
* - Always prefer using a standard useCallback/stable function wherever possible
|
|
209
|
+
* (the purpose of useStableCallback is to bridge the gap between top level contexts
|
|
210
|
+
* and cascading rereders in downstream components - **not** as an escape hatch)
|
|
211
|
+
* @param callback - the callback we want to stabilize
|
|
212
|
+
*/
|
|
213
|
+
var useStableCallback = (callback) => {
|
|
214
|
+
const ref = (0, react.useRef)(callback);
|
|
215
|
+
ref.current = callback;
|
|
216
|
+
return (0, react.useCallback)((...args) => ref.current(...args), []);
|
|
217
|
+
};
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/a11y/hooks/useAriaIdentifiers.ts
|
|
220
|
+
var sanitizeAriaRootId = (rootId) => rootId?.trim().replace(/[^A-Za-z0-9:_-]/g, "-") ?? "";
|
|
221
|
+
var buildAriaIdentifier = (sanitizedRootId, descriptor) => sanitizedRootId ? `${sanitizedRootId}-${descriptor}` : void 0;
|
|
222
|
+
/**
|
|
223
|
+
* Derives stable ARIA identifier IDs from a single root ID.
|
|
224
|
+
*
|
|
225
|
+
* Use this to keep dialog/component labeling conventions consistent without
|
|
226
|
+
* manually building `*-title` and `*-description` IDs at each call site.
|
|
227
|
+
*
|
|
228
|
+
* Behavior:
|
|
229
|
+
* - Root ID is trimmed and sanitized to `[A-Za-z0-9:_-]` before use.
|
|
230
|
+
* - Returns `undefined` IDs when root ID is missing/empty after sanitization.
|
|
231
|
+
*/
|
|
232
|
+
var useAriaIdentifiers = (rootId) => {
|
|
233
|
+
const sanitizedRootId = sanitizeAriaRootId(rootId);
|
|
234
|
+
return (0, react.useMemo)(() => ({
|
|
235
|
+
descriptionId: buildAriaIdentifier(sanitizedRootId, "description"),
|
|
236
|
+
titleId: buildAriaIdentifier(sanitizedRootId, "title")
|
|
237
|
+
}), [sanitizedRootId]);
|
|
238
|
+
};
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/components/Dialog/components/Alert.tsx
|
|
241
|
+
var Root = (0, react.forwardRef)(function AlertRoot({ children, className, ...props }, ref) {
|
|
242
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
243
|
+
...props,
|
|
244
|
+
className: (0, clsx.default)("str-chat__alert-root", className),
|
|
245
|
+
ref,
|
|
246
|
+
children
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
var Header = (0, react.forwardRef)(function AlertHeader({ children, className, description, descriptionId, Icon, title, titleId, ...props }, ref) {
|
|
250
|
+
const { dialogId } = useModalContext();
|
|
251
|
+
const { descriptionId: derivedDescriptionId, titleId: derivedTitleId } = useAriaIdentifiers(dialogId);
|
|
252
|
+
const resolvedTitleId = titleId ?? derivedTitleId;
|
|
253
|
+
const resolvedDescriptionId = descriptionId ?? derivedDescriptionId;
|
|
254
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
255
|
+
...props,
|
|
256
|
+
className: (0, clsx.default)("str-chat__alert-header", className),
|
|
257
|
+
ref,
|
|
258
|
+
children: title ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
259
|
+
className: "str-chat__alert-header__copy",
|
|
260
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
261
|
+
className: "str-chat__alert-header__title",
|
|
262
|
+
id: resolvedTitleId,
|
|
263
|
+
children: title
|
|
264
|
+
}), description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
265
|
+
className: "str-chat__alert-header__description",
|
|
266
|
+
id: resolvedDescriptionId,
|
|
267
|
+
children: description
|
|
268
|
+
})]
|
|
269
|
+
})] }) : children
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
var Alert = {
|
|
273
|
+
Actions: (0, react.forwardRef)(function AlertActions({ children, className, ...props }, ref) {
|
|
274
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
275
|
+
...props,
|
|
276
|
+
className: (0, clsx.default)("str-chat__alert-actions", className),
|
|
277
|
+
ref,
|
|
278
|
+
children
|
|
279
|
+
});
|
|
280
|
+
}),
|
|
281
|
+
Header,
|
|
282
|
+
Root
|
|
283
|
+
};
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region src/components/Dialog/service/DialogAnchor.tsx
|
|
286
|
+
function useDialogAnchor({ allowFlip, offset, open, placement, referenceElement, updateKey, updatePositionOnContentResize = false }) {
|
|
287
|
+
const [popperElement, setPopperElement] = (0, react.useState)(null);
|
|
288
|
+
const [stabilisedChosenPlacement, setStabilisedChosenPlacement] = (0, react.useState)(null);
|
|
289
|
+
const { placement: chosenPlacement, refs, strategy, update, x, y } = require_useNotificationApi.usePopoverPosition({
|
|
290
|
+
allowFlip,
|
|
291
|
+
freeze: true,
|
|
292
|
+
offset,
|
|
293
|
+
placement: stabilisedChosenPlacement ?? placement
|
|
294
|
+
});
|
|
295
|
+
if (!stabilisedChosenPlacement && popperElement && placement !== chosenPlacement) setStabilisedChosenPlacement(chosenPlacement);
|
|
296
|
+
else if (stabilisedChosenPlacement && !popperElement) setStabilisedChosenPlacement(null);
|
|
297
|
+
const frozenReferenceRef = (0, react.useRef)(null);
|
|
298
|
+
if (open && referenceElement && !frozenReferenceRef.current) frozenReferenceRef.current = referenceElement;
|
|
299
|
+
if (!open) frozenReferenceRef.current = null;
|
|
300
|
+
const effectiveReference = open ? frozenReferenceRef.current : referenceElement;
|
|
301
|
+
(0, react.useEffect)(() => {
|
|
302
|
+
refs.setReference(effectiveReference);
|
|
303
|
+
}, [effectiveReference, refs]);
|
|
304
|
+
(0, react.useEffect)(() => {
|
|
305
|
+
refs.setFloating(popperElement);
|
|
306
|
+
}, [popperElement, refs]);
|
|
307
|
+
(0, react.useEffect)(() => {
|
|
308
|
+
if (open && popperElement && effectiveReference) update?.();
|
|
309
|
+
}, [
|
|
310
|
+
open,
|
|
311
|
+
placement,
|
|
312
|
+
popperElement,
|
|
313
|
+
update,
|
|
314
|
+
updateKey,
|
|
315
|
+
effectiveReference
|
|
316
|
+
]);
|
|
317
|
+
(0, react.useEffect)(() => {
|
|
318
|
+
if (!popperElement || !updatePositionOnContentResize) return;
|
|
319
|
+
const resizeObserver = new ResizeObserver(update);
|
|
320
|
+
resizeObserver.observe(popperElement);
|
|
321
|
+
return () => {
|
|
322
|
+
resizeObserver.disconnect();
|
|
323
|
+
};
|
|
324
|
+
}, [
|
|
325
|
+
popperElement,
|
|
326
|
+
update,
|
|
327
|
+
updatePositionOnContentResize
|
|
328
|
+
]);
|
|
329
|
+
if (popperElement && !open) setPopperElement(null);
|
|
330
|
+
return {
|
|
331
|
+
placement: stabilisedChosenPlacement ?? chosenPlacement,
|
|
332
|
+
setPopperElement,
|
|
333
|
+
styles: {
|
|
334
|
+
left: x ?? 0,
|
|
335
|
+
position: strategy,
|
|
336
|
+
top: y ?? 0
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
var DialogAnchor = ({ allowFlip = true, children, className, closeOnClickOutside, closeTransitionMs = 0, dialogManagerId, focus = true, id, offset, placement = "auto", referenceElement = null, tabIndex, trapFocus, updateKey, updatePositionOnContentResize, ...restDivProps }) => {
|
|
341
|
+
/**
|
|
342
|
+
* Rendering lifecycle notes:
|
|
343
|
+
* - `open=true` renders dialog contents immediately.
|
|
344
|
+
* - `open=false` can keep contents mounted for `closeTransitionMs` to allow CSS exit
|
|
345
|
+
* animations before unmount.
|
|
346
|
+
*
|
|
347
|
+
* State exposed to CSS:
|
|
348
|
+
* - `data-str-chat-dialog-state="open"` while actively open.
|
|
349
|
+
* - `data-str-chat-dialog-state="closing"` during delayed unmount window.
|
|
350
|
+
*
|
|
351
|
+
* Consumers like `ContextMenu` combine:
|
|
352
|
+
* - `data-str-chat-dialog-state` from this component, and
|
|
353
|
+
* - `data-str-chat-placement` (e.g. `top-start`, `right-end`)
|
|
354
|
+
* to select the correct closing keyframe in CSS (horizontal vs vertical roll direction).
|
|
355
|
+
* In practice, JS only toggles state and timing (`closeTransitionMs`); CSS owns the
|
|
356
|
+
* visual motion details (transform/easing), so animation behavior stays declarative.
|
|
357
|
+
*/
|
|
358
|
+
const dialog = require_useNotificationApi.useDialog({
|
|
359
|
+
closeOnClickOutside,
|
|
360
|
+
dialogManagerId,
|
|
361
|
+
id
|
|
362
|
+
});
|
|
363
|
+
const open = require_useNotificationApi.useDialogIsOpen(id, dialogManagerId);
|
|
364
|
+
const [shouldRender, setShouldRender] = (0, react.useState)(open);
|
|
365
|
+
const closeTimeoutRef = (0, react.useRef)(null);
|
|
366
|
+
const isClosing = !open && shouldRender;
|
|
367
|
+
(0, react.useEffect)(() => {
|
|
368
|
+
if (open) {
|
|
369
|
+
setShouldRender(true);
|
|
370
|
+
if (closeTimeoutRef.current) {
|
|
371
|
+
clearTimeout(closeTimeoutRef.current);
|
|
372
|
+
closeTimeoutRef.current = null;
|
|
373
|
+
}
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (!shouldRender) return;
|
|
377
|
+
if (!closeTransitionMs) {
|
|
378
|
+
setShouldRender(false);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
closeTimeoutRef.current = setTimeout(() => {
|
|
382
|
+
setShouldRender(false);
|
|
383
|
+
closeTimeoutRef.current = null;
|
|
384
|
+
}, closeTransitionMs);
|
|
385
|
+
}, [
|
|
386
|
+
closeTransitionMs,
|
|
387
|
+
open,
|
|
388
|
+
shouldRender
|
|
389
|
+
]);
|
|
390
|
+
(0, react.useEffect)(() => () => {
|
|
391
|
+
if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
|
|
392
|
+
}, []);
|
|
393
|
+
const { placement: chosenPlacement, setPopperElement, styles } = useDialogAnchor({
|
|
394
|
+
allowFlip,
|
|
395
|
+
offset,
|
|
396
|
+
open: shouldRender,
|
|
397
|
+
placement,
|
|
398
|
+
referenceElement,
|
|
399
|
+
updateKey,
|
|
400
|
+
updatePositionOnContentResize
|
|
401
|
+
});
|
|
402
|
+
(0, react.useEffect)(() => {
|
|
403
|
+
if (!open) return;
|
|
404
|
+
const hideOnEscape = (event) => {
|
|
405
|
+
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
406
|
+
dialog?.close();
|
|
407
|
+
};
|
|
408
|
+
document.addEventListener("keyup", hideOnEscape);
|
|
409
|
+
return () => {
|
|
410
|
+
document.removeEventListener("keyup", hideOnEscape);
|
|
411
|
+
};
|
|
412
|
+
}, [dialog, open]);
|
|
413
|
+
if (!shouldRender) return null;
|
|
414
|
+
const { ["aria-describedby"]: ariaDescribedBy, ["aria-label"]: ariaLabel, ["aria-labelledby"]: ariaLabelledBy, ["aria-modal"]: ariaModal, role, ...anchorDivProps } = restDivProps;
|
|
415
|
+
const resolvedRole = trapFocus ? role ?? "dialog" : role;
|
|
416
|
+
const resolvedAriaModal = trapFocus ? true : ariaModal;
|
|
417
|
+
const resolvedAriaLabel = ariaLabelledBy ? void 0 : ariaLabel;
|
|
418
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.DialogPortalEntry, {
|
|
419
|
+
dialogId: id,
|
|
420
|
+
dialogManagerId,
|
|
421
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_aria_focus.FocusScope, {
|
|
422
|
+
autoFocus: focus,
|
|
423
|
+
contain: trapFocus,
|
|
424
|
+
restoreFocus: true,
|
|
425
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
426
|
+
...anchorDivProps,
|
|
427
|
+
"aria-describedby": ariaDescribedBy,
|
|
428
|
+
"aria-label": resolvedAriaLabel,
|
|
429
|
+
"aria-labelledby": ariaLabelledBy,
|
|
430
|
+
"aria-modal": resolvedAriaModal,
|
|
431
|
+
className: (0, clsx.default)("str-chat__dialog-contents", className),
|
|
432
|
+
"data-str-chat-dialog-state": isClosing ? "closing" : "open",
|
|
433
|
+
"data-str-chat-placement": chosenPlacement,
|
|
434
|
+
"data-testid": "str-chat__dialog-contents",
|
|
435
|
+
ref: setPopperElement,
|
|
436
|
+
role: resolvedRole,
|
|
437
|
+
style: styles,
|
|
438
|
+
tabIndex: typeof tabIndex !== "undefined" ? tabIndex : 0,
|
|
439
|
+
children
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
});
|
|
443
|
+
};
|
|
444
|
+
//#endregion
|
|
445
|
+
//#region src/components/Avatar/Avatar.tsx
|
|
446
|
+
var getInitials = (name) => {
|
|
447
|
+
const regex = /(\p{L}{1})\p{L}+/gu;
|
|
448
|
+
if (!name || name.trim().length === 0) return "";
|
|
449
|
+
const initials = Array.from(name?.matchAll(regex) || []);
|
|
450
|
+
if (!initials.length) return "";
|
|
451
|
+
return `${initials.at(0)[1]}${initials.length > 1 ? initials.at(-1)[1] : ""}`;
|
|
452
|
+
};
|
|
453
|
+
/**
|
|
454
|
+
* A round avatar image with fallback to username's first letter
|
|
455
|
+
*/
|
|
456
|
+
var Avatar = ({ className, FallbackIcon = require_useNotificationApi.IconUser, imageUrl, isOnline, size, userName, ...rest }) => {
|
|
457
|
+
const [error, setError] = (0, react.useState)(false);
|
|
458
|
+
(0, react.useEffect)(() => () => setError(false), [imageUrl]);
|
|
459
|
+
const nameString = userName?.toString() || "";
|
|
460
|
+
const avatarImageAlt = nameString.trim();
|
|
461
|
+
const sizeAwareInitials = (0, react.useMemo)(() => {
|
|
462
|
+
const initials = getInitials(nameString);
|
|
463
|
+
if (size === "sm" || size === "xs") return initials.charAt(0);
|
|
464
|
+
return initials;
|
|
465
|
+
}, [nameString, size]);
|
|
466
|
+
const showImage = typeof imageUrl === "string" && imageUrl && !error;
|
|
467
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
468
|
+
className: (0, clsx.default)(`str-chat__avatar`, className, {
|
|
469
|
+
"str-chat__avatar--multiple-letters": sizeAwareInitials.length > 1,
|
|
470
|
+
"str-chat__avatar--no-letters": !sizeAwareInitials.length,
|
|
471
|
+
"str-chat__avatar--one-letter": sizeAwareInitials.length === 1,
|
|
472
|
+
[`str-chat__avatar--size-${size}`]: typeof size === "string"
|
|
473
|
+
}),
|
|
474
|
+
"data-testid": "avatar",
|
|
475
|
+
role: "button",
|
|
476
|
+
title: userName,
|
|
477
|
+
...rest,
|
|
478
|
+
children: [typeof isOnline === "boolean" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: (0, clsx.default)("str-chat__avatar-status-badge", {
|
|
479
|
+
"str-chat__avatar-status-badge--offline": !isOnline,
|
|
480
|
+
"str-chat__avatar-status-badge--online": isOnline
|
|
481
|
+
}) }), showImage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
482
|
+
alt: avatarImageAlt,
|
|
483
|
+
className: "str-chat__avatar-image",
|
|
484
|
+
"data-testid": "avatar-img",
|
|
485
|
+
onError: () => setError(true),
|
|
486
|
+
src: imageUrl
|
|
487
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!!sizeAwareInitials.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
488
|
+
className: "str-chat__avatar-initials",
|
|
489
|
+
"data-testid": "avatar-fallback",
|
|
490
|
+
children: sizeAwareInitials
|
|
491
|
+
}), !sizeAwareInitials.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FallbackIcon, {})] })]
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
//#endregion
|
|
495
|
+
//#region src/components/Badge/Badge.tsx
|
|
496
|
+
/**
|
|
497
|
+
* Compact pill/circle badge for counts and labels.
|
|
498
|
+
* Uses design tokens: --badge-bg-*, --badge-text-*, --badge-border.
|
|
499
|
+
*/
|
|
500
|
+
var Badge = ({ children, className, size = "md", variant = "default", ...spanProps }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
501
|
+
...spanProps,
|
|
502
|
+
className: (0, clsx.default)("str-chat__badge", `str-chat__badge--variant-${variant}`, { [`str-chat__badge--size-${size}`]: size }, className),
|
|
503
|
+
children
|
|
504
|
+
});
|
|
505
|
+
var ErrorBadge = ({ className, size = "sm", ...rest }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
506
|
+
...rest,
|
|
507
|
+
className,
|
|
508
|
+
size,
|
|
509
|
+
variant: "error",
|
|
510
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconExclamationMarkFill, {})
|
|
511
|
+
});
|
|
512
|
+
//#endregion
|
|
513
|
+
//#region src/components/Avatar/ChannelAvatar.tsx
|
|
514
|
+
var ChannelAvatar = ({ displayMembers, imageUrl, size, userName, ...sharedProps }) => {
|
|
515
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupAvatar, {
|
|
516
|
+
displayMembers: (0, react.useMemo)(() => {
|
|
517
|
+
if (!imageUrl && displayMembers && displayMembers.length > 0) return displayMembers;
|
|
518
|
+
return [{
|
|
519
|
+
imageUrl,
|
|
520
|
+
userName
|
|
521
|
+
}];
|
|
522
|
+
}, [
|
|
523
|
+
displayMembers,
|
|
524
|
+
imageUrl,
|
|
525
|
+
userName
|
|
526
|
+
]),
|
|
527
|
+
size,
|
|
528
|
+
...sharedProps
|
|
529
|
+
});
|
|
530
|
+
};
|
|
531
|
+
//#endregion
|
|
532
|
+
//#region src/components/Avatar/GroupAvatar.tsx
|
|
533
|
+
/**
|
|
534
|
+
* Avatar component to display multiple users' avatars in a group.
|
|
535
|
+
* Renders a single Avatar if fewer than 2 members. Otherwise, renders up to 2 avatars (when overflowCount is set) or 4, plus an optional +N badge.
|
|
536
|
+
*/
|
|
537
|
+
var GroupAvatar = ({ badgeSize, className, displayMembers = [], isOnline, size, ...rest }) => {
|
|
538
|
+
const displayMembersToRender = (0, react.useMemo)(() => displayMembers.length > 4 ? displayMembers.slice(0, 2) : displayMembers, [displayMembers]);
|
|
539
|
+
const overflowCount = displayMembers.length - displayMembersToRender.length;
|
|
540
|
+
if (displayMembers.length < 2) {
|
|
541
|
+
const firstUser = displayMembers[0];
|
|
542
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Avatar, {
|
|
543
|
+
imageUrl: firstUser?.imageUrl,
|
|
544
|
+
isOnline,
|
|
545
|
+
size,
|
|
546
|
+
userName: firstUser?.userName,
|
|
547
|
+
...rest
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
let avatarSize = null;
|
|
551
|
+
if (size === "2xl") avatarSize = "lg";
|
|
552
|
+
else if (size === "xl") avatarSize = "md";
|
|
553
|
+
else if (size === "lg") avatarSize = "sm";
|
|
554
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
555
|
+
className: (0, clsx.default)("str-chat__avatar-group", {
|
|
556
|
+
"str-chat__avatar-group--offline": typeof isOnline === "boolean" && !isOnline,
|
|
557
|
+
"str-chat__avatar-group--online": typeof isOnline === "boolean" && isOnline,
|
|
558
|
+
[`str-chat__avatar-group--size-${size}`]: typeof size === "string"
|
|
559
|
+
}, className),
|
|
560
|
+
"data-testid": "group-avatar",
|
|
561
|
+
role: "button",
|
|
562
|
+
...rest,
|
|
563
|
+
children: [displayMembersToRender.map(({ id, imageUrl, userName }, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Avatar, {
|
|
564
|
+
imageUrl,
|
|
565
|
+
size: avatarSize,
|
|
566
|
+
userName
|
|
567
|
+
}, id || `${userName}-${imageUrl}-${index}`)), typeof overflowCount === "number" && overflowCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Badge, {
|
|
568
|
+
className: "str-chat__avatar-group__count-badge",
|
|
569
|
+
"data-testid": "group-avatar-count-badge",
|
|
570
|
+
size: badgeSize,
|
|
571
|
+
variant: "counter",
|
|
572
|
+
children: ["+", overflowCount]
|
|
573
|
+
})]
|
|
574
|
+
});
|
|
575
|
+
};
|
|
576
|
+
//#endregion
|
|
577
|
+
//#region src/a11y/a11yUtils.ts
|
|
578
|
+
var MENU_KEYBOARD_NAVIGATION_KEYS = [
|
|
579
|
+
"ArrowDown",
|
|
580
|
+
"ArrowUp",
|
|
581
|
+
"End",
|
|
582
|
+
"Home"
|
|
583
|
+
];
|
|
584
|
+
var isMenuKeyboardNavigationKey = (key) => MENU_KEYBOARD_NAVIGATION_KEYS.includes(key);
|
|
585
|
+
var getNextRovingFocusIndex = ({ activeIndex, itemCount, key }) => {
|
|
586
|
+
if (itemCount <= 0 || !isMenuKeyboardNavigationKey(key)) return null;
|
|
587
|
+
const lastIndex = itemCount - 1;
|
|
588
|
+
if (key === "Home") return 0;
|
|
589
|
+
if (key === "End") return lastIndex;
|
|
590
|
+
if (activeIndex === -1) return key === "ArrowUp" ? lastIndex : 0;
|
|
591
|
+
if (key === "ArrowUp") return activeIndex <= 0 ? lastIndex : activeIndex - 1;
|
|
592
|
+
return activeIndex >= lastIndex ? 0 : activeIndex + 1;
|
|
593
|
+
};
|
|
594
|
+
var getDefaultActiveIndex = (items) => {
|
|
595
|
+
const activeElement = document.activeElement;
|
|
596
|
+
if (!(activeElement instanceof Element)) return -1;
|
|
597
|
+
return items.findIndex((item) => item instanceof Element && item === activeElement);
|
|
598
|
+
};
|
|
599
|
+
var createRovingFocusKeyDownHandler = ({ focusItem = (item) => item.focus(), getActiveIndex = (items) => getDefaultActiveIndex(items), getItems }) => {
|
|
600
|
+
const handleKeyDown = (event) => {
|
|
601
|
+
const items = getItems(event);
|
|
602
|
+
const nextIndex = getNextRovingFocusIndex({
|
|
603
|
+
activeIndex: getActiveIndex(items, event),
|
|
604
|
+
itemCount: items.length,
|
|
605
|
+
key: event.key
|
|
606
|
+
});
|
|
607
|
+
if (nextIndex === null) return;
|
|
608
|
+
event.preventDefault();
|
|
609
|
+
const nextItem = items[nextIndex];
|
|
610
|
+
if (!nextItem) return;
|
|
611
|
+
focusItem(nextItem, event);
|
|
612
|
+
};
|
|
613
|
+
return handleKeyDown;
|
|
614
|
+
};
|
|
615
|
+
//#endregion
|
|
616
|
+
//#region src/components/Dialog/components/ContextMenu.tsx
|
|
617
|
+
var BaseContextMenuButton = ({ children, className, details, hasSubMenu, Icon, label, role = "menuitem", SubmenuIcon = require_useNotificationApi.IconChevronRight, variant, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
618
|
+
...props,
|
|
619
|
+
className: (0, clsx.default)("str-chat__context-menu__button", {
|
|
620
|
+
"str-chat__context-menu__button--with-submenu": hasSubMenu,
|
|
621
|
+
[`str-chat__context-menu__button--${variant}`]: typeof variant === "string"
|
|
622
|
+
}, className),
|
|
623
|
+
role,
|
|
624
|
+
type: "button",
|
|
625
|
+
children: [
|
|
626
|
+
Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "str-chat__context-menu__button__icon" }),
|
|
627
|
+
label ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
628
|
+
className: "str-chat__context-menu__button__label",
|
|
629
|
+
children: label
|
|
630
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
631
|
+
className: "str-chat__context-menu__button__details",
|
|
632
|
+
children: details
|
|
633
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
634
|
+
className: "str-chat__context-menu__button__label",
|
|
635
|
+
children
|
|
636
|
+
}),
|
|
637
|
+
!!hasSubMenu && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubmenuIcon, { className: "str-chat__context-menu__button__submenu-icon" })
|
|
638
|
+
]
|
|
639
|
+
});
|
|
640
|
+
var UserContextMenuButton = ({ children, className, imageUrl, role = "menuitem", userName, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
641
|
+
...props,
|
|
642
|
+
className: (0, clsx.default)("str-chat__context-menu__button str-chat__user-context-menu__button", className),
|
|
643
|
+
role,
|
|
644
|
+
type: "button",
|
|
645
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Avatar, {
|
|
646
|
+
imageUrl,
|
|
647
|
+
size: "sm",
|
|
648
|
+
userName
|
|
649
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
650
|
+
className: "str-chat__context-menu__button__label",
|
|
651
|
+
children: children ?? userName
|
|
652
|
+
})]
|
|
653
|
+
});
|
|
654
|
+
var EmojiContextMenuButton = ({ children, className, emoji, label, role = "menuitem", ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
655
|
+
...props,
|
|
656
|
+
className: (0, clsx.default)("str-chat__context-menu__button str-chat__emoji-context-menu__button", className),
|
|
657
|
+
role,
|
|
658
|
+
type: "button",
|
|
659
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
660
|
+
className: "str-chat__context-menu__button__emoji str-chat__emoji-item--entity",
|
|
661
|
+
children: emoji
|
|
662
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
663
|
+
className: "str-chat__context-menu__button__label",
|
|
664
|
+
children: children ?? label
|
|
665
|
+
})]
|
|
666
|
+
});
|
|
667
|
+
var ContextMenuButtonWithSubmenu = ({ children, className, Submenu, submenuContainerProps, submenuPlacement = "right-start", submenuRollAxis = "x", ...buttonProps }) => {
|
|
668
|
+
const { className: submenuClassName, ...submenuContainerRestProps } = submenuContainerProps ?? {};
|
|
669
|
+
const { registerDialogSubmenu, unregisterDialogSubmenu } = useContextMenuContext();
|
|
670
|
+
const buttonRef = (0, react.useRef)(null);
|
|
671
|
+
const [dialogContainer, setDialogContainer] = (0, react.useState)(null);
|
|
672
|
+
const keepSubmenuOpenFlag = (0, react.useRef)(false);
|
|
673
|
+
const dialogCloseTimeout = (0, react.useRef)(null);
|
|
674
|
+
const dialogId = (0, react.useMemo)(() => `submenu-${Math.random().toString(36).slice(2)}`, []);
|
|
675
|
+
const { dialog, dialogManager } = require_useNotificationApi.useDialogOnNearestManager({ id: dialogId });
|
|
676
|
+
const dialogIsOpen = require_useNotificationApi.useDialogIsOpen(dialogId, dialogManager?.id);
|
|
677
|
+
(0, react.useEffect)(() => {
|
|
678
|
+
if (!dialogIsOpen) return;
|
|
679
|
+
registerDialogSubmenu();
|
|
680
|
+
return () => unregisterDialogSubmenu();
|
|
681
|
+
}, [
|
|
682
|
+
dialogIsOpen,
|
|
683
|
+
registerDialogSubmenu,
|
|
684
|
+
unregisterDialogSubmenu
|
|
685
|
+
]);
|
|
686
|
+
const { placement: chosenPlacement, setPopperElement, styles } = useDialogAnchor({
|
|
687
|
+
offset: 8,
|
|
688
|
+
open: dialogIsOpen,
|
|
689
|
+
placement: submenuPlacement,
|
|
690
|
+
referenceElement: buttonRef.current
|
|
691
|
+
});
|
|
692
|
+
const closeDialogLazily = (0, react.useCallback)(() => {
|
|
693
|
+
if (dialogCloseTimeout.current) clearTimeout(dialogCloseTimeout.current);
|
|
694
|
+
dialogCloseTimeout.current = setTimeout(() => {
|
|
695
|
+
if (keepSubmenuOpenFlag.current) return;
|
|
696
|
+
dialog.close();
|
|
697
|
+
}, 100);
|
|
698
|
+
}, [dialog]);
|
|
699
|
+
const keepSubmenuOpen = (0, react.useCallback)(() => {
|
|
700
|
+
keepSubmenuOpenFlag.current = true;
|
|
701
|
+
}, []);
|
|
702
|
+
const allowToCloseSubmenu = (0, react.useCallback)(() => {
|
|
703
|
+
keepSubmenuOpenFlag.current = false;
|
|
704
|
+
}, []);
|
|
705
|
+
const closeSubmenu = (0, react.useCallback)(() => {
|
|
706
|
+
allowToCloseSubmenu();
|
|
707
|
+
closeDialogLazily();
|
|
708
|
+
}, [allowToCloseSubmenu, closeDialogLazily]);
|
|
709
|
+
const handleClose = (0, react.useCallback)((event) => {
|
|
710
|
+
const parentButton = buttonRef.current;
|
|
711
|
+
if (!dialogIsOpen || !parentButton) return;
|
|
712
|
+
event.stopPropagation();
|
|
713
|
+
closeDialogLazily();
|
|
714
|
+
parentButton.focus();
|
|
715
|
+
}, [
|
|
716
|
+
closeDialogLazily,
|
|
717
|
+
dialogIsOpen,
|
|
718
|
+
buttonRef
|
|
719
|
+
]);
|
|
720
|
+
const handleFocusParentButton = () => {
|
|
721
|
+
if (dialogIsOpen) return;
|
|
722
|
+
dialog.open();
|
|
723
|
+
keepSubmenuOpen();
|
|
724
|
+
};
|
|
725
|
+
(0, react.useEffect)(() => {
|
|
726
|
+
const parentButton = buttonRef.current;
|
|
727
|
+
if (!dialogIsOpen || !parentButton) return;
|
|
728
|
+
const hideOnEscape = (event) => {
|
|
729
|
+
if (event.key !== "Escape") return;
|
|
730
|
+
handleClose(event);
|
|
731
|
+
closeSubmenu();
|
|
732
|
+
};
|
|
733
|
+
document.addEventListener("keyup", hideOnEscape, { capture: true });
|
|
734
|
+
return () => {
|
|
735
|
+
document.removeEventListener("keyup", hideOnEscape, { capture: true });
|
|
736
|
+
};
|
|
737
|
+
}, [
|
|
738
|
+
dialogIsOpen,
|
|
739
|
+
handleClose,
|
|
740
|
+
closeSubmenu
|
|
741
|
+
]);
|
|
742
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(BaseContextMenuButton, {
|
|
743
|
+
"aria-expanded": dialogIsOpen,
|
|
744
|
+
"aria-haspopup": "menu",
|
|
745
|
+
className: (0, clsx.default)(className, "str_chat__button-with-submenu", { "str_chat__button-with-submenu--submenu-open": dialogIsOpen }),
|
|
746
|
+
hasSubMenu: true,
|
|
747
|
+
onBlur: closeSubmenu,
|
|
748
|
+
onClick: (event) => {
|
|
749
|
+
event.stopPropagation();
|
|
750
|
+
dialog.toggle();
|
|
751
|
+
},
|
|
752
|
+
onFocus: handleFocusParentButton,
|
|
753
|
+
onMouseEnter: handleFocusParentButton,
|
|
754
|
+
onMouseLeave: closeSubmenu,
|
|
755
|
+
...buttonProps,
|
|
756
|
+
ref: buttonRef,
|
|
757
|
+
children
|
|
758
|
+
}), dialogIsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
759
|
+
className: (0, clsx.default)("str-chat__context-menu__submenu-container", submenuClassName),
|
|
760
|
+
"data-str-chat-placement": chosenPlacement,
|
|
761
|
+
"data-str-chat-roll-axis": submenuRollAxis,
|
|
762
|
+
onBlur: (event) => {
|
|
763
|
+
if (event.relatedTarget instanceof Node && dialogContainer?.contains(event.relatedTarget)) return;
|
|
764
|
+
closeSubmenu();
|
|
765
|
+
},
|
|
766
|
+
onFocus: keepSubmenuOpen,
|
|
767
|
+
onMouseEnter: keepSubmenuOpen,
|
|
768
|
+
onMouseLeave: closeSubmenu,
|
|
769
|
+
ref: (element) => {
|
|
770
|
+
setPopperElement(element);
|
|
771
|
+
setDialogContainer(element);
|
|
772
|
+
},
|
|
773
|
+
style: styles,
|
|
774
|
+
tabIndex: -1,
|
|
775
|
+
...submenuContainerRestProps,
|
|
776
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Submenu, {})
|
|
777
|
+
})] });
|
|
778
|
+
};
|
|
779
|
+
var ContextMenuButton = (props) => {
|
|
780
|
+
const { Submenu, submenuContainerProps, submenuPlacement, submenuRollAxis, ...buttonProps } = props;
|
|
781
|
+
if (Submenu) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextMenuButtonWithSubmenu, {
|
|
782
|
+
...buttonProps,
|
|
783
|
+
Submenu,
|
|
784
|
+
submenuContainerProps,
|
|
785
|
+
submenuPlacement,
|
|
786
|
+
submenuRollAxis
|
|
787
|
+
});
|
|
788
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BaseContextMenuButton, { ...buttonProps });
|
|
789
|
+
};
|
|
790
|
+
var ContextMenuBackButton = ({ children, className, role = "menuitem", ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
791
|
+
...props,
|
|
792
|
+
className: (0, clsx.default)("str-chat__context-menu__back-button", className),
|
|
793
|
+
role,
|
|
794
|
+
type: "button",
|
|
795
|
+
children
|
|
796
|
+
});
|
|
797
|
+
var ContextMenuHeader = ({ children, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
798
|
+
...props,
|
|
799
|
+
className: (0, clsx.default)("str-chat__context-menu__header", className),
|
|
800
|
+
children
|
|
801
|
+
});
|
|
802
|
+
var ContextMenuBody = ({ children, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
803
|
+
...props,
|
|
804
|
+
className: (0, clsx.default)("str-chat__context-menu__body", className),
|
|
805
|
+
children
|
|
806
|
+
});
|
|
807
|
+
var ContextMenuRoot = react.default.forwardRef(function ContextMenuRoot({ className, role = "menu", ...props }, ref) {
|
|
808
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
809
|
+
...props,
|
|
810
|
+
className: (0, clsx.default)("str-chat__context-menu", className),
|
|
811
|
+
ref,
|
|
812
|
+
role
|
|
813
|
+
});
|
|
814
|
+
});
|
|
815
|
+
var DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR = [
|
|
816
|
+
"[role=\"menuitem\"]:not(:disabled)",
|
|
817
|
+
"[role=\"menuitemradio\"]:not(:disabled)",
|
|
818
|
+
"[role=\"menuitemcheckbox\"]:not(:disabled)"
|
|
819
|
+
].join(",");
|
|
820
|
+
var isVisibleContextMenuKeyboardNavigationItem = (item) => {
|
|
821
|
+
if (item.offsetParent !== null || item.offsetHeight > 0) return true;
|
|
822
|
+
if (item.hidden) return false;
|
|
823
|
+
if (item.style.display === "none") return false;
|
|
824
|
+
return true;
|
|
825
|
+
};
|
|
826
|
+
var getVisibleContextMenuKeyboardNavigationItems = (contextMenuRoot, itemSelector = DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR) => Array.from(contextMenuRoot?.querySelectorAll(itemSelector) ?? []).filter(isVisibleContextMenuKeyboardNavigationItem);
|
|
827
|
+
var createContextMenuFocusRestoreRequest = ({ contextMenuRoot, focusReturnTarget }) => {
|
|
828
|
+
const target = focusReturnTarget ?? (document.activeElement instanceof HTMLElement ? document.activeElement : null);
|
|
829
|
+
if (!target) return {
|
|
830
|
+
index: -1,
|
|
831
|
+
target: null
|
|
832
|
+
};
|
|
833
|
+
return {
|
|
834
|
+
index: getVisibleContextMenuKeyboardNavigationItems(contextMenuRoot).findIndex((menuItem) => menuItem === target),
|
|
835
|
+
target
|
|
836
|
+
};
|
|
837
|
+
};
|
|
838
|
+
var resolveContextMenuFocusRestoreTarget = ({ contextMenuRoot, request }) => {
|
|
839
|
+
if (!request) return null;
|
|
840
|
+
if (request.target?.isConnected) return request.target;
|
|
841
|
+
if (request.index >= 0) return getVisibleContextMenuKeyboardNavigationItems(contextMenuRoot)[request.index] ?? null;
|
|
842
|
+
return null;
|
|
843
|
+
};
|
|
844
|
+
var ContextMenuContext = react.default.createContext(void 0);
|
|
845
|
+
var useContextMenuContext = () => (0, react.useContext)(ContextMenuContext);
|
|
846
|
+
/**
|
|
847
|
+
* Internal/default content renderer for {@link ContextMenu}.
|
|
848
|
+
*
|
|
849
|
+
* Override this through `ComponentContext.ContextMenuContent` when you need to
|
|
850
|
+
* customize submenu/back navigation behavior while keeping the same anchor/focus
|
|
851
|
+
* handling from `ContextMenu`.
|
|
852
|
+
*/
|
|
853
|
+
function ContextMenuContent({ anchorReferenceElement, backLabel = "Back", children, className, enableAnimations = true, Header, items, ItemsWrapper, keyboardNavigation, menuClassName, onClose, onMenuLevelChange, transitionDirection, ...props }) {
|
|
854
|
+
const rootLevel = (0, react.useMemo)(() => ({
|
|
855
|
+
Header,
|
|
856
|
+
items,
|
|
857
|
+
ItemsWrapper,
|
|
858
|
+
menuClassName
|
|
859
|
+
}), [
|
|
860
|
+
Header,
|
|
861
|
+
items,
|
|
862
|
+
ItemsWrapper,
|
|
863
|
+
menuClassName
|
|
864
|
+
]);
|
|
865
|
+
const [menuStack, setMenuStack] = (0, react.useState)(() => [rootLevel]);
|
|
866
|
+
const [menuBodyAnimationKey, setMenuBodyAnimationKey] = (0, react.useState)(0);
|
|
867
|
+
const contextMenuRootRef = (0, react.useRef)(null);
|
|
868
|
+
const focusRestoreRequestRef = (0, react.useRef)(null);
|
|
869
|
+
const activeMenu = menuStack[menuStack.length - 1];
|
|
870
|
+
const ActiveMenuItemsWrapper = activeMenu.ItemsWrapper ?? react.default.Fragment;
|
|
871
|
+
const closeMenu = (0, react.useCallback)(() => {
|
|
872
|
+
onClose?.();
|
|
873
|
+
}, [onClose]);
|
|
874
|
+
const openSubmenu = (0, react.useCallback)(({ focusReturnTarget, Header, ItemsWrapper: SubmenuItemsWrapper, menuClassName, Submenu }) => {
|
|
875
|
+
const nextLevel = {
|
|
876
|
+
focusRestoreRequest: createContextMenuFocusRestoreRequest({
|
|
877
|
+
contextMenuRoot: contextMenuRootRef.current,
|
|
878
|
+
focusReturnTarget
|
|
879
|
+
}),
|
|
880
|
+
Header,
|
|
881
|
+
ItemsWrapper: SubmenuItemsWrapper ?? ItemsWrapper,
|
|
882
|
+
menuClassName,
|
|
883
|
+
Submenu
|
|
884
|
+
};
|
|
885
|
+
setMenuStack((current) => [...current, nextLevel]);
|
|
886
|
+
}, [ItemsWrapper]);
|
|
887
|
+
const returnToParentMenu = (0, react.useCallback)(() => {
|
|
888
|
+
setMenuStack((current) => {
|
|
889
|
+
if (current.length <= 1) return current;
|
|
890
|
+
focusRestoreRequestRef.current = current[current.length - 1]?.focusRestoreRequest ?? null;
|
|
891
|
+
return current.slice(0, -1);
|
|
892
|
+
});
|
|
893
|
+
}, []);
|
|
894
|
+
(0, react.useEffect)(() => {
|
|
895
|
+
setMenuStack((current) => {
|
|
896
|
+
if (current.length === 1 && current[0] === rootLevel) return current;
|
|
897
|
+
return [rootLevel];
|
|
898
|
+
});
|
|
899
|
+
}, [rootLevel]);
|
|
900
|
+
(0, react.useEffect)(() => {
|
|
901
|
+
onMenuLevelChange?.(menuStack.length);
|
|
902
|
+
}, [menuStack.length, onMenuLevelChange]);
|
|
903
|
+
(0, react.useEffect)(() => {
|
|
904
|
+
const focusRestoreRequest = focusRestoreRequestRef.current;
|
|
905
|
+
if (!focusRestoreRequest) return;
|
|
906
|
+
focusRestoreRequestRef.current = null;
|
|
907
|
+
requestAnimationFrame(() => {
|
|
908
|
+
resolveContextMenuFocusRestoreTarget({
|
|
909
|
+
contextMenuRoot: contextMenuRootRef.current,
|
|
910
|
+
request: focusRestoreRequest
|
|
911
|
+
})?.focus();
|
|
912
|
+
});
|
|
913
|
+
}, [menuStack.length]);
|
|
914
|
+
(0, react.useEffect)(() => {
|
|
915
|
+
if (!transitionDirection) return;
|
|
916
|
+
setMenuBodyAnimationKey((value) => value + 1);
|
|
917
|
+
}, [transitionDirection, menuStack.length]);
|
|
918
|
+
const dialogSubmenuOpenCountRef = (0, react.useRef)(0);
|
|
919
|
+
const registerDialogSubmenu = (0, react.useCallback)(() => {
|
|
920
|
+
dialogSubmenuOpenCountRef.current += 1;
|
|
921
|
+
}, []);
|
|
922
|
+
const unregisterDialogSubmenu = (0, react.useCallback)(() => {
|
|
923
|
+
dialogSubmenuOpenCountRef.current = Math.max(0, dialogSubmenuOpenCountRef.current - 1);
|
|
924
|
+
}, []);
|
|
925
|
+
const rovingFocusKeyDownHandler = (0, react.useMemo)(() => {
|
|
926
|
+
const itemSelector = keyboardNavigation?.itemSelector ?? DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR;
|
|
927
|
+
return createRovingFocusKeyDownHandler({ getItems: (event) => getVisibleContextMenuKeyboardNavigationItems(event.currentTarget, itemSelector) });
|
|
928
|
+
}, [keyboardNavigation]);
|
|
929
|
+
const escapeConsumedRef = (0, react.useRef)(false);
|
|
930
|
+
const keyboardNavigationHandler = (0, react.useCallback)((event) => {
|
|
931
|
+
if (event.key === "Escape") {
|
|
932
|
+
if (dialogSubmenuOpenCountRef.current > 0) return;
|
|
933
|
+
event.preventDefault();
|
|
934
|
+
event.stopPropagation();
|
|
935
|
+
if (menuStack.length > 1) {
|
|
936
|
+
escapeConsumedRef.current = true;
|
|
937
|
+
returnToParentMenu();
|
|
938
|
+
} else closeMenu();
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
rovingFocusKeyDownHandler(event);
|
|
942
|
+
}, [
|
|
943
|
+
closeMenu,
|
|
944
|
+
menuStack.length,
|
|
945
|
+
returnToParentMenu,
|
|
946
|
+
rovingFocusKeyDownHandler
|
|
947
|
+
]);
|
|
948
|
+
const suppressEscapeKeyUp = (0, react.useCallback)((event) => {
|
|
949
|
+
if (event.key === "Escape" && escapeConsumedRef.current) {
|
|
950
|
+
escapeConsumedRef.current = false;
|
|
951
|
+
event.stopPropagation();
|
|
952
|
+
}
|
|
953
|
+
}, []);
|
|
954
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextMenuContext.Provider, {
|
|
955
|
+
value: {
|
|
956
|
+
anchorReferenceElement,
|
|
957
|
+
closeMenu,
|
|
958
|
+
openSubmenu,
|
|
959
|
+
registerDialogSubmenu,
|
|
960
|
+
returnToParentMenu,
|
|
961
|
+
unregisterDialogSubmenu
|
|
962
|
+
},
|
|
963
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ContextMenuRoot, {
|
|
964
|
+
className: (0, clsx.default)(className, activeMenu.menuClassName),
|
|
965
|
+
"data-str-chat-enable-animations": enableAnimations,
|
|
966
|
+
onKeyDownCapture: keyboardNavigationHandler,
|
|
967
|
+
onKeyUpCapture: suppressEscapeKeyUp,
|
|
968
|
+
ref: contextMenuRootRef,
|
|
969
|
+
...props,
|
|
970
|
+
children: [activeMenu.Header ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(activeMenu.Header, {}) : menuStack.length > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextMenuHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ContextMenuBackButton, {
|
|
971
|
+
onClick: returnToParentMenu,
|
|
972
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconChevronLeft, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: backLabel })]
|
|
973
|
+
}) }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextMenuBody, {
|
|
974
|
+
className: (0, clsx.default)({
|
|
975
|
+
"str-chat__context-menu__body--submenu-backward": transitionDirection === "backward",
|
|
976
|
+
"str-chat__context-menu__body--submenu-forward": transitionDirection === "forward"
|
|
977
|
+
}),
|
|
978
|
+
children: activeMenu.Submenu ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(activeMenu.Submenu, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActiveMenuItemsWrapper, { children: typeof children !== "undefined" ? children : activeMenu.items?.map((Item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Item, {}, `context-menu-item-${index}`)) })
|
|
979
|
+
}, `context-menu-body-${menuStack.length}-${menuBodyAnimationKey}`)]
|
|
980
|
+
})
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Contextual actions menu that can be used in two modes:
|
|
985
|
+
*
|
|
986
|
+
* - Anchored dialog mode: pass `id` + `referenceElement` (submenu-aware positioning).
|
|
987
|
+
* - Inline mode: omit `id` and render a plain contextual list.
|
|
988
|
+
*
|
|
989
|
+
* Customization via `ComponentContext`:
|
|
990
|
+
*
|
|
991
|
+
* - `ContextMenu`: replace the whole menu container/behavior.
|
|
992
|
+
* - `ContextMenuContent`: keep default container behavior but customize menu content
|
|
993
|
+
* rendering (items, submenu transitions, back navigation UI).
|
|
994
|
+
* - To customize outside-click dismissal via `ComponentContext`, provide a custom
|
|
995
|
+
* `ContextMenu` that sets `closeOnClickOutside`:
|
|
996
|
+
*
|
|
997
|
+
* ```tsx
|
|
998
|
+
* const CustomContextMenu = (props: ContextMenuProps) => (
|
|
999
|
+
* <ContextMenu {...props} closeOnClickOutside={false} />
|
|
1000
|
+
* );
|
|
1001
|
+
*
|
|
1002
|
+
* <ComponentProvider value={{ ContextMenu: CustomContextMenu }}>
|
|
1003
|
+
* <Chat client={client}>{children}</Chat>
|
|
1004
|
+
* </ComponentProvider>
|
|
1005
|
+
* ```
|
|
1006
|
+
*
|
|
1007
|
+
* Example:
|
|
1008
|
+
* ```tsx
|
|
1009
|
+
* <ComponentProvider
|
|
1010
|
+
* value={{
|
|
1011
|
+
* ContextMenu: MyContextMenu,
|
|
1012
|
+
* ContextMenuContent: MyContextMenuContent,
|
|
1013
|
+
* }}
|
|
1014
|
+
* >
|
|
1015
|
+
* <Chat client={client}>{children}</Chat>
|
|
1016
|
+
* </ComponentProvider>
|
|
1017
|
+
* ```
|
|
1018
|
+
*/
|
|
1019
|
+
var ContextMenu = (props) => {
|
|
1020
|
+
const { ContextMenuContent: ContextMenuContentComponent = ContextMenuContent } = require_useNotificationApi.useComponentContext();
|
|
1021
|
+
const { allowFlip, closeOnClickOutside, closeTransitionMs = 130, dialogManagerId, focus, id, offset = 8, onMenuLevelChange: onMenuLevelChangeProp, placement, referenceElement, submenuTransitionDurationMs, tabIndex, trapFocus, ...menuProps } = props;
|
|
1022
|
+
const resolvedSubmenuTransitionDurationMs = submenuTransitionDurationMs ?? 460;
|
|
1023
|
+
const isAnchored = id != null;
|
|
1024
|
+
const [menuLevel, setMenuLevel] = (0, react.useState)(1);
|
|
1025
|
+
const [transitionDirection, setTransitionDirection] = (0, react.useState)(void 0);
|
|
1026
|
+
const [contentResetToken, setContentResetToken] = (0, react.useState)(0);
|
|
1027
|
+
const transitionTimeoutRef = (0, react.useRef)(null);
|
|
1028
|
+
const previousMenuLevelRef = (0, react.useRef)(1);
|
|
1029
|
+
const open = require_useNotificationApi.useDialogIsOpen(id ?? "", dialogManagerId);
|
|
1030
|
+
const previousOpenRef = (0, react.useRef)(open);
|
|
1031
|
+
(0, react.useEffect)(() => {
|
|
1032
|
+
if (!isAnchored) return;
|
|
1033
|
+
if (previousOpenRef.current && !open) {
|
|
1034
|
+
setMenuLevel(1);
|
|
1035
|
+
setTransitionDirection(void 0);
|
|
1036
|
+
setContentResetToken((value) => value + 1);
|
|
1037
|
+
previousMenuLevelRef.current = 1;
|
|
1038
|
+
if (transitionTimeoutRef.current) {
|
|
1039
|
+
clearTimeout(transitionTimeoutRef.current);
|
|
1040
|
+
transitionTimeoutRef.current = null;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
previousOpenRef.current = open;
|
|
1044
|
+
}, [isAnchored, open]);
|
|
1045
|
+
(0, react.useEffect)(() => () => {
|
|
1046
|
+
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
1047
|
+
}, []);
|
|
1048
|
+
const handleMenuLevelChange = (0, react.useCallback)((level) => {
|
|
1049
|
+
if (isAnchored) {
|
|
1050
|
+
const previousLevel = previousMenuLevelRef.current;
|
|
1051
|
+
if (level !== previousLevel) {
|
|
1052
|
+
setTransitionDirection(level > previousLevel ? "forward" : "backward");
|
|
1053
|
+
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
1054
|
+
transitionTimeoutRef.current = setTimeout(() => {
|
|
1055
|
+
setTransitionDirection(void 0);
|
|
1056
|
+
transitionTimeoutRef.current = null;
|
|
1057
|
+
}, resolvedSubmenuTransitionDurationMs);
|
|
1058
|
+
}
|
|
1059
|
+
previousMenuLevelRef.current = level;
|
|
1060
|
+
setMenuLevel(level);
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
onMenuLevelChangeProp?.(level);
|
|
1064
|
+
}, [
|
|
1065
|
+
isAnchored,
|
|
1066
|
+
onMenuLevelChangeProp,
|
|
1067
|
+
resolvedSubmenuTransitionDurationMs
|
|
1068
|
+
]);
|
|
1069
|
+
const content = /* @__PURE__ */ (0, react.createElement)(ContextMenuContentComponent, {
|
|
1070
|
+
anchorReferenceElement: isAnchored ? referenceElement : void 0,
|
|
1071
|
+
...menuProps,
|
|
1072
|
+
key: `context-menu-content-${contentResetToken}`,
|
|
1073
|
+
onMenuLevelChange: handleMenuLevelChange,
|
|
1074
|
+
transitionDirection
|
|
1075
|
+
});
|
|
1076
|
+
if (isAnchored) {
|
|
1077
|
+
const { backLabel: _b, enableAnimations: _ea, Header: _h, items: _i, ItemsWrapper: _w, keyboardNavigation: _kn, menuClassName: _m, onClose: _c, role: _r, ...anchorDivProps } = menuProps;
|
|
1078
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DialogAnchor, {
|
|
1079
|
+
allowFlip,
|
|
1080
|
+
closeOnClickOutside,
|
|
1081
|
+
closeTransitionMs,
|
|
1082
|
+
dialogManagerId,
|
|
1083
|
+
focus,
|
|
1084
|
+
id,
|
|
1085
|
+
offset,
|
|
1086
|
+
placement,
|
|
1087
|
+
referenceElement,
|
|
1088
|
+
tabIndex,
|
|
1089
|
+
trapFocus,
|
|
1090
|
+
updateKey: menuLevel,
|
|
1091
|
+
...anchorDivProps,
|
|
1092
|
+
children: content
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
return content;
|
|
1096
|
+
};
|
|
1097
|
+
//#endregion
|
|
1098
|
+
//#region src/components/Dialog/components/Prompt.tsx
|
|
1099
|
+
var PromptRoot = ({ children, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1100
|
+
...props,
|
|
1101
|
+
className: (0, clsx.default)("str-chat__prompt", className),
|
|
1102
|
+
children
|
|
1103
|
+
});
|
|
1104
|
+
var PromptHeader = ({ className, close, description, descriptionId, goBack, LeadingContent, title, titleId, TrailingContent }) => {
|
|
1105
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
1106
|
+
const { dialogId } = useModalContext();
|
|
1107
|
+
const { descriptionId: derivedDescriptionId, titleId: derivedTitleId } = useAriaIdentifiers(dialogId);
|
|
1108
|
+
const resolvedTitleId = titleId ?? derivedTitleId;
|
|
1109
|
+
const resolvedDescriptionId = descriptionId ?? derivedDescriptionId;
|
|
1110
|
+
const hasDescription = description != null && description !== "";
|
|
1111
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1112
|
+
className: (0, clsx.default)("str-chat__prompt__header", className, {
|
|
1113
|
+
"str-chat__prompt__header--withDescription": hasDescription,
|
|
1114
|
+
"str-chat__prompt__header--withGoBack": goBack
|
|
1115
|
+
}),
|
|
1116
|
+
children: [
|
|
1117
|
+
LeadingContent && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1118
|
+
className: "str-chat__prompt__header__leading-content",
|
|
1119
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LeadingContent, {})
|
|
1120
|
+
}),
|
|
1121
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1122
|
+
className: (0, clsx.default)("str-chat__prompt__header__title-group"),
|
|
1123
|
+
children: [
|
|
1124
|
+
goBack && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
1125
|
+
appearance: "ghost",
|
|
1126
|
+
"aria-label": t("Go back"),
|
|
1127
|
+
circular: true,
|
|
1128
|
+
className: "str-chat__prompt__header__go-back-button",
|
|
1129
|
+
onClick: goBack,
|
|
1130
|
+
size: "md",
|
|
1131
|
+
variant: "secondary",
|
|
1132
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconArrowLeft, {})
|
|
1133
|
+
}),
|
|
1134
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
1135
|
+
className: "str-chat__prompt__header__title",
|
|
1136
|
+
id: resolvedTitleId,
|
|
1137
|
+
children: title
|
|
1138
|
+
}),
|
|
1139
|
+
hasDescription && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1140
|
+
className: "str-chat__prompt__header__description",
|
|
1141
|
+
id: resolvedDescriptionId,
|
|
1142
|
+
children: description
|
|
1143
|
+
})
|
|
1144
|
+
]
|
|
1145
|
+
}),
|
|
1146
|
+
(close || TrailingContent) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1147
|
+
className: "str-chat__prompt__header__trailing-content",
|
|
1148
|
+
children: [TrailingContent && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TrailingContent, {}), close && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
1149
|
+
appearance: "ghost",
|
|
1150
|
+
"aria-describedby": hasDescription ? resolvedDescriptionId : void 0,
|
|
1151
|
+
"aria-label": typeof title === "string" ? t("Close prompt: {{ title }}", { title }) : t("Close"),
|
|
1152
|
+
circular: true,
|
|
1153
|
+
className: "str-chat__prompt__header__close-button",
|
|
1154
|
+
onClick: close,
|
|
1155
|
+
size: "md",
|
|
1156
|
+
variant: "secondary",
|
|
1157
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconXmark, {})
|
|
1158
|
+
})]
|
|
1159
|
+
})
|
|
1160
|
+
]
|
|
1161
|
+
});
|
|
1162
|
+
};
|
|
1163
|
+
var PromptBody = ({ children, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1164
|
+
className: (0, clsx.default)("str-chat__prompt__body", className),
|
|
1165
|
+
children
|
|
1166
|
+
});
|
|
1167
|
+
var PromptFooter = ({ children, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1168
|
+
className: (0, clsx.default)("str-chat__prompt__footer", className),
|
|
1169
|
+
children
|
|
1170
|
+
});
|
|
1171
|
+
var PromptFooterControls = ({ children, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1172
|
+
className: (0, clsx.default)("str-chat__prompt__footer__controls", className),
|
|
1173
|
+
children
|
|
1174
|
+
});
|
|
1175
|
+
var PromptFooterControlsButtonSecondary = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
1176
|
+
appearance: "ghost",
|
|
1177
|
+
className: (0, clsx.default)("str-chat__prompt__footer__controls-button", className),
|
|
1178
|
+
size: "md",
|
|
1179
|
+
variant: "secondary",
|
|
1180
|
+
...props
|
|
1181
|
+
});
|
|
1182
|
+
var PromptFooterControlsButtonPrimary = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
1183
|
+
appearance: "solid",
|
|
1184
|
+
className: (0, clsx.default)("str-chat__prompt__footer__controls-button", className),
|
|
1185
|
+
size: "md",
|
|
1186
|
+
variant: "primary",
|
|
1187
|
+
...props
|
|
1188
|
+
});
|
|
1189
|
+
var Prompt = {
|
|
1190
|
+
Body: PromptBody,
|
|
1191
|
+
Footer: PromptFooter,
|
|
1192
|
+
FooterControls: PromptFooterControls,
|
|
1193
|
+
FooterControlsButtonPrimary: PromptFooterControlsButtonPrimary,
|
|
1194
|
+
FooterControlsButtonSecondary: PromptFooterControlsButtonSecondary,
|
|
1195
|
+
Header: PromptHeader,
|
|
1196
|
+
Root: PromptRoot
|
|
1197
|
+
};
|
|
1198
|
+
//#endregion
|
|
1199
|
+
//#region src/a11y/hooks/useResolvedModalAriaProps.ts
|
|
1200
|
+
/**
|
|
1201
|
+
* Resolves modal labeling/description attributes from explicit props first,
|
|
1202
|
+
* then from the modal dialog id convention (`${dialogId}-title|description`).
|
|
1203
|
+
*
|
|
1204
|
+
* Rules:
|
|
1205
|
+
* - `aria-labelledby` wins over `aria-label`.
|
|
1206
|
+
* - `aria-describedby` defaults to inferred id when explicit value is absent.
|
|
1207
|
+
*/
|
|
1208
|
+
var useResolvedModalAriaProps = ({ ariaDescribedby, ariaLabel, ariaLabelledby, dialogId }) => {
|
|
1209
|
+
const { descriptionId, titleId } = useAriaIdentifiers(dialogId);
|
|
1210
|
+
return (0, react.useMemo)(() => {
|
|
1211
|
+
const resolvedAriaLabelledby = ariaLabel ? ariaLabelledby : ariaLabelledby ?? titleId;
|
|
1212
|
+
return {
|
|
1213
|
+
"aria-describedby": ariaDescribedby ?? descriptionId,
|
|
1214
|
+
"aria-label": resolvedAriaLabelledby ? void 0 : ariaLabel,
|
|
1215
|
+
"aria-labelledby": resolvedAriaLabelledby
|
|
1216
|
+
};
|
|
1217
|
+
}, [
|
|
1218
|
+
ariaDescribedby,
|
|
1219
|
+
ariaLabel,
|
|
1220
|
+
ariaLabelledby,
|
|
1221
|
+
descriptionId,
|
|
1222
|
+
titleId
|
|
1223
|
+
]);
|
|
1224
|
+
};
|
|
1225
|
+
//#endregion
|
|
1226
|
+
//#region src/components/Modal/GlobalModal.tsx
|
|
1227
|
+
var GlobalModal = ({ "aria-describedby": ariaDescribedby, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, children, className, CloseButtonOnOverlay, dialogId, dialogRootProps, onClose, onCloseAttempt, open, role = "dialog" }) => {
|
|
1228
|
+
const generatedDialogId = require_useNotificationApi.useStableId();
|
|
1229
|
+
const resolvedDialogId = dialogId ?? `modal-dialog-${generatedDialogId}`;
|
|
1230
|
+
const dialog = require_useNotificationApi.useModalDialog(resolvedDialogId);
|
|
1231
|
+
const isOpen = require_useNotificationApi.useModalDialogIsOpen(resolvedDialogId);
|
|
1232
|
+
const isTopmost = require_useNotificationApi.useModalDialogIsTopmost(resolvedDialogId);
|
|
1233
|
+
const overlayRef = (0, react.useRef)(null);
|
|
1234
|
+
const closeButtonRef = (0, react.useRef)(null);
|
|
1235
|
+
const closingRef = (0, react.useRef)(false);
|
|
1236
|
+
const { theme } = require_useNotificationApi.useChatContext();
|
|
1237
|
+
const { NotificationList: NotificationList$1 = NotificationList } = require_useNotificationApi.useComponentContext();
|
|
1238
|
+
const { className: dialogRootClassName, onKeyDown: dialogRootOnKeyDown, ...dialogRootPropsRest } = dialogRootProps ?? {};
|
|
1239
|
+
const dialogLabelingBaseId = dialog.id;
|
|
1240
|
+
const resolvedModalAriaProps = useResolvedModalAriaProps({
|
|
1241
|
+
ariaDescribedby,
|
|
1242
|
+
ariaLabel,
|
|
1243
|
+
ariaLabelledby,
|
|
1244
|
+
dialogId: dialogLabelingBaseId
|
|
1245
|
+
});
|
|
1246
|
+
const maybeClose = (0, react.useCallback)((source, event) => {
|
|
1247
|
+
if (onCloseAttempt?.(source, event) !== false) {
|
|
1248
|
+
dialog.close();
|
|
1249
|
+
closingRef.current = true;
|
|
1250
|
+
onClose?.(event);
|
|
1251
|
+
}
|
|
1252
|
+
}, [
|
|
1253
|
+
dialog,
|
|
1254
|
+
onClose,
|
|
1255
|
+
onCloseAttempt
|
|
1256
|
+
]);
|
|
1257
|
+
const modalContextValue = (0, react.useMemo)(() => ({
|
|
1258
|
+
close: () => maybeClose("button", {}),
|
|
1259
|
+
dialogId: dialogLabelingBaseId
|
|
1260
|
+
}), [dialogLabelingBaseId, maybeClose]);
|
|
1261
|
+
const handleOverlayClick = (event) => {
|
|
1262
|
+
if (!isTopmost) return;
|
|
1263
|
+
const target = event.target;
|
|
1264
|
+
if (overlayRef.current === target) maybeClose("overlay", event);
|
|
1265
|
+
};
|
|
1266
|
+
const handleCloseButtonClick = (event) => {
|
|
1267
|
+
if (!isTopmost) return;
|
|
1268
|
+
maybeClose("button", event);
|
|
1269
|
+
};
|
|
1270
|
+
const handleDialogKeyDown = (event) => {
|
|
1271
|
+
dialogRootOnKeyDown?.(event);
|
|
1272
|
+
if (event.defaultPrevented || event.key !== "Escape" || !isTopmost) return;
|
|
1273
|
+
maybeClose("escape", event);
|
|
1274
|
+
};
|
|
1275
|
+
(0, react.useEffect)(() => {
|
|
1276
|
+
if (!open) {
|
|
1277
|
+
closingRef.current = false;
|
|
1278
|
+
if (isOpen) dialog.close();
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
if (open && !isOpen && !closingRef.current) dialog.open();
|
|
1282
|
+
}, [
|
|
1283
|
+
dialog,
|
|
1284
|
+
isOpen,
|
|
1285
|
+
open
|
|
1286
|
+
]);
|
|
1287
|
+
if (!open || !isOpen) return null;
|
|
1288
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.DialogPortalEntry, {
|
|
1289
|
+
dialogId: resolvedDialogId,
|
|
1290
|
+
dialogManagerId: require_useNotificationApi.modalDialogManagerId,
|
|
1291
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalContextProvider, {
|
|
1292
|
+
value: modalContextValue,
|
|
1293
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1294
|
+
className: (0, clsx.default)("str-chat", theme, "str-chat__modal str-chat-react__modal str-chat__modal--open", className),
|
|
1295
|
+
onClick: handleOverlayClick,
|
|
1296
|
+
ref: overlayRef,
|
|
1297
|
+
children: [
|
|
1298
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_aria_focus.FocusScope, {
|
|
1299
|
+
autoFocus: isTopmost,
|
|
1300
|
+
contain: isTopmost,
|
|
1301
|
+
restoreFocus: true,
|
|
1302
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1303
|
+
...dialogRootPropsRest,
|
|
1304
|
+
"aria-describedby": resolvedModalAriaProps["aria-describedby"],
|
|
1305
|
+
"aria-label": resolvedModalAriaProps["aria-label"],
|
|
1306
|
+
"aria-labelledby": resolvedModalAriaProps["aria-labelledby"],
|
|
1307
|
+
"aria-modal": isTopmost ? "true" : void 0,
|
|
1308
|
+
className: (0, clsx.default)("str-chat__modal__dialog", dialogRootClassName),
|
|
1309
|
+
inert: isTopmost ? void 0 : true,
|
|
1310
|
+
onKeyDown: handleDialogKeyDown,
|
|
1311
|
+
role,
|
|
1312
|
+
tabIndex: isTopmost ? 0 : -1,
|
|
1313
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.DialogManagerProvider, {
|
|
1314
|
+
id: `${resolvedDialogId}-floating-dialog-manager`,
|
|
1315
|
+
portalDestinationProps: {
|
|
1316
|
+
captureOutsideClicks: true,
|
|
1317
|
+
className: "str-chat__modal__floating-dialog-overlay"
|
|
1318
|
+
},
|
|
1319
|
+
children
|
|
1320
|
+
})
|
|
1321
|
+
})
|
|
1322
|
+
}),
|
|
1323
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotificationList$1, {
|
|
1324
|
+
className: "str-chat__modal__notification-list",
|
|
1325
|
+
panel: "modal",
|
|
1326
|
+
verticalAlignment: "top"
|
|
1327
|
+
}),
|
|
1328
|
+
CloseButtonOnOverlay && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CloseButtonOnOverlay, {
|
|
1329
|
+
onClick: handleCloseButtonClick,
|
|
1330
|
+
ref: closeButtonRef
|
|
1331
|
+
})
|
|
1332
|
+
]
|
|
1333
|
+
})
|
|
1334
|
+
})
|
|
1335
|
+
});
|
|
1336
|
+
};
|
|
1337
|
+
//#endregion
|
|
1338
|
+
//#region src/components/Message/renderText/remarkPlugins/htmlToTextPlugin.ts
|
|
1339
|
+
var visitor = (node) => {
|
|
1340
|
+
if (node.type !== "html") return;
|
|
1341
|
+
node.type = "text";
|
|
1342
|
+
};
|
|
1343
|
+
var transform = (tree) => {
|
|
1344
|
+
(0, unist_util_visit.visit)(tree, visitor);
|
|
1345
|
+
};
|
|
1346
|
+
var htmlToTextPlugin = () => transform;
|
|
1347
|
+
//#endregion
|
|
1348
|
+
//#region src/components/Message/renderText/remarkPlugins/imageToLink.ts
|
|
1349
|
+
var text = (value) => ({
|
|
1350
|
+
type: "text",
|
|
1351
|
+
value
|
|
1352
|
+
});
|
|
1353
|
+
/**
|
|
1354
|
+
* Converts image Markdown links ()
|
|
1355
|
+
* to HTML <a href={url}>{url | title | alt}</a>
|
|
1356
|
+
*
|
|
1357
|
+
* By default, the anchor text content is the image url so that image preview can be generated / enriched on the server.
|
|
1358
|
+
* @param getTextLabelFrom
|
|
1359
|
+
*/
|
|
1360
|
+
function imageToLink({ getTextLabelFrom = "url" } = {}) {
|
|
1361
|
+
return (tree) => {
|
|
1362
|
+
const visitor = (node, index, parent) => {
|
|
1363
|
+
if (parent == null || index == null) return;
|
|
1364
|
+
const link = {
|
|
1365
|
+
children: [text(node[getTextLabelFrom] ?? node.url)],
|
|
1366
|
+
title: node.title ?? node.alt ?? node.url,
|
|
1367
|
+
type: "link",
|
|
1368
|
+
url: node.url
|
|
1369
|
+
};
|
|
1370
|
+
parent.children.splice(index, 1, link);
|
|
1371
|
+
return [unist_util_visit.SKIP, index + 1];
|
|
1372
|
+
};
|
|
1373
|
+
(0, unist_util_visit.visit)(tree, "image", visitor);
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
//#endregion
|
|
1377
|
+
//#region src/components/Message/renderText/remarkPlugins/plusPlusToEmphasis.ts
|
|
1378
|
+
/**
|
|
1379
|
+
* \S → first char must be non-whitespace
|
|
1380
|
+
* (?:...)?→ optional middle+closing when length > 1
|
|
1381
|
+
* [\s\S]*?→ anything (including newlines), lazy
|
|
1382
|
+
* final \S→ last char non-whitespace (only required when there’s more than 1)
|
|
1383
|
+
*
|
|
1384
|
+
* Matches:
|
|
1385
|
+
* ++a++
|
|
1386
|
+
* Does not match:
|
|
1387
|
+
* ++++
|
|
1388
|
+
* ++ ++
|
|
1389
|
+
*/
|
|
1390
|
+
var INS_REGEX = /\+\+(\S(?:[\s\S]*?\S)?)\+\+/g;
|
|
1391
|
+
var IGNORE_NODE_TYPES = new Set([
|
|
1392
|
+
"code",
|
|
1393
|
+
"inlineCode",
|
|
1394
|
+
"link",
|
|
1395
|
+
"linkReference",
|
|
1396
|
+
"definition",
|
|
1397
|
+
"math",
|
|
1398
|
+
"inlineMath"
|
|
1399
|
+
]);
|
|
1400
|
+
/**
|
|
1401
|
+
* Converts MD "++Some text++" to inserted text element rendered in HTML as <ins>Some text</ins>
|
|
1402
|
+
* https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/ins
|
|
1403
|
+
*/
|
|
1404
|
+
var plusPlusToEmphasis = () => {
|
|
1405
|
+
const visitor = (node, index, parent) => {
|
|
1406
|
+
if (IGNORE_NODE_TYPES.has(node.type)) return unist_util_visit.SKIP;
|
|
1407
|
+
if (node.type !== "text" || parent == null || typeof index !== "number") return;
|
|
1408
|
+
const value = node.value;
|
|
1409
|
+
INS_REGEX.lastIndex = 0;
|
|
1410
|
+
let match;
|
|
1411
|
+
let last = 0;
|
|
1412
|
+
const out = [];
|
|
1413
|
+
while (match = INS_REGEX.exec(value)) {
|
|
1414
|
+
const [full, inner] = match;
|
|
1415
|
+
const start = match.index;
|
|
1416
|
+
if (start > last) out.push({
|
|
1417
|
+
type: "text",
|
|
1418
|
+
value: value.slice(last, start)
|
|
1419
|
+
});
|
|
1420
|
+
out.push({
|
|
1421
|
+
children: [{
|
|
1422
|
+
type: "text",
|
|
1423
|
+
value: inner
|
|
1424
|
+
}],
|
|
1425
|
+
data: { hName: "ins" },
|
|
1426
|
+
type: "emphasis"
|
|
1427
|
+
});
|
|
1428
|
+
last = start + full.length;
|
|
1429
|
+
}
|
|
1430
|
+
if (out.length === 0) return;
|
|
1431
|
+
if (last < value.length) out.push({
|
|
1432
|
+
type: "text",
|
|
1433
|
+
value: value.slice(last)
|
|
1434
|
+
});
|
|
1435
|
+
parent.children.splice(index, 1, ...out);
|
|
1436
|
+
return [unist_util_visit.SKIP, index + out.length];
|
|
1437
|
+
};
|
|
1438
|
+
return (tree) => (0, unist_util_visit.visit)(tree, visitor);
|
|
1439
|
+
};
|
|
1440
|
+
//#endregion
|
|
1441
|
+
//#region src/components/Message/Timestamp.tsx
|
|
1442
|
+
function Timestamp(props) {
|
|
1443
|
+
const { calendar, calendarFormats, customClass, format, timestamp } = props;
|
|
1444
|
+
const { formatDate } = useMessageContext("MessageTimestamp");
|
|
1445
|
+
const { t, tDateTimeParser } = require_useNotificationApi.useTranslationContext("MessageTimestamp");
|
|
1446
|
+
const normalizedTimestamp = timestamp && require_useNotificationApi.isDate(timestamp) ? timestamp.toISOString() : timestamp;
|
|
1447
|
+
const when = (0, react.useMemo)(() => require_useNotificationApi.getDateString({
|
|
1448
|
+
calendar,
|
|
1449
|
+
calendarFormats,
|
|
1450
|
+
format,
|
|
1451
|
+
formatDate,
|
|
1452
|
+
messageCreatedAt: normalizedTimestamp,
|
|
1453
|
+
t,
|
|
1454
|
+
tDateTimeParser,
|
|
1455
|
+
timestampTranslationKey: "timestamp/MessageTimestamp"
|
|
1456
|
+
}), [
|
|
1457
|
+
calendar,
|
|
1458
|
+
calendarFormats,
|
|
1459
|
+
format,
|
|
1460
|
+
formatDate,
|
|
1461
|
+
normalizedTimestamp,
|
|
1462
|
+
t,
|
|
1463
|
+
tDateTimeParser
|
|
1464
|
+
]);
|
|
1465
|
+
if (!when) return null;
|
|
1466
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
|
|
1467
|
+
className: customClass,
|
|
1468
|
+
dateTime: normalizedTimestamp,
|
|
1469
|
+
title: normalizedTimestamp,
|
|
1470
|
+
children: when
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
//#endregion
|
|
1474
|
+
//#region src/components/Message/MessageTimestamp.tsx
|
|
1475
|
+
var UnMemoizedMessageTimestamp = (props) => {
|
|
1476
|
+
const { message: propMessage, ...timestampProps } = props;
|
|
1477
|
+
const { message: contextMessage } = useMessageContext("MessageTimestamp");
|
|
1478
|
+
const { Timestamp: Timestamp$1 = Timestamp } = require_useNotificationApi.useComponentContext("MessageTimestamp");
|
|
1479
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Timestamp$1, {
|
|
1480
|
+
timestamp: (propMessage || contextMessage).created_at,
|
|
1481
|
+
...timestampProps
|
|
1482
|
+
});
|
|
1483
|
+
};
|
|
1484
|
+
var MessageTimestamp = react.default.memo(UnMemoizedMessageTimestamp);
|
|
1485
|
+
//#endregion
|
|
1486
|
+
//#region src/components/Attachment/components/DownloadButton.tsx
|
|
1487
|
+
/**
|
|
1488
|
+
* Icon download control for {@link Audio} and {@link FileAttachment} rows.
|
|
1489
|
+
* (BaseImage defines its own small download link when `showDownloadButtonOnError` is used.)
|
|
1490
|
+
*/
|
|
1491
|
+
var DownloadButton = ({ assetUrl, className, suggestedFileName, tooltipTitle }) => {
|
|
1492
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
1493
|
+
if (!assetUrl) return null;
|
|
1494
|
+
const href = (0, _braintree_sanitize_url.sanitizeUrl)(assetUrl);
|
|
1495
|
+
if (!href) return null;
|
|
1496
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
1497
|
+
"aria-label": t("aria/Download attachment"),
|
|
1498
|
+
className: (0, clsx.default)("str-chat__button", "str-chat__button--secondary", "str-chat__button--outline", "str-chat__button--circular", "str-chat__button--size-sm", "str-chat__audio-attachment-download-button", className),
|
|
1499
|
+
download: suggestedFileName ?? "",
|
|
1500
|
+
href,
|
|
1501
|
+
rel: "noopener noreferrer",
|
|
1502
|
+
target: "_blank",
|
|
1503
|
+
title: tooltipTitle ?? t("Download Attachment"),
|
|
1504
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1505
|
+
className: "str-chat__button__content",
|
|
1506
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconDownload, { className: "str-chat__icon str-chat__audio-attachment-download-button__icon" })
|
|
1507
|
+
})
|
|
1508
|
+
});
|
|
1509
|
+
};
|
|
1510
|
+
//#endregion
|
|
1511
|
+
//#region src/components/FileIcon/FileIconSet.tsx
|
|
1512
|
+
var BASE_FILE_ICON_CLASSNAME = "str-chat__file-icon";
|
|
1513
|
+
var FILE_ICON_GRAPHIC_CLASSNAME = "str-chat__file-icon__graphic";
|
|
1514
|
+
/** Add this class (e.g. via className) when hiding the label with CSS to center the icon graphic. */
|
|
1515
|
+
var FILE_ICON_NO_LABEL_CLASSNAME = "str-chat__file-icon--no-label";
|
|
1516
|
+
/** Rendered dimensions (px) and label position in viewBox coords for consistent spacing. */
|
|
1517
|
+
var FILE_ICON_SIZE_CONFIG = {
|
|
1518
|
+
lg: {
|
|
1519
|
+
height: 40,
|
|
1520
|
+
labelX: 16,
|
|
1521
|
+
labelY: 36,
|
|
1522
|
+
width: 32
|
|
1523
|
+
},
|
|
1524
|
+
md: {
|
|
1525
|
+
height: 32,
|
|
1526
|
+
labelX: 16,
|
|
1527
|
+
labelY: 35,
|
|
1528
|
+
width: 26
|
|
1529
|
+
},
|
|
1530
|
+
sm: {
|
|
1531
|
+
height: 24,
|
|
1532
|
+
labelX: 16,
|
|
1533
|
+
labelY: 31.5,
|
|
1534
|
+
width: 19
|
|
1535
|
+
},
|
|
1536
|
+
xl: {
|
|
1537
|
+
height: 48,
|
|
1538
|
+
labelX: 16,
|
|
1539
|
+
labelY: 36,
|
|
1540
|
+
width: 40
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1543
|
+
/** Merge partial overrides with default config. Use for Chat-level fileIconSizeConfig. */
|
|
1544
|
+
var mergeFileIconSizeConfig = (overrides) => {
|
|
1545
|
+
if (!overrides) return FILE_ICON_SIZE_CONFIG;
|
|
1546
|
+
return [
|
|
1547
|
+
"sm",
|
|
1548
|
+
"md",
|
|
1549
|
+
"lg",
|
|
1550
|
+
"xl"
|
|
1551
|
+
].reduce((acc, size) => ({
|
|
1552
|
+
...acc,
|
|
1553
|
+
[size]: {
|
|
1554
|
+
...FILE_ICON_SIZE_CONFIG[size],
|
|
1555
|
+
...overrides[size]
|
|
1556
|
+
}
|
|
1557
|
+
}), {});
|
|
1558
|
+
};
|
|
1559
|
+
var FILE_ICON_VIEWBOX = {
|
|
1560
|
+
height: 40,
|
|
1561
|
+
width: 32
|
|
1562
|
+
};
|
|
1563
|
+
var FILE_ICON_PAPER_PATH = "M0 4C0 1.79086 1.79086 0 4 0H22.4L32 10V36C32 38.2091 30.2091 40 28 40H4C1.79086 40 0 38.2091 0 36V4Z";
|
|
1564
|
+
var FILE_ICON_FOLD_PATH = "M32 10H25.4C23.7431 10 22.4 8.65685 22.4 7V0L32 10Z";
|
|
1565
|
+
var FILE_ICON_WITHOUT_CAPTION_SYMBOL_SCALE_X = 32 / 26;
|
|
1566
|
+
var FILE_ICON_WITHOUT_CAPTION_SYMBOL_SCALE_Y = 40 / 32;
|
|
1567
|
+
var Svg = ({ className, size, sizeConfig, ...props }) => {
|
|
1568
|
+
const dimensions = size ? (sizeConfig ?? FILE_ICON_SIZE_CONFIG)[size] : void 0;
|
|
1569
|
+
const dimensionsStyle = dimensions ? {
|
|
1570
|
+
flexShrink: 0,
|
|
1571
|
+
height: `${dimensions.height}px`,
|
|
1572
|
+
width: `${dimensions.width}px`
|
|
1573
|
+
} : void 0;
|
|
1574
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1575
|
+
height: dimensions?.height,
|
|
1576
|
+
viewBox: `0 0 ${FILE_ICON_VIEWBOX.width} ${FILE_ICON_VIEWBOX.height}`,
|
|
1577
|
+
width: dimensions?.width,
|
|
1578
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1579
|
+
...props,
|
|
1580
|
+
className: (0, clsx.default)(BASE_FILE_ICON_CLASSNAME, { [`${BASE_FILE_ICON_CLASSNAME}--size-${size}`]: size }, className),
|
|
1581
|
+
style: {
|
|
1582
|
+
...dimensionsStyle,
|
|
1583
|
+
...props.style
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
1586
|
+
};
|
|
1587
|
+
var FileIconLabel = ({ label, size, sizeConfig }) => {
|
|
1588
|
+
const config = size ? (sizeConfig ?? FILE_ICON_SIZE_CONFIG)[size] : {
|
|
1589
|
+
labelX: 16,
|
|
1590
|
+
labelY: 33
|
|
1591
|
+
};
|
|
1592
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
1593
|
+
className: "str-chat__file-icon__label",
|
|
1594
|
+
x: config.labelX,
|
|
1595
|
+
y: config.labelY,
|
|
1596
|
+
children: label
|
|
1597
|
+
});
|
|
1598
|
+
};
|
|
1599
|
+
var TEXT_SYMBOLS = {
|
|
1600
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1601
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1602
|
+
fill: "white",
|
|
1603
|
+
height: "1.6",
|
|
1604
|
+
rx: "0.8",
|
|
1605
|
+
width: "14.4",
|
|
1606
|
+
x: "8",
|
|
1607
|
+
y: "12.2"
|
|
1608
|
+
}),
|
|
1609
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1610
|
+
fill: "white",
|
|
1611
|
+
height: "1.6",
|
|
1612
|
+
rx: "0.8",
|
|
1613
|
+
width: "14.4",
|
|
1614
|
+
x: "8",
|
|
1615
|
+
y: "20.2"
|
|
1616
|
+
}),
|
|
1617
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1618
|
+
fill: "white",
|
|
1619
|
+
height: "1.6",
|
|
1620
|
+
rx: "0.8",
|
|
1621
|
+
width: "9.6",
|
|
1622
|
+
x: "8",
|
|
1623
|
+
y: "16.2"
|
|
1624
|
+
})
|
|
1625
|
+
] }),
|
|
1626
|
+
withoutCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1627
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1628
|
+
fill: "white",
|
|
1629
|
+
height: "1.4",
|
|
1630
|
+
rx: "0.7",
|
|
1631
|
+
width: "12.6",
|
|
1632
|
+
x: "6",
|
|
1633
|
+
y: "14.8"
|
|
1634
|
+
}),
|
|
1635
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1636
|
+
fill: "white",
|
|
1637
|
+
height: "1.4",
|
|
1638
|
+
rx: "0.7",
|
|
1639
|
+
width: "12.6",
|
|
1640
|
+
x: "6",
|
|
1641
|
+
y: "21.8"
|
|
1642
|
+
}),
|
|
1643
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1644
|
+
fill: "white",
|
|
1645
|
+
height: "1.4",
|
|
1646
|
+
rx: "0.7",
|
|
1647
|
+
width: "8.4",
|
|
1648
|
+
x: "6",
|
|
1649
|
+
y: "18.3"
|
|
1650
|
+
})
|
|
1651
|
+
] })
|
|
1652
|
+
};
|
|
1653
|
+
var OTHER_SYMBOLS = {
|
|
1654
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1655
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1656
|
+
fill: "white",
|
|
1657
|
+
height: "1.6",
|
|
1658
|
+
rx: "0.8",
|
|
1659
|
+
width: "14.4",
|
|
1660
|
+
x: "8",
|
|
1661
|
+
y: "13.2"
|
|
1662
|
+
}),
|
|
1663
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1664
|
+
fill: "white",
|
|
1665
|
+
height: "1.6",
|
|
1666
|
+
rx: "0.8",
|
|
1667
|
+
width: "14.4",
|
|
1668
|
+
x: "8",
|
|
1669
|
+
y: "21.2"
|
|
1670
|
+
}),
|
|
1671
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
1672
|
+
fill: "white",
|
|
1673
|
+
height: "1.6",
|
|
1674
|
+
rx: "0.8",
|
|
1675
|
+
width: "9.6",
|
|
1676
|
+
x: "8",
|
|
1677
|
+
y: "17.2"
|
|
1678
|
+
})
|
|
1679
|
+
] }),
|
|
1680
|
+
withoutCaption: TEXT_SYMBOLS.withoutCaption
|
|
1681
|
+
};
|
|
1682
|
+
var CODE_SYMBOLS = {
|
|
1683
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1684
|
+
d: "M14.5 22.5L17.5 11.5M20.1666 14.1667L21.9732 16.0862C22.4564 16.5996 22.4564 17.4004 21.9732 17.9138L20.1666 19.8333M11.8333 19.8333L10.0267 17.9138C9.54351 17.4004 9.54351 16.5996 10.0267 16.0862L11.8333 14.1667",
|
|
1685
|
+
stroke: "white",
|
|
1686
|
+
strokeLinecap: "round",
|
|
1687
|
+
strokeLinejoin: "round",
|
|
1688
|
+
strokeWidth: "1.2"
|
|
1689
|
+
}),
|
|
1690
|
+
withoutCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1691
|
+
d: "M11.6876 23.8125L14.3126 14.1875M16.646 16.5208L18.2267 18.2004C18.6495 18.6496 18.6495 19.3503 18.2267 19.7996L16.646 21.4792M9.3543 21.4792L7.77352 19.7996C7.35072 19.3503 7.35072 18.6496 7.77352 18.2004L9.3543 16.5208",
|
|
1692
|
+
stroke: "white",
|
|
1693
|
+
strokeLinecap: "round",
|
|
1694
|
+
strokeLinejoin: "round",
|
|
1695
|
+
strokeWidth: "1.33333"
|
|
1696
|
+
})
|
|
1697
|
+
};
|
|
1698
|
+
var AUDIO_SYMBOLS = {
|
|
1699
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1700
|
+
d: "M20.5 15.5V18.5M22.5 14.5V19.5M13.5 19.5H10.5C10.3674 19.5 10.2402 19.4473 10.1464 19.3536C10.0527 19.2598 10 19.1326 10 19V15C10 14.8674 10.0527 14.7402 10.1464 14.6464C10.2402 14.5527 10.3674 14.5 10.5 14.5H13.5L18 11V23L13.5 19.5Z",
|
|
1701
|
+
stroke: "white",
|
|
1702
|
+
strokeLinecap: "round",
|
|
1703
|
+
strokeLinejoin: "round",
|
|
1704
|
+
strokeWidth: "1.2"
|
|
1705
|
+
}),
|
|
1706
|
+
withoutCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1707
|
+
d: "M17.5 17.5V20.5M19.5 16.5V21.5M10.5 21.5H7.5C7.36739 21.5 7.24021 21.4473 7.14645 21.3536C7.05268 21.2598 7 21.1326 7 21V17C7 16.8674 7.05268 16.7402 7.14645 16.6464C7.24021 16.5527 7.36739 16.5 7.5 16.5H10.5L15 13V25L10.5 21.5Z",
|
|
1708
|
+
stroke: "white",
|
|
1709
|
+
strokeLinecap: "round",
|
|
1710
|
+
strokeLinejoin: "round",
|
|
1711
|
+
strokeWidth: "1.33333"
|
|
1712
|
+
})
|
|
1713
|
+
};
|
|
1714
|
+
var PRESENTATION_SYMBOLS = {
|
|
1715
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1716
|
+
d: "M12.5 15.5H19.5M16 17.5V22.5M14 22.5H18M9.49999 17.5C9.41472 17.5001 9.33085 17.4783 9.25635 17.4368C9.18185 17.3953 9.1192 17.3355 9.07436 17.263C9.02952 17.1904 9.00397 17.1076 9.00014 17.0224C8.99631 16.9373 9.01433 16.8525 9.05249 16.7762L11.5525 11.7763C11.5941 11.6932 11.6579 11.6233 11.737 11.5745C11.816 11.5257 11.9071 11.4999 12 11.5H20C20.0929 11.4999 20.184 11.5257 20.263 11.5745C20.342 11.6233 20.4059 11.6932 20.4475 11.7763L22.9475 16.7762C22.9857 16.8525 23.0037 16.9373 22.9998 17.0224C22.996 17.1076 22.9705 17.1904 22.9256 17.263C22.8808 17.3355 22.8181 17.3953 22.7436 17.4368C22.6691 17.4783 22.5853 17.5001 22.5 17.5H9.49999Z",
|
|
1717
|
+
stroke: "white",
|
|
1718
|
+
strokeLinecap: "round",
|
|
1719
|
+
strokeLinejoin: "round",
|
|
1720
|
+
strokeWidth: "1.2"
|
|
1721
|
+
}),
|
|
1722
|
+
withoutCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1723
|
+
d: "M9.49999 17.5H16.5M13 19.5V24.5M11 24.5H15M6.49999 19.5C6.41472 19.5001 6.33085 19.4783 6.25635 19.4368C6.18185 19.3953 6.11921 19.3355 6.07436 19.263C6.02952 19.1904 6.00397 19.1076 6.00014 19.0224C5.99631 18.9373 6.01433 18.8525 6.05249 18.7763L8.55249 13.7763C8.59406 13.6932 8.65795 13.6233 8.73699 13.5745C8.81603 13.5257 8.9071 13.4999 8.99999 13.5H17C17.0929 13.4999 17.184 13.5257 17.263 13.5745C17.342 13.6233 17.4059 13.6932 17.4475 13.7763L19.9475 18.7763C19.9857 18.8525 20.0037 18.9373 19.9998 19.0224C19.996 19.1076 19.9705 19.1904 19.9256 19.263C19.8808 19.3355 19.8181 19.3953 19.7436 19.4368C19.6691 19.4783 19.5853 19.5001 19.5 19.5H6.49999Z",
|
|
1724
|
+
stroke: "white",
|
|
1725
|
+
strokeLinecap: "round",
|
|
1726
|
+
strokeLinejoin: "round",
|
|
1727
|
+
strokeWidth: "1.33333"
|
|
1728
|
+
})
|
|
1729
|
+
};
|
|
1730
|
+
var SPREADSHEET_SYMBOLS = {
|
|
1731
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1732
|
+
d: "M10 15.5H22M10 18.5H22M13.5 15.5V21.5M10 12.5H22V21C22 21.1326 21.9473 21.2598 21.8536 21.3536C21.7598 21.4473 21.6326 21.5 21.5 21.5H10.5C10.3674 21.5 10.2402 21.4473 10.1464 21.3536C10.0527 21.2598 10 21.1326 10 21V12.5Z",
|
|
1733
|
+
stroke: "white",
|
|
1734
|
+
strokeLinecap: "round",
|
|
1735
|
+
strokeLinejoin: "round",
|
|
1736
|
+
strokeWidth: "1.5"
|
|
1737
|
+
}),
|
|
1738
|
+
withoutCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1739
|
+
d: "M7 17.5H19M7 20.5H19M10.5 17.5V23.5M7 14.5H19V23C19 23.1326 18.9473 23.2598 18.8536 23.3536C18.7598 23.4473 18.6326 23.5 18.5 23.5H7.5C7.36739 23.5 7.24021 23.4473 7.14645 23.3536C7.05268 23.2598 7 23.1326 7 23V14.5Z",
|
|
1740
|
+
stroke: "white",
|
|
1741
|
+
strokeLinecap: "round",
|
|
1742
|
+
strokeLinejoin: "round",
|
|
1743
|
+
strokeWidth: "1.2"
|
|
1744
|
+
})
|
|
1745
|
+
};
|
|
1746
|
+
var COMPRESSION_SYMBOLS = {
|
|
1747
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1748
|
+
clipRule: "evenodd",
|
|
1749
|
+
d: "M9.41177 0H7.52942V2H9.41177V4H7.52942V6H9.41177V8H7.52942V10H9.41177V12H7.52942V14H9.41177V12H11.2941V10H9.41177V8H11.2941V6H9.41177V4H11.2941V2H9.41177V0ZM7.52942 17C7.52942 16.4477 7.9508 16 8.4706 16H10.3529C10.8727 16 11.2941 16.4477 11.2941 17V23C11.2941 23.5523 10.8727 24 10.3529 24H8.4706C7.9508 24 7.52942 23.5523 7.52942 23V17ZM8.4706 23V20H10.3529V23H8.4706Z",
|
|
1750
|
+
fill: "white",
|
|
1751
|
+
fillRule: "evenodd"
|
|
1752
|
+
}),
|
|
1753
|
+
withoutCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1754
|
+
clipRule: "evenodd",
|
|
1755
|
+
d: "M8.17031 0H6.11768V2.14737H8.17031V4.29474H6.11768V6.4421H8.17031V8.58947H6.11768V10.7368H8.17031V12.8842H6.11768V15.0316H8.17031V12.8842H10.2229V10.7368H8.17031V8.58947H10.2229V6.4421H8.17031V4.29474H10.2229V2.14737H8.17031V0ZM6.11768 18.2526C6.11768 17.6597 6.57717 17.1789 7.14399 17.1789H9.19662C9.76344 17.1789 10.2229 17.6597 10.2229 18.2526V24.6947C10.2229 25.2877 9.76344 25.7684 9.19662 25.7684H7.14399C6.57717 25.7684 6.11768 25.2877 6.11768 24.6947V18.2526ZM7.14399 24.6947V21.4737H9.19662V24.6947H7.14399Z",
|
|
1756
|
+
fill: "white",
|
|
1757
|
+
fillRule: "evenodd"
|
|
1758
|
+
})
|
|
1759
|
+
};
|
|
1760
|
+
var VIDEO_SYMBOLS = {
|
|
1761
|
+
withCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1762
|
+
d: "M20.5 16L23.5 14V20L20.5 18M10 13H20C20.2761 13 20.5 13.2239 20.5 13.5V20.5C20.5 20.7761 20.2761 21 20 21H10C9.72386 21 9.5 20.7761 9.5 20.5V13.5C9.5 13.2239 9.72386 13 10 13Z",
|
|
1763
|
+
stroke: "white",
|
|
1764
|
+
strokeLinecap: "round",
|
|
1765
|
+
strokeLinejoin: "round",
|
|
1766
|
+
strokeWidth: "1.2"
|
|
1767
|
+
}),
|
|
1768
|
+
withoutCaption: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1769
|
+
d: "M17.5001 18L20.5001 16V22L17.5001 20M7.00012 15H17.0001C17.2763 15 17.5001 15.2239 17.5001 15.5V22.5C17.5001 22.7761 17.2763 23 17.0001 23H7.00012C6.72398 23 6.50012 22.7761 6.50012 22.5V15.5C6.50012 15.2239 6.72398 15 7.00012 15Z",
|
|
1770
|
+
stroke: "white",
|
|
1771
|
+
strokeLinecap: "round",
|
|
1772
|
+
strokeLinejoin: "round",
|
|
1773
|
+
strokeWidth: "1.33333"
|
|
1774
|
+
})
|
|
1775
|
+
};
|
|
1776
|
+
var StandardFileTypeIcon = ({ className, color, fileTypeClassName, label, size, sizeConfig, symbols, ...props }) => {
|
|
1777
|
+
const renderLabel = !!label;
|
|
1778
|
+
const resolvedLabel = renderLabel ? label : void 0;
|
|
1779
|
+
const symbolVariant = renderLabel ? "withCaption" : "withoutCaption";
|
|
1780
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Svg, {
|
|
1781
|
+
...props,
|
|
1782
|
+
className: (0, clsx.default)(fileTypeClassName, className),
|
|
1783
|
+
size,
|
|
1784
|
+
sizeConfig,
|
|
1785
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
1786
|
+
className: FILE_ICON_GRAPHIC_CLASSNAME,
|
|
1787
|
+
children: [
|
|
1788
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1789
|
+
d: FILE_ICON_PAPER_PATH,
|
|
1790
|
+
fill: color
|
|
1791
|
+
}),
|
|
1792
|
+
renderLabel ? symbols[symbolVariant] : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("g", {
|
|
1793
|
+
transform: `scale(${FILE_ICON_WITHOUT_CAPTION_SYMBOL_SCALE_X} ${FILE_ICON_WITHOUT_CAPTION_SYMBOL_SCALE_Y})`,
|
|
1794
|
+
children: symbols[symbolVariant]
|
|
1795
|
+
}),
|
|
1796
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1797
|
+
d: FILE_ICON_FOLD_PATH,
|
|
1798
|
+
fill: "white",
|
|
1799
|
+
opacity: "0.5"
|
|
1800
|
+
})
|
|
1801
|
+
]
|
|
1802
|
+
}), resolvedLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileIconLabel, {
|
|
1803
|
+
label: resolvedLabel,
|
|
1804
|
+
size,
|
|
1805
|
+
sizeConfig
|
|
1806
|
+
})]
|
|
1807
|
+
});
|
|
1808
|
+
};
|
|
1809
|
+
var PDF_SMALL_SYMBOL = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1810
|
+
d: "M20.7533 19.5337C20.28 19.037 19.3093 18.7537 17.9373 18.7537C17.204 18.7537 16.3526 18.8244 15.43 18.9897C14.8647 18.4461 14.3499 17.8523 13.892 17.2157C13.5373 16.7424 13.2293 16.2224 12.9453 15.725C13.49 14.069 13.75 12.7204 13.75 11.7504C13.75 10.6624 13.348 9.52637 12.1886 9.52637C11.834 9.52637 11.4786 9.7397 11.2893 10.047C10.7693 10.9697 11.006 12.9804 11.9046 14.9677C11.5664 15.984 11.1876 16.9863 10.7693 17.9724C10.3906 18.8717 9.96465 19.7944 9.49131 20.6457C6.88931 21.687 5.20931 22.8937 5.01998 23.839C4.94931 24.1944 5.06731 24.5257 5.32798 24.7857C5.42265 24.857 5.75398 25.141 6.32131 25.141C8.04798 25.141 9.86998 22.349 10.7926 20.6697C11.5026 20.433 12.2126 20.1964 12.922 20.007C13.6704 19.8038 14.4284 19.638 15.1933 19.5104C17.0146 21.1424 18.6233 21.403 19.428 21.403C20.4213 21.403 20.7766 21.0004 20.8946 20.6697C21.108 20.243 20.966 19.7704 20.7533 19.5337ZM19.8066 20.2204C19.7353 20.575 19.38 20.8117 18.884 20.8117C18.742 20.8117 18.624 20.7877 18.4813 20.7644C17.5826 20.551 16.7306 20.1017 15.8793 19.3917C16.5357 19.2807 17.2003 19.2254 17.866 19.2264C18.3633 19.2264 18.7893 19.2497 19.0726 19.321C19.404 19.3917 19.9246 19.605 19.806 20.2197L19.8066 20.2204ZM14.7906 19.1084C14.1305 19.2321 13.4755 19.382 12.8273 19.5577C12.262 19.7047 11.7017 19.8703 11.1473 20.0544C11.4355 19.4962 11.7039 18.9281 11.952 18.351C12.236 17.6884 12.472 17.0024 12.7093 16.3637C12.9453 16.7657 13.206 17.1684 13.466 17.523C13.8911 18.065 14.3329 18.5937 14.7906 19.1084ZM11.692 10.307C11.7338 10.2232 11.7978 10.1525 11.877 10.1025C11.9563 10.0526 12.0477 10.0253 12.1413 10.0237C12.638 10.0237 12.7326 10.591 12.7326 11.041C12.7326 11.7977 12.496 12.957 12.094 14.2817C11.4073 12.4364 11.3606 10.899 11.692 10.307ZM9.08931 21.3317C7.88265 23.319 6.72331 24.549 6.01398 24.549C5.88599 24.5498 5.76132 24.5083 5.65931 24.431C5.51731 24.289 5.44598 24.1237 5.49331 23.9344C5.63531 23.2244 7.00731 22.231 9.08931 21.3317Z",
|
|
1811
|
+
fill: "white"
|
|
1812
|
+
});
|
|
1813
|
+
var PDF_LEGACY_SYMBOL = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1814
|
+
d: "M23.7533 19.2C23.28 18.7033 22.3093 18.42 20.9373 18.42C20.204 18.42 19.3526 18.4906 18.43 18.656C17.8647 18.1124 17.3499 17.5186 16.892 16.882C16.5373 16.4086 16.2293 15.8886 15.9453 15.3913C16.49 13.7353 16.75 12.3866 16.75 11.4166C16.75 10.3286 16.348 9.19263 15.1886 9.19263C14.834 9.19263 14.4786 9.40596 14.2893 9.71329C13.7693 10.636 14.006 12.6466 14.9046 14.634C14.5664 15.6502 14.1877 16.6526 13.7693 17.6386C13.3906 18.538 12.9646 19.4606 12.4913 20.312C9.88931 21.3533 8.20931 22.56 8.01998 23.5053C7.94931 23.8606 8.06731 24.192 8.32798 24.452C8.42265 24.5233 8.75398 24.8073 9.32131 24.8073C11.048 24.8073 12.87 22.0153 13.7926 20.336C14.5026 20.0993 15.2126 19.8626 15.922 19.6733C16.6704 19.4701 17.4284 19.3043 18.1933 19.1766C20.0146 20.8086 21.6233 21.0693 22.428 21.0693C23.4213 21.0693 23.7766 20.6666 23.8946 20.336C24.108 19.9093 23.966 19.4366 23.7533 19.2ZM22.8066 19.8866C22.7353 20.2413 22.38 20.478 21.884 20.478C21.742 20.478 21.624 20.454 21.4813 20.4306C20.5826 20.2173 19.7306 19.768 18.8793 19.058C19.5357 18.947 20.2003 18.8917 20.866 18.8926C21.3633 18.8926 21.7893 18.916 22.0726 18.9873C22.404 19.058 22.9246 19.2713 22.806 19.886L22.8066 19.8866ZM17.7906 18.7746C17.1305 18.8983 16.4755 19.0482 15.8273 19.224C15.262 19.3709 14.7017 19.5366 14.1473 19.7206C14.4355 19.1625 14.7039 18.5944 14.952 18.0173C15.236 17.3546 15.472 16.6686 15.7093 16.03C15.9453 16.432 16.206 16.8346 16.466 17.1893C16.8911 17.7313 17.3329 18.26 17.7906 18.7746ZM14.692 9.97329C14.7338 9.88949 14.7978 9.81875 14.877 9.7688C14.9563 9.71884 15.0477 9.69157 15.1413 9.68996C15.638 9.68996 15.7326 10.2573 15.7326 10.7073C15.7326 11.464 15.496 12.6233 15.094 13.948C14.4073 12.1026 14.3606 10.5653 14.692 9.97329ZM12.0893 20.998C10.8826 22.9853 9.72331 24.2153 9.01398 24.2153C8.88599 24.2161 8.76132 24.1746 8.65931 24.0973C8.51731 23.9553 8.44598 23.79 8.49331 23.6006C8.63531 22.8906 10.0073 21.8973 12.0893 20.998Z",
|
|
1815
|
+
fill: "white"
|
|
1816
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1817
|
+
d: "M9.74219 34.4258V28.6992H10.8828V29.3633H10.9531C11.0286 29.2096 11.1276 29.0781 11.25 28.9688C11.375 28.8594 11.5208 28.776 11.6875 28.7188C11.8542 28.6589 12.0391 28.6289 12.2422 28.6289C12.6016 28.6289 12.9115 28.7188 13.1719 28.8984C13.4323 29.0781 13.6328 29.3333 13.7734 29.6641C13.9167 29.9922 13.9883 30.3854 13.9883 30.8438V30.8516C13.9883 31.3125 13.918 31.7083 13.7773 32.0391C13.6367 32.3698 13.4362 32.6237 13.1758 32.8008C12.9154 32.9779 12.6042 33.0664 12.2422 33.0664C12.0443 33.0664 11.8607 33.0365 11.6914 32.9766C11.5247 32.9141 11.3776 32.8268 11.25 32.7148C11.125 32.6029 11.026 32.4688 10.9531 32.3125H10.8828V34.4258H9.74219ZM11.8516 32.1211C12.0547 32.1211 12.2279 32.0703 12.3711 31.9688C12.5169 31.8672 12.6289 31.7214 12.707 31.5312C12.7878 31.3411 12.8281 31.1146 12.8281 30.8516V30.8438C12.8281 30.5807 12.7878 30.3542 12.707 30.1641C12.6289 29.974 12.5169 29.8281 12.3711 29.7266C12.2279 29.625 12.0547 29.5742 11.8516 29.5742C11.651 29.5742 11.4766 29.625 11.3281 29.7266C11.1823 29.8281 11.069 29.974 10.9883 30.1641C10.9102 30.3516 10.8711 30.5781 10.8711 30.8438V30.8516C10.8711 31.112 10.9115 31.3385 10.9922 31.5312C11.0729 31.7214 11.1862 31.8672 11.332 31.9688C11.4805 32.0703 11.6536 32.1211 11.8516 32.1211ZM16.457 33.0664C16.1003 33.0664 15.7904 32.9779 15.5273 32.8008C15.2669 32.6211 15.0651 32.3659 14.9219 32.0352C14.7812 31.7044 14.7109 31.3099 14.7109 30.8516V30.8438C14.7109 30.3828 14.7799 29.987 14.918 29.6562C15.0586 29.3255 15.2591 29.0716 15.5195 28.8945C15.7799 28.7174 16.0924 28.6289 16.457 28.6289C16.6523 28.6289 16.8333 28.6602 17 28.7227C17.1693 28.7826 17.3177 28.8685 17.4453 28.9805C17.5729 29.0924 17.6719 29.2279 17.7422 29.3867H17.8125V27.0547H18.9531V33H17.8125V32.332H17.7422C17.6693 32.4857 17.5703 32.6172 17.4453 32.7266C17.3229 32.8359 17.1784 32.9206 17.0117 32.9805C16.8451 33.0378 16.6602 33.0664 16.457 33.0664ZM16.8438 32.1211C17.0469 32.1211 17.2214 32.0703 17.3672 31.9688C17.513 31.8672 17.625 31.7214 17.7031 31.5312C17.7839 31.3411 17.8242 31.1159 17.8242 30.8555V30.8477C17.8242 30.582 17.7839 30.3555 17.7031 30.168C17.625 29.9779 17.5117 29.832 17.3633 29.7305C17.2174 29.6263 17.0443 29.5742 16.8438 29.5742C16.6458 29.5742 16.4727 29.6263 16.3242 29.7305C16.1784 29.832 16.0664 29.9779 15.9883 30.168C15.9102 30.3555 15.8711 30.5807 15.8711 30.8438V30.8516C15.8711 31.1146 15.9102 31.3411 15.9883 31.5312C16.0664 31.7214 16.1784 31.8672 16.3242 31.9688C16.4701 32.0703 16.6432 32.1211 16.8438 32.1211ZM20.4648 33V29.5586H19.7695V28.6992H20.4648V28.2969C20.4648 28.0104 20.5156 27.7721 20.6172 27.582C20.7188 27.3919 20.8776 27.25 21.0938 27.1562C21.3125 27.0599 21.5951 27.0117 21.9414 27.0117C22.0586 27.0117 22.1641 27.0156 22.2578 27.0234C22.3542 27.0312 22.444 27.0417 22.5273 27.0547V27.8164C22.4909 27.8086 22.4427 27.8034 22.3828 27.8008C22.3255 27.7956 22.2604 27.793 22.1875 27.793C21.9661 27.793 21.8099 27.8438 21.7188 27.9453C21.6276 28.0443 21.582 28.1875 21.582 28.375V28.6992H22.4922V29.5586H21.6055V33H20.4648Z",
|
|
1818
|
+
fill: "white"
|
|
1819
|
+
})] });
|
|
1820
|
+
var FilePdfIcon = ({ className, label, size, sizeConfig, ...props }) => {
|
|
1821
|
+
const useLegacyPdfMarkup = !!label;
|
|
1822
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Svg, {
|
|
1823
|
+
...props,
|
|
1824
|
+
className: (0, clsx.default)("str-chat__file-icon--pdf", useLegacyPdfMarkup && "str-chat__file-icon--no-label", className),
|
|
1825
|
+
size,
|
|
1826
|
+
sizeConfig,
|
|
1827
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
1828
|
+
className: FILE_ICON_GRAPHIC_CLASSNAME,
|
|
1829
|
+
children: [
|
|
1830
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1831
|
+
d: FILE_ICON_PAPER_PATH,
|
|
1832
|
+
fill: "#E71A01"
|
|
1833
|
+
}),
|
|
1834
|
+
useLegacyPdfMarkup ? PDF_LEGACY_SYMBOL : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("g", {
|
|
1835
|
+
transform: `scale(${FILE_ICON_WITHOUT_CAPTION_SYMBOL_SCALE_X} ${FILE_ICON_WITHOUT_CAPTION_SYMBOL_SCALE_Y})`,
|
|
1836
|
+
children: PDF_SMALL_SYMBOL
|
|
1837
|
+
}),
|
|
1838
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1839
|
+
d: FILE_ICON_FOLD_PATH,
|
|
1840
|
+
fill: "white",
|
|
1841
|
+
opacity: "0.5"
|
|
1842
|
+
})
|
|
1843
|
+
]
|
|
1844
|
+
})
|
|
1845
|
+
});
|
|
1846
|
+
};
|
|
1847
|
+
var FileWordIcon = ({ className, label, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1848
|
+
...props,
|
|
1849
|
+
className,
|
|
1850
|
+
color: "#3375E2",
|
|
1851
|
+
fileTypeClassName: "str-chat__file-icon--doc",
|
|
1852
|
+
label,
|
|
1853
|
+
symbols: TEXT_SYMBOLS
|
|
1854
|
+
});
|
|
1855
|
+
var FilePowerPointIcon = ({ className, label, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1856
|
+
...props,
|
|
1857
|
+
className,
|
|
1858
|
+
color: "#D14423",
|
|
1859
|
+
fileTypeClassName: "str-chat__file-icon--ppt",
|
|
1860
|
+
label,
|
|
1861
|
+
symbols: PRESENTATION_SYMBOLS
|
|
1862
|
+
});
|
|
1863
|
+
var FileExcelIcon = ({ className = "", label, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1864
|
+
...props,
|
|
1865
|
+
className,
|
|
1866
|
+
color: "#0C864B",
|
|
1867
|
+
fileTypeClassName: "str-chat__file-icon--xls",
|
|
1868
|
+
label,
|
|
1869
|
+
symbols: SPREADSHEET_SYMBOLS
|
|
1870
|
+
});
|
|
1871
|
+
var FileArchiveIcon = ({ className = "", label = "", ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1872
|
+
...props,
|
|
1873
|
+
className,
|
|
1874
|
+
color: "#E59E34",
|
|
1875
|
+
fileTypeClassName: "str-chat__file-icon--compressed",
|
|
1876
|
+
label,
|
|
1877
|
+
symbols: COMPRESSION_SYMBOLS
|
|
1878
|
+
});
|
|
1879
|
+
var FileCodeIcon = ({ className = "", label, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1880
|
+
...props,
|
|
1881
|
+
className,
|
|
1882
|
+
color: "#00ACA1",
|
|
1883
|
+
fileTypeClassName: "str-chat__file-icon--code",
|
|
1884
|
+
label,
|
|
1885
|
+
symbols: CODE_SYMBOLS
|
|
1886
|
+
});
|
|
1887
|
+
var FileAudioIcon = ({ className = "", label, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1888
|
+
...props,
|
|
1889
|
+
className,
|
|
1890
|
+
color: "#2727B0",
|
|
1891
|
+
fileTypeClassName: "str-chat__file-icon--audio",
|
|
1892
|
+
label,
|
|
1893
|
+
symbols: AUDIO_SYMBOLS
|
|
1894
|
+
});
|
|
1895
|
+
var FileVideoIcon = ({ className = "", label, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1896
|
+
...props,
|
|
1897
|
+
className,
|
|
1898
|
+
color: "#A847B7",
|
|
1899
|
+
fileTypeClassName: "str-chat__file-icon--video",
|
|
1900
|
+
label,
|
|
1901
|
+
symbols: VIDEO_SYMBOLS
|
|
1902
|
+
});
|
|
1903
|
+
var FileFallbackIcon = ({ className = "", label = "", ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StandardFileTypeIcon, {
|
|
1904
|
+
...props,
|
|
1905
|
+
className,
|
|
1906
|
+
color: "#888888",
|
|
1907
|
+
fileTypeClassName: "str-chat__file-icon--other",
|
|
1908
|
+
label,
|
|
1909
|
+
symbols: OTHER_SYMBOLS
|
|
1910
|
+
});
|
|
1911
|
+
//#endregion
|
|
1912
|
+
//#region src/components/FileIcon/mimeTypes.ts
|
|
1913
|
+
var wordMimeTypes = [
|
|
1914
|
+
"application/msword",
|
|
1915
|
+
"application/msword-template",
|
|
1916
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
1917
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
|
1918
|
+
"application/vnd.ms-word.document.macroEnabled.12",
|
|
1919
|
+
"application/vnd.ms-word.template.macroEnabled.12",
|
|
1920
|
+
"application/vnd.oasis.opendocument.text",
|
|
1921
|
+
"application/vnd.oasis.opendocument.text-template",
|
|
1922
|
+
"application/vnd.oasis.opendocument.text-flat-xml"
|
|
1923
|
+
];
|
|
1924
|
+
var excelMimeTypes = [
|
|
1925
|
+
"text/csv",
|
|
1926
|
+
"application/vnd.ms-excel",
|
|
1927
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
1928
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
|
1929
|
+
"application/vnd.ms-excel.sheet.macroEnabled.12",
|
|
1930
|
+
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
1931
|
+
"application/vnd.ms-excel.addin.macroEnabled.12",
|
|
1932
|
+
"application/vnd.ms-excel.addin.macroEnabled.12",
|
|
1933
|
+
"application/vnd.oasis.opendocument.spreadsheet",
|
|
1934
|
+
"application/vnd.oasis.opendocument.spreadsheet-template",
|
|
1935
|
+
"application/vnd.oasis.opendocument.spreadsheet-flat-xml"
|
|
1936
|
+
];
|
|
1937
|
+
var powerpointMimeTypes = [
|
|
1938
|
+
"application/vnd.ms-powerpoint",
|
|
1939
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
1940
|
+
"application/vnd.openxmlformats-officedocument.presentationml.template",
|
|
1941
|
+
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
|
1942
|
+
"application/vnd.ms-powerpoint.addin.macroEnabled.12",
|
|
1943
|
+
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
|
|
1944
|
+
"application/vnd.ms-powerpoint.template.macroEnabled.12",
|
|
1945
|
+
"application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
|
|
1946
|
+
"application/vnd.oasis.opendocument.presentation",
|
|
1947
|
+
"application/vnd.oasis.opendocument.presentation-template",
|
|
1948
|
+
"application/vnd.oasis.opendocument.presentation-flat-xml"
|
|
1949
|
+
];
|
|
1950
|
+
var archiveFileTypes = [
|
|
1951
|
+
"application/zip",
|
|
1952
|
+
"application/x-7z-compressed",
|
|
1953
|
+
"application/x-archive",
|
|
1954
|
+
"application/x-tar",
|
|
1955
|
+
"application/gzip",
|
|
1956
|
+
"application/x-compress",
|
|
1957
|
+
"application/x-bzip",
|
|
1958
|
+
"application/x-lzip",
|
|
1959
|
+
"application/x-lz4",
|
|
1960
|
+
"application/x-lzma",
|
|
1961
|
+
"application/x-lzop",
|
|
1962
|
+
"application/x-xz",
|
|
1963
|
+
"application/x-webarchive",
|
|
1964
|
+
"application/vnd.rar"
|
|
1965
|
+
];
|
|
1966
|
+
var codeFileTypes = [
|
|
1967
|
+
"text/html",
|
|
1968
|
+
"text/css",
|
|
1969
|
+
"application/x-javascript",
|
|
1970
|
+
"text/javascript",
|
|
1971
|
+
"application/json",
|
|
1972
|
+
"text/x-python",
|
|
1973
|
+
"text/x-go",
|
|
1974
|
+
"text/x-csrc",
|
|
1975
|
+
"text/x-c++src",
|
|
1976
|
+
"application/x-ruby",
|
|
1977
|
+
"text/rust",
|
|
1978
|
+
"text/x-java",
|
|
1979
|
+
"application/x-php",
|
|
1980
|
+
"text/x-csharp",
|
|
1981
|
+
"text/x-scala",
|
|
1982
|
+
"text/x-erlang",
|
|
1983
|
+
"application/x-shellscript"
|
|
1984
|
+
];
|
|
1985
|
+
var mimeTypeToExtensionMap = {
|
|
1986
|
+
"application/epub+zip": "epub",
|
|
1987
|
+
"application/gzip": "gz",
|
|
1988
|
+
"application/java-archive": "jar",
|
|
1989
|
+
"application/json": "json",
|
|
1990
|
+
"application/ld+json": "jsonld",
|
|
1991
|
+
"application/msword": "doc",
|
|
1992
|
+
"application/msword-template": "dot",
|
|
1993
|
+
"application/octet-stream": "bin",
|
|
1994
|
+
"application/ogg": "ogx",
|
|
1995
|
+
"application/pdf": "pdf",
|
|
1996
|
+
"application/postscript": "ps",
|
|
1997
|
+
"application/rtf": "rtf",
|
|
1998
|
+
"application/vnd.amazon.ebook": "azw",
|
|
1999
|
+
"application/vnd.apple.installer+xml": "mpkg",
|
|
2000
|
+
"application/vnd.mozilla.xul+xml": "xul",
|
|
2001
|
+
"application/vnd.ms-excel": "xls",
|
|
2002
|
+
"application/vnd.ms-excel.addin.macroEnabled.12": "xlam",
|
|
2003
|
+
"application/vnd.ms-excel.sheet.macroEnabled.12": "xlsm",
|
|
2004
|
+
"application/vnd.ms-excel.template.macroEnabled.12": "xltm",
|
|
2005
|
+
"application/vnd.ms-fontobject": "eot",
|
|
2006
|
+
"application/vnd.ms-powerpoint": "ppt",
|
|
2007
|
+
"application/vnd.ms-powerpoint.addin.macroEnabled.12": "ppam",
|
|
2008
|
+
"application/vnd.ms-powerpoint.presentation.macroEnabled.12": "pptm",
|
|
2009
|
+
"application/vnd.ms-powerpoint.slideshow.macroEnabled.12": "ppsm",
|
|
2010
|
+
"application/vnd.ms-powerpoint.template.macroEnabled.12": "potm",
|
|
2011
|
+
"application/vnd.ms-word.document.macroEnabled.12": "docm",
|
|
2012
|
+
"application/vnd.ms-word.template.macroEnabled.12": "dotm",
|
|
2013
|
+
"application/vnd.oasis.opendocument.presentation": "odp",
|
|
2014
|
+
"application/vnd.oasis.opendocument.presentation-flat-xml": "fodp",
|
|
2015
|
+
"application/vnd.oasis.opendocument.presentation-template": "otp",
|
|
2016
|
+
"application/vnd.oasis.opendocument.spreadsheet": "ods",
|
|
2017
|
+
"application/vnd.oasis.opendocument.spreadsheet-flat-xml": "fods",
|
|
2018
|
+
"application/vnd.oasis.opendocument.spreadsheet-template": "ots",
|
|
2019
|
+
"application/vnd.oasis.opendocument.text": "odt",
|
|
2020
|
+
"application/vnd.oasis.opendocument.text-flat-xml": "fodt",
|
|
2021
|
+
"application/vnd.oasis.opendocument.text-template": "ott",
|
|
2022
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
|
|
2023
|
+
"application/vnd.openxmlformats-officedocument.presentationml.slideshow": "ppsx",
|
|
2024
|
+
"application/vnd.openxmlformats-officedocument.presentationml.template": "potx",
|
|
2025
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
|
2026
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.template": "xltx",
|
|
2027
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
2028
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.template": "dotx",
|
|
2029
|
+
"application/vnd.rar": "rar",
|
|
2030
|
+
"application/vnd.visio": "vsd",
|
|
2031
|
+
"application/wasm": "wasm",
|
|
2032
|
+
"application/x-7z-compressed": "7z",
|
|
2033
|
+
"application/x-abiword": "abw",
|
|
2034
|
+
"application/x-archive": "ar",
|
|
2035
|
+
"application/x-bzip": "bz",
|
|
2036
|
+
"application/x-bzip2": "bz2",
|
|
2037
|
+
"application/x-cdf": "cda",
|
|
2038
|
+
"application/x-compress": "Z",
|
|
2039
|
+
"application/x-csh": "csh",
|
|
2040
|
+
"application/x-dosexec": "exe",
|
|
2041
|
+
"application/x-freearc": "arc",
|
|
2042
|
+
"application/x-httpd-php": "php",
|
|
2043
|
+
"application/x-iso9660-image": "iso",
|
|
2044
|
+
"application/x-javascript": "js",
|
|
2045
|
+
"application/x-lz4": "lz4",
|
|
2046
|
+
"application/x-lzip": "lz",
|
|
2047
|
+
"application/x-lzma": "lzma",
|
|
2048
|
+
"application/x-lzop": "lzo",
|
|
2049
|
+
"application/x-mobipocket-ebook": "mobi",
|
|
2050
|
+
"application/x-msdownload": "exe",
|
|
2051
|
+
"application/x-perl": "pl",
|
|
2052
|
+
"application/x-php": "php",
|
|
2053
|
+
"application/x-rar-compressed": "rar",
|
|
2054
|
+
"application/x-ruby": "rb",
|
|
2055
|
+
"application/x-sh": "sh",
|
|
2056
|
+
"application/x-shellscript": "sh",
|
|
2057
|
+
"application/x-shockwave-flash": "swf",
|
|
2058
|
+
"application/x-sql": "sql",
|
|
2059
|
+
"application/x-stuffit": "sit",
|
|
2060
|
+
"application/x-tar": "tar",
|
|
2061
|
+
"application/x-webarchive": "war",
|
|
2062
|
+
"application/x-xz": "xz",
|
|
2063
|
+
"application/x-yaml": "yaml",
|
|
2064
|
+
"application/xhtml+xml": "xhtml",
|
|
2065
|
+
"application/xml": "xml",
|
|
2066
|
+
"application/zip": "zip",
|
|
2067
|
+
"audio/aac": "aac",
|
|
2068
|
+
"audio/flac": "flac",
|
|
2069
|
+
"audio/midi": "midi",
|
|
2070
|
+
"audio/mp4": "m4a",
|
|
2071
|
+
"audio/mpeg": "mp3",
|
|
2072
|
+
"audio/ogg": "oga",
|
|
2073
|
+
"audio/opus": "opus",
|
|
2074
|
+
"audio/wav": "wav",
|
|
2075
|
+
"audio/webm": "weba",
|
|
2076
|
+
"audio/x-aiff": "aiff",
|
|
2077
|
+
"audio/x-m4a": "m4a",
|
|
2078
|
+
"audio/x-midi": "midi",
|
|
2079
|
+
"audio/x-ms-wma": "wma",
|
|
2080
|
+
"audio/x-wav": "wav",
|
|
2081
|
+
"font/otf": "otf",
|
|
2082
|
+
"font/ttf": "ttf",
|
|
2083
|
+
"font/woff": "woff",
|
|
2084
|
+
"font/woff2": "woff2",
|
|
2085
|
+
"image/apng": "apng",
|
|
2086
|
+
"image/avif": "avif",
|
|
2087
|
+
"image/bmp": "bmp",
|
|
2088
|
+
"image/gif": "gif",
|
|
2089
|
+
"image/heic": "heic",
|
|
2090
|
+
"image/heif": "heif",
|
|
2091
|
+
"image/jpeg": "jpg",
|
|
2092
|
+
"image/png": "png",
|
|
2093
|
+
"image/svg+xml": "svg",
|
|
2094
|
+
"image/tiff": "tiff",
|
|
2095
|
+
"image/vnd.microsoft.icon": "ico",
|
|
2096
|
+
"image/webp": "webp",
|
|
2097
|
+
"image/x-icon": "ico",
|
|
2098
|
+
"text/calendar": "ics",
|
|
2099
|
+
"text/css": "css",
|
|
2100
|
+
"text/csv": "csv",
|
|
2101
|
+
"text/html": "html",
|
|
2102
|
+
"text/javascript": "js",
|
|
2103
|
+
"text/markdown": "md",
|
|
2104
|
+
"text/plain": "txt",
|
|
2105
|
+
"text/rtf": "rtf",
|
|
2106
|
+
"text/rust": "rs",
|
|
2107
|
+
"text/tab-separated-values": "tsv",
|
|
2108
|
+
"text/vcard": "vcf",
|
|
2109
|
+
"text/x-c": "c",
|
|
2110
|
+
"text/x-c++src": "cpp",
|
|
2111
|
+
"text/x-csharp": "cs",
|
|
2112
|
+
"text/x-csrc": "c",
|
|
2113
|
+
"text/x-diff": "diff",
|
|
2114
|
+
"text/x-erlang": "erl",
|
|
2115
|
+
"text/x-go": "go",
|
|
2116
|
+
"text/x-java": "java",
|
|
2117
|
+
"text/x-java-source": "java",
|
|
2118
|
+
"text/x-kotlin": "kt",
|
|
2119
|
+
"text/x-lua": "lua",
|
|
2120
|
+
"text/x-markdown": "md",
|
|
2121
|
+
"text/x-objectivec": "m",
|
|
2122
|
+
"text/x-pascal": "pas",
|
|
2123
|
+
"text/x-perl": "pl",
|
|
2124
|
+
"text/x-python": "py",
|
|
2125
|
+
"text/x-ruby": "rb",
|
|
2126
|
+
"text/x-rust": "rs",
|
|
2127
|
+
"text/x-scala": "scala",
|
|
2128
|
+
"text/x-sh": "sh",
|
|
2129
|
+
"text/x-shellscript": "sh",
|
|
2130
|
+
"text/x-sql": "sql",
|
|
2131
|
+
"text/x-swift": "swift",
|
|
2132
|
+
"text/x-typescript": "ts",
|
|
2133
|
+
"text/x-yaml": "yaml",
|
|
2134
|
+
"text/xml": "xml",
|
|
2135
|
+
"text/yaml": "yaml",
|
|
2136
|
+
"video/3gpp": "3gp",
|
|
2137
|
+
"video/3gpp2": "3g2",
|
|
2138
|
+
"video/mp2t": "ts",
|
|
2139
|
+
"video/mp4": "mp4",
|
|
2140
|
+
"video/mpeg": "mpeg",
|
|
2141
|
+
"video/ogg": "ogv",
|
|
2142
|
+
"video/quicktime": "mov",
|
|
2143
|
+
"video/webm": "webm",
|
|
2144
|
+
"video/x-flv": "flv",
|
|
2145
|
+
"video/x-m4v": "m4v",
|
|
2146
|
+
"video/x-matroska": "mkv",
|
|
2147
|
+
"video/x-ms-wmv": "wmv",
|
|
2148
|
+
"video/x-msvideo": "avi"
|
|
2149
|
+
};
|
|
2150
|
+
//#endregion
|
|
2151
|
+
//#region src/components/FileIcon/iconMap.ts
|
|
2152
|
+
function generateMimeTypeToIconMap({ FileArchiveIcon, FileCodeIcon, FileExcelIcon, FilePdfIcon, FilePowerPointIcon, FileWordIcon }) {
|
|
2153
|
+
const mimeTypeToIconMap = { "application/pdf": FilePdfIcon };
|
|
2154
|
+
for (const type of wordMimeTypes) mimeTypeToIconMap[type] = FileWordIcon;
|
|
2155
|
+
for (const type of excelMimeTypes) mimeTypeToIconMap[type] = FileExcelIcon;
|
|
2156
|
+
for (const type of powerpointMimeTypes) mimeTypeToIconMap[type] = FilePowerPointIcon;
|
|
2157
|
+
for (const type of archiveFileTypes) mimeTypeToIconMap[type] = FileArchiveIcon;
|
|
2158
|
+
for (const type of codeFileTypes) mimeTypeToIconMap[type] = FileCodeIcon;
|
|
2159
|
+
return mimeTypeToIconMap;
|
|
2160
|
+
}
|
|
2161
|
+
function generateGeneralTypeToIconMap({ FileAltIcon, FileAudioIcon, FileFallbackIcon, FileVideoIcon }) {
|
|
2162
|
+
return {
|
|
2163
|
+
"audio/": FileAudioIcon,
|
|
2164
|
+
"image/": FileFallbackIcon,
|
|
2165
|
+
"text/": FileAltIcon,
|
|
2166
|
+
"video/": FileVideoIcon
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
var iconMap = { standard: {
|
|
2170
|
+
...generateMimeTypeToIconMap({
|
|
2171
|
+
FileArchiveIcon,
|
|
2172
|
+
FileCodeIcon,
|
|
2173
|
+
FileExcelIcon,
|
|
2174
|
+
FilePdfIcon,
|
|
2175
|
+
FilePowerPointIcon,
|
|
2176
|
+
FileWordIcon
|
|
2177
|
+
}),
|
|
2178
|
+
...generateGeneralTypeToIconMap({
|
|
2179
|
+
FileAltIcon: FileFallbackIcon,
|
|
2180
|
+
FileAudioIcon,
|
|
2181
|
+
FileFallbackIcon,
|
|
2182
|
+
FileVideoIcon
|
|
2183
|
+
}),
|
|
2184
|
+
fallback: FileFallbackIcon
|
|
2185
|
+
} };
|
|
2186
|
+
//#endregion
|
|
2187
|
+
//#region src/components/FileIcon/FileIcon.tsx
|
|
2188
|
+
function mimeTypeToIcon(mimeType) {
|
|
2189
|
+
const theMap = iconMap["standard"];
|
|
2190
|
+
if (!mimeType) return theMap.fallback;
|
|
2191
|
+
const icon = theMap[mimeType];
|
|
2192
|
+
if (icon) return icon;
|
|
2193
|
+
if (mimeType.startsWith("audio/")) return theMap["audio/"] ?? theMap.fallback;
|
|
2194
|
+
if (mimeType.startsWith("video/")) return theMap["video/"] ?? theMap.fallback;
|
|
2195
|
+
if (mimeType.startsWith("image/")) return theMap["image/"] ?? theMap.fallback;
|
|
2196
|
+
if (mimeType.startsWith("text/")) return theMap["text/"] ?? theMap.fallback;
|
|
2197
|
+
return theMap.fallback;
|
|
2198
|
+
}
|
|
2199
|
+
var labelFromMimeType = ({ fileName, mimeType }) => {
|
|
2200
|
+
let label;
|
|
2201
|
+
if (mimeType) label = mimeTypeToExtensionMap[mimeType];
|
|
2202
|
+
if (!label && fileName) label = fileName.split(".").slice(-1)[0];
|
|
2203
|
+
return label;
|
|
2204
|
+
};
|
|
2205
|
+
var FileIcon = (props) => {
|
|
2206
|
+
const { className, fileName, mimeType, size = "md", sizeConfig: sizeConfigOverride, ...rest } = props;
|
|
2207
|
+
const sizeConfig = (0, react.useMemo)(() => mergeFileIconSizeConfig(sizeConfigOverride), [sizeConfigOverride]);
|
|
2208
|
+
const Icon = mimeTypeToIcon(mimeType);
|
|
2209
|
+
const label = fileName ? labelFromMimeType({
|
|
2210
|
+
fileName,
|
|
2211
|
+
mimeType
|
|
2212
|
+
}) : void 0;
|
|
2213
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
2214
|
+
...rest,
|
|
2215
|
+
className,
|
|
2216
|
+
label,
|
|
2217
|
+
size,
|
|
2218
|
+
sizeConfig
|
|
2219
|
+
});
|
|
2220
|
+
};
|
|
2221
|
+
//#endregion
|
|
2222
|
+
//#region src/components/AudioPlayback/components/formatTime.ts
|
|
2223
|
+
var formatTime = (totalSeconds, rounding = "ceil") => {
|
|
2224
|
+
if (totalSeconds == null || Number.isNaN(totalSeconds) || totalSeconds < 0) return null;
|
|
2225
|
+
const roundedSeconds = rounding === "floor" ? Math.floor(totalSeconds) : Math.ceil(totalSeconds);
|
|
2226
|
+
const hours = Math.floor(roundedSeconds / 3600);
|
|
2227
|
+
const minutes = Math.floor(roundedSeconds % 3600 / 60);
|
|
2228
|
+
const seconds = roundedSeconds % 60;
|
|
2229
|
+
const minSec = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
|
|
2230
|
+
return hours ? `${String(hours).padStart(2, "0")}:${minSec}` : minSec;
|
|
2231
|
+
};
|
|
2232
|
+
//#endregion
|
|
2233
|
+
//#region src/components/BaseImage/ImagePlaceholder.tsx
|
|
2234
|
+
var ImagePlaceholder = ({ className }) => {
|
|
2235
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
2236
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2237
|
+
"aria-label": t("aria/Image failed to load"),
|
|
2238
|
+
className: (0, clsx.default)("str-chat__image-placeholder", className),
|
|
2239
|
+
"data-testid": "str-chat__base-image-placeholder",
|
|
2240
|
+
role: "img",
|
|
2241
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconImage, {})
|
|
2242
|
+
});
|
|
2243
|
+
};
|
|
2244
|
+
//#endregion
|
|
2245
|
+
//#region src/components/BaseImage/BaseImage.tsx
|
|
2246
|
+
var BaseImage = (0, react.forwardRef)(function BaseImage({ src, ...props }, ref) {
|
|
2247
|
+
const { alt: propsAlt, className: propsClassName, onError: propsOnError, showDownloadButtonOnError = false, ...imgProps } = props;
|
|
2248
|
+
const [failedSrc, setFailedSrc] = (0, react.useState)(null);
|
|
2249
|
+
const { ImagePlaceholder: ImagePlaceholderComponent = ImagePlaceholder } = require_useNotificationApi.useComponentContext();
|
|
2250
|
+
const sanitizedUrl = (0, react.useMemo)(() => (0, _braintree_sanitize_url.sanitizeUrl)(src), [src]);
|
|
2251
|
+
const error = failedSrc === sanitizedUrl;
|
|
2252
|
+
(0, react.useEffect)(() => () => {
|
|
2253
|
+
setFailedSrc(null);
|
|
2254
|
+
}, [sanitizedUrl]);
|
|
2255
|
+
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImagePlaceholderComponent, { className: (0, clsx.default)(propsClassName, "str-chat__base-image--load-failed") }), showDownloadButtonOnError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DownloadButton, { assetUrl: sanitizedUrl })] });
|
|
2256
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
2257
|
+
"data-testid": "str-chat__base-image",
|
|
2258
|
+
...imgProps,
|
|
2259
|
+
alt: propsAlt ?? "",
|
|
2260
|
+
className: (0, clsx.default)(propsClassName, "str-chat__base-image"),
|
|
2261
|
+
onError: (e) => {
|
|
2262
|
+
setFailedSrc(sanitizedUrl);
|
|
2263
|
+
propsOnError?.(e);
|
|
2264
|
+
},
|
|
2265
|
+
ref,
|
|
2266
|
+
src: sanitizedUrl
|
|
2267
|
+
});
|
|
2268
|
+
});
|
|
2269
|
+
//#endregion
|
|
2270
|
+
//#region src/components/BaseImage/toBaseImageDescriptors.ts
|
|
2271
|
+
/**
|
|
2272
|
+
* Maps an attachment (or link preview) to image/video URLs and metadata for {@link BaseImage} or the gallery.
|
|
2273
|
+
*/
|
|
2274
|
+
var toBaseImageDescriptors = (attachment, options = {}) => {
|
|
2275
|
+
if ((0, stream_chat.isGiphyAttachment)(attachment)) {
|
|
2276
|
+
const giphyVersion = options?.giphyVersionName && attachment.giphy ? attachment.giphy[options.giphyVersionName] : void 0;
|
|
2277
|
+
return {
|
|
2278
|
+
alt: giphyVersion?.url || attachment.thumb_url,
|
|
2279
|
+
dimensions: giphyVersion ? {
|
|
2280
|
+
height: giphyVersion.height,
|
|
2281
|
+
width: giphyVersion.width
|
|
2282
|
+
} : void 0,
|
|
2283
|
+
imageUrl: attachment.thumb_url,
|
|
2284
|
+
title: attachment.title || attachment.thumb_url
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
if ((0, stream_chat.isScrapedContent)(attachment)) {
|
|
2288
|
+
const imageUrl = attachment.image_url || attachment.thumb_url;
|
|
2289
|
+
return {
|
|
2290
|
+
alt: attachment.title || imageUrl,
|
|
2291
|
+
imageUrl,
|
|
2292
|
+
title: attachment.title
|
|
2293
|
+
};
|
|
2294
|
+
}
|
|
2295
|
+
if ((0, stream_chat.isLocalVideoAttachment)(attachment)) return {
|
|
2296
|
+
title: attachment.title,
|
|
2297
|
+
videoThumbnailUrl: attachment.thumb_url ?? attachment.localMetadata.previewUri,
|
|
2298
|
+
videoUrl: attachment.asset_url ?? attachment.localMetadata.previewUri
|
|
2299
|
+
};
|
|
2300
|
+
if ((0, stream_chat.isVideoAttachment)(attachment)) return {
|
|
2301
|
+
title: attachment.title,
|
|
2302
|
+
videoThumbnailUrl: attachment.thumb_url,
|
|
2303
|
+
videoUrl: attachment.asset_url
|
|
2304
|
+
};
|
|
2305
|
+
if ((0, stream_chat.isLocalImageAttachment)(attachment)) {
|
|
2306
|
+
const imageUrl = attachment.image_url || attachment.localMetadata.previewUri;
|
|
2307
|
+
return {
|
|
2308
|
+
alt: attachment.title || imageUrl,
|
|
2309
|
+
imageUrl,
|
|
2310
|
+
title: attachment.title
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
if ((0, stream_chat.isImageAttachment)(attachment)) {
|
|
2314
|
+
const imageUrl = attachment.image_url;
|
|
2315
|
+
return {
|
|
2316
|
+
alt: attachment.title || imageUrl,
|
|
2317
|
+
imageUrl,
|
|
2318
|
+
title: attachment.title
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
};
|
|
2322
|
+
//#endregion
|
|
2323
|
+
//#region src/components/Gallery/GalleryContext.tsx
|
|
2324
|
+
/**
|
|
2325
|
+
* Maps an attachment (or link preview) to gallery item fields.
|
|
2326
|
+
* Delegates to {@link toBaseImageDescriptors}.
|
|
2327
|
+
*/
|
|
2328
|
+
var toGalleryItemDescriptors = (...args) => toBaseImageDescriptors(...args);
|
|
2329
|
+
var GalleryContext = (0, react.createContext)(void 0);
|
|
2330
|
+
var useGalleryContext = () => {
|
|
2331
|
+
const contextValue = (0, react.useContext)(GalleryContext);
|
|
2332
|
+
if (!contextValue) {
|
|
2333
|
+
console.warn(`The useGalleryContext hook was called outside of the GalleryContext provider. Make sure this hook is called within a child of the Gallery component.`);
|
|
2334
|
+
return {};
|
|
2335
|
+
}
|
|
2336
|
+
return contextValue;
|
|
2337
|
+
};
|
|
2338
|
+
//#endregion
|
|
2339
|
+
//#region src/components/Gallery/GalleryHeader.tsx
|
|
2340
|
+
var GalleryHeader = ({ currentItem }) => {
|
|
2341
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
2342
|
+
const { MessageTimestamp: MessageTimestamp$1 = MessageTimestamp } = require_useNotificationApi.useComponentContext("GalleryUI");
|
|
2343
|
+
const { isMyMessage, message } = useMessageContext("GalleryUI");
|
|
2344
|
+
const modalContext = (0, react.useContext)(ModalContext);
|
|
2345
|
+
const headerTitle = isMyMessage?.() && t("You") || message?.user?.name || message?.user?.id || currentItem.title || t("User uploaded content");
|
|
2346
|
+
const downloadUrl = (0, react.useMemo)(() => {
|
|
2347
|
+
const rawDownloadUrl = currentItem.videoUrl ?? currentItem.imageUrl;
|
|
2348
|
+
if (!rawDownloadUrl) return void 0;
|
|
2349
|
+
const sanitizedUrl = (0, _braintree_sanitize_url.sanitizeUrl)(rawDownloadUrl);
|
|
2350
|
+
return sanitizedUrl === "about:blank" ? void 0 : sanitizedUrl;
|
|
2351
|
+
}, [currentItem.imageUrl, currentItem.videoUrl]);
|
|
2352
|
+
const downloadLabel = t("aria/Download attachment");
|
|
2353
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2354
|
+
className: "str-chat__gallery__header",
|
|
2355
|
+
children: [
|
|
2356
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2357
|
+
"aria-hidden": "true",
|
|
2358
|
+
className: "str-chat__gallery__header-spacer"
|
|
2359
|
+
}),
|
|
2360
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2361
|
+
className: "str-chat__gallery__header-meta",
|
|
2362
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2363
|
+
className: "str-chat__gallery__title",
|
|
2364
|
+
children: headerTitle
|
|
2365
|
+
}), message?.created_at ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessageTimestamp$1, { customClass: "str-chat__gallery__timestamp" }) : null]
|
|
2366
|
+
}),
|
|
2367
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2368
|
+
className: "str-chat__gallery__header-actions",
|
|
2369
|
+
children: [downloadUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
2370
|
+
"aria-label": downloadLabel,
|
|
2371
|
+
className: "str-chat__gallery__action-button str-chat__gallery__action-button--download",
|
|
2372
|
+
download: true,
|
|
2373
|
+
href: downloadUrl,
|
|
2374
|
+
rel: "noreferrer",
|
|
2375
|
+
target: "_blank",
|
|
2376
|
+
title: downloadLabel,
|
|
2377
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconArrowDownCircle, {})
|
|
2378
|
+
}) : null, modalContext?.close ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
2379
|
+
"aria-label": t("Close"),
|
|
2380
|
+
className: "str-chat__gallery__action-button str-chat__gallery__action-button--close",
|
|
2381
|
+
onClick: modalContext.close,
|
|
2382
|
+
title: t("Close"),
|
|
2383
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconXmark, {})
|
|
2384
|
+
}) : null]
|
|
2385
|
+
})
|
|
2386
|
+
]
|
|
2387
|
+
});
|
|
2388
|
+
};
|
|
2389
|
+
//#endregion
|
|
2390
|
+
//#region src/components/VideoPlayer/VideoPlayer.tsx
|
|
2391
|
+
var ReactPlayer = react.default.lazy(() => Promise.resolve().then(() => require("./ReactPlayerWrapper.30240f76.js")));
|
|
2392
|
+
var VideoPlayer = ({ isPlaying, thumbnailUrl, videoUrl }) => {
|
|
2393
|
+
const { LoadingIndicator: LoadingIndicator$1 = LoadingIndicator, VideoPlayer: VideoPlayerContext } = require_useNotificationApi.useComponentContext();
|
|
2394
|
+
return VideoPlayerContext ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VideoPlayerContext, {
|
|
2395
|
+
thumbnailUrl,
|
|
2396
|
+
videoUrl
|
|
2397
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.default.Suspense, {
|
|
2398
|
+
fallback: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2399
|
+
className: "str-chat__video-player-loading",
|
|
2400
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoadingIndicator$1, {})
|
|
2401
|
+
}),
|
|
2402
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactPlayer, {
|
|
2403
|
+
isPlaying,
|
|
2404
|
+
thumbnailUrl,
|
|
2405
|
+
videoUrl
|
|
2406
|
+
})
|
|
2407
|
+
});
|
|
2408
|
+
};
|
|
2409
|
+
//#endregion
|
|
2410
|
+
//#region src/components/VideoPlayer/VideoThumbnail.tsx
|
|
2411
|
+
var VideoThumbnail = ({ className, onPlay, ...imageProps }) => {
|
|
2412
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
2413
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2414
|
+
className: "str-chat__message-attachment__video-thumbnail",
|
|
2415
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(BaseImage, {
|
|
2416
|
+
className: (0, clsx.default)("str-chat__message-attachment__video-thumbnail-image", className),
|
|
2417
|
+
...imageProps
|
|
2418
|
+
}), onPlay ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
2419
|
+
appearance: "solid",
|
|
2420
|
+
"aria-label": t("Play video"),
|
|
2421
|
+
circular: true,
|
|
2422
|
+
className: (0, clsx.default)("str-chat__message-attachment__video-thumbnail__play-indicator"),
|
|
2423
|
+
onClick: onPlay,
|
|
2424
|
+
size: "lg",
|
|
2425
|
+
variant: "secondary",
|
|
2426
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconPlayFill, {})
|
|
2427
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2428
|
+
className: "str-chat__message-attachment__video-thumbnail__play-indicator",
|
|
2429
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconPlayFill, {})
|
|
2430
|
+
})]
|
|
2431
|
+
});
|
|
2432
|
+
};
|
|
2433
|
+
//#endregion
|
|
2434
|
+
//#region src/components/Gallery/GalleryUI.tsx
|
|
2435
|
+
var SWIPE_THRESHOLD = 50;
|
|
2436
|
+
var TRANSITION_DURATION = 300;
|
|
2437
|
+
var GalleryUI = () => {
|
|
2438
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
2439
|
+
const { closeOnBackgroundClick, currentIndex, currentItem, goToNext, goToPrevious, hasNext, hasPrevious, itemCount, onRequestClose } = useGalleryContext();
|
|
2440
|
+
const modalContext = (0, react.useContext)(ModalContext);
|
|
2441
|
+
const [showVideo, setShowVideo] = (0, react.useState)(false);
|
|
2442
|
+
const isTransitioningRef = (0, react.useRef)(false);
|
|
2443
|
+
const [slideOffset, setSlideOffset] = (0, react.useState)(0);
|
|
2444
|
+
const [isDragging, setIsDragging] = (0, react.useState)(false);
|
|
2445
|
+
const [slideDirection, setSlideDirection] = (0, react.useState)(null);
|
|
2446
|
+
const ignoreNextClickRef = (0, react.useRef)(false);
|
|
2447
|
+
const touchStartRef = (0, react.useRef)(null);
|
|
2448
|
+
const isVerticalSwipeRef = (0, react.useRef)(false);
|
|
2449
|
+
const containerRef = (0, react.useRef)(null);
|
|
2450
|
+
(0, react.useEffect)(() => {
|
|
2451
|
+
setShowVideo(false);
|
|
2452
|
+
}, [currentIndex]);
|
|
2453
|
+
const prevIndexRef = (0, react.useRef)(currentIndex);
|
|
2454
|
+
(0, react.useEffect)(() => {
|
|
2455
|
+
if (prevIndexRef.current === currentIndex) return;
|
|
2456
|
+
setSlideDirection(currentIndex > prevIndexRef.current ? "forward" : "backward");
|
|
2457
|
+
setSlideOffset(0);
|
|
2458
|
+
setIsDragging(false);
|
|
2459
|
+
isTransitioningRef.current = true;
|
|
2460
|
+
const timer = setTimeout(() => {
|
|
2461
|
+
setSlideDirection(null);
|
|
2462
|
+
isTransitioningRef.current = false;
|
|
2463
|
+
}, TRANSITION_DURATION);
|
|
2464
|
+
prevIndexRef.current = currentIndex;
|
|
2465
|
+
return () => clearTimeout(timer);
|
|
2466
|
+
}, [currentIndex]);
|
|
2467
|
+
const handleGoToNext = (0, react.useCallback)(() => {
|
|
2468
|
+
if (isTransitioningRef.current) return;
|
|
2469
|
+
goToNext();
|
|
2470
|
+
}, [goToNext]);
|
|
2471
|
+
const handleGoToPrevious = (0, react.useCallback)(() => {
|
|
2472
|
+
if (isTransitioningRef.current) return;
|
|
2473
|
+
goToPrevious();
|
|
2474
|
+
}, [goToPrevious]);
|
|
2475
|
+
const handleKeyDown = (0, react.useCallback)((event) => {
|
|
2476
|
+
if (event.key === "ArrowLeft") {
|
|
2477
|
+
event.preventDefault();
|
|
2478
|
+
handleGoToPrevious();
|
|
2479
|
+
} else if (event.key === "ArrowRight") {
|
|
2480
|
+
event.preventDefault();
|
|
2481
|
+
handleGoToNext();
|
|
2482
|
+
}
|
|
2483
|
+
}, [handleGoToNext, handleGoToPrevious]);
|
|
2484
|
+
(0, react.useEffect)(() => {
|
|
2485
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2486
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
2487
|
+
}, [handleKeyDown]);
|
|
2488
|
+
const handleTouchStart = (0, react.useCallback)((event) => {
|
|
2489
|
+
if (isTransitioningRef.current) return;
|
|
2490
|
+
const touch = event.touches[0];
|
|
2491
|
+
ignoreNextClickRef.current = false;
|
|
2492
|
+
touchStartRef.current = {
|
|
2493
|
+
x: touch.clientX,
|
|
2494
|
+
y: touch.clientY
|
|
2495
|
+
};
|
|
2496
|
+
isVerticalSwipeRef.current = false;
|
|
2497
|
+
}, []);
|
|
2498
|
+
const handleTouchMove = (0, react.useCallback)((event) => {
|
|
2499
|
+
if (!touchStartRef.current || isTransitioningRef.current) return;
|
|
2500
|
+
const touch = event.touches[0];
|
|
2501
|
+
const deltaX = touch.clientX - touchStartRef.current.x;
|
|
2502
|
+
const deltaY = touch.clientY - touchStartRef.current.y;
|
|
2503
|
+
if (!isDragging && !isVerticalSwipeRef.current) {
|
|
2504
|
+
if (Math.abs(deltaY) > Math.abs(deltaX) && Math.abs(deltaY) > 10) {
|
|
2505
|
+
ignoreNextClickRef.current = true;
|
|
2506
|
+
isVerticalSwipeRef.current = true;
|
|
2507
|
+
return;
|
|
2508
|
+
}
|
|
2509
|
+
if (Math.abs(deltaX) > 10) {
|
|
2510
|
+
ignoreNextClickRef.current = true;
|
|
2511
|
+
setIsDragging(true);
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
if (isVerticalSwipeRef.current) return;
|
|
2515
|
+
if (!hasNext && deltaX < 0 || !hasPrevious && deltaX > 0) setSlideOffset(deltaX * .3);
|
|
2516
|
+
else setSlideOffset(deltaX);
|
|
2517
|
+
}, [
|
|
2518
|
+
isDragging,
|
|
2519
|
+
hasNext,
|
|
2520
|
+
hasPrevious
|
|
2521
|
+
]);
|
|
2522
|
+
const handleTouchEnd = (0, react.useCallback)(() => {
|
|
2523
|
+
if (!touchStartRef.current || isVerticalSwipeRef.current) {
|
|
2524
|
+
if (isVerticalSwipeRef.current) ignoreNextClickRef.current = true;
|
|
2525
|
+
touchStartRef.current = null;
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
const offset = slideOffset;
|
|
2529
|
+
if (isDragging || Math.abs(offset) > 10) ignoreNextClickRef.current = true;
|
|
2530
|
+
touchStartRef.current = null;
|
|
2531
|
+
if (Math.abs(offset) >= SWIPE_THRESHOLD) if (offset < 0 && hasNext) goToNext();
|
|
2532
|
+
else if (offset > 0 && hasPrevious) goToPrevious();
|
|
2533
|
+
else setSlideOffset(0);
|
|
2534
|
+
else setSlideOffset(0);
|
|
2535
|
+
setIsDragging(false);
|
|
2536
|
+
}, [
|
|
2537
|
+
slideOffset,
|
|
2538
|
+
hasNext,
|
|
2539
|
+
hasPrevious,
|
|
2540
|
+
goToNext,
|
|
2541
|
+
goToPrevious,
|
|
2542
|
+
isDragging
|
|
2543
|
+
]);
|
|
2544
|
+
const requestClose = modalContext?.close ?? onRequestClose;
|
|
2545
|
+
const handleBackgroundClick = (0, react.useCallback)((event) => {
|
|
2546
|
+
if (event.target !== event.currentTarget) return;
|
|
2547
|
+
if (ignoreNextClickRef.current) {
|
|
2548
|
+
ignoreNextClickRef.current = false;
|
|
2549
|
+
return;
|
|
2550
|
+
}
|
|
2551
|
+
if (!closeOnBackgroundClick) return;
|
|
2552
|
+
requestClose?.();
|
|
2553
|
+
}, [closeOnBackgroundClick, requestClose]);
|
|
2554
|
+
const mediaStyle = isDragging || slideOffset !== 0 && slideDirection === null ? { transform: `translateX(${slideOffset}px)` } : {};
|
|
2555
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2556
|
+
className: "str-chat__gallery",
|
|
2557
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2558
|
+
className: "str-chat__gallery__main",
|
|
2559
|
+
children: [
|
|
2560
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GalleryHeader, { currentItem }),
|
|
2561
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavButton, {
|
|
2562
|
+
"aria-label": t("Previous image"),
|
|
2563
|
+
className: (0, clsx.default)("str-chat__gallery__nav-button--prev", !hasPrevious && "str-chat__gallery__nav-button--hidden"),
|
|
2564
|
+
disabled: !hasPrevious,
|
|
2565
|
+
onClick: handleGoToPrevious,
|
|
2566
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconChevronLeft, {})
|
|
2567
|
+
}),
|
|
2568
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2569
|
+
className: "str-chat__gallery__slide-container",
|
|
2570
|
+
onClick: handleBackgroundClick,
|
|
2571
|
+
onTouchEnd: handleTouchEnd,
|
|
2572
|
+
onTouchMove: handleTouchMove,
|
|
2573
|
+
onTouchStart: handleTouchStart,
|
|
2574
|
+
ref: containerRef,
|
|
2575
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2576
|
+
className: (0, clsx.default)("str-chat__gallery__media-container", {
|
|
2577
|
+
"str-chat__gallery__media--dragging": isDragging,
|
|
2578
|
+
"str-chat__gallery__media--slide-backward": !isDragging && slideDirection === "backward",
|
|
2579
|
+
"str-chat__gallery__media--slide-forward": !isDragging && slideDirection === "forward"
|
|
2580
|
+
}),
|
|
2581
|
+
style: mediaStyle,
|
|
2582
|
+
children: currentItem.videoUrl && currentItem.videoThumbnailUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2583
|
+
className: "str-chat__gallery__media str-chat__gallery__media--video",
|
|
2584
|
+
children: showVideo ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VideoPlayer, {
|
|
2585
|
+
isPlaying: true,
|
|
2586
|
+
videoUrl: currentItem.videoUrl
|
|
2587
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VideoThumbnail, {
|
|
2588
|
+
alt: currentItem.title ?? "",
|
|
2589
|
+
onPlay: () => setShowVideo(true),
|
|
2590
|
+
src: currentItem.videoThumbnailUrl
|
|
2591
|
+
})
|
|
2592
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2593
|
+
className: "str-chat__gallery__media str-chat__gallery__media--image",
|
|
2594
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BaseImage, {
|
|
2595
|
+
alt: currentItem.alt,
|
|
2596
|
+
src: currentItem.imageUrl
|
|
2597
|
+
})
|
|
2598
|
+
})
|
|
2599
|
+
})
|
|
2600
|
+
}),
|
|
2601
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavButton, {
|
|
2602
|
+
"aria-label": t("Next image"),
|
|
2603
|
+
className: (0, clsx.default)("str-chat__gallery__nav-button--next", !hasNext && "str-chat__gallery__nav-button--hidden"),
|
|
2604
|
+
disabled: !hasNext,
|
|
2605
|
+
onClick: handleGoToNext,
|
|
2606
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconChevronRight, {})
|
|
2607
|
+
})
|
|
2608
|
+
]
|
|
2609
|
+
}), itemCount > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2610
|
+
className: "str-chat__gallery__position-indicator",
|
|
2611
|
+
children: [
|
|
2612
|
+
currentIndex + 1,
|
|
2613
|
+
" of ",
|
|
2614
|
+
itemCount
|
|
2615
|
+
]
|
|
2616
|
+
})]
|
|
2617
|
+
});
|
|
2618
|
+
};
|
|
2619
|
+
var NavButton = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
2620
|
+
...props,
|
|
2621
|
+
className: (0, clsx.default)("str-chat__gallery__nav-button", className)
|
|
2622
|
+
});
|
|
2623
|
+
//#endregion
|
|
2624
|
+
//#region src/components/Gallery/Gallery.tsx
|
|
2625
|
+
var Gallery = ({ closeOnBackgroundClick = true, GalleryUI: GalleryUI$1, initialIndex = 0, items, onIndexChange, onRequestClose }) => {
|
|
2626
|
+
const { GalleryUI: ContextGalleryUI } = require_useNotificationApi.useComponentContext();
|
|
2627
|
+
const ResolvedGalleryUI = GalleryUI$1 ?? ContextGalleryUI ?? GalleryUI;
|
|
2628
|
+
const [currentIndex, setCurrentIndex] = (0, react.useState)(initialIndex);
|
|
2629
|
+
const itemCount = items.length;
|
|
2630
|
+
const goToIndex = (0, react.useCallback)((index) => {
|
|
2631
|
+
if (index >= 0 && index < itemCount) setCurrentIndex(index);
|
|
2632
|
+
}, [itemCount]);
|
|
2633
|
+
const goToNext = (0, react.useCallback)(() => {
|
|
2634
|
+
setCurrentIndex((prev) => prev < itemCount - 1 ? prev + 1 : prev);
|
|
2635
|
+
}, [itemCount]);
|
|
2636
|
+
const goToPrevious = (0, react.useCallback)(() => {
|
|
2637
|
+
setCurrentIndex((prev) => prev > 0 ? prev - 1 : prev);
|
|
2638
|
+
}, []);
|
|
2639
|
+
(0, react.useEffect)(() => {
|
|
2640
|
+
onIndexChange?.(currentIndex);
|
|
2641
|
+
}, [currentIndex, onIndexChange]);
|
|
2642
|
+
const hasNext = currentIndex < itemCount - 1;
|
|
2643
|
+
const hasPrevious = currentIndex > 0;
|
|
2644
|
+
const currentItem = items[currentIndex];
|
|
2645
|
+
const contextValue = (0, react.useMemo)(() => ({
|
|
2646
|
+
closeOnBackgroundClick,
|
|
2647
|
+
currentIndex,
|
|
2648
|
+
currentItem,
|
|
2649
|
+
goToIndex,
|
|
2650
|
+
goToNext,
|
|
2651
|
+
goToPrevious,
|
|
2652
|
+
hasNext,
|
|
2653
|
+
hasPrevious,
|
|
2654
|
+
itemCount,
|
|
2655
|
+
items,
|
|
2656
|
+
onRequestClose
|
|
2657
|
+
}), [
|
|
2658
|
+
closeOnBackgroundClick,
|
|
2659
|
+
currentIndex,
|
|
2660
|
+
currentItem,
|
|
2661
|
+
goToIndex,
|
|
2662
|
+
goToNext,
|
|
2663
|
+
goToPrevious,
|
|
2664
|
+
hasNext,
|
|
2665
|
+
hasPrevious,
|
|
2666
|
+
itemCount,
|
|
2667
|
+
items,
|
|
2668
|
+
onRequestClose
|
|
2669
|
+
]);
|
|
2670
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GalleryContext.Provider, {
|
|
2671
|
+
value: contextValue,
|
|
2672
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResolvedGalleryUI, {})
|
|
2673
|
+
});
|
|
2674
|
+
};
|
|
2675
|
+
//#endregion
|
|
2676
|
+
//#region src/components/Form/SwitchField.tsx
|
|
2677
|
+
var SwitchField = ({ children, description, fieldClassName, title, ...props }) => {
|
|
2678
|
+
const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, checked, defaultChecked, disabled, id, onChange, onKeyDown, ...rest } = props;
|
|
2679
|
+
const generatedSwitchId = require_useNotificationApi.useStableId();
|
|
2680
|
+
const switchId = id ?? `str-chat__switch-field-${generatedSwitchId}`;
|
|
2681
|
+
const switchLabelId = `${switchId}-label`;
|
|
2682
|
+
const inputRef = (0, react.useRef)(null);
|
|
2683
|
+
const [uncontrolledChecked, setUncontrolledChecked] = (0, react.useState)(Boolean(defaultChecked));
|
|
2684
|
+
const isControlled = checked !== void 0;
|
|
2685
|
+
const isOn = isControlled ? checked : uncontrolledChecked;
|
|
2686
|
+
const isReadOnly = isControlled && onChange === void 0;
|
|
2687
|
+
const handleChange = (event) => {
|
|
2688
|
+
if (!isControlled) setUncontrolledChecked(event.target.checked);
|
|
2689
|
+
onChange?.(event);
|
|
2690
|
+
};
|
|
2691
|
+
const handleKeyDown = (event) => {
|
|
2692
|
+
onKeyDown?.(event);
|
|
2693
|
+
if (event.defaultPrevented || event.key !== " ") return;
|
|
2694
|
+
event.preventDefault();
|
|
2695
|
+
event.currentTarget.click();
|
|
2696
|
+
};
|
|
2697
|
+
const handleSwitchClick = (event) => {
|
|
2698
|
+
if (disabled || event.target === inputRef.current) return;
|
|
2699
|
+
inputRef.current?.click();
|
|
2700
|
+
};
|
|
2701
|
+
const childLabelId = ((0, react.isValidElement)(children) ? children : void 0)?.props.id;
|
|
2702
|
+
const resolvedAriaLabelledBy = ariaLabelledBy ?? (!ariaLabel ? title ? switchLabelId : childLabelId : void 0);
|
|
2703
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2704
|
+
className: (0, clsx.default)("str-chat__form__switch-field", fieldClassName, disabled && "str-chat__form__switch-field--disabled"),
|
|
2705
|
+
children: [title ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchFieldLabel, {
|
|
2706
|
+
description,
|
|
2707
|
+
htmlFor: switchId,
|
|
2708
|
+
id: switchLabelId,
|
|
2709
|
+
title
|
|
2710
|
+
}) : children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Switch, {
|
|
2711
|
+
...rest,
|
|
2712
|
+
"aria-label": ariaLabel,
|
|
2713
|
+
"aria-labelledby": resolvedAriaLabelledBy,
|
|
2714
|
+
checked: isOn,
|
|
2715
|
+
disabled,
|
|
2716
|
+
id: switchId,
|
|
2717
|
+
on: isOn,
|
|
2718
|
+
onChange: handleChange,
|
|
2719
|
+
onKeyDown: handleKeyDown,
|
|
2720
|
+
onSwitchClick: handleSwitchClick,
|
|
2721
|
+
readOnly: isReadOnly,
|
|
2722
|
+
switchRef: inputRef
|
|
2723
|
+
})]
|
|
2724
|
+
});
|
|
2725
|
+
};
|
|
2726
|
+
var Switch = ({ className, on, onSwitchClick, presentation, switchRef, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2727
|
+
"aria-hidden": presentation ? true : void 0,
|
|
2728
|
+
className: (0, clsx.default)("str-chat__form__switch-field__switch", { "str-chat__form__switch-field__switch--on": on }),
|
|
2729
|
+
onClick: presentation ? void 0 : onSwitchClick,
|
|
2730
|
+
children: [!presentation && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2731
|
+
...props,
|
|
2732
|
+
className: (0, clsx.default)("str-chat__form__switch-field__input", className),
|
|
2733
|
+
ref: switchRef,
|
|
2734
|
+
role: "switch",
|
|
2735
|
+
type: "checkbox"
|
|
2736
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "str-chat__form__switch-field__switch-handle" })]
|
|
2737
|
+
});
|
|
2738
|
+
var SwitchFieldLabel = ({ asError, children, className, description, title, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
2739
|
+
className: (0, clsx.default)("str-chat__form__switch-field__label", { "str-chat__form__switch-field__label--as-error": asError }, className),
|
|
2740
|
+
...props,
|
|
2741
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2742
|
+
className: "str-chat__form__switch-field__label__content",
|
|
2743
|
+
children: title ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchFieldTitle, { children: title }), description != null && description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchFieldDescription, { children: description })] }) : children
|
|
2744
|
+
})
|
|
2745
|
+
});
|
|
2746
|
+
var SwitchFieldTitle = ({ children, className, title, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2747
|
+
className: (0, clsx.default)("str-chat__form__switch-field__label__text", className),
|
|
2748
|
+
...props,
|
|
2749
|
+
children: children ?? title
|
|
2750
|
+
});
|
|
2751
|
+
var SwitchFieldDescription = ({ children, className, description, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2752
|
+
className: (0, clsx.default)("str-chat__form__switch-field__label__description", className),
|
|
2753
|
+
...props,
|
|
2754
|
+
children: children ?? description
|
|
2755
|
+
});
|
|
2756
|
+
//#endregion
|
|
2757
|
+
//#region src/components/Form/Checkbox.tsx
|
|
2758
|
+
var Checkbox = ({ checked, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2759
|
+
...props,
|
|
2760
|
+
className: (0, clsx.default)("str-chat__checkmark str-chat__checkbox", {
|
|
2761
|
+
"str-chat__checkbox--checked": checked,
|
|
2762
|
+
"str-chat__checkmark--checked": checked
|
|
2763
|
+
})
|
|
2764
|
+
});
|
|
2765
|
+
var Checkmark = Checkbox;
|
|
2766
|
+
//#endregion
|
|
2767
|
+
//#region src/components/Form/TextInput.tsx
|
|
2768
|
+
var TextInputIconMessageLine = ({ icon, text }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2769
|
+
"aria-hidden": true,
|
|
2770
|
+
className: "str-chat__form-text-input__message-icon",
|
|
2771
|
+
children: icon
|
|
2772
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2773
|
+
className: "str-chat__form-text-input__message-text",
|
|
2774
|
+
children: text
|
|
2775
|
+
})] });
|
|
2776
|
+
var TextInputFieldMessage = (props) => {
|
|
2777
|
+
if (props.kind === "neutral") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2778
|
+
className: (0, clsx.default)("str-chat__form-text-input__message", props.insidePlacement && "str-chat__form-text-input__message--field-message-inside"),
|
|
2779
|
+
id: props.id,
|
|
2780
|
+
children: props.text
|
|
2781
|
+
});
|
|
2782
|
+
else if (props.kind === "success") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2783
|
+
className: (0, clsx.default)("str-chat__form-text-input__message", "str-chat__form-text-input__message--success", props.insidePlacement && "str-chat__form-text-input__message--field-message-inside"),
|
|
2784
|
+
id: props.id,
|
|
2785
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TextInputIconMessageLine, {
|
|
2786
|
+
icon: props.successMessageIcon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconCheckmark, {}),
|
|
2787
|
+
text: props.text
|
|
2788
|
+
})
|
|
2789
|
+
});
|
|
2790
|
+
else if (props.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2791
|
+
className: (0, clsx.default)("str-chat__form-text-input__message", "str-chat__form-field-error", props.insidePlacement && "str-chat__form-text-input__message--field-message-inside"),
|
|
2792
|
+
id: props.id,
|
|
2793
|
+
role: "alert",
|
|
2794
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TextInputIconMessageLine, {
|
|
2795
|
+
icon: props.errorMessageIcon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconExclamationMark, {}),
|
|
2796
|
+
text: props.text
|
|
2797
|
+
})
|
|
2798
|
+
});
|
|
2799
|
+
return null;
|
|
2800
|
+
};
|
|
2801
|
+
var TextInput = (0, react.forwardRef)(function TextInput({ className, disabled, error = false, errorMessage, errorMessageIcon, fieldMessagePlacement = "outside", id: idProp, label, leading, message, successMessage, successMessageIcon, trailing, trailingText, variant = "outline", ...inputProps }, ref) {
|
|
2802
|
+
const autoId = require_useNotificationApi.useStableId();
|
|
2803
|
+
const id = idProp ?? autoId;
|
|
2804
|
+
const hasError = error && (errorMessage != null || message != null);
|
|
2805
|
+
const showSuccess = !hasError && successMessage != null;
|
|
2806
|
+
const showNeutral = !hasError && !showSuccess && message != null;
|
|
2807
|
+
const messageInside = fieldMessagePlacement === "inside" && (hasError || showSuccess || showNeutral);
|
|
2808
|
+
const messageId = hasError ? `${id}-field-error` : showSuccess || showNeutral ? `${id}-message` : void 0;
|
|
2809
|
+
const describedBy = [inputProps["aria-describedby"], messageId].filter((value) => !!value).join(" ");
|
|
2810
|
+
const fieldMessage = hasError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TextInputFieldMessage, {
|
|
2811
|
+
errorMessageIcon,
|
|
2812
|
+
id: messageId,
|
|
2813
|
+
insidePlacement: messageInside,
|
|
2814
|
+
kind: "error",
|
|
2815
|
+
text: errorMessage ?? message
|
|
2816
|
+
}) : showSuccess ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TextInputFieldMessage, {
|
|
2817
|
+
id: messageId,
|
|
2818
|
+
insidePlacement: messageInside,
|
|
2819
|
+
kind: "success",
|
|
2820
|
+
successMessageIcon,
|
|
2821
|
+
text: successMessage
|
|
2822
|
+
}) : showNeutral ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TextInputFieldMessage, {
|
|
2823
|
+
id: messageId,
|
|
2824
|
+
insidePlacement: messageInside,
|
|
2825
|
+
kind: "neutral",
|
|
2826
|
+
text: message
|
|
2827
|
+
}) : null;
|
|
2828
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2829
|
+
className: (0, clsx.default)("str-chat__form-text-input", error && "str-chat__form-text-input--error", showSuccess && "str-chat__form-text-input--success", disabled && "str-chat__form-text-input--disabled", messageInside && "str-chat__form-text-input--field-message-inside", className),
|
|
2830
|
+
children: [
|
|
2831
|
+
label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
2832
|
+
className: "str-chat__form-text-input__label",
|
|
2833
|
+
htmlFor: id,
|
|
2834
|
+
children: label
|
|
2835
|
+
}) : null,
|
|
2836
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2837
|
+
className: (0, clsx.default)("str-chat__form-text-input__wrapper", `str-chat__form-text-input__wrapper--${variant}`, messageInside && "str-chat__form-text-input__wrapper--field-message-inside"),
|
|
2838
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2839
|
+
className: "str-chat__form-text-input__control-row",
|
|
2840
|
+
children: [
|
|
2841
|
+
leading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2842
|
+
"aria-hidden": true,
|
|
2843
|
+
className: "str-chat__form-text-input__leading",
|
|
2844
|
+
children: leading
|
|
2845
|
+
}) : null,
|
|
2846
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2847
|
+
"aria-describedby": describedBy,
|
|
2848
|
+
"aria-invalid": error,
|
|
2849
|
+
className: "str-chat__form-text-input__input",
|
|
2850
|
+
disabled,
|
|
2851
|
+
id,
|
|
2852
|
+
ref,
|
|
2853
|
+
...inputProps
|
|
2854
|
+
}),
|
|
2855
|
+
trailingText != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2856
|
+
"aria-hidden": true,
|
|
2857
|
+
className: "str-chat__form-text-input__suffix",
|
|
2858
|
+
children: trailingText
|
|
2859
|
+
}) : null,
|
|
2860
|
+
trailing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2861
|
+
"aria-hidden": true,
|
|
2862
|
+
className: "str-chat__form-text-input__trailing",
|
|
2863
|
+
children: trailing
|
|
2864
|
+
}) : null
|
|
2865
|
+
]
|
|
2866
|
+
}), messageInside ? fieldMessage : null]
|
|
2867
|
+
}),
|
|
2868
|
+
messageInside ? null : fieldMessage
|
|
2869
|
+
]
|
|
2870
|
+
});
|
|
2871
|
+
});
|
|
2872
|
+
//#endregion
|
|
2873
|
+
//#region src/components/ListItemLayout/ListItemLayout.tsx
|
|
2874
|
+
var ListItemLayout = ({ ContentSlot = ListItemLayoutContent, contentClassName, description, descriptionClassName, destructive, LeadingIcon, LeadingSlot, RootElement, rootProps, selected, subtitle, subtitleClassName, title, titleClassName, TrailingIcon, TrailingSlot }) => {
|
|
2875
|
+
const ContainerComponent = RootElement ?? "div";
|
|
2876
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2877
|
+
className: "str-chat__list-item-layout",
|
|
2878
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ContainerComponent, {
|
|
2879
|
+
...ContainerComponent === "button" ? { type: "button" } : void 0,
|
|
2880
|
+
...rootProps,
|
|
2881
|
+
className: (0, clsx.default)("str-chat__list-item-layout__container", rootProps?.className, destructive && "str-chat__list-item-layout__container--destructive", selected && "str-chat__list-item-layout__container--selected"),
|
|
2882
|
+
children: [
|
|
2883
|
+
LeadingIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2884
|
+
className: "str-chat__list-item-layout__leading-icon",
|
|
2885
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LeadingIcon, {})
|
|
2886
|
+
}),
|
|
2887
|
+
LeadingSlot && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LeadingSlot, {}),
|
|
2888
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContentSlot, {
|
|
2889
|
+
className: contentClassName,
|
|
2890
|
+
description,
|
|
2891
|
+
descriptionClassName,
|
|
2892
|
+
subtitle,
|
|
2893
|
+
subtitleClassName,
|
|
2894
|
+
title,
|
|
2895
|
+
titleClassName
|
|
2896
|
+
}),
|
|
2897
|
+
TrailingIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2898
|
+
className: "str-chat__list-item-layout__trailing-icon",
|
|
2899
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TrailingIcon, {})
|
|
2900
|
+
}),
|
|
2901
|
+
TrailingSlot && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TrailingSlot, {})
|
|
2902
|
+
]
|
|
2903
|
+
})
|
|
2904
|
+
});
|
|
2905
|
+
};
|
|
2906
|
+
var ListItemLayoutContent = ({ className, description, descriptionClassName, subtitle, subtitleClassName, title, titleClassName, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2907
|
+
...props,
|
|
2908
|
+
className: (0, clsx.default)("str-chat__list-item-layout__content", className, {
|
|
2909
|
+
"str-chat__list-item-layout__content--withDescription": description,
|
|
2910
|
+
"str-chat__list-item-layout__content--withSubtitle": subtitle,
|
|
2911
|
+
"str-chat__list-item-layout__content--withTitle": title
|
|
2912
|
+
}),
|
|
2913
|
+
children: [
|
|
2914
|
+
title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2915
|
+
className: (0, clsx.default)("str-chat__list-item-layout__title", titleClassName),
|
|
2916
|
+
children: title
|
|
2917
|
+
}),
|
|
2918
|
+
subtitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2919
|
+
className: (0, clsx.default)("str-chat__list-item-layout__subtitle", subtitleClassName),
|
|
2920
|
+
children: subtitle
|
|
2921
|
+
}),
|
|
2922
|
+
description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2923
|
+
className: (0, clsx.default)("str-chat__list-item-layout__description", descriptionClassName),
|
|
2924
|
+
children: description
|
|
2925
|
+
})
|
|
2926
|
+
]
|
|
2927
|
+
});
|
|
2928
|
+
//#endregion
|
|
2929
|
+
//#region src/components/ChannelListItem/utils.tsx
|
|
2930
|
+
var remarkPlugins = [
|
|
2931
|
+
htmlToTextPlugin,
|
|
2932
|
+
[remark_gfm.default, { singleTilde: false }],
|
|
2933
|
+
plusPlusToEmphasis,
|
|
2934
|
+
imageToLink
|
|
2935
|
+
];
|
|
2936
|
+
var renderPreviewText = (text) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_markdown.default, {
|
|
2937
|
+
remarkPlugins,
|
|
2938
|
+
skipHtml: true,
|
|
2939
|
+
children: text
|
|
2940
|
+
});
|
|
2941
|
+
var getLatestPollVote = (latestVotesByOption) => {
|
|
2942
|
+
let latestVote;
|
|
2943
|
+
for (const optionVotes of Object.values(latestVotesByOption)) optionVotes.forEach((vote) => {
|
|
2944
|
+
if (latestVote && new Date(latestVote.updated_at) >= new Date(vote.created_at)) return;
|
|
2945
|
+
latestVote = vote;
|
|
2946
|
+
});
|
|
2947
|
+
return latestVote;
|
|
2948
|
+
};
|
|
2949
|
+
var getLatestMessagePreview = (channel, t, userLanguage = "en", isMessageAIGenerated) => {
|
|
2950
|
+
const latestMessage = channel.state.latestMessages[channel.state.latestMessages.length - 1];
|
|
2951
|
+
const previewTextToRender = getTranslatedMessageText({
|
|
2952
|
+
language: userLanguage,
|
|
2953
|
+
message: latestMessage
|
|
2954
|
+
}) || latestMessage?.text;
|
|
2955
|
+
const poll = latestMessage?.poll;
|
|
2956
|
+
if (!latestMessage) return t("Nothing yet...");
|
|
2957
|
+
if (require_useNotificationApi.isMessageDeleted(latestMessage)) return t("Message deleted");
|
|
2958
|
+
if (poll) if (!poll.vote_count) return t("📊 {{createdBy}} created: {{ pollName}}", {
|
|
2959
|
+
createdBy: poll.created_by?.id === channel.getClient().userID ? t("You") : poll.created_by?.name ?? t("Poll"),
|
|
2960
|
+
pollName: poll.name
|
|
2961
|
+
});
|
|
2962
|
+
else {
|
|
2963
|
+
const latestVote = getLatestPollVote(poll.latest_votes_by_option);
|
|
2964
|
+
const option = latestVote && poll.options.find((opt) => opt.id === latestVote.option_id);
|
|
2965
|
+
if (option && latestVote) return t("📊 {{votedBy}} voted: {{pollOptionText}}", {
|
|
2966
|
+
pollOptionText: option.text,
|
|
2967
|
+
votedBy: latestVote?.user?.id === channel.getClient().userID ? t("You") : latestVote.user?.name ?? t("Poll")
|
|
2968
|
+
});
|
|
2969
|
+
}
|
|
2970
|
+
if (previewTextToRender) return isMessageAIGenerated?.(latestMessage) ? previewTextToRender : renderPreviewText(previewTextToRender);
|
|
2971
|
+
if (latestMessage.command) return `/${latestMessage.command}`;
|
|
2972
|
+
if (latestMessage.attachments?.length) return t("🏙 Attachment...");
|
|
2973
|
+
if (latestMessage.shared_location) return t("📍Shared location");
|
|
2974
|
+
return t("Empty message...");
|
|
2975
|
+
};
|
|
2976
|
+
/**
|
|
2977
|
+
* Channel display image: channel.data.image, or for DM (2 members) the other member's user.image.
|
|
2978
|
+
*/
|
|
2979
|
+
var getChannelDisplayImage = (channel, currentUserId) => {
|
|
2980
|
+
const data = channel.data;
|
|
2981
|
+
if (data?.image && typeof data.image === "string") return data.image;
|
|
2982
|
+
const memberList = Object.values(channel.state.members);
|
|
2983
|
+
if (memberList.length === 2) {
|
|
2984
|
+
const image = memberList.find((m) => m.user?.id !== currentUserId)?.user?.image;
|
|
2985
|
+
if (image && typeof image === "string") return image;
|
|
2986
|
+
}
|
|
2987
|
+
};
|
|
2988
|
+
var getGroupChannelDisplayInfo = (channel) => {
|
|
2989
|
+
const members = Object.values(channel.state.members);
|
|
2990
|
+
if (members.length <= 2) return;
|
|
2991
|
+
const memberList = [];
|
|
2992
|
+
for (const member of members) {
|
|
2993
|
+
const { user } = member;
|
|
2994
|
+
if (!user?.name && !user?.image) continue;
|
|
2995
|
+
memberList.push({
|
|
2996
|
+
imageUrl: user.image,
|
|
2997
|
+
userName: user.name
|
|
2998
|
+
});
|
|
2999
|
+
}
|
|
3000
|
+
return { members: memberList };
|
|
3001
|
+
};
|
|
3002
|
+
//#endregion
|
|
3003
|
+
//#region src/components/ChannelListItem/hooks/useChannelDisplayName.ts
|
|
3004
|
+
/**
|
|
3005
|
+
* 1. channel.data.name
|
|
3006
|
+
* 2. DM (exactly 2 members): other member's name, then directMessageLabel
|
|
3007
|
+
* 3. Group (3+ members): comma-separated list of 2 other members' names (no ellipsis)
|
|
3008
|
+
* 4. undefined otherwise
|
|
3009
|
+
*/
|
|
3010
|
+
function computeChannelDisplayName(channel, directMessageLabel, currentUserId) {
|
|
3011
|
+
const data = channel.data;
|
|
3012
|
+
if (data?.name && typeof data.name === "string") return data.name;
|
|
3013
|
+
const memberList = Object.values(channel.state.members);
|
|
3014
|
+
const otherMembers = memberList.filter((m) => m.user?.id !== currentUserId);
|
|
3015
|
+
if (memberList.length === 2 && otherMembers.length === 1) return otherMembers[0].user?.name || directMessageLabel;
|
|
3016
|
+
if (otherMembers.length >= 2) {
|
|
3017
|
+
const names = otherMembers.map((m) => m.user?.name).filter(Boolean).slice(0, 2);
|
|
3018
|
+
if (names.length > 0) return names.join(", ");
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
/**
|
|
3022
|
+
* Channel display name with translation context.
|
|
3023
|
+
* 1. channel.data.name
|
|
3024
|
+
* 2. DM (exactly 2 members): other member's name, then translated "Direct message"
|
|
3025
|
+
* 3. Group (3+ members): comma-separated list of 2 other members' names (no ellipsis)
|
|
3026
|
+
* 4. undefined otherwise
|
|
3027
|
+
*/
|
|
3028
|
+
var useChannelDisplayName = (channel) => {
|
|
3029
|
+
const { client } = require_useNotificationApi.useChatContext("useChannelDisplayName");
|
|
3030
|
+
const { t } = require_useNotificationApi.useTranslationContext("useChannelDisplayName");
|
|
3031
|
+
const directMessageLabel = t("Direct message");
|
|
3032
|
+
const [displayName, setDisplayName] = (0, react.useState)(() => channel ? computeChannelDisplayName(channel, directMessageLabel, client.userID ?? void 0) : void 0);
|
|
3033
|
+
(0, react.useEffect)(() => {
|
|
3034
|
+
if (!channel) {
|
|
3035
|
+
setDisplayName(void 0);
|
|
3036
|
+
return;
|
|
3037
|
+
}
|
|
3038
|
+
const updateDisplayName = () => setDisplayName(computeChannelDisplayName(channel, directMessageLabel, client.userID ?? void 0));
|
|
3039
|
+
updateDisplayName();
|
|
3040
|
+
client.on("user.updated", updateDisplayName);
|
|
3041
|
+
return () => {
|
|
3042
|
+
client.off("user.updated", updateDisplayName);
|
|
3043
|
+
};
|
|
3044
|
+
}, [
|
|
3045
|
+
channel,
|
|
3046
|
+
channel?.data,
|
|
3047
|
+
client,
|
|
3048
|
+
directMessageLabel
|
|
3049
|
+
]);
|
|
3050
|
+
return displayName;
|
|
3051
|
+
};
|
|
3052
|
+
//#endregion
|
|
3053
|
+
//#region src/components/ChannelListItem/hooks/useChannelPreviewInfo.ts
|
|
3054
|
+
var emptyGroupInfo = {
|
|
3055
|
+
members: [],
|
|
3056
|
+
overflowCount: void 0
|
|
3057
|
+
};
|
|
3058
|
+
var useChannelPreviewInfo = (props) => {
|
|
3059
|
+
const { channel, overrideImage, overrideTitle } = props;
|
|
3060
|
+
const { client } = require_useNotificationApi.useChatContext();
|
|
3061
|
+
const channelDisplayName = useChannelDisplayName(channel);
|
|
3062
|
+
const displayTitle = overrideTitle ?? channelDisplayName;
|
|
3063
|
+
const [displayImage, setDisplayImage] = (0, react.useState)(() => channel ? overrideImage ?? getChannelDisplayImage(channel, client.userID ?? void 0) : void 0);
|
|
3064
|
+
const [groupChannelDisplayInfo, setGroupChannelDisplayInfo] = (0, react.useState)(() => channel ? getGroupChannelDisplayInfo(channel) ?? emptyGroupInfo : emptyGroupInfo);
|
|
3065
|
+
(0, react.useEffect)(() => {
|
|
3066
|
+
if (!channel) return;
|
|
3067
|
+
if (overrideImage) return;
|
|
3068
|
+
const updateInfo = () => {
|
|
3069
|
+
setDisplayImage(getChannelDisplayImage(channel, client.userID ?? void 0));
|
|
3070
|
+
setGroupChannelDisplayInfo(getGroupChannelDisplayInfo(channel) ?? emptyGroupInfo);
|
|
3071
|
+
};
|
|
3072
|
+
updateInfo();
|
|
3073
|
+
const { unsubscribe: unsubscribeChannelUpdated } = channel.on("channel.updated", updateInfo);
|
|
3074
|
+
const { unsubscribe: unsubscribeUserUpdated } = client.on("user.updated", updateInfo);
|
|
3075
|
+
return () => {
|
|
3076
|
+
unsubscribeChannelUpdated();
|
|
3077
|
+
unsubscribeUserUpdated();
|
|
3078
|
+
};
|
|
3079
|
+
}, [
|
|
3080
|
+
channel,
|
|
3081
|
+
channel?.data,
|
|
3082
|
+
client,
|
|
3083
|
+
overrideImage
|
|
3084
|
+
]);
|
|
3085
|
+
return (0, react.useMemo)(() => ({
|
|
3086
|
+
displayImage: overrideImage ?? displayImage,
|
|
3087
|
+
displayTitle,
|
|
3088
|
+
groupChannelDisplayInfo
|
|
3089
|
+
}), [
|
|
3090
|
+
displayImage,
|
|
3091
|
+
displayTitle,
|
|
3092
|
+
groupChannelDisplayInfo,
|
|
3093
|
+
overrideImage
|
|
3094
|
+
]);
|
|
3095
|
+
};
|
|
3096
|
+
//#endregion
|
|
3097
|
+
//#region src/utils/isDmChannel.ts
|
|
3098
|
+
var isDmChannel = ({ channel, ownUserId }) => {
|
|
3099
|
+
const memberCount = channel.data?.member_count ?? 0;
|
|
3100
|
+
return memberCount === 1 || memberCount === 2 && !!ownUserId && Object.values(channel.state?.members ?? {}).some(({ user }) => user?.id === ownUserId);
|
|
3101
|
+
};
|
|
3102
|
+
//#endregion
|
|
3103
|
+
//#region src/components/ChannelList/hooks/useSelectedChannelState.ts
|
|
3104
|
+
var noop = () => {};
|
|
3105
|
+
function useSelectedChannelState({ channel, selector, stateChangeEventKeys = ["all"] }) {
|
|
3106
|
+
return (0, use_sync_external_store_shim.useSyncExternalStore)((0, react.useCallback)((onStoreChange) => {
|
|
3107
|
+
if (!channel) return noop;
|
|
3108
|
+
const subscriptions = stateChangeEventKeys.map((et) => channel.on(et, () => {
|
|
3109
|
+
onStoreChange(selector(channel));
|
|
3110
|
+
}));
|
|
3111
|
+
return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
|
|
3112
|
+
}, [
|
|
3113
|
+
channel,
|
|
3114
|
+
selector,
|
|
3115
|
+
stateChangeEventKeys
|
|
3116
|
+
]), (0, react.useCallback)(() => {
|
|
3117
|
+
if (!channel) return void 0;
|
|
3118
|
+
return selector(channel);
|
|
3119
|
+
}, [channel, selector]));
|
|
3120
|
+
}
|
|
3121
|
+
//#endregion
|
|
3122
|
+
//#region src/components/ChannelList/hooks/useChannelMembershipState.ts
|
|
3123
|
+
var selector = (c) => c.state.membership;
|
|
3124
|
+
var keys = ["member.updated"];
|
|
3125
|
+
function useChannelMembershipState(channel) {
|
|
3126
|
+
return useSelectedChannelState({
|
|
3127
|
+
channel,
|
|
3128
|
+
selector,
|
|
3129
|
+
stateChangeEventKeys: keys
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
//#endregion
|
|
3133
|
+
//#region src/components/ChannelListItem/hooks/useIsChannelMuted.ts
|
|
3134
|
+
var useIsChannelMuted = (channel) => {
|
|
3135
|
+
const { client } = require_useNotificationApi.useChatContext("useIsChannelMuted");
|
|
3136
|
+
const [muted, setMuted] = (0, react.useState)(channel.muteStatus());
|
|
3137
|
+
(0, react.useEffect)(() => {
|
|
3138
|
+
const handleEvent = () => setMuted(channel.muteStatus());
|
|
3139
|
+
client.on("notification.channel_mutes_updated", handleEvent);
|
|
3140
|
+
return () => client.off("notification.channel_mutes_updated", handleEvent);
|
|
3141
|
+
}, [muted]);
|
|
3142
|
+
return muted;
|
|
3143
|
+
};
|
|
3144
|
+
//#endregion
|
|
3145
|
+
//#region src/components/ChannelListItem/hooks/useIsUserMuted.ts
|
|
3146
|
+
var useIsUserMuted = (targetUserId) => {
|
|
3147
|
+
const { mutes } = require_useNotificationApi.useChatContext();
|
|
3148
|
+
return (0, react.useMemo)(() => !!targetUserId && mutes.some((mute) => mute.target.id === targetUserId), [mutes, targetUserId]);
|
|
3149
|
+
};
|
|
3150
|
+
//#endregion
|
|
3151
|
+
//#region src/components/Notifications/Notification.tsx
|
|
3152
|
+
var IconsBySeverity = {
|
|
3153
|
+
error: require_useNotificationApi.IconExclamationMark,
|
|
3154
|
+
info: null,
|
|
3155
|
+
loading: require_useNotificationApi.IconRefresh,
|
|
3156
|
+
success: require_useNotificationApi.IconCheckmark,
|
|
3157
|
+
warning: require_useNotificationApi.IconExclamationTriangleFill
|
|
3158
|
+
};
|
|
3159
|
+
var DefaultNotificationIcon = ({ notification }) => {
|
|
3160
|
+
if (!notification.severity) return null;
|
|
3161
|
+
const Icon = IconsBySeverity[notification.severity] ?? null;
|
|
3162
|
+
return Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3163
|
+
className: "str-chat__notification-icon",
|
|
3164
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {})
|
|
3165
|
+
});
|
|
3166
|
+
};
|
|
3167
|
+
var Notification = (0, react.forwardRef)(({ className, entryDirection, Icon = DefaultNotificationIcon, notification, onDismiss, showClose = false, transitionState }, ref) => {
|
|
3168
|
+
const { removeNotification } = require_useNotificationApi.useNotificationApi();
|
|
3169
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
3170
|
+
const displayMessage = t("translationBuilderTopic/notification", {
|
|
3171
|
+
notification,
|
|
3172
|
+
value: notification.message
|
|
3173
|
+
});
|
|
3174
|
+
const handleDismiss = () => {
|
|
3175
|
+
if (onDismiss) {
|
|
3176
|
+
onDismiss();
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
3179
|
+
removeNotification(notification.id);
|
|
3180
|
+
};
|
|
3181
|
+
const isPersistent = !notification.duration;
|
|
3182
|
+
const severity = notification.severity;
|
|
3183
|
+
const livePriority = severity === "error" ? "assertive" : "polite";
|
|
3184
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3185
|
+
className: (0, clsx.default)("str-chat__notification", entryDirection && `str-chat__notification--enter-from-${entryDirection}`, transitionState === "enter" && "str-chat__notification--is-entering", transitionState === "exit" && "str-chat__notification--is-exiting", severity && `str-chat__notification--${severity}`, severity === "loading" && "str-chat__notification--loading", className),
|
|
3186
|
+
"data-testid": "notification",
|
|
3187
|
+
ref,
|
|
3188
|
+
children: [
|
|
3189
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3190
|
+
className: "str-chat__notification-content",
|
|
3191
|
+
children: [Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { notification }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3192
|
+
"aria-atomic": "true",
|
|
3193
|
+
"aria-live": livePriority,
|
|
3194
|
+
className: "str-chat__notification-message",
|
|
3195
|
+
role: livePriority === "assertive" ? "alert" : "status",
|
|
3196
|
+
children: displayMessage
|
|
3197
|
+
})]
|
|
3198
|
+
}),
|
|
3199
|
+
notification.actions && notification.actions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3200
|
+
className: "str-chat__notification-actions",
|
|
3201
|
+
children: notification.actions.map((action, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
3202
|
+
appearance: "outline",
|
|
3203
|
+
className: "str-chat__notification-action",
|
|
3204
|
+
inverseTheme: true,
|
|
3205
|
+
onClick: () => {
|
|
3206
|
+
action.handler();
|
|
3207
|
+
},
|
|
3208
|
+
size: "sm",
|
|
3209
|
+
variant: "secondary",
|
|
3210
|
+
children: action.label
|
|
3211
|
+
}, index))
|
|
3212
|
+
}),
|
|
3213
|
+
(showClose || isPersistent) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.Button, {
|
|
3214
|
+
appearance: "ghost",
|
|
3215
|
+
"aria-label": t("aria/Dismiss notification"),
|
|
3216
|
+
circular: true,
|
|
3217
|
+
className: "str-chat__notification-close-button",
|
|
3218
|
+
inverseTheme: true,
|
|
3219
|
+
onClick: handleDismiss,
|
|
3220
|
+
size: "sm",
|
|
3221
|
+
variant: "secondary",
|
|
3222
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_useNotificationApi.IconXmark, {})
|
|
3223
|
+
})
|
|
3224
|
+
]
|
|
3225
|
+
});
|
|
3226
|
+
});
|
|
3227
|
+
Notification.displayName = "Notification";
|
|
3228
|
+
//#endregion
|
|
3229
|
+
//#region src/components/Notifications/NotificationList.tsx
|
|
3230
|
+
var ENTER_TRANSLATION = {
|
|
3231
|
+
bottom: {
|
|
3232
|
+
x: "0%",
|
|
3233
|
+
y: "100%"
|
|
3234
|
+
},
|
|
3235
|
+
left: {
|
|
3236
|
+
x: "-100%",
|
|
3237
|
+
y: "0%"
|
|
3238
|
+
},
|
|
3239
|
+
right: {
|
|
3240
|
+
x: "100%",
|
|
3241
|
+
y: "0%"
|
|
3242
|
+
},
|
|
3243
|
+
top: {
|
|
3244
|
+
x: "0%",
|
|
3245
|
+
y: "-100%"
|
|
3246
|
+
}
|
|
3247
|
+
};
|
|
3248
|
+
var EXIT_ANIMATION_MS = 340;
|
|
3249
|
+
var DEFAULT_MIN_DISPLAY_MS = 1e3;
|
|
3250
|
+
var isEnterFrom = (value) => value === "bottom" || value === "left" || value === "right" || value === "top";
|
|
3251
|
+
var getNotificationEnterFrom = (notification, fallbackEnterFrom) => {
|
|
3252
|
+
if (!notification) return fallbackEnterFrom;
|
|
3253
|
+
const metadataEnterFrom = notification.metadata?.entryDirection;
|
|
3254
|
+
if (isEnterFrom(metadataEnterFrom)) return metadataEnterFrom;
|
|
3255
|
+
const originEnterFrom = notification.origin.context?.entryDirection;
|
|
3256
|
+
if (isEnterFrom(originEnterFrom)) return originEnterFrom;
|
|
3257
|
+
return fallbackEnterFrom;
|
|
3258
|
+
};
|
|
3259
|
+
var isPersistent = (notification) => !notification.duration;
|
|
3260
|
+
var haveSameType = (a, b) => !!a?.type && !!b?.type && a.type === b.type;
|
|
3261
|
+
/** FIFO queue selector — oldest `createdAt` other than `displayed` wins. */
|
|
3262
|
+
var pickOldest = (notifications, displayed) => {
|
|
3263
|
+
const excludeId = displayed?.id ?? null;
|
|
3264
|
+
let oldest = null;
|
|
3265
|
+
for (const notification of notifications) {
|
|
3266
|
+
if (notification.id === excludeId) continue;
|
|
3267
|
+
if (!oldest || notification.createdAt < oldest.createdAt) oldest = notification;
|
|
3268
|
+
}
|
|
3269
|
+
return oldest;
|
|
3270
|
+
};
|
|
3271
|
+
/** LIFO queue selector — newest `createdAt` other than `displayed` wins. */
|
|
3272
|
+
var pickNewest = (notifications, displayed) => {
|
|
3273
|
+
const excludeId = displayed?.id ?? null;
|
|
3274
|
+
let newest = null;
|
|
3275
|
+
for (const notification of notifications) {
|
|
3276
|
+
if (notification.id === excludeId) continue;
|
|
3277
|
+
if (!newest || notification.createdAt > newest.createdAt) newest = notification;
|
|
3278
|
+
}
|
|
3279
|
+
return newest;
|
|
3280
|
+
};
|
|
3281
|
+
var pickNewestPersistent = (notifications, excludeId) => {
|
|
3282
|
+
let newest = null;
|
|
3283
|
+
for (const notification of notifications) {
|
|
3284
|
+
if (notification.id === excludeId) continue;
|
|
3285
|
+
if (!isPersistent(notification)) continue;
|
|
3286
|
+
if (!newest || notification.createdAt > newest.createdAt) newest = notification;
|
|
3287
|
+
}
|
|
3288
|
+
return newest;
|
|
3289
|
+
};
|
|
3290
|
+
var pickNewestOfType = (notifications, type, excludeId) => {
|
|
3291
|
+
if (!type) return null;
|
|
3292
|
+
let newest = null;
|
|
3293
|
+
for (const notification of notifications) {
|
|
3294
|
+
if (notification.id === excludeId) continue;
|
|
3295
|
+
if (notification.type !== type) continue;
|
|
3296
|
+
if (!newest || notification.createdAt > newest.createdAt) newest = notification;
|
|
3297
|
+
}
|
|
3298
|
+
return newest;
|
|
3299
|
+
};
|
|
3300
|
+
/**
|
|
3301
|
+
* Builds the default `PickNextNotification` selector with a configurable queue fallback.
|
|
3302
|
+
* Encodes the snackbar concurrency rules from the design spec — the scheduling effect
|
|
3303
|
+
* only decides *when* to swap, the returned function decides *what* to swap to.
|
|
3304
|
+
*
|
|
3305
|
+
* Rules, in order of precedence:
|
|
3306
|
+
* 1. **Persistent wins.** Persistent variants (no `duration`) jump ahead of any
|
|
3307
|
+
* queued transient because they carry an action the user must acknowledge.
|
|
3308
|
+
* 2. **Persistent ↛ replaced by transient.** While a persistent is displayed it stays
|
|
3309
|
+
* put until dismissed externally or a *newer* persistent arrives.
|
|
3310
|
+
* 3. **Same-type refresh.** While a transient is displayed, a repeated trigger of the
|
|
3311
|
+
* same `type` collapses to its latest occurrence. (The scheduling effect detects
|
|
3312
|
+
* this via `haveSameType` and bypasses the dwell window so the refresh feels
|
|
3313
|
+
* instant; this function just makes sure the latest same-type is returned.)
|
|
3314
|
+
* 4. **Queue fallback.** Otherwise, `pickFromQueue` selects the next notification
|
|
3315
|
+
* (default: `pickOldest` / FIFO).
|
|
3316
|
+
*
|
|
3317
|
+
* Exported so callers that want to layer behavior on top of the design rules can wrap
|
|
3318
|
+
* the result instead of rewriting it.
|
|
3319
|
+
*/
|
|
3320
|
+
var createDefaultPickNext = (pickFromQueue = pickOldest) => (notifications, displayed) => {
|
|
3321
|
+
if (notifications.length === 0) return null;
|
|
3322
|
+
const newestPersistent = pickNewestPersistent(notifications, null);
|
|
3323
|
+
if (!displayed) return newestPersistent ?? pickFromQueue(notifications, null);
|
|
3324
|
+
if (!notifications.some(({ id }) => id === displayed.id)) return newestPersistent ?? pickFromQueue(notifications, null);
|
|
3325
|
+
if (isPersistent(displayed)) {
|
|
3326
|
+
const newerPersistent = newestPersistent && newestPersistent.id !== displayed.id ? newestPersistent : pickNewestPersistent(notifications, displayed.id);
|
|
3327
|
+
if (newerPersistent && newerPersistent.createdAt > displayed.createdAt) return newerPersistent;
|
|
3328
|
+
return displayed;
|
|
3329
|
+
}
|
|
3330
|
+
const sameTypeNewest = pickNewestOfType(notifications, displayed.type, displayed.id);
|
|
3331
|
+
if (sameTypeNewest) return sameTypeNewest;
|
|
3332
|
+
if (newestPersistent) return newestPersistent;
|
|
3333
|
+
return pickFromQueue(notifications, displayed) ?? displayed;
|
|
3334
|
+
};
|
|
3335
|
+
/** Default selector — design-spec rules with FIFO queue fallback (`pickOldest`). */
|
|
3336
|
+
var defaultPickNext = createDefaultPickNext(pickOldest);
|
|
3337
|
+
var NotificationList = ({ className, enterFrom = "bottom", fallbackPanel, filter, minDisplayMs = DEFAULT_MIN_DISPLAY_MS, panel, pickNext = defaultPickNext, verticalAlignment = "bottom" }) => {
|
|
3338
|
+
const { Notification: NotificationComponent = Notification } = require_useNotificationApi.useComponentContext();
|
|
3339
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
3340
|
+
const { removeNotification, startNotificationTimeout } = require_useNotificationApi.useNotificationApi();
|
|
3341
|
+
const exitTimeoutRef = (0, react.useRef)(null);
|
|
3342
|
+
const replacementTimeoutRef = (0, react.useRef)(null);
|
|
3343
|
+
const candidateRef = (0, react.useRef)(null);
|
|
3344
|
+
const displayedAtRef = (0, react.useRef)(null);
|
|
3345
|
+
const listRef = (0, react.useRef)(null);
|
|
3346
|
+
const observedElementRef = (0, react.useRef)(null);
|
|
3347
|
+
const startedTimeoutIdsRef = (0, react.useRef)(null);
|
|
3348
|
+
if (!startedTimeoutIdsRef.current) startedTimeoutIdsRef.current = /* @__PURE__ */ new Set();
|
|
3349
|
+
const [displayedNotification, setDisplayedNotification] = (0, react.useState)(null);
|
|
3350
|
+
const [transitionState, setTransitionState] = (0, react.useState)("enter");
|
|
3351
|
+
const notifications = useNotifications({
|
|
3352
|
+
applyDisplayFilter: true,
|
|
3353
|
+
fallbackPanel,
|
|
3354
|
+
filter: (0, react.useCallback)((notification) => {
|
|
3355
|
+
if (require_useNotificationApi.hasSystemNotificationTag(notification)) return false;
|
|
3356
|
+
return filter ? filter(notification) : true;
|
|
3357
|
+
}, [filter]),
|
|
3358
|
+
panel
|
|
3359
|
+
});
|
|
3360
|
+
const dismiss = (0, react.useCallback)((id) => {
|
|
3361
|
+
startedTimeoutIdsRef.current?.delete(id);
|
|
3362
|
+
removeNotification(id);
|
|
3363
|
+
}, [removeNotification]);
|
|
3364
|
+
(0, react.useEffect)(() => {
|
|
3365
|
+
const notificationIds = new Set(notifications.map(({ id }) => id));
|
|
3366
|
+
startedTimeoutIdsRef.current?.forEach((id) => {
|
|
3367
|
+
if (!notificationIds.has(id)) startedTimeoutIdsRef.current?.delete(id);
|
|
3368
|
+
});
|
|
3369
|
+
}, [notifications]);
|
|
3370
|
+
const clearReplacementTimeout = (0, react.useCallback)(() => {
|
|
3371
|
+
if (replacementTimeoutRef.current !== null) {
|
|
3372
|
+
window.clearTimeout(replacementTimeoutRef.current);
|
|
3373
|
+
replacementTimeoutRef.current = null;
|
|
3374
|
+
}
|
|
3375
|
+
}, []);
|
|
3376
|
+
(0, react.useEffect)(() => () => {
|
|
3377
|
+
clearReplacementTimeout();
|
|
3378
|
+
if (exitTimeoutRef.current !== null) {
|
|
3379
|
+
window.clearTimeout(exitTimeoutRef.current);
|
|
3380
|
+
exitTimeoutRef.current = null;
|
|
3381
|
+
}
|
|
3382
|
+
}, [clearReplacementTimeout]);
|
|
3383
|
+
(0, react.useEffect)(() => {
|
|
3384
|
+
candidateRef.current = pickNext(notifications, displayedNotification);
|
|
3385
|
+
}, [
|
|
3386
|
+
displayedNotification,
|
|
3387
|
+
notifications,
|
|
3388
|
+
pickNext
|
|
3389
|
+
]);
|
|
3390
|
+
(0, react.useEffect)(() => {
|
|
3391
|
+
if (transitionState === "exit") return;
|
|
3392
|
+
if (!displayedNotification) {
|
|
3393
|
+
const candidate = pickNext(notifications, null);
|
|
3394
|
+
if (candidate) {
|
|
3395
|
+
displayedAtRef.current = Date.now();
|
|
3396
|
+
setDisplayedNotification(candidate);
|
|
3397
|
+
setTransitionState("enter");
|
|
3398
|
+
}
|
|
3399
|
+
return;
|
|
3400
|
+
}
|
|
3401
|
+
const candidate = pickNext(notifications, displayedNotification);
|
|
3402
|
+
if (!candidate) {
|
|
3403
|
+
clearReplacementTimeout();
|
|
3404
|
+
setTransitionState("exit");
|
|
3405
|
+
exitTimeoutRef.current = window.setTimeout(() => {
|
|
3406
|
+
exitTimeoutRef.current = null;
|
|
3407
|
+
displayedAtRef.current = null;
|
|
3408
|
+
setDisplayedNotification(null);
|
|
3409
|
+
setTransitionState("enter");
|
|
3410
|
+
}, EXIT_ANIMATION_MS);
|
|
3411
|
+
return;
|
|
3412
|
+
}
|
|
3413
|
+
if (candidate.id === displayedNotification.id) {
|
|
3414
|
+
clearReplacementTimeout();
|
|
3415
|
+
return;
|
|
3416
|
+
}
|
|
3417
|
+
const displayedInStore = notifications.some(({ id }) => id === displayedNotification.id);
|
|
3418
|
+
const startSwap = () => {
|
|
3419
|
+
replacementTimeoutRef.current = null;
|
|
3420
|
+
setTransitionState("exit");
|
|
3421
|
+
const previousId = displayedNotification.id;
|
|
3422
|
+
const wasInStore = displayedInStore;
|
|
3423
|
+
exitTimeoutRef.current = window.setTimeout(() => {
|
|
3424
|
+
exitTimeoutRef.current = null;
|
|
3425
|
+
if (wasInStore) {
|
|
3426
|
+
startedTimeoutIdsRef.current?.delete(previousId);
|
|
3427
|
+
removeNotification(previousId);
|
|
3428
|
+
}
|
|
3429
|
+
const next = candidateRef.current;
|
|
3430
|
+
if (next && next.id !== previousId) {
|
|
3431
|
+
displayedAtRef.current = Date.now();
|
|
3432
|
+
setDisplayedNotification(next);
|
|
3433
|
+
setTransitionState("enter");
|
|
3434
|
+
} else {
|
|
3435
|
+
displayedAtRef.current = null;
|
|
3436
|
+
setDisplayedNotification(null);
|
|
3437
|
+
setTransitionState("enter");
|
|
3438
|
+
}
|
|
3439
|
+
}, EXIT_ANIMATION_MS);
|
|
3440
|
+
};
|
|
3441
|
+
if (!displayedInStore) {
|
|
3442
|
+
clearReplacementTimeout();
|
|
3443
|
+
startSwap();
|
|
3444
|
+
return;
|
|
3445
|
+
}
|
|
3446
|
+
if (haveSameType(displayedNotification, candidate)) {
|
|
3447
|
+
clearReplacementTimeout();
|
|
3448
|
+
startSwap();
|
|
3449
|
+
return;
|
|
3450
|
+
}
|
|
3451
|
+
const elapsed = displayedAtRef.current ? Date.now() - displayedAtRef.current : 0;
|
|
3452
|
+
const remaining = Math.max(0, minDisplayMs - elapsed);
|
|
3453
|
+
if (remaining === 0) {
|
|
3454
|
+
clearReplacementTimeout();
|
|
3455
|
+
startSwap();
|
|
3456
|
+
} else if (replacementTimeoutRef.current === null) replacementTimeoutRef.current = window.setTimeout(startSwap, remaining);
|
|
3457
|
+
}, [
|
|
3458
|
+
clearReplacementTimeout,
|
|
3459
|
+
displayedNotification,
|
|
3460
|
+
minDisplayMs,
|
|
3461
|
+
notifications,
|
|
3462
|
+
pickNext,
|
|
3463
|
+
removeNotification,
|
|
3464
|
+
transitionState
|
|
3465
|
+
]);
|
|
3466
|
+
const notification = displayedNotification;
|
|
3467
|
+
const notificationEnterFrom = getNotificationEnterFrom(notification, enterFrom);
|
|
3468
|
+
(0, react.useEffect)(() => {
|
|
3469
|
+
const element = observedElementRef.current;
|
|
3470
|
+
if (!element || !notification || transitionState === "exit") return;
|
|
3471
|
+
const startTimeout = () => {
|
|
3472
|
+
if (!startedTimeoutIdsRef.current || startedTimeoutIdsRef.current.has(notification.id)) return;
|
|
3473
|
+
startedTimeoutIdsRef.current.add(notification.id);
|
|
3474
|
+
startNotificationTimeout(notification.id);
|
|
3475
|
+
};
|
|
3476
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
3477
|
+
startTimeout();
|
|
3478
|
+
return;
|
|
3479
|
+
}
|
|
3480
|
+
const observer = new IntersectionObserver((entries) => {
|
|
3481
|
+
const [entry] = entries;
|
|
3482
|
+
if (!entry?.isIntersecting) return;
|
|
3483
|
+
startTimeout();
|
|
3484
|
+
observer.disconnect();
|
|
3485
|
+
}, {
|
|
3486
|
+
root: listRef.current,
|
|
3487
|
+
threshold: .5
|
|
3488
|
+
});
|
|
3489
|
+
observer.observe(element);
|
|
3490
|
+
return () => {
|
|
3491
|
+
observer.disconnect();
|
|
3492
|
+
};
|
|
3493
|
+
}, [
|
|
3494
|
+
notification,
|
|
3495
|
+
startNotificationTimeout,
|
|
3496
|
+
transitionState
|
|
3497
|
+
]);
|
|
3498
|
+
if (!notification) return null;
|
|
3499
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3500
|
+
"aria-label": t("aria/Notifications"),
|
|
3501
|
+
className: (0, clsx.default)("str-chat__notification-list", `str-chat__notification-list--enter-from-${notificationEnterFrom}`, `str-chat__notification-list--position-${verticalAlignment}`, panel && `str-chat__notification-list--${panel}`, className),
|
|
3502
|
+
"data-testid": "notification-list",
|
|
3503
|
+
ref: listRef,
|
|
3504
|
+
role: "region",
|
|
3505
|
+
style: {
|
|
3506
|
+
"--str-chat__notification-list-enter-x": ENTER_TRANSLATION[notificationEnterFrom].x,
|
|
3507
|
+
"--str-chat__notification-list-enter-y": ENTER_TRANSLATION[notificationEnterFrom].y
|
|
3508
|
+
},
|
|
3509
|
+
children: [
|
|
3510
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3511
|
+
"aria-hidden": true,
|
|
3512
|
+
className: "str-chat__notification-list__edge str-chat__notification-list__edge--top"
|
|
3513
|
+
}),
|
|
3514
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotificationComponent, {
|
|
3515
|
+
entryDirection: notificationEnterFrom,
|
|
3516
|
+
notification,
|
|
3517
|
+
onDismiss: () => dismiss(notification.id),
|
|
3518
|
+
ref: (element) => {
|
|
3519
|
+
observedElementRef.current = element;
|
|
3520
|
+
},
|
|
3521
|
+
showClose: !notification.duration,
|
|
3522
|
+
transitionState
|
|
3523
|
+
}, notification.id),
|
|
3524
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3525
|
+
"aria-hidden": true,
|
|
3526
|
+
className: "str-chat__notification-list__edge str-chat__notification-list__edge--bottom"
|
|
3527
|
+
})
|
|
3528
|
+
]
|
|
3529
|
+
});
|
|
3530
|
+
};
|
|
3531
|
+
//#endregion
|
|
3532
|
+
//#region src/components/ChannelHeader/hooks/useChannelHasMembersOnline.ts
|
|
3533
|
+
var getOtherWatchers = (watchers, ownUserId) => {
|
|
3534
|
+
const next = Object.assign({}, watchers ?? {});
|
|
3535
|
+
if (ownUserId) delete next[ownUserId];
|
|
3536
|
+
return next;
|
|
3537
|
+
};
|
|
3538
|
+
var useChannelHasMembersOnline = ({ channel: channelOverride, enabled = true } = {}) => {
|
|
3539
|
+
const { channel: contextChannel } = require_useNotificationApi.useChannelStateContext();
|
|
3540
|
+
const { client } = require_useNotificationApi.useChatContext();
|
|
3541
|
+
const channel = channelOverride ?? contextChannel;
|
|
3542
|
+
const ownUserId = client.user?.id;
|
|
3543
|
+
const [watchers, setWatchers] = (0, react.useState)(() => getOtherWatchers(channel?.state?.watchers, ownUserId));
|
|
3544
|
+
(0, react.useEffect)(() => {
|
|
3545
|
+
setWatchers(getOtherWatchers(channel?.state?.watchers, ownUserId));
|
|
3546
|
+
}, [channel, ownUserId]);
|
|
3547
|
+
(0, react.useEffect)(() => {
|
|
3548
|
+
if (!enabled || !channel) return;
|
|
3549
|
+
const startSubscription = channel.on("user.watching.start", (event) => {
|
|
3550
|
+
setWatchers((prev) => {
|
|
3551
|
+
if (!event.user?.id || event.user.id === ownUserId) return prev;
|
|
3552
|
+
if (prev[event.user.id]) return prev;
|
|
3553
|
+
return Object.assign({ [event.user.id]: event.user }, prev);
|
|
3554
|
+
});
|
|
3555
|
+
});
|
|
3556
|
+
const stopSubscription = channel.on("user.watching.stop", (event) => {
|
|
3557
|
+
setWatchers((prev) => {
|
|
3558
|
+
if (!event.user?.id || !prev[event.user.id]) return prev;
|
|
3559
|
+
const next = Object.assign({}, prev);
|
|
3560
|
+
delete next[event.user.id];
|
|
3561
|
+
return next;
|
|
3562
|
+
});
|
|
3563
|
+
});
|
|
3564
|
+
return () => {
|
|
3565
|
+
startSubscription.unsubscribe();
|
|
3566
|
+
stopSubscription.unsubscribe();
|
|
3567
|
+
};
|
|
3568
|
+
}, [
|
|
3569
|
+
channel,
|
|
3570
|
+
enabled,
|
|
3571
|
+
ownUserId
|
|
3572
|
+
]);
|
|
3573
|
+
if (!enabled) return false;
|
|
3574
|
+
return Object.keys(watchers).length > 0;
|
|
3575
|
+
};
|
|
3576
|
+
//#endregion
|
|
3577
|
+
//#region src/components/ChannelHeader/hooks/useChannelHeaderOnlineStatus.ts
|
|
3578
|
+
/**
|
|
3579
|
+
* Returns the channel header online status text (e.g. "Online", "Offline", or "X members, Y online").
|
|
3580
|
+
* Returns null when the channel has no members (nothing to show).
|
|
3581
|
+
*/
|
|
3582
|
+
function useChannelHeaderOnlineStatus({ channel: channelOverride, watcherCount: watcherCountOverride } = {}) {
|
|
3583
|
+
const { t } = require_useNotificationApi.useTranslationContext();
|
|
3584
|
+
const { client } = require_useNotificationApi.useChatContext();
|
|
3585
|
+
const { channel: contextChannel, watcherCount: contextWatcherCount = 0 } = require_useNotificationApi.useChannelStateContext();
|
|
3586
|
+
const channel = channelOverride ?? contextChannel;
|
|
3587
|
+
const watcherCount = watcherCountOverride ?? contextWatcherCount;
|
|
3588
|
+
const { member_count: memberCount = 0 } = channel?.data || {};
|
|
3589
|
+
const isDirectMessagingChannel = isDmChannel({
|
|
3590
|
+
channel,
|
|
3591
|
+
ownUserId: client.user?.id
|
|
3592
|
+
});
|
|
3593
|
+
const hasMembersOnline = useChannelHasMembersOnline({
|
|
3594
|
+
channel,
|
|
3595
|
+
enabled: isDirectMessagingChannel
|
|
3596
|
+
});
|
|
3597
|
+
if (!memberCount) return null;
|
|
3598
|
+
if (isDirectMessagingChannel) return hasMembersOnline ? t("Online") : t("Offline");
|
|
3599
|
+
return `${t("{{ memberCount }} members", { memberCount })} · ${t("{{ watcherCount }} online", { watcherCount })}`;
|
|
3600
|
+
}
|
|
3601
|
+
//#endregion
|
|
3602
|
+
Object.defineProperty(exports, "Alert", {
|
|
3603
|
+
enumerable: true,
|
|
3604
|
+
get: function() {
|
|
3605
|
+
return Alert;
|
|
3606
|
+
}
|
|
3607
|
+
});
|
|
3608
|
+
Object.defineProperty(exports, "Avatar", {
|
|
3609
|
+
enumerable: true,
|
|
3610
|
+
get: function() {
|
|
3611
|
+
return Avatar;
|
|
3612
|
+
}
|
|
3613
|
+
});
|
|
3614
|
+
Object.defineProperty(exports, "Badge", {
|
|
3615
|
+
enumerable: true,
|
|
3616
|
+
get: function() {
|
|
3617
|
+
return Badge;
|
|
3618
|
+
}
|
|
3619
|
+
});
|
|
3620
|
+
Object.defineProperty(exports, "BaseContextMenuButton", {
|
|
3621
|
+
enumerable: true,
|
|
3622
|
+
get: function() {
|
|
3623
|
+
return BaseContextMenuButton;
|
|
3624
|
+
}
|
|
3625
|
+
});
|
|
3626
|
+
Object.defineProperty(exports, "BaseImage", {
|
|
3627
|
+
enumerable: true,
|
|
3628
|
+
get: function() {
|
|
3629
|
+
return BaseImage;
|
|
3630
|
+
}
|
|
3631
|
+
});
|
|
3632
|
+
Object.defineProperty(exports, "ChannelAvatar", {
|
|
3633
|
+
enumerable: true,
|
|
3634
|
+
get: function() {
|
|
3635
|
+
return ChannelAvatar;
|
|
3636
|
+
}
|
|
3637
|
+
});
|
|
3638
|
+
Object.defineProperty(exports, "Checkbox", {
|
|
3639
|
+
enumerable: true,
|
|
3640
|
+
get: function() {
|
|
3641
|
+
return Checkbox;
|
|
3642
|
+
}
|
|
3643
|
+
});
|
|
3644
|
+
Object.defineProperty(exports, "Checkmark", {
|
|
3645
|
+
enumerable: true,
|
|
3646
|
+
get: function() {
|
|
3647
|
+
return Checkmark;
|
|
3648
|
+
}
|
|
3649
|
+
});
|
|
3650
|
+
Object.defineProperty(exports, "ContextMenu", {
|
|
3651
|
+
enumerable: true,
|
|
3652
|
+
get: function() {
|
|
3653
|
+
return ContextMenu;
|
|
3654
|
+
}
|
|
3655
|
+
});
|
|
3656
|
+
Object.defineProperty(exports, "ContextMenuBackButton", {
|
|
3657
|
+
enumerable: true,
|
|
3658
|
+
get: function() {
|
|
3659
|
+
return ContextMenuBackButton;
|
|
3660
|
+
}
|
|
3661
|
+
});
|
|
3662
|
+
Object.defineProperty(exports, "ContextMenuBody", {
|
|
3663
|
+
enumerable: true,
|
|
3664
|
+
get: function() {
|
|
3665
|
+
return ContextMenuBody;
|
|
3666
|
+
}
|
|
3667
|
+
});
|
|
3668
|
+
Object.defineProperty(exports, "ContextMenuButton", {
|
|
3669
|
+
enumerable: true,
|
|
3670
|
+
get: function() {
|
|
3671
|
+
return ContextMenuButton;
|
|
3672
|
+
}
|
|
3673
|
+
});
|
|
3674
|
+
Object.defineProperty(exports, "ContextMenuContent", {
|
|
3675
|
+
enumerable: true,
|
|
3676
|
+
get: function() {
|
|
3677
|
+
return ContextMenuContent;
|
|
3678
|
+
}
|
|
3679
|
+
});
|
|
3680
|
+
Object.defineProperty(exports, "ContextMenuHeader", {
|
|
3681
|
+
enumerable: true,
|
|
3682
|
+
get: function() {
|
|
3683
|
+
return ContextMenuHeader;
|
|
3684
|
+
}
|
|
3685
|
+
});
|
|
3686
|
+
Object.defineProperty(exports, "ContextMenuRoot", {
|
|
3687
|
+
enumerable: true,
|
|
3688
|
+
get: function() {
|
|
3689
|
+
return ContextMenuRoot;
|
|
3690
|
+
}
|
|
3691
|
+
});
|
|
3692
|
+
Object.defineProperty(exports, "DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR", {
|
|
3693
|
+
enumerable: true,
|
|
3694
|
+
get: function() {
|
|
3695
|
+
return DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR;
|
|
3696
|
+
}
|
|
3697
|
+
});
|
|
3698
|
+
Object.defineProperty(exports, "DialogAnchor", {
|
|
3699
|
+
enumerable: true,
|
|
3700
|
+
get: function() {
|
|
3701
|
+
return DialogAnchor;
|
|
3702
|
+
}
|
|
3703
|
+
});
|
|
3704
|
+
Object.defineProperty(exports, "DownloadButton", {
|
|
3705
|
+
enumerable: true,
|
|
3706
|
+
get: function() {
|
|
3707
|
+
return DownloadButton;
|
|
3708
|
+
}
|
|
3709
|
+
});
|
|
3710
|
+
Object.defineProperty(exports, "EmojiContextMenuButton", {
|
|
3711
|
+
enumerable: true,
|
|
3712
|
+
get: function() {
|
|
3713
|
+
return EmojiContextMenuButton;
|
|
3714
|
+
}
|
|
3715
|
+
});
|
|
3716
|
+
Object.defineProperty(exports, "ErrorBadge", {
|
|
3717
|
+
enumerable: true,
|
|
3718
|
+
get: function() {
|
|
3719
|
+
return ErrorBadge;
|
|
3720
|
+
}
|
|
3721
|
+
});
|
|
3722
|
+
Object.defineProperty(exports, "FILE_ICON_GRAPHIC_CLASSNAME", {
|
|
3723
|
+
enumerable: true,
|
|
3724
|
+
get: function() {
|
|
3725
|
+
return FILE_ICON_GRAPHIC_CLASSNAME;
|
|
3726
|
+
}
|
|
3727
|
+
});
|
|
3728
|
+
Object.defineProperty(exports, "FILE_ICON_NO_LABEL_CLASSNAME", {
|
|
3729
|
+
enumerable: true,
|
|
3730
|
+
get: function() {
|
|
3731
|
+
return FILE_ICON_NO_LABEL_CLASSNAME;
|
|
3732
|
+
}
|
|
3733
|
+
});
|
|
3734
|
+
Object.defineProperty(exports, "FileIcon", {
|
|
3735
|
+
enumerable: true,
|
|
3736
|
+
get: function() {
|
|
3737
|
+
return FileIcon;
|
|
3738
|
+
}
|
|
3739
|
+
});
|
|
3740
|
+
Object.defineProperty(exports, "FileSizeIndicator", {
|
|
3741
|
+
enumerable: true,
|
|
3742
|
+
get: function() {
|
|
3743
|
+
return FileSizeIndicator;
|
|
3744
|
+
}
|
|
3745
|
+
});
|
|
3746
|
+
Object.defineProperty(exports, "Gallery", {
|
|
3747
|
+
enumerable: true,
|
|
3748
|
+
get: function() {
|
|
3749
|
+
return Gallery;
|
|
3750
|
+
}
|
|
3751
|
+
});
|
|
3752
|
+
Object.defineProperty(exports, "GalleryContext", {
|
|
3753
|
+
enumerable: true,
|
|
3754
|
+
get: function() {
|
|
3755
|
+
return GalleryContext;
|
|
3756
|
+
}
|
|
3757
|
+
});
|
|
3758
|
+
Object.defineProperty(exports, "GalleryUI", {
|
|
3759
|
+
enumerable: true,
|
|
3760
|
+
get: function() {
|
|
3761
|
+
return GalleryUI;
|
|
3762
|
+
}
|
|
3763
|
+
});
|
|
3764
|
+
Object.defineProperty(exports, "GlobalModal", {
|
|
3765
|
+
enumerable: true,
|
|
3766
|
+
get: function() {
|
|
3767
|
+
return GlobalModal;
|
|
3768
|
+
}
|
|
3769
|
+
});
|
|
3770
|
+
Object.defineProperty(exports, "GroupAvatar", {
|
|
3771
|
+
enumerable: true,
|
|
3772
|
+
get: function() {
|
|
3773
|
+
return GroupAvatar;
|
|
3774
|
+
}
|
|
3775
|
+
});
|
|
3776
|
+
Object.defineProperty(exports, "Header", {
|
|
3777
|
+
enumerable: true,
|
|
3778
|
+
get: function() {
|
|
3779
|
+
return Header;
|
|
3780
|
+
}
|
|
3781
|
+
});
|
|
3782
|
+
Object.defineProperty(exports, "ImagePlaceholder", {
|
|
3783
|
+
enumerable: true,
|
|
3784
|
+
get: function() {
|
|
3785
|
+
return ImagePlaceholder;
|
|
3786
|
+
}
|
|
3787
|
+
});
|
|
3788
|
+
Object.defineProperty(exports, "ListItemLayout", {
|
|
3789
|
+
enumerable: true,
|
|
3790
|
+
get: function() {
|
|
3791
|
+
return ListItemLayout;
|
|
3792
|
+
}
|
|
3793
|
+
});
|
|
3794
|
+
Object.defineProperty(exports, "ListItemLayoutContent", {
|
|
3795
|
+
enumerable: true,
|
|
3796
|
+
get: function() {
|
|
3797
|
+
return ListItemLayoutContent;
|
|
3798
|
+
}
|
|
3799
|
+
});
|
|
3800
|
+
Object.defineProperty(exports, "LoadingIndicator", {
|
|
3801
|
+
enumerable: true,
|
|
3802
|
+
get: function() {
|
|
3803
|
+
return LoadingIndicator;
|
|
3804
|
+
}
|
|
3805
|
+
});
|
|
3806
|
+
Object.defineProperty(exports, "MessageContext", {
|
|
3807
|
+
enumerable: true,
|
|
3808
|
+
get: function() {
|
|
3809
|
+
return MessageContext;
|
|
3810
|
+
}
|
|
3811
|
+
});
|
|
3812
|
+
Object.defineProperty(exports, "MessageProvider", {
|
|
3813
|
+
enumerable: true,
|
|
3814
|
+
get: function() {
|
|
3815
|
+
return MessageProvider;
|
|
3816
|
+
}
|
|
3817
|
+
});
|
|
3818
|
+
Object.defineProperty(exports, "MessageTimestamp", {
|
|
3819
|
+
enumerable: true,
|
|
3820
|
+
get: function() {
|
|
3821
|
+
return MessageTimestamp;
|
|
3822
|
+
}
|
|
3823
|
+
});
|
|
3824
|
+
Object.defineProperty(exports, "MessageTranslationViewContext", {
|
|
3825
|
+
enumerable: true,
|
|
3826
|
+
get: function() {
|
|
3827
|
+
return MessageTranslationViewContext;
|
|
3828
|
+
}
|
|
3829
|
+
});
|
|
3830
|
+
Object.defineProperty(exports, "MessageTranslationViewProvider", {
|
|
3831
|
+
enumerable: true,
|
|
3832
|
+
get: function() {
|
|
3833
|
+
return MessageTranslationViewProvider;
|
|
3834
|
+
}
|
|
3835
|
+
});
|
|
3836
|
+
Object.defineProperty(exports, "ModalContext", {
|
|
3837
|
+
enumerable: true,
|
|
3838
|
+
get: function() {
|
|
3839
|
+
return ModalContext;
|
|
3840
|
+
}
|
|
3841
|
+
});
|
|
3842
|
+
Object.defineProperty(exports, "ModalContextProvider", {
|
|
3843
|
+
enumerable: true,
|
|
3844
|
+
get: function() {
|
|
3845
|
+
return ModalContextProvider;
|
|
3846
|
+
}
|
|
3847
|
+
});
|
|
3848
|
+
Object.defineProperty(exports, "Notification", {
|
|
3849
|
+
enumerable: true,
|
|
3850
|
+
get: function() {
|
|
3851
|
+
return Notification;
|
|
3852
|
+
}
|
|
3853
|
+
});
|
|
3854
|
+
Object.defineProperty(exports, "NotificationConfigurationProvider", {
|
|
3855
|
+
enumerable: true,
|
|
3856
|
+
get: function() {
|
|
3857
|
+
return NotificationConfigurationProvider;
|
|
3858
|
+
}
|
|
3859
|
+
});
|
|
3860
|
+
Object.defineProperty(exports, "NotificationList", {
|
|
3861
|
+
enumerable: true,
|
|
3862
|
+
get: function() {
|
|
3863
|
+
return NotificationList;
|
|
3864
|
+
}
|
|
3865
|
+
});
|
|
3866
|
+
Object.defineProperty(exports, "Prompt", {
|
|
3867
|
+
enumerable: true,
|
|
3868
|
+
get: function() {
|
|
3869
|
+
return Prompt;
|
|
3870
|
+
}
|
|
3871
|
+
});
|
|
3872
|
+
Object.defineProperty(exports, "Root", {
|
|
3873
|
+
enumerable: true,
|
|
3874
|
+
get: function() {
|
|
3875
|
+
return Root;
|
|
3876
|
+
}
|
|
3877
|
+
});
|
|
3878
|
+
Object.defineProperty(exports, "Switch", {
|
|
3879
|
+
enumerable: true,
|
|
3880
|
+
get: function() {
|
|
3881
|
+
return Switch;
|
|
3882
|
+
}
|
|
3883
|
+
});
|
|
3884
|
+
Object.defineProperty(exports, "SwitchField", {
|
|
3885
|
+
enumerable: true,
|
|
3886
|
+
get: function() {
|
|
3887
|
+
return SwitchField;
|
|
3888
|
+
}
|
|
3889
|
+
});
|
|
3890
|
+
Object.defineProperty(exports, "SwitchFieldDescription", {
|
|
3891
|
+
enumerable: true,
|
|
3892
|
+
get: function() {
|
|
3893
|
+
return SwitchFieldDescription;
|
|
3894
|
+
}
|
|
3895
|
+
});
|
|
3896
|
+
Object.defineProperty(exports, "SwitchFieldLabel", {
|
|
3897
|
+
enumerable: true,
|
|
3898
|
+
get: function() {
|
|
3899
|
+
return SwitchFieldLabel;
|
|
3900
|
+
}
|
|
3901
|
+
});
|
|
3902
|
+
Object.defineProperty(exports, "SwitchFieldTitle", {
|
|
3903
|
+
enumerable: true,
|
|
3904
|
+
get: function() {
|
|
3905
|
+
return SwitchFieldTitle;
|
|
3906
|
+
}
|
|
3907
|
+
});
|
|
3908
|
+
Object.defineProperty(exports, "TextInput", {
|
|
3909
|
+
enumerable: true,
|
|
3910
|
+
get: function() {
|
|
3911
|
+
return TextInput;
|
|
3912
|
+
}
|
|
3913
|
+
});
|
|
3914
|
+
Object.defineProperty(exports, "Timestamp", {
|
|
3915
|
+
enumerable: true,
|
|
3916
|
+
get: function() {
|
|
3917
|
+
return Timestamp;
|
|
3918
|
+
}
|
|
3919
|
+
});
|
|
3920
|
+
Object.defineProperty(exports, "UserContextMenuButton", {
|
|
3921
|
+
enumerable: true,
|
|
3922
|
+
get: function() {
|
|
3923
|
+
return UserContextMenuButton;
|
|
3924
|
+
}
|
|
3925
|
+
});
|
|
3926
|
+
Object.defineProperty(exports, "VideoPlayer", {
|
|
3927
|
+
enumerable: true,
|
|
3928
|
+
get: function() {
|
|
3929
|
+
return VideoPlayer;
|
|
3930
|
+
}
|
|
3931
|
+
});
|
|
3932
|
+
Object.defineProperty(exports, "VideoThumbnail", {
|
|
3933
|
+
enumerable: true,
|
|
3934
|
+
get: function() {
|
|
3935
|
+
return VideoThumbnail;
|
|
3936
|
+
}
|
|
3937
|
+
});
|
|
3938
|
+
Object.defineProperty(exports, "createDefaultPickNext", {
|
|
3939
|
+
enumerable: true,
|
|
3940
|
+
get: function() {
|
|
3941
|
+
return createDefaultPickNext;
|
|
3942
|
+
}
|
|
3943
|
+
});
|
|
3944
|
+
Object.defineProperty(exports, "createRovingFocusKeyDownHandler", {
|
|
3945
|
+
enumerable: true,
|
|
3946
|
+
get: function() {
|
|
3947
|
+
return createRovingFocusKeyDownHandler;
|
|
3948
|
+
}
|
|
3949
|
+
});
|
|
3950
|
+
Object.defineProperty(exports, "formatTime", {
|
|
3951
|
+
enumerable: true,
|
|
3952
|
+
get: function() {
|
|
3953
|
+
return formatTime;
|
|
3954
|
+
}
|
|
3955
|
+
});
|
|
3956
|
+
Object.defineProperty(exports, "getChannelDisplayImage", {
|
|
3957
|
+
enumerable: true,
|
|
3958
|
+
get: function() {
|
|
3959
|
+
return getChannelDisplayImage;
|
|
3960
|
+
}
|
|
3961
|
+
});
|
|
3962
|
+
Object.defineProperty(exports, "getGroupChannelDisplayInfo", {
|
|
3963
|
+
enumerable: true,
|
|
3964
|
+
get: function() {
|
|
3965
|
+
return getGroupChannelDisplayInfo;
|
|
3966
|
+
}
|
|
3967
|
+
});
|
|
3968
|
+
Object.defineProperty(exports, "getLatestMessagePreview", {
|
|
3969
|
+
enumerable: true,
|
|
3970
|
+
get: function() {
|
|
3971
|
+
return getLatestMessagePreview;
|
|
3972
|
+
}
|
|
3973
|
+
});
|
|
3974
|
+
Object.defineProperty(exports, "getTranslatedMessageText", {
|
|
3975
|
+
enumerable: true,
|
|
3976
|
+
get: function() {
|
|
3977
|
+
return getTranslatedMessageText;
|
|
3978
|
+
}
|
|
3979
|
+
});
|
|
3980
|
+
Object.defineProperty(exports, "htmlToTextPlugin", {
|
|
3981
|
+
enumerable: true,
|
|
3982
|
+
get: function() {
|
|
3983
|
+
return htmlToTextPlugin;
|
|
3984
|
+
}
|
|
3985
|
+
});
|
|
3986
|
+
Object.defineProperty(exports, "imageToLink", {
|
|
3987
|
+
enumerable: true,
|
|
3988
|
+
get: function() {
|
|
3989
|
+
return imageToLink;
|
|
3990
|
+
}
|
|
3991
|
+
});
|
|
3992
|
+
Object.defineProperty(exports, "isDmChannel", {
|
|
3993
|
+
enumerable: true,
|
|
3994
|
+
get: function() {
|
|
3995
|
+
return isDmChannel;
|
|
3996
|
+
}
|
|
3997
|
+
});
|
|
3998
|
+
Object.defineProperty(exports, "pickNewest", {
|
|
3999
|
+
enumerable: true,
|
|
4000
|
+
get: function() {
|
|
4001
|
+
return pickNewest;
|
|
4002
|
+
}
|
|
4003
|
+
});
|
|
4004
|
+
Object.defineProperty(exports, "pickOldest", {
|
|
4005
|
+
enumerable: true,
|
|
4006
|
+
get: function() {
|
|
4007
|
+
return pickOldest;
|
|
4008
|
+
}
|
|
4009
|
+
});
|
|
4010
|
+
Object.defineProperty(exports, "plusPlusToEmphasis", {
|
|
4011
|
+
enumerable: true,
|
|
4012
|
+
get: function() {
|
|
4013
|
+
return plusPlusToEmphasis;
|
|
4014
|
+
}
|
|
4015
|
+
});
|
|
4016
|
+
Object.defineProperty(exports, "renderPreviewText", {
|
|
4017
|
+
enumerable: true,
|
|
4018
|
+
get: function() {
|
|
4019
|
+
return renderPreviewText;
|
|
4020
|
+
}
|
|
4021
|
+
});
|
|
4022
|
+
Object.defineProperty(exports, "toBaseImageDescriptors", {
|
|
4023
|
+
enumerable: true,
|
|
4024
|
+
get: function() {
|
|
4025
|
+
return toBaseImageDescriptors;
|
|
4026
|
+
}
|
|
4027
|
+
});
|
|
4028
|
+
Object.defineProperty(exports, "toGalleryItemDescriptors", {
|
|
4029
|
+
enumerable: true,
|
|
4030
|
+
get: function() {
|
|
4031
|
+
return toGalleryItemDescriptors;
|
|
4032
|
+
}
|
|
4033
|
+
});
|
|
4034
|
+
Object.defineProperty(exports, "useAriaIdentifiers", {
|
|
4035
|
+
enumerable: true,
|
|
4036
|
+
get: function() {
|
|
4037
|
+
return useAriaIdentifiers;
|
|
4038
|
+
}
|
|
4039
|
+
});
|
|
4040
|
+
Object.defineProperty(exports, "useChannelDisplayName", {
|
|
4041
|
+
enumerable: true,
|
|
4042
|
+
get: function() {
|
|
4043
|
+
return useChannelDisplayName;
|
|
4044
|
+
}
|
|
4045
|
+
});
|
|
4046
|
+
Object.defineProperty(exports, "useChannelHasMembersOnline", {
|
|
4047
|
+
enumerable: true,
|
|
4048
|
+
get: function() {
|
|
4049
|
+
return useChannelHasMembersOnline;
|
|
4050
|
+
}
|
|
4051
|
+
});
|
|
4052
|
+
Object.defineProperty(exports, "useChannelHeaderOnlineStatus", {
|
|
4053
|
+
enumerable: true,
|
|
4054
|
+
get: function() {
|
|
4055
|
+
return useChannelHeaderOnlineStatus;
|
|
4056
|
+
}
|
|
4057
|
+
});
|
|
4058
|
+
Object.defineProperty(exports, "useChannelMembershipState", {
|
|
4059
|
+
enumerable: true,
|
|
4060
|
+
get: function() {
|
|
4061
|
+
return useChannelMembershipState;
|
|
4062
|
+
}
|
|
4063
|
+
});
|
|
4064
|
+
Object.defineProperty(exports, "useChannelPreviewInfo", {
|
|
4065
|
+
enumerable: true,
|
|
4066
|
+
get: function() {
|
|
4067
|
+
return useChannelPreviewInfo;
|
|
4068
|
+
}
|
|
4069
|
+
});
|
|
4070
|
+
Object.defineProperty(exports, "useContextMenuContext", {
|
|
4071
|
+
enumerable: true,
|
|
4072
|
+
get: function() {
|
|
4073
|
+
return useContextMenuContext;
|
|
4074
|
+
}
|
|
4075
|
+
});
|
|
4076
|
+
Object.defineProperty(exports, "useDialogAnchor", {
|
|
4077
|
+
enumerable: true,
|
|
4078
|
+
get: function() {
|
|
4079
|
+
return useDialogAnchor;
|
|
4080
|
+
}
|
|
4081
|
+
});
|
|
4082
|
+
Object.defineProperty(exports, "useGalleryContext", {
|
|
4083
|
+
enumerable: true,
|
|
4084
|
+
get: function() {
|
|
4085
|
+
return useGalleryContext;
|
|
4086
|
+
}
|
|
4087
|
+
});
|
|
4088
|
+
Object.defineProperty(exports, "useIsChannelMuted", {
|
|
4089
|
+
enumerable: true,
|
|
4090
|
+
get: function() {
|
|
4091
|
+
return useIsChannelMuted;
|
|
4092
|
+
}
|
|
4093
|
+
});
|
|
4094
|
+
Object.defineProperty(exports, "useIsUserMuted", {
|
|
4095
|
+
enumerable: true,
|
|
4096
|
+
get: function() {
|
|
4097
|
+
return useIsUserMuted;
|
|
4098
|
+
}
|
|
4099
|
+
});
|
|
4100
|
+
Object.defineProperty(exports, "useMessageContext", {
|
|
4101
|
+
enumerable: true,
|
|
4102
|
+
get: function() {
|
|
4103
|
+
return useMessageContext;
|
|
4104
|
+
}
|
|
4105
|
+
});
|
|
4106
|
+
Object.defineProperty(exports, "useMessageTranslationViewContext", {
|
|
4107
|
+
enumerable: true,
|
|
4108
|
+
get: function() {
|
|
4109
|
+
return useMessageTranslationViewContext;
|
|
4110
|
+
}
|
|
4111
|
+
});
|
|
4112
|
+
Object.defineProperty(exports, "useModalContext", {
|
|
4113
|
+
enumerable: true,
|
|
4114
|
+
get: function() {
|
|
4115
|
+
return useModalContext;
|
|
4116
|
+
}
|
|
4117
|
+
});
|
|
4118
|
+
Object.defineProperty(exports, "useNotificationConfigurationContext", {
|
|
4119
|
+
enumerable: true,
|
|
4120
|
+
get: function() {
|
|
4121
|
+
return useNotificationConfigurationContext;
|
|
4122
|
+
}
|
|
4123
|
+
});
|
|
4124
|
+
Object.defineProperty(exports, "useNotifications", {
|
|
4125
|
+
enumerable: true,
|
|
4126
|
+
get: function() {
|
|
4127
|
+
return useNotifications;
|
|
4128
|
+
}
|
|
4129
|
+
});
|
|
4130
|
+
Object.defineProperty(exports, "useSelectedChannelState", {
|
|
4131
|
+
enumerable: true,
|
|
4132
|
+
get: function() {
|
|
4133
|
+
return useSelectedChannelState;
|
|
4134
|
+
}
|
|
4135
|
+
});
|
|
4136
|
+
Object.defineProperty(exports, "useStableCallback", {
|
|
4137
|
+
enumerable: true,
|
|
4138
|
+
get: function() {
|
|
4139
|
+
return useStableCallback;
|
|
4140
|
+
}
|
|
4141
|
+
});
|
|
4142
|
+
|
|
4143
|
+
//# sourceMappingURL=useChannelHeaderOnlineStatus.6546ac83.js.map
|