@elliemae/ds-chat 3.3.0-next.8 → 3.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Code-review - 20 june 2022.md +119 -0
- package/dist/cjs/exported-related/bubble/props.js.map +1 -1
- package/dist/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +11 -208
- package/dist/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js.map +2 -2
- package/dist/cjs/parts/chat-container-messages-list/styled.js.map +1 -1
- package/dist/cjs/parts/chat-container-messages-list/useActionRef.js +58 -0
- package/dist/cjs/parts/chat-container-messages-list/useActionRef.js.map +7 -0
- package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js +100 -0
- package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js.map +7 -0
- package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +78 -0
- package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +7 -0
- package/dist/cjs/parts/chat-container-messages-list/useGetNewMessages.js.map +2 -2
- package/dist/cjs/parts/chat-container-messages-list/useGlobalEventListener.js +56 -0
- package/dist/cjs/parts/chat-container-messages-list/useGlobalEventListener.js.map +7 -0
- package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js +136 -0
- package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js.map +7 -0
- package/dist/cjs/react-desc-prop-types.js +20 -20
- package/dist/cjs/react-desc-prop-types.js.map +2 -2
- package/dist/esm/Code-review - 20 june 2022.md +119 -0
- package/dist/esm/exported-related/bubble/props.js.map +1 -1
- package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +13 -215
- package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js.map +2 -2
- package/dist/esm/parts/chat-container-messages-list/styled.js.map +1 -1
- package/dist/esm/parts/chat-container-messages-list/useActionRef.js +36 -0
- package/dist/esm/parts/chat-container-messages-list/useActionRef.js.map +7 -0
- package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js +82 -0
- package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js.map +7 -0
- package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +56 -0
- package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +7 -0
- package/dist/esm/parts/chat-container-messages-list/useGetNewMessages.js.map +2 -2
- package/dist/esm/parts/chat-container-messages-list/useGlobalEventListener.js +34 -0
- package/dist/esm/parts/chat-container-messages-list/useGlobalEventListener.js.map +7 -0
- package/dist/esm/parts/chat-container-messages-list/useKeyboard.js +114 -0
- package/dist/esm/parts/chat-container-messages-list/useKeyboard.js.map +7 -0
- package/dist/esm/react-desc-prop-types.js +10 -10
- package/dist/esm/react-desc-prop-types.js.map +2 -2
- 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
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAwD;AACxD,
|
|
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 {
|
|
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
|