@transferwise/components 0.0.0-experimental-bb2bef0 → 0.0.0-experimental-537cce6

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 (46) hide show
  1. package/build/alert/Alert.js +8 -0
  2. package/build/alert/Alert.js.map +1 -1
  3. package/build/alert/Alert.mjs +8 -0
  4. package/build/alert/Alert.mjs.map +1 -1
  5. package/build/common/closeButton/CloseButton.js +3 -1
  6. package/build/common/closeButton/CloseButton.js.map +1 -1
  7. package/build/common/closeButton/CloseButton.mjs +3 -1
  8. package/build/common/closeButton/CloseButton.mjs.map +1 -1
  9. package/build/i18n/en.json +0 -2
  10. package/build/i18n/en.json.js +0 -2
  11. package/build/i18n/en.json.js.map +1 -1
  12. package/build/i18n/en.json.mjs +0 -2
  13. package/build/i18n/en.json.mjs.map +1 -1
  14. package/build/phoneNumberInput/PhoneNumberInput.js +2 -36
  15. package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
  16. package/build/phoneNumberInput/PhoneNumberInput.messages.js +0 -6
  17. package/build/phoneNumberInput/PhoneNumberInput.messages.js.map +1 -1
  18. package/build/phoneNumberInput/PhoneNumberInput.messages.mjs +0 -6
  19. package/build/phoneNumberInput/PhoneNumberInput.messages.mjs.map +1 -1
  20. package/build/phoneNumberInput/PhoneNumberInput.mjs +2 -36
  21. package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  22. package/build/types/alert/Alert.d.ts.map +1 -1
  23. package/build/types/common/closeButton/CloseButton.d.ts +2 -0
  24. package/build/types/common/closeButton/CloseButton.d.ts.map +1 -1
  25. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
  26. package/build/types/phoneNumberInput/PhoneNumberInput.messages.d.ts +0 -8
  27. package/build/types/phoneNumberInput/PhoneNumberInput.messages.d.ts.map +1 -1
  28. package/build/types/test-utils/index.d.ts +0 -4
  29. package/build/types/test-utils/index.d.ts.map +1 -1
  30. package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
  31. package/build/withDisplayFormat/WithDisplayFormat.js +3 -2
  32. package/build/withDisplayFormat/WithDisplayFormat.js.map +1 -1
  33. package/build/withDisplayFormat/WithDisplayFormat.mjs +3 -2
  34. package/build/withDisplayFormat/WithDisplayFormat.mjs.map +1 -1
  35. package/package.json +3 -3
  36. package/src/alert/Alert.spec.tsx +11 -0
  37. package/src/alert/Alert.story.tsx +23 -9
  38. package/src/alert/Alert.tsx +14 -1
  39. package/src/common/closeButton/CloseButton.spec.tsx +13 -1
  40. package/src/common/closeButton/CloseButton.tsx +3 -0
  41. package/src/i18n/en.json +0 -2
  42. package/src/phoneNumberInput/PhoneNumberInput.messages.ts +0 -8
  43. package/src/phoneNumberInput/PhoneNumberInput.spec.tsx +43 -79
  44. package/src/phoneNumberInput/PhoneNumberInput.tsx +2 -34
  45. package/src/withDisplayFormat/WithDisplayFormat.spec.js +11 -15
  46. package/src/withDisplayFormat/WithDisplayFormat.tsx +3 -2
@@ -5,12 +5,4 @@ export default defineMessages({
5
5
  id: 'neptune.PhoneNumberInput.SelectInput.placeholder',
6
6
  defaultMessage: 'Select an option...',
7
7
  },
8
- countryCodeLabel: {
9
- id: 'neptune.PhoneNumberInput.countryCodeLabel',
10
- defaultMessage: 'Country code',
11
- },
12
- phoneNumberLabel: {
13
- id: 'neptune.PhoneNumberInput.phoneNumberLabel',
14
- defaultMessage: 'Phone number',
15
- },
16
8
  });
@@ -21,30 +21,28 @@ describe('PhoneNumberInput', () => {
21
21
  const customRender = (overrides: Partial<PhoneNumberInputProps> = {}, locale?: string) =>
22
22
  render(<PhoneNumberInput {...props} {...overrides} />, { locale });
23
23
 
24
- const getCountryCodeSelect = () => screen.getByRole('combobox');
25
- const getCountryCodeLabel = () => screen.getByText('Country code');
26
- const getPhoneNumberInput = () => screen.getByRole('textbox');
27
- const getPhoneNumberLabel = () => screen.getByText('Phone number');
24
+ const getPrefixEl = () => screen.getByRole('combobox');
25
+ const getInputEl = () => screen.getByRole('textbox');
28
26
 
29
27
  describe('defaults', () => {
30
28
  it('should set prefix control to default UK value', () => {
31
29
  customRender();
32
- expect(getCountryCodeSelect()).toHaveTextContent('+44');
30
+ expect(getPrefixEl()).toHaveTextContent('+44');
33
31
  });
34
32
 
35
33
  it('should set number control to empty', () => {
36
34
  customRender();
37
- expect(getPhoneNumberInput()).toHaveValue('');
35
+ expect(getInputEl()).toHaveValue('');
38
36
  });
39
37
 
40
38
  it('should not disable the select', () => {
41
39
  customRender();
42
- expect(getCountryCodeSelect()).toBeEnabled();
40
+ expect(getPrefixEl()).toBeEnabled();
43
41
  });
44
42
 
45
43
  it('should not disable the input', () => {
46
44
  customRender();
47
- expect(getPhoneNumberInput()).toBeEnabled();
45
+ expect(getInputEl()).toBeEnabled();
48
46
  });
49
47
  });
50
48
 
@@ -52,56 +50,22 @@ describe('PhoneNumberInput', () => {
52
50
  const prefix = '+39';
53
51
  const number = '123456789';
54
52
  customRender({ initialValue: `${prefix}${number}` });
55
- expect(getCountryCodeSelect()).toHaveTextContent(prefix);
56
- expect(getPhoneNumberInput()).toHaveValue(number);
53
+ expect(getPrefixEl()).toHaveTextContent(prefix);
54
+ expect(getInputEl()).toHaveValue(number);
57
55
  });
58
56
 
59
57
  describe('id prop', () => {
60
- it('should render sensible default IDs', () => {
58
+ it('should not render id by default', () => {
61
59
  customRender();
62
- const countryCodeSelectID = getCountryCodeSelect().getAttribute('id');
63
- expect(countryCodeSelectID).toMatch(/^country-code-select-[a-z0-9]{6}$/);
64
- const countryCodeLabelID = getCountryCodeLabel().getAttribute('id');
65
- expect(countryCodeLabelID).toMatch(/^country-code-label-[a-z0-9]{6}$/);
66
- const phoneNumberInputID = getPhoneNumberInput().getAttribute('id');
67
- expect(phoneNumberInputID).toMatch(/^phone-number-input-[a-z0-9]{6}$/);
68
- const phoneNumberLabelID = getPhoneNumberLabel().getAttribute('id');
69
- expect(phoneNumberLabelID).toMatch(/^phone-number-label-[a-z0-9]{6}$/);
60
+ expect(getPrefixEl()).not.toHaveAttribute('id');
61
+ expect(getInputEl()).not.toHaveAttribute('id');
70
62
  });
71
63
 
72
- it('should use the custom `id` as-is for the input but with slight modification for select', () => {
64
+ it('should respect `id` for the input and ignore the select', () => {
73
65
  const id = 'component-id';
74
66
  customRender({ id });
75
- expect(getPhoneNumberInput()).toHaveAttribute('id', id);
76
- expect(getPhoneNumberLabel()).toHaveAttribute('id', `${id}-phone-number-label`);
77
- expect(getCountryCodeSelect()).toHaveAttribute('id', `${id}-country-code-select`);
78
- expect(getCountryCodeLabel()).toHaveAttribute('id', `${id}-country-code-label`);
79
- });
80
-
81
- it('should set correct ARIA attributes on the country code select when id is provided', () => {
82
- const id = 'my-id';
83
- customRender({ id });
84
- // The select trigger should have aria-labelledby pointing to the label
85
- expect(getCountryCodeSelect()).toHaveAttribute('aria-labelledby', `${id}-country-code-label`);
86
- });
87
-
88
- it('should set correct ARIA attributes on the country code select when id is not provided', () => {
89
- customRender();
90
- // The select trigger should have aria-labelledby pointing to a generated label id
91
- const selectLabelledBy = getCountryCodeSelect().getAttribute('aria-labelledby');
92
- expect(selectLabelledBy).toMatch(/^country-code-label-[a-z0-9]{6}$/);
93
- });
94
-
95
- it('should set correct ARIA attributes on the phone number input when id is provided', () => {
96
- const id = 'my-id';
97
- customRender({ id });
98
- expect(getPhoneNumberInput()).toHaveAttribute('aria-labelledby', `${id}-phone-number-label`);
99
- });
100
-
101
- it('should set correct ARIA attributes on the phone number input when id is not provided', () => {
102
- customRender();
103
- const inputLabelledBy = getPhoneNumberInput().getAttribute('aria-labelledby');
104
- expect(inputLabelledBy).toMatch(/^phone-number-label-[a-z0-9]{6}$/);
67
+ expect(getPrefixEl()).not.toHaveAttribute('id');
68
+ expect(getInputEl()).toHaveAttribute('id', id);
105
69
  });
106
70
  });
107
71
 
@@ -130,38 +94,38 @@ describe('PhoneNumberInput', () => {
130
94
  it(`'${number}' number should update the value properly`, async () => {
131
95
  await renderAndPaste(number);
132
96
 
133
- expect(getCountryCodeSelect()).toHaveTextContent(countryCode);
134
- expect(getPhoneNumberInput()).toHaveValue(localNumber);
97
+ expect(getPrefixEl()).toHaveTextContent(countryCode);
98
+ expect(getInputEl()).toHaveValue(localNumber);
135
99
  expect(props.onChange).toHaveBeenCalledWith(number.replace(/[\s-]+/g, ''), countryCode);
136
100
  });
137
101
  });
138
102
 
139
103
  it('should not paste invalid characters', async () => {
140
104
  await renderAndPaste('+36asdasdasd');
141
- expect(getCountryCodeSelect()).toHaveTextContent(initialPrefix);
142
- expect(getPhoneNumberInput()).toHaveValue(initialNumber);
105
+ expect(getPrefixEl()).toHaveTextContent(initialPrefix);
106
+ expect(getInputEl()).toHaveValue(initialNumber);
143
107
  expect(props.onChange).not.toHaveBeenCalled();
144
108
  });
145
109
 
146
110
  it('should not paste countries which are not in the select', async () => {
147
111
  await renderAndPaste('+9992342343423');
148
- expect(getCountryCodeSelect()).toHaveTextContent(initialPrefix);
149
- expect(getPhoneNumberInput()).toHaveValue(initialNumber);
112
+ expect(getPrefixEl()).toHaveTextContent(initialPrefix);
113
+ expect(getInputEl()).toHaveValue(initialNumber);
150
114
  expect(props.onChange).not.toHaveBeenCalled();
151
115
  });
152
116
 
153
117
  it("should not paste numbers which doesn't start with the country code", async () => {
154
118
  await renderAndPaste('0+36303932551');
155
- expect(getCountryCodeSelect()).toHaveTextContent(initialPrefix);
156
- expect(getPhoneNumberInput()).toHaveValue(initialNumber);
119
+ expect(getPrefixEl()).toHaveTextContent(initialPrefix);
120
+ expect(getInputEl()).toHaveValue(initialNumber);
157
121
  expect(props.onChange).not.toHaveBeenCalled();
158
122
  });
159
123
 
160
124
  it("should allow pasting numbers which don't contain a country code", async () => {
161
125
  const newNumber = '06303932551';
162
126
  await renderAndPaste(newNumber);
163
- expect(getCountryCodeSelect()).toHaveTextContent(initialPrefix);
164
- expect(getPhoneNumberInput()).toHaveValue(newNumber);
127
+ expect(getPrefixEl()).toHaveTextContent(initialPrefix);
128
+ expect(getInputEl()).toHaveValue(newNumber);
165
129
  expect(props.onChange).toHaveBeenCalledWith(`${initialPrefix}${newNumber}`, initialPrefix);
166
130
  });
167
131
  });
@@ -172,12 +136,12 @@ describe('PhoneNumberInput', () => {
172
136
 
173
137
  it('should set the select to the longest matching prefix', () => {
174
138
  customRender(initialProps);
175
- expect(getCountryCodeSelect()).toHaveTextContent('+1868');
139
+ expect(getPrefixEl()).toHaveTextContent('+1868');
176
140
  });
177
141
 
178
142
  it('should set the number input to the rest of the number', () => {
179
143
  customRender(initialProps);
180
- expect(getPhoneNumberInput()).toHaveValue('123456789');
144
+ expect(getInputEl()).toHaveValue('123456789');
181
145
  });
182
146
  });
183
147
 
@@ -186,20 +150,20 @@ describe('PhoneNumberInput', () => {
186
150
 
187
151
  it('should empty the select', () => {
188
152
  customRender(initialProps);
189
- expect(getCountryCodeSelect()).toHaveTextContent('Select an option...');
153
+ expect(getPrefixEl()).toHaveTextContent('Select an option...');
190
154
  });
191
155
 
192
156
  it('should put the whole value in the input without the plus', () => {
193
157
  customRender(initialProps);
194
- expect(getPhoneNumberInput()).toHaveValue('999123456789');
158
+ expect(getInputEl()).toHaveValue('999123456789');
195
159
  });
196
160
  });
197
161
 
198
162
  describe('when an partial model is supplied (with a matching prefix)', () => {
199
163
  it('should set the select to the matching prefix and put the rest of the number in the suffix', () => {
200
164
  customRender({ initialValue: '+123' });
201
- expect(getCountryCodeSelect()).toHaveTextContent('+1');
202
- expect(getPhoneNumberInput()).toHaveValue('23');
165
+ expect(getPrefixEl()).toHaveTextContent('+1');
166
+ expect(getInputEl()).toHaveValue('23');
203
167
  });
204
168
  });
205
169
  });
@@ -207,8 +171,8 @@ describe('PhoneNumberInput', () => {
207
171
  describe('when disabled is true', () => {
208
172
  it('should disable both controls', () => {
209
173
  customRender({ disabled: true });
210
- expect(getCountryCodeSelect()).toBeDisabled();
211
- expect(getPhoneNumberInput()).toBeDisabled();
174
+ expect(getPrefixEl()).toBeDisabled();
175
+ expect(getInputEl()).toBeDisabled();
212
176
  });
213
177
  });
214
178
 
@@ -216,13 +180,13 @@ describe('PhoneNumberInput', () => {
216
180
  it('should use the provided placeholder', () => {
217
181
  const placeholder = 'custom placeholder';
218
182
  customRender({ placeholder });
219
- expect(getPhoneNumberInput()).toHaveAttribute('placeholder', placeholder);
183
+ expect(getInputEl()).toHaveAttribute('placeholder', placeholder);
220
184
  });
221
185
 
222
186
  it('should use the provided searchPlaceholder', async () => {
223
187
  const searchPlaceholder = 'search placeholder';
224
188
  customRender({ searchPlaceholder });
225
- await userEvent.click(getCountryCodeSelect());
189
+ await userEvent.click(getPrefixEl());
226
190
  expect(screen.getByRole('combobox', { name: searchPlaceholder })).toBeInTheDocument();
227
191
  });
228
192
  });
@@ -231,7 +195,7 @@ describe('PhoneNumberInput', () => {
231
195
  describe('and a value', () => {
232
196
  it('should use the prefix of the supplied value', () => {
233
197
  customRender({ initialValue: '+12345678' }, 'es');
234
- expect(getCountryCodeSelect()).toHaveTextContent('+1');
198
+ expect(getPrefixEl()).toHaveTextContent('+1');
235
199
  });
236
200
  });
237
201
 
@@ -239,14 +203,14 @@ describe('PhoneNumberInput', () => {
239
203
  describe('and no country code', () => {
240
204
  it('should default the prefix to the local country', () => {
241
205
  customRender(undefined, 'es');
242
- expect(getCountryCodeSelect()).toHaveTextContent('+34');
206
+ expect(getPrefixEl()).toHaveTextContent('+34');
243
207
  });
244
208
  });
245
209
 
246
210
  describe('and country code', () => {
247
211
  it('should override locale prefix with country specific prefix', () => {
248
212
  customRender({ countryCode: 'US' }, 'es');
249
- expect(getCountryCodeSelect()).toHaveTextContent('+1');
213
+ expect(getPrefixEl()).toHaveTextContent('+1');
250
214
  });
251
215
  });
252
216
  });
@@ -256,7 +220,7 @@ describe('PhoneNumberInput', () => {
256
220
  describe('valid number', () => {
257
221
  it('should trigger onChange handler', async () => {
258
222
  customRender();
259
- await userEvent.type(getPhoneNumberInput(), '123');
223
+ await userEvent.type(getInputEl(), '123');
260
224
  expect(props.onChange).toHaveBeenCalledWith('+44123', '+44');
261
225
  });
262
226
  });
@@ -264,7 +228,7 @@ describe('PhoneNumberInput', () => {
264
228
  describe('invalid number', () => {
265
229
  it('should trigger onChange with null value', async () => {
266
230
  customRender({ initialValue: '+1234' });
267
- await userEvent.type(getPhoneNumberInput(), '{Backspace}{Backspace}{Backspace}1');
231
+ await userEvent.type(getInputEl(), '{Backspace}{Backspace}{Backspace}1');
268
232
  expect(props.onChange).toHaveBeenCalledWith(null, '+1');
269
233
  });
270
234
  });
@@ -272,7 +236,7 @@ describe('PhoneNumberInput', () => {
272
236
  describe('when user insert invalid character', () => {
273
237
  it('should strip them', async () => {
274
238
  customRender({ initialValue: '+12345678' });
275
- await userEvent.type(getPhoneNumberInput(), '123--');
239
+ await userEvent.type(getInputEl(), '123--');
276
240
  expect(props.onChange).toHaveBeenCalledWith('+12345678123', '+1');
277
241
  });
278
242
  });
@@ -280,8 +244,8 @@ describe('PhoneNumberInput', () => {
280
244
  describe('overlapping prefix and suffix numbers', () => {
281
245
  it("shouldn't change the prefix number on matching suffix input", async () => {
282
246
  customRender({ countryCode: 'eg' });
283
- await userEvent.type(getPhoneNumberInput(), '1111111');
284
- expect(getPhoneNumberInput()).toHaveValue('1111111');
247
+ await userEvent.type(getInputEl(), '1111111');
248
+ expect(getInputEl()).toHaveValue('1111111');
285
249
  expect(props.onChange).toHaveBeenCalledWith('+201111111', '+20');
286
250
  });
287
251
  });
@@ -290,7 +254,7 @@ describe('PhoneNumberInput', () => {
290
254
  describe('when selectProps is supplied', () => {
291
255
  it('renders Select component with expected props', () => {
292
256
  customRender({ selectProps: { className: 'custom-class' } });
293
- expect(getCountryCodeSelect().parentElement).toHaveClass('custom-class');
257
+ expect(getPrefixEl().parentElement).toHaveClass('custom-class');
294
258
  });
295
259
  });
296
260
 
@@ -4,6 +4,7 @@ import { useIntl } from 'react-intl';
4
4
  import { Size, SizeLarge, SizeMedium, SizeSmall } from '../common';
5
5
  import { useInputAttributes } from '../inputs/contexts';
6
6
  import { SelectInput, SelectInputOptionContent, SelectInputProps } from '../inputs/SelectInput';
7
+
7
8
  import messages from './PhoneNumberInput.messages';
8
9
  import countries from './data/countries';
9
10
  import {
@@ -63,25 +64,6 @@ const PhoneNumberInput = ({
63
64
 
64
65
  const { locale, formatMessage } = useIntl();
65
66
 
66
- const createId = (customID: string | undefined, backup: string): string => {
67
- if (customID) {
68
- return customID + (backup ? `-${backup}` : '');
69
- }
70
- const random = Math.random().toString(36).slice(2, 8);
71
- return `${backup}-${random}`;
72
- };
73
-
74
- const ids = {
75
- countryCode: {
76
- label: createId(id, 'country-code-label'),
77
- select: createId(id, 'country-code-select'),
78
- },
79
- phoneNumber: {
80
- label: createId(id, 'phone-number-label'),
81
- input: createId(id, id ? '' : 'phone-number-input'),
82
- },
83
- };
84
-
85
67
  const [internalValue, setInternalValue] = useState<PhoneNumber>(() => {
86
68
  const cleanValue = initialValue ? cleanNumber(initialValue) : null;
87
69
 
@@ -169,9 +151,6 @@ const PhoneNumberInput = ({
169
151
  aria-labelledby={ariaLabelledBy}
170
152
  className="tw-telephone"
171
153
  >
172
- <label className="sr-only" id={ids.countryCode.label}>
173
- {formatMessage(messages.countryCodeLabel)}
174
- </label>
175
154
  <div className="tw-telephone__country-select">
176
155
  <SelectInput
177
156
  placeholder={formatMessage(messages.selectInputPlaceholder)}
@@ -202,13 +181,6 @@ const PhoneNumberInput = ({
202
181
  filterPlaceholder={searchPlaceholder}
203
182
  disabled={disabled}
204
183
  size={size}
205
- id={ids.countryCode.select}
206
- UNSAFE_triggerButtonProps={{
207
- id: ids.countryCode.select,
208
- 'aria-labelledby': ids.countryCode.label,
209
- 'aria-describedby': undefined,
210
- 'aria-invalid': undefined,
211
- }}
212
184
  onChange={(prefix) => {
213
185
  const country = prefix != null ? findCountryByPrefix(prefix) : null;
214
186
  setInternalValue((prev) => ({ ...prev, prefix, format: country?.phoneFormat }));
@@ -221,13 +193,10 @@ const PhoneNumberInput = ({
221
193
  {...selectProps}
222
194
  />
223
195
  </div>
224
- <label className="sr-only" id={ids.phoneNumber.label} htmlFor={ids.phoneNumber.input}>
225
- {formatMessage(messages.phoneNumberLabel)}
226
- </label>
227
196
  <div className="tw-telephone__number-input">
228
197
  <div className={`input-group input-group-${size}`}>
229
198
  <Input
230
- id={ids.phoneNumber.input}
199
+ id={id}
231
200
  autoComplete="tel-national"
232
201
  name="phoneNumber"
233
202
  inputMode="numeric"
@@ -235,7 +204,6 @@ const PhoneNumberInput = ({
235
204
  disabled={disabled}
236
205
  required={required}
237
206
  placeholder={placeholder}
238
- aria-labelledby={ids.phoneNumber.label}
239
207
  onChange={onSuffixChange}
240
208
  onPaste={onPaste}
241
209
  onFocus={onFocus}
@@ -3,7 +3,7 @@ import { userEvent, render, screen, waitFor } from '../test-utils';
3
3
  import { Input } from '../inputs/Input';
4
4
  import WithDisplayFormat from '.';
5
5
 
6
- const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
6
+ const user = userEvent;
7
7
 
8
8
  const setup = (props) =>
9
9
  render(
@@ -22,15 +22,6 @@ describe('InputWithTextFormat (React Testing Library)', () => {
22
22
  onBlur: jest.fn(),
23
23
  };
24
24
 
25
- beforeEach(() => {
26
- jest.useFakeTimers();
27
- });
28
-
29
- afterEach(async () => {
30
- await jest.runOnlyPendingTimersAsync();
31
- jest.useRealTimers();
32
- });
33
-
34
25
  [
35
26
  { value: '123', expectedValue: '12-3', displayPattern: '**-**-**' },
36
27
  { value: '1234', expectedValue: '12-34', displayPattern: '**-**-**' },
@@ -132,18 +123,23 @@ describe('InputWithTextFormat (React Testing Library)', () => {
132
123
  expect(input).toHaveValue('12');
133
124
  });
134
125
 
135
- // @FIXME (maybe) Is this behaviour expected? 🤔
136
- it(`moves to the end, when entered a char in the middle`, async () => {
126
+ it(`cusor preserve position when entered a char in the middle`, async () => {
137
127
  setup(initialProps);
138
128
  const input = screen.getByRole('textbox');
139
129
  await user.type(input, '123');
140
130
  expect(input).toHaveValue('12-3');
141
131
 
142
- await user.type(input, '{arrowLeft}{arrowLeft}{arrowLeft}@');
132
+ await user.keyboard('{arrowleft}{arrowleft}{arrowleft}');
133
+ await user.keyboard('@');
134
+
143
135
  expect(input).toHaveValue('1@-23');
144
136
 
145
- await user.type(input, 'x');
146
- expect(input).toHaveValue('1@-23x');
137
+ await user.keyboard('x');
138
+ expect(input).toHaveValue('1@-x23');
139
+
140
+ await user.keyboard('{arrowright}{backspace}');
141
+
142
+ expect(input).toHaveValue('1@-x3');
147
143
  });
148
144
 
149
145
  it(`supports pasting`, async () => {
@@ -270,7 +270,6 @@ class WithDisplayFormat<T extends TextElementProps> extends React.Component<
270
270
  handleCursorPositioning = (action: string) => {
271
271
  const { displayPattern } = this.props;
272
272
  const { triggerEvent, selectionStart, selectionEnd, pastedLength } = this.state;
273
- const target = triggerEvent?.currentTarget;
274
273
 
275
274
  const cursorPosition = getCursorPositionAfterKeystroke(
276
275
  action,
@@ -281,7 +280,9 @@ class WithDisplayFormat<T extends TextElementProps> extends React.Component<
281
280
  );
282
281
 
283
282
  setTimeout(() => {
284
- target?.setSelectionRange(cursorPosition, cursorPosition);
283
+ if (triggerEvent) {
284
+ (triggerEvent.target as HTMLTextElement).setSelectionRange(cursorPosition, cursorPosition);
285
+ }
285
286
  this.setState({ selectionStart: cursorPosition, selectionEnd: cursorPosition });
286
287
  }, 0);
287
288
  };