@transferwise/components 46.66.0 → 46.67.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.
- package/build/i18n/en.json +1 -0
- package/build/i18n/en.json.js +1 -0
- package/build/i18n/en.json.js.map +1 -1
- package/build/i18n/en.json.mjs +1 -0
- package/build/i18n/en.json.mjs.map +1 -1
- package/build/inputs/SelectInput.js +4 -0
- package/build/inputs/SelectInput.js.map +1 -1
- package/build/inputs/SelectInput.mjs +4 -0
- package/build/inputs/SelectInput.mjs.map +1 -1
- package/build/main.css +0 -24
- package/build/moneyInput/MoneyInput.js +8 -1
- package/build/moneyInput/MoneyInput.js.map +1 -1
- package/build/moneyInput/MoneyInput.messages.js +3 -0
- package/build/moneyInput/MoneyInput.messages.js.map +1 -1
- package/build/moneyInput/MoneyInput.messages.mjs +3 -0
- package/build/moneyInput/MoneyInput.messages.mjs.map +1 -1
- package/build/moneyInput/MoneyInput.mjs +8 -1
- package/build/moneyInput/MoneyInput.mjs.map +1 -1
- package/build/stepper/Stepper.js +12 -1
- package/build/stepper/Stepper.js.map +1 -1
- package/build/stepper/Stepper.mjs +12 -1
- package/build/stepper/Stepper.mjs.map +1 -1
- package/build/styles/main.css +0 -24
- package/build/styles/stepper/Stepper.css +0 -24
- package/build/types/inputs/SelectInput.d.ts +3 -1
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
- package/build/types/moneyInput/MoneyInput.messages.d.ts +5 -0
- package/build/types/moneyInput/MoneyInput.messages.d.ts.map +1 -1
- package/build/types/stepper/Stepper.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/flowNavigation/__snapshots__/FlowNavigation.spec.js.snap +1 -2
- package/src/i18n/en.json +1 -0
- package/src/inputs/SelectInput.tsx +8 -3
- package/src/main.css +0 -24
- package/src/moneyInput/MoneyInput.docs.mdx +34 -0
- package/src/moneyInput/MoneyInput.messages.ts +5 -0
- package/src/moneyInput/MoneyInput.rtl.spec.tsx +47 -0
- package/src/moneyInput/MoneyInput.spec.js +0 -11
- package/src/moneyInput/MoneyInput.story.tsx +10 -7
- package/src/moneyInput/MoneyInput.tsx +8 -1
- package/src/stepper/Stepper.css +0 -24
- package/src/stepper/Stepper.less +0 -17
- package/src/stepper/Stepper.spec.js +11 -5
- package/src/stepper/Stepper.tsx +13 -2
- package/src/withId/withId.story.tsx +1 -0
|
@@ -2,6 +2,7 @@ import { Field } from '../field/Field';
|
|
|
2
2
|
import { mockMatchMedia, mockResizeObserver, render, screen, userEvent } from '../test-utils';
|
|
3
3
|
|
|
4
4
|
import MoneyInput from './MoneyInput';
|
|
5
|
+
import messages from './MoneyInput.messages';
|
|
5
6
|
|
|
6
7
|
mockMatchMedia();
|
|
7
8
|
mockResizeObserver();
|
|
@@ -51,6 +52,7 @@ describe('MoneyInput', () => {
|
|
|
51
52
|
const props = {
|
|
52
53
|
currencies,
|
|
53
54
|
selectedCurrency: currencies[1],
|
|
55
|
+
searchPlaceholder: 'Type a currency / country',
|
|
54
56
|
amount: 1000,
|
|
55
57
|
onAmountChange: jest.fn(),
|
|
56
58
|
onCurrencyChange: jest.fn(),
|
|
@@ -90,4 +92,49 @@ describe('MoneyInput', () => {
|
|
|
90
92
|
);
|
|
91
93
|
expect(screen.getAllByRole('group')[0]).toHaveAccessibleName(/^Recipient gets/);
|
|
92
94
|
});
|
|
95
|
+
|
|
96
|
+
describe('ids', () => {
|
|
97
|
+
it('should guarantee id and connect the input with the selected currency via withId HoC', () => {
|
|
98
|
+
render(<MoneyInput {...props} />);
|
|
99
|
+
const input = screen.getByRole('textbox');
|
|
100
|
+
const button = screen.getByRole('combobox');
|
|
101
|
+
expect(input.getAttribute('id')).toBeTruthy();
|
|
102
|
+
expect(input).toHaveAttribute('aria-describedby', button.getAttribute('id'));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should have unique id for the select filter with predefined id', async () => {
|
|
106
|
+
const fieldId = 'myFieldId';
|
|
107
|
+
render(
|
|
108
|
+
<Field label="Multiple currencies" id={fieldId}>
|
|
109
|
+
<MoneyInput {...props} />
|
|
110
|
+
</Field>,
|
|
111
|
+
);
|
|
112
|
+
await userEvent.click(screen.getByRole('combobox'));
|
|
113
|
+
expect(screen.getByLabelText(props.searchPlaceholder)).toHaveAttribute(
|
|
114
|
+
'id',
|
|
115
|
+
`${fieldId}SelectedCurrencySearch`,
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should have unique id for the select filter without predefined id', async () => {
|
|
120
|
+
render(
|
|
121
|
+
<Field label="Multiple currencies">
|
|
122
|
+
<MoneyInput {...props} />
|
|
123
|
+
</Field>,
|
|
124
|
+
);
|
|
125
|
+
await userEvent.click(screen.getByRole('combobox'));
|
|
126
|
+
expect(screen.getByLabelText(props.searchPlaceholder)).toHaveAttribute(
|
|
127
|
+
'id',
|
|
128
|
+
expect.stringMatching(/^:.*?:SelectedCurrencySearch$/),
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should have AT label for the currency dropdown', () => {
|
|
134
|
+
render(<MoneyInput {...props} />);
|
|
135
|
+
expect(screen.getByRole('combobox')).toHaveAttribute(
|
|
136
|
+
'aria-label',
|
|
137
|
+
messages.selectCurrencyLabel.defaultMessage,
|
|
138
|
+
);
|
|
139
|
+
});
|
|
93
140
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { shallow } from 'enzyme';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
3
2
|
|
|
4
3
|
import { MoneyInput, Title, Input, SelectInput } from '..';
|
|
5
4
|
import { mockMatchMedia, mockResizeObserver } from '../test-utils';
|
|
@@ -818,14 +817,4 @@ describe('Money Input', () => {
|
|
|
818
817
|
});
|
|
819
818
|
});
|
|
820
819
|
});
|
|
821
|
-
|
|
822
|
-
describe('withId', () => {
|
|
823
|
-
it('should guarantee id and connect the input with the selected currency', () => {
|
|
824
|
-
render(<MoneyInput {...props} />);
|
|
825
|
-
const input = screen.getByRole('textbox');
|
|
826
|
-
const button = screen.getByRole('combobox');
|
|
827
|
-
expect(input.getAttribute('id')).toBeTruthy();
|
|
828
|
-
expect(input).toHaveAttribute('aria-describedby', button.getAttribute('id'));
|
|
829
|
-
});
|
|
830
|
-
});
|
|
831
820
|
});
|
|
@@ -9,13 +9,13 @@ import { Field } from '../field/Field';
|
|
|
9
9
|
export default {
|
|
10
10
|
component: MoneyInput,
|
|
11
11
|
title: 'Forms/MoneyInput',
|
|
12
|
-
render: function Render(args) {
|
|
12
|
+
render: function Render({ id, ...args }) {
|
|
13
13
|
const [selectedCurrency, setSelectedCurrency] = useState(args.selectedCurrency);
|
|
14
14
|
|
|
15
15
|
const handleOnCurrencyChange = (value: CurrencyOptionItem) => setSelectedCurrency(value);
|
|
16
16
|
|
|
17
17
|
return (
|
|
18
|
-
<Field label="Editable money input label" required>
|
|
18
|
+
<Field label="Editable money input label" required id={id}>
|
|
19
19
|
<MoneyInput
|
|
20
20
|
{...args}
|
|
21
21
|
selectedCurrency={selectedCurrency}
|
|
@@ -129,6 +129,7 @@ export const MultipleCurrencies: Story = {
|
|
|
129
129
|
},
|
|
130
130
|
selectedCurrency: exampleCurrency.usd,
|
|
131
131
|
searchPlaceholder: 'Type a currency / country',
|
|
132
|
+
id: 'moneyInput',
|
|
132
133
|
},
|
|
133
134
|
};
|
|
134
135
|
|
|
@@ -155,20 +156,22 @@ export const OpenedInput: Story = {
|
|
|
155
156
|
};
|
|
156
157
|
|
|
157
158
|
export const SmallInput: Story = {
|
|
158
|
-
render: (args) => {
|
|
159
|
+
render: ({ id, ...args }) => {
|
|
159
160
|
return (
|
|
160
161
|
<>
|
|
161
|
-
<Field
|
|
162
|
+
<Field label="Money inputs" required>
|
|
162
163
|
<MoneyInput {...args} {...SingleCurrency.args} />
|
|
163
164
|
</Field>
|
|
164
165
|
<br />
|
|
165
|
-
<
|
|
166
|
+
<Field label="Multiple currencies">
|
|
167
|
+
<MoneyInput {...args} {...MultipleCurrencies.args} />
|
|
168
|
+
</Field>
|
|
166
169
|
<hr />
|
|
167
|
-
<Field
|
|
170
|
+
<Field label="Error state" sentiment="negative" required>
|
|
168
171
|
<MoneyInput {...args} {...SingleCurrency.args} />
|
|
169
172
|
</Field>
|
|
170
173
|
<br />
|
|
171
|
-
<Field sentiment="negative">
|
|
174
|
+
<Field label="Multiple currencies: error state" sentiment="negative">
|
|
172
175
|
<MoneyInput {...args} {...MultipleCurrencies.args} />
|
|
173
176
|
</Field>
|
|
174
177
|
</>
|
|
@@ -314,7 +314,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
|
|
|
314
314
|
|
|
315
315
|
const isFixedCurrency = (!this.state.searchQuery && hasSingleCurrency()) || !onCurrencyChange;
|
|
316
316
|
const disabled = !this.props.onAmountChange;
|
|
317
|
-
const selectedCurrencyElementId = `${amountInputId}SelectedCurrency`;
|
|
317
|
+
const selectedCurrencyElementId = `${inputAttributes?.id ?? amountInputId}SelectedCurrency`;
|
|
318
318
|
|
|
319
319
|
return (
|
|
320
320
|
<div
|
|
@@ -387,6 +387,13 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
|
|
|
387
387
|
)}
|
|
388
388
|
>
|
|
389
389
|
<SelectInput
|
|
390
|
+
UNSAFE_triggerButtonProps={{
|
|
391
|
+
id: undefined,
|
|
392
|
+
'aria-labelledby': undefined,
|
|
393
|
+
'aria-describedby': undefined,
|
|
394
|
+
'aria-invalid': undefined,
|
|
395
|
+
'aria-label': this.props.intl.formatMessage(messages.selectCurrencyLabel),
|
|
396
|
+
}}
|
|
390
397
|
id={selectedCurrencyElementId}
|
|
391
398
|
items={selectOptions}
|
|
392
399
|
value={selectedCurrency}
|
package/src/stepper/Stepper.css
CHANGED
|
@@ -70,35 +70,11 @@
|
|
|
70
70
|
padding: 0 ;
|
|
71
71
|
}
|
|
72
72
|
.progress-bar {
|
|
73
|
-
float: left;
|
|
74
73
|
-webkit-backface-visibility: hidden;
|
|
75
|
-
height: 100%;
|
|
76
74
|
background-color: var(--color-interactive-primary);
|
|
77
|
-
border-top-left-radius: 1px;
|
|
78
|
-
border-bottom-left-radius: 1px;
|
|
79
75
|
transition: width 0.6s ease-in-out;
|
|
80
76
|
will-change: width;
|
|
81
77
|
}
|
|
82
|
-
[dir="rtl"] .progress-bar {
|
|
83
|
-
float: right;
|
|
84
|
-
}
|
|
85
|
-
.progress-bar::after {
|
|
86
|
-
float: right;
|
|
87
|
-
width: 8px;
|
|
88
|
-
height: 8px;
|
|
89
|
-
margin-top: -3px;
|
|
90
|
-
margin-right: -4px;
|
|
91
|
-
content: "";
|
|
92
|
-
border-radius: 4px;
|
|
93
|
-
}
|
|
94
|
-
[dir="rtl"] .progress-bar::after {
|
|
95
|
-
float: left;
|
|
96
|
-
}
|
|
97
|
-
[dir="rtl"] .progress-bar::after {
|
|
98
|
-
margin-left: -4px;
|
|
99
|
-
margin-right: 0;
|
|
100
|
-
margin-right: initial;
|
|
101
|
-
}
|
|
102
78
|
.btn-unstyled {
|
|
103
79
|
background: none;
|
|
104
80
|
border: none;
|
package/src/stepper/Stepper.less
CHANGED
|
@@ -78,27 +78,10 @@
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
.progress-bar {
|
|
81
|
-
.float(left);
|
|
82
|
-
|
|
83
81
|
-webkit-backface-visibility: hidden;
|
|
84
|
-
height: 100%;
|
|
85
82
|
background-color: var(--color-interactive-primary);
|
|
86
|
-
border-top-left-radius: 1px;
|
|
87
|
-
border-bottom-left-radius: 1px;
|
|
88
83
|
transition: width 0.6s ease-in-out;
|
|
89
84
|
will-change: width;
|
|
90
|
-
|
|
91
|
-
&::after {
|
|
92
|
-
.float(right);
|
|
93
|
-
|
|
94
|
-
width: 8px;
|
|
95
|
-
height: 8px;
|
|
96
|
-
margin-top: -3px;
|
|
97
|
-
.margin(right, -4px);
|
|
98
|
-
|
|
99
|
-
content: "";
|
|
100
|
-
border-radius: 4px;
|
|
101
|
-
}
|
|
102
85
|
}
|
|
103
86
|
|
|
104
87
|
.btn-unstyled {
|
|
@@ -40,15 +40,21 @@ describe('Stepper', () => {
|
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
it('sets the widths of the progress bar to match where you are in the flow', () => {
|
|
43
|
-
expect(totalWidth()).toBe('
|
|
43
|
+
expect(totalWidth()).toBe('0px');
|
|
44
44
|
activeStep(2);
|
|
45
|
-
expect(totalWidth()).toBe(
|
|
45
|
+
expect(totalWidth()).toBe(
|
|
46
|
+
'calc(100% + var(--progress-bar-start-shift) + var(--progress-bar-border-width))',
|
|
47
|
+
);
|
|
46
48
|
steps(5);
|
|
47
|
-
expect(totalWidth()).toBe(
|
|
49
|
+
expect(totalWidth()).toBe(
|
|
50
|
+
'calc(50% + var(--progress-bar-start-shift) + var(--progress-bar-border-width))',
|
|
51
|
+
);
|
|
48
52
|
activeStep(10000);
|
|
49
|
-
expect(totalWidth()).toBe(
|
|
53
|
+
expect(totalWidth()).toBe(
|
|
54
|
+
'calc(100% + var(--progress-bar-start-shift) + var(--progress-bar-border-width))',
|
|
55
|
+
);
|
|
50
56
|
activeStep(-10);
|
|
51
|
-
expect(totalWidth()).toBe('
|
|
57
|
+
expect(totalWidth()).toBe('0px');
|
|
52
58
|
});
|
|
53
59
|
});
|
|
54
60
|
|
package/src/stepper/Stepper.tsx
CHANGED
|
@@ -38,6 +38,18 @@ const Stepper = ({ steps, activeStep = 0, className }: StepperProps) => {
|
|
|
38
38
|
const stepPercentage = 1 / (steps.length - 1);
|
|
39
39
|
const percentageCompleted = activeStepIndex / (steps.length - 1);
|
|
40
40
|
|
|
41
|
+
const getProgressWidth = (): string => {
|
|
42
|
+
if (percentageCompleted === 0) {
|
|
43
|
+
return '0px';
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Progress bar starts with left/right (depends on rtl) shift `--progress-bar-start-shift` for hiding Progress bar's left and right borders
|
|
47
|
+
* which are used for progress vertical delimiter.
|
|
48
|
+
* When progress is completed, we need to add `--progress-bar-border-width` to the width to allow the right border be outside of the progress area.
|
|
49
|
+
*/
|
|
50
|
+
return `calc(${percentageCompleted * 100}% + var(--progress-bar-start-shift) + var(--progress-bar-border-width))`;
|
|
51
|
+
};
|
|
52
|
+
|
|
41
53
|
const renderStep = (step: Step, index: number) => {
|
|
42
54
|
const active = index === activeStepIndex;
|
|
43
55
|
const clickable = step.onClick && !active;
|
|
@@ -85,9 +97,8 @@ const Stepper = ({ steps, activeStep = 0, className }: StepperProps) => {
|
|
|
85
97
|
return (
|
|
86
98
|
<div className={clsx('tw-stepper', className)}>
|
|
87
99
|
<div className="progress">
|
|
88
|
-
<div className="progress-bar" style={{ width:
|
|
100
|
+
<div className="progress-bar" style={{ width: getProgressWidth() }} />
|
|
89
101
|
</div>
|
|
90
|
-
|
|
91
102
|
<ol className="tw-stepper-steps p-t-1 m-b-0">{steps.map(renderStep)}</ol>
|
|
92
103
|
</div>
|
|
93
104
|
);
|