@transferwise/components 46.27.0 → 46.28.0

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 (125) hide show
  1. package/build/i18n/th.json +2 -2
  2. package/build/index.js +327 -630
  3. package/build/index.js.map +1 -1
  4. package/build/index.mjs +328 -631
  5. package/build/index.mjs.map +1 -1
  6. package/build/types/alert/Alert.d.ts +47 -58
  7. package/build/types/alert/Alert.d.ts.map +1 -1
  8. package/build/types/alert/index.d.ts +2 -1
  9. package/build/types/alert/index.d.ts.map +1 -1
  10. package/build/types/button/Button.d.ts +7 -9
  11. package/build/types/button/Button.d.ts.map +1 -1
  12. package/build/types/common/dateUtils/isWithinRange/isWithinRange.d.ts +1 -1
  13. package/build/types/common/dateUtils/isWithinRange/isWithinRange.d.ts.map +1 -1
  14. package/build/types/common/dateUtils/moveToWithinRange/moveToWithinRange.d.ts +1 -1
  15. package/build/types/common/dateUtils/moveToWithinRange/moveToWithinRange.d.ts.map +1 -1
  16. package/build/types/common/propsValues/sentiment.d.ts +0 -1
  17. package/build/types/common/propsValues/sentiment.d.ts.map +1 -1
  18. package/build/types/dateLookup/DateLookup.d.ts +75 -28
  19. package/build/types/dateLookup/DateLookup.d.ts.map +1 -1
  20. package/build/types/dateLookup/DateLookup.messages.d.ts +42 -63
  21. package/build/types/dateLookup/DateLookup.messages.d.ts.map +1 -1
  22. package/build/types/dateLookup/dateHeader/DateHeader.d.ts +9 -22
  23. package/build/types/dateLookup/dateHeader/DateHeader.d.ts.map +1 -1
  24. package/build/types/dateLookup/dateHeader/index.d.ts +1 -1
  25. package/build/types/dateLookup/dateHeader/index.d.ts.map +1 -1
  26. package/build/types/dateLookup/dateTrigger/DateTrigger.d.ts +13 -31
  27. package/build/types/dateLookup/dateTrigger/DateTrigger.d.ts.map +1 -1
  28. package/build/types/dateLookup/dateTrigger/index.d.ts +1 -1
  29. package/build/types/dateLookup/dateTrigger/index.d.ts.map +1 -1
  30. package/build/types/dateLookup/dayCalendar/DayCalendar.d.ts +19 -2
  31. package/build/types/dateLookup/dayCalendar/DayCalendar.d.ts.map +1 -1
  32. package/build/types/dateLookup/dayCalendar/index.d.ts +1 -1
  33. package/build/types/dateLookup/dayCalendar/index.d.ts.map +1 -1
  34. package/build/types/dateLookup/dayCalendar/table/DayCalendarTable.d.ts +12 -2
  35. package/build/types/dateLookup/dayCalendar/table/DayCalendarTable.d.ts.map +1 -1
  36. package/build/types/dateLookup/dayCalendar/table/index.d.ts +1 -1
  37. package/build/types/dateLookup/dayCalendar/table/index.d.ts.map +1 -1
  38. package/build/types/dateLookup/getStartOfDay/getStartOfDay.d.ts +1 -1
  39. package/build/types/dateLookup/getStartOfDay/getStartOfDay.d.ts.map +1 -1
  40. package/build/types/dateLookup/getStartOfDay/index.d.ts +1 -1
  41. package/build/types/dateLookup/getStartOfDay/index.d.ts.map +1 -1
  42. package/build/types/dateLookup/index.d.ts +2 -1
  43. package/build/types/dateLookup/index.d.ts.map +1 -1
  44. package/build/types/dateLookup/monthCalendar/MonthCalendar.d.ts +17 -2
  45. package/build/types/dateLookup/monthCalendar/MonthCalendar.d.ts.map +1 -1
  46. package/build/types/dateLookup/monthCalendar/index.d.ts +1 -1
  47. package/build/types/dateLookup/monthCalendar/index.d.ts.map +1 -1
  48. package/build/types/dateLookup/monthCalendar/table/MonthCalendarTable.d.ts +10 -26
  49. package/build/types/dateLookup/monthCalendar/table/MonthCalendarTable.d.ts.map +1 -1
  50. package/build/types/dateLookup/monthCalendar/table/index.d.ts +1 -1
  51. package/build/types/dateLookup/monthCalendar/table/index.d.ts.map +1 -1
  52. package/build/types/dateLookup/yearCalendar/YearCalendar.d.ts +15 -2
  53. package/build/types/dateLookup/yearCalendar/YearCalendar.d.ts.map +1 -1
  54. package/build/types/dateLookup/yearCalendar/index.d.ts +1 -1
  55. package/build/types/dateLookup/yearCalendar/index.d.ts.map +1 -1
  56. package/build/types/dateLookup/yearCalendar/table/YearCalendarTable.d.ts +10 -26
  57. package/build/types/dateLookup/yearCalendar/table/YearCalendarTable.d.ts.map +1 -1
  58. package/build/types/dateLookup/yearCalendar/table/index.d.ts +1 -1
  59. package/build/types/dateLookup/yearCalendar/table/index.d.ts.map +1 -1
  60. package/build/types/index.d.ts +2 -1
  61. package/build/types/index.d.ts.map +1 -1
  62. package/build/types/inlineAlert/InlineAlert.d.ts +2 -4
  63. package/build/types/inlineAlert/InlineAlert.d.ts.map +1 -1
  64. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  65. package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
  66. package/build/types/inputs/_Popover.d.ts.map +1 -1
  67. package/build/types/statusIcon/StatusIcon.d.ts +1 -1
  68. package/build/types/statusIcon/StatusIcon.d.ts.map +1 -1
  69. package/package.json +1 -1
  70. package/src/alert/{Alert.spec.js → Alert.spec.tsx} +43 -40
  71. package/src/alert/Alert.story.tsx +1 -2
  72. package/src/alert/Alert.tsx +218 -0
  73. package/src/alert/index.ts +2 -0
  74. package/src/button/Button.tsx +6 -10
  75. package/src/common/dateUtils/isWithinRange/isWithinRange.spec.ts +21 -0
  76. package/src/common/dateUtils/isWithinRange/isWithinRange.ts +2 -2
  77. package/src/common/dateUtils/moveToWithinRange/moveToWithinRange.ts +8 -4
  78. package/src/common/propsValues/sentiment.ts +0 -10
  79. package/src/dateLookup/DateLookup.state.spec.js +7 -0
  80. package/src/dateLookup/{DateLookup.story.js → DateLookup.story.tsx} +13 -14
  81. package/src/dateLookup/DateLookup.tests.story.tsx +70 -0
  82. package/src/dateLookup/{DateLookup.js → DateLookup.tsx} +115 -81
  83. package/src/dateLookup/dateHeader/{DateHeader.js → DateHeader.tsx} +15 -15
  84. package/src/dateLookup/dateTrigger/DateTrigger.spec.js +0 -22
  85. package/src/dateLookup/dateTrigger/{DateTrigger.js → DateTrigger.tsx} +15 -32
  86. package/src/dateLookup/dayCalendar/{DayCalendar.js → DayCalendar.tsx} +14 -21
  87. package/src/dateLookup/dayCalendar/table/{DayCalendarTable.js → DayCalendarTable.tsx} +26 -37
  88. package/src/dateLookup/getStartOfDay/{getStartOfDay.js → getStartOfDay.tsx} +1 -1
  89. package/src/dateLookup/index.ts +2 -0
  90. package/src/dateLookup/monthCalendar/{MonthCalendar.js → MonthCalendar.tsx} +19 -22
  91. package/src/dateLookup/monthCalendar/table/{MonthCalendarTable.js → MonthCalendarTable.tsx} +31 -30
  92. package/src/dateLookup/yearCalendar/{YearCalendar.js → YearCalendar.tsx} +18 -21
  93. package/src/dateLookup/yearCalendar/table/{YearCalendarTable.js → YearCalendarTable.tsx} +26 -28
  94. package/src/i18n/th.json +2 -2
  95. package/src/index.ts +2 -1
  96. package/src/inlineAlert/InlineAlert.spec.tsx +0 -7
  97. package/src/inlineAlert/InlineAlert.tsx +19 -47
  98. package/src/inputs/InputGroup.tsx +3 -3
  99. package/src/inputs/SelectInput.tsx +1 -0
  100. package/src/inputs/_BottomSheet.tsx +44 -54
  101. package/src/inputs/_Popover.tsx +20 -23
  102. package/src/statusIcon/StatusIcon.tsx +14 -14
  103. package/build/types/alert/withArrow/alertArrowPositions.d.ts +0 -9
  104. package/build/types/alert/withArrow/alertArrowPositions.d.ts.map +0 -1
  105. package/build/types/alert/withArrow/index.d.ts +0 -3
  106. package/build/types/alert/withArrow/index.d.ts.map +0 -1
  107. package/build/types/alert/withArrow/withArrow.d.ts +0 -11
  108. package/build/types/alert/withArrow/withArrow.d.ts.map +0 -1
  109. package/src/alert/Alert.js +0 -196
  110. package/src/alert/index.js +0 -1
  111. package/src/alert/withArrow/alertArrowPositions.ts +0 -9
  112. package/src/alert/withArrow/index.js +0 -2
  113. package/src/alert/withArrow/withArrow.js +0 -50
  114. package/src/alert/withArrow/withArrow.spec.js +0 -51
  115. package/src/dateLookup/index.js +0 -1
  116. /package/src/dateLookup/{DateLookup.messages.js → DateLookup.messages.ts} +0 -0
  117. /package/src/dateLookup/dateHeader/{index.js → index.ts} +0 -0
  118. /package/src/dateLookup/dateTrigger/{index.js → index.ts} +0 -0
  119. /package/src/dateLookup/dayCalendar/{index.js → index.ts} +0 -0
  120. /package/src/dateLookup/dayCalendar/table/{index.js → index.ts} +0 -0
  121. /package/src/dateLookup/getStartOfDay/{index.js → index.ts} +0 -0
  122. /package/src/dateLookup/monthCalendar/{index.js → index.ts} +0 -0
  123. /package/src/dateLookup/monthCalendar/table/{index.js → index.ts} +0 -0
  124. /package/src/dateLookup/yearCalendar/{index.js → index.ts} +0 -0
  125. /package/src/dateLookup/yearCalendar/table/{index.js → index.ts} +0 -0
@@ -1,8 +1,15 @@
1
1
  import classNames from 'classnames';
2
- import PropTypes from 'prop-types';
3
- import { createRef, PureComponent } from 'react';
2
+ import { createRef, PureComponent, KeyboardEvent } from 'react';
4
3
 
5
- import { Size, MonthFormat, Position, Breakpoint } from '../common';
4
+ import {
5
+ Size,
6
+ MonthFormat,
7
+ Position,
8
+ Breakpoint,
9
+ SizeSmall,
10
+ SizeMedium,
11
+ SizeLarge,
12
+ } from '../common';
6
13
  import { isWithinRange, moveToWithinRange } from '../common/dateUtils';
7
14
  import ResponsivePanel from '../common/responsivePanel';
8
15
 
@@ -12,18 +19,55 @@ import { getStartOfDay } from './getStartOfDay';
12
19
  import MonthCalendar from './monthCalendar';
13
20
  import YearCalendar from './yearCalendar';
14
21
 
15
- const MODE = {
16
- DAY: 'day',
17
- MONTH: 'month',
18
- YEAR: 'year',
19
- };
22
+ export interface DateLookupProps {
23
+ id?: string;
24
+ value: Date | null;
25
+ min?: Date | null;
26
+ max?: Date | null;
27
+ size?: SizeSmall | SizeMedium | SizeLarge;
28
+ placeholder?: string;
29
+ label?: string;
30
+ 'aria-labelledby'?: string;
31
+ monthFormat?: `${MonthFormat}`;
32
+ disabled?: boolean;
33
+ clearable?: boolean;
34
+ onChange: (date: Date | null) => void;
35
+ onFocus?: () => void;
36
+ onBlur?: () => void;
37
+ }
38
+
39
+ interface DateLookupState {
40
+ selectedDate: Date | null;
41
+ originalDate: Date | null;
42
+ min: Date | null;
43
+ max: Date | null;
44
+ viewMonth: number;
45
+ viewYear: number;
46
+ open: boolean;
47
+ mode: 'day' | 'month' | 'year';
48
+ isMobile: boolean;
49
+ }
50
+
51
+ class DateLookup extends PureComponent<DateLookupProps, DateLookupState> {
52
+ declare props: DateLookupProps &
53
+ Required<Pick<DateLookupProps, keyof typeof DateLookup.defaultProps>>;
20
54
 
21
- class DateLookup extends PureComponent {
22
- element = createRef();
55
+ static defaultProps = {
56
+ value: null,
57
+ min: null,
58
+ max: null,
59
+ size: Size.MEDIUM,
60
+ placeholder: '',
61
+ label: '',
62
+ monthFormat: MonthFormat.LONG,
63
+ disabled: false,
64
+ clearable: false,
65
+ } satisfies Partial<DateLookupProps>;
23
66
 
24
- dropdown = createRef();
67
+ element = createRef<HTMLDivElement>();
68
+ dropdown = createRef<HTMLDivElement>();
25
69
 
26
- constructor(props) {
70
+ constructor(props: DateLookup['props']) {
27
71
  super(props);
28
72
  this.state = {
29
73
  selectedDate: getStartOfDay(props.value),
@@ -33,40 +77,41 @@ class DateLookup extends PureComponent {
33
77
  viewMonth: (props.value || new Date()).getMonth(),
34
78
  viewYear: (props.value || new Date()).getFullYear(),
35
79
  open: false,
36
- mode: MODE.DAY,
80
+ mode: 'day',
37
81
  isMobile: false,
38
82
  };
39
83
  }
40
84
 
41
- static getDerivedStateFromProps(props, state) {
85
+ static getDerivedStateFromProps(props: DateLookup['props'], state: DateLookupState) {
42
86
  const propsSelected = getStartOfDay(props.value);
43
87
  const propsMin = getStartOfDay(props.min);
44
88
  const propsMax = getStartOfDay(props.max);
45
- const hasSelectedChanged = +state.selectedDate !== +propsSelected;
46
- const hasMinChanged = +state.min !== +propsMin;
47
- const hasMaxChanged = +state.max !== +propsMax;
89
+ const hasSelectedChanged = state.selectedDate?.getTime() !== propsSelected?.getTime();
90
+ const hasMinChanged = state.min?.getTime() !== propsMin?.getTime();
91
+ const hasMaxChanged = state.max?.getTime() !== propsMax?.getTime();
48
92
  if (hasSelectedChanged || hasMinChanged || hasMaxChanged) {
49
93
  const selectedDate = hasSelectedChanged ? propsSelected : state.selectedDate;
50
94
  const min = hasMinChanged ? propsMin : state.min;
51
95
  const max = hasMaxChanged ? propsMax : state.max;
52
- // make sure that selected date is within allowed range
53
- if (!isWithinRange(selectedDate, min, max)) {
96
+ if (selectedDate && !isWithinRange(selectedDate, min, max)) {
54
97
  props.onChange(moveToWithinRange(selectedDate, min, max));
55
98
  return null;
56
99
  }
57
- const viewMonth = (selectedDate || new Date()).getMonth();
58
- const viewYear = (selectedDate || new Date()).getFullYear();
100
+ const viewDateThatIsWithinRange: Date =
101
+ selectedDate || ((min || max) && moveToWithinRange(new Date(), min, max)) || new Date();
102
+ const viewMonth = viewDateThatIsWithinRange.getMonth();
103
+ const viewYear = viewDateThatIsWithinRange.getFullYear();
59
104
  return { selectedDate, min, max, viewMonth, viewYear };
60
105
  }
61
106
  return null;
62
107
  }
63
108
 
64
- componentDidUpdate(previousProps) {
65
- if (+this.props.value !== +previousProps.value && this.state.open) {
109
+ componentDidUpdate(previousProps: DateLookupProps) {
110
+ if (this.props.value?.getTime() !== previousProps.value?.getTime() && this.state.open) {
66
111
  this.focusOn('.active');
67
112
  }
68
- this.mediaQuery = window.matchMedia(`(max-width: ${Breakpoint.SMALL}px)`);
69
- this.setState({ isMobile: this.mediaQuery.matches });
113
+ const mediaQuery = window.matchMedia(`(max-width: ${Breakpoint.SMALL}px)`);
114
+ this.setState({ isMobile: mediaQuery.matches });
70
115
  }
71
116
 
72
117
  componentWillUnmount() {
@@ -77,7 +122,7 @@ class DateLookup extends PureComponent {
77
122
  open = () => {
78
123
  const { onFocus } = this.props;
79
124
 
80
- this.setState({ open: true, mode: MODE.DAY });
125
+ this.setState({ open: true, mode: 'day' });
81
126
  if (onFocus) {
82
127
  onFocus();
83
128
  }
@@ -99,7 +144,7 @@ class DateLookup extends PureComponent {
99
144
  }
100
145
  };
101
146
 
102
- handleKeyDown = (event) => {
147
+ handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
103
148
  const { open, originalDate } = this.state;
104
149
  switch (event.key) {
105
150
  case 'ArrowLeft':
@@ -146,29 +191,31 @@ class DateLookup extends PureComponent {
146
191
  }
147
192
  };
148
193
 
149
- adjustDate = (daysToAdd, monthsToAdd, yearsToAdd) => {
194
+ adjustDate = (daysToAdd: number, monthsToAdd: number, yearsToAdd: number) => {
150
195
  const { selectedDate, min, max, mode, originalDate } = this.state;
151
196
  if (originalDate === null) {
152
197
  this.setState({ originalDate: selectedDate });
153
198
  }
154
- let date;
199
+ let date: Date | null;
155
200
  if (selectedDate) {
156
201
  date = new Date(
157
- mode === MODE.YEAR ? selectedDate.getFullYear() + yearsToAdd : selectedDate.getFullYear(),
158
- mode === MODE.MONTH ? selectedDate.getMonth() + monthsToAdd : selectedDate.getMonth(),
159
- mode === MODE.DAY ? selectedDate.getDate() + daysToAdd : selectedDate.getDate(),
202
+ mode === 'year' ? selectedDate.getFullYear() + yearsToAdd : selectedDate.getFullYear(),
203
+ mode === 'month' ? selectedDate.getMonth() + monthsToAdd : selectedDate.getMonth(),
204
+ mode === 'day' ? selectedDate.getDate() + daysToAdd : selectedDate.getDate(),
160
205
  );
161
206
  } else {
162
207
  date = getStartOfDay(new Date());
163
208
  }
164
- date = moveToWithinRange(date, min, max);
165
- if (+date !== +selectedDate) {
209
+ if (date) {
210
+ date = moveToWithinRange(date, min, max);
211
+ }
212
+ if (date?.getTime() !== selectedDate?.getTime()) {
166
213
  this.props.onChange(date);
167
214
  }
168
215
  };
169
216
 
170
- focusOn = (preferredElement, fallbackElement) => {
171
- const element = this.element.current.querySelector(preferredElement);
217
+ focusOn = (preferredElement: string, fallbackElement?: string) => {
218
+ const element = this.element.current?.querySelector(preferredElement) as HTMLElement | null;
172
219
  if (element) {
173
220
  element.focus();
174
221
  } else if (fallbackElement) {
@@ -176,19 +223,19 @@ class DateLookup extends PureComponent {
176
223
  }
177
224
  };
178
225
 
179
- switchMode = (mode) => {
226
+ switchMode = (mode: 'day' | 'month' | 'year') => {
180
227
  this.setState({ mode }, () => {
181
228
  this.focusOn('.active', '.today');
182
229
  });
183
230
  };
184
231
 
185
- switchToDays = () => this.switchMode(MODE.DAY);
232
+ switchToDays = () => this.switchMode('day');
186
233
 
187
- switchToMonths = () => this.switchMode(MODE.MONTH);
234
+ switchToMonths = () => this.switchMode('month');
188
235
 
189
- switchToYears = () => this.switchMode(MODE.YEAR);
236
+ switchToYears = () => this.switchMode('year');
190
237
 
191
- handleSelectedDateUpdate = (selectedDate) => {
238
+ handleSelectedDateUpdate = (selectedDate: Date) => {
192
239
  this.setState({ selectedDate }, () => {
193
240
  this.props.onChange(selectedDate);
194
241
  this.close();
@@ -205,25 +252,38 @@ class DateLookup extends PureComponent {
205
252
  const { placeholder, monthFormat } = this.props;
206
253
  return (
207
254
  <div className={classNames({ 'p-a-1': !isMobile })}>
208
- {mode === MODE.DAY && (
255
+ {mode === 'day' && (
209
256
  <DayCalendar
210
- {...{ selectedDate, min, max, viewMonth, viewYear, monthFormat }}
257
+ selectedDate={selectedDate}
258
+ min={min}
259
+ max={max}
260
+ viewMonth={viewMonth}
261
+ viewYear={viewYear}
262
+ monthFormat={monthFormat}
211
263
  onSelect={this.handleSelectedDateUpdate}
212
264
  onLabelClick={this.switchToYears}
213
265
  onViewDateUpdate={this.handleViewDateUpdate}
214
266
  />
215
267
  )}
216
- {mode === MODE.MONTH && (
268
+ {mode === 'month' && (
217
269
  <MonthCalendar
218
- {...{ selectedDate, min, max, viewYear, placeholder }}
270
+ selectedDate={selectedDate}
271
+ min={min}
272
+ max={max}
273
+ viewYear={viewYear}
274
+ placeholder={placeholder}
219
275
  onSelect={this.switchToDays}
220
276
  onLabelClick={this.switchToYears}
221
277
  onViewDateUpdate={this.handleViewDateUpdate}
222
278
  />
223
279
  )}
224
- {mode === MODE.YEAR && (
280
+ {mode === 'year' && (
225
281
  <YearCalendar
226
- {...{ selectedDate, min, max, viewYear, placeholder }}
282
+ selectedDate={selectedDate}
283
+ min={min}
284
+ max={max}
285
+ viewYear={viewYear}
286
+ placeholder={placeholder}
227
287
  onSelect={this.switchToMonths}
228
288
  onViewDateUpdate={this.handleViewDateUpdate}
229
289
  />
@@ -251,7 +311,7 @@ class DateLookup extends PureComponent {
251
311
  value,
252
312
  } = this.props;
253
313
  return (
254
- <div // eslint-disable-line jsx-a11y/no-static-element-interactions
314
+ <div
255
315
  ref={this.element}
256
316
  id={this.props.id}
257
317
  aria-labelledby={ariaLabelledBy}
@@ -259,9 +319,14 @@ class DateLookup extends PureComponent {
259
319
  onKeyDown={this.handleKeyDown}
260
320
  >
261
321
  <DateTrigger
262
- {...{ selectedDate, size, placeholder, label, monthFormat, disabled }}
322
+ selectedDate={selectedDate}
323
+ size={size}
324
+ placeholder={placeholder}
325
+ label={label}
326
+ monthFormat={monthFormat}
327
+ disabled={disabled || false}
263
328
  onClick={this.open}
264
- onClear={!disabled && clearable && value ? this.handleClear : null}
329
+ onClear={!disabled && clearable && value ? this.handleClear : undefined}
265
330
  />
266
331
  <ResponsivePanel
267
332
  anchorRef={this.element}
@@ -277,35 +342,4 @@ class DateLookup extends PureComponent {
277
342
  }
278
343
  }
279
344
 
280
- DateLookup.propTypes = {
281
- id: PropTypes.string,
282
- value: PropTypes.instanceOf(Date),
283
- min: PropTypes.instanceOf(Date),
284
- max: PropTypes.instanceOf(Date),
285
- size: PropTypes.oneOf(['sm', 'md', 'lg']),
286
- placeholder: PropTypes.string,
287
- label: PropTypes.string,
288
- 'aria-labelledby': PropTypes.string,
289
- monthFormat: PropTypes.oneOf(['long', 'short']),
290
- disabled: PropTypes.bool,
291
- onChange: PropTypes.func.isRequired,
292
- onFocus: PropTypes.func,
293
- onBlur: PropTypes.func,
294
- clearable: PropTypes.bool,
295
- };
296
-
297
- DateLookup.defaultProps = {
298
- value: null,
299
- min: null,
300
- max: null,
301
- size: Size.MEDIUM,
302
- placeholder: '',
303
- label: '',
304
- monthFormat: MonthFormat.LONG,
305
- disabled: false,
306
- onFocus: null,
307
- onBlur: null,
308
- clearable: false,
309
- };
310
-
311
345
  export default DateLookup;
@@ -1,5 +1,4 @@
1
1
  import classNames from 'classnames';
2
- import PropTypes from 'prop-types';
3
2
  import { useIntl } from 'react-intl';
4
3
 
5
4
  import Chevron from '../../chevron';
@@ -10,7 +9,21 @@ import messages from '../DateLookup.messages';
10
9
 
11
10
  const buttonClasses = 'btn-link p-a-0 text-no-decoration np-text-body-large-bold rounded-sm';
12
11
 
13
- const DateHeader = ({ label, onLabelClick, onPreviousClick, onNextClick, dateMode }) => {
12
+ interface DateHeaderProps {
13
+ label?: string;
14
+ onLabelClick?: () => void;
15
+ onPreviousClick: () => void;
16
+ onNextClick: () => void;
17
+ dateMode: string;
18
+ }
19
+
20
+ const DateHeader: React.FC<DateHeaderProps> = ({
21
+ label,
22
+ onLabelClick,
23
+ onPreviousClick,
24
+ onNextClick,
25
+ dateMode,
26
+ }) => {
14
27
  const intl = useIntl();
15
28
  const { isMobile } = useLayout();
16
29
  return (
@@ -59,17 +72,4 @@ const DateHeader = ({ label, onLabelClick, onPreviousClick, onNextClick, dateMod
59
72
  );
60
73
  };
61
74
 
62
- DateHeader.propTypes = {
63
- label: PropTypes.string,
64
- onLabelClick: PropTypes.func,
65
- onPreviousClick: PropTypes.func.isRequired,
66
- onNextClick: PropTypes.func.isRequired,
67
- dateMode: PropTypes.string,
68
- };
69
-
70
- DateHeader.defaultProps = {
71
- label: null,
72
- onLabelClick: () => {},
73
- };
74
-
75
75
  export default DateHeader;
@@ -2,7 +2,6 @@ import * as formatting from '@transferwise/formatting';
2
2
  import { shallow } from 'enzyme';
3
3
 
4
4
  import Chevron from '../../chevron';
5
- import { fakeKeyDownEventForKey } from '../../common/fakeEvents';
6
5
 
7
6
  import DateTrigger from '.';
8
7
 
@@ -116,27 +115,6 @@ describe('DateTrigger', () => {
116
115
  expect(clearButton()).toHaveLength(1);
117
116
  });
118
117
 
119
- it('calls onClear when user press Space', () => {
120
- const onClear = jest.fn();
121
- component.setProps({ onClear });
122
- clearButton().simulate('keypress', fakeKeyDownEventForKey(' '));
123
- expect(onClear).toHaveBeenCalledTimes(1);
124
- });
125
-
126
- it('calls onClear when user press Enter', () => {
127
- const onClear = jest.fn();
128
- component.setProps({ onClear });
129
- clearButton().simulate('keypress', fakeKeyDownEventForKey('Enter'));
130
- expect(onClear).toHaveBeenCalledTimes(1);
131
- });
132
-
133
- it(`doesn't call onClear when user press a random key`, () => {
134
- const onClear = jest.fn();
135
- component.setProps({ onClear });
136
- clearButton().simulate('keypress', fakeKeyDownEventForKey('r'));
137
- expect(onClear).not.toHaveBeenCalled();
138
- });
139
-
140
118
  const button = () => component.find('.np-date-trigger');
141
119
  const clearButton = () => component.find('.clear-btn');
142
120
  const chevron = () => component.find(Chevron);
@@ -1,17 +1,26 @@
1
1
  import { formatDate } from '@transferwise/formatting';
2
- import { isKey } from '@transferwise/neptune-validation';
3
- import PropTypes from 'prop-types';
4
2
  import { useIntl } from 'react-intl';
5
3
 
6
4
  import Chevron from '../../chevron';
7
- import { Size, Position } from '../../common';
5
+ import { Size, Position, SizeSmall, SizeMedium, SizeLarge } from '../../common';
8
6
  import { CloseButton } from '../../common/closeButton/CloseButton';
9
7
 
10
8
  import messages from './DateTrigger.messages';
11
9
 
12
- const DateTrigger = ({
10
+ interface DateTriggerProps {
11
+ selectedDate: Date | null;
12
+ size: SizeSmall | SizeMedium | SizeLarge;
13
+ placeholder: string;
14
+ label: string;
15
+ monthFormat: 'short' | 'long';
16
+ disabled: boolean;
17
+ onClick: () => void;
18
+ onClear?: () => void;
19
+ }
20
+
21
+ const DateTrigger: React.FC<DateTriggerProps> = ({
13
22
  selectedDate,
14
- size,
23
+ size = Size.MEDIUM,
15
24
  placeholder,
16
25
  label,
17
26
  monthFormat,
@@ -21,14 +30,6 @@ const DateTrigger = ({
21
30
  }) => {
22
31
  const { locale, formatMessage } = useIntl();
23
32
 
24
- const handleKeyDown = (event) => {
25
- if (isKey({ keyType: 'Space', event: event }) || isKey({ keyType: 'Enter', event: event })) {
26
- event.stopPropagation();
27
- event.preventDefault();
28
- onClear();
29
- }
30
- };
31
-
32
33
  return (
33
34
  <>
34
35
  <button
@@ -64,12 +65,11 @@ const DateTrigger = ({
64
65
  className={`clear-btn clear-btn--${size}`}
65
66
  aria-label={`${formatMessage(messages.ariaLabel)} ${label}`}
66
67
  size={Size.SMALL}
67
- onClick={(event) => {
68
+ onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
68
69
  event.stopPropagation();
69
70
  event.preventDefault();
70
71
  onClear();
71
72
  }}
72
- onKeyPress={handleKeyDown}
73
73
  />
74
74
  </span>
75
75
  </>
@@ -78,21 +78,4 @@ const DateTrigger = ({
78
78
  );
79
79
  };
80
80
 
81
- DateTrigger.propTypes = {
82
- selectedDate: PropTypes.instanceOf(Date),
83
- size: PropTypes.oneOf(['sm', 'md', 'lg']),
84
- placeholder: PropTypes.string.isRequired,
85
- label: PropTypes.string.isRequired,
86
- monthFormat: PropTypes.oneOf(['short', 'long']).isRequired,
87
- disabled: PropTypes.bool.isRequired,
88
- onClick: PropTypes.func,
89
- onClear: PropTypes.func,
90
- };
91
-
92
- DateTrigger.defaultProps = {
93
- selectedDate: null,
94
- size: Size.MEDIUM,
95
- onClear: undefined,
96
- };
97
-
98
81
  export default DateTrigger;
@@ -1,7 +1,6 @@
1
1
  import { formatDate } from '@transferwise/formatting';
2
- import PropTypes from 'prop-types';
3
2
  import { PureComponent } from 'react';
4
- import { injectIntl } from 'react-intl';
3
+ import { injectIntl, WrappedComponentProps } from 'react-intl';
5
4
 
6
5
  import { MonthFormat } from '../../common';
7
6
  import messages from '../DateLookup.messages';
@@ -9,7 +8,19 @@ import DateHeader from '../dateHeader';
9
8
 
10
9
  import DayCalendarTable from './table';
11
10
 
12
- class DayCalendar extends PureComponent {
11
+ interface DayCalendarProps extends WrappedComponentProps {
12
+ selectedDate: Date | null;
13
+ min: Date | null;
14
+ max: Date | null;
15
+ viewMonth: number;
16
+ viewYear: number;
17
+ monthFormat: `${MonthFormat}`;
18
+ onSelect: (date: Date) => void;
19
+ onLabelClick: () => void;
20
+ onViewDateUpdate: (date: { month: number; year: number }) => void;
21
+ }
22
+
23
+ class DayCalendar extends PureComponent<DayCalendarProps> {
13
24
  selectPreviousMonth = () => {
14
25
  const { viewMonth, viewYear } = this.props;
15
26
  this.props.onViewDateUpdate({
@@ -56,22 +67,4 @@ class DayCalendar extends PureComponent {
56
67
  }
57
68
  }
58
69
 
59
- DayCalendar.propTypes = {
60
- selectedDate: PropTypes.instanceOf(Date),
61
- min: PropTypes.instanceOf(Date),
62
- max: PropTypes.instanceOf(Date),
63
- viewMonth: PropTypes.number.isRequired,
64
- viewYear: PropTypes.number.isRequired,
65
- monthFormat: PropTypes.oneOf([MonthFormat.LONG, MonthFormat.SHORT]).isRequired,
66
- onSelect: PropTypes.func.isRequired,
67
- onLabelClick: PropTypes.func.isRequired,
68
- onViewDateUpdate: PropTypes.func.isRequired,
69
- };
70
-
71
- DayCalendar.defaultProps = {
72
- selectedDate: null,
73
- min: null,
74
- max: null,
75
- };
76
-
77
70
  export default injectIntl(DayCalendar);
@@ -1,16 +1,24 @@
1
1
  import { formatDate } from '@transferwise/formatting';
2
- import PropTypes from 'prop-types';
3
2
  import { PureComponent } from 'react';
4
- import { injectIntl } from 'react-intl';
3
+ import { injectIntl, WrappedComponentProps } from 'react-intl';
5
4
 
6
5
  import { getDayNames, isWithinRange } from '../../../common/dateUtils';
7
6
  import { getFocusableTime } from '../../getFocusableTime/getFocusableTime';
8
7
  import { getStartOfDay } from '../../getStartOfDay';
9
8
  import TableLink from '../../tableLink';
10
9
 
11
- const SHORT_DAY_FORMAT = { day: 'numeric' };
10
+ const SHORT_DAY_FORMAT: Intl.DateTimeFormatOptions = { day: 'numeric' };
12
11
 
13
- class DayCalendarTable extends PureComponent {
12
+ interface DayCalendarTableProps extends WrappedComponentProps {
13
+ selectedDate: Date | null;
14
+ min: Date | null;
15
+ max: Date | null;
16
+ viewMonth: number;
17
+ viewYear: number;
18
+ onSelect: (date: Date) => void;
19
+ }
20
+
21
+ class DayCalendarTable extends PureComponent<DayCalendarTableProps> {
14
22
  getTableStructure = () => {
15
23
  const { viewMonth, viewYear } = this.props;
16
24
  let firstDayOfMonth = new Date(viewYear, viewMonth, 1).getDay();
@@ -20,13 +28,13 @@ class DayCalendarTable extends PureComponent {
20
28
  }
21
29
  const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
22
30
 
23
- let week = [];
24
- const weeks = [];
31
+ let week: number[] = [];
32
+ const weeks: number[][] = [];
25
33
  let i;
26
34
 
27
35
  // Pad first week
28
36
  for (i = 1; i < firstDayOfMonth; i += 1) {
29
- week.push(false);
37
+ week.push(-1);
30
38
  }
31
39
  // Fill in days
32
40
  for (i = 1; i <= daysInMonth; i += 1) {
@@ -39,7 +47,7 @@ class DayCalendarTable extends PureComponent {
39
47
  if (week.length > 0) {
40
48
  // Pad last week
41
49
  for (i = week.length; i < 7; i += 1) {
42
- week.push(false);
50
+ week.push(-1);
43
51
  }
44
52
  weeks.push(week);
45
53
  }
@@ -50,29 +58,29 @@ class DayCalendarTable extends PureComponent {
50
58
  daysShort = getDayNames(this.props.intl.locale, 'narrow');
51
59
  daysLong = getDayNames(this.props.intl.locale, 'long');
52
60
 
53
- selectDay = (day) => {
61
+ selectDay = (day: number) => {
54
62
  const { viewMonth, viewYear, onSelect } = this.props;
55
63
  onSelect(new Date(viewYear, viewMonth, day));
56
64
  };
57
65
 
58
- isDisabled = (day) => {
66
+ isDisabled = (day: number) => {
59
67
  const { min, max, viewMonth, viewYear } = this.props;
60
68
  const date = new Date(viewYear, viewMonth, day);
61
69
 
62
70
  return !isWithinRange(date, min, max);
63
71
  };
64
72
 
65
- isActive = (day) => {
73
+ isActive = (day: number) => {
66
74
  const { selectedDate, viewMonth, viewYear } = this.props;
67
75
  return !!(selectedDate && +new Date(viewYear, viewMonth, day) === +selectedDate);
68
76
  };
69
77
 
70
- isToday = (day) => {
78
+ isToday = (day: number) => {
71
79
  const { viewMonth, viewYear } = this.props;
72
80
  return Number(getStartOfDay(new Date())) === Number(new Date(viewYear, viewMonth, day));
73
81
  };
74
82
 
75
- getAutofocusDay = (weeks) => {
83
+ getAutofocusDay = (weeks: number[][]) => {
76
84
  const days = weeks.flatMap((week) => week);
77
85
  return getFocusableTime({
78
86
  isActive: this.isActive,
@@ -83,13 +91,9 @@ class DayCalendarTable extends PureComponent {
83
91
  };
84
92
 
85
93
  render() {
86
- const {
87
- viewMonth,
88
- viewYear,
89
- intl: { locale },
90
- } = this.props;
94
+ const { viewMonth, viewYear, intl } = this.props;
91
95
  const weeks = this.getTableStructure();
92
- let autoFocusDay = this.getAutofocusDay(weeks, viewMonth, viewYear);
96
+ const autoFocusDay = this.getAutofocusDay(weeks);
93
97
  return (
94
98
  <table className="table table-condensed table-bordered tw-date-lookup-calendar m-b-0">
95
99
  <thead>
@@ -119,17 +123,17 @@ class DayCalendarTable extends PureComponent {
119
123
  <tr key={weekIndex}>
120
124
  {week.map((day, dayIndex) => (
121
125
  <td key={dayIndex} className={dayIndex > 4 ? 'weekend' : ''}>
122
- {day && (
126
+ {day !== -1 && (
123
127
  <TableLink
124
128
  item={day}
125
129
  type="day"
126
130
  title={formatDate(
127
131
  new Date(viewYear, viewMonth, day),
128
- locale,
132
+ intl.locale,
129
133
  SHORT_DAY_FORMAT,
130
134
  )}
131
135
  autofocus={day === autoFocusDay}
132
- longTitle={formatDate(new Date(viewYear, viewMonth, day), locale)}
136
+ longTitle={formatDate(new Date(viewYear, viewMonth, day), intl.locale)}
133
137
  active={this.isActive(day)}
134
138
  disabled={this.isDisabled(day)}
135
139
  today={this.isToday(day)}
@@ -147,19 +151,4 @@ class DayCalendarTable extends PureComponent {
147
151
  }
148
152
  }
149
153
 
150
- DayCalendarTable.propTypes = {
151
- selectedDate: PropTypes.instanceOf(Date),
152
- min: PropTypes.instanceOf(Date),
153
- max: PropTypes.instanceOf(Date),
154
- viewMonth: PropTypes.number.isRequired,
155
- viewYear: PropTypes.number.isRequired,
156
- onSelect: PropTypes.func.isRequired,
157
- };
158
-
159
- DayCalendarTable.defaultProps = {
160
- selectedDate: null,
161
- min: null,
162
- max: null,
163
- };
164
-
165
154
  export default injectIntl(DayCalendarTable);