@transferwise/components 0.0.0-experimental-26e03bf → 0.0.0-experimental-c82d979

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 (195) hide show
  1. package/build/calendarInput/CalendarInput.js +159 -0
  2. package/build/calendarInput/CalendarInput.js.map +1 -0
  3. package/build/{dateLookup/DateLookup.messages.js → calendarInput/CalendarInput.messages.js} +1 -1
  4. package/build/calendarInput/CalendarInput.messages.js.map +1 -0
  5. package/build/{dateLookup/DateLookup.messages.mjs → calendarInput/CalendarInput.messages.mjs} +1 -1
  6. package/build/calendarInput/CalendarInput.messages.mjs.map +1 -0
  7. package/build/calendarInput/CalendarInput.mjs +155 -0
  8. package/build/calendarInput/CalendarInput.mjs.map +1 -0
  9. package/build/{dateLookup → calendarInput}/dateHeader/DateHeader.js +4 -4
  10. package/build/calendarInput/dateHeader/DateHeader.js.map +1 -0
  11. package/build/{dateLookup → calendarInput}/dateHeader/DateHeader.mjs +1 -1
  12. package/build/calendarInput/dateHeader/DateHeader.mjs.map +1 -0
  13. package/build/{dateLookup → calendarInput}/dayCalendar/DayCalendar.js +2 -2
  14. package/build/calendarInput/dayCalendar/DayCalendar.js.map +1 -0
  15. package/build/{dateLookup → calendarInput}/dayCalendar/DayCalendar.mjs +1 -1
  16. package/build/calendarInput/dayCalendar/DayCalendar.mjs.map +1 -0
  17. package/build/calendarInput/dayCalendar/table/DayCalendarTable.js.map +1 -0
  18. package/build/calendarInput/dayCalendar/table/DayCalendarTable.mjs.map +1 -0
  19. package/build/calendarInput/getFocusableTime/getFocusableTime.js.map +1 -0
  20. package/build/calendarInput/getFocusableTime/getFocusableTime.mjs.map +1 -0
  21. package/build/calendarInput/getStartOfDay/getStartOfDay.js.map +1 -0
  22. package/build/calendarInput/getStartOfDay/getStartOfDay.mjs.map +1 -0
  23. package/build/{dateLookup → calendarInput}/monthCalendar/MonthCalendar.js +2 -2
  24. package/build/calendarInput/monthCalendar/MonthCalendar.js.map +1 -0
  25. package/build/{dateLookup → calendarInput}/monthCalendar/MonthCalendar.mjs +1 -1
  26. package/build/calendarInput/monthCalendar/MonthCalendar.mjs.map +1 -0
  27. package/build/calendarInput/monthCalendar/table/MonthCalendarTable.js.map +1 -0
  28. package/build/calendarInput/monthCalendar/table/MonthCalendarTable.mjs.map +1 -0
  29. package/build/{dateLookup → calendarInput}/tableLink/TableLink.js +2 -2
  30. package/build/calendarInput/tableLink/TableLink.js.map +1 -0
  31. package/build/{dateLookup → calendarInput}/tableLink/TableLink.mjs +1 -1
  32. package/build/calendarInput/tableLink/TableLink.mjs.map +1 -0
  33. package/build/{dateLookup → calendarInput}/yearCalendar/YearCalendar.js +2 -2
  34. package/build/calendarInput/yearCalendar/YearCalendar.js.map +1 -0
  35. package/build/{dateLookup → calendarInput}/yearCalendar/YearCalendar.mjs +1 -1
  36. package/build/calendarInput/yearCalendar/YearCalendar.mjs.map +1 -0
  37. package/build/calendarInput/yearCalendar/table/YearCalendarTable.js.map +1 -0
  38. package/build/calendarInput/yearCalendar/table/YearCalendarTable.mjs.map +1 -0
  39. package/build/dateLookup/DateLookup.js +28 -165
  40. package/build/dateLookup/DateLookup.js.map +1 -1
  41. package/build/dateLookup/DateLookup.mjs +29 -166
  42. package/build/dateLookup/DateLookup.mjs.map +1 -1
  43. package/build/index.js +2 -0
  44. package/build/index.js.map +1 -1
  45. package/build/index.mjs +1 -0
  46. package/build/index.mjs.map +1 -1
  47. package/build/main.css +97 -106
  48. package/build/prompt/InfoPrompt/InfoPrompt.js +1 -1
  49. package/build/prompt/InfoPrompt/InfoPrompt.js.map +1 -1
  50. package/build/prompt/InfoPrompt/InfoPrompt.mjs +2 -2
  51. package/build/prompt/InfoPrompt/InfoPrompt.mjs.map +1 -1
  52. package/build/styles/calendarInput/CalendarInput.css +83 -0
  53. package/build/styles/dateLookup/DateLookup.css +0 -90
  54. package/build/styles/main.css +97 -106
  55. package/build/types/calendarInput/CalendarInput.d.ts +13 -0
  56. package/build/types/calendarInput/CalendarInput.d.ts.map +1 -0
  57. package/build/types/{dateLookup/DateLookup.messages.d.ts → calendarInput/CalendarInput.messages.d.ts} +1 -1
  58. package/build/types/calendarInput/CalendarInput.messages.d.ts.map +1 -0
  59. package/build/types/calendarInput/dateHeader/DateHeader.d.ts.map +1 -0
  60. package/build/types/calendarInput/dateHeader/index.d.ts.map +1 -0
  61. package/build/types/calendarInput/dayCalendar/DayCalendar.d.ts.map +1 -0
  62. package/build/types/calendarInput/dayCalendar/index.d.ts.map +1 -0
  63. package/build/types/calendarInput/dayCalendar/table/DayCalendarTable.d.ts.map +1 -0
  64. package/build/types/calendarInput/dayCalendar/table/index.d.ts.map +1 -0
  65. package/build/types/calendarInput/getFocusableTime/getFocusableTime.d.ts.map +1 -0
  66. package/build/types/calendarInput/getStartOfDay/getStartOfDay.d.ts.map +1 -0
  67. package/build/types/calendarInput/getStartOfDay/index.d.ts.map +1 -0
  68. package/build/types/calendarInput/index.d.ts +3 -0
  69. package/build/types/calendarInput/index.d.ts.map +1 -0
  70. package/build/types/{dateLookup → calendarInput}/monthCalendar/MonthCalendar.d.ts +1 -1
  71. package/build/types/calendarInput/monthCalendar/MonthCalendar.d.ts.map +1 -0
  72. package/build/types/calendarInput/monthCalendar/index.d.ts.map +1 -0
  73. package/build/types/{dateLookup → calendarInput}/monthCalendar/table/MonthCalendarTable.d.ts +1 -1
  74. package/build/types/calendarInput/monthCalendar/table/MonthCalendarTable.d.ts.map +1 -0
  75. package/build/types/calendarInput/monthCalendar/table/index.d.ts.map +1 -0
  76. package/build/types/calendarInput/tableLink/TableLink.d.ts.map +1 -0
  77. package/build/types/calendarInput/tableLink/index.d.ts.map +1 -0
  78. package/build/types/{dateLookup → calendarInput}/yearCalendar/YearCalendar.d.ts +1 -1
  79. package/build/types/calendarInput/yearCalendar/YearCalendar.d.ts.map +1 -0
  80. package/build/types/calendarInput/yearCalendar/index.d.ts.map +1 -0
  81. package/build/types/{dateLookup → calendarInput}/yearCalendar/table/YearCalendarTable.d.ts +1 -1
  82. package/build/types/calendarInput/yearCalendar/table/YearCalendarTable.d.ts.map +1 -0
  83. package/build/types/calendarInput/yearCalendar/table/index.d.ts.map +1 -0
  84. package/build/types/dateLookup/DateLookup.d.ts +2 -25
  85. package/build/types/dateLookup/DateLookup.d.ts.map +1 -1
  86. package/build/types/index.d.ts +2 -0
  87. package/build/types/index.d.ts.map +1 -1
  88. package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts +2 -3
  89. package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts.map +1 -1
  90. package/package.json +3 -3
  91. package/src/calendarInput/CalendarInput.css +83 -0
  92. package/src/calendarInput/CalendarInput.less +79 -0
  93. package/src/calendarInput/CalendarInput.story.tsx +65 -0
  94. package/src/calendarInput/CalendarInput.test.tsx +140 -0
  95. package/src/calendarInput/CalendarInput.tsx +165 -0
  96. package/src/{dateLookup → calendarInput}/dateHeader/DateHeader.tsx +1 -1
  97. package/src/{dateLookup → calendarInput}/dayCalendar/DayCalendar.tsx +1 -1
  98. package/src/calendarInput/index.ts +2 -0
  99. package/src/{dateLookup → calendarInput}/monthCalendar/MonthCalendar.tsx +2 -2
  100. package/src/{dateLookup → calendarInput}/monthCalendar/table/MonthCalendarTable.tsx +1 -1
  101. package/src/{dateLookup → calendarInput}/tableLink/TableLink.tsx +1 -1
  102. package/src/{dateLookup → calendarInput}/yearCalendar/YearCalendar.tsx +2 -2
  103. package/src/{dateLookup → calendarInput}/yearCalendar/table/YearCalendarTable.tsx +1 -1
  104. package/src/dateLookup/DateLookup.css +0 -90
  105. package/src/dateLookup/DateLookup.less +0 -91
  106. package/src/dateLookup/DateLookup.test.tsx +0 -124
  107. package/src/dateLookup/DateLookup.tsx +31 -157
  108. package/src/index.ts +2 -0
  109. package/src/main.css +97 -106
  110. package/src/main.less +1 -0
  111. package/src/prompt/InfoPrompt/InfoPrompt.story.tsx +0 -42
  112. package/src/prompt/InfoPrompt/InfoPrompt.test.tsx +1 -65
  113. package/src/prompt/InfoPrompt/InfoPrompt.tsx +4 -15
  114. package/build/dateLookup/DateLookup.messages.js.map +0 -1
  115. package/build/dateLookup/DateLookup.messages.mjs.map +0 -1
  116. package/build/dateLookup/dateHeader/DateHeader.js.map +0 -1
  117. package/build/dateLookup/dateHeader/DateHeader.mjs.map +0 -1
  118. package/build/dateLookup/dayCalendar/DayCalendar.js.map +0 -1
  119. package/build/dateLookup/dayCalendar/DayCalendar.mjs.map +0 -1
  120. package/build/dateLookup/dayCalendar/table/DayCalendarTable.js.map +0 -1
  121. package/build/dateLookup/dayCalendar/table/DayCalendarTable.mjs.map +0 -1
  122. package/build/dateLookup/getFocusableTime/getFocusableTime.js.map +0 -1
  123. package/build/dateLookup/getFocusableTime/getFocusableTime.mjs.map +0 -1
  124. package/build/dateLookup/getStartOfDay/getStartOfDay.js.map +0 -1
  125. package/build/dateLookup/getStartOfDay/getStartOfDay.mjs.map +0 -1
  126. package/build/dateLookup/monthCalendar/MonthCalendar.js.map +0 -1
  127. package/build/dateLookup/monthCalendar/MonthCalendar.mjs.map +0 -1
  128. package/build/dateLookup/monthCalendar/table/MonthCalendarTable.js.map +0 -1
  129. package/build/dateLookup/monthCalendar/table/MonthCalendarTable.mjs.map +0 -1
  130. package/build/dateLookup/tableLink/TableLink.js.map +0 -1
  131. package/build/dateLookup/tableLink/TableLink.mjs.map +0 -1
  132. package/build/dateLookup/yearCalendar/YearCalendar.js.map +0 -1
  133. package/build/dateLookup/yearCalendar/YearCalendar.mjs.map +0 -1
  134. package/build/dateLookup/yearCalendar/table/YearCalendarTable.js.map +0 -1
  135. package/build/dateLookup/yearCalendar/table/YearCalendarTable.mjs.map +0 -1
  136. package/build/types/dateLookup/DateLookup.messages.d.ts.map +0 -1
  137. package/build/types/dateLookup/dateHeader/DateHeader.d.ts.map +0 -1
  138. package/build/types/dateLookup/dateHeader/index.d.ts.map +0 -1
  139. package/build/types/dateLookup/dayCalendar/DayCalendar.d.ts.map +0 -1
  140. package/build/types/dateLookup/dayCalendar/index.d.ts.map +0 -1
  141. package/build/types/dateLookup/dayCalendar/table/DayCalendarTable.d.ts.map +0 -1
  142. package/build/types/dateLookup/dayCalendar/table/index.d.ts.map +0 -1
  143. package/build/types/dateLookup/getFocusableTime/getFocusableTime.d.ts.map +0 -1
  144. package/build/types/dateLookup/getStartOfDay/getStartOfDay.d.ts.map +0 -1
  145. package/build/types/dateLookup/getStartOfDay/index.d.ts.map +0 -1
  146. package/build/types/dateLookup/monthCalendar/MonthCalendar.d.ts.map +0 -1
  147. package/build/types/dateLookup/monthCalendar/index.d.ts.map +0 -1
  148. package/build/types/dateLookup/monthCalendar/table/MonthCalendarTable.d.ts.map +0 -1
  149. package/build/types/dateLookup/monthCalendar/table/index.d.ts.map +0 -1
  150. package/build/types/dateLookup/tableLink/TableLink.d.ts.map +0 -1
  151. package/build/types/dateLookup/tableLink/index.d.ts.map +0 -1
  152. package/build/types/dateLookup/yearCalendar/YearCalendar.d.ts.map +0 -1
  153. package/build/types/dateLookup/yearCalendar/index.d.ts.map +0 -1
  154. package/build/types/dateLookup/yearCalendar/table/YearCalendarTable.d.ts.map +0 -1
  155. package/build/types/dateLookup/yearCalendar/table/index.d.ts.map +0 -1
  156. /package/build/{dateLookup → calendarInput}/dayCalendar/table/DayCalendarTable.js +0 -0
  157. /package/build/{dateLookup → calendarInput}/dayCalendar/table/DayCalendarTable.mjs +0 -0
  158. /package/build/{dateLookup → calendarInput}/getFocusableTime/getFocusableTime.js +0 -0
  159. /package/build/{dateLookup → calendarInput}/getFocusableTime/getFocusableTime.mjs +0 -0
  160. /package/build/{dateLookup → calendarInput}/getStartOfDay/getStartOfDay.js +0 -0
  161. /package/build/{dateLookup → calendarInput}/getStartOfDay/getStartOfDay.mjs +0 -0
  162. /package/build/{dateLookup → calendarInput}/monthCalendar/table/MonthCalendarTable.js +0 -0
  163. /package/build/{dateLookup → calendarInput}/monthCalendar/table/MonthCalendarTable.mjs +0 -0
  164. /package/build/{dateLookup → calendarInput}/yearCalendar/table/YearCalendarTable.js +0 -0
  165. /package/build/{dateLookup → calendarInput}/yearCalendar/table/YearCalendarTable.mjs +0 -0
  166. /package/build/types/{dateLookup → calendarInput}/dateHeader/DateHeader.d.ts +0 -0
  167. /package/build/types/{dateLookup → calendarInput}/dateHeader/index.d.ts +0 -0
  168. /package/build/types/{dateLookup → calendarInput}/dayCalendar/DayCalendar.d.ts +0 -0
  169. /package/build/types/{dateLookup → calendarInput}/dayCalendar/index.d.ts +0 -0
  170. /package/build/types/{dateLookup → calendarInput}/dayCalendar/table/DayCalendarTable.d.ts +0 -0
  171. /package/build/types/{dateLookup → calendarInput}/dayCalendar/table/index.d.ts +0 -0
  172. /package/build/types/{dateLookup → calendarInput}/getFocusableTime/getFocusableTime.d.ts +0 -0
  173. /package/build/types/{dateLookup → calendarInput}/getStartOfDay/getStartOfDay.d.ts +0 -0
  174. /package/build/types/{dateLookup → calendarInput}/getStartOfDay/index.d.ts +0 -0
  175. /package/build/types/{dateLookup → calendarInput}/monthCalendar/index.d.ts +0 -0
  176. /package/build/types/{dateLookup → calendarInput}/monthCalendar/table/index.d.ts +0 -0
  177. /package/build/types/{dateLookup → calendarInput}/tableLink/TableLink.d.ts +0 -0
  178. /package/build/types/{dateLookup → calendarInput}/tableLink/index.d.ts +0 -0
  179. /package/build/types/{dateLookup → calendarInput}/yearCalendar/index.d.ts +0 -0
  180. /package/build/types/{dateLookup → calendarInput}/yearCalendar/table/index.d.ts +0 -0
  181. /package/src/{dateLookup/DateLookup.messages.ts → calendarInput/CalendarInput.messages.ts} +0 -0
  182. /package/src/{dateLookup → calendarInput}/dateHeader/index.ts +0 -0
  183. /package/src/{dateLookup → calendarInput}/dayCalendar/index.ts +0 -0
  184. /package/src/{dateLookup → calendarInput}/dayCalendar/table/DayCalendarTable.tsx +0 -0
  185. /package/src/{dateLookup → calendarInput}/dayCalendar/table/index.ts +0 -0
  186. /package/src/{dateLookup → calendarInput}/getFocusableTime/getFocusable.test.ts +0 -0
  187. /package/src/{dateLookup → calendarInput}/getFocusableTime/getFocusableTime.tsx +0 -0
  188. /package/src/{dateLookup → calendarInput}/getStartOfDay/getStartOfDay.test.js +0 -0
  189. /package/src/{dateLookup → calendarInput}/getStartOfDay/getStartOfDay.tsx +0 -0
  190. /package/src/{dateLookup → calendarInput}/getStartOfDay/index.ts +0 -0
  191. /package/src/{dateLookup → calendarInput}/monthCalendar/index.ts +0 -0
  192. /package/src/{dateLookup → calendarInput}/monthCalendar/table/index.ts +0 -0
  193. /package/src/{dateLookup → calendarInput}/tableLink/index.ts +0 -0
  194. /package/src/{dateLookup → calendarInput}/yearCalendar/index.ts +0 -0
  195. /package/src/{dateLookup → calendarInput}/yearCalendar/table/index.ts +0 -0
@@ -1,7 +1,6 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { createRef, PureComponent, KeyboardEvent } from 'react';
3
- import { Breakpoint } from '@transferwise/neptune-tokens';
4
-
3
+ import CalendarInput from '../calendarInput';
5
4
  import {
6
5
  Size,
7
6
  MonthFormat,
@@ -10,15 +9,10 @@ import {
10
9
  type SizeMedium,
11
10
  type SizeLarge,
12
11
  } from '../common';
13
- import { isWithinRange, moveToWithinRange, returnDateView } from '../common/dateUtils';
14
12
  import ResponsivePanel from '../common/responsivePanel';
15
13
  import { WithInputAttributesProps, withInputAttributes } from '../inputs/contexts';
16
14
  import { OverlayIdProvider } from '../provider/overlay/OverlayIdProvider';
17
15
  import DateTrigger from './dateTrigger';
18
- import DayCalendar from './dayCalendar';
19
- import { getStartOfDay } from './getStartOfDay';
20
- import MonthCalendar from './monthCalendar';
21
- import YearCalendar from './yearCalendar';
22
16
 
23
17
  export interface DateLookupProps {
24
18
  id?: string;
@@ -40,15 +34,8 @@ export interface DateLookupProps {
40
34
  type DateLookupPropsWithInputAttributes = DateLookupProps & Partial<WithInputAttributesProps>;
41
35
 
42
36
  interface DateLookupState {
43
- selectedDate: Date | null;
44
37
  originalDate: Date | null;
45
- min: Date | null;
46
- max: Date | null;
47
- viewMonth: number;
48
- viewYear: number;
49
38
  open: boolean;
50
- mode: 'day' | 'month' | 'year';
51
- isMobile: boolean;
52
39
  }
53
40
 
54
41
  class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateLookupState> {
@@ -68,64 +55,29 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
68
55
  } satisfies Partial<DateLookupPropsWithInputAttributes>;
69
56
 
70
57
  element = createRef<HTMLDivElement>();
71
- dropdown = createRef<HTMLDivElement>();
72
58
 
73
59
  constructor(props: DateLookup['props']) {
74
60
  super(props);
75
- const dateView = returnDateView(props.value, props.min, props.max);
76
61
  this.state = {
77
- selectedDate: getStartOfDay(props.value),
78
62
  originalDate: null,
79
- min: getStartOfDay(props.min),
80
- max: getStartOfDay(props.max),
81
- viewMonth: dateView.getMonth(),
82
- viewYear: dateView.getFullYear(),
83
63
  open: false,
84
- mode: 'day',
85
- isMobile: false,
86
64
  };
87
65
  }
88
66
 
89
- static getDerivedStateFromProps(props: DateLookup['props'], state: DateLookupState) {
90
- const propsSelected = getStartOfDay(props.value);
91
- const propsMin = getStartOfDay(props.min);
92
- const propsMax = getStartOfDay(props.max);
93
- const hasSelectedChanged = state.selectedDate?.getTime() !== propsSelected?.getTime();
94
- const hasMinChanged = state.min?.getTime() !== propsMin?.getTime();
95
- const hasMaxChanged = state.max?.getTime() !== propsMax?.getTime();
96
- if (hasSelectedChanged || hasMinChanged || hasMaxChanged) {
97
- const selectedDate = hasSelectedChanged ? propsSelected : state.selectedDate;
98
- const min = hasMinChanged ? propsMin : state.min;
99
- const max = hasMaxChanged ? propsMax : state.max;
100
- if (selectedDate && !isWithinRange(selectedDate, min, max)) {
101
- props.onChange(moveToWithinRange(selectedDate, min, max));
102
- return null;
103
- }
104
- const viewDateThatIsWithinRange: Date = returnDateView(selectedDate, min, max);
105
- const viewMonth = viewDateThatIsWithinRange.getMonth();
106
- const viewYear = viewDateThatIsWithinRange.getFullYear();
107
- return { selectedDate, min, max, viewMonth, viewYear };
108
- }
109
- return null;
110
- }
111
-
112
67
  componentDidUpdate(previousProps: DateLookupPropsWithInputAttributes) {
113
68
  if (this.props.value?.getTime() !== previousProps.value?.getTime() && this.state.open) {
114
69
  this.focusOn('.active');
115
70
  }
116
- const mediaQuery = window.matchMedia(`(max-width: ${Breakpoint.SMALL}px)`);
117
- this.setState({ isMobile: mediaQuery.matches });
118
71
  }
119
72
 
120
73
  componentWillUnmount() {
121
- // Prevents memory leak by cleaning state.
122
74
  this.setState = () => {};
123
75
  }
124
76
 
125
77
  open = () => {
126
78
  const { onFocus } = this.props;
127
79
 
128
- this.setState({ open: true, mode: 'day' });
80
+ this.setState({ open: true });
129
81
  if (onFocus) {
130
82
  onFocus();
131
83
  }
@@ -151,36 +103,13 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
151
103
  const { open, originalDate } = this.state;
152
104
  switch (event.key) {
153
105
  case 'ArrowLeft':
154
- if (open) {
155
- this.adjustDate(-1, -1, -1);
156
- } else {
157
- this.open();
158
- }
159
- event.preventDefault();
160
- break;
161
106
  case 'ArrowUp':
162
- if (open) {
163
- this.adjustDate(-7, -4, -4);
164
- } else {
165
- this.open();
166
- }
167
- event.preventDefault();
168
- break;
169
107
  case 'ArrowRight':
170
- if (open) {
171
- this.adjustDate(1, 1, 1);
172
- } else {
173
- this.open();
174
- }
175
- event.preventDefault();
176
- break;
177
108
  case 'ArrowDown':
178
- if (open) {
179
- this.adjustDate(7, 4, 4);
180
- } else {
109
+ if (!open) {
181
110
  this.open();
111
+ event.preventDefault();
182
112
  }
183
- event.preventDefault();
184
113
  break;
185
114
  case 'Escape':
186
115
  if (originalDate !== null) {
@@ -194,27 +123,6 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
194
123
  }
195
124
  };
196
125
 
197
- adjustDate = (daysToAdd: number, monthsToAdd: number, yearsToAdd: number) => {
198
- const { selectedDate, min, max, mode, originalDate } = this.state;
199
- if (originalDate === null) {
200
- this.setState({ originalDate: selectedDate });
201
- }
202
- let date: Date | null;
203
- if (selectedDate) {
204
- date = new Date(
205
- mode === 'year' ? selectedDate.getFullYear() + yearsToAdd : selectedDate.getFullYear(),
206
- mode === 'month' ? selectedDate.getMonth() + monthsToAdd : selectedDate.getMonth(),
207
- mode === 'day' ? selectedDate.getDate() + daysToAdd : selectedDate.getDate(),
208
- );
209
- } else {
210
- date = getStartOfDay(new Date());
211
- }
212
- date &&= moveToWithinRange(date, min, max);
213
- if (date?.getTime() !== selectedDate?.getTime()) {
214
- this.props.onChange(date);
215
- }
216
- };
217
-
218
126
  focusOn = (preferredElement: string, fallbackElement?: string) => {
219
127
  const element = this.element.current?.querySelector(preferredElement) as HTMLElement | null;
220
128
  if (element) {
@@ -224,71 +132,37 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
224
132
  }
225
133
  };
226
134
 
227
- switchMode = (mode: 'day' | 'month' | 'year') => {
228
- this.setState({ mode }, () => {
229
- this.focusOn('.active', '.today');
230
- });
231
- };
232
-
233
- switchToDays = () => this.switchMode('day');
234
-
235
- switchToMonths = () => this.switchMode('month');
236
-
237
- switchToYears = () => this.switchMode('year');
238
-
239
- handleSelectedDateUpdate = (selectedDate: Date) => {
240
- this.setState({ selectedDate }, () => {
241
- this.props.onChange(selectedDate);
242
- this.close();
243
- this.focusOn('.btn');
244
- });
135
+ handleDateChange = (date: Date | null) => {
136
+ this.setState(
137
+ (state) => {
138
+ const originalDate = state.originalDate ?? this.props.value;
139
+ return { originalDate };
140
+ },
141
+ () => {
142
+ this.props.onChange(date);
143
+ },
144
+ );
245
145
  };
246
146
 
247
- handleViewDateUpdate = ({ month = this.state.viewMonth, year = this.state.viewYear }) => {
248
- this.setState({ viewMonth: month, viewYear: year });
147
+ handleDateSelect = (date: Date) => {
148
+ this.props.onChange(date);
149
+ this.close();
150
+ this.focusOn('.btn');
249
151
  };
250
152
 
251
153
  getCalendar = () => {
252
- const { selectedDate, min, max, viewMonth, viewYear, mode, isMobile } = this.state;
253
- const { placeholder, monthFormat } = this.props;
154
+ const { value, min, max, monthFormat, placeholder } = this.props;
254
155
  return (
255
- <div className={clsx({ 'p-a-1': !isMobile })}>
256
- {mode === 'day' && (
257
- <DayCalendar
258
- selectedDate={selectedDate}
259
- min={min}
260
- max={max}
261
- viewMonth={viewMonth}
262
- viewYear={viewYear}
263
- monthFormat={monthFormat}
264
- onSelect={this.handleSelectedDateUpdate}
265
- onLabelClick={this.switchToYears}
266
- onViewDateUpdate={this.handleViewDateUpdate}
267
- />
268
- )}
269
- {mode === 'month' && (
270
- <MonthCalendar
271
- selectedDate={selectedDate}
272
- min={min}
273
- max={max}
274
- viewYear={viewYear}
275
- placeholder={placeholder}
276
- onSelect={this.switchToDays}
277
- onLabelClick={this.switchToYears}
278
- onViewDateUpdate={this.handleViewDateUpdate}
279
- />
280
- )}
281
- {mode === 'year' && (
282
- <YearCalendar
283
- selectedDate={selectedDate}
284
- min={min}
285
- max={max}
286
- viewYear={viewYear}
287
- placeholder={placeholder}
288
- onSelect={this.switchToMonths}
289
- onViewDateUpdate={this.handleViewDateUpdate}
290
- />
291
- )}
156
+ <div className="p-a-1">
157
+ <CalendarInput
158
+ value={value}
159
+ min={min}
160
+ max={max}
161
+ monthFormat={monthFormat}
162
+ placeholder={placeholder}
163
+ onChange={this.handleDateChange}
164
+ onSelect={this.handleDateSelect}
165
+ />
292
166
  </div>
293
167
  );
294
168
  };
@@ -299,7 +173,7 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
299
173
  };
300
174
 
301
175
  render() {
302
- const { selectedDate, open } = this.state;
176
+ const { open } = this.state;
303
177
 
304
178
  const {
305
179
  inputAttributes,
@@ -329,7 +203,7 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
329
203
  <DateTrigger
330
204
  id={id}
331
205
  ariaLabelledBy={ariaLabelledBy}
332
- selectedDate={selectedDate}
206
+ selectedDate={value}
333
207
  size={size}
334
208
  placeholder={placeholder}
335
209
  label={label}
package/src/index.ts CHANGED
@@ -29,6 +29,7 @@ export type {
29
29
  export type { BottomSheetProps } from './common/bottomSheet';
30
30
  export type { DateInputProps } from './dateInput';
31
31
  export type { DateLookupProps } from './dateLookup';
32
+ export type { CalendarInputProps } from './calendarInput';
32
33
  export type { DecisionProps } from './decision/Decision';
33
34
  export type { DefinitionListProps, DefinitionListDefinition } from './definitionList';
34
35
  export type { DimmerProps } from './dimmer';
@@ -163,6 +164,7 @@ export { default as CriticalCommsBanner } from './criticalBanner';
163
164
  export type { CriticalCommsBannerProps } from './criticalBanner';
164
165
  export { default as DateInput } from './dateInput';
165
166
  export { default as DateLookup } from './dateLookup';
167
+ export { default as CalendarInput } from './calendarInput';
166
168
  export { default as Decision } from './decision';
167
169
  export { default as DefinitionList } from './definitionList';
168
170
  export { default as Dimmer } from './dimmer';
package/src/main.css CHANGED
@@ -27180,6 +27180,103 @@ a[data-toggle="tooltip"] {
27180
27180
  scale: -1 1;
27181
27181
  }
27182
27182
 
27183
+ .tw-date-lookup-calendar {
27184
+ min-width: 300px;
27185
+ text-align: center;
27186
+ table-layout: fixed;
27187
+ border: none;
27188
+ background-color: inherit;
27189
+ }
27190
+
27191
+ .tw-date-lookup-calendar thead {
27192
+ background-color: transparent;
27193
+ background-color: initial;
27194
+ }
27195
+
27196
+ .tw-date-lookup-calendar > tbody > tr > td.weekend button {
27197
+ color: #5d7079;
27198
+ color: var(--color-content-secondary);
27199
+ }
27200
+
27201
+ .tw-date-lookup-calendar > tbody > tr > td {
27202
+ border: none;
27203
+ padding: 4px;
27204
+ padding: var(--size-4);
27205
+ }
27206
+
27207
+ @media (max-width: 320px) {
27208
+ .tw-date-lookup-calendar > tbody > tr > td {
27209
+ padding: 0;
27210
+ }
27211
+ }
27212
+
27213
+ .tw-date-lookup-calendar > tbody > tr > td:has(.tw-date-lookup-day-option) {
27214
+ padding: 1px;
27215
+ }
27216
+
27217
+ .tw-date-lookup-calendar > tbody > tr > td button {
27218
+ width: 100%;
27219
+ padding: 4px 0;
27220
+ padding: var(--size-4) 0;
27221
+ color: #0097c7;
27222
+ color: var(--color-content-accent);
27223
+ border: transparent;
27224
+ border-radius: 10px;
27225
+ border-radius: var(--radius-small);
27226
+ background-color: transparent;
27227
+ font-weight: 600;
27228
+ font-weight: var(--font-weight-semi-bold);
27229
+ color: #37517e;
27230
+ color: var(--color-content-primary);
27231
+ }
27232
+
27233
+ @media (max-width: 320px) {
27234
+ .tw-date-lookup-calendar > tbody > tr > td button {
27235
+ padding: 0;
27236
+ }
27237
+ }
27238
+
27239
+ .tw-date-lookup-calendar > tbody > tr > td button.tw-date-lookup-day-option {
27240
+ height: 40px;
27241
+ height: var(--size-40);
27242
+ border-radius: 9999px;
27243
+ border-radius: var(--radius-full);
27244
+ line-height: 40px;
27245
+ line-height: var(--size-40);
27246
+ width: 40px;
27247
+ width: var(--size-40);
27248
+ padding: 0;
27249
+ display: inline-flex;
27250
+ align-items: center;
27251
+ justify-content: center;
27252
+ }
27253
+
27254
+ .tw-date-lookup-calendar > tbody > tr > td button.tw-date-lookup-day-option.today {
27255
+ -webkit-text-decoration: underline;
27256
+ text-decoration: underline;
27257
+ text-decoration-thickness: 2px;
27258
+ text-underline-offset: 4px;
27259
+ }
27260
+
27261
+ .tw-date-lookup-calendar > tbody > tr > td:not(.disabled):not(:disabled) button.show-focus,
27262
+ .tw-date-lookup-calendar > tbody > tr > td:hover button:not(.disabled):not(:disabled) {
27263
+ background-color: var(--color-background-screen-hover);
27264
+ }
27265
+
27266
+ .tw-date-lookup-calendar > tbody > tr > td:not(.disabled):not(:disabled) button.active {
27267
+ background-color: var(--color-interactive-primary);
27268
+ color: var(--color-interactive-contrast);
27269
+ }
27270
+
27271
+ .tw-date-lookup-calendar abbr {
27272
+ -webkit-text-decoration: none;
27273
+ text-decoration: none;
27274
+ }
27275
+
27276
+ .tw-date-lookup-header-current-container {
27277
+ display: inline;
27278
+ }
27279
+
27183
27280
  .np-card {
27184
27281
  overflow: hidden;
27185
27282
  transition-property: transform, box-shadow;
@@ -28317,112 +28414,6 @@ button.np-option {
28317
28414
  width: 400px;
28318
28415
  }
28319
28416
 
28320
- .tw-date-lookup-calendar {
28321
- min-width: 300px;
28322
- text-align: center;
28323
- table-layout: fixed;
28324
- background-color: inherit;
28325
- }
28326
-
28327
- .tw-date-lookup-calendar > tbody > tr > td.weekend button {
28328
- color: #5d7079;
28329
- color: var(--color-content-secondary);
28330
- }
28331
-
28332
- .tw-date-lookup-calendar > tbody > tr > td {
28333
- padding: 4px;
28334
- padding: var(--size-4);
28335
- }
28336
-
28337
- @media (max-width: 320px) {
28338
- .tw-date-lookup-calendar > tbody > tr > td {
28339
- padding: 0;
28340
- }
28341
- }
28342
-
28343
- .tw-date-lookup-calendar > tbody > tr > td:has(.tw-date-lookup-day-option) {
28344
- padding: 1px;
28345
- }
28346
-
28347
- .tw-date-lookup-calendar > tbody > tr > td button {
28348
- width: 100%;
28349
- padding: 4px 0;
28350
- padding: var(--size-4) 0;
28351
- color: #0097c7;
28352
- color: var(--color-content-accent);
28353
- border: transparent;
28354
- border-radius: 10px;
28355
- border-radius: var(--radius-small);
28356
- background-color: transparent;
28357
- font-weight: 600;
28358
- font-weight: var(--font-weight-semi-bold);
28359
- color: #37517e;
28360
- color: var(--color-content-primary);
28361
- }
28362
-
28363
- @media (max-width: 320px) {
28364
- .tw-date-lookup-calendar > tbody > tr > td button {
28365
- padding: 0;
28366
- }
28367
- }
28368
-
28369
- .tw-date-lookup-calendar > tbody > tr > td button.tw-date-lookup-day-option {
28370
- height: 40px;
28371
- height: var(--size-40);
28372
- border-radius: 9999px;
28373
- border-radius: var(--radius-full);
28374
- line-height: 40px;
28375
- line-height: var(--size-40);
28376
- width: 40px;
28377
- width: var(--size-40);
28378
- padding: 0;
28379
- display: inline-flex;
28380
- align-items: center;
28381
- justify-content: center;
28382
- }
28383
-
28384
- .tw-date-lookup-calendar > tbody > tr > td button.tw-date-lookup-day-option.today {
28385
- -webkit-text-decoration: underline;
28386
- text-decoration: underline;
28387
- text-decoration-thickness: 2px;
28388
- text-underline-offset: 4px;
28389
- }
28390
-
28391
- .tw-date-lookup-calendar > tbody > tr > td:not(.disabled):not(:disabled) button.show-focus,
28392
- .tw-date-lookup-calendar > tbody > tr > td:hover button:not(.disabled):not(:disabled) {
28393
- background-color: var(--color-background-screen-hover);
28394
- }
28395
-
28396
- .tw-date-lookup-calendar > tbody > tr > td:not(.disabled):not(:disabled) button.active {
28397
- background-color: var(--color-interactive-primary);
28398
- color: var(--color-interactive-contrast);
28399
- }
28400
-
28401
- .tw-date-lookup-calendar abbr {
28402
- -webkit-text-decoration: none;
28403
- text-decoration: none;
28404
- }
28405
-
28406
- .tw-date-lookup-header-current-container {
28407
- display: inline;
28408
- }
28409
-
28410
- .np-theme-personal.tw-date-lookup-menu .table-bordered,
28411
- .np-theme-personal .tw-date-lookup-menu .table-bordered {
28412
- border: none;
28413
- }
28414
-
28415
- .np-theme-personal.tw-date-lookup-menu thead,
28416
- .np-theme-personal .tw-date-lookup-menu thead {
28417
- background-color: transparent;
28418
- background-color: initial;
28419
- }
28420
-
28421
- .np-theme-personal.tw-date-lookup-menu td,
28422
- .np-theme-personal .tw-date-lookup-menu td {
28423
- border: none;
28424
- }
28425
-
28426
28417
  .np-date-trigger {
28427
28418
  overflow: hidden;
28428
28419
  text-overflow: ellipsis;
package/src/main.less CHANGED
@@ -16,6 +16,7 @@
16
16
  @import "./body/Body.less";
17
17
  @import "./button/LegacyButton.less";
18
18
  @import "./button/Button.less";
19
+ @import "./calendarInput/CalendarInput.less";
19
20
  @import "./card/Card.less";
20
21
  @import "./carousel/Carousel.less";
21
22
  @import "./checkboxButton/CheckboxButton.less";
@@ -6,7 +6,6 @@ import { Confetti, GiftBox, Star, Suitcase, Briefcase, Plane } from '@transferwi
6
6
  import { lorem10, lorem20 } from '../../test-utils';
7
7
  import Button from '../../button';
8
8
  import Title from '../../title';
9
- import Link from '../../link';
10
9
  import { InfoPrompt, InfoPromptProps, InfoPromptMedia } from './InfoPrompt';
11
10
 
12
11
  const withComponentGrid =
@@ -233,47 +232,6 @@ export const WithAction: StoryObj<InfoPromptProps> = {
233
232
  ),
234
233
  };
235
234
 
236
- /**
237
- * The `description` prop accepts rich content (ReactNode), allowing inline interactive elements
238
- * such as links that can trigger a popover.
239
- *
240
- * **Important**: If the description contains an interactive element, do not use the `action` prop
241
- * simultaneously — InfoPrompt should have at most one interaction.
242
- */
243
- export const WithRichDescription: StoryObj<InfoPromptProps> = {
244
- render: (args: InfoPromptProps) => (
245
- <>
246
- <InfoPrompt
247
- {...args}
248
- sentiment="neutral"
249
- description={
250
- <>
251
- Your transfer is subject to our{' '}
252
- <Link href="/fees" target="_blank" type="link-default">
253
- fee schedule
254
- </Link>
255
- .
256
- </>
257
- }
258
- />
259
- <InfoPrompt
260
- {...args}
261
- sentiment="warning"
262
- title="Verification Required"
263
- description={
264
- <>
265
- Please{' '}
266
- <Link href="/verify" type="link-default">
267
- verify your identity
268
- </Link>{' '}
269
- to continue sending money.
270
- </>
271
- }
272
- />
273
- </>
274
- ),
275
- };
276
-
277
235
  /**
278
236
  * When `onDismiss` is provided, a close button appears allowing users to dismiss the prompt.
279
237
  * Note: The component itself is not automatically removed - you must handle state management.
@@ -1,5 +1,4 @@
1
- import { act, fireEvent, mockMatchMedia, render, screen, userEvent } from '../../test-utils';
2
- import { WDS_LIVE_REGION_DELAY_MS } from '../../common/constants';
1
+ import { fireEvent, mockMatchMedia, render, screen, userEvent, waitFor } from '../../test-utils';
3
2
  import { resetLiveRegionAnnouncementQueue } from '../../common/liveRegion/LiveRegion';
4
3
  import { InfoPrompt, InfoPromptProps } from './InfoPrompt';
5
4
 
@@ -16,74 +15,11 @@ describe('InfoPrompt', () => {
16
15
  resetLiveRegionAnnouncementQueue();
17
16
  });
18
17
 
19
- afterEach(() => {
20
- jest.clearAllTimers();
21
- jest.useRealTimers();
22
- });
23
-
24
18
  it('renders description', () => {
25
19
  render(<InfoPrompt {...defaultProps} />);
26
20
  expect(screen.getByText('Prompt description')).toBeInTheDocument();
27
21
  });
28
22
 
29
- it('renders rich-content description (ReactNode)', () => {
30
- render(
31
- <InfoPrompt
32
- description={
33
- <>
34
- See our <a href="/fees">fee schedule</a>.
35
- </>
36
- }
37
- />,
38
- );
39
- expect(screen.getByRole('link', { name: 'fee schedule', hidden: true })).toBeInTheDocument();
40
- expect(screen.getByRole('link', { name: 'fee schedule', hidden: true })).toHaveAttribute(
41
- 'href',
42
- '/fees',
43
- );
44
- });
45
-
46
- it('re-announces when rich-content description text changes', () => {
47
- jest.useFakeTimers();
48
-
49
- const { rerender } = render(
50
- <InfoPrompt
51
- description={
52
- <>
53
- See our <a href="/fees">fee schedule</a>.
54
- </>
55
- }
56
- />,
57
- );
58
-
59
- act(() => {
60
- jest.advanceTimersByTime(WDS_LIVE_REGION_DELAY_MS);
61
- });
62
-
63
- const liveRegion = screen.getByRole('status');
64
- expect(liveRegion.firstElementChild).not.toHaveAttribute('aria-hidden');
65
- expect(liveRegion).toHaveTextContent('See our fee schedule.');
66
-
67
- rerender(
68
- <InfoPrompt
69
- description={
70
- <>
71
- Read the updated <a href="/fees">pricing guide</a>.
72
- </>
73
- }
74
- />,
75
- );
76
-
77
- expect(liveRegion.firstElementChild).toHaveAttribute('aria-hidden', 'true');
78
-
79
- act(() => {
80
- jest.advanceTimersByTime(WDS_LIVE_REGION_DELAY_MS);
81
- });
82
-
83
- expect(liveRegion.firstElementChild).not.toHaveAttribute('aria-hidden');
84
- expect(liveRegion).toHaveTextContent('Read the updated pricing guide.');
85
- });
86
-
87
23
  it('renders title when provided', () => {
88
24
  render(<InfoPrompt {...defaultProps} title="Test Title" />);
89
25
  expect(screen.getByText('Test Title')).toBeInTheDocument();