@elliemae/ds-chat 3.3.0-next.8 → 3.3.0-next.9

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 (37) hide show
  1. package/dist/cjs/Code-review - 20 june 2022.md +119 -0
  2. package/dist/cjs/exported-related/bubble/props.js.map +1 -1
  3. package/dist/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +11 -208
  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.map +1 -1
  6. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js +58 -0
  7. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js.map +7 -0
  8. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js +100 -0
  9. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js.map +7 -0
  10. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +78 -0
  11. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +7 -0
  12. package/dist/cjs/parts/chat-container-messages-list/useGetNewMessages.js.map +2 -2
  13. package/dist/cjs/parts/chat-container-messages-list/useGlobalEventListener.js +56 -0
  14. package/dist/cjs/parts/chat-container-messages-list/useGlobalEventListener.js.map +7 -0
  15. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js +136 -0
  16. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js.map +7 -0
  17. package/dist/cjs/react-desc-prop-types.js +20 -20
  18. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  19. package/dist/esm/Code-review - 20 june 2022.md +119 -0
  20. package/dist/esm/exported-related/bubble/props.js.map +1 -1
  21. package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +13 -215
  22. package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js.map +2 -2
  23. package/dist/esm/parts/chat-container-messages-list/styled.js.map +1 -1
  24. package/dist/esm/parts/chat-container-messages-list/useActionRef.js +36 -0
  25. package/dist/esm/parts/chat-container-messages-list/useActionRef.js.map +7 -0
  26. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js +82 -0
  27. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js.map +7 -0
  28. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +56 -0
  29. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +7 -0
  30. package/dist/esm/parts/chat-container-messages-list/useGetNewMessages.js.map +2 -2
  31. package/dist/esm/parts/chat-container-messages-list/useGlobalEventListener.js +34 -0
  32. package/dist/esm/parts/chat-container-messages-list/useGlobalEventListener.js.map +7 -0
  33. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js +114 -0
  34. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js.map +7 -0
  35. package/dist/esm/react-desc-prop-types.js +10 -10
  36. package/dist/esm/react-desc-prop-types.js.map +2 -2
  37. package/package.json +10 -10
@@ -0,0 +1,119 @@
1
+ # Personal preferences/opinions:
2
+
3
+ ## `packages/ds-chat/src/ChatDataTestids.tsx`
4
+
5
+ maybe this could have been a better way to handle the test-id hierarchy?
6
+ I personally prefeer this way, but it's just personal preference
7
+
8
+ ```js
9
+ export const ChatDataTestIds = {
10
+ COMPOSER: {
11
+ TEXTAREA: 'chat-composer-textarea',
12
+ SEND_BUTTON: 'chat-composer-send-button',
13
+ },
14
+ CARD: {
15
+ TITLE: 'chat-card-title',
16
+ WRAPPER: 'chat-card-wrapper',
17
+ TIME: 'chat-card-time',
18
+ RIGHT_ADDON: 'chat-right-addon',
19
+ CONTENT: 'chat-card-content',
20
+ },
21
+ LOADING_INDICATOR: 'ds-chat-loading-indicator',
22
+ HEADER: {
23
+ TITLE: 'chat-header-title',
24
+ CHILDREN: 'chat-header-children',
25
+ },
26
+ THREAD_CONTAINER: 'chat-thread-container',
27
+ LOAD_MORE_BUTTON: 'ds-chat-load-more-btn',
28
+ FLOATING_BUTTON: 'chat-floating-button',
29
+ SYSTEM_MSG: {
30
+ TITLE: 'chat-system-message-title',
31
+ BODY: 'chat-system-message-body',
32
+ TIME: 'chat-system-message-time',
33
+ },
34
+ BUBBLE: {
35
+ ROOT: 'ds-chat-bubble',
36
+ TITLE: 'chat-bubble-title',
37
+ BODY: 'chat-bubble-body',
38
+ },
39
+ BANNER: 'ds-banner-container',
40
+ };
41
+ ```
42
+
43
+ # Scaffolding and Semantinc naming
44
+
45
+ ## Generic
46
+
47
+ the way this component it's structured we don't have a clear "top-to-down" flow, it's hard to even identify the "entry point"
48
+
49
+ this is due to the fact that this was created with extreme composition in mind, but if we need to follow extreme composition
50
+
51
+ we should create different packages with each part having it's own "clear top-to-down flow and entry point" instread of squeezing everything here
52
+
53
+ we could re-arrange this `@elliemea/ds-chat` to become an "aggregator" package, re-exporting the differente pieces as per `@elliemae/ds-controlled-form`
54
+
55
+ and we could create separate atomic `@elliemae/ds-chat-${composer/container/bubble/card/sidebar...}` packages...
56
+
57
+ ## `packages/ds-chat/src/styled.tsx`
58
+
59
+ this file contains only constants,
60
+ it doesn't even import styled-components...
61
+ we should move the content under `packages/ds-chat/src/config/style-constants.tsx` in my opinion
62
+
63
+ # Typescript related
64
+
65
+ ## `packages/ds-chat/src/react-desc-prop-types.tsx`
66
+
67
+ the `DSChatT` namespace is exposing both composer props and container props,
68
+
69
+ this is unexpected we should instead have two different namespaces,
70
+
71
+ - `DSChatComposerT`
72
+ - `DSChatContainerT`
73
+
74
+ since they are pretty much different components
75
+
76
+ ## `packages/ds-chat/src/exported-related/bubble/props.ts`
77
+
78
+ must be reviewed, optional props and required options are not clearly defined, if they variate based on the "Type" we should create expected props per type and define props as
79
+
80
+ ```typescript
81
+ export type BubblePropsT = SenderBubblePropsT | RecipientBubblePropsT | DelimiterBubblePropsT | SystemBubblePropsT;
82
+ ```
83
+
84
+ an example of how to handle polymorphism in typescript can be found at `packages/ds-form-date-time-picker/src/propTypes.tsx` line 50 ~ 137
85
+
86
+ # Features and dimsum standards
87
+
88
+ ## `packages/ds-chat/src/**/*/styled.tsx`
89
+
90
+ Theme `slot` feature is not yet implemented
91
+
92
+ ## `packages/ds-chat/src/parts/chat-container-messages-list/ChatContainerMessagesList.tsx`
93
+
94
+ **339 line** in one file is overdoing it, we should use the `useChatContainerMessageList` custom hook configuring the logic to make the component easier to mantain
95
+
96
+ I re-factored the code but we need testing that this didn't break anything before releasing it
97
+
98
+ # Eslint
99
+
100
+ basically every single file has some sort of eslint error, most of the errors comes from typescript typings.
101
+
102
+ we need to re-define typings correctly AND document them properly in storybook, right now storybook props are not in sync, some props are missing, some other parts are lying (documentation says receive an array of numbers, we send an array of strings and such...)
103
+
104
+ I will not list all of these errors because they are present basically everywhere and the fix should be kind of "global" too, as in, fixing typescript typing
105
+
106
+ I think it's a good idea to fix this Eslint errors only after splitting the chat exported-related into their own packages
107
+
108
+ # Conclusions
109
+
110
+ We need to overhaul the code...
111
+
112
+ The next steps in my opinion are:
113
+
114
+ - Divide this into sub-packages `@elliemae/ds-chat-${composer/container/bubble/card/sidebar...}`
115
+ - Make sure every single sub-packages comply with the "clear top-to-down flow and entry point" good practice + typescript namespace + proper Storybook Schema definitions
116
+ - Make every single sub-package eslint-error free
117
+ - deploy sub-packages with "typesafe:true" in their package.json configurations
118
+
119
+ After above steps are taken care of we could fine-detail check the code again
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/exported-related/bubble/props.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import { PropTypes } from '@elliemae/ds-utilities';\nimport React from 'react';\n\n// eslint-disable-next-line no-unused-vars\nfunction noop<T extends unknown[]>(..._args: T): void {}\nexport const BUBBLE_TYPES = {\n SENDER: 'SENDER',\n RECIPIENT: 'RECIPIENT',\n DELIMITER: 'DELIMITER',\n SYSTEM: 'SYSTEM',\n};\n\nexport type BubbleTypesKeys = keyof typeof BUBBLE_TYPES;\nexport type BubbleTypesValues = typeof BUBBLE_TYPES[BubbleTypesKeys];\n\nexport interface BubblePropsT {\n dsId: string | number;\n type: BubbleTypesValues;\n title?: string;\n body: string;\n time: string;\n errorMessage: string | React.ReactChild;\n helpMessage: string | React.ReactChild;\n onClick: (id: string | number) => void;\n}\n\nexport const defaultBubbleProps: BubblePropsT = {\n dsId: '',\n type: BUBBLE_TYPES.SENDER,\n time: '',\n body: '',\n onClick: noop,\n errorMessage: '',\n helpMessage: '',\n};\n\nexport const BubblesPropTypes = {\n dsId: PropTypes.oneOfType([PropTypes.string, PropTypes.number])\n .description('Unique id for bubble')\n .defaultValue(defaultBubbleProps.dsId),\n type: PropTypes.oneOf([BUBBLE_TYPES.RECIPIENT, BUBBLE_TYPES.SENDER])\n .isRequired.description('Define bubble type ')\n .defaultValue(defaultBubbleProps.type),\n title: PropTypes.string.description('Title of the bubble').defaultValue(defaultBubbleProps.title),\n time: PropTypes.string.isRequired.description('Time of the bubble').defaultValue(defaultBubbleProps.title),\n body: PropTypes.oneOfType([PropTypes.string, PropTypes.element])\n .isRequired.description('Bubble content')\n .defaultValue(defaultBubbleProps.body),\n onClick: PropTypes.func.description('Callback when the bubble is tapped').defaultValue(defaultBubbleProps.onClick),\n errorMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element])\n .description('Error message to display at bottom of the bubble')\n .defaultValue(defaultBubbleProps.onClick),\n helpMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element])\n .description('Help message to display at bottom of the bubble')\n .defaultValue(defaultBubbleProps.onClick),\n};\n\nexport const propsArrowBubble = {\n type: PropTypes.oneOf([BUBBLE_TYPES.RECIPIENT, BUBBLE_TYPES.SENDER]).isRequired.defaultValue(defaultBubbleProps.type),\n};\n", "import * as React from 'react';\nexport { React };\n"],
4
+ "sourcesContent": ["import { PropTypes } from '@elliemae/ds-utilities';\nimport React from 'react';\n\n// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars\nfunction noop<T extends unknown[]>(..._args: T): void {}\nexport const BUBBLE_TYPES = {\n SENDER: 'SENDER',\n RECIPIENT: 'RECIPIENT',\n DELIMITER: 'DELIMITER',\n SYSTEM: 'SYSTEM',\n};\n\nexport type BubbleTypesKeys = keyof typeof BUBBLE_TYPES;\nexport type BubbleTypesValues = typeof BUBBLE_TYPES[BubbleTypesKeys];\n\nexport interface BubblePropsT {\n dsId: string | number;\n type: BubbleTypesValues;\n title?: string;\n body: string;\n time: string;\n errorMessage: string | React.ReactChild;\n helpMessage: string | React.ReactChild;\n onClick: (id: string | number) => void;\n}\n\nexport const defaultBubbleProps: BubblePropsT = {\n dsId: '',\n type: BUBBLE_TYPES.SENDER,\n time: '',\n body: '',\n onClick: noop,\n errorMessage: '',\n helpMessage: '',\n};\n\nexport const BubblesPropTypes = {\n dsId: PropTypes.oneOfType([PropTypes.string, PropTypes.number])\n .description('Unique id for bubble')\n .defaultValue(defaultBubbleProps.dsId),\n type: PropTypes.oneOf([BUBBLE_TYPES.RECIPIENT, BUBBLE_TYPES.SENDER])\n .isRequired.description('Define bubble type ')\n .defaultValue(defaultBubbleProps.type),\n title: PropTypes.string.description('Title of the bubble').defaultValue(defaultBubbleProps.title),\n time: PropTypes.string.isRequired.description('Time of the bubble').defaultValue(defaultBubbleProps.title),\n body: PropTypes.oneOfType([PropTypes.string, PropTypes.element])\n .isRequired.description('Bubble content')\n .defaultValue(defaultBubbleProps.body),\n onClick: PropTypes.func.description('Callback when the bubble is tapped').defaultValue(defaultBubbleProps.onClick),\n errorMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element])\n .description('Error message to display at bottom of the bubble')\n .defaultValue(defaultBubbleProps.onClick),\n helpMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element])\n .description('Help message to display at bottom of the bubble')\n .defaultValue(defaultBubbleProps.onClick),\n};\n\nexport const propsArrowBubble = {\n type: PropTypes.oneOf([BUBBLE_TYPES.RECIPIENT, BUBBLE_TYPES.SENDER]).isRequired.defaultValue(defaultBubbleProps.type),\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,0BAA0B;AAI1B,iBAAsC,OAAgB;AAAC;AAChD,MAAM,eAAe;AAAA,EAC1B,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,WAAW;AAAA,EACX,QAAQ;AACV;AAgBO,MAAM,qBAAmC;AAAA,EAC9C,MAAM;AAAA,EACN,MAAM,aAAa;AAAA,EACnB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,cAAc;AAAA,EACd,aAAa;AACf;AAEO,MAAM,mBAAmB;AAAA,EAC9B,MAAM,8BAAU,UAAU,CAAC,8BAAU,QAAQ,8BAAU,MAAM,CAAC,EAC3D,YAAY,sBAAsB,EAClC,aAAa,mBAAmB,IAAI;AAAA,EACvC,MAAM,8BAAU,MAAM,CAAC,aAAa,WAAW,aAAa,MAAM,CAAC,EAChE,WAAW,YAAY,qBAAqB,EAC5C,aAAa,mBAAmB,IAAI;AAAA,EACvC,OAAO,8BAAU,OAAO,YAAY,qBAAqB,EAAE,aAAa,mBAAmB,KAAK;AAAA,EAChG,MAAM,8BAAU,OAAO,WAAW,YAAY,oBAAoB,EAAE,aAAa,mBAAmB,KAAK;AAAA,EACzG,MAAM,8BAAU,UAAU,CAAC,8BAAU,QAAQ,8BAAU,OAAO,CAAC,EAC5D,WAAW,YAAY,gBAAgB,EACvC,aAAa,mBAAmB,IAAI;AAAA,EACvC,SAAS,8BAAU,KAAK,YAAY,oCAAoC,EAAE,aAAa,mBAAmB,OAAO;AAAA,EACjH,cAAc,8BAAU,UAAU,CAAC,8BAAU,QAAQ,8BAAU,OAAO,CAAC,EACpE,YAAY,kDAAkD,EAC9D,aAAa,mBAAmB,OAAO;AAAA,EAC1C,aAAa,8BAAU,UAAU,CAAC,8BAAU,QAAQ,8BAAU,OAAO,CAAC,EACnE,YAAY,iDAAiD,EAC7D,aAAa,mBAAmB,OAAO;AAC5C;AAEO,MAAM,mBAAmB;AAAA,EAC9B,MAAM,8BAAU,MAAM,CAAC,aAAa,WAAW,aAAa,MAAM,CAAC,EAAE,WAAW,aAAa,mBAAmB,IAAI;AACtH;",
6
6
  "names": []
7
7
  }
@@ -28,224 +28,27 @@ module.exports = __toCommonJS(ChatContainerMessagesList_exports);
28
28
  var React = __toESM(require("react"));
29
29
  var import_react = __toESM(require("react"));
30
30
  var import_ds_utilities = require("@elliemae/ds-utilities");
31
- var import_react_virtual = require("react-virtual");
32
31
  var import_ds_button = __toESM(require("@elliemae/ds-button"));
33
- var import_lodash = require("lodash");
34
32
  var import_bubble = require("../../exported-related/bubble");
35
33
  var import_message_delimiter = require("../../exported-related/message-delimiter");
36
34
  var import_system_message = require("../../exported-related/system-message");
37
35
  var import_styled = require("./styled");
38
36
  var import_react_desc_prop_types = require("../../react-desc-prop-types");
39
37
  var import_useGetNewMessages = require("./useGetNewMessages");
40
- const getPadding = ({ hasMoreItems, bannerPosition, isLoading }) => {
41
- const padding = {
42
- paddingStart: 0,
43
- paddingEnd: -5
44
- };
45
- if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === "top"))
46
- padding.paddingStart = 42;
47
- else if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === "bottom"))
48
- padding.paddingEnd = 42;
49
- return padding;
50
- };
38
+ var import_useChatContainerMessageList = require("./useChatContainerMessageList");
51
39
  const ChatContainerMessagesList = (props) => {
52
- const propsWithDefault = (0, import_ds_utilities.useMemoMergePropsWithDefault)(props, import_react_desc_prop_types.defaultPropsMessagesList);
53
- (0, import_ds_utilities.useValidateTypescriptPropTypes)(propsWithDefault, import_react_desc_prop_types.ChatContainerMessagesListPropTypes);
54
- const globalAttributes = (0, import_ds_utilities.useGetGlobalAttributes)(propsWithDefault);
55
- const {
56
- sendingText,
57
- bannerPosition,
58
- sendingMessages,
59
- messages,
60
- actionRef,
61
- onScrollEnds,
62
- getMoreMessages,
63
- hasMoreItems,
64
- isLoading,
65
- bannerRef
66
- } = propsWithDefault;
67
- const pendingOnScroll = import_react.default.useRef(false);
68
- const loadMoreRef = import_react.default.useRef(null);
69
- const virtualListRef = import_react.default.useRef();
70
40
  const {
71
- scrollToIndex: vScroll,
72
- totalSize,
73
- virtualItems
74
- } = (0, import_react_virtual.useVirtual)({
75
- size: messages?.length,
76
- parentRef: virtualListRef,
77
- overscan: 15,
78
- ...getPadding({ hasMoreItems, bannerPosition, isLoading }),
79
- estimateSize: import_react.default.useCallback(() => 80, [])
80
- });
41
+ propsWithDefault,
42
+ globalAttributes,
43
+ useVirtualHelpers,
44
+ handleKey,
45
+ handleListKey,
46
+ loadMoreRef,
47
+ virtualListRef
48
+ } = (0, import_useChatContainerMessageList.useChatContainerMessageList)(props);
49
+ const { sendingText, sendingMessages, messages, getMoreMessages, hasMoreItems, isLoading } = propsWithDefault;
50
+ const { totalSize, virtualItems } = useVirtualHelpers;
81
51
  const newMessages = (0, import_useGetNewMessages.useGetNewMessages)(messages);
82
- const debouncedScroll = import_react.default.useMemo(() => (0, import_lodash.debounce)(() => {
83
- if (document.visibilityState === "hidden") {
84
- pendingOnScroll.current = true;
85
- return [];
86
- }
87
- if (!virtualListRef.current)
88
- return [];
89
- pendingOnScroll.current = false;
90
- const { bottom, top } = virtualListRef.current?.getBoundingClientRect();
91
- const list = virtualListRef.current.querySelectorAll('[data-element="chat-element-list-item"]');
92
- const indexList = [];
93
- list.forEach((item) => {
94
- const { top: itemTop } = item.getBoundingClientRect();
95
- const itemPadding = 10;
96
- if (itemTop + itemPadding < bottom && itemTop + itemPadding > top)
97
- indexList.push(item.dataset.index);
98
- });
99
- if (onScrollEnds)
100
- onScrollEnds(indexList);
101
- return indexList;
102
- }, 500), [onScrollEnds]);
103
- const onScrollStop = import_react.default.useCallback(debouncedScroll, [debouncedScroll]);
104
- const onlyFocus = import_react.default.useCallback((index) => {
105
- virtualListRef.current.querySelector(`[data-index="${index}"]`).focus();
106
- }, []);
107
- const scrollAndFocus = import_react.default.useCallback((index, b = { align: "center" }) => {
108
- vScroll(index, b);
109
- setTimeout(() => {
110
- onlyFocus(index);
111
- }, 300);
112
- onScrollStop();
113
- }, [onScrollStop, onlyFocus, vScroll]);
114
- const checkPendingOnScroll = import_react.default.useCallback(() => {
115
- if (pendingOnScroll.current === true)
116
- onScrollStop();
117
- }, [onScrollStop]);
118
- import_react.default.useEffect(() => {
119
- if (actionRef && actionRef.current) {
120
- actionRef.current.scrollToIndex = (a, b = { align: "center" }) => {
121
- vScroll(a, b);
122
- onScrollStop();
123
- };
124
- actionRef.current.getMessagesInView = onScrollStop;
125
- onScrollStop();
126
- actionRef.current.focusToIndex = (a, b = { align: "center" }) => {
127
- scrollAndFocus(a, b);
128
- };
129
- actionRef.current.focusToIndexWithoutScroll = onlyFocus;
130
- actionRef.current.focusToList = () => {
131
- virtualListRef.current?.focus();
132
- };
133
- }
134
- }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll]);
135
- import_react.default.useEffect(() => {
136
- let handlerCallback = null;
137
- const localVirtualRef = virtualListRef.current;
138
- const onScroll = () => {
139
- if (handlerCallback)
140
- clearTimeout(handlerCallback);
141
- handlerCallback = setTimeout(onScrollStop, 300);
142
- };
143
- if (onScrollEnds) {
144
- virtualListRef.current.addEventListener("scroll", onScroll);
145
- }
146
- document.addEventListener("visibilitychange", checkPendingOnScroll);
147
- return () => {
148
- if (handlerCallback)
149
- clearTimeout(handlerCallback);
150
- if (onScrollEnds)
151
- localVirtualRef.removeEventListener("scroll", onScroll);
152
- document.removeEventListener("visibilitychange", checkPendingOnScroll);
153
- };
154
- }, [onScrollStop, onScrollEnds, checkPendingOnScroll]);
155
- const handleKey = import_react.default.useCallback((e) => {
156
- const { key } = e;
157
- const index = Number(e.currentTarget.dataset.index);
158
- e.stopPropagation();
159
- switch (key) {
160
- case "ArrowUp":
161
- e.preventDefault();
162
- if (index > 0) {
163
- (virtualListRef.current?.querySelector(`[data-index="${index - 1}"]`)).focus();
164
- } else if (hasMoreItems === "top") {
165
- loadMoreRef.current?.focus();
166
- }
167
- break;
168
- case "ArrowDown":
169
- e.preventDefault();
170
- if (index < messages?.length - 1) {
171
- (virtualListRef.current?.querySelector(`[data-index="${index + 1}"]`)).focus();
172
- }
173
- break;
174
- case "Home":
175
- e.preventDefault();
176
- scrollAndFocus(0);
177
- break;
178
- case "End":
179
- e.preventDefault();
180
- scrollAndFocus(messages?.length - 1);
181
- break;
182
- case "Tab":
183
- if (hasMoreItems === "bottom" && !e.shiftKey) {
184
- e.preventDefault();
185
- loadMoreRef.current?.focus();
186
- } else if (hasMoreItems === "top" && e.shiftKey) {
187
- e.preventDefault();
188
- loadMoreRef.current?.focus();
189
- } else if (!e.shiftKey) {
190
- if (bannerPosition) {
191
- e.preventDefault();
192
- bannerRef?.current?.focusOnWrapper();
193
- }
194
- } else {
195
- e.preventDefault();
196
- virtualListRef.current?.focus();
197
- }
198
- break;
199
- default:
200
- break;
201
- }
202
- }, [bannerRef, hasMoreItems, messages?.length, bannerPosition, scrollAndFocus]);
203
- const handleListKey = import_react.default.useCallback((e) => {
204
- const { key } = e;
205
- switch (key) {
206
- case "ArrowUp":
207
- e.preventDefault();
208
- if (document.activeElement !== loadMoreRef.current) {
209
- onlyFocus(onScrollStop()?.shift());
210
- }
211
- break;
212
- case "ArrowDown":
213
- e.preventDefault();
214
- if (document.activeElement === loadMoreRef.current) {
215
- virtualListRef.current.querySelector(`[data-index="0"]`).focus();
216
- } else {
217
- onlyFocus(onScrollStop()?.pop());
218
- }
219
- break;
220
- case "Home":
221
- e.preventDefault();
222
- scrollAndFocus(0);
223
- break;
224
- case "End":
225
- e.preventDefault();
226
- scrollAndFocus(messages?.length - 1);
227
- break;
228
- case "Tab":
229
- if (document.activeElement !== loadMoreRef.current) {
230
- if (hasMoreItems === "bottom" && !e.shiftKey) {
231
- e.preventDefault();
232
- loadMoreRef.current?.focus();
233
- } else if (!e.shiftKey) {
234
- e.preventDefault();
235
- actionRef.current.focusToComposer();
236
- }
237
- } else if (!e.shiftKey) {
238
- e.preventDefault();
239
- actionRef.current.focusToComposer();
240
- } else {
241
- e.preventDefault();
242
- virtualListRef.current?.focus();
243
- }
244
- break;
245
- default:
246
- break;
247
- }
248
- }, [actionRef, hasMoreItems, messages?.length, onScrollStop, onlyFocus, scrollAndFocus]);
249
52
  const render = import_react.default.useMemo(() => virtualItems.map((virtualItem) => {
250
53
  const { index, measureRef, start } = virtualItem;
251
54
  const row = messages[index];
@@ -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 React, { CSSProperties, WeakValidationMap } from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useGetGlobalAttributes,\n useValidateTypescriptPropTypes,\n describe,\n} from '@elliemae/ds-utilities';\nimport { useVirtual } from 'react-virtual';\nimport DSButton from '@elliemae/ds-button';\nimport { debounce } from 'lodash';\nimport { ChatBubble, BUBBLE_TYPES } from '../../exported-related/bubble';\nimport { MessageDelimiter } from '../../exported-related/message-delimiter';\nimport { SystemMessage } from '../../exported-related/system-message';\nimport {\n StyledWrapperListItem,\n StyledChatContainerContentList,\n StyledChatContainerContentListScroll,\n StyledWrapper,\n StyledLoadMoreContainer,\n ListItem,\n StyledNewMessagesHiddenContainer,\n} from './styled';\nimport { DSChatT, ChatContainerMessagesListPropTypes, defaultPropsMessagesList } from '../../react-desc-prop-types';\nimport { useGetNewMessages } from './useGetNewMessages';\n\nconst getPadding = ({ hasMoreItems, bannerPosition, isLoading }: DSChatT.GetPaddingT) => {\n const padding = {\n paddingStart: 0,\n paddingEnd: -5,\n };\n if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'top')) padding.paddingStart = 42;\n else if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'bottom')) padding.paddingEnd = 42;\n return padding;\n};\nconst ChatContainerMessagesList: React.ComponentType<DSChatT.MessagesListProps> = (props) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSChatT.MessagesListProps>(props, defaultPropsMessagesList);\n useValidateTypescriptPropTypes<DSChatT.MessagesListProps>(propsWithDefault, ChatContainerMessagesListPropTypes);\n const globalAttributes = useGetGlobalAttributes(propsWithDefault);\n const {\n sendingText,\n bannerPosition,\n sendingMessages,\n messages,\n actionRef,\n onScrollEnds,\n getMoreMessages,\n hasMoreItems,\n isLoading,\n bannerRef,\n } = propsWithDefault;\n const pendingOnScroll = React.useRef(false);\n const loadMoreRef = React.useRef(null);\n const virtualListRef = React.useRef<HTMLDivElement>();\n // estimateSize should not be really required given what was stated on\n // https://github.com/tannerlinsley/react-virtual/issues/23\n const {\n scrollToIndex: vScroll,\n totalSize,\n virtualItems,\n } = useVirtual({\n size: messages?.length,\n parentRef: virtualListRef,\n overscan: 15,\n ...getPadding({ hasMoreItems, bannerPosition, isLoading }),\n estimateSize: React.useCallback(() => 80, []),\n });\n\n const newMessages = useGetNewMessages(messages);\n\n const debouncedScroll = React.useMemo(\n () =>\n debounce((): number[] => {\n if (document.visibilityState === 'hidden') {\n pendingOnScroll.current = true;\n return [];\n }\n if (!virtualListRef.current) return [];\n pendingOnScroll.current = false;\n const { bottom, top } = virtualListRef.current?.getBoundingClientRect();\n\n const list = virtualListRef.current.querySelectorAll(\n '[data-element=\"chat-element-list-item\"]',\n ) as NodeListOf<HTMLDivElement>;\n const indexList = [];\n list.forEach((item: HTMLElement) => {\n const { top: itemTop } = item.getBoundingClientRect();\n\n const itemPadding = 10;\n if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index);\n });\n if (onScrollEnds) onScrollEnds(indexList);\n return indexList;\n }, 500),\n [onScrollEnds],\n );\n\n const onScrollStop = React.useCallback(debouncedScroll, [debouncedScroll]);\n\n const onlyFocus = React.useCallback((index?: number) => {\n (virtualListRef.current.querySelector(`[data-index=\"${index}\"]`) as HTMLDivElement).focus();\n }, []);\n\n const scrollAndFocus = React.useCallback(\n (index: number, b = { align: 'center' }) => {\n vScroll(index, b);\n setTimeout(() => {\n onlyFocus(index);\n }, 300);\n onScrollStop();\n },\n [onScrollStop, onlyFocus, vScroll],\n );\n\n const checkPendingOnScroll = React.useCallback(() => {\n if (pendingOnScroll.current === true) onScrollStop();\n }, [onScrollStop]);\n\n React.useEffect(() => {\n if (actionRef && actionRef.current) {\n actionRef.current.scrollToIndex = (a, b = { align: 'center' }) => {\n vScroll(a, b as any);\n onScrollStop();\n };\n actionRef.current.getMessagesInView = onScrollStop;\n onScrollStop(); // init useMemo due to debounce use.\n actionRef.current.focusToIndex = (a, b = { align: 'center' } as ScrollToOptions) => {\n scrollAndFocus(a, b);\n };\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = () => {\n virtualListRef.current?.focus();\n };\n }\n }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll]);\n\n React.useEffect(() => {\n let handlerCallback = null;\n const localVirtualRef = virtualListRef.current;\n const onScroll = () => {\n if (handlerCallback) clearTimeout(handlerCallback);\n handlerCallback = setTimeout(onScrollStop, 300);\n };\n if (onScrollEnds) {\n virtualListRef.current.addEventListener('scroll', onScroll);\n }\n document.addEventListener('visibilitychange', checkPendingOnScroll);\n return () => {\n if (handlerCallback) clearTimeout(handlerCallback);\n if (onScrollEnds) localVirtualRef.removeEventListener('scroll', onScroll);\n document.removeEventListener('visibilitychange', checkPendingOnScroll);\n };\n }, [onScrollStop, onScrollEnds, checkPendingOnScroll]);\n\n const handleKey = React.useCallback(\n (e: React.KeyboardEvent) => {\n const { key } = e;\n const index = Number(e.currentTarget.dataset.index);\n e.stopPropagation();\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (index > 0) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index - 1}\"]`) as HTMLDivElement).focus();\n } else if (hasMoreItems === 'top') {\n loadMoreRef.current?.focus();\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (index < messages?.length - 1) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index + 1}\"]`) as HTMLDivElement).focus();\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n scrollAndFocus(messages?.length - 1);\n break;\n case 'Tab':\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (hasMoreItems === 'top' && e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n if (bannerPosition) {\n e.preventDefault();\n bannerRef?.current?.focusOnWrapper();\n }\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [bannerRef, hasMoreItems, messages?.length, bannerPosition, scrollAndFocus],\n );\n const handleListKey = React.useCallback(\n (e: React.KeyboardEvent) => {\n const { key } = e;\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (document.activeElement !== loadMoreRef.current) {\n onlyFocus(onScrollStop()?.shift());\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (document.activeElement === loadMoreRef.current) {\n (virtualListRef.current.querySelector(`[data-index=\"0\"]`) as HTMLDivElement).focus();\n } else {\n onlyFocus(onScrollStop()?.pop());\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n scrollAndFocus(messages?.length - 1);\n break;\n case 'Tab':\n if (document.activeElement !== loadMoreRef.current) {\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current.focusToComposer();\n }\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current.focusToComposer();\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [actionRef, hasMoreItems, messages?.length, onScrollStop, onlyFocus, scrollAndFocus],\n );\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 ref={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 // eslint-disable-next-line eslint-comments/no-unlimited-disable\n <ChatBubble {...row} helpMessage={isSending ? sendingText : row.helpMessage} />\n ) : null}\n {row.type === BUBBLE_TYPES.DELIMITER ? <MessageDelimiter {...row} /> : null}\n {row.type === BUBBLE_TYPES.SYSTEM ? <SystemMessage {...row} /> : 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=\"chat-thread-container\"\n tabIndex={0}\n ref={virtualListRef as React.RefObject<HTMLDivElement>}\n role=\"list\"\n onKeyDown={handleListKey}\n >\n <StyledChatContainerContentListScroll height={`${totalSize}px`}>\n {!isLoading && hasMoreItems ? (\n <StyledLoadMoreContainer hasMoreItems={hasMoreItems}>\n <DSButton\n labelText=\"Load More\"\n buttonType=\"secondary\"\n onClick={getMoreMessages}\n data-testid=\"ds-chat-load-more-btn\"\n innerRef={loadMoreRef}\n />\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.propTypes = ChatContainerMessagesListPropTypes as WeakValidationMap<unknown>;\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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",
4
+ "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React, { CSSProperties, WeakValidationMap } from 'react';\nimport { describe } from '@elliemae/ds-utilities';\nimport DSButton from '@elliemae/ds-button';\nimport { ChatBubble, BUBBLE_TYPES } from '../../exported-related/bubble';\nimport { MessageDelimiter } from '../../exported-related/message-delimiter';\nimport { SystemMessage } from '../../exported-related/system-message';\nimport {\n StyledWrapperListItem,\n StyledChatContainerContentList,\n StyledChatContainerContentListScroll,\n StyledWrapper,\n StyledLoadMoreContainer,\n ListItem,\n StyledNewMessagesHiddenContainer,\n} from './styled';\nimport { DSChatT, ChatContainerMessagesListPropTypes } from '../../react-desc-prop-types';\nimport { useGetNewMessages } from './useGetNewMessages';\nimport { useChatContainerMessageList } from './useChatContainerMessageList';\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 ref={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 // eslint-disable-next-line eslint-comments/no-unlimited-disable\n <ChatBubble {...row} helpMessage={isSending ? sendingText : row.helpMessage} />\n ) : null}\n {row.type === BUBBLE_TYPES.DELIMITER ? <MessageDelimiter {...row} /> : null}\n {row.type === BUBBLE_TYPES.SYSTEM ? <SystemMessage {...row} /> : 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=\"chat-thread-container\"\n tabIndex={0}\n ref={virtualListRef as React.RefObject<HTMLDivElement>}\n role=\"list\"\n onKeyDown={handleListKey}\n >\n <StyledChatContainerContentListScroll height={`${totalSize}px`}>\n {!isLoading && hasMoreItems ? (\n <StyledLoadMoreContainer hasMoreItems={hasMoreItems}>\n <DSButton\n labelText=\"Load More\"\n buttonType=\"secondary\"\n onClick={getMoreMessages}\n data-testid=\"ds-chat-load-more-btn\"\n innerRef={loadMoreRef}\n />\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.propTypes = ChatContainerMessagesListPropTypes as WeakValidationMap<unknown>;\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;ADGvB,mBAAwD;AACxD,0BAAyB;AACzB,uBAAqB;AACrB,oBAAyC;AACzC,+BAAiC;AACjC,4BAA8B;AAC9B,oBAQO;AACP,mCAA4D;AAC5D,+BAAkC;AAClC,yCAA4C;AAE5C,MAAM,4BAA4E,CAAC,UAAU;AAC3F,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE,oEAA4B,KAAK;AAErC,QAAM,EAAE,aAAa,iBAAiB,UAAU,iBAAiB,cAAc,cAAc;AAC7F,QAAM,EAAE,WAAW,iBAAiB;AAEpC,QAAM,cAAc,gDAAkB,QAAQ;AAE9C,QAAM,SAAS,qBAAM,QACnB,MACE,aAAa,IAAI,CAAC,gBAAgB;AAChC,UAAM,EAAE,OAAO,YAAY,UAAU;AACrC,UAAM,MAAM,SAAS;AACrB,UAAM,YAAY,mBAAmB,gBAAgB,KAAK,CAAC,MAAM,MAAM,IAAI,IAAI;AAC/E,UAAM,QAAuB;AAAA,MAC3B,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WAAW,cAAc;AAAA,MACzB,OAAO;AAAA,IACT;AAEA,WACE,mDAAC;AAAA,MACC,gBAAa;AAAA,MACb,cAAY;AAAA,MACZ,KAAK,kBAAkB,SAAS,IAAI,QAAQ,IAAI;AAAA,MAChD;AAAA,MACA,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX,MAAK;AAAA,OAEL,mDAAC;AAAA,MAAsB,MAAM,IAAI;AAAA,OAC9B,IAAI,SAAS,2BAAa,UAAU,IAAI,SAAS,2BAAa,YAE7D,mDAAC;AAAA,MAAY,GAAG;AAAA,MAAK,aAAa,YAAY,cAAc,IAAI;AAAA,KAAa,IAC3E,MACH,IAAI,SAAS,2BAAa,YAAY,mDAAC;AAAA,MAAkB,GAAG;AAAA,KAAK,IAAK,MACtE,IAAI,SAAS,2BAAa,SAAS,mDAAC;AAAA,MAAe,GAAG;AAAA,KAAK,IAAK,IACnE,CACF;AAAA,EAEJ,CAAC,GACH,CAAC,cAAc,UAAU,iBAAiB,WAAW,WAAW,CAClE;AAEA,SACE,mDAAC;AAAA,IAAe,GAAG;AAAA,KACjB,mDAAC;AAAA,IACC,eAAY;AAAA,IACZ,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAK;AAAA,IACL,WAAW;AAAA,KAEX,mDAAC;AAAA,IAAqC,QAAQ,GAAG;AAAA,KAC9C,CAAC,aAAa,eACb,mDAAC;AAAA,IAAwB;AAAA,KACvB,mDAAC;AAAA,IACC,WAAU;AAAA,IACV,YAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAY;AAAA,IACZ,UAAU;AAAA,GACZ,CACF,IACE,MACH,MACH,CACF,GAEA,mDAAC;AAAA,IAAiC,aAAU;AAAA,IAAS,eAAY;AAAA,KAC9D,YAAY,IAAI,CAAC,eAChB,mDAAC;AAAA,IAAE,KAAK,WAAW;AAAA,KAChB,WAAW,OAAM,KAAE,WAAW,MAAK,KAAE,WAAW,MAAK,KAAE,WAAW,cAAa,KAAE,WAAW,WAC/F,CACD,CACH,CACF;AAEJ;AAEA,0BAA0B,YAAY;AACtC,0BAA0B,cAAc;AACxC,MAAM,sCAAsC,kCAAS,yBAAyB;AAC9E,oCAAoC,YAAY;",
6
6
  "names": []
7
7
  }
@@ -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 { BUBBLE_TYPES } from '../../exported-related/bubble/index';\nimport { BubbleProps } from '../../exported-related/bubble/props';\n\nexport const StyledWrapper = styled.div`\n width: 100%;\n height: 100%;\n`;\n\n// list\nexport const StyledWrapperListItem = styled.div<Partial<BubbleProps>>`\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"],
4
+ "sourcesContent": ["import { styled } from '@elliemae/ds-system';\nimport { BUBBLE_TYPES } from '../../exported-related/bubble/index';\nimport { BubblePropsT } from '../../exported-related/bubble/props';\n\nexport const StyledWrapper = styled.div`\n width: 100%;\n height: 100%;\n`;\n\n// list\nexport const StyledWrapperListItem = styled.div<Partial<BubblePropsT>>`\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
5
  "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAAuB;AACvB,oBAA6B;AAGtB,MAAM,gBAAgB,wBAAO;AAAA;AAAA;AAAA;AAM7B,MAAM,wBAAwB,wBAAO;AAAA;AAAA,IAExC,CAAC,UACD,MAAM,SAAS,2BAAa,UAC5B,YAAY,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,MAAM;AAAA;AAAA,IAEhF,CAAC,UACD,MAAM,SAAS,2BAAa,aAC5B,YAAY,MAAM,MAAM,MAAM,WAAW,MAAM,MAAM,MAAM;AAAA,MACzD,MAAM,MAAM,MAAM;AAAA;AAAA,IAEpB,CAAC,UACD,MAAM,SAAS,2BAAa,UAC5B,YAAY,MAAM,MAAM,MAAM;AAAA;AAAA;AAI3B,MAAM,iCAAiC,wBAAO;AAAA;AAAA;AAAA,aAGxC,CAAC,UAAU,MAAM,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAMnC,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;AAAA;AAAA;AAItB,MAAM,0BAA0B,wBAAO;AAAA;AAAA,uBAEvB,CAAC,UAAU,MAAM,MAAM,MAAM;AAAA,aACvC,CAAC,UAAU,MAAM,MAAM,MAAM;AAAA,WAC/B,CAAC,UAAU,MAAM,MAAM,MAAM;AAAA,YAC5B,CAAC,UAAU,MAAM,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA,IAIrC,CAAC,UAAW,MAAM,iBAAiB,QAAQ,YAAY;AAAA,IACvD,CAAC,UAAW,MAAM,iBAAiB,WAAW,eAAe;AAAA;AAE1D,MAAM,WAAW,wBAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAShB,CAAC,UAAU,MAAM,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+ var useActionRef_exports = {};
23
+ __export(useActionRef_exports, {
24
+ useActionRef: () => useActionRef
25
+ });
26
+ module.exports = __toCommonJS(useActionRef_exports);
27
+ var React = __toESM(require("react"));
28
+ var import_react = __toESM(require("react"));
29
+ const useActionRef = ({
30
+ actionRef,
31
+ useVirtualHelpers: { scrollToIndex: vScroll },
32
+ virtualListRef,
33
+ onScrollStop,
34
+ onlyFocus,
35
+ scrollAndFocus
36
+ }) => {
37
+ import_react.default.useEffect(() => {
38
+ if (actionRef && actionRef.current) {
39
+ const scrollToIndex = (index, opts = { align: "center" }) => {
40
+ vScroll(index, opts);
41
+ onScrollStop();
42
+ };
43
+ const focusToIndex = (index, opts = { align: "center" }) => {
44
+ scrollAndFocus(index, opts);
45
+ };
46
+ const focusToList = () => {
47
+ virtualListRef.current?.focus();
48
+ };
49
+ actionRef.current.scrollToIndex = scrollToIndex;
50
+ actionRef.current.getMessagesInView = onScrollStop;
51
+ onScrollStop();
52
+ actionRef.current.focusToIndex = focusToIndex;
53
+ actionRef.current.focusToIndexWithoutScroll = onlyFocus;
54
+ actionRef.current.focusToList = focusToList;
55
+ }
56
+ }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);
57
+ };
58
+ //# sourceMappingURL=useActionRef.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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 DebouncedFunc } from 'lodash';\nimport { useVirtual } from 'react-virtual';\nimport { DSChatT } from '../../react-desc-prop-types';\n\ntype UseActionRefArgs = {\n actionRef: DSChatT.ActionRef;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n onScrollStop: DebouncedFunc<() => string[]>;\n onlyFocus: (index?: number) => void;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n};\n\nexport const useActionRef = ({\n actionRef,\n useVirtualHelpers: { scrollToIndex: vScroll },\n virtualListRef,\n onScrollStop,\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 vScroll(index, opts);\n onScrollStop();\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 = onScrollStop;\n // I have no idea what the next line refeers to\n // keeping this from original code to avoid any possible breaking-change\n onScrollStop(); // init useMemo due to debounce use.\n actionRef.current.focusToIndex = focusToIndex;\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = focusToList;\n }\n }, [actionRef, onScrollStop, 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;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,MACsB;AACtB,uBAAM,UAAU,MAAM;AACpB,QAAI,aAAa,UAAU,SAAS;AAClC,YAAM,gBAA+D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AAC1G,gBAAQ,OAAO,IAAI;AACnB,qBAAa;AAAA,MACf;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;AAGtC,mBAAa;AACb,gBAAU,QAAQ,eAAe;AACjC,gBAAU,QAAQ,4BAA4B;AAC9C,gBAAU,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,WAAW,cAAc,WAAW,gBAAgB,SAAS,cAAc,CAAC;AAClF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+ var useChatContainerMessageList_exports = {};
23
+ __export(useChatContainerMessageList_exports, {
24
+ useChatContainerMessageList: () => useChatContainerMessageList
25
+ });
26
+ module.exports = __toCommonJS(useChatContainerMessageList_exports);
27
+ var React = __toESM(require("react"));
28
+ var import_react = __toESM(require("react"));
29
+ var import_ds_utilities = require("@elliemae/ds-utilities");
30
+ var import_react_virtual = require("react-virtual");
31
+ var import_useActionRef = require("./useActionRef");
32
+ var import_useGlobalEventListener = require("./useGlobalEventListener");
33
+ var import_useKeyboard = require("./useKeyboard");
34
+ var import_useFocusAndScrollHelpers = require("./useFocusAndScrollHelpers");
35
+ var import_react_desc_prop_types = require("../../react-desc-prop-types");
36
+ const getPadding = ({ hasMoreItems, bannerPosition, isLoading }) => {
37
+ const padding = {
38
+ paddingStart: 0,
39
+ paddingEnd: -5
40
+ };
41
+ if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === "top"))
42
+ padding.paddingStart = 42;
43
+ else if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === "bottom"))
44
+ padding.paddingEnd = 42;
45
+ return padding;
46
+ };
47
+ const useChatContainerMessageList = (props) => {
48
+ const propsWithDefault = (0, import_ds_utilities.useMemoMergePropsWithDefault)(props, import_react_desc_prop_types.defaultPropsMessagesList);
49
+ (0, import_ds_utilities.useValidateTypescriptPropTypes)(propsWithDefault, import_react_desc_prop_types.ChatContainerMessagesListPropTypes);
50
+ const globalAttributes = (0, import_ds_utilities.useGetGlobalAttributes)(propsWithDefault);
51
+ const loadMoreRef = import_react.default.useRef();
52
+ const virtualListRef = import_react.default.useRef();
53
+ const pendingOnScroll = import_react.default.useRef(false);
54
+ const { bannerPosition, messages, actionRef, hasMoreItems, isLoading } = propsWithDefault;
55
+ const useVirtualHelpers = (0, import_react_virtual.useVirtual)({
56
+ size: messages?.length,
57
+ parentRef: virtualListRef,
58
+ overscan: 15,
59
+ ...getPadding({ hasMoreItems, bannerPosition, isLoading }),
60
+ estimateSize: import_react.default.useCallback(() => 80, [])
61
+ });
62
+ const { onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll } = (0, import_useFocusAndScrollHelpers.useFocusAndScrollHelpers)({
63
+ propsWithDefault,
64
+ useVirtualHelpers,
65
+ pendingOnScroll,
66
+ virtualListRef
67
+ });
68
+ (0, import_useActionRef.useActionRef)({
69
+ actionRef,
70
+ useVirtualHelpers,
71
+ virtualListRef,
72
+ onScrollStop,
73
+ onlyFocus,
74
+ scrollAndFocus
75
+ });
76
+ (0, import_useGlobalEventListener.useGlobalEventListener)({
77
+ propsWithDefault,
78
+ virtualListRef,
79
+ onScrollStop,
80
+ checkPendingOnScroll
81
+ });
82
+ const keyboardMethods = (0, import_useKeyboard.useKeyboard)({
83
+ propsWithDefault,
84
+ actionRef,
85
+ virtualListRef,
86
+ loadMoreRef,
87
+ scrollAndFocus,
88
+ onlyFocus,
89
+ onScrollStop
90
+ });
91
+ return import_react.default.useMemo(() => ({
92
+ propsWithDefault,
93
+ globalAttributes,
94
+ useVirtualHelpers,
95
+ loadMoreRef,
96
+ virtualListRef,
97
+ ...keyboardMethods
98
+ }), [globalAttributes, keyboardMethods, propsWithDefault, useVirtualHelpers, loadMoreRef, virtualListRef]);
99
+ };
100
+ //# sourceMappingURL=useChatContainerMessageList.js.map