stream-chat-react 14.7.0 → 14.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{ReactPlayerWrapper.c340ab05.js → ReactPlayerWrapper.60a93742.js} +2 -2
- package/dist/cjs/{ReactPlayerWrapper.c340ab05.js.map → ReactPlayerWrapper.60a93742.js.map} +1 -1
- package/dist/cjs/channel-detail.js +2 -2
- package/dist/cjs/emojis.js +2 -2
- package/dist/cjs/index.js +2909 -744
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/{useChannelHeaderOnlineStatus.d39ede24.js → useChannelHeaderOnlineStatus.72753090.js} +373 -63
- package/dist/cjs/useChannelHeaderOnlineStatus.72753090.js.map +1 -0
- package/dist/cjs/{useMessageComposerController.f1a3d182.js → useMessageComposerController.f8f20e3d.js} +2 -2
- package/dist/cjs/{useMessageComposerController.f1a3d182.js.map → useMessageComposerController.f8f20e3d.js.map} +1 -1
- package/dist/cjs/{useNotificationApi.87ba0b39.js → useNotificationApi.bf76a16b.js} +294 -42
- package/dist/cjs/useNotificationApi.bf76a16b.js.map +1 -0
- package/dist/css/index.css +56 -26
- package/dist/css/index.css.map +1 -1
- package/dist/es/channel-detail.mjs +2 -2
- package/dist/es/emojis.mjs +2 -2
- package/dist/es/index.mjs +2874 -735
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/{useChannelHeaderOnlineStatus.b3a51ca7.mjs → useChannelHeaderOnlineStatus.c86db868.mjs} +337 -64
- package/dist/es/useChannelHeaderOnlineStatus.c86db868.mjs.map +1 -0
- package/dist/es/{useMessageComposerController.2309f433.mjs → useMessageComposerController.d50f6168.mjs} +2 -2
- package/dist/es/{useMessageComposerController.2309f433.mjs.map → useMessageComposerController.d50f6168.mjs.map} +1 -1
- package/dist/es/{useNotificationApi.eff88f29.mjs → useNotificationApi.ed6bff88.mjs} +271 -43
- package/dist/es/useNotificationApi.ed6bff88.mjs.map +1 -0
- package/dist/types/a11y/accessibleLabel.d.ts +38 -0
- package/dist/types/a11y/accessibleLabel.d.ts.map +1 -0
- package/dist/types/a11y/hooks/useListboxKeyboardNavigation.d.ts +73 -0
- package/dist/types/a11y/hooks/useListboxKeyboardNavigation.d.ts.map +1 -0
- package/dist/types/a11y/hooks/useVirtualizedListboxKeyboardNavigation.d.ts +41 -0
- package/dist/types/a11y/hooks/useVirtualizedListboxKeyboardNavigation.d.ts.map +1 -0
- package/dist/types/components/Accessibility/AriaLiveAnnouncerProvider.d.ts +13 -0
- package/dist/types/components/Accessibility/AriaLiveAnnouncerProvider.d.ts.map +1 -0
- package/dist/types/components/Accessibility/AriaLiveOutlet.d.ts +24 -0
- package/dist/types/components/Accessibility/AriaLiveOutlet.d.ts.map +1 -0
- package/dist/types/components/Accessibility/AriaLiveOutletContext.d.ts +25 -0
- package/dist/types/components/Accessibility/AriaLiveOutletContext.d.ts.map +1 -0
- package/dist/types/components/Accessibility/NotificationAnnouncer.d.ts +21 -1
- package/dist/types/components/Accessibility/NotificationAnnouncer.d.ts.map +1 -1
- package/dist/types/components/Accessibility/hooks/useAudioPlaybackChangeAnnouncements.d.ts +3 -0
- package/dist/types/components/Accessibility/hooks/useAudioPlaybackChangeAnnouncements.d.ts.map +1 -0
- package/dist/types/components/Accessibility/hooks/useFocusReturn.d.ts +44 -0
- package/dist/types/components/Accessibility/hooks/useFocusReturn.d.ts.map +1 -0
- package/dist/types/components/Accessibility/hooks/useInertWhenHidden.d.ts +88 -0
- package/dist/types/components/Accessibility/hooks/useInertWhenHidden.d.ts.map +1 -0
- package/dist/types/components/Accessibility/hooks/useInteractionAnnouncements.d.ts +114 -0
- package/dist/types/components/Accessibility/hooks/useInteractionAnnouncements.d.ts.map +1 -0
- package/dist/types/components/Accessibility/index.d.ts +7 -1
- package/dist/types/components/Accessibility/index.d.ts.map +1 -1
- package/dist/types/components/Accessibility/scheduling/index.d.ts +4 -0
- package/dist/types/components/Accessibility/scheduling/index.d.ts.map +1 -0
- package/dist/types/components/Accessibility/scheduling/useAnnouncementQueue.d.ts +25 -0
- package/dist/types/components/Accessibility/scheduling/useAnnouncementQueue.d.ts.map +1 -0
- package/dist/types/components/Accessibility/scheduling/useDebouncedAnnounce.d.ts +54 -0
- package/dist/types/components/Accessibility/scheduling/useDebouncedAnnounce.d.ts.map +1 -0
- package/dist/types/components/Accessibility/scheduling/useSettledAnnouncement.d.ts +74 -0
- package/dist/types/components/Accessibility/scheduling/useSettledAnnouncement.d.ts.map +1 -0
- package/dist/types/components/Accessibility/useAriaLiveAnnouncer.d.ts +24 -1
- package/dist/types/components/Accessibility/useAriaLiveAnnouncer.d.ts.map +1 -1
- package/dist/types/components/Attachment/AttachmentActions.d.ts.map +1 -1
- package/dist/types/components/Attachment/Giphy.d.ts.map +1 -1
- package/dist/types/components/Attachment/giphyAccessibility.d.ts +11 -0
- package/dist/types/components/Attachment/giphyAccessibility.d.ts.map +1 -0
- package/dist/types/components/AudioPlayback/WithAudioPlayback.d.ts.map +1 -1
- package/dist/types/components/ChannelList/ChannelListUI.d.ts.map +1 -1
- package/dist/types/components/ChannelList/hooks/index.d.ts +1 -0
- package/dist/types/components/ChannelList/hooks/index.d.ts.map +1 -1
- package/dist/types/components/ChannelList/hooks/useChannelListKeyboardNavigation.d.ts +17 -0
- package/dist/types/components/ChannelList/hooks/useChannelListKeyboardNavigation.d.ts.map +1 -0
- package/dist/types/components/ChannelListItem/ChannelListItem.d.ts +7 -0
- package/dist/types/components/ChannelListItem/ChannelListItem.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.defaults.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemUI.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/index.d.ts +1 -0
- package/dist/types/components/ChannelListItem/index.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/utils.a11y.d.ts +112 -0
- package/dist/types/components/ChannelListItem/utils.a11y.d.ts.map +1 -0
- package/dist/types/components/ChannelListItem/utils.d.ts +10 -2
- package/dist/types/components/ChannelListItem/utils.d.ts.map +1 -1
- package/dist/types/components/Chat/Chat.d.ts.map +1 -1
- package/dist/types/components/ChatView/ChatView.a11y.utility.d.ts +9 -17
- package/dist/types/components/ChatView/ChatView.a11y.utility.d.ts.map +1 -1
- package/dist/types/components/ChatView/ChatView.d.ts +7 -7
- package/dist/types/components/ChatView/ChatView.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/ContextMenu.d.ts +17 -2
- package/dist/types/components/Dialog/components/ContextMenu.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Prompt.d.ts.map +1 -1
- package/dist/types/components/Dialog/service/DialogAnchor.d.ts.map +1 -1
- package/dist/types/components/Form/SwitchField.d.ts.map +1 -1
- package/dist/types/components/Form/TextInput.d.ts.map +1 -1
- package/dist/types/components/InfiniteScrollPaginator/InfiniteScrollPaginator.d.ts +7 -0
- package/dist/types/components/InfiniteScrollPaginator/InfiniteScrollPaginator.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/hooks/useMediaRecorder.d.ts +2 -2
- package/dist/types/components/MediaRecorder/hooks/useMediaRecorder.d.ts.map +1 -1
- package/dist/types/components/MessageActions/DownloadSubmenu.d.ts.map +1 -1
- package/dist/types/components/MessageActions/RemindMeSubmenu.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/AttachmentSelector.d.ts +8 -2
- package/dist/types/components/MessageComposer/AttachmentSelector/AttachmentSelector.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/CommandsMenu.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/CommandChip.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/MessageComposerActions.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/hooks/useAttachmentManagerState.d.ts +2 -0
- package/dist/types/components/MessageComposer/hooks/useAttachmentManagerState.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/index.d.ts +2 -1
- package/dist/types/components/MessageComposer/index.d.ts.map +1 -1
- package/dist/types/components/MessageList/MessageList.d.ts.map +1 -1
- package/dist/types/components/MessageList/VirtualizedMessageList.d.ts.map +1 -1
- package/dist/types/components/Modal/GlobalModal.d.ts +6 -1
- package/dist/types/components/Modal/GlobalModal.d.ts.map +1 -1
- package/dist/types/components/Notifications/Notification.d.ts.map +1 -1
- package/dist/types/components/Notifications/hooks/useNotificationApi.d.ts +7 -0
- package/dist/types/components/Notifications/hooks/useNotificationApi.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/NameField.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/OptionFieldSet.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/PollCreationDialog.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/PollCreationDialogControls.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/PollOptionReorderHandle.d.ts +17 -0
- package/dist/types/components/Poll/PollCreationDialog/PollOptionReorderHandle.d.ts.map +1 -0
- package/dist/types/components/ReactFileUtilities/UploadButton.d.ts.map +1 -1
- package/dist/types/components/Search/Search.d.ts +9 -1
- package/dist/types/components/Search/Search.d.ts.map +1 -1
- package/dist/types/components/Search/SearchBar/SearchBar.d.ts.map +1 -1
- package/dist/types/components/Search/SearchContext.d.ts +1 -1
- package/dist/types/components/Search/SearchContext.d.ts.map +1 -1
- package/dist/types/components/Search/SearchResults/SearchResults.d.ts.map +1 -1
- package/dist/types/components/Search/SearchResults/SearchSourceResultListFooter.d.ts.map +1 -1
- package/dist/types/components/Search/hooks/index.d.ts +2 -0
- package/dist/types/components/Search/hooks/index.d.ts.map +1 -1
- package/dist/types/components/Search/hooks/useAnnounceSearchResultCount.d.ts +27 -0
- package/dist/types/components/Search/hooks/useAnnounceSearchResultCount.d.ts.map +1 -0
- package/dist/types/components/Search/hooks/useSearchResultsKeyboardNavigation.d.ts +13 -0
- package/dist/types/components/Search/hooks/useSearchResultsKeyboardNavigation.d.ts.map +1 -0
- package/dist/types/components/TextareaComposer/SuggestionList/MentionItem/UserItem.d.ts.map +1 -1
- package/dist/types/components/TextareaComposer/SuggestionList/SuggestionList.d.ts +21 -1
- package/dist/types/components/TextareaComposer/SuggestionList/SuggestionList.d.ts.map +1 -1
- package/dist/types/components/TextareaComposer/TextareaComposer.d.ts +9 -1
- package/dist/types/components/TextareaComposer/TextareaComposer.d.ts.map +1 -1
- package/dist/types/components/Threads/ThreadList/ThreadList.d.ts.map +1 -1
- package/dist/types/components/Threads/ThreadList/ThreadListItemUI.d.ts +7 -1
- package/dist/types/components/Threads/ThreadList/ThreadListItemUI.d.ts.map +1 -1
- package/dist/types/components/Threads/ThreadList/index.d.ts +1 -0
- package/dist/types/components/Threads/ThreadList/index.d.ts.map +1 -1
- package/dist/types/components/Threads/ThreadList/utils.a11y.d.ts +111 -0
- package/dist/types/components/Threads/ThreadList/utils.a11y.d.ts.map +1 -0
- package/dist/types/components/Threads/UnreadCountBadge.d.ts.map +1 -1
- package/dist/types/components/UtilityComponents/hooks/useMutationObserver.d.ts +23 -0
- package/dist/types/components/UtilityComponents/hooks/useMutationObserver.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/components/index.d.ts.map +1 -1
- package/dist/types/context/index.d.ts +1 -0
- package/dist/types/context/index.d.ts.map +1 -1
- package/dist/types/i18n/Streami18n.d.ts +79 -13
- package/dist/types/i18n/Streami18n.d.ts.map +1 -1
- package/package.json +6 -3
- package/dist/cjs/useChannelHeaderOnlineStatus.d39ede24.js.map +0 -1
- package/dist/cjs/useNotificationApi.87ba0b39.js.map +0 -1
- package/dist/es/useChannelHeaderOnlineStatus.b3a51ca7.mjs.map +0 -1
- package/dist/es/useNotificationApi.eff88f29.mjs.map +0 -1
- package/dist/types/components/Accessibility/AriaLiveRegion.d.ts +0 -3
- package/dist/types/components/Accessibility/AriaLiveRegion.d.ts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import React, { createContext, createElement, forwardRef, isValidElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
1
|
+
import { $n as useStableId, Ar as DialogPortalEntry, Bn as IconUser, Cr as DialogManagerProvider, En as IconRefresh, Gr as useComponentContext, Ht as IconDownload, Ir as useDialogOnNearestManager, It as IconChevronLeft, Jr as useChatContext, Jt as IconExclamationMarkFill, Lr as useModalDialog, Lt as IconChevronRight, Mt as IconCheckmark, Nr as useDialog, Pr as useDialogIsOpen, Q as isMessageDeleted, Qn as Button, Rr as useModalDialogIsOpen, Tr as modalDialogManagerId, Vr as useStateStore, Yn as IconXmark, Yt as IconExclamationTriangleFill, Zr as useChannelStateContext, _r as getDateString, an as IconLoading, bt as IconArrowDownCircle, ir as isNotificationForPanel, jr as Portal, mr as useTranslationContext, n as hasSystemNotificationTag, qt as IconExclamationMark, r as useNotificationApi, sr as AriaLiveAnnouncerContext, tn as IconImage, vr as isDate, xn as IconPlayFill, xt as IconArrowLeft, z as usePopoverPosition, zr as useModalDialogIsTopmost } from "./useNotificationApi.ed6bff88.mjs";
|
|
2
|
+
import React, { createContext, createElement, forwardRef, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import { isGiphyAttachment, isImageAttachment, isLocalImageAttachment, isLocalVideoAttachment, isScrapedContent, isVideoAttachment } from "stream-chat";
|
|
5
5
|
import clsx from "clsx";
|
|
@@ -9,6 +9,9 @@ import { SKIP, visit } from "unist-util-visit";
|
|
|
9
9
|
import ReactMarkdown from "react-markdown";
|
|
10
10
|
import remarkGfm from "remark-gfm";
|
|
11
11
|
import { sanitizeUrl } from "@braintree/sanitize-url";
|
|
12
|
+
import { toString } from "mdast-util-to-string";
|
|
13
|
+
import remarkParse from "remark-parse";
|
|
14
|
+
import { unified } from "unified";
|
|
12
15
|
//#region src/context/MessageContext.tsx
|
|
13
16
|
var MessageContext = React.createContext(void 0);
|
|
14
17
|
var MessageProvider = ({ children, value }) => /* @__PURE__ */ jsx(MessageContext.Provider, {
|
|
@@ -107,6 +110,84 @@ var useModalContext = () => {
|
|
|
107
110
|
return contextValue;
|
|
108
111
|
};
|
|
109
112
|
//#endregion
|
|
113
|
+
//#region src/components/Accessibility/AriaLiveOutletContext.ts
|
|
114
|
+
var AriaLiveOutletContext = createContext(void 0);
|
|
115
|
+
var useAriaLiveOutletContext = () => useContext(AriaLiveOutletContext);
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/components/VisuallyHidden/VisuallyHidden.tsx
|
|
118
|
+
var visuallyHiddenStyle = {
|
|
119
|
+
border: 0,
|
|
120
|
+
clip: "rect(0, 0, 0, 0)",
|
|
121
|
+
height: "1px",
|
|
122
|
+
margin: "-1px",
|
|
123
|
+
overflow: "hidden",
|
|
124
|
+
padding: 0,
|
|
125
|
+
position: "absolute",
|
|
126
|
+
whiteSpace: "nowrap",
|
|
127
|
+
width: "1px"
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Hides content visually while preserving it for assistive technologies.
|
|
131
|
+
*/
|
|
132
|
+
var VisuallyHidden = ({ children, style, ...rest }) => /* @__PURE__ */ jsx("span", {
|
|
133
|
+
...rest,
|
|
134
|
+
style: {
|
|
135
|
+
...visuallyHiddenStyle,
|
|
136
|
+
...style
|
|
137
|
+
},
|
|
138
|
+
children
|
|
139
|
+
});
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/components/Accessibility/AriaLiveOutlet.tsx
|
|
142
|
+
/**
|
|
143
|
+
* Dumb render target for the unified announcer. Registers itself with the nearest
|
|
144
|
+
* {@link AriaLiveAnnouncerProvider} and renders the polite/assertive live regions ONLY when
|
|
145
|
+
* it is the active (innermost) outlet, so exactly one region is live at a time — always in
|
|
146
|
+
* the active accessibility-tree scope. Mount one at the `Chat` root and one inside each
|
|
147
|
+
* `aria-modal` dialog (with a higher `layer`).
|
|
148
|
+
*/
|
|
149
|
+
var AriaLiveOutlet = ({ layer = 0, portal = false }) => {
|
|
150
|
+
const context = useAriaLiveOutletContext();
|
|
151
|
+
const idRef = useRef(null);
|
|
152
|
+
if (idRef.current === null) idRef.current = Symbol("aria-live-outlet");
|
|
153
|
+
const registerOutlet = context?.registerOutlet;
|
|
154
|
+
const unregisterOutlet = context?.unregisterOutlet;
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
const id = idRef.current;
|
|
157
|
+
if (!id || !registerOutlet || !unregisterOutlet) return;
|
|
158
|
+
registerOutlet(id, layer);
|
|
159
|
+
return () => unregisterOutlet(id);
|
|
160
|
+
}, [
|
|
161
|
+
layer,
|
|
162
|
+
registerOutlet,
|
|
163
|
+
unregisterOutlet
|
|
164
|
+
]);
|
|
165
|
+
const getPortalDestination = useCallback(() => document.body, []);
|
|
166
|
+
if (!context || context.activeOutletId !== idRef.current) return null;
|
|
167
|
+
const { announcementsByPriority } = context;
|
|
168
|
+
const liveRegions = /* @__PURE__ */ jsxs(VisuallyHidden, { children: [/* @__PURE__ */ jsx("div", {
|
|
169
|
+
"aria-atomic": "false",
|
|
170
|
+
"aria-live": "polite",
|
|
171
|
+
"aria-relevant": "additions",
|
|
172
|
+
"data-testid": "str-chat__aria-live-region--polite",
|
|
173
|
+
role: "status",
|
|
174
|
+
children: announcementsByPriority.polite.map((announcement) => /* @__PURE__ */ jsx("div", { children: announcement.message }, announcement.id))
|
|
175
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
176
|
+
"aria-atomic": "false",
|
|
177
|
+
"aria-live": "assertive",
|
|
178
|
+
"aria-relevant": "additions",
|
|
179
|
+
"data-testid": "str-chat__aria-live-region--assertive",
|
|
180
|
+
role: "alert",
|
|
181
|
+
children: announcementsByPriority.assertive.map((announcement) => /* @__PURE__ */ jsx("div", { children: announcement.message }, announcement.id))
|
|
182
|
+
})] });
|
|
183
|
+
if (!portal) return liveRegions;
|
|
184
|
+
return /* @__PURE__ */ jsx(Portal, {
|
|
185
|
+
getPortalDestination,
|
|
186
|
+
isOpen: true,
|
|
187
|
+
children: liveRegions
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
//#endregion
|
|
110
191
|
//#region src/components/Notifications/NotificationConfigurationContext.tsx
|
|
111
192
|
var defaultNotificationDisplayFilter = () => true;
|
|
112
193
|
var defaultNotificationConfigurationContextValue = { displayFilter: defaultNotificationDisplayFilter };
|
|
@@ -418,7 +499,7 @@ var DialogAnchor = ({ allowFlip = true, children, className, closeOnClickOutside
|
|
|
418
499
|
autoFocus: focus,
|
|
419
500
|
contain: trapFocus,
|
|
420
501
|
restoreFocus: true,
|
|
421
|
-
children: /* @__PURE__ */
|
|
502
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
422
503
|
...anchorDivProps,
|
|
423
504
|
"aria-describedby": ariaDescribedBy,
|
|
424
505
|
"aria-label": resolvedAriaLabel,
|
|
@@ -432,7 +513,7 @@ var DialogAnchor = ({ allowFlip = true, children, className, closeOnClickOutside
|
|
|
432
513
|
role: resolvedRole,
|
|
433
514
|
style: styles,
|
|
434
515
|
tabIndex: typeof tabIndex !== "undefined" ? tabIndex : 0,
|
|
435
|
-
children
|
|
516
|
+
children: [children, resolvedAriaModal && /* @__PURE__ */ jsx(AriaLiveOutlet, { layer: 1 })]
|
|
436
517
|
})
|
|
437
518
|
})
|
|
438
519
|
});
|
|
@@ -639,6 +720,7 @@ var UserContextMenuButton = ({ children, className, imageUrl, role = "menuitem",
|
|
|
639
720
|
role,
|
|
640
721
|
type: "button",
|
|
641
722
|
children: [/* @__PURE__ */ jsx(Avatar, {
|
|
723
|
+
"aria-hidden": true,
|
|
642
724
|
imageUrl,
|
|
643
725
|
size: "sm",
|
|
644
726
|
userName
|
|
@@ -783,13 +865,28 @@ var ContextMenuButton = (props) => {
|
|
|
783
865
|
});
|
|
784
866
|
return /* @__PURE__ */ jsx(BaseContextMenuButton, { ...buttonProps });
|
|
785
867
|
};
|
|
786
|
-
var ContextMenuBackButton = ({ children, className, role = "menuitem", ...props }) =>
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
868
|
+
var ContextMenuBackButton = ({ "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, children, className, role = "menuitem", ...props }) => {
|
|
869
|
+
const { t } = useTranslationContext();
|
|
870
|
+
const generatedBackNavigationLabelId = useStableId();
|
|
871
|
+
const generatedVisibleLabelId = useStableId();
|
|
872
|
+
const resolvedAriaLabel = ariaLabel ?? t("aria/Back to parent menu button");
|
|
873
|
+
const resolvedAriaLabelledBy = ariaLabelledBy ?? `${generatedVisibleLabelId} ${generatedBackNavigationLabelId}`;
|
|
874
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
875
|
+
...props,
|
|
876
|
+
"aria-labelledby": resolvedAriaLabelledBy,
|
|
877
|
+
className: clsx("str-chat__context-menu__back-button", className),
|
|
878
|
+
role,
|
|
879
|
+
type: "button",
|
|
880
|
+
children: [!ariaLabelledBy && /* @__PURE__ */ jsx(VisuallyHidden, {
|
|
881
|
+
id: generatedBackNavigationLabelId,
|
|
882
|
+
children: resolvedAriaLabel
|
|
883
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
884
|
+
className: "str-chat__context-menu__back-button__content",
|
|
885
|
+
id: generatedVisibleLabelId,
|
|
886
|
+
children
|
|
887
|
+
})]
|
|
888
|
+
});
|
|
889
|
+
};
|
|
793
890
|
var ContextMenuHeader = ({ children, className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
794
891
|
...props,
|
|
795
892
|
className: clsx("str-chat__context-menu__header", className),
|
|
@@ -837,6 +934,13 @@ var resolveContextMenuFocusRestoreTarget = ({ contextMenuRoot, request }) => {
|
|
|
837
934
|
if (request.index >= 0) return getVisibleContextMenuKeyboardNavigationItems(contextMenuRoot)[request.index] ?? null;
|
|
838
935
|
return null;
|
|
839
936
|
};
|
|
937
|
+
var CONTEXT_MENU_HEADER_SELECTOR = ".str-chat__context-menu__header";
|
|
938
|
+
var resolveSubmenuInitialFocusTarget = ({ contextMenuRoot, initialFocus, itemSelector }) => {
|
|
939
|
+
if (initialFocus === "none") return null;
|
|
940
|
+
const items = getVisibleContextMenuKeyboardNavigationItems(contextMenuRoot, itemSelector);
|
|
941
|
+
if (initialFocus === "first") return items[0] ?? null;
|
|
942
|
+
return items.find((item) => !item.closest(CONTEXT_MENU_HEADER_SELECTOR)) ?? items[0] ?? null;
|
|
943
|
+
};
|
|
840
944
|
var ContextMenuContext = React.createContext(void 0);
|
|
841
945
|
var useContextMenuContext = () => useContext(ContextMenuContext);
|
|
842
946
|
/**
|
|
@@ -846,7 +950,10 @@ var useContextMenuContext = () => useContext(ContextMenuContext);
|
|
|
846
950
|
* customize submenu/back navigation behavior while keeping the same anchor/focus
|
|
847
951
|
* handling from `ContextMenu`.
|
|
848
952
|
*/
|
|
849
|
-
function ContextMenuContent({ anchorReferenceElement, backLabel
|
|
953
|
+
function ContextMenuContent({ anchorReferenceElement, backButtonAriaLabel, backLabel, children, className, enableAnimations = true, Header, items, ItemsWrapper, keyboardNavigation, menuClassName, onClose, onMenuLevelChange, transitionDirection, ...props }) {
|
|
954
|
+
const { t } = useTranslationContext();
|
|
955
|
+
const resolvedBackLabel = backLabel ?? t("Back");
|
|
956
|
+
const { ["aria-describedby"]: rootAriaDescribedBy, ["aria-label"]: rootAriaLabel, ["aria-labelledby"]: rootAriaLabelledBy, ...contextMenuRootProps } = props;
|
|
850
957
|
const rootLevel = useMemo(() => ({
|
|
851
958
|
Header,
|
|
852
959
|
items,
|
|
@@ -862,18 +969,23 @@ function ContextMenuContent({ anchorReferenceElement, backLabel = "Back", childr
|
|
|
862
969
|
const [menuBodyAnimationKey, setMenuBodyAnimationKey] = useState(0);
|
|
863
970
|
const contextMenuRootRef = useRef(null);
|
|
864
971
|
const focusRestoreRequestRef = useRef(null);
|
|
972
|
+
const pendingForwardFocusRef = useRef(null);
|
|
865
973
|
const activeMenu = menuStack[menuStack.length - 1];
|
|
974
|
+
const keyboardNavigationItemSelector = keyboardNavigation?.itemSelector ?? DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR;
|
|
866
975
|
const ActiveMenuItemsWrapper = activeMenu.ItemsWrapper ?? React.Fragment;
|
|
867
976
|
const closeMenu = useCallback(() => {
|
|
868
977
|
onClose?.();
|
|
869
978
|
}, [onClose]);
|
|
870
|
-
const openSubmenu = useCallback(({ focusReturnTarget, Header, ItemsWrapper: SubmenuItemsWrapper, menuClassName, Submenu }) => {
|
|
979
|
+
const openSubmenu = useCallback(({ focusReturnTarget, Header, initialFocus = "first-item", ItemsWrapper: SubmenuItemsWrapper, menuClassName, Submenu }) => {
|
|
980
|
+
pendingForwardFocusRef.current = initialFocus;
|
|
981
|
+
focusRestoreRequestRef.current = null;
|
|
871
982
|
const nextLevel = {
|
|
872
983
|
focusRestoreRequest: createContextMenuFocusRestoreRequest({
|
|
873
984
|
contextMenuRoot: contextMenuRootRef.current,
|
|
874
985
|
focusReturnTarget
|
|
875
986
|
}),
|
|
876
987
|
Header,
|
|
988
|
+
initialFocus,
|
|
877
989
|
ItemsWrapper: SubmenuItemsWrapper ?? ItemsWrapper,
|
|
878
990
|
menuClassName,
|
|
879
991
|
Submenu
|
|
@@ -884,6 +996,7 @@ function ContextMenuContent({ anchorReferenceElement, backLabel = "Back", childr
|
|
|
884
996
|
setMenuStack((current) => {
|
|
885
997
|
if (current.length <= 1) return current;
|
|
886
998
|
focusRestoreRequestRef.current = current[current.length - 1]?.focusRestoreRequest ?? null;
|
|
999
|
+
pendingForwardFocusRef.current = null;
|
|
887
1000
|
return current.slice(0, -1);
|
|
888
1001
|
});
|
|
889
1002
|
}, []);
|
|
@@ -896,17 +1009,24 @@ function ContextMenuContent({ anchorReferenceElement, backLabel = "Back", childr
|
|
|
896
1009
|
useEffect(() => {
|
|
897
1010
|
onMenuLevelChange?.(menuStack.length);
|
|
898
1011
|
}, [menuStack.length, onMenuLevelChange]);
|
|
899
|
-
|
|
1012
|
+
useLayoutEffect(() => {
|
|
900
1013
|
const focusRestoreRequest = focusRestoreRequestRef.current;
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1014
|
+
const pendingForwardFocus = pendingForwardFocusRef.current;
|
|
1015
|
+
if (!focusRestoreRequest && !pendingForwardFocus) return;
|
|
1016
|
+
const contextMenuRoot = contextMenuRootRef.current;
|
|
1017
|
+
(focusRestoreRequest ? resolveContextMenuFocusRestoreTarget({
|
|
1018
|
+
contextMenuRoot,
|
|
1019
|
+
request: focusRestoreRequest
|
|
1020
|
+
}) : resolveSubmenuInitialFocusTarget({
|
|
1021
|
+
contextMenuRoot,
|
|
1022
|
+
initialFocus: pendingForwardFocus,
|
|
1023
|
+
itemSelector: keyboardNavigationItemSelector
|
|
1024
|
+
}))?.focus();
|
|
1025
|
+
}, [
|
|
1026
|
+
keyboardNavigationItemSelector,
|
|
1027
|
+
menuBodyAnimationKey,
|
|
1028
|
+
menuStack.length
|
|
1029
|
+
]);
|
|
910
1030
|
useEffect(() => {
|
|
911
1031
|
if (!transitionDirection) return;
|
|
912
1032
|
setMenuBodyAnimationKey((value) => value + 1);
|
|
@@ -918,10 +1038,7 @@ function ContextMenuContent({ anchorReferenceElement, backLabel = "Back", childr
|
|
|
918
1038
|
const unregisterDialogSubmenu = useCallback(() => {
|
|
919
1039
|
dialogSubmenuOpenCountRef.current = Math.max(0, dialogSubmenuOpenCountRef.current - 1);
|
|
920
1040
|
}, []);
|
|
921
|
-
const rovingFocusKeyDownHandler = useMemo(() => {
|
|
922
|
-
const itemSelector = keyboardNavigation?.itemSelector ?? DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR;
|
|
923
|
-
return createRovingFocusKeyDownHandler({ getItems: (event) => getVisibleContextMenuKeyboardNavigationItems(event.currentTarget, itemSelector) });
|
|
924
|
-
}, [keyboardNavigation]);
|
|
1041
|
+
const rovingFocusKeyDownHandler = useMemo(() => createRovingFocusKeyDownHandler({ getItems: (event) => getVisibleContextMenuKeyboardNavigationItems(event.currentTarget, keyboardNavigationItemSelector) }), [keyboardNavigationItemSelector]);
|
|
925
1042
|
const escapeConsumedRef = useRef(false);
|
|
926
1043
|
const keyboardNavigationHandler = useCallback((event) => {
|
|
927
1044
|
if (event.key === "Escape") {
|
|
@@ -947,6 +1064,7 @@ function ContextMenuContent({ anchorReferenceElement, backLabel = "Back", childr
|
|
|
947
1064
|
event.stopPropagation();
|
|
948
1065
|
}
|
|
949
1066
|
}, []);
|
|
1067
|
+
const isSubmenuLevel = menuStack.length > 1;
|
|
950
1068
|
return /* @__PURE__ */ jsx(ContextMenuContext.Provider, {
|
|
951
1069
|
value: {
|
|
952
1070
|
anchorReferenceElement,
|
|
@@ -957,15 +1075,19 @@ function ContextMenuContent({ anchorReferenceElement, backLabel = "Back", childr
|
|
|
957
1075
|
unregisterDialogSubmenu
|
|
958
1076
|
},
|
|
959
1077
|
children: /* @__PURE__ */ jsxs(ContextMenuRoot, {
|
|
1078
|
+
"aria-describedby": isSubmenuLevel ? void 0 : rootAriaDescribedBy,
|
|
1079
|
+
"aria-label": isSubmenuLevel ? t("aria/Submenu") : rootAriaLabel,
|
|
1080
|
+
"aria-labelledby": isSubmenuLevel ? void 0 : rootAriaLabelledBy,
|
|
960
1081
|
className: clsx(className, activeMenu.menuClassName),
|
|
961
1082
|
"data-str-chat-enable-animations": enableAnimations,
|
|
962
1083
|
onKeyDownCapture: keyboardNavigationHandler,
|
|
963
1084
|
onKeyUpCapture: suppressEscapeKeyUp,
|
|
964
1085
|
ref: contextMenuRootRef,
|
|
965
|
-
...
|
|
1086
|
+
...contextMenuRootProps,
|
|
966
1087
|
children: [activeMenu.Header ? /* @__PURE__ */ jsx(activeMenu.Header, {}) : menuStack.length > 1 ? /* @__PURE__ */ jsx(ContextMenuHeader, { children: /* @__PURE__ */ jsxs(ContextMenuBackButton, {
|
|
1088
|
+
"aria-label": backButtonAriaLabel,
|
|
967
1089
|
onClick: returnToParentMenu,
|
|
968
|
-
children: [/* @__PURE__ */ jsx(IconChevronLeft, {}), /* @__PURE__ */ jsx("span", { children:
|
|
1090
|
+
children: [/* @__PURE__ */ jsx(IconChevronLeft, {}), /* @__PURE__ */ jsx("span", { children: resolvedBackLabel })]
|
|
969
1091
|
}) }) : null, /* @__PURE__ */ jsx(ContextMenuBody, {
|
|
970
1092
|
className: clsx({
|
|
971
1093
|
"str-chat__context-menu__body--submenu-backward": transitionDirection === "backward",
|
|
@@ -1070,9 +1192,13 @@ var ContextMenu = (props) => {
|
|
|
1070
1192
|
transitionDirection
|
|
1071
1193
|
});
|
|
1072
1194
|
if (isAnchored) {
|
|
1073
|
-
const { backLabel: _b, enableAnimations: _ea, Header: _h, items: _i, ItemsWrapper: _w, keyboardNavigation: _kn, menuClassName: _m, onClose: _c, role: _r, ...anchorDivProps } = menuProps;
|
|
1195
|
+
const { ["aria-describedby"]: ariaDescribedBy, ["aria-label"]: ariaLabel, ["aria-labelledby"]: ariaLabelledBy, backButtonAriaLabel: _bbal, backLabel: _b, enableAnimations: _ea, Header: _h, items: _i, ItemsWrapper: _w, keyboardNavigation: _kn, menuClassName: _m, onClose: _c, role: _r, ...anchorDivProps } = menuProps;
|
|
1196
|
+
const isSubmenuLevel = menuLevel > 1;
|
|
1074
1197
|
return /* @__PURE__ */ jsx(DialogAnchor, {
|
|
1075
1198
|
allowFlip,
|
|
1199
|
+
"aria-describedby": isSubmenuLevel ? void 0 : ariaDescribedBy,
|
|
1200
|
+
"aria-label": isSubmenuLevel ? void 0 : ariaLabel,
|
|
1201
|
+
"aria-labelledby": isSubmenuLevel ? void 0 : ariaLabelledBy,
|
|
1076
1202
|
closeOnClickOutside,
|
|
1077
1203
|
closeTransitionMs,
|
|
1078
1204
|
dialogManagerId,
|
|
@@ -1143,8 +1269,7 @@ var PromptHeader = ({ className, close, description, descriptionId, goBack, Lead
|
|
|
1143
1269
|
className: "str-chat__prompt__header__trailing-content",
|
|
1144
1270
|
children: [TrailingContent && /* @__PURE__ */ jsx(TrailingContent, {}), close && /* @__PURE__ */ jsx(Button, {
|
|
1145
1271
|
appearance: "ghost",
|
|
1146
|
-
"aria-
|
|
1147
|
-
"aria-label": typeof title === "string" ? t("Close prompt: {{ title }}", { title }) : t("Close"),
|
|
1272
|
+
"aria-label": t("Close"),
|
|
1148
1273
|
circular: true,
|
|
1149
1274
|
className: "str-chat__prompt__header__close-button",
|
|
1150
1275
|
onClick: close,
|
|
@@ -1220,19 +1345,21 @@ var useResolvedModalAriaProps = ({ ariaDescribedby, ariaLabel, ariaLabelledby, d
|
|
|
1220
1345
|
};
|
|
1221
1346
|
//#endregion
|
|
1222
1347
|
//#region src/components/Modal/GlobalModal.tsx
|
|
1223
|
-
var GlobalModal = ({ "aria-describedby": ariaDescribedby, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, children, className, CloseButtonOnOverlay, dialogId, dialogRootProps, onClose, onCloseAttempt, open, role = "dialog" }) => {
|
|
1348
|
+
var GlobalModal = ({ "aria-describedby": ariaDescribedby, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, children, className, CloseButtonOnOverlay, dialogId, dialogRootProps, getInitialFocusElement, initialFocusStrategy, onClose, onCloseAttempt, open, role = "dialog" }) => {
|
|
1224
1349
|
const generatedDialogId = useStableId();
|
|
1225
1350
|
const resolvedDialogId = dialogId ?? `modal-dialog-${generatedDialogId}`;
|
|
1226
1351
|
const dialog = useModalDialog(resolvedDialogId);
|
|
1227
1352
|
const isOpen = useModalDialogIsOpen(resolvedDialogId);
|
|
1228
1353
|
const isTopmost = useModalDialogIsTopmost(resolvedDialogId);
|
|
1229
1354
|
const overlayRef = useRef(null);
|
|
1355
|
+
const dialogRef = useRef(null);
|
|
1230
1356
|
const closeButtonRef = useRef(null);
|
|
1231
1357
|
const closingRef = useRef(false);
|
|
1232
1358
|
const { theme } = useChatContext();
|
|
1233
1359
|
const { NotificationList: NotificationList$1 = NotificationList } = useComponentContext();
|
|
1234
1360
|
const { className: dialogRootClassName, onKeyDown: dialogRootOnKeyDown, ...dialogRootPropsRest } = dialogRootProps ?? {};
|
|
1235
|
-
const dialogLabelingBaseId =
|
|
1361
|
+
const dialogLabelingBaseId = resolvedDialogId;
|
|
1362
|
+
const resolvedInitialFocusStrategy = initialFocusStrategy ?? "firstElement";
|
|
1236
1363
|
const resolvedModalAriaProps = useResolvedModalAriaProps({
|
|
1237
1364
|
ariaDescribedby,
|
|
1238
1365
|
ariaLabel,
|
|
@@ -1265,8 +1392,18 @@ var GlobalModal = ({ "aria-describedby": ariaDescribedby, "aria-label": ariaLabe
|
|
|
1265
1392
|
};
|
|
1266
1393
|
const handleDialogKeyDown = (event) => {
|
|
1267
1394
|
dialogRootOnKeyDown?.(event);
|
|
1268
|
-
if (event.defaultPrevented ||
|
|
1269
|
-
|
|
1395
|
+
if (event.defaultPrevented || !isTopmost) return;
|
|
1396
|
+
if (event.key === "Escape") {
|
|
1397
|
+
maybeClose("escape", event);
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
if (event.key === "Enter" && event.target === dialogRef.current) {
|
|
1401
|
+
const target = dialogRef.current?.querySelector("[data-autofocus]");
|
|
1402
|
+
if (target) {
|
|
1403
|
+
event.preventDefault();
|
|
1404
|
+
target.focus();
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1270
1407
|
};
|
|
1271
1408
|
useEffect(() => {
|
|
1272
1409
|
if (!open) {
|
|
@@ -1280,6 +1417,21 @@ var GlobalModal = ({ "aria-describedby": ariaDescribedby, "aria-label": ariaLabe
|
|
|
1280
1417
|
isOpen,
|
|
1281
1418
|
open
|
|
1282
1419
|
]);
|
|
1420
|
+
useEffect(() => {
|
|
1421
|
+
if (!open || !isOpen || !isTopmost || !getInitialFocusElement && resolvedInitialFocusStrategy === "firstElement") return;
|
|
1422
|
+
const frame = requestAnimationFrame(() => {
|
|
1423
|
+
const dialogElement = dialogRef.current;
|
|
1424
|
+
if (!dialogElement) return;
|
|
1425
|
+
(getInitialFocusElement?.(dialogElement) ?? dialogElement).focus();
|
|
1426
|
+
});
|
|
1427
|
+
return () => cancelAnimationFrame(frame);
|
|
1428
|
+
}, [
|
|
1429
|
+
getInitialFocusElement,
|
|
1430
|
+
isOpen,
|
|
1431
|
+
isTopmost,
|
|
1432
|
+
open,
|
|
1433
|
+
resolvedInitialFocusStrategy
|
|
1434
|
+
]);
|
|
1283
1435
|
if (!open || !isOpen) return null;
|
|
1284
1436
|
return /* @__PURE__ */ jsx(DialogPortalEntry, {
|
|
1285
1437
|
dialogId: resolvedDialogId,
|
|
@@ -1292,7 +1444,7 @@ var GlobalModal = ({ "aria-describedby": ariaDescribedby, "aria-label": ariaLabe
|
|
|
1292
1444
|
ref: overlayRef,
|
|
1293
1445
|
children: [
|
|
1294
1446
|
/* @__PURE__ */ jsx(FocusScope, {
|
|
1295
|
-
autoFocus: isTopmost,
|
|
1447
|
+
autoFocus: isTopmost && !getInitialFocusElement && resolvedInitialFocusStrategy === "firstElement",
|
|
1296
1448
|
contain: isTopmost,
|
|
1297
1449
|
restoreFocus: true,
|
|
1298
1450
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -1304,15 +1456,16 @@ var GlobalModal = ({ "aria-describedby": ariaDescribedby, "aria-label": ariaLabe
|
|
|
1304
1456
|
className: clsx("str-chat__modal__dialog", dialogRootClassName),
|
|
1305
1457
|
inert: isTopmost ? void 0 : true,
|
|
1306
1458
|
onKeyDown: handleDialogKeyDown,
|
|
1459
|
+
ref: dialogRef,
|
|
1307
1460
|
role,
|
|
1308
1461
|
tabIndex: isTopmost ? 0 : -1,
|
|
1309
|
-
children: /* @__PURE__ */
|
|
1462
|
+
children: /* @__PURE__ */ jsxs(DialogManagerProvider, {
|
|
1310
1463
|
id: `${resolvedDialogId}-floating-dialog-manager`,
|
|
1311
1464
|
portalDestinationProps: {
|
|
1312
1465
|
captureOutsideClicks: true,
|
|
1313
1466
|
className: "str-chat__modal__floating-dialog-overlay"
|
|
1314
1467
|
},
|
|
1315
|
-
children
|
|
1468
|
+
children: [children, isTopmost && /* @__PURE__ */ jsx(AriaLiveOutlet, { layer: 1 })]
|
|
1316
1469
|
})
|
|
1317
1470
|
})
|
|
1318
1471
|
}),
|
|
@@ -2676,13 +2829,28 @@ var SwitchField = ({ children, description, fieldClassName, title, ...props }) =
|
|
|
2676
2829
|
const switchId = id ?? `str-chat__switch-field-${generatedSwitchId}`;
|
|
2677
2830
|
const switchLabelId = `${switchId}-label`;
|
|
2678
2831
|
const inputRef = useRef(null);
|
|
2832
|
+
const announce = useContext(AriaLiveAnnouncerContext)?.announce;
|
|
2833
|
+
const { t } = useTranslationContext("SwitchField");
|
|
2679
2834
|
const [uncontrolledChecked, setUncontrolledChecked] = useState(Boolean(defaultChecked));
|
|
2680
2835
|
const isControlled = checked !== void 0;
|
|
2681
2836
|
const isOn = isControlled ? checked : uncontrolledChecked;
|
|
2682
2837
|
const isReadOnly = isControlled && onChange === void 0;
|
|
2838
|
+
const childLabelId = (isValidElement(children) ? children : void 0)?.props.id;
|
|
2839
|
+
const resolvedAriaLabelledBy = ariaLabelledBy ?? (!ariaLabel ? title ? switchLabelId : childLabelId : void 0);
|
|
2840
|
+
const resolveAnnouncementName = () => {
|
|
2841
|
+
if (title) return title;
|
|
2842
|
+
if (ariaLabel) return ariaLabel;
|
|
2843
|
+
if (resolvedAriaLabelledBy) {
|
|
2844
|
+
const labelEl = document.getElementById(resolvedAriaLabelledBy);
|
|
2845
|
+
return ((labelEl?.querySelector(".str-chat__form__switch-field__label__text"))?.textContent || labelEl?.textContent || "").trim() || void 0;
|
|
2846
|
+
}
|
|
2847
|
+
};
|
|
2683
2848
|
const handleChange = (event) => {
|
|
2684
2849
|
if (!isControlled) setUncontrolledChecked(event.target.checked);
|
|
2685
2850
|
onChange?.(event);
|
|
2851
|
+
const setting = resolveAnnouncementName();
|
|
2852
|
+
if (!announce || !setting) return;
|
|
2853
|
+
announce(event.target.checked ? t("aria/{{ setting }} enabled", { setting }) : t("aria/{{ setting }} disabled", { setting }), { priority: "polite" });
|
|
2686
2854
|
};
|
|
2687
2855
|
const handleKeyDown = (event) => {
|
|
2688
2856
|
onKeyDown?.(event);
|
|
@@ -2694,8 +2862,6 @@ var SwitchField = ({ children, description, fieldClassName, title, ...props }) =
|
|
|
2694
2862
|
if (disabled || event.target === inputRef.current) return;
|
|
2695
2863
|
inputRef.current?.click();
|
|
2696
2864
|
};
|
|
2697
|
-
const childLabelId = (isValidElement(children) ? children : void 0)?.props.id;
|
|
2698
|
-
const resolvedAriaLabelledBy = ariaLabelledBy ?? (!ariaLabel ? title ? switchLabelId : childLabelId : void 0);
|
|
2699
2865
|
return /* @__PURE__ */ jsxs("div", {
|
|
2700
2866
|
className: clsx("str-chat__form__switch-field", fieldClassName, disabled && "str-chat__form__switch-field--disabled"),
|
|
2701
2867
|
children: [title ? /* @__PURE__ */ jsx(SwitchFieldLabel, {
|
|
@@ -2835,7 +3001,6 @@ var TextInput = forwardRef(function TextInput({ className, disabled, error = fal
|
|
|
2835
3001
|
className: "str-chat__form-text-input__control-row",
|
|
2836
3002
|
children: [
|
|
2837
3003
|
leading ? /* @__PURE__ */ jsx("span", {
|
|
2838
|
-
"aria-hidden": true,
|
|
2839
3004
|
className: "str-chat__form-text-input__leading",
|
|
2840
3005
|
children: leading
|
|
2841
3006
|
}) : null,
|
|
@@ -2854,7 +3019,6 @@ var TextInput = forwardRef(function TextInput({ className, disabled, error = fal
|
|
|
2854
3019
|
children: trailingText
|
|
2855
3020
|
}) : null,
|
|
2856
3021
|
trailing ? /* @__PURE__ */ jsx("span", {
|
|
2857
|
-
"aria-hidden": true,
|
|
2858
3022
|
className: "str-chat__form-text-input__trailing",
|
|
2859
3023
|
children: trailing
|
|
2860
3024
|
}) : null
|
|
@@ -2934,6 +3098,16 @@ var renderPreviewText = (text) => /* @__PURE__ */ jsx(ReactMarkdown, {
|
|
|
2934
3098
|
skipHtml: true,
|
|
2935
3099
|
children: text
|
|
2936
3100
|
});
|
|
3101
|
+
var createPlainTextProcessor = () => unified().use(remarkParse).use(remarkPlugins);
|
|
3102
|
+
var plainTextProcessor;
|
|
3103
|
+
var stripMarkdownToText = (text) => {
|
|
3104
|
+
try {
|
|
3105
|
+
const processor = plainTextProcessor ?? (plainTextProcessor = createPlainTextProcessor());
|
|
3106
|
+
return toString(processor.runSync(processor.parse(text))) || text;
|
|
3107
|
+
} catch {
|
|
3108
|
+
return text;
|
|
3109
|
+
}
|
|
3110
|
+
};
|
|
2937
3111
|
var getLatestPollVote = (latestVotesByOption) => {
|
|
2938
3112
|
let latestVote;
|
|
2939
3113
|
for (const optionVotes of Object.values(latestVotesByOption)) optionVotes.forEach((vote) => {
|
|
@@ -2942,32 +3116,130 @@ var getLatestPollVote = (latestVotesByOption) => {
|
|
|
2942
3116
|
});
|
|
2943
3117
|
return latestVote;
|
|
2944
3118
|
};
|
|
2945
|
-
|
|
2946
|
-
|
|
3119
|
+
/**
|
|
3120
|
+
* Resolves the channel's latest-message preview once: the localized DISPLAY string, a `kind`
|
|
3121
|
+
* discriminant, and the bits announcements need (poll question, attachment type). Single source of
|
|
3122
|
+
* truth for the display variant ({@link getLatestMessagePreview}) and the announcement variant
|
|
3123
|
+
* ({@link getLatestMessagePreviewText}), so the translation lookup and branching run once per call.
|
|
3124
|
+
*/
|
|
3125
|
+
var getLatestMessagePreviewParts = (channel, t, userLanguage = "en", latestMessageArg) => {
|
|
3126
|
+
const latestMessage = latestMessageArg ?? channel.state.latestMessages[channel.state.latestMessages.length - 1];
|
|
2947
3127
|
const previewTextToRender = getTranslatedMessageText({
|
|
2948
3128
|
language: userLanguage,
|
|
2949
3129
|
message: latestMessage
|
|
2950
3130
|
}) || latestMessage?.text;
|
|
2951
3131
|
const poll = latestMessage?.poll;
|
|
2952
|
-
if (!latestMessage) return
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
}
|
|
2958
|
-
|
|
3132
|
+
if (!latestMessage) return {
|
|
3133
|
+
isUserMessageText: false,
|
|
3134
|
+
kind: "empty",
|
|
3135
|
+
latestMessage,
|
|
3136
|
+
text: t("Nothing yet...")
|
|
3137
|
+
};
|
|
3138
|
+
if (isMessageDeleted(latestMessage)) return {
|
|
3139
|
+
isUserMessageText: false,
|
|
3140
|
+
kind: "deleted",
|
|
3141
|
+
latestMessage,
|
|
3142
|
+
text: t("Message deleted")
|
|
3143
|
+
};
|
|
3144
|
+
if (poll) if (!poll.vote_count) {
|
|
3145
|
+
const createdBy = poll.created_by?.id === channel.getClient().userID ? t("You") : poll.created_by?.name ?? t("Poll");
|
|
3146
|
+
return {
|
|
3147
|
+
isUserMessageText: false,
|
|
3148
|
+
kind: "poll",
|
|
3149
|
+
latestMessage,
|
|
3150
|
+
pollName: poll.name,
|
|
3151
|
+
text: t("📊 {{createdBy}} created: {{ pollName}}", {
|
|
3152
|
+
createdBy,
|
|
3153
|
+
pollName: poll.name
|
|
3154
|
+
})
|
|
3155
|
+
};
|
|
3156
|
+
} else {
|
|
2959
3157
|
const latestVote = getLatestPollVote(poll.latest_votes_by_option);
|
|
2960
3158
|
const option = latestVote && poll.options.find((opt) => opt.id === latestVote.option_id);
|
|
2961
|
-
if (option && latestVote) return
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
3159
|
+
if (option && latestVote) return {
|
|
3160
|
+
isUserMessageText: false,
|
|
3161
|
+
kind: "poll",
|
|
3162
|
+
latestMessage,
|
|
3163
|
+
pollName: poll.name,
|
|
3164
|
+
text: t("📊 {{votedBy}} voted: {{pollOptionText}}", {
|
|
3165
|
+
pollOptionText: option.text,
|
|
3166
|
+
votedBy: latestVote?.user?.id === channel.getClient().userID ? t("You") : latestVote.user?.name ?? t("Poll")
|
|
3167
|
+
})
|
|
3168
|
+
};
|
|
3169
|
+
}
|
|
3170
|
+
if (previewTextToRender) return {
|
|
3171
|
+
isUserMessageText: true,
|
|
3172
|
+
kind: "text",
|
|
3173
|
+
latestMessage,
|
|
3174
|
+
text: previewTextToRender
|
|
3175
|
+
};
|
|
3176
|
+
if (latestMessage.command) return {
|
|
3177
|
+
isUserMessageText: false,
|
|
3178
|
+
kind: "command",
|
|
3179
|
+
latestMessage,
|
|
3180
|
+
text: `/${latestMessage.command}`
|
|
3181
|
+
};
|
|
3182
|
+
if (latestMessage.attachments?.length) return {
|
|
3183
|
+
isUserMessageText: false,
|
|
3184
|
+
kind: "attachment",
|
|
3185
|
+
latestMessage,
|
|
3186
|
+
text: t("🏙 Attachment...")
|
|
3187
|
+
};
|
|
3188
|
+
if (latestMessage.shared_location) return {
|
|
3189
|
+
isUserMessageText: false,
|
|
3190
|
+
kind: "location",
|
|
3191
|
+
latestMessage,
|
|
3192
|
+
text: t("📍Shared location")
|
|
3193
|
+
};
|
|
3194
|
+
return {
|
|
3195
|
+
isUserMessageText: false,
|
|
3196
|
+
kind: "text",
|
|
3197
|
+
latestMessage,
|
|
3198
|
+
text: t("Empty message...")
|
|
3199
|
+
};
|
|
3200
|
+
};
|
|
3201
|
+
/**
|
|
3202
|
+
* Maps a known attachment `type` to a localized, human-readable word (e.g. "image" → "Image"). The
|
|
3203
|
+
* cases are literal `t('aria/…')` calls so `i18next-cli` extracts them. Unknown/custom types return
|
|
3204
|
+
* `undefined`, so the announcement falls back to a generic "Attachment".
|
|
3205
|
+
*/
|
|
3206
|
+
var getAttachmentTypeLabel = (type, t) => {
|
|
3207
|
+
switch (type) {
|
|
3208
|
+
case "audio": return t("aria/audio");
|
|
3209
|
+
case "file": return t("aria/file");
|
|
3210
|
+
case "giphy": return t("aria/GIF");
|
|
3211
|
+
case "image": return t("aria/image");
|
|
3212
|
+
case "video": return t("aria/video");
|
|
3213
|
+
case "voiceRecording": return t("aria/voice message");
|
|
3214
|
+
default: return;
|
|
2965
3215
|
}
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
3216
|
+
};
|
|
3217
|
+
/**
|
|
3218
|
+
* The text announced for the channel's latest message (for an accessible name / live region).
|
|
3219
|
+
* Non-text content gets a concise, screen-reader-friendly phrasing that may differ from the visible
|
|
3220
|
+
* preview: a poll announces its question, an attachment its type, a shared location and a deleted
|
|
3221
|
+
* message a plain phrase. User-message text is stripped of markdown so the words are read, not the
|
|
3222
|
+
* syntax (AI-generated text is returned verbatim, matching the display path).
|
|
3223
|
+
*/
|
|
3224
|
+
var getLatestMessagePreviewText = (channel, t, userLanguage = "en", isMessageAIGenerated, latestMessage) => {
|
|
3225
|
+
const { isUserMessageText, kind, latestMessage: resolvedLatestMessage, pollName, text } = getLatestMessagePreviewParts(channel, t, userLanguage, latestMessage);
|
|
3226
|
+
switch (kind) {
|
|
3227
|
+
case "poll": return t("aria/Poll: {{ pollName }}", { pollName: pollName ?? "" });
|
|
3228
|
+
case "attachment": {
|
|
3229
|
+
const realAttachments = resolvedLatestMessage?.attachments?.filter((attachment) => !attachment.og_scrape_url) ?? [];
|
|
3230
|
+
if (realAttachments.length > 1) return t("aria/Message with attachments");
|
|
3231
|
+
const typeLabel = getAttachmentTypeLabel(realAttachments[0]?.type, t);
|
|
3232
|
+
return typeLabel ? t("aria/Attachment {{ attachmentType }}", { attachmentType: typeLabel }) : t("aria/Attachment");
|
|
3233
|
+
}
|
|
3234
|
+
case "location": return t("aria/Shared location");
|
|
3235
|
+
case "empty": return t("aria/There are no messages in this chat.");
|
|
3236
|
+
case "text": return isUserMessageText && resolvedLatestMessage && !isMessageAIGenerated?.(resolvedLatestMessage) ? stripMarkdownToText(text) : text;
|
|
3237
|
+
default: return text;
|
|
3238
|
+
}
|
|
3239
|
+
};
|
|
3240
|
+
var getLatestMessagePreview = (channel, t, userLanguage = "en", isMessageAIGenerated, latestMessage) => {
|
|
3241
|
+
const { isUserMessageText, latestMessage: resolvedLatestMessage, text } = getLatestMessagePreviewParts(channel, t, userLanguage, latestMessage);
|
|
3242
|
+
return isUserMessageText && resolvedLatestMessage && !isMessageAIGenerated?.(resolvedLatestMessage) ? renderPreviewText(text) : text;
|
|
2971
3243
|
};
|
|
2972
3244
|
/**
|
|
2973
3245
|
* Channel display image: channel.data.image, or for DM (2 members) the other member's user.image.
|
|
@@ -3192,7 +3464,8 @@ var Notification = forwardRef(({ className, entryDirection, Icon = DefaultNotifi
|
|
|
3192
3464
|
};
|
|
3193
3465
|
const isPersistent = !notification.duration;
|
|
3194
3466
|
const severity = notification.severity;
|
|
3195
|
-
const
|
|
3467
|
+
const ariaLiveOverride = notification.metadata?.ariaLive;
|
|
3468
|
+
const livePriority = ariaLiveOverride === "assertive" || ariaLiveOverride === "polite" ? ariaLiveOverride : severity === "error" ? "assertive" : "polite";
|
|
3196
3469
|
return /* @__PURE__ */ jsxs("div", {
|
|
3197
3470
|
className: clsx("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),
|
|
3198
3471
|
"data-testid": "notification",
|
|
@@ -3611,6 +3884,6 @@ function useChannelHeaderOnlineStatus({ channel: channelOverride, watcherCount:
|
|
|
3611
3884
|
return `${t("{{ memberCount }} members", { memberCount })} · ${t("{{ watcherCount }} online", { watcherCount })}`;
|
|
3612
3885
|
}
|
|
3613
3886
|
//#endregion
|
|
3614
|
-
export {
|
|
3887
|
+
export { ContextMenu as $, Gallery as A, VisuallyHidden as At, formatTime as B, MessageContext as Bt, Checkbox as C, useStableCallback as Ct, SwitchFieldDescription as D, NotificationConfigurationProvider as Dt, SwitchField as E, useNotifications as Et, toGalleryItemDescriptors as F, useModalContext as Ft, MessageTimestamp as G, FILE_ICON_GRAPHIC_CLASSNAME as H, useMessageContext as Ht, useGalleryContext as I, MessageTranslationViewContext as It, imageToLink as J, Timestamp as K, toBaseImageDescriptors as L, MessageTranslationViewProvider as Lt, VideoThumbnail as M, useAriaLiveOutletContext as Mt, VideoPlayer as N, ModalContext as Nt, SwitchFieldLabel as O, useNotificationConfigurationContext as Ot, GalleryContext as P, ModalContextProvider as Pt, BaseContextMenuButton as Q, BaseImage as R, getTranslatedMessageText as Rt, TextInput as S, useAriaIdentifiers as St, Switch as T, LoadingIndicator as Tt, FILE_ICON_NO_LABEL_CLASSNAME as U, FileIcon as V, MessageProvider as Vt, DownloadButton as W, GlobalModal as X, htmlToTextPlugin as Y, Prompt as Z, getLatestMessagePreview as _, DialogAnchor as _t, pickNewest as a, ContextMenuRoot as at, ListItemLayout as b, Header as bt, useIsUserMuted as c, UserContextMenuButton as ct, useSelectedChannelState as d, getNextRovingFocusIndex as dt, ContextMenuBackButton as et, isDmChannel as f, GroupAvatar as ft, getGroupChannelDisplayInfo as g, Avatar as gt, getChannelDisplayImage as h, ErrorBadge as ht, createDefaultPickNext as i, ContextMenuHeader as it, GalleryUI as j, AriaLiveOutletContext as jt, SwitchFieldTitle as k, AriaLiveOutlet as kt, useIsChannelMuted as l, useContextMenuContext as lt, useChannelDisplayName as m, Badge as mt, useChannelHasMembersOnline as n, ContextMenuButton as nt, pickOldest as o, DEFAULT_CONTEXT_MENU_KEYBOARD_NAVIGATION_ITEM_SELECTOR as ot, useChannelPreviewInfo as p, ChannelAvatar as pt, plusPlusToEmphasis as q, NotificationList as r, ContextMenuContent as rt, Notification as s, EmojiContextMenuButton as st, useChannelHeaderOnlineStatus as t, ContextMenuBody as tt, useChannelMembershipState as u, createRovingFocusKeyDownHandler as ut, getLatestMessagePreviewText as v, useDialogAnchor as vt, Checkmark as w, FileSizeIndicator as wt, ListItemLayoutContent as x, Root as xt, renderPreviewText as y, Alert as yt, ImagePlaceholder as z, useMessageTranslationViewContext as zt };
|
|
3615
3888
|
|
|
3616
|
-
//# sourceMappingURL=useChannelHeaderOnlineStatus.
|
|
3889
|
+
//# sourceMappingURL=useChannelHeaderOnlineStatus.c86db868.mjs.map
|