@elliemae/ds-chat 2.0.0-next.9 → 2.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/cjs/parts/bubble/ChatBubble.js +9 -6
  2. package/cjs/parts/bubble/ChatBubbleArrow.js +64 -61
  3. package/cjs/parts/bubble/props.js +1 -1
  4. package/cjs/parts/bubble/styled.js +1 -1
  5. package/cjs/parts/chat-composer/ChatContainerComposer.js +14 -7
  6. package/cjs/parts/chat-composer/props.js +4 -0
  7. package/cjs/parts/chat-composer/styled.js +2 -2
  8. package/cjs/parts/chat-container/ChatContainer.js +50 -9
  9. package/cjs/parts/chat-container/props.js +1 -1
  10. package/cjs/parts/chat-container/styled.js +1 -1
  11. package/cjs/parts/chat-container-header/ChatContainerHeader.js +3 -3
  12. package/cjs/parts/chat-container-header/helpers.js +31 -0
  13. package/cjs/parts/chat-container-header/styled.js +6 -6
  14. package/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +134 -29
  15. package/cjs/parts/chat-container-messages-list/props.js +4 -2
  16. package/cjs/parts/chat-container-messages-list/styled.js +2 -2
  17. package/cjs/parts/chat-empty-state/ChatEmptyState.js +2 -3
  18. package/cjs/parts/chat-sidebar/SideBarChat.js +57 -29
  19. package/cjs/parts/chat-sidebar/props.js +11 -1
  20. package/cjs/parts/chat-sidebar/styled.js +2 -2
  21. package/cjs/parts/floating-button/FloatingButton.js +12 -10
  22. package/cjs/parts/sidebar-button/SidebarButton.js +5 -0
  23. package/cjs/parts/sidebar-button/props.js +2 -3
  24. package/cjs/parts/system-message/style.js +1 -1
  25. package/cjs/parts/tile-button/TileButton.js +30 -27
  26. package/cjs/parts/tile-button/props.js +12 -8
  27. package/cjs/parts/tile-button/styled.js +6 -2
  28. package/esm/parts/bubble/ChatBubble.js +8 -5
  29. package/esm/parts/bubble/ChatBubbleArrow.js +64 -61
  30. package/esm/parts/bubble/props.js +1 -1
  31. package/esm/parts/bubble/styled.js +1 -1
  32. package/esm/parts/chat-composer/ChatContainerComposer.js +13 -5
  33. package/esm/parts/chat-composer/props.js +4 -0
  34. package/esm/parts/chat-container/ChatContainer.js +50 -9
  35. package/esm/parts/chat-container/props.js +1 -1
  36. package/esm/parts/chat-container/styled.js +1 -1
  37. package/esm/parts/chat-container-header/ChatContainerHeader.js +3 -2
  38. package/esm/parts/chat-container-header/helpers.js +23 -0
  39. package/esm/parts/chat-container-header/styled.js +6 -6
  40. package/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +134 -29
  41. package/esm/parts/chat-container-messages-list/props.js +4 -2
  42. package/esm/parts/chat-container-messages-list/styled.js +2 -2
  43. package/esm/parts/chat-empty-state/ChatEmptyState.js +1 -1
  44. package/esm/parts/chat-sidebar/SideBarChat.js +57 -28
  45. package/esm/parts/chat-sidebar/props.js +11 -1
  46. package/esm/parts/chat-sidebar/styled.js +2 -2
  47. package/esm/parts/floating-button/FloatingButton.js +12 -9
  48. package/esm/parts/sidebar-button/SidebarButton.js +5 -0
  49. package/esm/parts/sidebar-button/props.js +1 -1
  50. package/esm/parts/system-message/style.js +1 -1
  51. package/esm/parts/tile-button/TileButton.js +31 -26
  52. package/esm/parts/tile-button/props.js +11 -3
  53. package/esm/parts/tile-button/styled.js +6 -3
  54. package/package.json +16 -6
  55. package/types/parts/bubble/styled.d.ts +3 -3
  56. package/types/parts/bubble/tests/ChatBubble.test.d.ts +1 -0
  57. package/types/parts/chat-card/styled.d.ts +1 -1
  58. package/types/parts/chat-composer/ChatContainerComposer.d.ts +2 -0
  59. package/types/parts/chat-composer/props.d.ts +10 -6
  60. package/types/parts/chat-composer/styled.d.ts +2 -2
  61. package/types/parts/chat-composer/tests/ChatContainerComposer.test.d.ts +1 -0
  62. package/types/parts/chat-container/props.d.ts +2 -0
  63. package/types/parts/chat-container/styled.d.ts +2 -2
  64. package/types/parts/chat-container-header/helpers.d.ts +6 -0
  65. package/types/parts/chat-container-header/styled.d.ts +3 -3
  66. package/types/parts/chat-container-messages-list/props.d.ts +6 -0
  67. package/types/parts/chat-empty-state/styled.d.ts +1 -1
  68. package/types/parts/chat-sidebar/SideBarChat.d.ts +3 -0
  69. package/types/parts/chat-sidebar/props.d.ts +8 -1
  70. package/types/parts/chat-sidebar/styled.d.ts +2 -2
  71. package/types/parts/floating-container/styled.d.ts +1 -1
  72. package/types/parts/grid-influencer/styled.d.ts +2 -2
  73. package/types/parts/message-delimiter/styled.d.ts +1 -1
  74. package/types/parts/sidebar-button/styled.d.ts +1 -1
  75. package/types/parts/system-message/style.d.ts +2 -2
  76. package/types/parts/tile-button/TileButton.d.ts +3 -0
  77. package/types/parts/tile-button/props.d.ts +6 -0
  78. package/types/parts/tile-button/styled.d.ts +5 -4
@@ -6,24 +6,23 @@ var _jsx = require('@babel/runtime/helpers/jsx');
6
6
  require('core-js/modules/web.url.to-json.js');
7
7
  var React = require('react');
8
8
  var reactDesc = require('react-desc');
9
- var DSTooltip = require('@elliemae/ds-tooltip');
9
+ var dsTooltip = require('@elliemae/ds-tooltip');
10
10
  var dsGrid = require('@elliemae/ds-grid');
11
- var CloseXsmall = require('@elliemae/ds-icons/CloseXsmall');
11
+ var dsIcons = require('@elliemae/ds-icons');
12
12
  var styled = require('./styled.js');
13
13
  var props = require('./props.js');
14
14
  var useValidateProps = require('./config/useValidateProps.js');
15
+ var jsxRuntime = require('react/jsx-runtime');
15
16
 
16
17
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
17
18
 
18
19
  var _jsx__default = /*#__PURE__*/_interopDefaultLegacy(_jsx);
19
20
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
20
- var DSTooltip__default = /*#__PURE__*/_interopDefaultLegacy(DSTooltip);
21
- var CloseXsmall__default = /*#__PURE__*/_interopDefaultLegacy(CloseXsmall);
22
21
 
23
22
  var _StyledWrapperLeftBor, _CloseXsmall;
24
23
 
25
24
  const TileButton = props => {
26
- var _Icon, _StyledStatusBadge, _StyledTileButtonLabe;
25
+ var _Icon, _StyledTileButtonLabe, _span;
27
26
 
28
27
  useValidateProps.useValidateProps(props, TileButtonWithSchema.toJSON());
29
28
  const {
@@ -42,7 +41,10 @@ const TileButton = props => {
42
41
  disabled,
43
42
  selected,
44
43
  isHeader,
45
- ariaLabel
44
+ ariaLabel,
45
+ tooltipPlacement,
46
+ disableTooltip,
47
+ innerRef
46
48
  } = props;
47
49
  const handleClick = React__default["default"].useCallback(() => {
48
50
  onClick(dsId, title);
@@ -58,17 +60,19 @@ const TileButton = props => {
58
60
  justifyContent: "center"
59
61
  }, void 0, _Icon || (_Icon = /*#__PURE__*/_jsx__default["default"](Icon, {
60
62
  size: "m"
61
- })), badge ? _StyledStatusBadge || (_StyledStatusBadge = /*#__PURE__*/_jsx__default["default"](styled.StyledStatusBadge, {
63
+ })), badge ? /*#__PURE__*/_jsx__default["default"](styled.StyledStatusBadge, {
62
64
  badgeColor: badgeColor,
63
- badgePosition: badgePosition
64
- })) : null)), !isHeader ? /*#__PURE__*/_jsx__default["default"](dsGrid.Grid, {
65
+ badgePosition: badgePosition,
66
+ "data-testid": "tile-badge-".concat(dsId)
67
+ }) : null)), !isHeader ? /*#__PURE__*/_jsx__default["default"](dsGrid.Grid, {
65
68
  width: "100%",
66
69
  justifyContent: "center"
67
70
  }, void 0, label ? _StyledTileButtonLabe || (_StyledTileButtonLabe = /*#__PURE__*/_jsx__default["default"](styled.StyledTileButtonLabel, {}, void 0, label)) : null) : null), [isHeader, Icon, badge, badgeColor, badgePosition, label]);
68
- return /*#__PURE__*/_jsx__default["default"](styled.StyledTileButton, {
71
+ const Btn = React__default["default"].useMemo(() => /*#__PURE__*/jsxRuntime.jsx(styled.StyledTileButton, {
69
72
  isHeader: isHeader,
70
73
  value: dsId,
71
74
  "data-testid": "tile-button-".concat(dsId),
75
+ "data-key": dsId,
72
76
  onClick: handleClick,
73
77
  onFocus: onFocus,
74
78
  onBlur: onBlur,
@@ -77,23 +81,22 @@ const TileButton = props => {
77
81
  badgeColor: badgeColor,
78
82
  badgePosition: badgePosition,
79
83
  "aria-pressed": selected,
80
- "aria-label": ariaLabel
81
- }, dsId, /*#__PURE__*/_jsx__default["default"](styled.StyledWrapper, {
82
- alignItems: "center",
83
- justifyContent: "center"
84
- }, void 0, title ? /*#__PURE__*/_jsx__default["default"](DSTooltip__default["default"], {
85
- containerProps: {
86
- id: "ds-chat-tile-tooltip-button-".concat(dsId),
87
- 'data-testid': "ds-chat-tile-tooltip-button-".concat(dsId)
88
- },
89
- interactionType: "hover",
90
- title: title,
91
- triggerComponent: /*#__PURE__*/_jsx__default["default"]("span", {}, void 0, MainContent),
92
- placement: "bottom"
93
- }) : MainContent, _StyledWrapperLeftBor || (_StyledWrapperLeftBor = /*#__PURE__*/_jsx__default["default"](styled.StyledWrapperLeftBorder, {})), showClose && !disabled ? /*#__PURE__*/_jsx__default["default"](styled.CloseButton, {
94
- onClick: onClose,
95
- value: dsId
96
- }, void 0, _CloseXsmall || (_CloseXsmall = /*#__PURE__*/_jsx__default["default"](CloseXsmall__default["default"], {}))) : null));
84
+ "aria-label": ariaLabel,
85
+ ref: innerRef,
86
+ children: /*#__PURE__*/_jsx__default["default"](styled.StyledWrapper, {
87
+ alignItems: "center",
88
+ justifyContent: "center"
89
+ }, void 0, _span || (_span = /*#__PURE__*/_jsx__default["default"]("span", {}, void 0, MainContent)), _StyledWrapperLeftBor || (_StyledWrapperLeftBor = /*#__PURE__*/_jsx__default["default"](styled.StyledWrapperLeftBorder, {})), showClose && !disabled ? /*#__PURE__*/_jsx__default["default"](styled.CloseButton, {
90
+ onClick: onClose,
91
+ value: dsId,
92
+ "data-testid": "tile-close-btn-".concat(dsId)
93
+ }, void 0, _CloseXsmall || (_CloseXsmall = /*#__PURE__*/_jsx__default["default"](dsIcons.CloseXsmall, {}))) : null)
94
+ }, dsId), [MainContent, ariaLabel, badgeColor, badgePosition, disabled, dsId, handleClick, isHeader, onBlur, onClose, onFocus, selected, showClose, innerRef]);
95
+ return title && !disableTooltip ? /*#__PURE__*/_jsx__default["default"](styled.StyledTooltipV3ButtonWrapper, {}, void 0, /*#__PURE__*/_jsx__default["default"](dsTooltip.DSTooltipV3, {
96
+ id: "ds-chat-tile-tooltip-button-".concat(dsId),
97
+ text: title,
98
+ startPlacementPreference: tooltipPlacement
99
+ }, void 0, Btn)) : Btn;
97
100
  };
98
101
 
99
102
  TileButton.defaultProps = props.defaultTileButton;
@@ -4,14 +4,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var reactDesc = require('react-desc');
6
6
  var lodash = require('lodash');
7
- var Comments = require('@elliemae/ds-icons/Comments');
8
-
9
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
-
11
- var Comments__default = /*#__PURE__*/_interopDefaultLegacy(Comments);
7
+ var dsIcons = require('@elliemae/ds-icons');
12
8
 
13
9
  const defaultTileButton = {
14
- Icon: Comments__default["default"],
10
+ Icon: dsIcons.Comments,
15
11
  dsId: undefined,
16
12
  label: '',
17
13
  onClick: lodash.noop,
@@ -26,7 +22,10 @@ const defaultTileButton = {
26
22
  disabled: false,
27
23
  selected: false,
28
24
  isHeader: false,
29
- ariaLabel: 'Tile button'
25
+ ariaLabel: 'Tile button',
26
+ tooltipPlacement: 'right',
27
+ disableTooltip: false,
28
+ innerRef: lodash.noop
30
29
  };
31
30
  const propsTileButton = {
32
31
  Icon: reactDesc.PropTypes.func.description('Icon component').defaultValue(defaultTileButton.Icon),
@@ -44,7 +43,12 @@ const propsTileButton = {
44
43
  disabled: reactDesc.PropTypes.bool.description('It will disabled the button').defaultValue(defaultTileButton.disabled),
45
44
  selected: reactDesc.PropTypes.bool.description('Indicate that the button is selected').defaultValue(defaultTileButton.disabled),
46
45
  isHeader: reactDesc.PropTypes.bool.description("It won't render the label").defaultValue(defaultTileButton.disabled),
47
- ariaLabel: reactDesc.PropTypes.string.description('aria-label attribute').defaultValue(defaultTileButton.ariaLabel)
46
+ ariaLabel: reactDesc.PropTypes.string.description('aria-label attribute').defaultValue(defaultTileButton.ariaLabel),
47
+ tooltipPlacement: reactDesc.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'"),
48
+ disableTooltip: reactDesc.PropTypes.bool.description('Disable tooltip option').defaultValue(defaultTileButton.disableTooltip),
49
+ innerRef: reactDesc.PropTypes.oneOfType([reactDesc.PropTypes.func, reactDesc.PropTypes.shape({
50
+ current: reactDesc.PropTypes.any
51
+ })]).description('reference to the component')
48
52
  };
49
53
 
50
54
  exports.defaultTileButton = defaultTileButton;
@@ -54,8 +54,11 @@ const CloseButton = /*#__PURE__*/styled__default["default"].button.withConfig({
54
54
  componentId: "sc-1ebp1zs-5"
55
55
  })(["outline:none;background:none;height:9px;width:9px;position:absolute;top:1px;right:1px;overflow:hidden;padding:0;border:none;span{position:absolute;left:-3px;top:-4px;}&:focus,&:hover{svg{fill:", ";}&:after{display:block;content:'';position:absolute;top:0;left:0;width:100%;height:100%;border:solid 1px ", ";border-radius:2px;}}cursor:pointer;"], props => props.theme.colors.brand[600], props => props.theme.colors.brand[600]); // MAIN WRAPPER
56
56
 
57
- const StyledTileButton = /*#__PURE__*/styled__default["default"].button.withConfig({
57
+ const StyledTooltipV3ButtonWrapper = /*#__PURE__*/styled__default["default"].div.withConfig({
58
58
  componentId: "sc-1ebp1zs-6"
59
+ })(["height:", "px;width:", "px;"], BUTTON_SIDEBAR_HEIGHT, MIN_WIDTH_SIDEBAR);
60
+ const StyledTileButton = /*#__PURE__*/styled__default["default"].button.withConfig({
61
+ componentId: "sc-1ebp1zs-7"
59
62
  })(["outline:none;background:transparent;height:", "px;width:", "px;position:relative;padding:0;border:none;cursor:pointer;border-bottom:", ";&:focus,&:hover,&:active,&:disabled{background:", ";& ", "{border:2px solid ", ";margin-top:-2px;", ";}}&:focus,&:hover{& ", "{background:", ";}& ", "{color:", ";}& svg{fill:", ";}}&:active:not(:disabled){background:", ";& ", "{background:", ";}& ", "{color:", ";font-weight:600;}& svg{fill:", ";}& ", "{border:2px solid ", ";}}&:disabled{background:", ";", "{background:", ";}& ", "{background:", ";border:2px solid ", ";}", "{svg{fill:", ";}}", "{color:", ";}}", ""], BUTTON_SIDEBAR_HEIGHT, MIN_WIDTH_SIDEBAR, props => props.isHeader ? "1px solid ".concat(props.theme.colors.neutral['200']) : 'none', props => props.theme.colors.neutral['080'], StyledStatusBadge, props => props.theme.colors.neutral['080'], props => {
60
63
  switch (props.badgePosition) {
61
64
  case 'left':
@@ -75,7 +78,7 @@ const StyledTileButton = /*#__PURE__*/styled__default["default"].button.withConf
75
78
  return '';
76
79
  });
77
80
  const StyledWrapper = /*#__PURE__*/styled__default["default"](dsGrid.Grid).withConfig({
78
- componentId: "sc-1ebp1zs-7"
81
+ componentId: "sc-1ebp1zs-8"
79
82
  })(["height:100%;width:100%;position:relative;"]);
80
83
 
81
84
  exports.CloseButton = CloseButton;
@@ -83,6 +86,7 @@ exports.StyledStatusBadge = StyledStatusBadge;
83
86
  exports.StyledTileButton = StyledTileButton;
84
87
  exports.StyledTileButtonIcon = StyledTileButtonIcon;
85
88
  exports.StyledTileButtonLabel = StyledTileButtonLabel;
89
+ exports.StyledTooltipV3ButtonWrapper = StyledTooltipV3ButtonWrapper;
86
90
  exports.StyledWrapper = StyledWrapper;
87
91
  exports.StyledWrapperCentralContent = StyledWrapperCentralContent;
88
92
  exports.StyledWrapperLeftBorder = StyledWrapperLeftBorder;
@@ -1,14 +1,16 @@
1
1
  import _jsx from '@babel/runtime/helpers/esm/jsx';
2
2
  import 'core-js/modules/web.url.to-json.js';
3
- import 'react';
3
+ import 'core-js/modules/esnext.async-iterator.map.js';
4
+ import 'core-js/modules/esnext.iterator.map.js';
5
+ import React from 'react';
4
6
  import { describe } from 'react-desc';
5
- import Warning from '@elliemae/ds-icons/WarningCircleFill';
7
+ import { WarningCircleFill } from '@elliemae/ds-icons';
6
8
  import { StyledWrapper, StyledColoredBubble, StyledTitleBubble, StyledTitleLeftBubble, StyledTitleRightBubble, StyleBodyWrapper, StyleErrorMessage, StyleHelpMessage } from './styled.js';
7
9
  import { propsBubbles } from './props.js';
8
10
  import { useValidateProps } from './config/useValidateProps.js';
9
11
  import { ChatBubbleArrow } from './ChatBubbleArrow.js';
10
12
 
11
- var _Warning;
13
+ var _br, _WarningCircleFill;
12
14
 
13
15
  const ChatBubble = props => {
14
16
  useValidateProps(props, ChatBubbleWithSchema.toJSON());
@@ -21,6 +23,7 @@ const ChatBubble = props => {
21
23
  errorMessage,
22
24
  helpMessage
23
25
  } = props;
26
+ const bodyParts = React.useMemo(() => typeof body === 'string' ? body.split('\n') : [body], [body]);
24
27
  return /*#__PURE__*/_jsx(StyledWrapper, {
25
28
  "data-testid": "ds-chat-bubble-".concat(dsId),
26
29
  type: type
@@ -40,14 +43,14 @@ const ChatBubble = props => {
40
43
  "data-testid": "chat-bubble-time-".concat(dsId)
41
44
  }, void 0, time)), /*#__PURE__*/_jsx(StyleBodyWrapper, {
42
45
  "data-testid": "chat-bubble-body-".concat(dsId)
43
- }, void 0, body), /*#__PURE__*/_jsx(ChatBubbleArrow, {
46
+ }, void 0, bodyParts.map((item, index) => /*#__PURE__*/_jsx(React.Fragment, {}, "".concat(item, "-").concat(index), item, index < bodyParts.length - 1 ? _br || (_br = /*#__PURE__*/_jsx("br", {})) : null))), /*#__PURE__*/_jsx(ChatBubbleArrow, {
44
47
  type: type
45
48
  })), errorMessage ? /*#__PURE__*/_jsx(StyleErrorMessage, {
46
49
  "data-testid": "chat-bubble-error-message-".concat(dsId),
47
50
  p: "xxs",
48
51
  gutter: "xxs",
49
52
  cols: [1, 'auto']
50
- }, void 0, /*#__PURE__*/_jsx("span", {}, void 0, errorMessage), _Warning || (_Warning = /*#__PURE__*/_jsx(Warning, {}))) : null, helpMessage ? /*#__PURE__*/_jsx(StyleHelpMessage, {
53
+ }, void 0, /*#__PURE__*/_jsx("span", {}, void 0, errorMessage), _WarningCircleFill || (_WarningCircleFill = /*#__PURE__*/_jsx(WarningCircleFill, {}))) : null, helpMessage ? /*#__PURE__*/_jsx(StyleHelpMessage, {
51
54
  "data-testid": "chat-bubble-help-message-".concat(dsId),
52
55
  p: "xxs",
53
56
  gutter: "xxs",
@@ -4,66 +4,69 @@ import { StyledBubbleArrow } from './styled.js';
4
4
  import { BUBBLE_TYPES } from './props.js';
5
5
 
6
6
  var _svg, _svg2;
7
- const ChatBubbleArrow = ({
8
- type
9
- }) => /*#__PURE__*/_jsx(StyledBubbleArrow, {}, void 0, type === BUBBLE_TYPES.RECIPIENT ? _svg || (_svg = /*#__PURE__*/_jsx("svg", {
10
- width: "15px",
11
- height: "14px",
12
- viewBox: "0 0 15 14"
13
- }, void 0, /*#__PURE__*/_jsx("defs", {}, void 0, /*#__PURE__*/_jsx("path", {
14
- d: "M12,8.5 C12,7.9373169 11.6782751,7.4856453 11.2282104,7.196228 C11.2286673,7.1967363 3,2 3,2 L3,10 L10.5627441,10 L10.5658569,9.9933472 C11.3630371,9.9580688 12,9.3058472 12,8.5 Z",
15
- id: "path-1"
16
- }), /*#__PURE__*/_jsx("filter", {
17
- x: "-55.6%",
18
- y: "-50.0%",
19
- width: "211.1%",
20
- height: "225.0%",
21
- filterUnits: "objectBoundingBox",
22
- id: "filter-2"
23
- }, void 0, /*#__PURE__*/_jsx("feOffset", {
24
- dx: "2.3",
25
- dy: "1.2",
26
- in: "SourceAlpha",
27
- result: "shadowOffsetOuter1"
28
- }), /*#__PURE__*/_jsx("feGaussianBlur", {
29
- stdDeviation: "1.5",
30
- in: "shadowOffsetOuter1",
31
- result: "shadowBlurOuter1"
32
- }), /*#__PURE__*/_jsx("feColorMatrix", {
33
- values: "0 0 0 0 0.207843137 0 0 0 0 0.235294118 0 0 0 0 0.274509804 0 0 0 0.8 0",
34
- type: "matrix",
35
- in: "shadowBlurOuter1"
36
- }))), /*#__PURE__*/_jsx("g", {
37
- id: "[DSK]-Visual-Design",
38
- stroke: "none",
39
- strokeWidth: "1",
40
- fill: "none",
41
- fillRule: "evenodd"
42
- }, void 0, /*#__PURE__*/_jsx("g", {
43
- id: "Path-Copy",
44
- transform: "translate(7.500000, 6.000000) scale(-1, 1) translate(-7.500000, -6.000000) "
45
- }, void 0, /*#__PURE__*/_jsx("use", {
46
- fill: "black",
47
- fillOpacity: "1",
48
- filter: "url(#filter-2)",
49
- xlinkHref: "#path-1"
50
- }), /*#__PURE__*/_jsx("use", {
51
- fill: "#FFFFFF",
52
- fillRule: "evenodd",
53
- xlinkHref: "#path-1"
54
- }))))) : _svg2 || (_svg2 = /*#__PURE__*/_jsx("svg", {
55
- width: "9px",
56
- height: "8px",
57
- viewBox: "0 0 9 8"
58
- }, void 0, /*#__PURE__*/_jsx("g", {
59
- stroke: "none",
60
- strokeWidth: "1",
61
- fill: "none",
62
- fillRule: "evenodd"
63
- }, void 0, /*#__PURE__*/_jsx("path", {
64
- d: "M9,6.5 C9,5.9373169 8.6782751,5.4856453 8.2282104,5.196228 C8.2286673,5.1967363 0,0 0,0 L0,8 L7.5627441,8 L7.5658569,7.9933472 C8.3630371,7.9580688 9,7.3058472 9,6.5 Z",
65
- id: "Path",
66
- fill: "#1E79C2"
67
- })))));
7
+ const ChatBubbleArrow = _ref => {
8
+ let {
9
+ type
10
+ } = _ref;
11
+ return /*#__PURE__*/_jsx(StyledBubbleArrow, {}, void 0, type === BUBBLE_TYPES.RECIPIENT ? _svg || (_svg = /*#__PURE__*/_jsx("svg", {
12
+ width: "15px",
13
+ height: "14px",
14
+ viewBox: "0 0 15 14"
15
+ }, void 0, /*#__PURE__*/_jsx("defs", {}, void 0, /*#__PURE__*/_jsx("path", {
16
+ d: "M12,8.5 C12,7.9373169 11.6782751,7.4856453 11.2282104,7.196228 C11.2286673,7.1967363 3,2 3,2 L3,10 L10.5627441,10 L10.5658569,9.9933472 C11.3630371,9.9580688 12,9.3058472 12,8.5 Z",
17
+ id: "path-1"
18
+ }), /*#__PURE__*/_jsx("filter", {
19
+ x: "-55.6%",
20
+ y: "-50.0%",
21
+ width: "211.1%",
22
+ height: "225.0%",
23
+ filterUnits: "objectBoundingBox",
24
+ id: "filter-2"
25
+ }, void 0, /*#__PURE__*/_jsx("feOffset", {
26
+ dx: "2.3",
27
+ dy: "1.2",
28
+ in: "SourceAlpha",
29
+ result: "shadowOffsetOuter1"
30
+ }), /*#__PURE__*/_jsx("feGaussianBlur", {
31
+ stdDeviation: "1.5",
32
+ in: "shadowOffsetOuter1",
33
+ result: "shadowBlurOuter1"
34
+ }), /*#__PURE__*/_jsx("feColorMatrix", {
35
+ values: "0 0 0 0 0.207843137 0 0 0 0 0.235294118 0 0 0 0 0.274509804 0 0 0 0.8 0",
36
+ type: "matrix",
37
+ in: "shadowBlurOuter1"
38
+ }))), /*#__PURE__*/_jsx("g", {
39
+ id: "[DSK]-Visual-Design",
40
+ stroke: "none",
41
+ strokeWidth: "1",
42
+ fill: "none",
43
+ fillRule: "evenodd"
44
+ }, void 0, /*#__PURE__*/_jsx("g", {
45
+ id: "Path-Copy",
46
+ transform: "translate(7.500000, 6.000000) scale(-1, 1) translate(-7.500000, -6.000000) "
47
+ }, void 0, /*#__PURE__*/_jsx("use", {
48
+ fill: "black",
49
+ fillOpacity: "1",
50
+ filter: "url(#filter-2)",
51
+ xlinkHref: "#path-1"
52
+ }), /*#__PURE__*/_jsx("use", {
53
+ fill: "#FFFFFF",
54
+ fillRule: "evenodd",
55
+ xlinkHref: "#path-1"
56
+ }))))) : _svg2 || (_svg2 = /*#__PURE__*/_jsx("svg", {
57
+ width: "9px",
58
+ height: "8px",
59
+ viewBox: "0 0 9 8"
60
+ }, void 0, /*#__PURE__*/_jsx("g", {
61
+ stroke: "none",
62
+ strokeWidth: "1",
63
+ fill: "none",
64
+ fillRule: "evenodd"
65
+ }, void 0, /*#__PURE__*/_jsx("path", {
66
+ d: "M9,6.5 C9,5.9373169 8.6782751,5.4856453 8.2282104,5.196228 C8.2286673,5.1967363 0,0 0,0 L0,8 L7.5627441,8 L7.5658569,7.9933472 C8.3630371,7.9580688 9,7.3058472 9,6.5 Z",
67
+ id: "Path",
68
+ fill: "#1E79C2"
69
+ })))));
70
+ };
68
71
 
69
72
  export { ChatBubbleArrow };
@@ -28,7 +28,7 @@ const propsBubbles = {
28
28
  type: PropTypes.oneOf([BUBBLE_TYPES.RECIPIENT, BUBBLE_TYPES.SENDER]).isRequired.description('Define bubble type ').defaultValue(defaultBubbleProps.type),
29
29
  title: PropTypes.string.isRequired.description('Title of the bubble').defaultValue(defaultBubbleProps.title),
30
30
  time: PropTypes.string.isRequired.description('Time of the bubble').defaultValue(defaultBubbleProps.title),
31
- body: PropTypes.oneOf(['string', 'element']).isRequired.description('Bubble content').defaultValue(defaultBubbleProps.body),
31
+ body: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired.description('Bubble content').defaultValue(defaultBubbleProps.body),
32
32
  onClick: PropTypes.string.description('Callback when the bubble is tapped').defaultValue(defaultBubbleProps.onClick),
33
33
  errorMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).description('Error message to display at bottom of the bubble').defaultValue(defaultBubbleProps.onClick),
34
34
  helpMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).description('Help message to display at bottom of the bubble').defaultValue(defaultBubbleProps.onClick)
@@ -22,7 +22,7 @@ const StyleBodyWrapper = /*#__PURE__*/styled.div.withConfig({
22
22
  })(["font-size:13px;font-weight:400;line-height:15px;min-height:18px;padding:0px 10px 8px 10px;"]);
23
23
  const StyleErrorMessage = /*#__PURE__*/styled.div.withConfig({
24
24
  componentId: "sc-fe8e9o-5"
25
- })(["font-size:12px;font-weight:400;padding-top:", ";padding-bottom:", ";color:", ";align-items:flex-end;justify-content:center;text-align:right;line-height:15px;svg{fill:", ";}a{font-size:12px;color:", ";}.em-ds-icon{margin-left:8px;}"], props => props.theme.space.xxxs, props => props.theme.space.xxxs, props => props.theme.colors.danger[900], props => props.theme.colors.danger[900], props => props.theme.colors.danger[900]);
25
+ })(["font-size:12px;font-weight:400;padding-top:", ";color:", ";align-items:flex-end;justify-content:center;text-align:right;line-height:15px;svg{fill:", ";}a{font-size:12px;color:", ";}.em-ds-icon{margin-left:8px;}"], props => props.theme.space.xxxs, props => props.theme.colors.danger[900], props => props.theme.colors.danger[900], props => props.theme.colors.danger[900]);
26
26
  const StyleHelpMessage = /*#__PURE__*/styled(StyleErrorMessage).withConfig({
27
27
  componentId: "sc-fe8e9o-6"
28
28
  })(["font-size:12px;line-height:15px;color:", ";svg{fill:", ";}a{font-size:12px;color:", ";}"], props => props.theme.colors.neutral[500], props => props.theme.colors.danger[500], props => props.theme.colors.danger[500]); // bubble sender/ recipient
@@ -2,10 +2,15 @@ import _jsx from '@babel/runtime/helpers/esm/jsx';
2
2
  import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
3
3
  import 'core-js/modules/web.url.to-json.js';
4
4
  import 'core-js/modules/web.dom-collections.iterator.js';
5
+ import 'core-js/modules/esnext.async-iterator.filter.js';
6
+ import 'core-js/modules/esnext.iterator.constructor.js';
7
+ import 'core-js/modules/esnext.iterator.filter.js';
8
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
9
+ import 'core-js/modules/esnext.iterator.for-each.js';
5
10
  import React from 'react';
6
11
  import { Grid } from '@elliemae/ds-grid';
7
12
  import { describe } from 'react-desc';
8
- import PaperAirplane from '@elliemae/ds-icons/PaperAirplane';
13
+ import { PaperAirplane } from '@elliemae/ds-icons';
9
14
  import { StyledChatContainerContentComposer, StyledComposerInput, StyledComposerButton, StyledCounterArea, StyledCounterErrorA11y } from './styled.js';
10
15
  import { useValidateProps } from './config/useValidateProps.js';
11
16
  import { composerProps, defaultComposerPros } from './props.js';
@@ -28,9 +33,11 @@ const ChatComposer = props => {
28
33
  onSend,
29
34
  onFocus,
30
35
  onBlur,
36
+ onKeyDown,
31
37
  maxHeight = 300,
32
38
  placeholder,
33
39
  inputMaxLength,
40
+ maxLengthMessage,
34
41
  buttonDisabled,
35
42
  dataTestid,
36
43
  actionRef
@@ -48,7 +55,7 @@ const ChatComposer = props => {
48
55
  onResize(newHeight);
49
56
  setHeight(newHeight);
50
57
  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);
51
- }, [inputValue, internalMaxHeight]);
58
+ }, [inputValue, internalMaxHeight, onResize]);
52
59
  React.useEffect(() => {
53
60
  if (actionRef && actionRef.current) {
54
61
  actionRef.current.focusToComposer = () => {
@@ -59,7 +66,7 @@ const ChatComposer = props => {
59
66
  inputSend.current.focus();
60
67
  };
61
68
  }
62
- }, [actionRef.current]);
69
+ }, [actionRef]);
63
70
  const handleChange = React.useCallback(e => {
64
71
  onChange(e.target.value);
65
72
  }, [onChange]);
@@ -85,6 +92,7 @@ const ChatComposer = props => {
85
92
  value: inputValue,
86
93
  onFocus: onFocus,
87
94
  onBlur: onBlur,
95
+ onKeyDown: onKeyDown,
88
96
  placeholder: placeholder,
89
97
  "aria-label": "Message to send",
90
98
  "data-testid": "chat-composer-textarea"
@@ -128,8 +136,8 @@ const ChatComposer = props => {
128
136
  }, void 0, inputMaxLength && hasError ? /*#__PURE__*/jsxs(Fragment, {
129
137
  children: [/*#__PURE__*/_jsx(StyledCounterErrorA11y, {
130
138
  role: "alert"
131
- }, void 0, "You have exceeded the character limit by ", inputLength - inputMaxLength), "Please limit to less than ", inputMaxLength, " characters.", ' ']
132
- }) : '', inputMaxLength ? "".concat(inputLength, " / ").concat(inputMaxLength) : ''), _Grid || (_Grid = /*#__PURE__*/_jsx(Grid, {}))));
139
+ }, void 0, maxLengthMessage || "You have exceeded the character limit by ".concat(inputLength - inputMaxLength)), maxLengthMessage || "Please limit to less than ".concat(inputMaxLength, " characters. ")]
140
+ }) : '', inputMaxLength ? " ".concat(inputLength, " / ").concat(inputMaxLength) : ''), _Grid || (_Grid = /*#__PURE__*/_jsx(Grid, {}))));
133
141
  };
134
142
 
135
143
  ChatComposer.defaultProps = defaultComposerPros;
@@ -9,8 +9,10 @@ const defaultComposerPros = {
9
9
  onSend: noop,
10
10
  onFocus: noop,
11
11
  onBlur: noop,
12
+ onKeyDown: noop,
12
13
  maxHeight: 0,
13
14
  inputMaxLength: undefined,
15
+ maxLengthMessage: undefined,
14
16
  buttonDisabled: false,
15
17
  dataTestid: 'ds-chat-composer',
16
18
  actionRef: noop
@@ -18,11 +20,13 @@ const defaultComposerPros = {
18
20
  const composerProps = {
19
21
  placeholder: PropTypes.string.description('Input Placeholder').defaultValue(defaultComposerPros.placeholder),
20
22
  inputValue: PropTypes.string.description('Input value').defaultValue(defaultComposerPros.inputValue),
23
+ maxLengthMessage: PropTypes.string.description('Max length message').defaultValue(defaultComposerPros.maxLengthMessage),
21
24
  onChange: PropTypes.func.description('Called when the user types').defaultValue(defaultComposerPros.onChange),
22
25
  onResize: PropTypes.func.description('Called the input changes his height').defaultValue(defaultComposerPros.onResize),
23
26
  onSend: PropTypes.func.description('Called when the click send').defaultValue(defaultComposerPros.onSend),
24
27
  onFocus: PropTypes.func.description('Input focus').defaultValue(defaultComposerPros.onFocus),
25
28
  onBlur: PropTypes.func.description('Input blur').defaultValue(defaultComposerPros.onBlur),
29
+ onKeyDown: PropTypes.func.description('Input on key down').defaultValue(defaultComposerPros.onKeyDown),
26
30
  maxHeight: PropTypes.number.description('Max height of the composer. Use 0 for no limit').defaultValue(defaultComposerPros.onBlur),
27
31
  inputMaxLength: PropTypes.number.description('Max length of the composer. `undefined` for no limit').defaultValue(defaultComposerPros.inputMaxLength),
28
32
  buttonDisabled: PropTypes.bool.description('Control the disabled for the send button').defaultValue(defaultComposerPros.buttonDisabled),
@@ -1,9 +1,14 @@
1
+ import 'core-js/modules/esnext.async-iterator.filter.js';
2
+ import 'core-js/modules/esnext.iterator.constructor.js';
3
+ import 'core-js/modules/esnext.iterator.filter.js';
4
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
5
+ import 'core-js/modules/esnext.iterator.for-each.js';
1
6
  import _jsx from '@babel/runtime/helpers/esm/jsx';
2
7
  import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
3
8
  import React from 'react';
4
9
  import { noop } from 'lodash';
5
10
  import { describe } from 'react-desc';
6
- import DSIndeterminateProgressIndicator from '@elliemae/ds-basic/IndeterminateProgressIndicator';
11
+ import DSIndeterminateProgressIndicator from '@elliemae/ds-indeterminate-progress-indicator';
7
12
  import DSBanner, { BANNER_TYPES } from '@elliemae/ds-banner';
8
13
  import { ChatComposer } from '../chat-composer/ChatContainerComposer.js';
9
14
  import { ChatContainerMessagesList } from '../chat-container-messages-list/ChatContainerMessagesList.js';
@@ -30,7 +35,8 @@ const ChatContainer = props => {
30
35
  messagesListProps,
31
36
  composerProps,
32
37
  composerProps: {
33
- onResize: onComposerResize
38
+ onResize: onComposerResize,
39
+ onKeyDown: onComposerKeyDown
34
40
  },
35
41
  actionRef,
36
42
  autoScroll,
@@ -39,6 +45,10 @@ const ChatContainer = props => {
39
45
  hasMoreItems,
40
46
  getMoreMessages
41
47
  } = props;
48
+ const bannerRef = React.useRef({
49
+ focusOnWrapper: noop,
50
+ focusOnLink: noop
51
+ });
42
52
  const containerRef = React.useRef();
43
53
  const listRef = React.useRef({
44
54
  scrollToIndex: noop
@@ -53,6 +63,29 @@ const ChatContainer = props => {
53
63
  }
54
64
  }, [onComposerResize, messagesListProps.messages, autoScroll]);
55
65
  const Container = device === 'desktop' ? StyledChatContainerContent : MobileStyledChatContainerContent;
66
+ const handleTabs = React.useCallback(e => {
67
+ if (onComposerKeyDown) onComposerKeyDown(e);else {
68
+ const ref = actionRef || listRef;
69
+
70
+ if (e.shiftKey && e.key === 'Tab') {
71
+ e.preventDefault();
72
+
73
+ if (['top', 'bottom'].includes(bannerPosition)) {
74
+ bannerRef.current.focusOnWrapper();
75
+ } else {
76
+ const last = ref.current.getMessagesInView().pop();
77
+ ref.current.focusToIndexWithoutScroll(last);
78
+ }
79
+ }
80
+ }
81
+ }, [actionRef, onComposerKeyDown, bannerPosition]); // Map actions
82
+
83
+ React.useEffect(() => {
84
+ if (actionRef && actionRef.current) {
85
+ actionRef.current.focusOnBanner = bannerRef.current.focusOnWrapper;
86
+ actionRef.current.focusOnBannerLink = bannerRef.current.focusOnLink;
87
+ }
88
+ }, [actionRef]);
56
89
  return /*#__PURE__*/jsxs(Container, {
57
90
  rows: ['minmax(0, 1fr)', 'auto'],
58
91
  ref: containerRef,
@@ -60,7 +93,8 @@ const ChatContainer = props => {
60
93
  "aria-label": "chat window",
61
94
  children: [/*#__PURE__*/_jsx("div", {
62
95
  style: {
63
- position: 'relative'
96
+ position: 'relative',
97
+ overflow: 'hidden'
64
98
  }
65
99
  }, void 0, /*#__PURE__*/jsx(ChatContainerMessagesList, _objectSpread(_objectSpread({}, messagesListProps), {}, {
66
100
  actionRef: actionRef || listRef,
@@ -68,13 +102,17 @@ const ChatContainer = props => {
68
102
  hasMoreItems: hasMoreItems,
69
103
  getMoreMessages: getMoreMessages,
70
104
  sendingMessages: sendingMessages,
71
- sendingText: sendingText
105
+ sendingText: sendingText,
106
+ bannerPosition: bannerPosition,
107
+ bannerRef: bannerRef
72
108
  })), ['top', 'bottom'].includes(isLoading) ? /*#__PURE__*/_jsx(StyledIndicatorContainer, {
73
- isLoading: isLoading
109
+ isLoading: isLoading,
110
+ "data-testid": "ds-chat-loading-indicator"
74
111
  }, void 0, _DSIndeterminateProgr || (_DSIndeterminateProgr = /*#__PURE__*/_jsx(DSIndeterminateProgressIndicator, {
75
112
  processing: true,
76
113
  title: "Loading"
77
- }))) : null, ['top', 'bottom'].includes(bannerPosition) ? /*#__PURE__*/_jsx(StyledIndicatorContainer, {
114
+ }))) : null, /*#__PURE__*/_jsx(StyledIndicatorContainer, {
115
+ linear: true,
78
116
  isLoading: bannerPosition
79
117
  }, void 0, /*#__PURE__*/_jsx(DSBanner, {
80
118
  showCloseButton: true,
@@ -88,15 +126,18 @@ const ChatContainer = props => {
88
126
  },
89
127
  onClose: bannerProps.onClose,
90
128
  isOpen: true,
91
- type: BANNER_TYPES.INFO
92
- })) : null, sendingMessages && sendingMessages.length > 0 ? _StyledIndicatorConta || (_StyledIndicatorConta = /*#__PURE__*/_jsx(StyledIndicatorContainer, {
129
+ type: bannerProps.type || BANNER_TYPES.INFO,
130
+ actionRef: bannerRef
131
+ })), sendingMessages && sendingMessages.length > 0 ? _StyledIndicatorConta || (_StyledIndicatorConta = /*#__PURE__*/_jsx(StyledIndicatorContainer, {
93
132
  isLoading: "bottom",
94
- linear: true
133
+ linear: true,
134
+ "data-testid": "ds-chat-loading-indicator"
95
135
  }, void 0, /*#__PURE__*/_jsx(DSIndeterminateProgressIndicator, {
96
136
  processing: true,
97
137
  title: "Loading",
98
138
  lineOnly: true
99
139
  }))) : null), /*#__PURE__*/jsx(ChatComposer, _objectSpread(_objectSpread({}, composerProps), {}, {
140
+ onKeyDown: handleTabs,
100
141
  onResize: onResize,
101
142
  maxHeight: (((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.clientHeight) || 0) / 2,
102
143
  actionRef: actionRef || listRef
@@ -31,7 +31,7 @@ const containerProps = {
31
31
  hasMoreItems: PropTypes.oneOf(['top', 'bottom', undefined]).description('Show Load More button at the `top` or `bottom` of the container'),
32
32
  getMoreMessages: PropTypes.func.description('Called when the user clicks on load more').defaultValue(defaultProps.getMoreMessages),
33
33
  bannerPosition: PropTypes.oneOf(['top', 'bottom', undefined]).description('Show Loading messages indicator at the `top` or `bottom` of the container'),
34
- bannerProps: PropTypes.object.description('Banner configuration').defaultValue(defaultProps.bannerProps),
34
+ bannerProps: 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),
35
35
  sendingMessages: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.arrayOf(PropTypes.number)]).description('Array of ids of sending messages').defaultValue(defaultProps.sendingMessages),
36
36
  sendingText: PropTypes.string.description('Label description for messages in sending status').defaultValue(defaultProps.sendingText),
37
37
  actionRef: 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)
@@ -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
- })(["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;' : '');
13
+ })(["transition:0.4s ease-in-out;position:absolute;visibility:hidden;pointer-events:none;width:100%;padding:0 ", ";left:0;right:0;background:", ";", " ", ""], 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;}"], StyledTitleLeftBubble, StyleBodyWrapper, StyledTitleRightBubble, Wrapper, Title, Message, Time, StyledComposerInput);