@elliemae/ds-chat 2.0.0-alpha.1 → 2.0.0-alpha.13

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 (168) hide show
  1. package/cjs/ChatDataTestids.js +27 -0
  2. package/cjs/index.js +1 -0
  3. package/cjs/parts/bubble/ChatBubble.js +33 -20
  4. package/cjs/parts/bubble/ChatBubbleArrow.js +64 -61
  5. package/cjs/parts/bubble/config/useValidateProps.js +31 -0
  6. package/cjs/parts/bubble/index.js +1 -0
  7. package/cjs/parts/bubble/props.js +5 -5
  8. package/cjs/parts/bubble/styled.js +12 -41
  9. package/cjs/parts/chat-card/ChatCard.js +26 -20
  10. package/cjs/parts/chat-card/config/useValidateProps.js +11 -0
  11. package/cjs/parts/chat-card/props.js +3 -3
  12. package/cjs/parts/chat-card/styled.js +6 -6
  13. package/cjs/parts/chat-composer/ChatContainerComposer.js +50 -25
  14. package/cjs/parts/chat-composer/config/useValidateProps.js +11 -0
  15. package/cjs/parts/chat-composer/props.js +10 -4
  16. package/cjs/parts/chat-composer/styled.js +8 -8
  17. package/cjs/parts/chat-container/ChatContainer.js +79 -29
  18. package/cjs/parts/chat-container/config/useValidateProps.js +11 -0
  19. package/cjs/parts/chat-container/props.js +12 -7
  20. package/cjs/parts/chat-container/styled.js +5 -5
  21. package/cjs/parts/chat-container-header/ChatContainerHeader.js +7 -7
  22. package/cjs/parts/chat-container-header/helpers.js +31 -0
  23. package/cjs/parts/chat-container-header/styled.js +6 -6
  24. package/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +214 -34
  25. package/cjs/parts/chat-container-messages-list/config/useValidateProps.js +11 -0
  26. package/cjs/parts/chat-container-messages-list/props.js +6 -10
  27. package/cjs/parts/chat-container-messages-list/styled.js +11 -14
  28. package/cjs/parts/chat-empty-state/ChatEmptyState.js +22 -12
  29. package/cjs/parts/chat-empty-state/config/useValidateProps.js +11 -0
  30. package/cjs/parts/chat-empty-state/props.js +2 -1
  31. package/cjs/parts/chat-empty-state/styled.js +2 -2
  32. package/cjs/parts/chat-sidebar/SideBarChat.js +70 -36
  33. package/cjs/parts/chat-sidebar/config/useValidateProps.js +11 -0
  34. package/cjs/parts/chat-sidebar/props.js +11 -1
  35. package/cjs/parts/chat-sidebar/styled.js +4 -4
  36. package/cjs/parts/floating-button/FloatingButton.js +18 -10
  37. package/cjs/parts/floating-button/props.js +6 -2
  38. package/cjs/parts/floating-button/styled.js +1 -1
  39. package/cjs/parts/floating-container/styled.js +1 -1
  40. package/cjs/parts/grid-influencer/InfluencerContainer.js +2 -2
  41. package/cjs/parts/grid-influencer/styled.js +4 -8
  42. package/cjs/parts/message-delimiter/MessageDelimiter.js +18 -12
  43. package/cjs/parts/message-delimiter/config/useValidateProps.js +11 -0
  44. package/cjs/parts/message-delimiter/props.js +1 -1
  45. package/cjs/parts/message-delimiter/styled.js +4 -4
  46. package/cjs/parts/sidebar-button/SidebarButton.js +12 -7
  47. package/cjs/parts/sidebar-button/props.js +3 -4
  48. package/cjs/parts/sidebar-button/styled.js +4 -4
  49. package/cjs/parts/system-message/SystemMessage.js +21 -15
  50. package/cjs/parts/system-message/config/useValidateProps.js +11 -0
  51. package/cjs/parts/system-message/style.js +6 -6
  52. package/cjs/parts/tile-button/TileButton.js +40 -34
  53. package/cjs/parts/tile-button/config/useValidateProps.js +11 -0
  54. package/cjs/parts/tile-button/props.js +15 -13
  55. package/cjs/parts/tile-button/styled.js +22 -15
  56. package/cjs/styled.js +1 -1
  57. package/esm/ChatDataTestids.js +23 -0
  58. package/esm/index.js +1 -1
  59. package/esm/parts/bubble/ChatBubble.js +24 -12
  60. package/esm/parts/bubble/ChatBubbleArrow.js +64 -61
  61. package/esm/parts/bubble/config/useValidateProps.js +27 -0
  62. package/esm/parts/bubble/index.js +1 -1
  63. package/esm/parts/bubble/props.js +4 -4
  64. package/esm/parts/bubble/styled.js +3 -32
  65. package/esm/parts/chat-card/ChatCard.js +26 -20
  66. package/esm/parts/chat-card/config/useValidateProps.js +7 -0
  67. package/esm/parts/chat-card/props.js +3 -3
  68. package/esm/parts/chat-composer/ChatContainerComposer.js +33 -7
  69. package/esm/parts/chat-composer/config/useValidateProps.js +7 -0
  70. package/esm/parts/chat-composer/props.js +10 -4
  71. package/esm/parts/chat-composer/styled.js +2 -2
  72. package/esm/parts/chat-container/ChatContainer.js +68 -18
  73. package/esm/parts/chat-container/config/useValidateProps.js +7 -0
  74. package/esm/parts/chat-container/props.js +12 -7
  75. package/esm/parts/chat-container/styled.js +2 -2
  76. package/esm/parts/chat-container-header/ChatContainerHeader.js +3 -2
  77. package/esm/parts/chat-container-header/helpers.js +23 -0
  78. package/esm/parts/chat-container-header/styled.js +6 -6
  79. package/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +202 -22
  80. package/esm/parts/chat-container-messages-list/config/useValidateProps.js +7 -0
  81. package/esm/parts/chat-container-messages-list/props.js +6 -10
  82. package/esm/parts/chat-container-messages-list/styled.js +6 -10
  83. package/esm/parts/chat-empty-state/ChatEmptyState.js +16 -6
  84. package/esm/parts/chat-empty-state/config/useValidateProps.js +7 -0
  85. package/esm/parts/chat-empty-state/props.js +2 -1
  86. package/esm/parts/chat-sidebar/SideBarChat.js +69 -34
  87. package/esm/parts/chat-sidebar/config/useValidateProps.js +7 -0
  88. package/esm/parts/chat-sidebar/props.js +11 -1
  89. package/esm/parts/chat-sidebar/styled.js +2 -2
  90. package/esm/parts/floating-button/FloatingButton.js +18 -9
  91. package/esm/parts/floating-button/props.js +6 -2
  92. package/esm/parts/grid-influencer/styled.js +2 -6
  93. package/esm/parts/message-delimiter/MessageDelimiter.js +18 -12
  94. package/esm/parts/message-delimiter/config/useValidateProps.js +7 -0
  95. package/esm/parts/message-delimiter/props.js +1 -1
  96. package/esm/parts/message-delimiter/styled.js +1 -1
  97. package/esm/parts/sidebar-button/SidebarButton.js +6 -1
  98. package/esm/parts/sidebar-button/props.js +1 -1
  99. package/esm/parts/sidebar-button/styled.js +1 -1
  100. package/esm/parts/system-message/SystemMessage.js +21 -15
  101. package/esm/parts/system-message/config/useValidateProps.js +7 -0
  102. package/esm/parts/system-message/style.js +1 -1
  103. package/esm/parts/tile-button/TileButton.js +35 -27
  104. package/esm/parts/tile-button/config/useValidateProps.js +7 -0
  105. package/esm/parts/tile-button/props.js +14 -7
  106. package/esm/parts/tile-button/styled.js +15 -10
  107. package/esm/styled.js +1 -1
  108. package/package.json +69 -6
  109. package/types/ChatDataTestids.d.ts +21 -0
  110. package/types/index.d.ts +1 -1
  111. package/types/parts/bubble/ChatBubble.d.ts +20 -5
  112. package/types/parts/bubble/config/useValidateProps.d.ts +2 -0
  113. package/types/parts/bubble/index.d.ts +1 -1
  114. package/types/parts/bubble/props.d.ts +13 -4
  115. package/types/parts/bubble/styled.d.ts +9 -9
  116. package/types/parts/bubble/tests/ChatBubble.test.d.ts +1 -0
  117. package/types/parts/chat-card/ChatCard.d.ts +25 -5
  118. package/types/parts/chat-card/config/useValidateProps.d.ts +2 -0
  119. package/types/parts/chat-card/props.d.ts +19 -3
  120. package/types/parts/chat-card/styled.d.ts +6 -6
  121. package/types/parts/chat-composer/ChatContainerComposer.d.ts +48 -12
  122. package/types/parts/chat-composer/config/useValidateProps.d.ts +2 -0
  123. package/types/parts/chat-composer/styled.d.ts +117 -24
  124. package/types/parts/chat-composer/tests/ChatContainerComposer.test.d.ts +1 -0
  125. package/types/parts/chat-container/ChatContainer.d.ts +54 -12
  126. package/types/parts/chat-container/config/useValidateProps.d.ts +2 -0
  127. package/types/parts/chat-container/styled.d.ts +4 -4
  128. package/types/parts/chat-container/tests/ChatContainer.test.d.ts +1 -0
  129. package/types/parts/chat-container-header/helpers.d.ts +6 -0
  130. package/types/parts/chat-container-header/styled.d.ts +3 -3
  131. package/types/parts/chat-container-messages-list/ChatContainerMessagesList.d.ts +39 -9
  132. package/types/parts/chat-container-messages-list/config/useValidateProps.d.ts +2 -0
  133. package/types/parts/chat-container-messages-list/styled.d.ts +7 -6
  134. package/types/parts/chat-empty-state/ChatEmptyState.d.ts +19 -1
  135. package/types/parts/chat-empty-state/config/useValidateProps.d.ts +2 -0
  136. package/types/parts/chat-empty-state/props.d.ts +7 -1
  137. package/types/parts/chat-empty-state/styled.d.ts +2 -2
  138. package/types/parts/chat-sidebar/SideBarChat.d.ts +40 -10
  139. package/types/parts/chat-sidebar/config/useValidateProps.d.ts +2 -0
  140. package/types/parts/chat-sidebar/props.d.ts +39 -9
  141. package/types/parts/chat-sidebar/styled.d.ts +2 -2
  142. package/types/parts/floating-button/FloatingButton.d.ts +11 -2
  143. package/types/parts/floating-button/props.d.ts +13 -1
  144. package/types/parts/floating-button/styled.d.ts +1 -1
  145. package/types/parts/floating-container/styled.d.ts +1 -2
  146. package/types/parts/grid-influencer/styled.d.ts +2 -2
  147. package/types/parts/message-delimiter/MessageDelimiter.d.ts +22 -5
  148. package/types/parts/message-delimiter/config/useValidateProps.d.ts +2 -0
  149. package/types/parts/message-delimiter/props.d.ts +16 -3
  150. package/types/parts/message-delimiter/styled.d.ts +3 -3
  151. package/types/parts/sidebar-button/SidebarButton.d.ts +16 -5
  152. package/types/parts/sidebar-button/props.d.ts +16 -5
  153. package/types/parts/sidebar-button/styled.d.ts +3 -3
  154. package/types/parts/system-message/SystemMessage.d.ts +13 -3
  155. package/types/parts/system-message/config/useValidateProps.d.ts +2 -0
  156. package/types/parts/system-message/props.d.ts +7 -1
  157. package/types/parts/system-message/style.d.ts +5 -5
  158. package/types/parts/tile-button/TileButton.d.ts +66 -17
  159. package/types/parts/tile-button/config/useValidateProps.d.ts +2 -0
  160. package/types/parts/tile-button/props.d.ts +64 -16
  161. package/types/parts/tile-button/styled.d.ts +9 -8
  162. package/types/prop-types.d.ts +28 -9
  163. package/types/tests/utils.d.ts +27 -0
  164. package/cjs/package.json +0 -4
  165. package/esm/package.json +0 -4
  166. package/types/parts/chat-composer/props.d.ts +0 -32
  167. package/types/parts/chat-container/props.d.ts +0 -38
  168. package/types/parts/chat-container-messages-list/props.d.ts +0 -31
@@ -1,41 +1,62 @@
1
+ import 'core-js/modules/esnext.async-iterator.filter.js';
2
+ import 'core-js/modules/esnext.iterator.filter.js';
1
3
  import _jsx from '@babel/runtime/helpers/esm/jsx';
2
4
  import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
5
+ import 'core-js/modules/esnext.async-iterator.some.js';
6
+ import 'core-js/modules/esnext.iterator.constructor.js';
7
+ import 'core-js/modules/esnext.iterator.some.js';
8
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
9
+ import 'core-js/modules/esnext.iterator.for-each.js';
10
+ import 'core-js/modules/esnext.async-iterator.map.js';
11
+ import 'core-js/modules/esnext.iterator.map.js';
12
+ import 'core-js/modules/esnext.async-iterator.find.js';
13
+ import 'core-js/modules/esnext.iterator.find.js';
3
14
  import React from 'react';
4
15
  import { describe } from 'react-desc';
5
16
  import { useVirtual } from 'react-virtual';
6
- import DSButton from '@elliemae/ds-basic/Button';
17
+ import DSButton from '@elliemae/ds-button';
7
18
  import { ChatBubble } from '../bubble/ChatBubble.js';
8
19
  import { BUBBLE_TYPES } from '../bubble/props.js';
9
20
  import { MessageDelimiter } from '../message-delimiter/MessageDelimiter.js';
10
21
  import { SystemMessage } from '../system-message/SystemMessage.js';
11
- import { StyledWrapperListItem, StyledWrapper, StyledChatContainerContentList, StyledChatContainerContentListScroll, StyledLoadMoreContainer } from './styled.js';
22
+ import { ListItem, StyledWrapperListItem, StyledWrapper, StyledChatContainerContentList, StyledChatContainerContentListScroll, StyledLoadMoreContainer } from './styled.js';
12
23
  import { listProps, defaultProps } from './props.js';
24
+ import { useValidateProps } from './config/useValidateProps.js';
13
25
  import { jsx } from 'react/jsx-runtime';
14
26
 
15
27
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
16
28
 
17
29
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
18
30
 
19
- const getPadding = hasMoreItems => {
31
+ const getPadding = _ref => {
32
+ let {
33
+ hasMoreItems,
34
+ bannerPosition,
35
+ isLoading
36
+ } = _ref;
20
37
  const padding = {
21
38
  paddingStart: 0,
22
39
  paddingEnd: -5
23
40
  };
24
- if (hasMoreItems === 'top') padding.paddingStart = 42;else if (hasMoreItems === 'bottom') padding.paddingEnd = 42;
41
+ if ([hasMoreItems, bannerPosition, isLoading].some(item => item === 'top')) padding.paddingStart = 42;else if ([hasMoreItems, bannerPosition, isLoading].some(item => item === 'bottom')) padding.paddingEnd = 42;
25
42
  return padding;
26
43
  };
27
44
 
28
45
  const ChatContainerMessagesList = props => {
46
+ useValidateProps(props, listProps);
29
47
  const {
30
48
  sendingText,
49
+ bannerPosition,
31
50
  sendingMessages,
32
51
  messages,
33
52
  actionRef,
34
53
  onScrollEnds,
35
54
  getMoreMessages,
36
55
  hasMoreItems,
37
- isLoading
56
+ isLoading,
57
+ bannerRef
38
58
  } = props;
59
+ const loadMoreRef = React.useRef(null);
39
60
  const virtualListRef = React.useRef(); // estimateSize should not be really required given what was stated on
40
61
  // https://github.com/tannerlinsley/react-virtual/issues/23
41
62
 
@@ -47,33 +68,185 @@ const ChatContainerMessagesList = props => {
47
68
  size: messages.length,
48
69
  parentRef: virtualListRef,
49
70
  overscan: 15
50
- }, getPadding(hasMoreItems)), {}, {
71
+ }, getPadding({
72
+ hasMoreItems,
73
+ bannerPosition,
74
+ isLoading
75
+ })), {}, {
51
76
  estimateSize: React.useCallback(() => 80, [])
52
77
  }));
53
78
  const onScrollStop = React.useCallback(() => {
79
+ var _virtualListRef$curre;
80
+
54
81
  const {
55
82
  bottom,
56
83
  top
57
- } = virtualListRef.current.getBoundingClientRect();
84
+ } = (_virtualListRef$curre = virtualListRef.current) === null || _virtualListRef$curre === void 0 ? void 0 : _virtualListRef$curre.getBoundingClientRect();
58
85
  const list = virtualListRef.current.querySelectorAll('[data-element="chat-element-list-item"]');
59
86
  const indexList = [];
60
87
  list.forEach(item => {
61
88
  const {
62
- top: itemTop
89
+ top: itemTop,
90
+ bottom: itemBottom
63
91
  } = item.getBoundingClientRect();
64
- if (itemTop < bottom && itemTop > top) indexList.push(item.dataset.index);
92
+ const itemPadding = 10;
93
+ if (itemTop + itemPadding < bottom && itemBottom - itemPadding > top) indexList.push(item.dataset.index);
65
94
  });
66
95
  if (onScrollEnds) onScrollEnds(indexList);
67
96
  return indexList;
68
97
  }, [onScrollEnds]);
69
- React.useImperativeHandle(actionRef, () => ({
70
- scrollToIndex: (a, b = {
98
+ const onlyFocus = React.useCallback(index => {
99
+ setTimeout(() => {
100
+ virtualListRef.current.querySelector("[data-index=\"".concat(index, "\"]")).focus();
101
+ }, 300);
102
+ }, []);
103
+ const scrollAndFocus = React.useCallback(function (index) {
104
+ let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
71
105
  align: 'center'
72
- }) => {
73
- vScroll(a, b);
74
- },
75
- getMessagesInView: onScrollStop
76
- }));
106
+ };
107
+ vScroll(index, b);
108
+ onlyFocus(index);
109
+ }, [onlyFocus, vScroll]);
110
+ React.useEffect(() => {
111
+ if (actionRef && actionRef.current) {
112
+ actionRef.current.scrollToIndex = function (a) {
113
+ let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
114
+ align: 'center'
115
+ };
116
+ vScroll(a, b);
117
+ };
118
+
119
+ actionRef.current.getMessagesInView = onScrollStop;
120
+
121
+ actionRef.current.focusToIndex = function (a) {
122
+ let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
123
+ align: 'center'
124
+ };
125
+ scrollAndFocus(a, b);
126
+ };
127
+
128
+ actionRef.current.focusToIndexWithoutScroll = onlyFocus;
129
+
130
+ actionRef.current.focusToList = a => {
131
+ var _virtualListRef$curre2;
132
+
133
+ (_virtualListRef$curre2 = virtualListRef.current) === null || _virtualListRef$curre2 === void 0 ? void 0 : _virtualListRef$curre2.focus();
134
+ };
135
+ }
136
+ }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll]);
137
+ const handleKey = React.useCallback(e => {
138
+ const {
139
+ key
140
+ } = e;
141
+ const index = Number(e.currentTarget.dataset.index);
142
+ e.stopPropagation();
143
+
144
+ switch (key) {
145
+ case 'ArrowUp':
146
+ e.preventDefault();
147
+ if (index > 0) virtualListRef.current.querySelector("[data-index=\"".concat(index - 1, "\"]")).focus();
148
+ break;
149
+
150
+ case 'ArrowDown':
151
+ e.preventDefault();
152
+
153
+ if (index < messages.length - 1) {
154
+ virtualListRef.current.querySelector("[data-index=\"".concat(index + 1, "\"]")).focus();
155
+ }
156
+
157
+ break;
158
+
159
+ case 'Home':
160
+ e.preventDefault();
161
+ scrollAndFocus(0);
162
+ break;
163
+
164
+ case 'End':
165
+ e.preventDefault();
166
+ scrollAndFocus(messages.length - 1);
167
+ break;
168
+
169
+ case 'Tab':
170
+ e.preventDefault();
171
+
172
+ if (hasMoreItems === 'bottom' && !e.shiftKey) {
173
+ var _loadMoreRef$current;
174
+
175
+ (_loadMoreRef$current = loadMoreRef.current) === null || _loadMoreRef$current === void 0 ? void 0 : _loadMoreRef$current.focus();
176
+ } else if (hasMoreItems === 'top' && e.shiftKey) {
177
+ var _loadMoreRef$current2;
178
+
179
+ (_loadMoreRef$current2 = loadMoreRef.current) === null || _loadMoreRef$current2 === void 0 ? void 0 : _loadMoreRef$current2.focus();
180
+ } else if (!e.shiftKey) {
181
+ if (bannerPosition) {
182
+ bannerRef.current.focusOnWrapper();
183
+ } else {
184
+ actionRef.current.focusToComposer();
185
+ }
186
+ } else {
187
+ var _virtualListRef$curre3;
188
+
189
+ (_virtualListRef$curre3 = virtualListRef.current) === null || _virtualListRef$curre3 === void 0 ? void 0 : _virtualListRef$curre3.focus();
190
+ }
191
+
192
+ break;
193
+ }
194
+ }, [actionRef, hasMoreItems, messages.length, bannerPosition, scrollAndFocus]);
195
+ const handleListKey = React.useCallback(e => {
196
+ const {
197
+ key
198
+ } = e;
199
+
200
+ switch (key) {
201
+ case 'ArrowUp':
202
+ e.preventDefault();
203
+ onlyFocus(onScrollStop().shift());
204
+ break;
205
+
206
+ case 'ArrowDown':
207
+ e.preventDefault();
208
+ onlyFocus(onScrollStop().pop());
209
+ break;
210
+
211
+ case 'Home':
212
+ e.preventDefault();
213
+ scrollAndFocus(0);
214
+ break;
215
+
216
+ case 'End':
217
+ e.preventDefault();
218
+ scrollAndFocus(messages.length - 1);
219
+ break;
220
+
221
+ case 'Tab':
222
+ if (document.activeElement !== loadMoreRef.current) {
223
+ if (hasMoreItems === 'bottom' && !e.shiftKey) {
224
+ var _loadMoreRef$current3;
225
+
226
+ e.preventDefault();
227
+ (_loadMoreRef$current3 = loadMoreRef.current) === null || _loadMoreRef$current3 === void 0 ? void 0 : _loadMoreRef$current3.focus();
228
+ } else if (hasMoreItems === 'top' && e.shiftKey) {
229
+ var _loadMoreRef$current4;
230
+
231
+ e.preventDefault();
232
+ (_loadMoreRef$current4 = loadMoreRef.current) === null || _loadMoreRef$current4 === void 0 ? void 0 : _loadMoreRef$current4.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
+ var _virtualListRef$curre4;
242
+
243
+ e.preventDefault();
244
+ (_virtualListRef$curre4 = virtualListRef.current) === null || _virtualListRef$curre4 === void 0 ? void 0 : _virtualListRef$curre4.focus();
245
+ }
246
+
247
+ break;
248
+ }
249
+ }, [actionRef, hasMoreItems, messages.length, onScrollStop, onlyFocus, scrollAndFocus]);
77
250
  React.useEffect(() => {
78
251
  let handlerCallback = null;
79
252
  const localVirtualRef = virtualListRef.current;
@@ -104,14 +277,17 @@ const ChatContainerMessagesList = props => {
104
277
  position: 'absolute',
105
278
  top: 0,
106
279
  left: 0,
107
- transform: `translateY(${start}px)`,
280
+ transform: "translateY(".concat(start, "px)"),
108
281
  width: '100%'
109
282
  };
110
- return /*#__PURE__*/jsx("div", {
283
+ return /*#__PURE__*/jsx(ListItem, {
111
284
  "data-element": "chat-element-list-item",
112
285
  "data-index": index,
113
286
  style: style,
114
287
  ref: measureRef,
288
+ tabIndex: 0,
289
+ onKeyDown: handleKey,
290
+ role: "listitem",
115
291
  children: /*#__PURE__*/_jsx(StyledWrapperListItem, {
116
292
  type: row.type
117
293
  }, void 0, row.type === BUBBLE_TYPES.SENDER || row.type === BUBBLE_TYPES.RECIPIENT ?
@@ -120,21 +296,25 @@ const ChatContainerMessagesList = props => {
120
296
  jsx(ChatBubble, _objectSpread(_objectSpread({}, row), {}, {
121
297
  helpMessage: isSending ? sendingText : row.helpMessage
122
298
  })) : null, row.type === BUBBLE_TYPES.DELIMITER ? /*#__PURE__*/jsx(MessageDelimiter, _objectSpread({}, row)) : null, row.type === BUBBLE_TYPES.SYSTEM ? /*#__PURE__*/jsx(SystemMessage, _objectSpread({}, row)) : null)
123
- }, `ds-chat-bubble-${index}`);
124
- }), [virtualItems, messages, sendingMessages]);
299
+ }, "ds-chat-bubble-".concat(index, "-").concat(row.dsId, "-").concat(row.type));
300
+ }), [virtualItems, messages, sendingMessages, handleKey, sendingText]);
125
301
  return /*#__PURE__*/_jsx(StyledWrapper, {}, void 0, /*#__PURE__*/jsx(StyledChatContainerContentList, {
126
302
  "data-testid": "chat-thread-container",
127
303
  tabIndex: 0,
128
304
  "aria-live": "polite",
129
305
  ref: virtualListRef,
306
+ role: "list",
307
+ onKeyDown: handleListKey,
130
308
  children: /*#__PURE__*/_jsx(StyledChatContainerContentListScroll, {
131
- height: `${totalSize}px`
309
+ height: "".concat(totalSize, "px")
132
310
  }, void 0, render, !isLoading && hasMoreItems ? /*#__PURE__*/_jsx(StyledLoadMoreContainer, {
133
311
  hasMoreItems: hasMoreItems
134
312
  }, void 0, /*#__PURE__*/_jsx(DSButton, {
135
313
  labelText: "Load More",
136
314
  buttonType: "secondary",
137
- onClick: getMoreMessages
315
+ onClick: getMoreMessages,
316
+ "data-testid": "ds-chat-load-more-btn",
317
+ innerRef: loadMoreRef
138
318
  })) : null)
139
319
  }));
140
320
  };
@@ -0,0 +1,7 @@
1
+ import { useValidateTypescriptPropTypes } from '@elliemae/ds-props-helpers';
2
+
3
+ const useValidateProps = (props, propTypes) => {
4
+ useValidateTypescriptPropTypes(props, propTypes);
5
+ };
6
+
7
+ export { useValidateProps };
@@ -7,22 +7,18 @@ const defaultProps = {
7
7
  onScrollEnds: () => [],
8
8
  getMoreMessages: noop,
9
9
  sendingMessages: undefined,
10
- sendingText: 'Sending'
10
+ sendingText: 'Sending',
11
+ bannerPosition: undefined,
12
+ bannerRef: undefined
11
13
  };
12
14
  const listProps = {
13
15
  messages: PropTypes.arrayOf(PropTypes.object).description('The array of out-of-the-box items you want to render inside the ChatMessageList').defaultValue(defaultProps.messages),
14
- actionRef: PropTypes.func.description(`Reference:
15
- {
16
- scrollToIndex: (n: number) => void,
17
- getMessagesInView: () => number[],
18
- }
19
-
20
- `).defaultValue(defaultProps.messages),
21
- onScrollEnds: PropTypes.func.description(`Called when the scroll stops.`),
16
+ actionRef: PropTypes.object.description("Reference: \n { \n scrollToIndex: (n: number) => void,\n getMessagesInView: () => number[],\n focusToIndex: (n: number) => void,\n focusToIndexWithoutScroll: (n: number) => void,\n focusToList: () => void,\n focusToComposer: () => void,\n focusToSend: () => void,\n }\n \n ").defaultValue(defaultProps.actionRef),
17
+ onScrollEnds: PropTypes.func.description("Called when the scroll stops."),
22
18
  isLoading: PropTypes.oneOf(['top', 'bottom', undefined]).description('Keeps the load more space while the loading is in progress'),
23
19
  hasMoreItems: PropTypes.oneOf(['top', 'bottom', undefined]).description('Show Load More button at the `top` or `bottom` of the container'),
24
20
  getMoreMessages: PropTypes.func.description('Called when the user clicks on load more').defaultValue(defaultProps.getMoreMessages),
25
- sendingMessages: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])).description('Array of ids of sending messages').defaultValue(defaultProps.sendingMessages),
21
+ sendingMessages: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.arrayOf(PropTypes.number)]).description('Array of ids of sending messages').defaultValue(defaultProps.sendingMessages),
26
22
  sendingText: PropTypes.string.description('Label description for messages in sending status').defaultValue(defaultProps.sendingText)
27
23
  };
28
24
 
@@ -1,8 +1,5 @@
1
1
  import styled from 'styled-components';
2
- import '@babel/runtime/helpers/esm/jsx';
3
- import 'react';
4
- import '@elliemae/ds-icons/WarningCircleFill';
5
- import '@elliemae/ds-grid';
2
+ import '../bubble/ChatBubble.js';
6
3
  import { BUBBLE_TYPES } from '../bubble/props.js';
7
4
 
8
5
  const StyledWrapper = /*#__PURE__*/styled.div.withConfig({
@@ -11,11 +8,7 @@ const StyledWrapper = /*#__PURE__*/styled.div.withConfig({
11
8
 
12
9
  const StyledWrapperListItem = /*#__PURE__*/styled.div.withConfig({
13
10
  componentId: "sc-1jhprzr-1"
14
- })(["min-width:100%;", ";", ";", ";"], props => props.type === BUBBLE_TYPES.SENDER && `padding: ${props.theme.space.xxs} ${props.theme.space.xxs} 0px 13%
15
- `, props => props.type === BUBBLE_TYPES.RECIPIENT && `padding: ${props.theme.space.xxs} 13% ${props.theme.space.xxs}
16
- ${props.theme.space.xxs}
17
- `, props => props.type === BUBBLE_TYPES.SYSTEM && `padding: ${props.theme.space.xxs} 0px
18
- `);
11
+ })(["min-width:100%;", ";", ";", ";"], props => props.type === BUBBLE_TYPES.SENDER && "padding: ".concat(props.theme.space.xxs, " ").concat(props.theme.space.xxs, " ").concat(props.theme.space.xxs, " 13%\n "), props => props.type === BUBBLE_TYPES.RECIPIENT && "padding: ".concat(props.theme.space.xxs, " 13% ").concat(props.theme.space.xxs, "\n ").concat(props.theme.space.xxs, "\n "), props => props.type === BUBBLE_TYPES.SYSTEM && "padding: ".concat(props.theme.space.xxs, " 0px\n "));
19
12
  const StyledChatContainerContentList = /*#__PURE__*/styled.div.withConfig({
20
13
  componentId: "sc-1jhprzr-2"
21
14
  })(["width:100%;height:100%;padding:", ";padding-bottom:0;overflow-y:auto;overflow-x:hidden;"], props => props.theme.space.xs);
@@ -25,5 +18,8 @@ const StyledChatContainerContentListScroll = /*#__PURE__*/styled.div.withConfig(
25
18
  const StyledLoadMoreContainer = /*#__PURE__*/styled.div.withConfig({
26
19
  componentId: "sc-1jhprzr-4"
27
20
  })(["position:absolute;width:calc(100% + ", ");padding:", ";left:-", ";right:-", ";display:grid;justify-content:center;align-items:center;", " ", ""], props => props.theme.space.xxs, props => props.theme.space.xxs, props => props.theme.space.xxs, props => props.theme.space.xxs, props => props.hasMoreItems === 'top' ? 'top: 0;' : '', props => props.hasMoreItems === 'bottom' ? 'bottom: 0;' : '');
21
+ const ListItem = /*#__PURE__*/styled.div.withConfig({
22
+ componentId: "sc-1jhprzr-5"
23
+ })(["&:focus,&:focus-visible{outline:none;&:after{content:'';display:block;position:absolute;top:0;left:-", ";pointer-events:none;border-radius:2px;background-color:#ebedf0;width:calc(100% + 24px);border:2px solid #1e79c2;height:100%;z-index:-1;}}"], props => props.theme.space.xxs);
28
24
 
29
- export { StyledChatContainerContentList, StyledChatContainerContentListScroll, StyledLoadMoreContainer, StyledWrapper, StyledWrapperListItem };
25
+ export { ListItem, StyledChatContainerContentList, StyledChatContainerContentListScroll, StyledLoadMoreContainer, StyledWrapper, StyledWrapperListItem };
@@ -1,15 +1,21 @@
1
1
  import _jsx from '@babel/runtime/helpers/esm/jsx';
2
+ import 'core-js/modules/web.url.to-json.js';
2
3
  import { useMemo } from 'react';
4
+ import { describe } from 'react-desc';
3
5
  import { Grid } from '@elliemae/ds-grid';
4
- import Communications from '@elliemae/ds-icons/Communications';
6
+ import { Communications } from '@elliemae/ds-icons';
7
+ import { emptyStateProps, defaultProps } from './props.js';
5
8
  import { MessageWrapper, ChatEmptyStateWrapper } from './styled.js';
9
+ import { useValidateProps } from './config/useValidateProps.js';
6
10
 
7
- const ChatEmptyState = ({
8
- label,
9
- action
10
- }) => {
11
+ const ChatEmptyState = props => {
11
12
  var _Grid, _Grid2;
12
13
 
14
+ useValidateProps(props, ChatEmptyStateListWithSchema.toJSON());
15
+ const {
16
+ label,
17
+ action
18
+ } = props;
13
19
  const MainContent = useMemo(() => /*#__PURE__*/_jsx(Grid, {
14
20
  alignItems: "center",
15
21
  justifyContent: "center"
@@ -32,4 +38,8 @@ const ChatEmptyState = ({
32
38
  }, void 0, MainContent);
33
39
  };
34
40
 
35
- export { ChatEmptyState };
41
+ ChatEmptyState.defaultProps = defaultProps;
42
+ const ChatEmptyStateListWithSchema = describe(ChatEmptyState);
43
+ ChatEmptyStateListWithSchema.propTypes = emptyStateProps;
44
+
45
+ export { ChatEmptyState, ChatEmptyStateListWithSchema };
@@ -0,0 +1,7 @@
1
+ import { useValidatePropTypes } from '@elliemae/ds-props-helpers';
2
+
3
+ const useValidateProps = (props, schema) => {
4
+ useValidatePropTypes(props, schema);
5
+ };
6
+
7
+ export { useValidateProps };
@@ -5,7 +5,8 @@ const defaultProps = {
5
5
  action: null
6
6
  };
7
7
  const emptyStateProps = {
8
- label: PropTypes.arrayOf(PropTypes.string).description('No Message to show text helper').defaultValue(defaultProps.label)
8
+ label: PropTypes.arrayOf(PropTypes.string).description('No Message to show text helper').defaultValue(defaultProps.label),
9
+ action: PropTypes.node.description('action element').defaultValue(defaultProps.action)
9
10
  };
10
11
 
11
12
  export { defaultProps, emptyStateProps };
@@ -1,50 +1,85 @@
1
1
  import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
2
2
  import _jsx from '@babel/runtime/helpers/esm/jsx';
3
- import 'react';
3
+ import 'core-js/modules/web.url.to-json.js';
4
+ import 'core-js/modules/esnext.async-iterator.map.js';
5
+ import 'core-js/modules/esnext.iterator.map.js';
6
+ import 'core-js/modules/esnext.async-iterator.filter.js';
7
+ import 'core-js/modules/esnext.iterator.constructor.js';
8
+ import 'core-js/modules/esnext.iterator.filter.js';
9
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
10
+ import 'core-js/modules/esnext.iterator.for-each.js';
11
+ import React from 'react';
4
12
  import { describe } from 'react-desc';
5
- import MenuExpand from '@elliemae/ds-icons/MenuExpand';
6
- import MenuCollapse from '@elliemae/ds-icons/MenuCollapse';
13
+ import { MenuCollapse, MenuExpand } from '@elliemae/ds-icons';
7
14
  import { StyledSideBarContainer, StyledSideBarButtonsContainer } from './styled.js';
8
15
  import { TileButton } from '../tile-button/TileButton.js';
9
16
  import { SidebarButton } from '../sidebar-button/SidebarButton.js';
10
17
  import { chatSidebarProps, defaultProps } from './props.js';
11
- import { jsx } from 'react/jsx-runtime';
18
+ import { useValidateProps } from './config/useValidateProps.js';
19
+ import { jsxs, jsx } from 'react/jsx-runtime';
12
20
 
13
21
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
14
22
 
15
23
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
16
24
 
17
- const FooterChat = ({
18
- expanded,
19
- onFooterClose,
20
- onFooterExpand,
21
- footerButtonExtraProps
22
- }) => /*#__PURE__*/_jsx(SidebarButton, {
23
- dsId: "sidebar_footer",
24
- label: null,
25
- Icon: !expanded ? MenuCollapse : MenuExpand,
26
- onClick: expanded ? onFooterClose : onFooterExpand,
27
- "aria-pressed": expanded,
28
- "aria-label": footerButtonExtraProps['aria-label']
29
- });
25
+ const FooterChat = _ref => {
26
+ let {
27
+ expanded,
28
+ onFooterClose,
29
+ onFooterExpand,
30
+ footerButtonExtraProps
31
+ } = _ref;
32
+ return /*#__PURE__*/_jsx(SidebarButton, {
33
+ dsId: "sidebar_footer",
34
+ label: null,
35
+ Icon: !expanded ? MenuCollapse : MenuExpand,
36
+ onClick: expanded ? onFooterClose : onFooterExpand,
37
+ "aria-pressed": expanded,
38
+ "aria-label": footerButtonExtraProps['aria-label']
39
+ });
40
+ };
30
41
 
31
- const SideBarChat = ({
32
- sidebarItems,
33
- expanded,
34
- onFooterClose,
35
- onFooterExpand,
36
- selectedItem,
37
- footerButtonExtraProps
38
- }) => /*#__PURE__*/_jsx(StyledSideBarContainer, {
39
- rows: [1, 'auto']
40
- }, void 0, /*#__PURE__*/_jsx(StyledSideBarButtonsContainer, {}, void 0, sidebarItems.map(p => /*#__PURE__*/jsx(TileButton, _objectSpread(_objectSpread({}, p), {}, {
41
- selected: selectedItem === p.dsId
42
- })))), /*#__PURE__*/_jsx(FooterChat, {
43
- expanded: expanded,
44
- onFooterClose: onFooterClose,
45
- onFooterExpand: onFooterExpand,
46
- footerButtonExtraProps: footerButtonExtraProps
47
- }));
42
+ const SideBarChat = props => {
43
+ useValidateProps(props, SideBarChatWithSchema.toJSON());
44
+ const {
45
+ sidebarItems,
46
+ expanded,
47
+ onFooterClose,
48
+ onFooterExpand,
49
+ selectedItem,
50
+ footerButtonExtraProps,
51
+ tooltipPlacement,
52
+ enableTooltipWhenIsClosed,
53
+ actionRef
54
+ } = props;
55
+ const {
56
+ current: listRef
57
+ } = React.useRef({});
58
+ const registerReference = React.useCallback(ref => {
59
+ if (ref) listRef[ref.dataset.key] = ref;
60
+ }, [listRef]);
61
+ React.useEffect(() => {
62
+ if (actionRef.current.listRef) {
63
+ actionRef.current.listRef = listRef;
64
+ }
65
+ }, [sidebarItems, expanded, actionRef, listRef]);
66
+ return /*#__PURE__*/jsxs(StyledSideBarContainer, {
67
+ rows: [1, 'auto'],
68
+ ref: listRef,
69
+ children: [/*#__PURE__*/_jsx(StyledSideBarButtonsContainer, {}, void 0, sidebarItems.map(p => /*#__PURE__*/jsx(TileButton, _objectSpread(_objectSpread({
70
+ innerRef: registerReference
71
+ }, p), {}, {
72
+ selected: selectedItem === p.dsId,
73
+ tooltipPlacement: tooltipPlacement,
74
+ disableTooltip: enableTooltipWhenIsClosed ? false : !expanded
75
+ }), p.dsId))), /*#__PURE__*/_jsx(FooterChat, {
76
+ expanded: expanded,
77
+ onFooterClose: onFooterClose,
78
+ onFooterExpand: onFooterExpand,
79
+ footerButtonExtraProps: footerButtonExtraProps
80
+ })]
81
+ });
82
+ };
48
83
 
49
84
  SideBarChat.defaultProps = defaultProps;
50
85
  const SideBarChatWithSchema = describe(SideBarChat);
@@ -0,0 +1,7 @@
1
+ import { useValidatePropTypes } from '@elliemae/ds-props-helpers';
2
+
3
+ const useValidateProps = (props, schema) => {
4
+ useValidatePropTypes(props, schema);
5
+ };
6
+
7
+ export { useValidateProps };
@@ -11,17 +11,27 @@ const defaultProps = {
11
11
  onHeaderClose: noop,
12
12
  footerButtonExtraProps: {
13
13
  'aria-label': 'expand or collapse button'
14
+ },
15
+ tooltipPlacement: 'right',
16
+ enableTooltipWhenIsClosed: false,
17
+ actionRef: {
18
+ current: {
19
+ listRef: []
20
+ }
14
21
  }
15
22
  };
16
23
  const chatSidebarProps = {
17
24
  sidebarItems: PropTypes.arrayOf(PropTypes.object).description('The array of out-of-the-box items you want to render inside the sidebar nav of the chat').defaultValue(defaultProps.sidebarItems),
18
25
  expanded: PropTypes.bool.description('Whether to show the chat expanded or collapsed').defaultValue(defaultProps.expanded),
19
26
  selectedItem: PropTypes.string.description('The id of the chat item you want to be opened').defaultValue(defaultProps.selectedItem),
27
+ tooltipPlacement: PropTypes.oneOf(['top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']).description('start placement preferences, as per popperjs placement option').defaultValue("'right'"),
28
+ enableTooltipWhenIsClosed: PropTypes.bool.description('Enable tooltip when is closed').defaultValue(defaultProps.onFooterExpand),
20
29
  onFooterExpand: PropTypes.func.description('The function to call when the chat is opened via the footer').defaultValue(defaultProps.onFooterExpand),
21
30
  onFooterClose: PropTypes.func.description('The function to call when the chat is closed via the footer').defaultValue(defaultProps.onFooterClose),
22
31
  onHeaderExpand: PropTypes.func.description('The function to call when the chat is opened via the header').defaultValue(defaultProps.onHeaderExpand),
23
32
  onHeaderClose: PropTypes.func.description('The function to call when the chat is closed via the header').defaultValue(defaultProps.onHeaderClose),
24
- footerButtonExtraProps: PropTypes.object.description('Expand/collapse footer button extra props').defaultValue(defaultProps.footerButtonExtraProps)
33
+ footerButtonExtraProps: PropTypes.object.description('Expand/collapse footer button extra props').defaultValue(defaultProps.footerButtonExtraProps),
34
+ actionRef: PropTypes.object.description("Action ref for sidebar\n {\n listRef: references to Tiles\n }\n ").defaultValue(defaultProps.actionRef)
25
35
  };
26
36
 
27
37
  export { chatSidebarProps, defaultProps };
@@ -4,9 +4,9 @@ import { MIN_WIDTH_SIDEBAR, BUTTON_SIDEBAR_HEIGHT } from '../../styled.js';
4
4
 
5
5
  const StyledSideBarContainer = /*#__PURE__*/styled(Grid).withConfig({
6
6
  componentId: "sc-16uijso-0"
7
- })(["height:100%;width:", "px;background:", ";border-right:1px solid ", ";"], MIN_WIDTH_SIDEBAR, props => props.theme.colors.neutral['050'], props => props.theme.colors.neutral['100']);
7
+ })(["height:100%;width:", "px;background:", ";border-right:1px solid ", ";overflow:hidden;"], MIN_WIDTH_SIDEBAR, props => props.theme.colors.neutral['050'], props => props.theme.colors.neutral['100']);
8
8
  const StyledSideBarButtonsContainer = /*#__PURE__*/styled(Grid).withConfig({
9
9
  componentId: "sc-16uijso-1"
10
- })(["overflow-y:auto;align-items:flex-start;justify-content:flex-start;grid-template-rows:repeat(auto-fill,", "px);"], BUTTON_SIDEBAR_HEIGHT);
10
+ })(["overflow-y:auto;align-items:flex-start;justify-content:flex-start;grid-template-rows:repeat(auto-fill,", "px);overflow-x:hidden;scrollbar-width:thin;&::-webkit-scrollbar{width:6px;}"], BUTTON_SIDEBAR_HEIGHT);
11
11
 
12
12
  export { StyledSideBarButtonsContainer, StyledSideBarContainer };
@@ -1,18 +1,27 @@
1
1
  import _jsx from '@babel/runtime/helpers/esm/jsx';
2
2
  import 'react';
3
- import Comments from '@elliemae/ds-icons/Comments';
3
+ import { Comments } from '@elliemae/ds-icons';
4
4
  import { StyledFloatingButton } from './styled.js';
5
5
  import { defaultFloatingButton } from './props.js';
6
+ import { jsx } from 'react/jsx-runtime';
6
7
 
7
8
  var _Comments;
8
- const FloatingButton = ({
9
- onClick
10
- }) => /*#__PURE__*/_jsx(StyledFloatingButton, {
11
- "data-testid": "chat-floating-button",
12
- onClick: onClick
13
- }, void 0, _Comments || (_Comments = /*#__PURE__*/_jsx(Comments, {
14
- size: "l"
15
- })));
9
+ const FloatingButton = _ref => {
10
+ let {
11
+ onClick,
12
+ onFocus,
13
+ innerRef
14
+ } = _ref;
15
+ return /*#__PURE__*/jsx(StyledFloatingButton, {
16
+ onFocus: onFocus,
17
+ ref: innerRef,
18
+ "data-testid": "chat-floating-button",
19
+ onClick: onClick,
20
+ children: _Comments || (_Comments = /*#__PURE__*/_jsx(Comments, {
21
+ size: "l"
22
+ }))
23
+ });
24
+ };
16
25
  FloatingButton.defaultProps = defaultFloatingButton;
17
26
 
18
27
  export { FloatingButton };