@elliemae/ds-chat 2.0.0-alpha.10 → 2.0.0-alpha.14

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 (123) hide show
  1. package/cjs/ChatDataTestids.js +27 -0
  2. package/cjs/parts/bubble/ChatBubble.js +15 -12
  3. package/cjs/parts/bubble/ChatBubbleArrow.js +64 -61
  4. package/cjs/parts/bubble/config/useValidateProps.js +5 -6
  5. package/cjs/parts/bubble/props.js +1 -1
  6. package/cjs/parts/bubble/styled.js +2 -31
  7. package/cjs/parts/chat-card/props.js +2 -2
  8. package/cjs/parts/chat-composer/ChatContainerComposer.js +16 -8
  9. package/cjs/parts/chat-composer/props.js +5 -11
  10. package/cjs/parts/chat-composer/styled.js +4 -4
  11. package/cjs/parts/chat-container/ChatContainer.js +67 -20
  12. package/cjs/parts/chat-container/config/useValidateProps.js +2 -2
  13. package/cjs/parts/chat-container/props.js +7 -13
  14. package/cjs/parts/chat-container/styled.js +2 -2
  15. package/cjs/parts/chat-container-header/ChatContainerHeader.js +3 -3
  16. package/cjs/parts/chat-container-header/helpers.js +31 -0
  17. package/cjs/parts/chat-container-header/styled.js +6 -6
  18. package/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +156 -40
  19. package/cjs/parts/chat-container-messages-list/config/useValidateProps.js +2 -2
  20. package/cjs/parts/chat-container-messages-list/props.js +5 -13
  21. package/cjs/parts/chat-container-messages-list/styled.js +2 -6
  22. package/cjs/parts/chat-empty-state/ChatEmptyState.js +2 -3
  23. package/cjs/parts/chat-sidebar/SideBarChat.js +57 -29
  24. package/cjs/parts/chat-sidebar/props.js +11 -1
  25. package/cjs/parts/chat-sidebar/styled.js +2 -2
  26. package/cjs/parts/floating-button/FloatingButton.js +18 -10
  27. package/cjs/parts/floating-button/props.js +6 -2
  28. package/cjs/parts/grid-influencer/styled.js +2 -6
  29. package/cjs/parts/message-delimiter/styled.js +1 -1
  30. package/cjs/parts/sidebar-button/SidebarButton.js +6 -1
  31. package/cjs/parts/sidebar-button/props.js +2 -3
  32. package/cjs/parts/system-message/style.js +1 -1
  33. package/cjs/parts/tile-button/TileButton.js +31 -28
  34. package/cjs/parts/tile-button/props.js +12 -8
  35. package/cjs/parts/tile-button/styled.js +12 -5
  36. package/cjs/styled.js +1 -1
  37. package/esm/ChatDataTestids.js +23 -0
  38. package/esm/parts/bubble/ChatBubble.js +14 -11
  39. package/esm/parts/bubble/ChatBubbleArrow.js +64 -61
  40. package/esm/parts/bubble/config/useValidateProps.js +5 -6
  41. package/esm/parts/bubble/props.js +1 -1
  42. package/esm/parts/bubble/styled.js +2 -31
  43. package/esm/parts/chat-card/props.js +2 -2
  44. package/esm/parts/chat-composer/ChatContainerComposer.js +15 -6
  45. package/esm/parts/chat-composer/props.js +5 -11
  46. package/esm/parts/chat-composer/styled.js +2 -2
  47. package/esm/parts/chat-container/ChatContainer.js +65 -18
  48. package/esm/parts/chat-container/config/useValidateProps.js +2 -2
  49. package/esm/parts/chat-container/props.js +7 -13
  50. package/esm/parts/chat-container/styled.js +2 -2
  51. package/esm/parts/chat-container-header/ChatContainerHeader.js +3 -2
  52. package/esm/parts/chat-container-header/helpers.js +23 -0
  53. package/esm/parts/chat-container-header/styled.js +6 -6
  54. package/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +154 -38
  55. package/esm/parts/chat-container-messages-list/config/useValidateProps.js +2 -2
  56. package/esm/parts/chat-container-messages-list/props.js +5 -13
  57. package/esm/parts/chat-container-messages-list/styled.js +2 -6
  58. package/esm/parts/chat-empty-state/ChatEmptyState.js +1 -1
  59. package/esm/parts/chat-sidebar/SideBarChat.js +57 -28
  60. package/esm/parts/chat-sidebar/props.js +11 -1
  61. package/esm/parts/chat-sidebar/styled.js +2 -2
  62. package/esm/parts/floating-button/FloatingButton.js +18 -9
  63. package/esm/parts/floating-button/props.js +6 -2
  64. package/esm/parts/grid-influencer/styled.js +2 -6
  65. package/esm/parts/message-delimiter/styled.js +1 -1
  66. package/esm/parts/sidebar-button/SidebarButton.js +6 -1
  67. package/esm/parts/sidebar-button/props.js +1 -1
  68. package/esm/parts/system-message/style.js +1 -1
  69. package/esm/parts/tile-button/TileButton.js +32 -27
  70. package/esm/parts/tile-button/props.js +11 -3
  71. package/esm/parts/tile-button/styled.js +12 -7
  72. package/esm/styled.js +1 -1
  73. package/package.json +29 -6
  74. package/types/ChatDataTestids.d.ts +21 -0
  75. package/types/parts/bubble/ChatBubble.d.ts +18 -5
  76. package/types/parts/bubble/props.d.ts +13 -4
  77. package/types/parts/bubble/styled.d.ts +9 -9
  78. package/types/parts/bubble/tests/ChatBubble.test.d.ts +1 -0
  79. package/types/parts/chat-card/ChatCard.d.ts +24 -4
  80. package/types/parts/chat-card/props.d.ts +19 -3
  81. package/types/parts/chat-card/styled.d.ts +6 -6
  82. package/types/parts/chat-composer/ChatContainerComposer.d.ts +48 -13
  83. package/types/parts/chat-composer/styled.d.ts +117 -24
  84. package/types/parts/chat-composer/tests/ChatContainerComposer.test.d.ts +1 -0
  85. package/types/parts/chat-container/ChatContainer.d.ts +54 -13
  86. package/types/parts/chat-container/config/useValidateProps.d.ts +1 -1
  87. package/types/parts/chat-container/styled.d.ts +4 -4
  88. package/types/parts/chat-container/tests/ChatContainer.test.d.ts +1 -0
  89. package/types/parts/chat-container-header/helpers.d.ts +6 -0
  90. package/types/parts/chat-container-header/styled.d.ts +3 -3
  91. package/types/parts/chat-container-messages-list/ChatContainerMessagesList.d.ts +39 -9
  92. package/types/parts/chat-container-messages-list/config/useValidateProps.d.ts +1 -1
  93. package/types/parts/chat-container-messages-list/styled.d.ts +7 -7
  94. package/types/parts/chat-empty-state/ChatEmptyState.d.ts +12 -3
  95. package/types/parts/chat-empty-state/props.d.ts +7 -2
  96. package/types/parts/chat-empty-state/styled.d.ts +2 -2
  97. package/types/parts/chat-sidebar/SideBarChat.d.ts +39 -9
  98. package/types/parts/chat-sidebar/props.d.ts +39 -9
  99. package/types/parts/chat-sidebar/styled.d.ts +2 -2
  100. package/types/parts/floating-button/FloatingButton.d.ts +11 -2
  101. package/types/parts/floating-button/props.d.ts +13 -1
  102. package/types/parts/floating-button/styled.d.ts +1 -1
  103. package/types/parts/floating-container/styled.d.ts +1 -2
  104. package/types/parts/grid-influencer/styled.d.ts +2 -2
  105. package/types/parts/message-delimiter/MessageDelimiter.d.ts +21 -4
  106. package/types/parts/message-delimiter/props.d.ts +16 -3
  107. package/types/parts/message-delimiter/styled.d.ts +3 -3
  108. package/types/parts/sidebar-button/SidebarButton.d.ts +16 -5
  109. package/types/parts/sidebar-button/props.d.ts +16 -5
  110. package/types/parts/sidebar-button/styled.d.ts +3 -3
  111. package/types/parts/system-message/SystemMessage.d.ts +12 -2
  112. package/types/parts/system-message/props.d.ts +7 -1
  113. package/types/parts/system-message/style.d.ts +5 -5
  114. package/types/parts/tile-button/TileButton.d.ts +66 -17
  115. package/types/parts/tile-button/props.d.ts +64 -16
  116. package/types/parts/tile-button/styled.d.ts +9 -8
  117. package/types/prop-types.d.ts +28 -9
  118. package/types/tests/utils.d.ts +27 -0
  119. package/cjs/package.json +0 -4
  120. package/esm/package.json +0 -4
  121. package/types/parts/chat-composer/props.d.ts +0 -35
  122. package/types/parts/chat-container/props.d.ts +0 -39
  123. package/types/parts/chat-container-messages-list/props.d.ts +0 -23
@@ -2,12 +2,17 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ require('core-js/modules/esnext.async-iterator.filter.js');
6
+ require('core-js/modules/esnext.iterator.constructor.js');
7
+ require('core-js/modules/esnext.iterator.filter.js');
8
+ require('core-js/modules/esnext.async-iterator.for-each.js');
9
+ require('core-js/modules/esnext.iterator.for-each.js');
5
10
  var _jsx = require('@babel/runtime/helpers/jsx');
6
11
  var _defineProperty = require('@babel/runtime/helpers/defineProperty');
7
12
  var React = require('react');
8
13
  var lodash = require('lodash');
9
14
  var reactDesc = require('react-desc');
10
- var DSIndeterminateProgressIndicator = require('@elliemae/ds-basic/IndeterminateProgressIndicator');
15
+ var DSIndeterminateProgressIndicator = require('@elliemae/ds-indeterminate-progress-indicator');
11
16
  var DSBanner = require('@elliemae/ds-banner');
12
17
  var ChatContainerComposer = require('../chat-composer/ChatContainerComposer.js');
13
18
  var ChatContainerMessagesList = require('../chat-container-messages-list/ChatContainerMessagesList.js');
@@ -30,10 +35,10 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
30
35
 
31
36
  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__default["default"](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; }
32
37
 
33
- const ChatContainer = props => {
38
+ const ChatContainer = props$1 => {
34
39
  var _containerRef$current;
35
40
 
36
- useValidateProps.useValidateProps(props, ChatContainerWithSchema.toTypescript());
41
+ useValidateProps.useValidateProps(props$1, props.containerProps);
37
42
  const {
38
43
  sendingText,
39
44
  sendingMessages,
@@ -42,15 +47,20 @@ const ChatContainer = props => {
42
47
  messagesListProps,
43
48
  composerProps,
44
49
  composerProps: {
45
- onResize: onComposerResize
50
+ onResize: onComposerResize,
51
+ onKeyDown: onComposerKeyDown
46
52
  },
47
53
  actionRef,
48
- autoScroll,
49
54
  device,
50
55
  isLoading,
51
56
  hasMoreItems,
52
- getMoreMessages
53
- } = props;
57
+ getMoreMessages,
58
+ ariaLabel
59
+ } = props$1;
60
+ const bannerRef = React__default["default"].useRef({
61
+ focusOnWrapper: lodash.noop,
62
+ focusOnLink: lodash.noop
63
+ });
54
64
  const containerRef = React__default["default"].useRef();
55
65
  const listRef = React__default["default"].useRef({
56
66
  scrollToIndex: lodash.noop
@@ -58,21 +68,51 @@ const ChatContainer = props => {
58
68
  const onResize = React__default["default"].useCallback(height => {
59
69
  if (onComposerResize) onComposerResize(height);
60
70
 
61
- if (autoScroll) {
62
- listRef.current.scrollToIndex(messagesListProps.messages.length - 1, {
63
- align: 'end'
64
- });
71
+ if (height > 30) {
72
+ /*
73
+ setTimeout is used to equal the animation duration from the
74
+ composer text area when increase its size
75
+ */
76
+ setTimeout(() => {
77
+ actionRef.current.scrollToIndex(messagesListProps.messages.length - 1, {
78
+ align: 'start'
79
+ });
80
+ }, 50);
65
81
  }
66
- }, [onComposerResize, messagesListProps.messages, autoScroll]);
82
+ }, [onComposerResize, messagesListProps.messages, actionRef]);
67
83
  const Container = device === 'desktop' ? styled.StyledChatContainerContent : styled.MobileStyledChatContainerContent;
84
+ const handleTabs = React__default["default"].useCallback(e => {
85
+ if (onComposerKeyDown) onComposerKeyDown(e);else {
86
+ const ref = actionRef || listRef;
87
+
88
+ if (e.shiftKey && e.key === 'Tab') {
89
+ e.preventDefault();
90
+
91
+ if (['top', 'bottom'].includes(bannerPosition)) {
92
+ bannerRef.current.focusOnWrapper();
93
+ } else {
94
+ const last = ref.current.getMessagesInView().pop();
95
+ ref.current.focusToIndexWithoutScroll(last);
96
+ }
97
+ }
98
+ }
99
+ }, [actionRef, onComposerKeyDown, bannerPosition]); // Map actions
100
+
101
+ React__default["default"].useEffect(() => {
102
+ if (actionRef && actionRef.current) {
103
+ actionRef.current.focusOnBanner = bannerRef.current.focusOnWrapper;
104
+ actionRef.current.focusOnBannerLink = bannerRef.current.focusOnLink;
105
+ }
106
+ }, [actionRef]);
68
107
  return /*#__PURE__*/jsxRuntime.jsxs(Container, {
69
108
  rows: ['minmax(0, 1fr)', 'auto'],
70
109
  ref: containerRef,
71
110
  role: "region",
72
- "aria-label": "chat window",
111
+ "aria-label": ariaLabel,
73
112
  children: [/*#__PURE__*/_jsx__default["default"]("div", {
74
113
  style: {
75
- position: 'relative'
114
+ position: 'relative',
115
+ overflow: 'hidden'
76
116
  }
77
117
  }, void 0, /*#__PURE__*/jsxRuntime.jsx(ChatContainerMessagesList.ChatContainerMessagesList, _objectSpread(_objectSpread({}, messagesListProps), {}, {
78
118
  actionRef: actionRef || listRef,
@@ -80,13 +120,17 @@ const ChatContainer = props => {
80
120
  hasMoreItems: hasMoreItems,
81
121
  getMoreMessages: getMoreMessages,
82
122
  sendingMessages: sendingMessages,
83
- sendingText: sendingText
123
+ sendingText: sendingText,
124
+ bannerPosition: bannerPosition,
125
+ bannerRef: bannerRef
84
126
  })), ['top', 'bottom'].includes(isLoading) ? /*#__PURE__*/_jsx__default["default"](styled.StyledIndicatorContainer, {
85
- isLoading: isLoading
127
+ isLoading: isLoading,
128
+ "data-testid": "ds-chat-loading-indicator"
86
129
  }, void 0, _DSIndeterminateProgr || (_DSIndeterminateProgr = /*#__PURE__*/_jsx__default["default"](DSIndeterminateProgressIndicator__default["default"], {
87
130
  processing: true,
88
131
  title: "Loading"
89
- }))) : null, ['top', 'bottom'].includes(bannerPosition) ? /*#__PURE__*/_jsx__default["default"](styled.StyledIndicatorContainer, {
132
+ }))) : null, /*#__PURE__*/_jsx__default["default"](styled.StyledIndicatorContainer, {
133
+ linear: true,
90
134
  isLoading: bannerPosition
91
135
  }, void 0, /*#__PURE__*/_jsx__default["default"](DSBanner__default["default"], {
92
136
  showCloseButton: true,
@@ -100,15 +144,18 @@ const ChatContainer = props => {
100
144
  },
101
145
  onClose: bannerProps.onClose,
102
146
  isOpen: true,
103
- type: DSBanner.BANNER_TYPES.INFO
104
- })) : null, sendingMessages && sendingMessages.length > 0 ? _StyledIndicatorConta || (_StyledIndicatorConta = /*#__PURE__*/_jsx__default["default"](styled.StyledIndicatorContainer, {
147
+ type: bannerProps.type || DSBanner.BANNER_TYPES.INFO,
148
+ actionRef: bannerRef
149
+ })), sendingMessages && sendingMessages.length > 0 ? _StyledIndicatorConta || (_StyledIndicatorConta = /*#__PURE__*/_jsx__default["default"](styled.StyledIndicatorContainer, {
105
150
  isLoading: "bottom",
106
- linear: true
151
+ linear: true,
152
+ "data-testid": "ds-chat-loading-indicator"
107
153
  }, void 0, /*#__PURE__*/_jsx__default["default"](DSIndeterminateProgressIndicator__default["default"], {
108
154
  processing: true,
109
155
  title: "Loading",
110
156
  lineOnly: true
111
157
  }))) : null), /*#__PURE__*/jsxRuntime.jsx(ChatContainerComposer.ChatComposer, _objectSpread(_objectSpread({}, composerProps), {}, {
158
+ onKeyDown: handleTabs,
112
159
  onResize: onResize,
113
160
  maxHeight: (((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.clientHeight) || 0) / 2,
114
161
  actionRef: actionRef || listRef
@@ -4,8 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var dsPropsHelpers = require('@elliemae/ds-props-helpers');
6
6
 
7
- const useValidateProps = (props, schema) => {
8
- dsPropsHelpers.useValidateTypescriptPropTypes(props, schema);
7
+ const useValidateProps = (props, propTypes) => {
8
+ dsPropsHelpers.useValidateTypescriptPropTypes(props, propTypes);
9
9
  };
10
10
 
11
11
  exports.useValidateProps = useValidateProps;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var reactDesc = require('react-desc');
6
6
  var lodash = require('lodash');
7
+ var DSBanner = require('@elliemae/ds-banner');
7
8
  var props = require('../chat-container-messages-list/props.js');
8
9
  var props$1 = require('../chat-composer/props.js');
9
10
 
@@ -18,13 +19,15 @@ const defaultProps = {
18
19
  getMoreMessages: lodash.noop,
19
20
  bannerPosition: undefined,
20
21
  bannerProps: {
22
+ type: DSBanner.BANNER_TYPES.INFO,
21
23
  label: 'Unread Messages',
22
24
  viewLabel: 'View',
23
25
  onView: lodash.noop,
24
26
  onClose: lodash.noop
25
27
  },
26
28
  sendingMessages: undefined,
27
- sendingText: 'Sending'
29
+ sendingText: 'Sending',
30
+ ariaLabel: 'Chat window'
28
31
  };
29
32
  const containerProps = {
30
33
  messagesListProps: reactDesc.PropTypes.object.description('ChatMessageList props "messages" / "onScrollEnds"').defaultValue(defaultProps.messagesListProps),
@@ -35,20 +38,11 @@ const containerProps = {
35
38
  hasMoreItems: reactDesc.PropTypes.oneOf(['top', 'bottom', undefined]).description('Show Load More button at the `top` or `bottom` of the container'),
36
39
  getMoreMessages: reactDesc.PropTypes.func.description('Called when the user clicks on load more').defaultValue(defaultProps.getMoreMessages),
37
40
  bannerPosition: reactDesc.PropTypes.oneOf(['top', 'bottom', undefined]).description('Show Loading messages indicator at the `top` or `bottom` of the container'),
38
- bannerProps: reactDesc.PropTypes.object.description('Banner configuration').defaultValue(defaultProps.bannerProps),
41
+ bannerProps: reactDesc.PropTypes.object.description("Banner configuration:\n label: string;\n viewLabel: string;\n type: BANNER_TYPES;\n onView: () => void;\n onClose: () => void;\n ").defaultValue(defaultProps.bannerProps),
39
42
  sendingMessages: reactDesc.PropTypes.oneOfType([reactDesc.PropTypes.arrayOf(reactDesc.PropTypes.string), reactDesc.PropTypes.arrayOf(reactDesc.PropTypes.number)]).description('Array of ids of sending messages').defaultValue(defaultProps.sendingMessages),
40
43
  sendingText: reactDesc.PropTypes.string.description('Label description for messages in sending status').defaultValue(defaultProps.sendingText),
41
- actionRef: reactDesc.PropTypes.object.description(`Reference:
42
- {
43
- scrollToIndex: (n: number) => void,
44
- getMessagesInView: () => number[],
45
- focusToIndex: (n: number) => void,
46
- focusToList: () => void,
47
- focusToComposer: () => void,
48
- focusToSend: () => void,
49
- }
50
-
51
- `).defaultValue(defaultProps.actionRef)
44
+ actionRef: reactDesc.PropTypes.object.description("Reference: \n { \n scrollToIndex: (n: number) => void,\n getMessagesInView: () => number[],\n focusToIndex: (n: number) => void,\n focusToList: () => void,\n focusToComposer: () => void,\n focusToSend: () => void,\n }\n \n ").defaultValue(defaultProps.actionRef),
45
+ ariaLabel: reactDesc.PropTypes.string.description('Aria Label description for chat container').defaultValue(defaultProps.ariaLabel)
52
46
  };
53
47
 
54
48
  exports.containerProps = containerProps;
@@ -18,10 +18,10 @@ 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
- })(["position:absolute;width:calc(100% + ", ");padding:", ";left:-", ";right:-", ";background:", ";", " ", ""], props => props.theme.space.xxs, props => !props.linear ? props.theme.space.xxs : 0, props => props.theme.space.xxs, props => props.theme.space.xxs, props => props.theme.colors.neutral['000'], props => props.isLoading === 'top' ? 'top: 0;' : '', props => props.isLoading === 'bottom' ? 'bottom: 0;' : '');
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
- })(["", ",", "{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;}"], styled$1.StyledTitleLeftBubble, styled$1.StyleBodyWrapper, styled$1.StyledTitleRightBubble, style.Wrapper, style.Title, style.Message, style.Time, styled$2.StyledComposerInput);
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);
25
25
 
26
26
  exports.CONTAINER_WIDTH = CONTAINER_WIDTH;
27
27
  exports.MobileStyledChatContainerContent = MobileStyledChatContainerContent;
@@ -3,14 +3,14 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _jsx = require('@babel/runtime/helpers/jsx');
6
- var React = require('react');
6
+ require('react');
7
7
  var dsTruncatedTooltipText = require('@elliemae/ds-truncated-tooltip-text');
8
8
  var styled = require('./styled.js');
9
+ var helpers = require('./helpers.js');
9
10
 
10
11
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
12
 
12
13
  var _jsx__default = /*#__PURE__*/_interopDefaultLegacy(_jsx);
13
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
14
14
 
15
15
  const ChatContainerHeader = props => {
16
16
  const {
@@ -30,7 +30,7 @@ const ChatContainerHeader = props => {
30
30
  }, void 0, /*#__PURE__*/_jsx__default["default"](dsTruncatedTooltipText.SimpleTruncatedTooltipText, {
31
31
  value: title
32
32
  })), /*#__PURE__*/_jsx__default["default"](styled.StyledChatContainerContentHeaderActions, {
33
- cols: React__default["default"].Children.toArray(children).filter(e => e).map(() => '32px'),
33
+ cols: helpers.validHeaderChilds(children),
34
34
  justifyContent: "flex-end",
35
35
  "data-testid": "chat-container-header-children"
36
36
  }, void 0, children));
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ require('core-js/modules/esnext.async-iterator.map.js');
6
+ require('core-js/modules/esnext.iterator.map.js');
7
+ require('core-js/modules/esnext.async-iterator.filter.js');
8
+ require('core-js/modules/esnext.iterator.constructor.js');
9
+ require('core-js/modules/esnext.iterator.filter.js');
10
+ require('core-js/modules/esnext.async-iterator.constructor.js');
11
+ require('core-js/modules/esnext.async-iterator.to-array.js');
12
+ require('core-js/modules/esnext.iterator.to-array.js');
13
+ var React = require('react');
14
+
15
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
16
+
17
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
18
+
19
+ const validHeaderChilds = children => React__default["default"].Children.toArray(children).filter(e => {
20
+ if (Array.isArray(e.props.children)) {
21
+ return false;
22
+ }
23
+
24
+ if (e.props.children === undefined && e.$$typeof.toString() === 'Symbol(react.element)') {
25
+ return true;
26
+ }
27
+
28
+ return !!e.props.children;
29
+ }).map(() => '32px');
30
+
31
+ exports.validHeaderChilds = validHeaderChilds;
@@ -9,15 +9,15 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
9
9
 
10
10
  var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled);
11
11
 
12
- const StyledChatContainerContentHeader = /*#__PURE__*/styled__default["default"](dsGrid.Grid).withConfig({
12
+ const StyledChatContainerContentHeaderActions = /*#__PURE__*/styled__default["default"](dsGrid.Grid).withConfig({
13
13
  componentId: "sc-jmynvr-0"
14
- })(["width:100%;min-height:48px;border-bottom:1px solid ", ";background:", ";"], props => props.theme.colors.neutral['200'], props => props.theme.colors.neutral['050']);
15
- const StyledChatContainerContentHeaderLabel = /*#__PURE__*/styled__default["default"](dsGrid.Grid).withConfig({
14
+ })(["max-width:80px;"]);
15
+ const StyledChatContainerContentHeader = /*#__PURE__*/styled__default["default"](dsGrid.Grid).withConfig({
16
16
  componentId: "sc-jmynvr-1"
17
- })(["justify-content:center;align-items:center;font-weight:bold;font-size:18px;color:", ";"], props => props.theme.colors.neutral['700']);
18
- const StyledChatContainerContentHeaderActions = /*#__PURE__*/styled__default["default"](dsGrid.Grid).withConfig({
17
+ })(["width:100%;min-height:48px;border-bottom:1px solid ", ";background:", ";", "{& button{background:transparent;}}"], props => props.theme.colors.neutral['200'], props => props.theme.colors.neutral['050'], StyledChatContainerContentHeaderActions);
18
+ const StyledChatContainerContentHeaderLabel = /*#__PURE__*/styled__default["default"](dsGrid.Grid).withConfig({
19
19
  componentId: "sc-jmynvr-2"
20
- })(["max-width:80px;"]);
20
+ })(["justify-content:center;align-items:center;font-weight:bold;font-size:18px;color:", ";"], props => props.theme.colors.neutral['700']);
21
21
 
22
22
  exports.StyledChatContainerContentHeader = StyledChatContainerContentHeader;
23
23
  exports.StyledChatContainerContentHeaderActions = StyledChatContainerContentHeaderActions;
@@ -4,10 +4,21 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _jsx = require('@babel/runtime/helpers/jsx');
6
6
  var _defineProperty = require('@babel/runtime/helpers/defineProperty');
7
+ require('core-js/modules/esnext.async-iterator.some.js');
8
+ require('core-js/modules/esnext.iterator.constructor.js');
9
+ require('core-js/modules/esnext.iterator.some.js');
10
+ require('core-js/modules/esnext.async-iterator.for-each.js');
11
+ require('core-js/modules/esnext.iterator.for-each.js');
12
+ require('core-js/modules/esnext.async-iterator.map.js');
13
+ require('core-js/modules/esnext.iterator.map.js');
14
+ require('core-js/modules/esnext.async-iterator.find.js');
15
+ require('core-js/modules/esnext.iterator.find.js');
16
+ require('core-js/modules/esnext.async-iterator.filter.js');
17
+ require('core-js/modules/esnext.iterator.filter.js');
7
18
  var React = require('react');
8
19
  var reactDesc = require('react-desc');
9
20
  var reactVirtual = require('react-virtual');
10
- var DSButton = require('@elliemae/ds-basic/Button');
21
+ var DSButton = require('@elliemae/ds-button');
11
22
  var ChatBubble = require('../bubble/ChatBubble.js');
12
23
  var props$1 = require('../bubble/props.js');
13
24
  var MessageDelimiter = require('../message-delimiter/MessageDelimiter.js');
@@ -28,27 +39,35 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
28
39
 
29
40
  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__default["default"](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; }
30
41
 
31
- const getPadding = hasMoreItems => {
42
+ const getPadding = _ref => {
43
+ let {
44
+ hasMoreItems,
45
+ bannerPosition,
46
+ isLoading
47
+ } = _ref;
32
48
  const padding = {
33
49
  paddingStart: 0,
34
50
  paddingEnd: -5
35
51
  };
36
- if (hasMoreItems === 'top') padding.paddingStart = 42;else if (hasMoreItems === 'bottom') padding.paddingEnd = 42;
52
+ if ([hasMoreItems, bannerPosition, isLoading].some(item => item === 'top')) padding.paddingStart = 42;else if ([hasMoreItems, bannerPosition, isLoading].some(item => item === 'bottom')) padding.paddingEnd = 42;
37
53
  return padding;
38
54
  };
39
55
 
40
- const ChatContainerMessagesList = props => {
41
- useValidateProps.useValidateProps(props, ChatContainerMessagesListWithSchema.toTypescript());
56
+ const ChatContainerMessagesList = props$2 => {
57
+ useValidateProps.useValidateProps(props$2, props.listProps);
42
58
  const {
43
59
  sendingText,
60
+ bannerPosition,
44
61
  sendingMessages,
45
62
  messages,
46
63
  actionRef,
47
64
  onScrollEnds,
48
65
  getMoreMessages,
49
66
  hasMoreItems,
50
- isLoading
51
- } = props;
67
+ isLoading,
68
+ bannerRef
69
+ } = props$2;
70
+ const loadMoreRef = React__default["default"].useRef(null);
52
71
  const virtualListRef = React__default["default"].useRef(); // estimateSize should not be really required given what was stated on
53
72
  // https://github.com/tannerlinsley/react-virtual/issues/23
54
73
 
@@ -60,90 +79,185 @@ const ChatContainerMessagesList = props => {
60
79
  size: messages.length,
61
80
  parentRef: virtualListRef,
62
81
  overscan: 15
63
- }, getPadding(hasMoreItems)), {}, {
82
+ }, getPadding({
83
+ hasMoreItems,
84
+ bannerPosition,
85
+ isLoading
86
+ })), {}, {
64
87
  estimateSize: React__default["default"].useCallback(() => 80, [])
65
88
  }));
66
89
  const onScrollStop = React__default["default"].useCallback(() => {
90
+ var _virtualListRef$curre;
91
+
67
92
  const {
68
93
  bottom,
69
94
  top
70
- } = virtualListRef.current.getBoundingClientRect();
95
+ } = (_virtualListRef$curre = virtualListRef.current) === null || _virtualListRef$curre === void 0 ? void 0 : _virtualListRef$curre.getBoundingClientRect();
71
96
  const list = virtualListRef.current.querySelectorAll('[data-element="chat-element-list-item"]');
72
97
  const indexList = [];
73
98
  list.forEach(item => {
74
99
  const {
75
- top: itemTop
100
+ top: itemTop,
101
+ bottom: itemBottom
76
102
  } = item.getBoundingClientRect();
77
- if (itemTop < bottom && itemTop > top) indexList.push(item.dataset.index);
103
+ const itemPadding = 10;
104
+ if (itemTop + itemPadding < bottom && itemBottom - itemPadding > top) indexList.push(item.dataset.index);
78
105
  });
79
106
  if (onScrollEnds) onScrollEnds(indexList);
80
107
  return indexList;
81
108
  }, [onScrollEnds]);
82
- const scrollAndFocus = React__default["default"].useCallback(index => {
83
- vScroll(index, {
84
- align: 'center'
85
- });
109
+ const onlyFocus = React__default["default"].useCallback(index => {
86
110
  setTimeout(() => {
87
- virtualListRef.current.querySelector(`[data-index="${index}"]`).focus();
111
+ virtualListRef.current.querySelector("[data-index=\"".concat(index, "\"]")).focus();
88
112
  }, 300);
89
- }, [vScroll]);
113
+ }, []);
114
+ const scrollAndFocus = React__default["default"].useCallback(function (index) {
115
+ let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
116
+ align: 'center'
117
+ };
118
+ vScroll(index, b);
119
+ onlyFocus(index);
120
+ }, [onlyFocus, vScroll]);
90
121
  React__default["default"].useEffect(() => {
91
122
  if (actionRef && actionRef.current) {
92
- actionRef.current.scrollToIndex = (a, b = {
93
- align: 'center'
94
- }) => {
123
+ actionRef.current.scrollToIndex = function (a) {
124
+ let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
125
+ align: 'center'
126
+ };
95
127
  vScroll(a, b);
96
128
  };
97
129
 
98
130
  actionRef.current.getMessagesInView = onScrollStop;
99
131
 
100
- actionRef.current.focusToIndex = (a, b = {
101
- align: 'center'
102
- }) => {
103
- scrollAndFocus(a);
132
+ actionRef.current.focusToIndex = function (a) {
133
+ let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
134
+ align: 'center'
135
+ };
136
+ scrollAndFocus(a, b);
104
137
  };
105
138
 
106
- actionRef.current.focusToList = (a, b = {
107
- align: 'center'
108
- }) => {
109
- var _virtualListRef$curre;
139
+ actionRef.current.focusToIndexWithoutScroll = onlyFocus;
140
+
141
+ actionRef.current.focusToList = a => {
142
+ var _virtualListRef$curre2;
110
143
 
111
- (_virtualListRef$curre = virtualListRef.current) === null || _virtualListRef$curre === void 0 ? void 0 : _virtualListRef$curre.focus();
144
+ (_virtualListRef$curre2 = virtualListRef.current) === null || _virtualListRef$curre2 === void 0 ? void 0 : _virtualListRef$curre2.focus();
112
145
  };
113
146
  }
114
- }, [actionRef, onScrollStop, scrollAndFocus, vScroll]);
147
+ }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll]);
115
148
  const handleKey = React__default["default"].useCallback(e => {
116
- e.preventDefault();
117
149
  const {
118
150
  key
119
151
  } = e;
120
152
  const index = Number(e.currentTarget.dataset.index);
153
+ e.stopPropagation();
121
154
 
122
155
  switch (key) {
123
156
  case 'ArrowUp':
124
- if (index > 0) virtualListRef.current.querySelector(`[data-index="${index - 1}"]`).focus();
157
+ e.preventDefault();
158
+ if (index > 0) virtualListRef.current.querySelector("[data-index=\"".concat(index - 1, "\"]")).focus();
125
159
  break;
126
160
 
127
161
  case 'ArrowDown':
162
+ e.preventDefault();
163
+
128
164
  if (index < messages.length - 1) {
129
- virtualListRef.current.querySelector(`[data-index="${index + 1}"]`).focus();
165
+ virtualListRef.current.querySelector("[data-index=\"".concat(index + 1, "\"]")).focus();
130
166
  }
131
167
 
132
168
  break;
133
169
 
134
170
  case 'Home':
171
+ e.preventDefault();
135
172
  scrollAndFocus(0);
136
173
  break;
137
174
 
138
175
  case 'End':
176
+ e.preventDefault();
139
177
  scrollAndFocus(messages.length - 1);
140
178
  break;
141
179
 
142
180
  case 'Tab':
143
- actionRef.current.focusToComposer();
181
+ e.preventDefault();
182
+
183
+ if (hasMoreItems === 'bottom' && !e.shiftKey) {
184
+ var _loadMoreRef$current;
185
+
186
+ (_loadMoreRef$current = loadMoreRef.current) === null || _loadMoreRef$current === void 0 ? void 0 : _loadMoreRef$current.focus();
187
+ } else if (hasMoreItems === 'top' && e.shiftKey) {
188
+ var _loadMoreRef$current2;
189
+
190
+ (_loadMoreRef$current2 = loadMoreRef.current) === null || _loadMoreRef$current2 === void 0 ? void 0 : _loadMoreRef$current2.focus();
191
+ } else if (!e.shiftKey) {
192
+ if (bannerPosition) {
193
+ bannerRef.current.focusOnWrapper();
194
+ } else {
195
+ actionRef.current.focusToComposer();
196
+ }
197
+ } else {
198
+ var _virtualListRef$curre3;
199
+
200
+ (_virtualListRef$curre3 = virtualListRef.current) === null || _virtualListRef$curre3 === void 0 ? void 0 : _virtualListRef$curre3.focus();
201
+ }
202
+
203
+ break;
204
+ }
205
+ }, [actionRef, hasMoreItems, messages.length, bannerPosition, scrollAndFocus]);
206
+ const handleListKey = React__default["default"].useCallback(e => {
207
+ const {
208
+ key
209
+ } = e;
210
+
211
+ switch (key) {
212
+ case 'ArrowUp':
213
+ e.preventDefault();
214
+ onlyFocus(onScrollStop().shift());
215
+ break;
216
+
217
+ case 'ArrowDown':
218
+ e.preventDefault();
219
+ onlyFocus(onScrollStop().pop());
220
+ break;
221
+
222
+ case 'Home':
223
+ e.preventDefault();
224
+ scrollAndFocus(0);
225
+ break;
226
+
227
+ case 'End':
228
+ e.preventDefault();
229
+ scrollAndFocus(messages.length - 1);
230
+ break;
231
+
232
+ case 'Tab':
233
+ if (document.activeElement !== loadMoreRef.current) {
234
+ if (hasMoreItems === 'bottom' && !e.shiftKey) {
235
+ var _loadMoreRef$current3;
236
+
237
+ e.preventDefault();
238
+ (_loadMoreRef$current3 = loadMoreRef.current) === null || _loadMoreRef$current3 === void 0 ? void 0 : _loadMoreRef$current3.focus();
239
+ } else if (hasMoreItems === 'top' && e.shiftKey) {
240
+ var _loadMoreRef$current4;
241
+
242
+ e.preventDefault();
243
+ (_loadMoreRef$current4 = loadMoreRef.current) === null || _loadMoreRef$current4 === void 0 ? void 0 : _loadMoreRef$current4.focus();
244
+ } else if (!e.shiftKey) {
245
+ e.preventDefault();
246
+ actionRef.current.focusToComposer();
247
+ }
248
+ } else if (!e.shiftKey) {
249
+ e.preventDefault();
250
+ actionRef.current.focusToComposer();
251
+ } else {
252
+ var _virtualListRef$curre4;
253
+
254
+ e.preventDefault();
255
+ (_virtualListRef$curre4 = virtualListRef.current) === null || _virtualListRef$curre4 === void 0 ? void 0 : _virtualListRef$curre4.focus();
256
+ }
257
+
144
258
  break;
145
259
  }
146
- }, [actionRef, messages.length, scrollAndFocus]);
260
+ }, [actionRef, hasMoreItems, messages.length, onScrollStop, onlyFocus, scrollAndFocus]);
147
261
  React__default["default"].useEffect(() => {
148
262
  let handlerCallback = null;
149
263
  const localVirtualRef = virtualListRef.current;
@@ -174,7 +288,7 @@ const ChatContainerMessagesList = props => {
174
288
  position: 'absolute',
175
289
  top: 0,
176
290
  left: 0,
177
- transform: `translateY(${start}px)`,
291
+ transform: "translateY(".concat(start, "px)"),
178
292
  width: '100%'
179
293
  };
180
294
  return /*#__PURE__*/jsxRuntime.jsx(styled.ListItem, {
@@ -193,7 +307,7 @@ const ChatContainerMessagesList = props => {
193
307
  jsxRuntime.jsx(ChatBubble.ChatBubble, _objectSpread(_objectSpread({}, row), {}, {
194
308
  helpMessage: isSending ? sendingText : row.helpMessage
195
309
  })) : null, row.type === props$1.BUBBLE_TYPES.DELIMITER ? /*#__PURE__*/jsxRuntime.jsx(MessageDelimiter.MessageDelimiter, _objectSpread({}, row)) : null, row.type === props$1.BUBBLE_TYPES.SYSTEM ? /*#__PURE__*/jsxRuntime.jsx(SystemMessage.SystemMessage, _objectSpread({}, row)) : null)
196
- }, `ds-chat-bubble-${index}`);
310
+ }, "ds-chat-bubble-".concat(index, "-").concat(row.dsId, "-").concat(row.type));
197
311
  }), [virtualItems, messages, sendingMessages, handleKey, sendingText]);
198
312
  return /*#__PURE__*/_jsx__default["default"](styled.StyledWrapper, {}, void 0, /*#__PURE__*/jsxRuntime.jsx(styled.StyledChatContainerContentList, {
199
313
  "data-testid": "chat-thread-container",
@@ -201,15 +315,17 @@ const ChatContainerMessagesList = props => {
201
315
  "aria-live": "polite",
202
316
  ref: virtualListRef,
203
317
  role: "list",
204
- onKeyDown: handleKey,
318
+ onKeyDown: handleListKey,
205
319
  children: /*#__PURE__*/_jsx__default["default"](styled.StyledChatContainerContentListScroll, {
206
- height: `${totalSize}px`
320
+ height: "".concat(totalSize, "px")
207
321
  }, void 0, render, !isLoading && hasMoreItems ? /*#__PURE__*/_jsx__default["default"](styled.StyledLoadMoreContainer, {
208
322
  hasMoreItems: hasMoreItems
209
323
  }, void 0, /*#__PURE__*/_jsx__default["default"](DSButton__default["default"], {
210
324
  labelText: "Load More",
211
325
  buttonType: "secondary",
212
- onClick: getMoreMessages
326
+ onClick: getMoreMessages,
327
+ "data-testid": "ds-chat-load-more-btn",
328
+ innerRef: loadMoreRef
213
329
  })) : null)
214
330
  }));
215
331
  };
@@ -4,8 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var dsPropsHelpers = require('@elliemae/ds-props-helpers');
6
6
 
7
- const useValidateProps = (props, schema) => {
8
- dsPropsHelpers.useValidateTypescriptPropTypes(props, schema);
7
+ const useValidateProps = (props, propTypes) => {
8
+ dsPropsHelpers.useValidateTypescriptPropTypes(props, propTypes);
9
9
  };
10
10
 
11
11
  exports.useValidateProps = useValidateProps;