@transferwise/components 0.0.0-experimental-3fa5a2b → 0.0.0-experimental-47ae02a
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.
- package/build/index.js +170 -193
- package/build/index.js.map +1 -1
- package/build/index.mjs +163 -186
- package/build/index.mjs.map +1 -1
- package/build/types/accordion/AccordionItem/AccordionItem.d.ts.map +1 -1
- package/build/types/common/hooks/useMedia.d.ts.map +1 -1
- package/build/types/common/panel/Panel.d.ts.map +1 -1
- package/build/types/common/responsivePanel/ResponsivePanel.d.ts.map +1 -1
- package/build/types/dateLookup/DateLookup.d.ts +5 -6
- package/build/types/dateLookup/DateLookup.d.ts.map +1 -1
- package/build/types/dimmer/Dimmer.d.ts +1 -11
- package/build/types/dimmer/Dimmer.d.ts.map +1 -1
- package/build/types/drawer/Drawer.d.ts +4 -4
- package/build/types/index.d.ts +3 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts +2 -1
- package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts.map +1 -1
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/inputs/contexts.d.ts +2 -2
- package/build/types/inputs/contexts.d.ts.map +1 -1
- package/build/types/modal/Modal.d.ts.map +1 -1
- package/build/types/processIndicator/ProcessIndicator.d.ts +36 -19
- package/build/types/processIndicator/ProcessIndicator.d.ts.map +1 -1
- package/build/types/processIndicator/index.d.ts +2 -2
- package/build/types/processIndicator/index.d.ts.map +1 -1
- package/build/types/promoCard/PromoCard.d.ts.map +1 -1
- package/build/types/select/searchBox/SearchBox.d.ts +1 -1
- package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts +2 -1
- package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts.map +1 -1
- package/build/types/tooltip/Tooltip.d.ts +1 -1
- package/build/types/tooltip/Tooltip.d.ts.map +1 -1
- package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
- package/build/types/withDisplayFormat/WithDisplayFormat.d.ts +14 -14
- package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
- package/package.json +7 -11
- package/src/accordion/AccordionItem/AccordionItem.tsx +2 -4
- package/src/avatarWrapper/AvatarWrapper.story.tsx +1 -3
- package/src/button/Button.tsx +1 -1
- package/src/common/hooks/useConditionalListener/useConditionalListener.spec.js +1 -1
- package/src/common/hooks/useHasIntersected/useHasIntersected.spec.js +3 -3
- package/src/common/hooks/useMedia.spec.ts +1 -1
- package/src/common/hooks/useMedia.ts +1 -2
- package/src/common/panel/Panel.tsx +90 -92
- package/src/common/responsivePanel/ResponsivePanel.tsx +34 -38
- package/src/dateLookup/DateLookup.rtl.spec.tsx +181 -5
- package/src/dateLookup/DateLookup.testingLibrary.spec.js +171 -124
- package/src/dateLookup/DateLookup.tsx +9 -14
- package/src/drawer/Drawer.js +3 -3
- package/src/field/Field.tsx +3 -3
- package/src/index.ts +3 -2
- package/src/inputWithDisplayFormat/InputWithDisplayFormat.tsx +2 -1
- package/src/inputs/SelectInput.story.tsx +1 -0
- package/src/inputs/SelectInput.tsx +10 -2
- package/src/inputs/contexts.tsx +4 -4
- package/src/modal/Modal.tsx +1 -2
- package/src/processIndicator/ProcessIndicator.rtl.spec.tsx +45 -0
- package/src/processIndicator/ProcessIndicator.tsx +110 -0
- package/src/promoCard/PromoCard.tsx +1 -2
- package/src/radio/__snapshots__/Radio.rtl.spec.tsx.snap +0 -1
- package/src/snackbar/Snackbar.spec.js +4 -1
- package/src/tabs/Tabs.spec.js +46 -27
- package/src/test-utils/index.js +5 -7
- package/src/test-utils/jest.setup.js +9 -3
- package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.tsx +2 -1
- package/src/tooltip/Tooltip.tsx +44 -46
- package/src/tooltip/__snapshots__/Tooltip.spec.tsx.snap +2 -2
- package/src/upload/Upload.spec.js +34 -13
- package/src/uploadInput/UploadInput.spec.tsx +21 -23
- package/src/uploadInput/uploadItem/UploadItem.tsx +1 -3
- package/src/utilities/logActionRequired.js +1 -1
- package/src/withDisplayFormat/WithDisplayFormat.spec.js +63 -32
- package/src/withDisplayFormat/WithDisplayFormat.tsx +28 -28
- package/src/dateLookup/DateLookup.keyboardEvents.spec.js +0 -180
- package/src/processIndicator/ProcessIndicator.js +0 -117
- package/src/processIndicator/ProcessIndicator.spec.js +0 -101
- /package/src/processIndicator/{index.js → index.ts} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import '@testing-library/jest-dom';
|
|
2
2
|
import user from '@testing-library/user-event';
|
|
3
|
+
import { act } from 'react';
|
|
3
4
|
|
|
4
5
|
import { render, screen, mockMatchMedia } from '../test-utils';
|
|
5
|
-
|
|
6
|
-
import DateLookup from '.';
|
|
6
|
+
import DateLookup from './DateLookup';
|
|
7
7
|
|
|
8
8
|
mockMatchMedia();
|
|
9
9
|
|
|
@@ -20,171 +20,218 @@ describe('DateLookup (events)', () => {
|
|
|
20
20
|
const min = new Date(2018, 11, 26);
|
|
21
21
|
const max = new Date(2018, 11, 28);
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
describe('when not clearable', () => {
|
|
24
|
+
/** @type {jest.Mock} */
|
|
25
|
+
let handleChange;
|
|
26
|
+
|
|
27
|
+
const setup = async () => {
|
|
28
|
+
handleChange = jest.fn();
|
|
29
|
+
|
|
30
|
+
/** @type {import('@testing-library/react').RenderResult} */
|
|
31
|
+
let view;
|
|
32
|
+
await act(async () => {
|
|
33
|
+
view = render(
|
|
34
|
+
<>
|
|
35
|
+
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
|
36
|
+
<label id="prioritized-label">Prioritized label</label>
|
|
37
|
+
<DateLookup
|
|
38
|
+
value={date}
|
|
39
|
+
min={min}
|
|
40
|
+
max={max}
|
|
41
|
+
size="lg"
|
|
42
|
+
placeholder="Asd.."
|
|
43
|
+
label="label"
|
|
44
|
+
aria-labelledby="prioritized-label"
|
|
45
|
+
disabled={false}
|
|
46
|
+
clearable={false}
|
|
47
|
+
onChange={handleChange}
|
|
48
|
+
onClick={jest.fn()}
|
|
49
|
+
/>
|
|
50
|
+
</>,
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
return view;
|
|
40
54
|
};
|
|
41
|
-
({ container } = render(
|
|
42
|
-
<>
|
|
43
|
-
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
|
44
|
-
<label id="prioritized-label">Prioritized label</label>
|
|
45
|
-
<DateLookup {...props} />
|
|
46
|
-
</>,
|
|
47
|
-
));
|
|
48
|
-
});
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
it('switches to years', async () => {
|
|
57
|
+
const view = await setup();
|
|
58
|
+
openDateLookup(view);
|
|
59
|
+
clickDateButton(view);
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
openDateLookup();
|
|
56
|
-
clickDateButton();
|
|
61
|
+
expect(getActiveYearButton(view)).toHaveFocus();
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
closeDateLookup(view);
|
|
64
|
+
});
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
it('has aria-label for 20 years', async () => {
|
|
67
|
+
const view = await setup();
|
|
68
|
+
openDateLookup(view);
|
|
69
|
+
clickDateButton(view);
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
71
|
+
expect(getButtonByAriaLabel('next 20 years')).toBeInTheDocument();
|
|
72
|
+
expect(getButtonByAriaLabel('previous 20 years')).toBeInTheDocument();
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
clickDateButton();
|
|
72
|
-
user.click(getActiveYearButton());
|
|
74
|
+
closeDateLookup(view);
|
|
75
|
+
});
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
it('switches to months', async () => {
|
|
78
|
+
const view = await setup();
|
|
79
|
+
openDateLookup(view);
|
|
80
|
+
clickDateButton(view);
|
|
81
|
+
user.click(getActiveYearButton(view));
|
|
76
82
|
|
|
77
|
-
|
|
78
|
-
openDateLookup();
|
|
79
|
-
clickDateButton();
|
|
80
|
-
user.click(getActiveYearButton());
|
|
83
|
+
expect(getActiveMonthButton(view)).toHaveFocus();
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
85
|
+
closeDateLookup(view);
|
|
86
|
+
});
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
it('has aria label for year', async () => {
|
|
89
|
+
const view = await setup();
|
|
90
|
+
openDateLookup(view);
|
|
91
|
+
clickDateButton(view);
|
|
92
|
+
user.click(getActiveYearButton(view));
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
expect(getButtonByAriaLabel('next year')).toBeInTheDocument();
|
|
95
|
+
expect(getButtonByAriaLabel('previous year')).toBeInTheDocument();
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
clickDateButton();
|
|
98
|
-
user.click(getActiveYearButton());
|
|
99
|
-
user.click(getActiveMonthButton());
|
|
97
|
+
closeDateLookup(view);
|
|
98
|
+
});
|
|
100
99
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
it('switches to days', async () => {
|
|
101
|
+
const view = await setup();
|
|
102
|
+
openDateLookup(view);
|
|
103
|
+
clickDateButton(view);
|
|
104
|
+
user.click(getActiveYearButton(view));
|
|
105
|
+
user.click(getActiveMonthButton(view));
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
openDateLookup();
|
|
107
|
-
const d = new Date(2018, 11, 28);
|
|
108
|
-
const newDay = screen.getByText(d.getDate().toString());
|
|
109
|
-
user.click(newDay);
|
|
107
|
+
expect(getActiveDayButton(view)).toHaveFocus();
|
|
110
108
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
});
|
|
109
|
+
closeDateLookup(view);
|
|
110
|
+
});
|
|
114
111
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
expect(screen.getByRole('button', { name: /selected day/i })).toBeInTheDocument();
|
|
122
|
-
});
|
|
112
|
+
it('has aria label for month', async () => {
|
|
113
|
+
const view = await setup();
|
|
114
|
+
openDateLookup(view);
|
|
115
|
+
clickDateButton(view);
|
|
116
|
+
user.click(getActiveYearButton(view));
|
|
117
|
+
user.click(getActiveMonthButton(view));
|
|
123
118
|
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
expect(getButtonByAriaLabel('next month')).toBeInTheDocument();
|
|
120
|
+
expect(getButtonByAriaLabel('previous month')).toBeInTheDocument();
|
|
121
|
+
|
|
122
|
+
closeDateLookup(view);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('updates selected date and closes', async () => {
|
|
126
|
+
const view = await setup();
|
|
127
|
+
openDateLookup(view);
|
|
128
|
+
const d = new Date(2018, 11, 28);
|
|
129
|
+
const newDay = screen.getByText(d.getDate().toString());
|
|
130
|
+
user.click(newDay);
|
|
131
|
+
|
|
132
|
+
expect(handleChange).toHaveBeenCalledWith(d);
|
|
133
|
+
expect(getOpenButton(view)).toHaveFocus();
|
|
134
|
+
|
|
135
|
+
closeDateLookup(view);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('has aria label on selected date', async () => {
|
|
139
|
+
const view = await setup();
|
|
140
|
+
openDateLookup(view);
|
|
141
|
+
const d = new Date(2018, 11, 28);
|
|
142
|
+
const newDay = screen.getByText(d.getDate().toString());
|
|
143
|
+
user.click(newDay);
|
|
144
|
+
openDateLookup(view);
|
|
145
|
+
expect(screen.getByRole('button', { name: /selected day/i })).toBeInTheDocument();
|
|
146
|
+
|
|
147
|
+
closeDateLookup(view);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('supports custom `aria-labelledby` attribute', async () => {
|
|
151
|
+
const view = await setup();
|
|
152
|
+
expect(screen.getByLabelText('Prioritized label')).toHaveClass('input-group');
|
|
153
|
+
|
|
154
|
+
closeDateLookup(view);
|
|
155
|
+
});
|
|
126
156
|
});
|
|
127
157
|
|
|
128
158
|
describe('when is clearable', () => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
159
|
+
/** @satisfies {import('./DateLookup').DateLookupProps} */
|
|
160
|
+
const props = {
|
|
161
|
+
value: date,
|
|
162
|
+
onChange: jest.fn(),
|
|
163
|
+
clearable: true,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const setup = async () => {
|
|
167
|
+
/** @type {import('@testing-library/react').RenderResult} */
|
|
168
|
+
let view;
|
|
169
|
+
await act(async () => {
|
|
170
|
+
view = render(<DateLookup {...props} />);
|
|
171
|
+
});
|
|
172
|
+
return view;
|
|
173
|
+
};
|
|
133
174
|
|
|
134
|
-
it(`doesn't show clear button if disable is true`, () => {
|
|
135
|
-
|
|
175
|
+
it(`doesn't show clear button if disable is true`, async () => {
|
|
176
|
+
const view = await setup();
|
|
177
|
+
expect(getClearButton(view)).toBeInTheDocument();
|
|
136
178
|
|
|
137
|
-
rerender(<DateLookup {...props} disabled />);
|
|
179
|
+
view.rerender(<DateLookup {...props} disabled />);
|
|
138
180
|
|
|
139
|
-
expect(getClearButton()).not.toBeInTheDocument();
|
|
181
|
+
expect(getClearButton(view)).not.toBeInTheDocument();
|
|
140
182
|
});
|
|
141
183
|
|
|
142
|
-
it('when user clicks on clear the focus returns to btn', () => {
|
|
143
|
-
|
|
144
|
-
|
|
184
|
+
it('when user clicks on clear the focus returns to btn', async () => {
|
|
185
|
+
const view = await setup();
|
|
186
|
+
clickClearButton(view);
|
|
187
|
+
expect(getOpenButton(view)).toHaveFocus();
|
|
145
188
|
});
|
|
146
189
|
|
|
147
|
-
it('onChange gets called with null when reset button is clicked', () => {
|
|
148
|
-
|
|
190
|
+
it('onChange gets called with null when reset button is clicked', async () => {
|
|
191
|
+
const view = await setup();
|
|
192
|
+
clickClearButton(view);
|
|
149
193
|
expect(props.onChange).toHaveBeenCalledWith(null);
|
|
150
194
|
});
|
|
151
195
|
});
|
|
152
196
|
|
|
153
|
-
const openDateLookup = () =>
|
|
154
|
-
user.click(getOpenButton());
|
|
155
|
-
};
|
|
197
|
+
const openDateLookup = (/** @type {import('@testing-library/react').RenderResult} */ view) =>
|
|
198
|
+
user.click(getOpenButton(view));
|
|
156
199
|
|
|
157
|
-
const clickDateButton = () =>
|
|
158
|
-
user.click(getDateButton());
|
|
159
|
-
};
|
|
200
|
+
const clickDateButton = (/** @type {import('@testing-library/react').RenderResult} */ view) =>
|
|
201
|
+
user.click(getDateButton(view));
|
|
160
202
|
|
|
161
203
|
// Close dateLookup and removes events attached to documents.
|
|
162
|
-
const closeDateLookup = () =>
|
|
163
|
-
user.click(container);
|
|
164
|
-
};
|
|
204
|
+
const closeDateLookup = (/** @type {import('@testing-library/react').RenderResult} */ view) =>
|
|
205
|
+
user.click(view.container);
|
|
165
206
|
|
|
166
|
-
const clickClearButton = () =>
|
|
167
|
-
user.click(getClearButton());
|
|
168
|
-
};
|
|
207
|
+
const clickClearButton = (/** @type {import('@testing-library/react').RenderResult} */ view) =>
|
|
208
|
+
user.click(getClearButton(view));
|
|
169
209
|
|
|
170
|
-
const getActiveYearButton = (
|
|
171
|
-
|
|
210
|
+
const getActiveYearButton = (
|
|
211
|
+
/** @type {import('@testing-library/react').RenderResult} */ view,
|
|
212
|
+
) => {
|
|
213
|
+
return view.container.querySelector('button.tw-date-lookup-year-option.active');
|
|
172
214
|
};
|
|
173
215
|
|
|
174
|
-
const getActiveMonthButton = (
|
|
175
|
-
|
|
216
|
+
const getActiveMonthButton = (
|
|
217
|
+
/** @type {import('@testing-library/react').RenderResult} */ view,
|
|
218
|
+
) => {
|
|
219
|
+
return view.container.querySelector('button.tw-date-lookup-month-option.active');
|
|
176
220
|
};
|
|
177
221
|
|
|
178
|
-
const getActiveDayButton = (
|
|
179
|
-
|
|
222
|
+
const getActiveDayButton = (
|
|
223
|
+
/** @type {import('@testing-library/react').RenderResult} */ view,
|
|
224
|
+
) => {
|
|
225
|
+
return view.container.querySelector('button.tw-date-lookup-day-option.active');
|
|
180
226
|
};
|
|
181
227
|
|
|
182
|
-
const getButtonByAriaLabel = (ariaLabel) => {
|
|
228
|
+
const getButtonByAriaLabel = (/** @type {string} */ ariaLabel) => {
|
|
183
229
|
return screen.getByRole('button', { name: ariaLabel });
|
|
184
230
|
};
|
|
185
|
-
const getClearButton = (
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
const
|
|
231
|
+
const getClearButton = (/** @type {import('@testing-library/react').RenderResult} */ view) =>
|
|
232
|
+
view.container.querySelector('.clear-btn');
|
|
233
|
+
const getOpenButton = (/** @type {import('@testing-library/react').RenderResult} */ view) =>
|
|
234
|
+
view.container.querySelector('button.np-date-trigger');
|
|
235
|
+
const getDateButton = (/** @type {import('@testing-library/react').RenderResult} */ view) =>
|
|
236
|
+
view.container.querySelector('button.tw-date-lookup-header-current');
|
|
190
237
|
});
|
|
@@ -19,7 +19,7 @@ import { getStartOfDay } from './getStartOfDay';
|
|
|
19
19
|
import MonthCalendar from './monthCalendar';
|
|
20
20
|
import YearCalendar from './yearCalendar';
|
|
21
21
|
|
|
22
|
-
export interface DateLookupProps {
|
|
22
|
+
export interface DateLookupProps extends Partial<WithInputAttributesProps> {
|
|
23
23
|
id?: string;
|
|
24
24
|
value: Date | null;
|
|
25
25
|
min?: Date | null;
|
|
@@ -36,8 +36,6 @@ export interface DateLookupProps {
|
|
|
36
36
|
onBlur?: () => void;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
type DateLookupPropsWithInputAttributes = DateLookupProps & Partial<WithInputAttributesProps>;
|
|
40
|
-
|
|
41
39
|
interface DateLookupState {
|
|
42
40
|
selectedDate: Date | null;
|
|
43
41
|
originalDate: Date | null;
|
|
@@ -50,9 +48,9 @@ interface DateLookupState {
|
|
|
50
48
|
isMobile: boolean;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
class DateLookup extends PureComponent<
|
|
54
|
-
declare props:
|
|
55
|
-
Required<Pick<
|
|
51
|
+
class DateLookup extends PureComponent<DateLookupProps, DateLookupState> {
|
|
52
|
+
declare props: DateLookupProps &
|
|
53
|
+
Required<Pick<DateLookupProps, keyof typeof DateLookup.defaultProps>>;
|
|
56
54
|
|
|
57
55
|
static defaultProps = {
|
|
58
56
|
value: null,
|
|
@@ -64,7 +62,7 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
|
|
|
64
62
|
monthFormat: MonthFormat.LONG,
|
|
65
63
|
disabled: false,
|
|
66
64
|
clearable: false,
|
|
67
|
-
} satisfies Partial<
|
|
65
|
+
} satisfies Partial<DateLookupProps>;
|
|
68
66
|
|
|
69
67
|
element = createRef<HTMLDivElement>();
|
|
70
68
|
dropdown = createRef<HTMLDivElement>();
|
|
@@ -108,7 +106,7 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
|
|
|
108
106
|
return null;
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
componentDidUpdate(previousProps:
|
|
109
|
+
componentDidUpdate(previousProps: DateLookupProps) {
|
|
112
110
|
if (this.props.value?.getTime() !== previousProps.value?.getTime() && this.state.open) {
|
|
113
111
|
this.focusOn('.active');
|
|
114
112
|
}
|
|
@@ -352,9 +350,6 @@ class DateLookup extends PureComponent<DateLookupPropsWithInputAttributes, DateL
|
|
|
352
350
|
|
|
353
351
|
export const DateLookupWithoutInputAttributes = DateLookup;
|
|
354
352
|
|
|
355
|
-
export default withInputAttributes(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
nonLabelable: true,
|
|
359
|
-
},
|
|
360
|
-
);
|
|
353
|
+
export default withInputAttributes(DateLookup as React.ComponentType<DateLookupProps>, {
|
|
354
|
+
nonLabelable: true,
|
|
355
|
+
});
|
package/src/drawer/Drawer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useId } from '@radix-ui/react-id';
|
|
2
1
|
import classNames from 'classnames';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import { useId } from 'react';
|
|
4
4
|
|
|
5
5
|
import { Position, Typography } from '../common';
|
|
6
6
|
import { CloseButton } from '../common/closeButton';
|
|
@@ -56,12 +56,12 @@ Drawer.propTypes = {
|
|
|
56
56
|
footerContent: PropTypes.node,
|
|
57
57
|
/** The content to appear in the drawer header. */
|
|
58
58
|
headerTitle: PropTypes.node,
|
|
59
|
-
/** The action to perform on close click. */
|
|
60
|
-
onClose: PropTypes.func,
|
|
61
59
|
/** The status of Drawer either open or not. */
|
|
62
60
|
open: PropTypes.bool,
|
|
63
61
|
/** The placement of Drawer on the screen either left or right. On mobile it will default to bottom. */
|
|
64
62
|
position: PropTypes.oneOf(['left', 'right', 'bottom']),
|
|
63
|
+
/** The action to perform on close click. */
|
|
64
|
+
onClose: PropTypes.func,
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
Drawer.defaultProps = {
|
package/src/field/Field.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useId } from '@radix-ui/react-id';
|
|
2
1
|
import classNames from 'classnames';
|
|
2
|
+
import { useId } from 'react';
|
|
3
3
|
|
|
4
4
|
import { Sentiment } from '../common';
|
|
5
5
|
import InlineAlert from '../inlineAlert/InlineAlert';
|
|
@@ -27,10 +27,10 @@ export const Field = ({ id, label, hint, error, className, children }: FieldProp
|
|
|
27
27
|
|
|
28
28
|
const labelId = useId();
|
|
29
29
|
|
|
30
|
-
const fallbackInputId = useId();
|
|
30
|
+
const fallbackInputId = useId();
|
|
31
31
|
const inputId = id !== null ? id ?? fallbackInputId : undefined;
|
|
32
32
|
|
|
33
|
-
const descriptionId = useId();
|
|
33
|
+
const descriptionId = useId();
|
|
34
34
|
|
|
35
35
|
return (
|
|
36
36
|
<FieldLabelIdContextProvider value={labelId}>
|
package/src/index.ts
CHANGED
|
@@ -52,6 +52,7 @@ export type {
|
|
|
52
52
|
export type { NavigationOptionListProps } from './navigationOptionsList';
|
|
53
53
|
export type { PhoneNumberInputProps } from './phoneNumberInput/PhoneNumberInput';
|
|
54
54
|
export type { PopoverProps } from './popover';
|
|
55
|
+
export type { ProcessIndicatorProps } from './processIndicator';
|
|
55
56
|
export type { ProgressProps } from './progress';
|
|
56
57
|
export type { ProgressBarProps } from './progressBar';
|
|
57
58
|
export type { DirectionProviderProps, LanguageProviderProps, ProviderProps } from './provider';
|
|
@@ -104,8 +105,8 @@ export { default as Display } from './display';
|
|
|
104
105
|
export { default as Drawer } from './drawer';
|
|
105
106
|
export { default as DropFade } from './dropFade';
|
|
106
107
|
export { default as Emphasis } from './emphasis';
|
|
107
|
-
export { default as FlowNavigation } from './flowNavigation/FlowNavigation';
|
|
108
108
|
export { Field } from './field/Field';
|
|
109
|
+
export { default as FlowNavigation } from './flowNavigation/FlowNavigation';
|
|
109
110
|
export { default as Header } from './header';
|
|
110
111
|
export { default as Image } from './image';
|
|
111
112
|
export { default as Info } from './info';
|
|
@@ -139,7 +140,7 @@ export { default as Popover } from './popover';
|
|
|
139
140
|
export { default as ProcessIndicator } from './processIndicator';
|
|
140
141
|
export { default as Progress } from './progress';
|
|
141
142
|
export { default as ProgressBar } from './progressBar';
|
|
142
|
-
export {
|
|
143
|
+
export { default as PromoCard, PromoCardGroup } from './promoCard';
|
|
143
144
|
export { DirectionProvider, LanguageProvider, default as Provider } from './provider';
|
|
144
145
|
export { default as Radio } from './radio';
|
|
145
146
|
export { default as RadioGroup } from './radioGroup';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Input, type InputProps } from '../inputs/Input';
|
|
2
2
|
import WithDisplayFormat, { type WithDisplayFormatProps } from '../withDisplayFormat';
|
|
3
3
|
|
|
4
|
-
export interface InputWithDisplayFormatProps
|
|
4
|
+
export interface InputWithDisplayFormatProps
|
|
5
|
+
extends Omit<WithDisplayFormatProps<InputProps>, 'render'> {}
|
|
5
6
|
|
|
6
7
|
const InputWithDisplayFormat = (props: InputWithDisplayFormatProps) => (
|
|
7
8
|
<WithDisplayFormat<InputProps> {...props} render={(renderProps) => <Input {...renderProps} />} />
|
|
@@ -197,6 +197,7 @@ export const Currencies: Story<Currency> = {
|
|
|
197
197
|
|
|
198
198
|
const input = screen.getByRole('searchbox');
|
|
199
199
|
|
|
200
|
+
await userEvent.click(input);
|
|
200
201
|
await userEvent.type(input, 'huf');
|
|
201
202
|
await expect(
|
|
202
203
|
within(screen.getByRole('listbox')).queryByRole('option'),
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { Listbox as ListboxBase } from '@headlessui/react';
|
|
2
|
-
import { useId } from '@radix-ui/react-id';
|
|
3
2
|
import { Check, ChevronDown, Cross, CrossCircle } from '@transferwise/icons';
|
|
4
3
|
import classNames from 'classnames';
|
|
5
4
|
import mergeProps from 'merge-props';
|
|
6
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
createContext,
|
|
7
|
+
forwardRef,
|
|
8
|
+
useContext,
|
|
9
|
+
useEffect,
|
|
10
|
+
useId,
|
|
11
|
+
useMemo,
|
|
12
|
+
useRef,
|
|
13
|
+
useState,
|
|
14
|
+
} from 'react';
|
|
7
15
|
import { useIntl } from 'react-intl';
|
|
8
16
|
|
|
9
17
|
import { useEffectEvent } from '../common/hooks/useEffectEvent';
|
package/src/inputs/contexts.tsx
CHANGED
|
@@ -31,12 +31,12 @@ export interface WithInputAttributesProps {
|
|
|
31
31
|
inputAttributes: ReturnType<typeof useInputAttributes>;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export function withInputAttributes<T
|
|
35
|
-
Component: React.ComponentType<T
|
|
34
|
+
export function withInputAttributes<T>(
|
|
35
|
+
Component: React.ComponentType<T & Partial<WithInputAttributesProps>>,
|
|
36
36
|
args?: UseInputAttributesArgs,
|
|
37
37
|
) {
|
|
38
|
-
function ComponentWithInputAttributes(props:
|
|
39
|
-
return <Component inputAttributes={useInputAttributes(args)} {...
|
|
38
|
+
function ComponentWithInputAttributes(props: T) {
|
|
39
|
+
return <Component inputAttributes={useInputAttributes(args)} {...props} />;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
ComponentWithInputAttributes.displayName = `withInputAttributes(${Component.displayName || Component.name || 'Component'})`;
|
package/src/modal/Modal.tsx
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { act } from 'react';
|
|
2
|
+
|
|
3
|
+
import { render, screen } from '../test-utils';
|
|
4
|
+
import ProcessIndicator, { ProcessIndicatorProps } from './ProcessIndicator';
|
|
5
|
+
|
|
6
|
+
describe('ProcessIndicator', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
jest.useFakeTimers();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await jest.runOnlyPendingTimersAsync();
|
|
13
|
+
jest.useRealTimers();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('supports transitioning between states', async () => {
|
|
17
|
+
const handleAnimationCompleted = jest.fn();
|
|
18
|
+
const initialProps = {
|
|
19
|
+
'data-testid': 'process-indicator',
|
|
20
|
+
onAnimationCompleted: handleAnimationCompleted,
|
|
21
|
+
} satisfies ProcessIndicatorProps;
|
|
22
|
+
const view = render(<ProcessIndicator {...initialProps} />);
|
|
23
|
+
|
|
24
|
+
expect(screen.getByTestId('process-indicator')).not.toHaveClass('process-success');
|
|
25
|
+
expect(screen.getByTestId('process-indicator')).not.toHaveClass('process-xl');
|
|
26
|
+
|
|
27
|
+
const updatedProps = {
|
|
28
|
+
status: 'succeeded',
|
|
29
|
+
size: 'xl',
|
|
30
|
+
} satisfies ProcessIndicatorProps;
|
|
31
|
+
view.rerender(<ProcessIndicator {...initialProps} {...updatedProps} />);
|
|
32
|
+
await act(async () => {
|
|
33
|
+
await jest.runOnlyPendingTimersAsync();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(screen.getByTestId('process-indicator')).toHaveClass('process-success');
|
|
37
|
+
expect(screen.getByTestId('process-indicator')).toHaveClass('process-xl');
|
|
38
|
+
expect(handleAnimationCompleted).not.toHaveBeenCalled();
|
|
39
|
+
|
|
40
|
+
await jest.runOnlyPendingTimersAsync();
|
|
41
|
+
|
|
42
|
+
expect(handleAnimationCompleted).toHaveBeenCalledWith(updatedProps.status);
|
|
43
|
+
expect(handleAnimationCompleted).toHaveBeenCalledTimes(1);
|
|
44
|
+
});
|
|
45
|
+
});
|