@hipay/hipay-material-ui 2.0.0-beta.36 → 2.0.0-beta.37

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 (85) hide show
  1. package/HiAppBar/HiAppBar.js +0 -2
  2. package/HiCell/CellAddress.js +140 -0
  3. package/HiCell/CellDate.js +140 -0
  4. package/HiCell/CellIcon.js +122 -0
  5. package/HiCell/CellImage.js +132 -0
  6. package/HiCell/CellNumeric.js +122 -0
  7. package/HiCell/CellPinToAction.js +92 -0
  8. package/HiCell/CellRate.js +184 -0
  9. package/HiCell/CellSentinel.js +179 -0
  10. package/HiCell/CellText.js +250 -0
  11. package/HiCell/index.js +71 -0
  12. package/HiCheckbox/HiCheckbox.js +2 -2
  13. package/HiDatePicker/Caption.js +0 -1
  14. package/HiDatePicker/HiDatePicker.js +1 -1
  15. package/HiDatePicker/HiDateRangePicker.js +756 -0
  16. package/HiDatePicker/HiDateRangeSelector.js +495 -0
  17. package/HiDatePicker/ListPicker.js +0 -1
  18. package/HiDatePicker/ListPicker.spec.js +1 -2
  19. package/HiDatePicker/NavBar.js +2 -2
  20. package/HiDatePicker/NavBar.spec.js +4 -5
  21. package/HiDatePicker/Overlays/CustomOverlayLayout.js +0 -1
  22. package/HiDatePicker/Overlays/MonthPickerOverlay.js +0 -1
  23. package/HiDatePicker/Overlays/MonthPickerOverlay.spec.js +0 -1
  24. package/HiDatePicker/Overlays/Overlay.js +0 -1
  25. package/HiDatePicker/Overlays/Overlay.spec.js +0 -5
  26. package/HiDatePicker/Overlays/TimePickerOverlay.js +0 -1
  27. package/HiDatePicker/Overlays/TimePickerOverlay.spec.js +0 -1
  28. package/HiDatePicker/Overlays/YearPickerOverlay.js +0 -1
  29. package/HiDatePicker/Overlays/YearPickerOverlay.spec.js +0 -1
  30. package/HiDatePicker/Weekday.js +0 -1
  31. package/HiDatePicker/stylesheet.js +7 -3
  32. package/HiForm/HiFormControl.js +23 -3
  33. package/HiForm/HiInput.js +2 -2
  34. package/HiSelect/HiSelect.js +1 -1
  35. package/HiSelect/HiSuggestSelect.js +8 -8
  36. package/HiSelectableList/HiSelectableList.js +3 -1
  37. package/HiSelectableList/HiSelectableListItem.js +14 -11
  38. package/es/HiAppBar/HiAppBar.js +0 -2
  39. package/es/HiCell/CellAddress.js +97 -0
  40. package/es/HiCell/CellDate.js +94 -0
  41. package/es/HiCell/CellIcon.js +83 -0
  42. package/es/HiCell/CellImage.js +91 -0
  43. package/es/HiCell/CellNumeric.js +80 -0
  44. package/es/HiCell/CellPinToAction.js +53 -0
  45. package/es/HiCell/CellRate.js +142 -0
  46. package/es/HiCell/CellSentinel.js +140 -0
  47. package/es/HiCell/CellText.js +198 -0
  48. package/es/HiCell/index.js +8 -0
  49. package/es/HiCheckbox/HiCheckbox.js +2 -2
  50. package/es/HiDatePicker/Caption.js +0 -1
  51. package/es/HiDatePicker/HiDatePicker.js +1 -1
  52. package/es/HiDatePicker/HiDateRangePicker.js +661 -0
  53. package/es/HiDatePicker/HiDateRangeSelector.js +432 -0
  54. package/es/HiDatePicker/ListPicker.js +0 -1
  55. package/es/HiDatePicker/ListPicker.spec.js +1 -2
  56. package/es/HiDatePicker/NavBar.js +2 -2
  57. package/es/HiDatePicker/NavBar.spec.js +4 -5
  58. package/es/HiDatePicker/Overlays/CustomOverlayLayout.js +0 -1
  59. package/es/HiDatePicker/Overlays/MonthPickerOverlay.js +0 -1
  60. package/es/HiDatePicker/Overlays/MonthPickerOverlay.spec.js +0 -1
  61. package/es/HiDatePicker/Overlays/Overlay.js +0 -1
  62. package/es/HiDatePicker/Overlays/Overlay.spec.js +0 -3
  63. package/es/HiDatePicker/Overlays/TimePickerOverlay.js +0 -1
  64. package/es/HiDatePicker/Overlays/TimePickerOverlay.spec.js +0 -1
  65. package/es/HiDatePicker/Overlays/YearPickerOverlay.js +0 -1
  66. package/es/HiDatePicker/Overlays/YearPickerOverlay.spec.js +0 -1
  67. package/es/HiDatePicker/Overlays/index.js +0 -1
  68. package/es/HiDatePicker/Weekday.js +0 -1
  69. package/es/HiDatePicker/stylesheet.js +7 -3
  70. package/es/HiForm/HiFormControl.js +22 -3
  71. package/es/HiForm/HiInput.js +2 -2
  72. package/es/HiSelect/HiSelect.js +1 -1
  73. package/es/HiSelect/HiSuggestSelect.js +8 -8
  74. package/es/HiSelectableList/HiSelectableList.js +3 -1
  75. package/es/HiSelectableList/HiSelectableListItem.js +14 -11
  76. package/es/index.js +2 -1
  77. package/es/styles/createPalette.js +2 -1
  78. package/es/utils/helpers.js +117 -0
  79. package/index.es.js +3 -2
  80. package/index.js +1 -1
  81. package/package.json +1 -1
  82. package/styles/createPalette.js +1 -1
  83. package/umd/hipay-material-ui.development.js +39 -14
  84. package/umd/hipay-material-ui.production.min.js +2 -2
  85. package/utils/helpers.js +134 -0
@@ -0,0 +1,53 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import withStyles from '../styles/withStyles';
4
+ import HiPin from '../HiPin';
5
+ export const styles = {
6
+ wrapper: {
7
+ maxWidth: '100%',
8
+ display: 'inline-flex'
9
+ }
10
+ };
11
+ /**
12
+ * Cette cellule permet d'afficher un pin avec callback (optionnel).
13
+ */
14
+
15
+ var _ref = React.createElement(HiPin, null, "0");
16
+
17
+ class CellPinToAction extends React.PureComponent {
18
+ render() {
19
+ const {
20
+ classes,
21
+ onClick,
22
+ number
23
+ } = this.props;
24
+ if (number === undefined) return '';
25
+ return React.createElement("div", {
26
+ className: classes.wrapper
27
+ }, number === 0 ? _ref : React.createElement(HiPin, {
28
+ color: "primary",
29
+ onClick: onClick
30
+ }, number));
31
+ }
32
+
33
+ }
34
+
35
+ CellPinToAction.propTypes = process.env.NODE_ENV !== "production" ? {
36
+ /**
37
+ * Useful to extend the style applied to components.
38
+ */
39
+ classes: PropTypes.object,
40
+
41
+ /**
42
+ * Pin number to display
43
+ */
44
+ number: PropTypes.number,
45
+
46
+ /**
47
+ * Fonction de callback onClick sur le pin
48
+ */
49
+ onClick: PropTypes.func
50
+ } : {};
51
+ export default withStyles(styles, {
52
+ name: 'HmuiCellPin'
53
+ })(CellPinToAction);
@@ -0,0 +1,142 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classNames from 'classnames';
4
+ import { ArrowBottomRight, ArrowTopRight, Equal } from 'mdi-material-ui';
5
+ import { formatRate } from '../utils/helpers';
6
+ import withStyles from '../styles/withStyles';
7
+ export const styles = theme => ({
8
+ flexContent: {
9
+ display: 'flex',
10
+ flexDirection: 'column',
11
+ justifyContent: 'center',
12
+ overflow: 'hidden',
13
+ position: 'relative',
14
+ textAlign: 'right'
15
+ },
16
+ trendChipIcon: {
17
+ width: 14,
18
+ height: 14,
19
+ position: 'relative',
20
+ top: 2
21
+ },
22
+ positive: {
23
+ color: theme.palette.positive.main
24
+ },
25
+ negative: {
26
+ color: theme.palette.negative.main
27
+ },
28
+ neutral: {
29
+ color: theme.palette.neutral.main
30
+ },
31
+ spanIndicator: {
32
+ fontSize: 11,
33
+ float: 'right',
34
+ color: '#737373',
35
+ position: 'relative',
36
+ right: 3
37
+ },
38
+ rateDiv: {
39
+ position: 'relative'
40
+ }
41
+ });
42
+ /**
43
+ * Cette cellule permet d'afficher un pourcentage
44
+ * avec une icône d'évolution (optionnelle) et un indicateur du type de données représentées (optionnel)
45
+ */
46
+
47
+ class CellRate extends React.PureComponent {
48
+ render() {
49
+ const {
50
+ classes,
51
+ value,
52
+ trendchip,
53
+ isPositive,
54
+ indicator,
55
+ locale,
56
+ view
57
+ } = this.props;
58
+ let trendIcon;
59
+ const displayedRate = formatRate(value, view, locale);
60
+
61
+ switch (trendchip) {
62
+ case 'equal':
63
+ trendIcon = React.createElement(Equal, {
64
+ className: classNames(classes.trendChipIcon, classes.neutral)
65
+ });
66
+ break;
67
+
68
+ case 'up':
69
+ trendIcon = React.createElement(ArrowTopRight, {
70
+ className: classNames(classes.trendChipIcon, {
71
+ [classes.positive]: isPositive,
72
+ [classes.negative]: !isPositive
73
+ })
74
+ });
75
+ break;
76
+
77
+ case 'down':
78
+ trendIcon = React.createElement(ArrowBottomRight, {
79
+ className: classNames(classes.trendChipIcon, {
80
+ [classes.positive]: !isPositive,
81
+ [classes.negative]: isPositive
82
+ })
83
+ });
84
+ break;
85
+
86
+ default:
87
+ break;
88
+ }
89
+
90
+ return React.createElement("div", {
91
+ className: classes.flexContent
92
+ }, React.createElement("div", {
93
+ className: typeof indicator === 'undefined' && classes.rateDiv || ''
94
+ }, displayedRate, trendIcon), typeof indicator !== 'undefined' && React.createElement("span", {
95
+ className: classes.spanIndicator
96
+ }, indicator));
97
+ }
98
+
99
+ }
100
+
101
+ CellRate.defaultProps = {
102
+ isPositive: true
103
+ };
104
+ CellRate.propTypes = process.env.NODE_ENV !== "production" ? {
105
+ /**
106
+ * Useful to extend the style applied to components.
107
+ */
108
+ classes: PropTypes.object,
109
+
110
+ /**
111
+ * Spécifie le type de donnée évalué (ex: 'volume', 'amount', ...)
112
+ */
113
+ indicator: PropTypes.string,
114
+
115
+ /**
116
+ * True si une augmentation est considérée comme positive, détermine la couleur de l'icône
117
+ */
118
+ isPositive: PropTypes.bool,
119
+
120
+ /**
121
+ * Locale BCP 47
122
+ */
123
+ locale: PropTypes.string,
124
+
125
+ /**
126
+ * Évolution par rapport à la période précédente, détermine l'icône associée
127
+ */
128
+ trendchip: PropTypes.oneOf(['up', 'down', 'equal']).isRequired,
129
+
130
+ /**
131
+ * Rate
132
+ */
133
+ value: PropTypes.number.isRequired,
134
+
135
+ /**
136
+ * View (L/M/S)
137
+ */
138
+ view: PropTypes.oneOf(['l', 'm', 's'])
139
+ } : {};
140
+ export default withStyles(styles, {
141
+ name: 'HmuiCellRate'
142
+ })(CellRate);
@@ -0,0 +1,140 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import HiColoredLabel from '../HiColoredLabel';
4
+ import withStyles from '../styles/withStyles';
5
+ export const styles = {
6
+ smartDecision: {
7
+ marginLeft: 2,
8
+ display: 'inline-block',
9
+ minWidth: 18
10
+ },
11
+ label: {
12
+ marginLeft: 2
13
+ },
14
+ nowrap: {
15
+ whiteSpace: 'nowrap'
16
+ }
17
+ };
18
+ /**
19
+ * Get Theme color from fraudResult
20
+ * @param fraudResult
21
+ * @returns {*}
22
+ */
23
+
24
+ function getColorFromFraudResult(fraudResult) {
25
+ let color;
26
+
27
+ switch (fraudResult.toUpperCase()) {
28
+ case 'ACCEPTED':
29
+ color = 'positive';
30
+ break;
31
+
32
+ case 'BLOCKED':
33
+ color = 'negative';
34
+ break;
35
+
36
+ case 'CHALLENGED':
37
+ color = 'middle';
38
+ break;
39
+
40
+ case 'PENDING':
41
+ color = 'primary';
42
+ break;
43
+
44
+ case 'FORCE_AUTHENTICATE':
45
+ case 'ASK_AUTHENTICATE':
46
+ default:
47
+ color = 'neutral';
48
+ break;
49
+ }
50
+
51
+ return color;
52
+ }
53
+ /**
54
+ * Cette cellule permet d'afficher le résultat de Sentinel (score & fraudResult & smartDecision)
55
+ */
56
+
57
+
58
+ class CellSentinel extends React.PureComponent {
59
+ render() {
60
+ const {
61
+ classes,
62
+ score,
63
+ fraudResult,
64
+ automaticFraudReviewResult,
65
+ pendingManualAction,
66
+ smartDecision,
67
+ hideFraudResult
68
+ } = this.props;
69
+ const scoreLabel = score > 0 ? `+${score}` : `${score}`;
70
+ return React.createElement("div", {
71
+ style: {
72
+ textAlign: 'right'
73
+ }
74
+ }, React.createElement(HiColoredLabel, {
75
+ label: scoreLabel,
76
+ color: getColorFromFraudResult(fraudResult),
77
+ classes: {
78
+ root: classes.label
79
+ },
80
+ active: pendingManualAction
81
+ }), !hideFraudResult && React.createElement(HiColoredLabel, {
82
+ label: fraudResult.toUpperCase().substr(0, 1),
83
+ color: getColorFromFraudResult(fraudResult),
84
+ classes: {
85
+ root: classes.label
86
+ },
87
+ active: pendingManualAction
88
+ }), !!smartDecision && React.createElement("div", {
89
+ className: classes.smartDecision
90
+ }, automaticFraudReviewResult && React.createElement(HiColoredLabel, {
91
+ label: automaticFraudReviewResult.toUpperCase().substr(0, 1),
92
+ color: getColorFromFraudResult(automaticFraudReviewResult),
93
+ active: pendingManualAction
94
+ })));
95
+ }
96
+
97
+ }
98
+
99
+ CellSentinel.defaultProps = {
100
+ hideFraudResult: false
101
+ };
102
+ CellSentinel.propTypes = process.env.NODE_ENV !== "production" ? {
103
+ /**
104
+ * Résultat de l'automaticFraudReview si la transaction est passée par SmartDecision
105
+ */
106
+ automaticFraudReviewResult: PropTypes.string,
107
+
108
+ /**
109
+ * Useful to extend the style applied to components.
110
+ */
111
+ classes: PropTypes.object,
112
+
113
+ /**
114
+ * Résultat de la fraude
115
+ */
116
+ fraudResult: PropTypes.string.isRequired,
117
+
118
+ /**
119
+ * Si true le fraudResult ne sera pas affiché
120
+ */
121
+ hideFraudResult: PropTypes.bool,
122
+
123
+ /**
124
+ * Signal qu'il attend une réponse manuelle
125
+ */
126
+ pendingManualAction: PropTypes.bool,
127
+
128
+ /**
129
+ * Score de la fraude
130
+ */
131
+ score: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
132
+
133
+ /**
134
+ * Active le SmartDecision (ajoute l'indicateur ou blanc)
135
+ */
136
+ smartDecision: PropTypes.bool
137
+ } : {};
138
+ export default withStyles(styles, {
139
+ name: 'HmuiCellSentinel'
140
+ })(CellSentinel);
@@ -0,0 +1,198 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import withStyles from '../styles/withStyles';
4
+ import HiColoredLabel from '../HiColoredLabel';
5
+ export const styles = {
6
+ leftEllipsisSpan: {
7
+ display: 'inline-block',
8
+ overflow: 'hidden',
9
+ textOverflow: 'ellipsis',
10
+ whiteSpace: 'pre',
11
+ direction: 'rtl'
12
+ },
13
+ rightEllipsisSpan: {
14
+ display: 'inline-block',
15
+ overflow: 'hidden',
16
+ textOverflow: 'ellipsis',
17
+ whiteSpace: 'pre'
18
+ },
19
+ noEllipsisSpan: {
20
+ display: 'inline-block',
21
+ overflow: 'hidden',
22
+ whiteSpace: 'pre'
23
+ }
24
+ };
25
+
26
+ class CellText extends React.Component {
27
+ constructor(props) {
28
+ super(props);
29
+ this.cellText = null;
30
+ this.buildEllipsis = this.buildEllipsis.bind(this);
31
+ }
32
+ /**
33
+ * TODO - Ellipsis (middle, after-first-word)
34
+ */
35
+
36
+
37
+ componentDidMount() {
38
+ this.buildEllipsis();
39
+ }
40
+
41
+ componentDidUpdate(prevProps) {
42
+ if (prevProps.label !== this.props.label) this.buildEllipsis();
43
+ }
44
+
45
+ buildEllipsis() {
46
+ /**
47
+ * Calcul l'espace disponible dans la cellule en plus du premier mot
48
+ * si il reste de l'espace, définit la largeur du span pour le reste du texte
49
+ */
50
+ if (this.props.ellipsis === 'after-first-word' || this.props.ellipsis === 'name') {
51
+ if (this.cellText !== null) {
52
+ const [startSpan, endSpan] = this.cellText.getElementsByTagName('span');
53
+
54
+ if (typeof startSpan !== 'undefined' && typeof endSpan !== 'undefined') {
55
+ const availableEndSpace = this.cellText.offsetWidth - startSpan.offsetWidth - 2;
56
+
57
+ if (availableEndSpace > 0) {
58
+ endSpan.style.width = `${availableEndSpace}px`;
59
+ } else {
60
+ startSpan.style.width = '100%';
61
+ }
62
+ }
63
+ }
64
+ }
65
+ /**
66
+ * Calcul l'espace pris par les 2 spans (les 2 moitiés du texte),
67
+ * si ils dépassent la largeur de la cellule :
68
+ * - diminue d'autant et proportionnellement chaque span
69
+ * - ajoute l'ellipse à gauche de la deuxième moitié du texte.
70
+ */
71
+
72
+
73
+ if (this.props.ellipsis === 'middle') {
74
+ if (this.cellText !== null) {
75
+ const [startSpan, endSpan] = this.cellText.getElementsByTagName('span');
76
+
77
+ if (typeof startSpan !== 'undefined' && typeof endSpan !== 'undefined') {
78
+ const availableEndSpace = this.cellText.offsetWidth - startSpan.offsetWidth - endSpan.offsetWidth;
79
+
80
+ if (availableEndSpace < 0) {
81
+ startSpan.style.width = '50%';
82
+ endSpan.style.width = '49%';
83
+ } else {
84
+ startSpan.style.width = 'initial';
85
+ endSpan.style.width = 'initial';
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ render() {
93
+ const {
94
+ classes,
95
+ label,
96
+ ellipsis,
97
+ color
98
+ } = this.props;
99
+ let start;
100
+ let end;
101
+ let valueElement = '';
102
+ const valueString = label.toString();
103
+
104
+ switch (ellipsis) {
105
+ case 'name':
106
+ case 'after-first-word':
107
+ // Split value in 2 strings around first whitespace
108
+ start = valueString.substr(0, valueString.indexOf(' '));
109
+ end = valueString.substr(valueString.indexOf(' ') + 1);
110
+
111
+ if (start === '') {
112
+ start = end;
113
+ end = '';
114
+ }
115
+
116
+ valueElement = React.createElement("div", {
117
+ ref: div => {
118
+ this.cellText = div;
119
+ }
120
+ }, React.createElement("span", {
121
+ className: classes.rightEllipsisSpan
122
+ }, `${start} `), React.createElement("span", {
123
+ className: classes.leftEllipsisSpan
124
+ }, end));
125
+ break;
126
+
127
+ case 'middle':
128
+ // Split value in 2 strings
129
+ start = valueString.substr(0, Math.round(valueString.length / 2));
130
+ end = valueString.substr(Math.round(valueString.length / 2));
131
+ valueElement = React.createElement("div", {
132
+ ref: div => {
133
+ this.cellText = div;
134
+ }
135
+ }, React.createElement("span", {
136
+ className: classes.noEllipsisSpan
137
+ }, start), React.createElement("span", {
138
+ className: classes.leftEllipsisSpan
139
+ }, end));
140
+ break;
141
+
142
+ case 'left':
143
+ valueElement = color ? React.createElement(HiColoredLabel, {
144
+ className: classes.leftEllipsisSpan,
145
+ label: valueString,
146
+ color: color
147
+ }) : React.createElement("div", {
148
+ className: classes.leftEllipsisSpan,
149
+ style: {
150
+ width: '100%'
151
+ }
152
+ }, valueString);
153
+ break;
154
+
155
+ case 'right':
156
+ default:
157
+ valueElement = color ? React.createElement(HiColoredLabel, {
158
+ className: classes.rightEllipsisSpan,
159
+ label: valueString,
160
+ color: color
161
+ }) : React.createElement("div", {
162
+ className: classes.rightEllipsisSpan,
163
+ style: {
164
+ width: '100%'
165
+ }
166
+ }, valueString);
167
+ break;
168
+ }
169
+
170
+ return valueElement;
171
+ }
172
+
173
+ }
174
+
175
+ CellText.propTypes = process.env.NODE_ENV !== "production" ? {
176
+ /**
177
+ * Useful to extend the style applied to components.
178
+ */
179
+ classes: PropTypes.object,
180
+
181
+ /**
182
+ * Couleur du text & du background
183
+ */
184
+ color: PropTypes.string,
185
+
186
+ /**
187
+ * Ellipsis
188
+ */
189
+ ellipsis: PropTypes.oneOf(['left', 'right', 'middle', 'name', 'after-first-word']),
190
+
191
+ /**
192
+ * Label à afficher
193
+ */
194
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
195
+ } : {};
196
+ export default withStyles(styles, {
197
+ name: 'HmuiCellText'
198
+ })(CellText);
@@ -0,0 +1,8 @@
1
+ export { default as CellAddress } from './CellAddress';
2
+ export { default as CellDate } from './CellDate';
3
+ export { default as CellIcon } from './CellIcon';
4
+ export { default as CellImage } from './CellImage';
5
+ export { default as CellNumeric } from './CellNumeric';
6
+ export { default as CellRate } from './CellRate';
7
+ export { default as CellSentinel } from './CellSentinel';
8
+ export { default as CellText } from './CellText';
@@ -10,8 +10,8 @@ import HiIcon from '../HiIcon';
10
10
  import classNames from 'classnames';
11
11
  export const styles = theme => ({
12
12
  root: {
13
- marginRight: 6,
14
- marginLeft: 6,
13
+ marginRight: 4,
14
+ marginLeft: 4,
15
15
  padding: 0
16
16
  },
17
17
  checked: {},
@@ -1,5 +1,4 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/objectSpread";
2
- // @flow weak
3
2
  import React from 'react';
4
3
  import PropTypes from 'prop-types';
5
4
  import withStyles from '../styles/withStyles';
@@ -213,7 +213,7 @@ class HiDatePicker extends React.Component {
213
213
  todayButton: translations.today,
214
214
  onTodayButtonClick: this.handleCurrentMonthChange,
215
215
  weekdayElement: Weekday,
216
- navbarElement: props2 => React.createElement(NavBar, _extends({
216
+ NavBarElement: props2 => React.createElement(NavBar, _extends({
217
217
  showClockButton: enableTime,
218
218
  onClockClick: this.handleClockClick
219
219
  }, props2)),