@elliemae/ds-chat 2.1.0-rc.1 → 2.1.0-rc.10
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/cjs/ChatDataTestids.js +2 -1
- package/cjs/parts/chat-composer/ChatContainerComposer.js +12 -6
- package/cjs/parts/chat-composer/props.js +2 -0
- package/cjs/parts/chat-container/ChatContainer.js +12 -12
- package/cjs/parts/chat-container/styled.js +1 -1
- package/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +11 -18
- package/esm/ChatDataTestids.js +2 -1
- package/esm/parts/chat-composer/ChatContainerComposer.js +12 -6
- package/esm/parts/chat-composer/props.js +2 -0
- package/esm/parts/chat-container/ChatContainer.js +12 -12
- package/esm/parts/chat-container/styled.js +1 -1
- package/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +9 -16
- package/package.json +10 -10
- package/types/ChatDataTestids.d.ts +1 -0
- package/types/parts/chat-composer/ChatContainerComposer.d.ts +3 -0
- package/types/tests/utils.d.ts +1 -27
package/cjs/ChatDataTestids.js
CHANGED
|
@@ -21,7 +21,8 @@ const ChatDataTestIds = {
|
|
|
21
21
|
SYSTEM_MSG_TIME: 'chat-system-message-time',
|
|
22
22
|
BUBBLE: 'ds-chat-bubble',
|
|
23
23
|
BUBBLE_TITLE: 'chat-bubble-title',
|
|
24
|
-
BUBBLE_BODY: 'chat-bubble-body'
|
|
24
|
+
BUBBLE_BODY: 'chat-bubble-body',
|
|
25
|
+
BANNER: 'ds-banner-container'
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
exports.ChatDataTestIds = ChatDataTestIds;
|
|
@@ -48,10 +48,12 @@ const ChatComposer = props => {
|
|
|
48
48
|
placeholder,
|
|
49
49
|
inputMaxLength,
|
|
50
50
|
maxLengthMessage,
|
|
51
|
+
ariaMaxLengthMessage,
|
|
51
52
|
buttonDisabled,
|
|
52
53
|
dataTestid,
|
|
53
54
|
actionRef
|
|
54
55
|
} = props;
|
|
56
|
+
const COMPOSER_MIN_HEIGHT = 32;
|
|
55
57
|
const input = React__default["default"].useRef();
|
|
56
58
|
const inputSize = React__default["default"].useRef();
|
|
57
59
|
const inputSend = React__default["default"].useRef();
|
|
@@ -62,10 +64,10 @@ const ChatComposer = props => {
|
|
|
62
64
|
var _inputSize$current, _inputSize$current2, _inputSize$current3, _inputSize$current4;
|
|
63
65
|
|
|
64
66
|
const newHeight = ((_inputSize$current = inputSize.current) === null || _inputSize$current === void 0 ? void 0 : _inputSize$current.scrollHeight) > internalMaxHeight ? internalMaxHeight : (_inputSize$current2 = inputSize.current) === null || _inputSize$current2 === void 0 ? void 0 : _inputSize$current2.scrollHeight;
|
|
65
|
-
onResize(newHeight);
|
|
67
|
+
if (newHeight !== height && newHeight > COMPOSER_MIN_HEIGHT) onResize(newHeight);
|
|
66
68
|
setHeight(newHeight);
|
|
67
69
|
setShowScroll(((_inputSize$current3 = inputSize.current) === null || _inputSize$current3 === void 0 ? void 0 : _inputSize$current3.scrollHeight) - ((_inputSize$current4 = inputSize.current) === null || _inputSize$current4 === void 0 ? void 0 : _inputSize$current4.clientHeight) > 5);
|
|
68
|
-
}, [inputValue, internalMaxHeight, onResize]);
|
|
70
|
+
}, [inputValue, internalMaxHeight, height, onResize]);
|
|
69
71
|
React__default["default"].useEffect(() => {
|
|
70
72
|
if (actionRef && actionRef.current) {
|
|
71
73
|
actionRef.current.focusToComposer = () => {
|
|
@@ -92,6 +94,9 @@ const ChatComposer = props => {
|
|
|
92
94
|
"data-testid": dataTestid
|
|
93
95
|
}, void 0, /*#__PURE__*/_jsx__default["default"](dsGrid.Grid, {
|
|
94
96
|
cols: ['1fr', '24px'],
|
|
97
|
+
style: {
|
|
98
|
+
height: heightProps.height
|
|
99
|
+
},
|
|
95
100
|
justifyContent: "center",
|
|
96
101
|
alignItems: "flex-end",
|
|
97
102
|
gutter: "xxs"
|
|
@@ -105,7 +110,9 @@ const ChatComposer = props => {
|
|
|
105
110
|
onKeyDown: onKeyDown,
|
|
106
111
|
placeholder: placeholder,
|
|
107
112
|
"aria-label": "Message to send",
|
|
108
|
-
"data-testid": "chat-composer-textarea"
|
|
113
|
+
"data-testid": "chat-composer-textarea",
|
|
114
|
+
name: "chat-composer-textarea",
|
|
115
|
+
id: "chat-composer-textarea"
|
|
109
116
|
}), /*#__PURE__*/_jsx__default["default"](dsGrid.Grid, {
|
|
110
117
|
height: "32px",
|
|
111
118
|
alignItems: "center"
|
|
@@ -132,8 +139,7 @@ const ChatComposer = props => {
|
|
|
132
139
|
width: (_input$current = input.current) === null || _input$current === void 0 ? void 0 : _input$current.clientWidth
|
|
133
140
|
},
|
|
134
141
|
onChange: handleChange,
|
|
135
|
-
value: inputValue
|
|
136
|
-
|
|
142
|
+
value: inputValue
|
|
137
143
|
}), /*#__PURE__*/_jsx__default["default"](dsGrid.Grid, {
|
|
138
144
|
cols: ['1fr', '24px'],
|
|
139
145
|
justifyContent: "flex-end",
|
|
@@ -146,7 +152,7 @@ const ChatComposer = props => {
|
|
|
146
152
|
}, void 0, inputMaxLength && hasError ? /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
147
153
|
children: [/*#__PURE__*/_jsx__default["default"](styled.StyledCounterErrorA11y, {
|
|
148
154
|
role: "alert"
|
|
149
|
-
}, void 0,
|
|
155
|
+
}, void 0, ariaMaxLengthMessage || "You have entered ".concat(inputLength, " characters and have exceeded the limit by ").concat(inputLength - inputMaxLength, ". Please limit to less than ").concat(inputMaxLength, " characters. ")), maxLengthMessage || "Please limit to less than ".concat(inputMaxLength, " characters. ")]
|
|
150
156
|
}) : '', inputMaxLength ? " ".concat(inputLength, " / ").concat(inputMaxLength) : ''), _Grid || (_Grid = /*#__PURE__*/_jsx__default["default"](dsGrid.Grid, {}))));
|
|
151
157
|
};
|
|
152
158
|
|
|
@@ -8,6 +8,7 @@ var lodash = require('lodash');
|
|
|
8
8
|
const defaultComposerPros = {
|
|
9
9
|
placeholder: 'Type your message',
|
|
10
10
|
inputValue: '',
|
|
11
|
+
ariaMaxLengthMessage: '',
|
|
11
12
|
onChange: lodash.noop,
|
|
12
13
|
onResize: lodash.noop,
|
|
13
14
|
onSend: lodash.noop,
|
|
@@ -24,6 +25,7 @@ const defaultComposerPros = {
|
|
|
24
25
|
const composerProps = {
|
|
25
26
|
placeholder: reactDesc.PropTypes.string.description('Input Placeholder').defaultValue(defaultComposerPros.placeholder),
|
|
26
27
|
inputValue: reactDesc.PropTypes.string.description('Input value').defaultValue(defaultComposerPros.inputValue),
|
|
28
|
+
ariaMaxLengthMessage: reactDesc.PropTypes.string.description('Aria message for Max length message when exceeded').defaultValue(defaultComposerPros.maxLengthMessage),
|
|
27
29
|
maxLengthMessage: reactDesc.PropTypes.string.description('Max length message').defaultValue(defaultComposerPros.maxLengthMessage),
|
|
28
30
|
onChange: reactDesc.PropTypes.func.description('Called when the user types').defaultValue(defaultComposerPros.onChange),
|
|
29
31
|
onResize: reactDesc.PropTypes.func.description('Called the input changes his height').defaultValue(defaultComposerPros.onResize),
|
|
@@ -36,7 +36,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
36
36
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
37
37
|
|
|
38
38
|
const ChatContainer = props$1 => {
|
|
39
|
-
var _containerRef$current;
|
|
39
|
+
var _messagesListProps$me2, _containerRef$current;
|
|
40
40
|
|
|
41
41
|
useValidateProps.useValidateProps(props$1, props.containerProps);
|
|
42
42
|
const {
|
|
@@ -67,18 +67,16 @@ const ChatContainer = props$1 => {
|
|
|
67
67
|
});
|
|
68
68
|
const onResize = React__default["default"].useCallback(height => {
|
|
69
69
|
if (onComposerResize) onComposerResize(height);
|
|
70
|
-
|
|
71
|
-
if (height > 30) {
|
|
72
|
-
/*
|
|
70
|
+
/*
|
|
73
71
|
setTimeout is used to equal the animation duration from the
|
|
74
72
|
composer text area when increase its size
|
|
75
73
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
}
|
|
74
|
+
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
actionRef.current.scrollToIndex(messagesListProps.messages.length - 1, {
|
|
77
|
+
align: 'start'
|
|
78
|
+
});
|
|
79
|
+
}, 50);
|
|
82
80
|
}, [onComposerResize, messagesListProps.messages, actionRef]);
|
|
83
81
|
const Container = device === 'desktop' ? styled.StyledChatContainerContent : styled.MobileStyledChatContainerContent;
|
|
84
82
|
const handleTabs = React__default["default"].useCallback(e => {
|
|
@@ -86,7 +84,9 @@ const ChatContainer = props$1 => {
|
|
|
86
84
|
const ref = actionRef || listRef;
|
|
87
85
|
|
|
88
86
|
if (e.shiftKey && e.key === 'Tab') {
|
|
89
|
-
|
|
87
|
+
var _messagesListProps$me;
|
|
88
|
+
|
|
89
|
+
if (((_messagesListProps$me = messagesListProps.messages) === null || _messagesListProps$me === void 0 ? void 0 : _messagesListProps$me.length) > 0) {
|
|
90
90
|
e.preventDefault();
|
|
91
91
|
|
|
92
92
|
if (['top', 'bottom'].includes(bannerPosition)) {
|
|
@@ -100,7 +100,7 @@ const ChatContainer = props$1 => {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
}, [actionRef, onComposerKeyDown, bannerPosition, messagesListProps.messages.length]); // Map actions
|
|
103
|
+
}, [actionRef, onComposerKeyDown, bannerPosition, (_messagesListProps$me2 = messagesListProps.messages) === null || _messagesListProps$me2 === void 0 ? void 0 : _messagesListProps$me2.length]); // Map actions
|
|
104
104
|
|
|
105
105
|
React__default["default"].useEffect(() => {
|
|
106
106
|
if (actionRef && actionRef.current) {
|
|
@@ -18,7 +18,7 @@ const StyledChatContainerContent = /*#__PURE__*/styled__default["default"](dsGri
|
|
|
18
18
|
})(["height:100%;min-width:", "px;overflow:hidden;background:", ";position:relative;"], CONTAINER_WIDTH, props => props.theme.colors.neutral['050']);
|
|
19
19
|
const StyledIndicatorContainer = /*#__PURE__*/styled__default["default"].div.withConfig({
|
|
20
20
|
componentId: "sc-d732wo-1"
|
|
21
|
-
})(["transition:0.4s ease-in-out;position:absolute;visibility:hidden;pointer-events:none;width:100%;padding:0 ", ";left:0;right:0;background:", ";", " ", " & div,a{font-size:13px;}"], props => !props.linear ? props.theme.space.xxs : 0, props => props.theme.colors.neutral['000'], props => props.isLoading === 'top' ? "\n top: -41px;\n transform: translate(0, 41px);\n visibility: visible;\n pointer-events: auto
|
|
21
|
+
})(["transition:0.4s ease-in-out;position:absolute;visibility:hidden;pointer-events:none;width:100%;padding:0 ", ";left:0;right:0;background:", ";", " ", " & div,a{font-size:13px;}"], props => !props.linear ? props.theme.space.xxs : 0, props => props.theme.colors.neutral['000'], props => props.isLoading === 'top' ? "\n top: -41px;\n transform: translate(0, 41px);\n visibility: visible;\n pointer-events: auto;\n " : '', props => props.isLoading === 'bottom' ? "\n bottom: -41px;\n transform: translate(0, -41px);\n visibility: visible;\n pointer-events: auto;\n " : '');
|
|
22
22
|
const MobileStyledChatContainerContent = /*#__PURE__*/styled__default["default"](StyledChatContainerContent).withConfig({
|
|
23
23
|
componentId: "sc-d732wo-2"
|
|
24
24
|
})(["", ",", "{font-size:16px;}", "{font-size:13px;}", "{background-color:#fff;box-shadow:-0 1px 3px rgba(53,60,70,0.8);}", ",", "{font-size:16px;text-align:left;}", "{font-size:13px;}", "{font-size:16px;}", "{font-size:16px;}"], styled$1.StyledTitleLeftBubble, styled$1.StyleBodyWrapper, styled$1.StyledTitleRightBubble, style.Wrapper, style.Title, style.Message, style.Time, styled$2.StyledComposerInput, StyledIndicatorContainer);
|
|
@@ -26,7 +26,6 @@ var MessageDelimiter = require('../message-delimiter/MessageDelimiter.js');
|
|
|
26
26
|
var SystemMessage = require('../system-message/SystemMessage.js');
|
|
27
27
|
var styled = require('./styled.js');
|
|
28
28
|
var props = require('./props.js');
|
|
29
|
-
var useValidateProps = require('./config/useValidateProps.js');
|
|
30
29
|
var jsxRuntime = require('react/jsx-runtime');
|
|
31
30
|
|
|
32
31
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -54,8 +53,7 @@ const getPadding = _ref => {
|
|
|
54
53
|
return padding;
|
|
55
54
|
};
|
|
56
55
|
|
|
57
|
-
const ChatContainerMessagesList = props
|
|
58
|
-
useValidateProps.useValidateProps(props$2, props.listProps);
|
|
56
|
+
const ChatContainerMessagesList = props => {
|
|
59
57
|
const {
|
|
60
58
|
sendingText,
|
|
61
59
|
bannerPosition,
|
|
@@ -67,7 +65,7 @@ const ChatContainerMessagesList = props$2 => {
|
|
|
67
65
|
hasMoreItems,
|
|
68
66
|
isLoading,
|
|
69
67
|
bannerRef
|
|
70
|
-
} = props
|
|
68
|
+
} = props;
|
|
71
69
|
const pendingOnScroll = React__default["default"].useRef(false);
|
|
72
70
|
const loadMoreRef = React__default["default"].useRef(null);
|
|
73
71
|
const virtualListRef = React__default["default"].useRef(); // estimateSize should not be really required given what was stated on
|
|
@@ -96,6 +94,7 @@ const ChatContainerMessagesList = props$2 => {
|
|
|
96
94
|
return [];
|
|
97
95
|
}
|
|
98
96
|
|
|
97
|
+
if (!virtualListRef.current) return [];
|
|
99
98
|
pendingOnScroll.current = false;
|
|
100
99
|
const {
|
|
101
100
|
bottom,
|
|
@@ -138,6 +137,7 @@ const ChatContainerMessagesList = props$2 => {
|
|
|
138
137
|
};
|
|
139
138
|
|
|
140
139
|
actionRef.current.getMessagesInView = onScrollStop;
|
|
140
|
+
onScrollStop(); // init useMemo due to debounce use.
|
|
141
141
|
|
|
142
142
|
actionRef.current.focusToIndex = function (a) {
|
|
143
143
|
let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
@@ -203,12 +203,7 @@ const ChatContainerMessagesList = props$2 => {
|
|
|
203
203
|
|
|
204
204
|
e.preventDefault();
|
|
205
205
|
(_loadMoreRef$current2 = loadMoreRef.current) === null || _loadMoreRef$current2 === void 0 ? void 0 : _loadMoreRef$current2.focus();
|
|
206
|
-
} else if (hasMoreItems === 'top' && e.shiftKey) {
|
|
207
|
-
var _loadMoreRef$current3;
|
|
208
|
-
|
|
209
|
-
e.preventDefault();
|
|
210
|
-
(_loadMoreRef$current3 = loadMoreRef.current) === null || _loadMoreRef$current3 === void 0 ? void 0 : _loadMoreRef$current3.focus();
|
|
211
|
-
} else if (!e.shiftKey) {
|
|
206
|
+
} else if (hasMoreItems === 'top' && e.shiftKey) ; else if (!e.shiftKey) {
|
|
212
207
|
if (bannerPosition) {
|
|
213
208
|
e.preventDefault();
|
|
214
209
|
bannerRef.current.focusOnWrapper();
|
|
@@ -222,7 +217,7 @@ const ChatContainerMessagesList = props$2 => {
|
|
|
222
217
|
|
|
223
218
|
break;
|
|
224
219
|
}
|
|
225
|
-
}, [
|
|
220
|
+
}, [bannerRef, hasMoreItems, messages.length, bannerPosition, scrollAndFocus]);
|
|
226
221
|
const handleListKey = React__default["default"].useCallback(e => {
|
|
227
222
|
const {
|
|
228
223
|
key
|
|
@@ -232,9 +227,7 @@ const ChatContainerMessagesList = props$2 => {
|
|
|
232
227
|
case 'ArrowUp':
|
|
233
228
|
e.preventDefault();
|
|
234
229
|
|
|
235
|
-
if (document.activeElement
|
|
236
|
-
scrollAndFocus(messages.length - 1);
|
|
237
|
-
} else {
|
|
230
|
+
if (document.activeElement !== loadMoreRef.current) {
|
|
238
231
|
onlyFocus(onScrollStop().shift());
|
|
239
232
|
}
|
|
240
233
|
|
|
@@ -264,15 +257,15 @@ const ChatContainerMessagesList = props$2 => {
|
|
|
264
257
|
case 'Tab':
|
|
265
258
|
if (document.activeElement !== loadMoreRef.current) {
|
|
266
259
|
if (hasMoreItems === 'bottom' && !e.shiftKey) {
|
|
267
|
-
var _loadMoreRef$
|
|
260
|
+
var _loadMoreRef$current3;
|
|
268
261
|
|
|
269
262
|
e.preventDefault();
|
|
270
|
-
(_loadMoreRef$
|
|
263
|
+
(_loadMoreRef$current3 = loadMoreRef.current) === null || _loadMoreRef$current3 === void 0 ? void 0 : _loadMoreRef$current3.focus();
|
|
271
264
|
} else if (hasMoreItems === 'top' && e.shiftKey) {
|
|
272
|
-
var _loadMoreRef$
|
|
265
|
+
var _loadMoreRef$current4;
|
|
273
266
|
|
|
274
267
|
e.preventDefault();
|
|
275
|
-
(_loadMoreRef$
|
|
268
|
+
(_loadMoreRef$current4 = loadMoreRef.current) === null || _loadMoreRef$current4 === void 0 ? void 0 : _loadMoreRef$current4.focus();
|
|
276
269
|
} else if (!e.shiftKey) {
|
|
277
270
|
e.preventDefault();
|
|
278
271
|
actionRef.current.focusToComposer();
|
package/esm/ChatDataTestids.js
CHANGED
|
@@ -17,7 +17,8 @@ const ChatDataTestIds = {
|
|
|
17
17
|
SYSTEM_MSG_TIME: 'chat-system-message-time',
|
|
18
18
|
BUBBLE: 'ds-chat-bubble',
|
|
19
19
|
BUBBLE_TITLE: 'chat-bubble-title',
|
|
20
|
-
BUBBLE_BODY: 'chat-bubble-body'
|
|
20
|
+
BUBBLE_BODY: 'chat-bubble-body',
|
|
21
|
+
BANNER: 'ds-banner-container'
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
export { ChatDataTestIds };
|
|
@@ -38,10 +38,12 @@ const ChatComposer = props => {
|
|
|
38
38
|
placeholder,
|
|
39
39
|
inputMaxLength,
|
|
40
40
|
maxLengthMessage,
|
|
41
|
+
ariaMaxLengthMessage,
|
|
41
42
|
buttonDisabled,
|
|
42
43
|
dataTestid,
|
|
43
44
|
actionRef
|
|
44
45
|
} = props;
|
|
46
|
+
const COMPOSER_MIN_HEIGHT = 32;
|
|
45
47
|
const input = React.useRef();
|
|
46
48
|
const inputSize = React.useRef();
|
|
47
49
|
const inputSend = React.useRef();
|
|
@@ -52,10 +54,10 @@ const ChatComposer = props => {
|
|
|
52
54
|
var _inputSize$current, _inputSize$current2, _inputSize$current3, _inputSize$current4;
|
|
53
55
|
|
|
54
56
|
const newHeight = ((_inputSize$current = inputSize.current) === null || _inputSize$current === void 0 ? void 0 : _inputSize$current.scrollHeight) > internalMaxHeight ? internalMaxHeight : (_inputSize$current2 = inputSize.current) === null || _inputSize$current2 === void 0 ? void 0 : _inputSize$current2.scrollHeight;
|
|
55
|
-
onResize(newHeight);
|
|
57
|
+
if (newHeight !== height && newHeight > COMPOSER_MIN_HEIGHT) onResize(newHeight);
|
|
56
58
|
setHeight(newHeight);
|
|
57
59
|
setShowScroll(((_inputSize$current3 = inputSize.current) === null || _inputSize$current3 === void 0 ? void 0 : _inputSize$current3.scrollHeight) - ((_inputSize$current4 = inputSize.current) === null || _inputSize$current4 === void 0 ? void 0 : _inputSize$current4.clientHeight) > 5);
|
|
58
|
-
}, [inputValue, internalMaxHeight, onResize]);
|
|
60
|
+
}, [inputValue, internalMaxHeight, height, onResize]);
|
|
59
61
|
React.useEffect(() => {
|
|
60
62
|
if (actionRef && actionRef.current) {
|
|
61
63
|
actionRef.current.focusToComposer = () => {
|
|
@@ -82,6 +84,9 @@ const ChatComposer = props => {
|
|
|
82
84
|
"data-testid": dataTestid
|
|
83
85
|
}, void 0, /*#__PURE__*/_jsx(Grid, {
|
|
84
86
|
cols: ['1fr', '24px'],
|
|
87
|
+
style: {
|
|
88
|
+
height: heightProps.height
|
|
89
|
+
},
|
|
85
90
|
justifyContent: "center",
|
|
86
91
|
alignItems: "flex-end",
|
|
87
92
|
gutter: "xxs"
|
|
@@ -95,7 +100,9 @@ const ChatComposer = props => {
|
|
|
95
100
|
onKeyDown: onKeyDown,
|
|
96
101
|
placeholder: placeholder,
|
|
97
102
|
"aria-label": "Message to send",
|
|
98
|
-
"data-testid": "chat-composer-textarea"
|
|
103
|
+
"data-testid": "chat-composer-textarea",
|
|
104
|
+
name: "chat-composer-textarea",
|
|
105
|
+
id: "chat-composer-textarea"
|
|
99
106
|
}), /*#__PURE__*/_jsx(Grid, {
|
|
100
107
|
height: "32px",
|
|
101
108
|
alignItems: "center"
|
|
@@ -122,8 +129,7 @@ const ChatComposer = props => {
|
|
|
122
129
|
width: (_input$current = input.current) === null || _input$current === void 0 ? void 0 : _input$current.clientWidth
|
|
123
130
|
},
|
|
124
131
|
onChange: handleChange,
|
|
125
|
-
value: inputValue
|
|
126
|
-
|
|
132
|
+
value: inputValue
|
|
127
133
|
}), /*#__PURE__*/_jsx(Grid, {
|
|
128
134
|
cols: ['1fr', '24px'],
|
|
129
135
|
justifyContent: "flex-end",
|
|
@@ -136,7 +142,7 @@ const ChatComposer = props => {
|
|
|
136
142
|
}, void 0, inputMaxLength && hasError ? /*#__PURE__*/jsxs(Fragment, {
|
|
137
143
|
children: [/*#__PURE__*/_jsx(StyledCounterErrorA11y, {
|
|
138
144
|
role: "alert"
|
|
139
|
-
}, void 0,
|
|
145
|
+
}, void 0, ariaMaxLengthMessage || "You have entered ".concat(inputLength, " characters and have exceeded the limit by ").concat(inputLength - inputMaxLength, ". Please limit to less than ").concat(inputMaxLength, " characters. ")), maxLengthMessage || "Please limit to less than ".concat(inputMaxLength, " characters. ")]
|
|
140
146
|
}) : '', inputMaxLength ? " ".concat(inputLength, " / ").concat(inputMaxLength) : ''), _Grid || (_Grid = /*#__PURE__*/_jsx(Grid, {}))));
|
|
141
147
|
};
|
|
142
148
|
|
|
@@ -4,6 +4,7 @@ import { noop } from 'lodash';
|
|
|
4
4
|
const defaultComposerPros = {
|
|
5
5
|
placeholder: 'Type your message',
|
|
6
6
|
inputValue: '',
|
|
7
|
+
ariaMaxLengthMessage: '',
|
|
7
8
|
onChange: noop,
|
|
8
9
|
onResize: noop,
|
|
9
10
|
onSend: noop,
|
|
@@ -20,6 +21,7 @@ const defaultComposerPros = {
|
|
|
20
21
|
const composerProps = {
|
|
21
22
|
placeholder: PropTypes.string.description('Input Placeholder').defaultValue(defaultComposerPros.placeholder),
|
|
22
23
|
inputValue: PropTypes.string.description('Input value').defaultValue(defaultComposerPros.inputValue),
|
|
24
|
+
ariaMaxLengthMessage: PropTypes.string.description('Aria message for Max length message when exceeded').defaultValue(defaultComposerPros.maxLengthMessage),
|
|
23
25
|
maxLengthMessage: PropTypes.string.description('Max length message').defaultValue(defaultComposerPros.maxLengthMessage),
|
|
24
26
|
onChange: PropTypes.func.description('Called when the user types').defaultValue(defaultComposerPros.onChange),
|
|
25
27
|
onResize: PropTypes.func.description('Called the input changes his height').defaultValue(defaultComposerPros.onResize),
|
|
@@ -24,7 +24,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
24
24
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
25
25
|
|
|
26
26
|
const ChatContainer = props => {
|
|
27
|
-
var _containerRef$current;
|
|
27
|
+
var _messagesListProps$me2, _containerRef$current;
|
|
28
28
|
|
|
29
29
|
useValidateProps(props, containerProps);
|
|
30
30
|
const {
|
|
@@ -55,18 +55,16 @@ const ChatContainer = props => {
|
|
|
55
55
|
});
|
|
56
56
|
const onResize = React.useCallback(height => {
|
|
57
57
|
if (onComposerResize) onComposerResize(height);
|
|
58
|
-
|
|
59
|
-
if (height > 30) {
|
|
60
|
-
/*
|
|
58
|
+
/*
|
|
61
59
|
setTimeout is used to equal the animation duration from the
|
|
62
60
|
composer text area when increase its size
|
|
63
61
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
}
|
|
62
|
+
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
actionRef.current.scrollToIndex(messagesListProps.messages.length - 1, {
|
|
65
|
+
align: 'start'
|
|
66
|
+
});
|
|
67
|
+
}, 50);
|
|
70
68
|
}, [onComposerResize, messagesListProps.messages, actionRef]);
|
|
71
69
|
const Container = device === 'desktop' ? StyledChatContainerContent : MobileStyledChatContainerContent;
|
|
72
70
|
const handleTabs = React.useCallback(e => {
|
|
@@ -74,7 +72,9 @@ const ChatContainer = props => {
|
|
|
74
72
|
const ref = actionRef || listRef;
|
|
75
73
|
|
|
76
74
|
if (e.shiftKey && e.key === 'Tab') {
|
|
77
|
-
|
|
75
|
+
var _messagesListProps$me;
|
|
76
|
+
|
|
77
|
+
if (((_messagesListProps$me = messagesListProps.messages) === null || _messagesListProps$me === void 0 ? void 0 : _messagesListProps$me.length) > 0) {
|
|
78
78
|
e.preventDefault();
|
|
79
79
|
|
|
80
80
|
if (['top', 'bottom'].includes(bannerPosition)) {
|
|
@@ -88,7 +88,7 @@ const ChatContainer = props => {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
}, [actionRef, onComposerKeyDown, bannerPosition, messagesListProps.messages.length]); // Map actions
|
|
91
|
+
}, [actionRef, onComposerKeyDown, bannerPosition, (_messagesListProps$me2 = messagesListProps.messages) === null || _messagesListProps$me2 === void 0 ? void 0 : _messagesListProps$me2.length]); // Map actions
|
|
92
92
|
|
|
93
93
|
React.useEffect(() => {
|
|
94
94
|
if (actionRef && actionRef.current) {
|
|
@@ -10,7 +10,7 @@ const StyledChatContainerContent = /*#__PURE__*/styled(Grid).withConfig({
|
|
|
10
10
|
})(["height:100%;min-width:", "px;overflow:hidden;background:", ";position:relative;"], CONTAINER_WIDTH, props => props.theme.colors.neutral['050']);
|
|
11
11
|
const StyledIndicatorContainer = /*#__PURE__*/styled.div.withConfig({
|
|
12
12
|
componentId: "sc-d732wo-1"
|
|
13
|
-
})(["transition:0.4s ease-in-out;position:absolute;visibility:hidden;pointer-events:none;width:100%;padding:0 ", ";left:0;right:0;background:", ";", " ", " & div,a{font-size:13px;}"], props => !props.linear ? props.theme.space.xxs : 0, props => props.theme.colors.neutral['000'], props => props.isLoading === 'top' ? "\n top: -41px;\n transform: translate(0, 41px);\n visibility: visible;\n pointer-events: auto
|
|
13
|
+
})(["transition:0.4s ease-in-out;position:absolute;visibility:hidden;pointer-events:none;width:100%;padding:0 ", ";left:0;right:0;background:", ";", " ", " & div,a{font-size:13px;}"], props => !props.linear ? props.theme.space.xxs : 0, props => props.theme.colors.neutral['000'], props => props.isLoading === 'top' ? "\n top: -41px;\n transform: translate(0, 41px);\n visibility: visible;\n pointer-events: auto;\n " : '', props => props.isLoading === 'bottom' ? "\n bottom: -41px;\n transform: translate(0, -41px);\n visibility: visible;\n pointer-events: auto;\n " : '');
|
|
14
14
|
const MobileStyledChatContainerContent = /*#__PURE__*/styled(StyledChatContainerContent).withConfig({
|
|
15
15
|
componentId: "sc-d732wo-2"
|
|
16
16
|
})(["", ",", "{font-size:16px;}", "{font-size:13px;}", "{background-color:#fff;box-shadow:-0 1px 3px rgba(53,60,70,0.8);}", ",", "{font-size:16px;text-align:left;}", "{font-size:13px;}", "{font-size:16px;}", "{font-size:16px;}"], StyledTitleLeftBubble, StyleBodyWrapper, StyledTitleRightBubble, Wrapper, Title, Message, Time, StyledComposerInput, StyledIndicatorContainer);
|
|
@@ -22,7 +22,6 @@ import { MessageDelimiter } from '../message-delimiter/MessageDelimiter.js';
|
|
|
22
22
|
import { SystemMessage } from '../system-message/SystemMessage.js';
|
|
23
23
|
import { ListItem, StyledWrapperListItem, StyledWrapper, StyledChatContainerContentList, StyledChatContainerContentListScroll, StyledLoadMoreContainer } from './styled.js';
|
|
24
24
|
import { listProps, defaultProps } from './props.js';
|
|
25
|
-
import { useValidateProps } from './config/useValidateProps.js';
|
|
26
25
|
import { jsx } from 'react/jsx-runtime';
|
|
27
26
|
|
|
28
27
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
@@ -44,7 +43,6 @@ const getPadding = _ref => {
|
|
|
44
43
|
};
|
|
45
44
|
|
|
46
45
|
const ChatContainerMessagesList = props => {
|
|
47
|
-
useValidateProps(props, listProps);
|
|
48
46
|
const {
|
|
49
47
|
sendingText,
|
|
50
48
|
bannerPosition,
|
|
@@ -85,6 +83,7 @@ const ChatContainerMessagesList = props => {
|
|
|
85
83
|
return [];
|
|
86
84
|
}
|
|
87
85
|
|
|
86
|
+
if (!virtualListRef.current) return [];
|
|
88
87
|
pendingOnScroll.current = false;
|
|
89
88
|
const {
|
|
90
89
|
bottom,
|
|
@@ -127,6 +126,7 @@ const ChatContainerMessagesList = props => {
|
|
|
127
126
|
};
|
|
128
127
|
|
|
129
128
|
actionRef.current.getMessagesInView = onScrollStop;
|
|
129
|
+
onScrollStop(); // init useMemo due to debounce use.
|
|
130
130
|
|
|
131
131
|
actionRef.current.focusToIndex = function (a) {
|
|
132
132
|
let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
@@ -192,12 +192,7 @@ const ChatContainerMessagesList = props => {
|
|
|
192
192
|
|
|
193
193
|
e.preventDefault();
|
|
194
194
|
(_loadMoreRef$current2 = loadMoreRef.current) === null || _loadMoreRef$current2 === void 0 ? void 0 : _loadMoreRef$current2.focus();
|
|
195
|
-
} else if (hasMoreItems === 'top' && e.shiftKey) {
|
|
196
|
-
var _loadMoreRef$current3;
|
|
197
|
-
|
|
198
|
-
e.preventDefault();
|
|
199
|
-
(_loadMoreRef$current3 = loadMoreRef.current) === null || _loadMoreRef$current3 === void 0 ? void 0 : _loadMoreRef$current3.focus();
|
|
200
|
-
} else if (!e.shiftKey) {
|
|
195
|
+
} else if (hasMoreItems === 'top' && e.shiftKey) ; else if (!e.shiftKey) {
|
|
201
196
|
if (bannerPosition) {
|
|
202
197
|
e.preventDefault();
|
|
203
198
|
bannerRef.current.focusOnWrapper();
|
|
@@ -211,7 +206,7 @@ const ChatContainerMessagesList = props => {
|
|
|
211
206
|
|
|
212
207
|
break;
|
|
213
208
|
}
|
|
214
|
-
}, [
|
|
209
|
+
}, [bannerRef, hasMoreItems, messages.length, bannerPosition, scrollAndFocus]);
|
|
215
210
|
const handleListKey = React.useCallback(e => {
|
|
216
211
|
const {
|
|
217
212
|
key
|
|
@@ -221,9 +216,7 @@ const ChatContainerMessagesList = props => {
|
|
|
221
216
|
case 'ArrowUp':
|
|
222
217
|
e.preventDefault();
|
|
223
218
|
|
|
224
|
-
if (document.activeElement
|
|
225
|
-
scrollAndFocus(messages.length - 1);
|
|
226
|
-
} else {
|
|
219
|
+
if (document.activeElement !== loadMoreRef.current) {
|
|
227
220
|
onlyFocus(onScrollStop().shift());
|
|
228
221
|
}
|
|
229
222
|
|
|
@@ -253,15 +246,15 @@ const ChatContainerMessagesList = props => {
|
|
|
253
246
|
case 'Tab':
|
|
254
247
|
if (document.activeElement !== loadMoreRef.current) {
|
|
255
248
|
if (hasMoreItems === 'bottom' && !e.shiftKey) {
|
|
256
|
-
var _loadMoreRef$
|
|
249
|
+
var _loadMoreRef$current3;
|
|
257
250
|
|
|
258
251
|
e.preventDefault();
|
|
259
|
-
(_loadMoreRef$
|
|
252
|
+
(_loadMoreRef$current3 = loadMoreRef.current) === null || _loadMoreRef$current3 === void 0 ? void 0 : _loadMoreRef$current3.focus();
|
|
260
253
|
} else if (hasMoreItems === 'top' && e.shiftKey) {
|
|
261
|
-
var _loadMoreRef$
|
|
254
|
+
var _loadMoreRef$current4;
|
|
262
255
|
|
|
263
256
|
e.preventDefault();
|
|
264
|
-
(_loadMoreRef$
|
|
257
|
+
(_loadMoreRef$current4 = loadMoreRef.current) === null || _loadMoreRef$current4 === void 0 ? void 0 : _loadMoreRef$current4.focus();
|
|
265
258
|
} else if (!e.shiftKey) {
|
|
266
259
|
e.preventDefault();
|
|
267
260
|
actionRef.current.focusToComposer();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elliemae/ds-chat",
|
|
3
|
-
"version": "2.1.0-rc.
|
|
3
|
+
"version": "2.1.0-rc.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "ICE MT - Dimsum - Chat",
|
|
6
6
|
"module": "./esm/index.js",
|
|
@@ -305,15 +305,15 @@
|
|
|
305
305
|
"generateSubmodules": true
|
|
306
306
|
},
|
|
307
307
|
"dependencies": {
|
|
308
|
-
"@elliemae/ds-banner": "2.1.0-rc.
|
|
309
|
-
"@elliemae/ds-button": "2.1.0-rc.
|
|
310
|
-
"@elliemae/ds-grid": "2.1.0-rc.
|
|
311
|
-
"@elliemae/ds-icons": "2.1.0-rc.
|
|
312
|
-
"@elliemae/ds-indeterminate-progress-indicator": "2.1.0-rc.
|
|
313
|
-
"@elliemae/ds-props-helpers": "2.1.0-rc.
|
|
314
|
-
"@elliemae/ds-system": "2.1.0-rc.
|
|
315
|
-
"@elliemae/ds-tooltip": "2.1.0-rc.
|
|
316
|
-
"@elliemae/ds-truncated-tooltip-text": "2.1.0-rc.
|
|
308
|
+
"@elliemae/ds-banner": "2.1.0-rc.10",
|
|
309
|
+
"@elliemae/ds-button": "2.1.0-rc.10",
|
|
310
|
+
"@elliemae/ds-grid": "2.1.0-rc.10",
|
|
311
|
+
"@elliemae/ds-icons": "2.1.0-rc.10",
|
|
312
|
+
"@elliemae/ds-indeterminate-progress-indicator": "2.1.0-rc.10",
|
|
313
|
+
"@elliemae/ds-props-helpers": "2.1.0-rc.10",
|
|
314
|
+
"@elliemae/ds-system": "2.1.0-rc.10",
|
|
315
|
+
"@elliemae/ds-tooltip": "2.1.0-rc.10",
|
|
316
|
+
"@elliemae/ds-truncated-tooltip-text": "2.1.0-rc.10",
|
|
317
317
|
"prop-types": "~15.7.2",
|
|
318
318
|
"react-desc": "~4.1.2",
|
|
319
319
|
"react-virtual": "~2.3.2"
|
|
@@ -10,6 +10,9 @@ declare const ChatComposer: {
|
|
|
10
10
|
inputValue: {
|
|
11
11
|
deprecated: import("react-desc").PropTypesDescValidator;
|
|
12
12
|
};
|
|
13
|
+
ariaMaxLengthMessage: {
|
|
14
|
+
deprecated: import("react-desc").PropTypesDescValidator;
|
|
15
|
+
};
|
|
13
16
|
maxLengthMessage: {
|
|
14
17
|
deprecated: import("react-desc").PropTypesDescValidator;
|
|
15
18
|
};
|
package/types/tests/utils.d.ts
CHANGED
|
@@ -1,27 +1 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
dsId: string;
|
|
3
|
-
body: string;
|
|
4
|
-
type: string;
|
|
5
|
-
title: string;
|
|
6
|
-
time: string;
|
|
7
|
-
extraProps?: undefined;
|
|
8
|
-
helpMessage?: undefined;
|
|
9
|
-
} | {
|
|
10
|
-
dsId: string;
|
|
11
|
-
type: string;
|
|
12
|
-
title: string;
|
|
13
|
-
extraProps: {
|
|
14
|
-
'data-testid': string;
|
|
15
|
-
};
|
|
16
|
-
body?: undefined;
|
|
17
|
-
time?: undefined;
|
|
18
|
-
helpMessage?: undefined;
|
|
19
|
-
} | {
|
|
20
|
-
dsId: string;
|
|
21
|
-
body: string;
|
|
22
|
-
type: string;
|
|
23
|
-
title: string;
|
|
24
|
-
time: string;
|
|
25
|
-
helpMessage: string | null;
|
|
26
|
-
extraProps?: undefined;
|
|
27
|
-
})[];
|
|
1
|
+
export declare const loadMsgs: (q: number) => unknown;
|