@elliemae/ds-chat-container 3.80.0-next.4 → 3.80.0-next.41

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.
Files changed (52) hide show
  1. package/dist/cjs/DSChatContainerDefinitions.js +7 -1
  2. package/dist/cjs/DSChatContainerDefinitions.js.map +2 -2
  3. package/dist/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +134 -69
  4. package/dist/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js.map +2 -2
  5. package/dist/cjs/parts/chat-container-messages-list/styled.js +33 -35
  6. package/dist/cjs/parts/chat-container-messages-list/styled.js.map +2 -2
  7. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js +2 -5
  8. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js.map +2 -2
  9. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js +33 -20
  10. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js.map +2 -2
  11. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +38 -43
  12. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +2 -2
  13. package/dist/cjs/parts/chat-container-messages-list/useGlobalEventListener.js.map +1 -1
  14. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js +8 -15
  15. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js.map +2 -2
  16. package/dist/cjs/parts/chat-container-messages-list/useMessageFocusTracker.js +132 -0
  17. package/dist/cjs/parts/chat-container-messages-list/useMessageFocusTracker.js.map +7 -0
  18. package/dist/cjs/react-desc-prop-types.js +39 -23
  19. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  20. package/dist/cjs/typescript-testing/typescript-chat-container-valid.js +31 -0
  21. package/dist/cjs/typescript-testing/typescript-chat-container-valid.js.map +2 -2
  22. package/dist/esm/DSChatContainerDefinitions.js +7 -1
  23. package/dist/esm/DSChatContainerDefinitions.js.map +2 -2
  24. package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +135 -72
  25. package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js.map +2 -2
  26. package/dist/esm/parts/chat-container-messages-list/styled.js +33 -35
  27. package/dist/esm/parts/chat-container-messages-list/styled.js.map +2 -2
  28. package/dist/esm/parts/chat-container-messages-list/useActionRef.js +2 -5
  29. package/dist/esm/parts/chat-container-messages-list/useActionRef.js.map +2 -2
  30. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js +33 -20
  31. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js.map +2 -2
  32. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +39 -44
  33. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +2 -2
  34. package/dist/esm/parts/chat-container-messages-list/useGlobalEventListener.js.map +1 -1
  35. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js +8 -15
  36. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js.map +2 -2
  37. package/dist/esm/parts/chat-container-messages-list/useMessageFocusTracker.js +102 -0
  38. package/dist/esm/parts/chat-container-messages-list/useMessageFocusTracker.js.map +7 -0
  39. package/dist/esm/react-desc-prop-types.js +40 -24
  40. package/dist/esm/react-desc-prop-types.js.map +2 -2
  41. package/dist/esm/typescript-testing/typescript-chat-container-valid.js +31 -0
  42. package/dist/esm/typescript-testing/typescript-chat-container-valid.js.map +2 -2
  43. package/dist/types/DSChatContainerDefinitions.d.ts +8 -0
  44. package/dist/types/parts/chat-container-messages-list/styled.d.ts +18 -5
  45. package/dist/types/parts/chat-container-messages-list/useActionRef.d.ts +4 -6
  46. package/dist/types/parts/chat-container-messages-list/useChatContainerMessageList.d.ts +7 -3
  47. package/dist/types/parts/chat-container-messages-list/useFocusAndScrollHelpers.d.ts +9 -6
  48. package/dist/types/parts/chat-container-messages-list/useGlobalEventListener.d.ts +1 -1
  49. package/dist/types/parts/chat-container-messages-list/useKeyboard.d.ts +7 -3
  50. package/dist/types/parts/chat-container-messages-list/useMessageFocusTracker.d.ts +52 -0
  51. package/dist/types/react-desc-prop-types.d.ts +800 -789
  52. package/package.json +17 -17
@@ -30,11 +30,17 @@ var DSChatContainerDefinitions_exports = {};
30
30
  __export(DSChatContainerDefinitions_exports, {
31
31
  DSChatContainerComposerName: () => DSChatContainerComposerName,
32
32
  DSChatContainerMessagesList: () => DSChatContainerMessagesList,
33
- DSChatContainerName: () => DSChatContainerName
33
+ DSChatContainerName: () => DSChatContainerName,
34
+ DSChatContainerSlotName: () => DSChatContainerSlotName,
35
+ DSChatContainerSlots: () => DSChatContainerSlots
34
36
  });
35
37
  module.exports = __toCommonJS(DSChatContainerDefinitions_exports);
36
38
  var React = __toESM(require("react"));
37
39
  const DSChatContainerName = "DSChatcontainername";
38
40
  const DSChatContainerComposerName = "DSChatcontainercomposer";
39
41
  const DSChatContainerMessagesList = "DSChatcontainermessageslist";
42
+ const DSChatContainerSlotName = "DSChatcontainer";
43
+ const DSChatContainerSlots = {
44
+ MESSAGES_LIST_SCROLL_AREA: "messages-list-scroll-area"
45
+ };
40
46
  //# sourceMappingURL=DSChatContainerDefinitions.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/DSChatContainerDefinitions.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["export const DSChatContainerName = 'DSChatcontainername';\nexport const DSChatContainerComposerName = 'DSChatcontainercomposer';\nexport const DSChatContainerMessagesList = 'DSChatcontainermessageslist';\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAhB,MAAM,sBAAsB;AAC5B,MAAM,8BAA8B;AACpC,MAAM,8BAA8B;",
4
+ "sourcesContent": ["export const DSChatContainerName = 'DSChatcontainername';\nexport const DSChatContainerComposerName = 'DSChatcontainercomposer';\nexport const DSChatContainerMessagesList = 'DSChatcontainermessageslist';\n\n/**\n * Slot system: the main component and its parts share one slot owner name, each part with its own slot\n * names (the convention of the `ds-chat-container-compliance` change, which moves these into `src/constants/`).\n */\nexport const DSChatContainerSlotName = 'DSChatcontainer';\nexport const DSChatContainerSlots = {\n MESSAGES_LIST_SCROLL_AREA: 'messages-list-scroll-area',\n} as const;\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAhB,MAAM,sBAAsB;AAC5B,MAAM,8BAA8B;AACpC,MAAM,8BAA8B;AAMpC,MAAM,0BAA0B;AAChC,MAAM,uBAAuB;AAAA,EAClC,2BAA2B;AAC7B;",
6
6
  "names": []
7
7
  }
@@ -44,89 +44,154 @@ var import_styled = require("./styled.js");
44
44
  var import_react_desc_prop_types = require("../../react-desc-prop-types.js");
45
45
  var import_useGetNewMessages = require("./useGetNewMessages.js");
46
46
  var import_useChatContainerMessageList = require("./useChatContainerMessageList.js");
47
+ var import_useMessageFocusTracker = require("./useMessageFocusTracker.js");
47
48
  var import_ChatContainerDataTestids = require("../../ChatContainerDataTestids.js");
49
+ const ESTIMATED_MESSAGE_HEIGHT = 80;
50
+ const estimateSize = () => ESTIMATED_MESSAGE_HEIGHT;
51
+ const WRAPPER_LIST_PROPS = { role: "none" };
52
+ const ItemRenderer = ({ index, extraItemProps }) => {
53
+ const { messages, sendingMessages, sendingText, focusRequest, focusCallbacks } = extraItemProps ?? {};
54
+ const row = messages?.[index];
55
+ const isFocusTarget = Boolean(
56
+ row && focusRequest && (focusRequest.messageId === (0, import_useMessageFocusTracker.getMessageFocusId)(row, index) || focusRequest.messageId === (0, import_useMessageFocusTracker.getMessagePositionId)(index))
57
+ );
58
+ const requestId = isFocusTarget && focusRequest ? focusRequest.requestId : 0;
59
+ const preventScroll = isFocusTarget && focusRequest ? focusRequest.preventScroll : false;
60
+ const focusRef = import_react.default.useCallback(
61
+ (node) => {
62
+ if (!node || !isFocusTarget || !focusCallbacks) return;
63
+ const item = node.closest("[data-index]");
64
+ const takeFocus = focusCallbacks.mayTakeFocus(requestId, item);
65
+ if (!takeFocus) return;
66
+ item?.focus({ preventScroll: takeFocus === "restore" || preventScroll });
67
+ focusCallbacks.markFulfilled(requestId);
68
+ },
69
+ [isFocusTarget, requestId, preventScroll, focusCallbacks]
70
+ );
71
+ if (!row) return null;
72
+ const isSending = sendingMessages && sendingMessages.find((m) => m === row.dsId);
73
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_styled.StyledWrapperListItem, { type: row.type, innerRef: focusRef, children: [
74
+ row.type === import_ds_chat_bubble.BUBBLE_TYPES.SENDER || row.type === import_ds_chat_bubble.BUBBLE_TYPES.RECIPIENT ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_chat_bubble.ChatBubble, { ...row, helpMessage: isSending ? sendingText : row.helpMessage }) : null,
75
+ row.type === import_ds_chat_bubble.BUBBLE_TYPES.DELIMITER ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_chat_message_delimeter.MessageDelimiter, { ...row }) : null,
76
+ row.type === import_ds_chat_bubble.BUBBLE_TYPES.SYSTEM ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_chat_system_message.SystemMessage, { ...row }) : null
77
+ ] });
78
+ };
48
79
  const ChatContainerMessagesList = (props) => {
49
80
  const {
50
81
  propsWithDefault,
51
82
  globalAttributes,
52
- useVirtualHelpers,
83
+ fastListActionRef,
84
+ paddingStart,
85
+ paddingEnd,
53
86
  handleKey,
54
87
  handleListKey,
55
88
  loadMoreRef,
56
- virtualListRef
89
+ virtualListRef,
90
+ focusTracker
57
91
  } = (0, import_useChatContainerMessageList.useChatContainerMessageList)(props);
58
92
  const { sendingText, sendingMessages, messages, getMoreMessages, hasMoreItems, isLoading } = propsWithDefault;
59
- const { totalSize, virtualItems } = useVirtualHelpers;
60
93
  const newMessages = (0, import_useGetNewMessages.useGetNewMessages)(messages);
61
- const render = import_react.default.useMemo(
62
- () => virtualItems.map((virtualItem) => {
63
- const { index, measureRef, start } = virtualItem;
64
- const row = messages[index];
65
- const isSending = sendingMessages && sendingMessages.find((m) => m === row.dsId);
66
- const style = {
67
- position: "absolute",
68
- top: 0,
69
- left: 0,
70
- transform: `translateY(${start}px)`,
71
- width: "100%"
72
- };
73
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
74
- import_styled.ListItem,
75
- {
76
- "data-element": "chat-element-list-item",
77
- "data-index": index,
78
- style,
79
- innerRef: measureRef,
80
- tabIndex: -1,
81
- onKeyDown: handleKey,
82
- role: "listitem",
83
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_styled.StyledWrapperListItem, { type: row.type, children: [
84
- row.type === import_ds_chat_bubble.BUBBLE_TYPES.SENDER || row.type === import_ds_chat_bubble.BUBBLE_TYPES.RECIPIENT ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_chat_bubble.ChatBubble, { ...row, helpMessage: isSending ? sendingText : row.helpMessage }) : null,
85
- row.type === import_ds_chat_bubble.BUBBLE_TYPES.DELIMITER ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_chat_message_delimeter.MessageDelimiter, { ...row }) : null,
86
- row.type === import_ds_chat_bubble.BUBBLE_TYPES.SYSTEM ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_chat_system_message.SystemMessage, { ...row }) : null
87
- ] })
88
- },
89
- `ds-chat-bubble-${index}-${row.dsId}-${row.type}`
90
- );
91
- }),
92
- [virtualItems, messages, sendingMessages, handleKey, sendingText]
94
+ const getOwnerProps = import_react.default.useCallback(() => propsWithDefault, [propsWithDefault]);
95
+ const getId = import_react.default.useCallback(
96
+ (index) => `${index}-${messages[index].dsId}-${messages[index].type}`,
97
+ [messages]
98
+ );
99
+ const {
100
+ focusRequest,
101
+ mayTakeFocus,
102
+ markFulfilled,
103
+ trackFocusedMessage,
104
+ trackFocusResetter,
105
+ handleFocusOut,
106
+ listRootRef
107
+ } = focusTracker;
108
+ const focusCallbacks = import_react.default.useMemo(() => ({ mayTakeFocus, markFulfilled }), [mayTakeFocus, markFulfilled]);
109
+ const extraItemProps = import_react.default.useMemo(
110
+ () => ({ messages, sendingMessages, sendingText, focusRequest, focusCallbacks }),
111
+ [messages, sendingMessages, sendingText, focusRequest, focusCallbacks]
93
112
  );
94
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_styled.StyledWrapper, { ...globalAttributes, children: [
95
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
96
- import_styled.StyledChatContainerContentList,
113
+ const { onFocus: onFocusFromConsumer, onBlur: onBlurFromConsumer } = globalAttributes;
114
+ const handleFocusIn = import_react.default.useCallback(
115
+ (e) => {
116
+ const item = e.target.closest('[data-element="chat-element-list-item"]');
117
+ const index = item?.dataset.index;
118
+ const position = Number(index);
119
+ const row = index !== void 0 ? messages[position] : void 0;
120
+ if (row) trackFocusedMessage((0, import_useMessageFocusTracker.getMessageFocusId)(row, position));
121
+ else trackFocusResetter();
122
+ onFocusFromConsumer?.(e);
123
+ },
124
+ [messages, trackFocusedMessage, trackFocusResetter, onFocusFromConsumer]
125
+ );
126
+ const handleFocusOutWithConsumer = import_react.default.useCallback(
127
+ (e) => {
128
+ handleFocusOut(e);
129
+ onBlurFromConsumer?.(e);
130
+ },
131
+ [handleFocusOut, onBlurFromConsumer]
132
+ );
133
+ const itemProps = import_react.default.useMemo(
134
+ () => ({ "data-element": "chat-element-list-item", tabIndex: -1, onKeyDown: handleKey }),
135
+ [handleKey]
136
+ );
137
+ const extraContent = import_react.default.useMemo(
138
+ () => !isLoading && hasMoreItems ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.StyledLoadMoreContainer, { hasMoreItems, role: "listitem", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
139
+ import_ds_button_v2.DSButtonV2,
97
140
  {
98
- "data-testid": import_ChatContainerDataTestids.ChatContainerDataTestIds.THREAD_CONTAINER,
99
- tabIndex: 0,
100
- innerRef: virtualListRef,
101
- role: "list",
102
- onKeyDown: handleListKey,
103
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_styled.StyledChatContainerContentListScroll, { height: `${totalSize}px`, children: [
104
- !isLoading && hasMoreItems ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.StyledLoadMoreContainer, { hasMoreItems, role: "listitem", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
105
- import_ds_button_v2.DSButtonV2,
106
- {
107
- buttonType: "outline",
108
- onClick: getMoreMessages,
109
- "data-testid": import_ChatContainerDataTestids.ChatContainerDataTestIds.LOAD_MORE_BUTTON,
110
- innerRef: loadMoreRef,
111
- children: "Load More"
112
- }
113
- ) }) : null,
114
- render
115
- ] })
141
+ buttonType: "outline",
142
+ onClick: getMoreMessages,
143
+ "data-testid": import_ChatContainerDataTestids.ChatContainerDataTestIds.LOAD_MORE_BUTTON,
144
+ innerRef: loadMoreRef,
145
+ children: "Load More"
116
146
  }
117
- ),
118
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.StyledNewMessagesHiddenContainer, { "aria-live": "polite", "aria-hidden": "false", children: newMessages.map((newMessage) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
119
- newMessage.title,
120
- " ",
121
- newMessage.time,
122
- " ",
123
- newMessage.body,
124
- " ",
125
- newMessage.errorMessage,
126
- " ",
127
- newMessage.helpMessage
128
- ] }, newMessage.dsId)) })
129
- ] });
147
+ ) }) : null,
148
+ [isLoading, hasMoreItems, getMoreMessages, loadMoreRef]
149
+ );
150
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
151
+ import_styled.StyledWrapper,
152
+ {
153
+ ...globalAttributes,
154
+ innerRef: listRootRef,
155
+ onFocus: handleFocusIn,
156
+ onBlur: handleFocusOutWithConsumer,
157
+ children: [
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
159
+ import_styled.StyledFastList,
160
+ {
161
+ getOwnerProps,
162
+ "data-testid": import_ChatContainerDataTestids.ChatContainerDataTestIds.THREAD_CONTAINER,
163
+ role: "list",
164
+ tabIndex: 0,
165
+ onKeyDown: handleListKey,
166
+ innerRef: virtualListRef,
167
+ actionRef: fastListActionRef,
168
+ remountOnCountChange: false,
169
+ count: messages.length,
170
+ getId,
171
+ estimateSize,
172
+ paddingStart,
173
+ paddingEnd,
174
+ ItemRenderer,
175
+ extraItemProps,
176
+ extraContent,
177
+ dsFastlistWrapperList: WRAPPER_LIST_PROPS,
178
+ dsFastlistItem: itemProps
179
+ }
180
+ ),
181
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.StyledNewMessagesHiddenContainer, { "aria-live": "polite", "aria-hidden": "false", children: newMessages.map((newMessage) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
182
+ newMessage.title,
183
+ " ",
184
+ newMessage.time,
185
+ " ",
186
+ newMessage.body,
187
+ " ",
188
+ newMessage.errorMessage,
189
+ " ",
190
+ newMessage.helpMessage
191
+ ] }, newMessage.dsId)) })
192
+ ]
193
+ }
194
+ );
130
195
  };
131
196
  ChatContainerMessagesList.displayName = "ChatContainerMessagesList";
132
197
  const ChatContainerMessagesListWithSchema = (0, import_ds_props_helpers.describe)(ChatContainerMessagesList);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/chat-container-messages-list/ChatContainerMessagesList.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport type { CSSProperties, WeakValidationMap } from 'react';\nimport React from 'react';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { DSButtonV2, type DSButtonV2T } from '@elliemae/ds-button-v2';\nimport { ChatBubble, BUBBLE_TYPES } from '@elliemae/ds-chat-bubble';\nimport type { DSChatMessageDelimeterT } from '@elliemae/ds-chat-message-delimeter';\nimport { MessageDelimiter } from '@elliemae/ds-chat-message-delimeter';\nimport type { DSChatSystemMessageT } from '@elliemae/ds-chat-system-message';\nimport { SystemMessage } from '@elliemae/ds-chat-system-message';\nimport {\n StyledWrapperListItem,\n StyledChatContainerContentList,\n StyledChatContainerContentListScroll,\n StyledWrapper,\n StyledLoadMoreContainer,\n ListItem,\n StyledNewMessagesHiddenContainer,\n} from './styled.js';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\nimport { ChatContainerMessagesListPropTypes } from '../../react-desc-prop-types.js';\nimport { useGetNewMessages } from './useGetNewMessages.js';\nimport { useChatContainerMessageList } from './useChatContainerMessageList.js';\nimport { ChatContainerDataTestIds } from '../../ChatContainerDataTestids.js';\n\ntype ButtonV2InnerRefT = DSButtonV2T.Props['innerRef'];\n\nconst ChatContainerMessagesList: React.ComponentType<DSChatT.MessagesListProps> = (props) => {\n const {\n propsWithDefault,\n globalAttributes,\n useVirtualHelpers,\n handleKey,\n handleListKey,\n loadMoreRef,\n virtualListRef,\n } = useChatContainerMessageList(props);\n\n const { sendingText, sendingMessages, messages, getMoreMessages, hasMoreItems, isLoading } = propsWithDefault;\n const { totalSize, virtualItems } = useVirtualHelpers;\n\n const newMessages = useGetNewMessages(messages);\n\n const render = React.useMemo(\n () =>\n virtualItems.map((virtualItem) => {\n const { index, measureRef, start } = virtualItem;\n const row = messages[index];\n const isSending = sendingMessages && sendingMessages.find((m) => m === row.dsId);\n const style: CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n transform: `translateY(${start}px)`,\n width: '100%',\n };\n\n return (\n <ListItem\n data-element=\"chat-element-list-item\"\n data-index={index}\n key={`ds-chat-bubble-${index}-${row.dsId}-${row.type}`}\n style={style}\n innerRef={measureRef}\n tabIndex={-1}\n onKeyDown={handleKey}\n role=\"listitem\"\n >\n <StyledWrapperListItem type={row.type}>\n {row.type === BUBBLE_TYPES.SENDER || row.type === BUBBLE_TYPES.RECIPIENT ? (\n <ChatBubble {...row} helpMessage={isSending ? sendingText : row.helpMessage} />\n ) : null}\n {row.type === BUBBLE_TYPES.DELIMITER ? (\n <MessageDelimiter {...(row as unknown as DSChatMessageDelimeterT.Props)} />\n ) : null}\n {row.type === BUBBLE_TYPES.SYSTEM ? <SystemMessage {...(row as DSChatSystemMessageT.Props)} /> : null}\n </StyledWrapperListItem>\n </ListItem>\n );\n }),\n [virtualItems, messages, sendingMessages, handleKey, sendingText],\n );\n\n return (\n <StyledWrapper {...globalAttributes}>\n <StyledChatContainerContentList\n data-testid={ChatContainerDataTestIds.THREAD_CONTAINER}\n tabIndex={0}\n innerRef={virtualListRef as React.RefObject<HTMLDivElement>}\n role=\"list\"\n onKeyDown={handleListKey}\n >\n <StyledChatContainerContentListScroll height={`${totalSize}px`}>\n {!isLoading && hasMoreItems ? (\n <StyledLoadMoreContainer hasMoreItems={hasMoreItems} role=\"listitem\">\n <DSButtonV2\n buttonType=\"outline\"\n onClick={getMoreMessages}\n data-testid={ChatContainerDataTestIds.LOAD_MORE_BUTTON}\n innerRef={loadMoreRef as ButtonV2InnerRefT}\n >\n Load More\n </DSButtonV2>\n </StyledLoadMoreContainer>\n ) : null}\n {render}\n </StyledChatContainerContentListScroll>\n </StyledChatContainerContentList>\n {/* We repeat the render with the new available messages */}\n <StyledNewMessagesHiddenContainer aria-live=\"polite\" aria-hidden=\"false\">\n {newMessages.map((newMessage) => (\n <p key={newMessage.dsId}>\n {newMessage.title} {newMessage.time} {newMessage.body} {newMessage.errorMessage} {newMessage.helpMessage}\n </p>\n ))}\n </StyledNewMessagesHiddenContainer>\n </StyledWrapper>\n );\n};\n\nChatContainerMessagesList.displayName = 'ChatContainerMessagesList';\nconst ChatContainerMessagesListWithSchema = describe(ChatContainerMessagesList);\nChatContainerMessagesListWithSchema.propTypes = ChatContainerMessagesListPropTypes as WeakValidationMap<unknown>;\n\nexport { ChatContainerMessagesList, ChatContainerMessagesListWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADsEX;AAlEZ,mBAAkB;AAClB,8BAAyB;AACzB,0BAA6C;AAC7C,4BAAyC;AAEzC,uCAAiC;AAEjC,oCAA8B;AAC9B,oBAQO;AAEP,mCAAmD;AACnD,+BAAkC;AAClC,yCAA4C;AAC5C,sCAAyC;AAIzC,MAAM,4BAA4E,CAAC,UAAU;AAC3F,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,gEAA4B,KAAK;AAErC,QAAM,EAAE,aAAa,iBAAiB,UAAU,iBAAiB,cAAc,UAAU,IAAI;AAC7F,QAAM,EAAE,WAAW,aAAa,IAAI;AAEpC,QAAM,kBAAc,4CAAkB,QAAQ;AAE9C,QAAM,SAAS,aAAAA,QAAM;AAAA,IACnB,MACE,aAAa,IAAI,CAAC,gBAAgB;AAChC,YAAM,EAAE,OAAO,YAAY,MAAM,IAAI;AACrC,YAAM,MAAM,SAAS,KAAK;AAC1B,YAAM,YAAY,mBAAmB,gBAAgB,KAAK,CAAC,MAAM,MAAM,IAAI,IAAI;AAC/E,YAAM,QAAuB;AAAA,QAC3B,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,QACN,WAAW,cAAc,KAAK;AAAA,QAC9B,OAAO;AAAA,MACT;AAEA,aACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAa;AAAA,UACb,cAAY;AAAA,UAEZ;AAAA,UACA,UAAU;AAAA,UACV,UAAU;AAAA,UACV,WAAW;AAAA,UACX,MAAK;AAAA,UAEL,uDAAC,uCAAsB,MAAM,IAAI,MAC9B;AAAA,gBAAI,SAAS,mCAAa,UAAU,IAAI,SAAS,mCAAa,YAC7D,4CAAC,oCAAY,GAAG,KAAK,aAAa,YAAY,cAAc,IAAI,aAAa,IAC3E;AAAA,YACH,IAAI,SAAS,mCAAa,YACzB,4CAAC,qDAAkB,GAAI,KAAkD,IACvE;AAAA,YACH,IAAI,SAAS,mCAAa,SAAS,4CAAC,+CAAe,GAAI,KAAoC,IAAK;AAAA,aACnG;AAAA;AAAA,QAfK,kBAAkB,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAAA,MAgBtD;AAAA,IAEJ,CAAC;AAAA,IACH,CAAC,cAAc,UAAU,iBAAiB,WAAW,WAAW;AAAA,EAClE;AAEA,SACE,6CAAC,+BAAe,GAAG,kBACjB;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,eAAa,yDAAyB;AAAA,QACtC,UAAU;AAAA,QACV,UAAU;AAAA,QACV,MAAK;AAAA,QACL,WAAW;AAAA,QAEX,uDAAC,sDAAqC,QAAQ,GAAG,SAAS,MACvD;AAAA,WAAC,aAAa,eACb,4CAAC,yCAAwB,cAA4B,MAAK,YACxD;AAAA,YAAC;AAAA;AAAA,cACC,YAAW;AAAA,cACX,SAAS;AAAA,cACT,eAAa,yDAAyB;AAAA,cACtC,UAAU;AAAA,cACX;AAAA;AAAA,UAED,GACF,IACE;AAAA,UACH;AAAA,WACH;AAAA;AAAA,IACF;AAAA,IAEA,4CAAC,kDAAiC,aAAU,UAAS,eAAY,SAC9D,sBAAY,IAAI,CAAC,eAChB,6CAAC,OACE;AAAA,iBAAW;AAAA,MAAM;AAAA,MAAE,WAAW;AAAA,MAAK;AAAA,MAAE,WAAW;AAAA,MAAK;AAAA,MAAE,WAAW;AAAA,MAAa;AAAA,MAAE,WAAW;AAAA,SADvF,WAAW,IAEnB,CACD,GACH;AAAA,KACF;AAEJ;AAEA,0BAA0B,cAAc;AACxC,MAAM,0CAAsC,kCAAS,yBAAyB;AAC9E,oCAAoC,YAAY;",
4
+ "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport type { WeakValidationMap } from 'react';\nimport React from 'react';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { DSButtonV2, type DSButtonV2T } from '@elliemae/ds-button-v2';\nimport { ChatBubble, BUBBLE_TYPES } from '@elliemae/ds-chat-bubble';\nimport type { DSChatMessageDelimeterT } from '@elliemae/ds-chat-message-delimeter';\nimport { MessageDelimiter } from '@elliemae/ds-chat-message-delimeter';\nimport type { DSChatSystemMessageT } from '@elliemae/ds-chat-system-message';\nimport { SystemMessage } from '@elliemae/ds-chat-system-message';\nimport {\n StyledWrapperListItem,\n StyledFastList,\n StyledWrapper,\n StyledLoadMoreContainer,\n StyledNewMessagesHiddenContainer,\n} from './styled.js';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\nimport { ChatContainerMessagesListPropTypes } from '../../react-desc-prop-types.js';\nimport { useGetNewMessages } from './useGetNewMessages.js';\nimport { useChatContainerMessageList } from './useChatContainerMessageList.js';\nimport { getMessageFocusId, getMessagePositionId } from './useMessageFocusTracker.js';\nimport type { MessageFocusRequest, useMessageFocusTracker } from './useMessageFocusTracker.js';\nimport { ChatContainerDataTestIds } from '../../ChatContainerDataTestids.js';\n\ntype ButtonV2InnerRefT = DSButtonV2T.Props['innerRef'];\n\ntype FocusTracker = ReturnType<typeof useMessageFocusTracker>;\ntype ItemFocusCallbacks = Pick<FocusTracker, 'mayTakeFocus' | 'markFulfilled'>;\n\ntype ItemExtraProps = {\n messages: DSChatT.MessagesListProps['messages'];\n sendingMessages: DSChatT.MessagesListProps['sendingMessages'];\n sendingText: DSChatT.MessagesListProps['sendingText'];\n focusRequest: MessageFocusRequest | null;\n focusCallbacks: ItemFocusCallbacks;\n};\n\nconst ESTIMATED_MESSAGE_HEIGHT = 80;\nconst estimateSize = () => ESTIMATED_MESSAGE_HEIGHT;\n// the wrapper `ds-fast-list` renders is neutral: the scroll container owns the `list` role\nconst WRAPPER_LIST_PROPS = { role: 'none' };\n\n/**\n * Module-level on purpose: `DSFastList` renders it as a component, so its identity must be stable or\n * every item would remount on each render of the list.\n */\nconst ItemRenderer: React.ComponentType<{ index: number; extraItemProps?: object }> = ({ index, extraItemProps }) => {\n // `styled(DSFastList)` drops DSFastList's generic, so `extraItemProps` arrives typed as `object`\n const { messages, sendingMessages, sendingText, focusRequest, focusCallbacks } = (extraItemProps ??\n {}) as Partial<ItemExtraProps>;\n const row = messages?.[index];\n const isFocusTarget = Boolean(\n row &&\n focusRequest &&\n (focusRequest.messageId === getMessageFocusId(row, index) ||\n focusRequest.messageId === getMessagePositionId(index)),\n );\n const requestId = isFocusTarget && focusRequest ? focusRequest.requestId : 0;\n const preventScroll = isFocusTarget && focusRequest ? focusRequest.preventScroll : false;\n /**\n * The only place a message is focused. It runs once React has committed the message, so a target that is\n * not mounted yet (far away, or remounted after older messages were loaded) is focused when it mounts. The\n * focusable element is the item wrapper `ds-fast-list` renders around this component, the one carrying\n * `data-index` and QA's `data-element`, so it is reached with `closest` from this message's own node.\n */\n const focusRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n if (!node || !isFocusTarget || !focusCallbacks) return;\n const item = node.closest<HTMLElement>('[data-index]');\n const takeFocus = focusCallbacks.mayTakeFocus(requestId, item);\n if (!takeFocus) return;\n item?.focus({ preventScroll: takeFocus === 'restore' || preventScroll });\n focusCallbacks.markFulfilled(requestId);\n },\n [isFocusTarget, requestId, preventScroll, focusCallbacks],\n );\n if (!row) return null;\n const isSending = sendingMessages && sendingMessages.find((m) => m === row.dsId);\n return (\n <StyledWrapperListItem type={row.type} innerRef={focusRef}>\n {row.type === BUBBLE_TYPES.SENDER || row.type === BUBBLE_TYPES.RECIPIENT ? (\n <ChatBubble {...row} helpMessage={isSending ? sendingText : row.helpMessage} />\n ) : null}\n {row.type === BUBBLE_TYPES.DELIMITER ? (\n <MessageDelimiter {...(row as unknown as DSChatMessageDelimeterT.Props)} />\n ) : null}\n {row.type === BUBBLE_TYPES.SYSTEM ? <SystemMessage {...(row as DSChatSystemMessageT.Props)} /> : null}\n </StyledWrapperListItem>\n );\n};\n\nconst ChatContainerMessagesList: React.ComponentType<DSChatT.MessagesListProps> = (props) => {\n const {\n propsWithDefault,\n globalAttributes,\n fastListActionRef,\n paddingStart,\n paddingEnd,\n handleKey,\n handleListKey,\n loadMoreRef,\n virtualListRef,\n focusTracker,\n } = useChatContainerMessageList(props);\n\n const { sendingText, sendingMessages, messages, getMoreMessages, hasMoreItems, isLoading } = propsWithDefault;\n\n const newMessages = useGetNewMessages(messages);\n\n const getOwnerProps = React.useCallback(() => propsWithDefault, [propsWithDefault]);\n /**\n * The key must carry the index. `ds-fast-list` reuses an item's DOM node for as long as its key is the same,\n * but the virtualizer measures each node by its `data-index` and does not measure a node again when only its\n * index changes. With a key made only of `dsId`, loading older messages (which shifts every index) keeps the\n * nodes and leaves their measurements pointing at another position: items overlap or leave gaps, and the list\n * flickers while scrolling. An index-bearing key recreates the shifted items so they are measured at their\n * new index, as the list did before it was moved onto `ds-fast-list`.\n */\n const getId = React.useCallback(\n (index: number) => `${index}-${messages[index].dsId}-${messages[index].type}`,\n [messages],\n );\n const {\n focusRequest,\n mayTakeFocus,\n markFulfilled,\n trackFocusedMessage,\n trackFocusResetter,\n handleFocusOut,\n listRootRef,\n } = focusTracker;\n const focusCallbacks = React.useMemo(() => ({ mayTakeFocus, markFulfilled }), [mayTakeFocus, markFulfilled]);\n const extraItemProps = React.useMemo(\n () => ({ messages, sendingMessages, sendingText, focusRequest, focusCallbacks }),\n [messages, sendingMessages, sendingText, focusRequest, focusCallbacks],\n );\n const { onFocus: onFocusFromConsumer, onBlur: onBlurFromConsumer } = globalAttributes as {\n onFocus?: React.FocusEventHandler<HTMLElement>;\n onBlur?: React.FocusEventHandler<HTMLElement>;\n };\n /**\n * Keeps the focus intent equal to the message that actually got the focus (keyboard, mouse or API), also when\n * the focus is on a descendant of the message, and clears it when the focus moves to anything else in the list.\n */\n const handleFocusIn = React.useCallback(\n (e: React.FocusEvent<HTMLElement>) => {\n const item = (e.target as HTMLElement).closest<HTMLElement>('[data-element=\"chat-element-list-item\"]');\n const index = item?.dataset.index;\n const position = Number(index);\n const row = index !== undefined ? messages[position] : undefined;\n if (row) trackFocusedMessage(getMessageFocusId(row, position));\n else trackFocusResetter();\n onFocusFromConsumer?.(e);\n },\n [messages, trackFocusedMessage, trackFocusResetter, onFocusFromConsumer],\n );\n const handleFocusOutWithConsumer = React.useCallback(\n (e: React.FocusEvent<HTMLElement>) => {\n handleFocusOut(e);\n onBlurFromConsumer?.(e);\n },\n [handleFocusOut, onBlurFromConsumer],\n );\n const itemProps = React.useMemo(\n () => ({ 'data-element': 'chat-element-list-item', tabIndex: -1, onKeyDown: handleKey }),\n [handleKey],\n );\n const extraContent = React.useMemo(\n () =>\n !isLoading && hasMoreItems ? (\n <StyledLoadMoreContainer hasMoreItems={hasMoreItems} role=\"listitem\">\n <DSButtonV2\n buttonType=\"outline\"\n onClick={getMoreMessages}\n data-testid={ChatContainerDataTestIds.LOAD_MORE_BUTTON}\n innerRef={loadMoreRef as ButtonV2InnerRefT}\n >\n Load More\n </DSButtonV2>\n </StyledLoadMoreContainer>\n ) : null,\n [isLoading, hasMoreItems, getMoreMessages, loadMoreRef],\n );\n\n return (\n <StyledWrapper\n {...globalAttributes}\n innerRef={listRootRef}\n onFocus={handleFocusIn}\n onBlur={handleFocusOutWithConsumer}\n >\n <StyledFastList\n getOwnerProps={getOwnerProps}\n data-testid={ChatContainerDataTestIds.THREAD_CONTAINER}\n role=\"list\"\n tabIndex={0}\n onKeyDown={handleListKey}\n innerRef={virtualListRef}\n actionRef={fastListActionRef}\n remountOnCountChange={false}\n count={messages.length}\n getId={getId}\n estimateSize={estimateSize}\n paddingStart={paddingStart}\n paddingEnd={paddingEnd}\n ItemRenderer={ItemRenderer}\n extraItemProps={extraItemProps}\n extraContent={extraContent}\n dsFastlistWrapperList={WRAPPER_LIST_PROPS}\n dsFastlistItem={itemProps}\n />\n {/* We repeat the render with the new available messages */}\n <StyledNewMessagesHiddenContainer aria-live=\"polite\" aria-hidden=\"false\">\n {newMessages.map((newMessage) => (\n <p key={newMessage.dsId}>\n {newMessage.title} {newMessage.time} {newMessage.body} {newMessage.errorMessage} {newMessage.helpMessage}\n </p>\n ))}\n </StyledNewMessagesHiddenContainer>\n </StyledWrapper>\n );\n};\n\nChatContainerMessagesList.displayName = 'ChatContainerMessagesList';\nconst ChatContainerMessagesListWithSchema = describe(ChatContainerMessagesList);\nChatContainerMessagesListWithSchema.propTypes = ChatContainerMessagesListPropTypes as WeakValidationMap<unknown>;\n\nexport { ChatContainerMessagesList, ChatContainerMessagesListWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": "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",
6
6
  "names": ["React"]
7
7
  }
@@ -28,9 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var styled_exports = {};
30
30
  __export(styled_exports, {
31
- ListItem: () => ListItem,
32
- StyledChatContainerContentList: () => StyledChatContainerContentList,
33
- StyledChatContainerContentListScroll: () => StyledChatContainerContentListScroll,
31
+ StyledFastList: () => StyledFastList,
34
32
  StyledLoadMoreContainer: () => StyledLoadMoreContainer,
35
33
  StyledNewMessagesHiddenContainer: () => StyledNewMessagesHiddenContainer,
36
34
  StyledWrapper: () => StyledWrapper,
@@ -39,7 +37,9 @@ __export(styled_exports, {
39
37
  module.exports = __toCommonJS(styled_exports);
40
38
  var React = __toESM(require("react"));
41
39
  var import_ds_system = require("@elliemae/ds-system");
40
+ var import_ds_fast_list = require("@elliemae/ds-fast-list");
42
41
  var import_ds_chat_bubble = require("@elliemae/ds-chat-bubble");
42
+ var import_DSChatContainerDefinitions = require("../../DSChatContainerDefinitions.js");
43
43
  const StyledWrapper = import_ds_system.styled.div`
44
44
  width: 100%;
45
45
  height: 100%;
@@ -54,13 +54,36 @@ const StyledWrapperListItem = import_ds_system.styled.div`
54
54
  ${(props) => props.type === import_ds_chat_bubble.BUBBLE_TYPES.SYSTEM && `padding: ${props.theme.space.xxs} 0px
55
55
  `};
56
56
  `;
57
- const StyledChatContainerContentList = import_ds_system.styled.div`
58
- width: 100%;
59
- height: 100%;
60
- padding: ${(props) => props.theme.space.xs};
61
- padding-bottom: 0;
62
- overflow-y: auto;
63
- overflow-x: hidden;
57
+ const StyledFastList = (0, import_ds_system.styled)(import_ds_fast_list.DSFastList, {
58
+ name: import_DSChatContainerDefinitions.DSChatContainerSlotName,
59
+ slot: import_DSChatContainerDefinitions.DSChatContainerSlots.MESSAGES_LIST_SCROLL_AREA
60
+ })`
61
+ && {
62
+ padding: 0 ${(props) => props.theme.space.xs} 0 ${(props) => props.theme.space.xs};
63
+ overflow-y: auto;
64
+ overflow-x: hidden;
65
+ }
66
+
67
+ [data-element='chat-element-list-item'] {
68
+ &:focus,
69
+ &:focus-visible {
70
+ outline: none;
71
+ &:after {
72
+ content: '';
73
+ display: block;
74
+ position: absolute;
75
+ top: 0;
76
+ left: -${(props) => props.theme.space.xxs};
77
+ pointer-events: none;
78
+ border-radius: 2px;
79
+ background-color: #ebedf0;
80
+ width: calc(100% + 24px);
81
+ border: 2px solid #1e79c2;
82
+ height: 100%;
83
+ z-index: -1;
84
+ }
85
+ }
86
+ }
64
87
  `;
65
88
  const StyledNewMessagesHiddenContainer = import_ds_system.styled.div`
66
89
  position: absolute;
@@ -74,11 +97,6 @@ const StyledNewMessagesHiddenContainer = import_ds_system.styled.div`
74
97
  clip-path: inset(100%);
75
98
  white-space: nowrap;
76
99
  `;
77
- const StyledChatContainerContentListScroll = import_ds_system.styled.div`
78
- width: 100%;
79
- height: ${(props) => props.height};
80
- position: relative;
81
- `;
82
100
  const StyledLoadMoreContainer = import_ds_system.styled.div`
83
101
  position: absolute;
84
102
  width: calc(100% + ${(props) => props.theme.space.xxs});
@@ -91,24 +109,4 @@ const StyledLoadMoreContainer = import_ds_system.styled.div`
91
109
  ${(props) => props.hasMoreItems === "top" ? "top: 0;" : ""}
92
110
  ${(props) => props.hasMoreItems === "bottom" ? "bottom: 0;" : ""}
93
111
  `;
94
- const ListItem = import_ds_system.styled.div`
95
- &:focus,
96
- &:focus-visible {
97
- outline: none;
98
- &:after {
99
- content: '';
100
- display: block;
101
- position: absolute;
102
- top: 0;
103
- left: -${(props) => props.theme.space.xxs};
104
- pointer-events: none;
105
- border-radius: 2px;
106
- background-color: #ebedf0;
107
- width: calc(100% + 24px);
108
- border: 2px solid #1e79c2;
109
- height: 100%;
110
- z-index: -1;
111
- }
112
- }
113
- `;
114
112
  //# sourceMappingURL=styled.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/chat-container-messages-list/styled.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import { styled } from '@elliemae/ds-system';\nimport type { DSChatBubbleT } from '@elliemae/ds-chat-bubble';\nimport { BUBBLE_TYPES } from '@elliemae/ds-chat-bubble';\n\nexport const StyledWrapper = styled.div`\n width: 100%;\n height: 100%;\n`;\n\n// list\nexport const StyledWrapperListItem = styled.div<Partial<DSChatBubbleT.Props>>`\n min-width: 100%;\n ${(props) =>\n props.type === BUBBLE_TYPES.SENDER &&\n `padding: ${props.theme.space.xxs} ${props.theme.space.xxs} ${props.theme.space.xxs} 13%\n `};\n ${(props) =>\n props.type === BUBBLE_TYPES.RECIPIENT &&\n `padding: ${props.theme.space.xxs} 13% ${props.theme.space.xxs}\n ${props.theme.space.xxs}\n `};\n ${(props) =>\n props.type === BUBBLE_TYPES.SYSTEM &&\n `padding: ${props.theme.space.xxs} 0px\n `};\n`;\n\nexport const StyledChatContainerContentList = styled.div`\n width: 100%;\n height: 100%;\n padding: ${(props) => props.theme.space.xs};\n padding-bottom: 0;\n overflow-y: auto;\n overflow-x: hidden;\n`;\n\nexport const StyledNewMessagesHiddenContainer = styled.div`\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n border: 0;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n clip-path: inset(100%);\n white-space: nowrap;\n`;\n\nexport const StyledChatContainerContentListScroll = styled.div<{ height: string }>`\n width: 100%;\n height: ${(props) => props.height};\n position: relative;\n`;\n\nexport const StyledLoadMoreContainer = styled.div<{ hasMoreItems?: 'top' | 'bottom' }>`\n position: absolute;\n width: calc(100% + ${(props) => props.theme.space.xxs});\n padding: ${(props) => props.theme.space.xxs};\n left: -${(props) => props.theme.space.xxs};\n right: -${(props) => props.theme.space.xxs};\n display: grid;\n justify-content: center;\n align-items: center;\n ${(props) => (props.hasMoreItems === 'top' ? 'top: 0;' : '')}\n ${(props) => (props.hasMoreItems === 'bottom' ? 'bottom: 0;' : '')}\n`;\nexport const ListItem = styled.div`\n &:focus,\n &:focus-visible {\n outline: none;\n &:after {\n content: '';\n display: block;\n position: absolute;\n top: 0;\n left: -${(props) => props.theme.space.xxs};\n pointer-events: none;\n border-radius: 2px;\n background-color: #ebedf0;\n width: calc(100% + 24px);\n border: 2px solid #1e79c2;\n height: 100%;\n z-index: -1;\n }\n }\n`;\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAAuB;AAEvB,4BAA6B;AAEtB,MAAM,gBAAgB,wBAAO;AAAA;AAAA;AAAA;AAM7B,MAAM,wBAAwB,wBAAO;AAAA;AAAA,IAExC,CAAC,UACD,MAAM,SAAS,mCAAa,UAC5B,YAAY,MAAM,MAAM,MAAM,GAAG,IAAI,MAAM,MAAM,MAAM,GAAG,IAAI,MAAM,MAAM,MAAM,GAAG;AAAA,GACpF;AAAA,IACC,CAAC,UACD,MAAM,SAAS,mCAAa,aAC5B,YAAY,MAAM,MAAM,MAAM,GAAG,QAAQ,MAAM,MAAM,MAAM,GAAG;AAAA,MAC5D,MAAM,MAAM,MAAM,GAAG;AAAA,GACxB;AAAA,IACC,CAAC,UACD,MAAM,SAAS,mCAAa,UAC5B,YAAY,MAAM,MAAM,MAAM,GAAG;AAAA,GAClC;AAAA;AAGI,MAAM,iCAAiC,wBAAO;AAAA;AAAA;AAAA,aAGxC,CAAC,UAAU,MAAM,MAAM,MAAM,EAAE;AAAA;AAAA;AAAA;AAAA;AAMrC,MAAM,mCAAmC,wBAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAahD,MAAM,uCAAuC,wBAAO;AAAA;AAAA,YAE/C,CAAC,UAAU,MAAM,MAAM;AAAA;AAAA;AAI5B,MAAM,0BAA0B,wBAAO;AAAA;AAAA,uBAEvB,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA,aAC1C,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA,WAClC,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA,YAC/B,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA;AAAA;AAAA;AAAA,IAIxC,CAAC,UAAW,MAAM,iBAAiB,QAAQ,YAAY,EAAG;AAAA,IAC1D,CAAC,UAAW,MAAM,iBAAiB,WAAW,eAAe,EAAG;AAAA;AAE7D,MAAM,WAAW,wBAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAShB,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
4
+ "sourcesContent": ["import { styled } from '@elliemae/ds-system';\nimport { DSFastList } from '@elliemae/ds-fast-list';\nimport type { DSChatBubbleT } from '@elliemae/ds-chat-bubble';\nimport { BUBBLE_TYPES } from '@elliemae/ds-chat-bubble';\nimport { DSChatContainerSlotName, DSChatContainerSlots } from '../../DSChatContainerDefinitions.js';\n\nexport const StyledWrapper = styled.div`\n width: 100%;\n height: 100%;\n`;\n\n// list\nexport const StyledWrapperListItem = styled.div<Partial<DSChatBubbleT.Props>>`\n min-width: 100%;\n ${(props) =>\n props.type === BUBBLE_TYPES.SENDER &&\n `padding: ${props.theme.space.xxs} ${props.theme.space.xxs} ${props.theme.space.xxs} 13%\n `};\n ${(props) =>\n props.type === BUBBLE_TYPES.RECIPIENT &&\n `padding: ${props.theme.space.xxs} 13% ${props.theme.space.xxs}\n ${props.theme.space.xxs}\n `};\n ${(props) =>\n props.type === BUBBLE_TYPES.SYSTEM &&\n `padding: ${props.theme.space.xxs} 0px\n `};\n`;\n\n/**\n * The scroll container is DSFastList's own container, so its horizontal padding and overflow rules are\n * applied through the class that `styled(DSFastList)` forwards to it. `&&` doubles the class so these\n * rules win over the container's own `overflow: auto` regardless of style injection order.\n *\n * No padding-top here on purpose: the scroll container is also the virtualizer's scroll element, and\n * the virtualizer compares the raw `scrollTop` with its own content-relative item positions with no\n * awareness of CSS padding, so a CSS top-padding would desync `getVisibleItems()` near the top boundary\n * by roughly the padding's own size. The equivalent top space is passed as the virtualizer's\n * `paddingStart` instead (see useChatContainerMessageList.ts).\n */\nexport const StyledFastList = styled(DSFastList, {\n name: DSChatContainerSlotName,\n slot: DSChatContainerSlots.MESSAGES_LIST_SCROLL_AREA,\n})`\n && {\n padding: 0 ${(props) => props.theme.space.xs} 0 ${(props) => props.theme.space.xs};\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n [data-element='chat-element-list-item'] {\n &:focus,\n &:focus-visible {\n outline: none;\n &:after {\n content: '';\n display: block;\n position: absolute;\n top: 0;\n left: -${(props) => props.theme.space.xxs};\n pointer-events: none;\n border-radius: 2px;\n background-color: #ebedf0;\n width: calc(100% + 24px);\n border: 2px solid #1e79c2;\n height: 100%;\n z-index: -1;\n }\n }\n }\n`;\n\nexport const StyledNewMessagesHiddenContainer = styled.div`\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n border: 0;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n clip-path: inset(100%);\n white-space: nowrap;\n`;\n\nexport const StyledLoadMoreContainer = styled.div<{ hasMoreItems?: 'top' | 'bottom' }>`\n position: absolute;\n width: calc(100% + ${(props) => props.theme.space.xxs});\n padding: ${(props) => props.theme.space.xxs};\n left: -${(props) => props.theme.space.xxs};\n right: -${(props) => props.theme.space.xxs};\n display: grid;\n justify-content: center;\n align-items: center;\n ${(props) => (props.hasMoreItems === 'top' ? 'top: 0;' : '')}\n ${(props) => (props.hasMoreItems === 'bottom' ? 'bottom: 0;' : '')}\n`;\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAAuB;AACvB,0BAA2B;AAE3B,4BAA6B;AAC7B,wCAA8D;AAEvD,MAAM,gBAAgB,wBAAO;AAAA;AAAA;AAAA;AAM7B,MAAM,wBAAwB,wBAAO;AAAA;AAAA,IAExC,CAAC,UACD,MAAM,SAAS,mCAAa,UAC5B,YAAY,MAAM,MAAM,MAAM,GAAG,IAAI,MAAM,MAAM,MAAM,GAAG,IAAI,MAAM,MAAM,MAAM,GAAG;AAAA,GACpF;AAAA,IACC,CAAC,UACD,MAAM,SAAS,mCAAa,aAC5B,YAAY,MAAM,MAAM,MAAM,GAAG,QAAQ,MAAM,MAAM,MAAM,GAAG;AAAA,MAC5D,MAAM,MAAM,MAAM,GAAG;AAAA,GACxB;AAAA,IACC,CAAC,UACD,MAAM,SAAS,mCAAa,UAC5B,YAAY,MAAM,MAAM,MAAM,GAAG;AAAA,GAClC;AAAA;AAcI,MAAM,qBAAiB,yBAAO,gCAAY;AAAA,EAC/C,MAAM;AAAA,EACN,MAAM,uDAAqB;AAC7B,CAAC;AAAA;AAAA,iBAEgB,CAAC,UAAU,MAAM,MAAM,MAAM,EAAE,MAAM,CAAC,UAAU,MAAM,MAAM,MAAM,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAcpE,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAa1C,MAAM,mCAAmC,wBAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAahD,MAAM,0BAA0B,wBAAO;AAAA;AAAA,uBAEvB,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA,aAC1C,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA,WAClC,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA,YAC/B,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG;AAAA;AAAA;AAAA;AAAA,IAIxC,CAAC,UAAW,MAAM,iBAAiB,QAAQ,YAAY,EAAG;AAAA,IAC1D,CAAC,UAAW,MAAM,iBAAiB,WAAW,eAAe,EAAG;AAAA;",
6
6
  "names": []
7
7
  }
@@ -35,9 +35,8 @@ var React = __toESM(require("react"));
35
35
  var import_react = __toESM(require("react"));
36
36
  const useActionRef = ({
37
37
  actionRef,
38
- useVirtualHelpers: { scrollToIndex: vScroll },
38
+ vScroll,
39
39
  virtualListRef,
40
- updateCache,
41
40
  getMessagesInView,
42
41
  onlyFocus,
43
42
  scrollAndFocus
@@ -49,7 +48,6 @@ const useActionRef = ({
49
48
  vScroll(index, opts);
50
49
  requestAnimationFrame(() => {
51
50
  vScroll(index, opts);
52
- updateCache();
53
51
  });
54
52
  }, 0);
55
53
  };
@@ -61,11 +59,10 @@ const useActionRef = ({
61
59
  };
62
60
  actionRef.current.scrollToIndex = scrollToIndex;
63
61
  actionRef.current.getMessagesInView = getMessagesInView;
64
- updateCache();
65
62
  actionRef.current.focusToIndex = focusToIndex;
66
63
  actionRef.current.focusToIndexWithoutScroll = onlyFocus;
67
64
  actionRef.current.focusToList = focusToList;
68
65
  }
69
- }, [actionRef, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);
66
+ }, [actionRef, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);
70
67
  };
71
68
  //# sourceMappingURL=useActionRef.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/chat-container-messages-list/useActionRef.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseActionRefArgs = {\n actionRef: DSChatT.ActionRef;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n updateCache: () => void;\n getMessagesInView: () => string[];\n onlyFocus: (index: string) => void;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n};\n\nexport const useActionRef = ({\n actionRef,\n useVirtualHelpers: { scrollToIndex: vScroll },\n virtualListRef,\n updateCache,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n}: UseActionRefArgs) => {\n React.useEffect(() => {\n if (actionRef && actionRef.current) {\n const scrollToIndex: DSChatT.ActionRef['current']['scrollToIndex'] = (index, opts = { align: 'center' }) => {\n setTimeout(() => {\n vScroll(index, opts);\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, opts);\n updateCache();\n });\n }, 0);\n };\n const focusToIndex: DSChatT.ActionRef['current']['focusToIndex'] = (index, opts = { align: 'center' }) => {\n scrollAndFocus(index, opts);\n };\n const focusToList = () => {\n virtualListRef.current?.focus();\n };\n\n actionRef.current.scrollToIndex = scrollToIndex;\n actionRef.current.getMessagesInView = getMessagesInView;\n updateCache(); // populate cache immediately on mount \u2014 leading throttle fires synchronously\n actionRef.current.focusToIndex = focusToIndex;\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = focusToList;\n }\n }, [actionRef, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAcX,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAwB;AACtB,eAAAA,QAAM,UAAU,MAAM;AACpB,QAAI,aAAa,UAAU,SAAS;AAClC,YAAM,gBAA+D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AAC1G,mBAAW,MAAM;AACf,kBAAQ,OAAO,IAAI;AAYnB,gCAAsB,MAAM;AAC1B,oBAAQ,OAAO,IAAI;AACnB,wBAAY;AAAA,UACd,CAAC;AAAA,QACH,GAAG,CAAC;AAAA,MACN;AACA,YAAM,eAA6D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AACxG,uBAAe,OAAO,IAAI;AAAA,MAC5B;AACA,YAAM,cAAc,MAAM;AACxB,uBAAe,SAAS,MAAM;AAAA,MAChC;AAEA,gBAAU,QAAQ,gBAAgB;AAClC,gBAAU,QAAQ,oBAAoB;AACtC,kBAAY;AACZ,gBAAU,QAAQ,eAAe;AACjC,gBAAU,QAAQ,4BAA4B;AAC9C,gBAAU,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,WAAW,aAAa,mBAAmB,WAAW,gBAAgB,SAAS,cAAc,CAAC;AACpG;",
4
+ "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseActionRefArgs = {\n actionRef: DSChatT.ActionRef;\n vScroll: (index: number, opts?: DSChatT.ScrollActionOptions) => void;\n virtualListRef: React.MutableRefObject<HTMLDivElement | null>;\n getMessagesInView: () => string[];\n onlyFocus: (index: string) => void;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollActionOptions) => void;\n};\n\nexport const useActionRef = ({\n actionRef,\n vScroll,\n virtualListRef,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n}: UseActionRefArgs) => {\n React.useEffect(() => {\n if (actionRef && actionRef.current) {\n const scrollToIndex: DSChatT.ActionRef['current']['scrollToIndex'] = (index, opts = { align: 'center' }) => {\n setTimeout(() => {\n vScroll(index, opts);\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can align the element with correct measurements\n */\n requestAnimationFrame(() => {\n vScroll(index, opts);\n });\n }, 0);\n };\n const focusToIndex: DSChatT.ActionRef['current']['focusToIndex'] = (index, opts = { align: 'center' }) => {\n scrollAndFocus(index, opts);\n };\n const focusToList = () => {\n virtualListRef.current?.focus();\n };\n\n actionRef.current.scrollToIndex = scrollToIndex;\n actionRef.current.getMessagesInView = getMessagesInView;\n actionRef.current.focusToIndex = focusToIndex;\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = focusToList;\n }\n }, [actionRef, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAYX,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAwB;AACtB,eAAAA,QAAM,UAAU,MAAM;AACpB,QAAI,aAAa,UAAU,SAAS;AAClC,YAAM,gBAA+D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AAC1G,mBAAW,MAAM;AACf,kBAAQ,OAAO,IAAI;AASnB,gCAAsB,MAAM;AAC1B,oBAAQ,OAAO,IAAI;AAAA,UACrB,CAAC;AAAA,QACH,GAAG,CAAC;AAAA,MACN;AACA,YAAM,eAA6D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AACxG,uBAAe,OAAO,IAAI;AAAA,MAC5B;AACA,YAAM,cAAc,MAAM;AACxB,uBAAe,SAAS,MAAM;AAAA,MAChC;AAEA,gBAAU,QAAQ,gBAAgB;AAClC,gBAAU,QAAQ,oBAAoB;AACtC,gBAAU,QAAQ,eAAe;AACjC,gBAAU,QAAQ,4BAA4B;AAC9C,gBAAU,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,WAAW,mBAAmB,WAAW,gBAAgB,SAAS,cAAc,CAAC;AACvF;",
6
6
  "names": ["React"]
7
7
  }
@@ -33,12 +33,13 @@ __export(useChatContainerMessageList_exports, {
33
33
  module.exports = __toCommonJS(useChatContainerMessageList_exports);
34
34
  var React = __toESM(require("react"));
35
35
  var import_react = __toESM(require("react"));
36
+ var import_styled_components = require("styled-components");
36
37
  var import_ds_props_helpers = require("@elliemae/ds-props-helpers");
37
- var import_react_virtual = require("react-virtual");
38
38
  var import_useActionRef = require("./useActionRef.js");
39
39
  var import_useGlobalEventListener = require("./useGlobalEventListener.js");
40
40
  var import_useKeyboard = require("./useKeyboard.js");
41
41
  var import_useFocusAndScrollHelpers = require("./useFocusAndScrollHelpers.js");
42
+ var import_useMessageFocusTracker = require("./useMessageFocusTracker.js");
42
43
  var import_react_desc_prop_types = require("../../react-desc-prop-types.js");
43
44
  var import_DSChatContainerDefinitions = require("../../DSChatContainerDefinitions.js");
44
45
  const getPadding = ({ hasMoreItems, bannerPosition, isLoading }) => {
@@ -59,29 +60,27 @@ const useChatContainerMessageList = (props) => {
59
60
  );
60
61
  const globalAttributes = (0, import_ds_props_helpers.useGetGlobalAttributes)(propsWithDefault);
61
62
  const loadMoreRef = import_react.default.useRef();
62
- const virtualListRef = import_react.default.useRef();
63
+ const virtualListRef = import_react.default.useRef(null);
64
+ const fastListActionRef = import_react.default.useRef({});
63
65
  const pendingOnScroll = import_react.default.useRef(false);
64
- const { bannerPosition, messages, actionRef, hasMoreItems, isLoading } = propsWithDefault;
65
- const useVirtualHelpers = (0, import_react_virtual.useVirtual)({
66
- size: messages?.length,
67
- parentRef: virtualListRef,
68
- overscan: 15,
69
- ...getPadding({ hasMoreItems, bannerPosition, isLoading }),
70
- // estimateSize should not be really required given what was stated on
71
- // https://github.com/tannerlinsley/react-virtual/issues/23
72
- estimateSize: import_react.default.useCallback(() => 80, [])
73
- });
74
- const { onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll } = (0, import_useFocusAndScrollHelpers.useFocusAndScrollHelpers)({
66
+ const { bannerPosition, actionRef, hasMoreItems, isLoading } = propsWithDefault;
67
+ const theme = (0, import_styled_components.useTheme)();
68
+ const containerPaddingStart = parseInt(theme.space.xs, 10);
69
+ const padding = getPadding({ hasMoreItems, bannerPosition, isLoading });
70
+ const paddingStart = padding.paddingStart + containerPaddingStart;
71
+ const { paddingEnd } = padding;
72
+ const focusTracker = (0, import_useMessageFocusTracker.useMessageFocusTracker)(virtualListRef);
73
+ const { trackFocusMessage } = focusTracker;
74
+ const { vScroll, onScrollStop, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll } = (0, import_useFocusAndScrollHelpers.useFocusAndScrollHelpers)({
75
75
  propsWithDefault,
76
- useVirtualHelpers,
76
+ fastListActionRef,
77
77
  pendingOnScroll,
78
- virtualListRef
78
+ trackFocusMessage
79
79
  });
80
80
  (0, import_useActionRef.useActionRef)({
81
81
  actionRef,
82
- useVirtualHelpers,
82
+ vScroll,
83
83
  virtualListRef,
84
- updateCache,
85
84
  getMessagesInView,
86
85
  onlyFocus,
87
86
  scrollAndFocus
@@ -99,18 +98,32 @@ const useChatContainerMessageList = (props) => {
99
98
  loadMoreRef,
100
99
  scrollAndFocus,
101
100
  onlyFocus,
102
- getMessagesInView
101
+ getMessagesInView,
102
+ trackFocusMessage
103
103
  });
104
104
  return import_react.default.useMemo(
105
105
  () => ({
106
106
  propsWithDefault,
107
107
  globalAttributes,
108
- useVirtualHelpers,
108
+ fastListActionRef,
109
+ paddingStart,
110
+ paddingEnd,
109
111
  loadMoreRef,
110
112
  virtualListRef,
113
+ focusTracker,
111
114
  ...keyboardMethods
112
115
  }),
113
- [globalAttributes, keyboardMethods, propsWithDefault, useVirtualHelpers, loadMoreRef, virtualListRef]
116
+ [
117
+ globalAttributes,
118
+ keyboardMethods,
119
+ propsWithDefault,
120
+ fastListActionRef,
121
+ paddingStart,
122
+ paddingEnd,
123
+ loadMoreRef,
124
+ virtualListRef,
125
+ focusTracker
126
+ ]
114
127
  );
115
128
  };
116
129
  //# sourceMappingURL=useChatContainerMessageList.js.map