@transferwise/components 46.17.2 → 46.18.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/index.esm.js +28 -20
- package/build/index.esm.js.map +1 -1
- package/build/index.js +27 -19
- package/build/index.js.map +1 -1
- package/build/main.css +4 -0
- package/build/styles/instructionsList/InstructionsList.css +4 -0
- package/build/styles/main.css +4 -0
- package/build/types/accordion/Accordion.d.ts +3 -7
- package/build/types/accordion/Accordion.d.ts.map +1 -1
- package/build/types/accordion/index.d.ts +1 -0
- package/build/types/accordion/index.d.ts.map +1 -1
- package/build/types/body/Body.d.ts +1 -1
- package/build/types/chips/Chips.d.ts +2 -2
- package/build/types/chips/Chips.d.ts.map +1 -1
- package/build/types/dateLookup/DateLookup.d.ts +1 -0
- package/build/types/dateLookup/DateLookup.d.ts.map +1 -1
- package/build/types/dateLookup/getFocusableTime/getFocusableTime.d.ts +1 -1
- package/build/types/dateLookup/getFocusableTime/getFocusableTime.d.ts.map +1 -1
- package/build/types/decision/Decision.d.ts +1 -1
- package/build/types/decision/Decision.d.ts.map +1 -1
- package/build/types/flowNavigation/FlowNavigation.d.ts +1 -1
- package/build/types/flowNavigation/FlowNavigation.d.ts.map +1 -1
- package/build/types/flowNavigation/animatedLabel/AnimatedLabel.d.ts +1 -1
- package/build/types/flowNavigation/animatedLabel/AnimatedLabel.d.ts.map +1 -1
- package/build/types/index.d.ts +2 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instructionsList/InstructionsList.d.ts +4 -4
- package/build/types/instructionsList/InstructionsList.d.ts.map +1 -1
- package/build/types/markdown/Markdown.d.ts +2 -2
- package/build/types/markdown/Markdown.d.ts.map +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts.map +1 -1
- package/build/types/radioGroup/RadioGroup.d.ts +2 -1
- package/build/types/radioGroup/RadioGroup.d.ts.map +1 -1
- package/build/types/radioGroup/index.d.ts +1 -1
- package/build/types/radioGroup/index.d.ts.map +1 -1
- package/build/types/segmentedControl/SegmentedControl.d.ts +3 -3
- package/build/types/segmentedControl/SegmentedControl.d.ts.map +1 -1
- package/build/types/slidingPanel/SlidingPanel.d.ts.map +1 -1
- package/build/types/stepper/Stepper.d.ts +1 -1
- package/build/types/stepper/Stepper.d.ts.map +1 -1
- package/build/types/typeahead/Typeahead.d.ts +8 -6
- package/build/types/typeahead/Typeahead.d.ts.map +1 -1
- package/build/types/typeahead/typeaheadInput/TypeaheadInput.d.ts +1 -1
- package/build/types/typeahead/typeaheadInput/TypeaheadInput.d.ts.map +1 -1
- package/build/types/uploadInput/UploadInput.d.ts +1 -1
- package/build/types/uploadInput/UploadInput.d.ts.map +1 -1
- package/build/types/uploadInput/uploadButton/UploadButton.d.ts +1 -1
- package/build/types/uploadInput/uploadButton/UploadButton.d.ts.map +1 -1
- package/build/types/uploadInput/uploadButton/getAllowedFileTypes.d.ts +1 -1
- package/build/types/uploadInput/uploadButton/getAllowedFileTypes.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/accordion/Accordion.tsx +6 -7
- package/src/accordion/index.ts +1 -0
- package/src/chips/Chips.story.tsx +2 -2
- package/src/chips/Chips.tsx +2 -2
- package/src/dateLookup/DateLookup.js +2 -0
- package/src/dateLookup/DateLookup.story.js +3 -0
- package/src/dateLookup/DateLookup.view.spec.js +5 -0
- package/src/dateLookup/dateTrigger/DateTrigger.js +1 -1
- package/src/dateLookup/dateTrigger/DateTrigger.spec.js +11 -3
- package/src/dateLookup/getFocusableTime/getFocusableTime.tsx +1 -1
- package/src/decision/Decision.tsx +1 -1
- package/src/flowNavigation/FlowNavigation.tsx +1 -1
- package/src/flowNavigation/__snapshots__/FlowNavigation.spec.js.snap +6 -0
- package/src/flowNavigation/animatedLabel/AnimatedLabel.tsx +1 -1
- package/src/index.ts +2 -1
- package/src/instructionsList/InstructionsList.css +4 -0
- package/src/instructionsList/InstructionsList.less +5 -0
- package/src/instructionsList/InstructionsList.tsx +7 -7
- package/src/main.css +4 -0
- package/src/markdown/Markdown.tsx +3 -3
- package/src/moneyInput/MoneyInput.tsx +3 -3
- package/src/phoneNumberInput/PhoneNumberInput.tsx +1 -1
- package/src/phoneNumberInput/utils/excludeCountries/excludeCountries.ts +5 -2
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.ts +1 -1
- package/src/phoneNumberInput/utils/longestMatchingPrefix/index.ts +1 -1
- package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.ts +1 -1
- package/src/promoCard/PromoCardGroup.tsx +1 -1
- package/src/radioGroup/RadioGroup.tsx +6 -1
- package/src/radioGroup/index.ts +1 -1
- package/src/segmentedControl/SegmentedControl.tsx +3 -3
- package/src/slidingPanel/SlidingPanel.js +1 -0
- package/src/stepper/Stepper.spec.js +16 -0
- package/src/stepper/Stepper.tsx +2 -1
- package/src/typeahead/Typeahead.story.tsx +109 -0
- package/src/typeahead/Typeahead.tsx +18 -9
- package/src/typeahead/typeaheadInput/TypeaheadInput.tsx +1 -1
- package/src/uploadInput/UploadInput.tsx +6 -6
- package/src/uploadInput/uploadButton/UploadButton.tsx +5 -7
- package/src/uploadInput/uploadButton/getAllowedFileTypes.ts +1 -1
|
@@ -2,17 +2,16 @@ import { useState, FC } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import AccordionItem, { AccordionItemProps } from './AccordionItem';
|
|
4
4
|
|
|
5
|
+
export type AccordionItem = Pick<
|
|
6
|
+
AccordionItemProps,
|
|
7
|
+
'id' | 'title' | 'subtitle' | 'content' | 'icon'
|
|
8
|
+
>;
|
|
9
|
+
|
|
5
10
|
export interface AccordionProps {
|
|
6
11
|
/** The index of the item that should be open by default. */
|
|
7
12
|
indexOpen?: number;
|
|
8
13
|
/** An array of items to display in the accordion. */
|
|
9
|
-
items:
|
|
10
|
-
id?: string;
|
|
11
|
-
title: React.ReactNode;
|
|
12
|
-
subtitle?: React.ReactNode;
|
|
13
|
-
content: React.ReactNode;
|
|
14
|
-
icon?: React.ReactNode;
|
|
15
|
-
}[];
|
|
14
|
+
items: readonly AccordionItem[];
|
|
16
15
|
/** A callback function that is called when an item is clicked. */
|
|
17
16
|
onClick?: (index: number) => void;
|
|
18
17
|
/** @deprecated */
|
package/src/accordion/index.ts
CHANGED
|
@@ -11,8 +11,8 @@ const meta: Meta<typeof Chips> = {
|
|
|
11
11
|
export default meta;
|
|
12
12
|
|
|
13
13
|
const FilterTemplate: Story<ChipsProps> = (args: ChipsProps) => {
|
|
14
|
-
const [selected, setSelected] = useState<ChipValue[]>(
|
|
15
|
-
args.selected
|
|
14
|
+
const [selected, setSelected] = useState<readonly ChipValue[]>(
|
|
15
|
+
args.selected == null || Array.isArray(args.selected) ? args.selected : [args.selected],
|
|
16
16
|
);
|
|
17
17
|
return (
|
|
18
18
|
<Chips
|
package/src/chips/Chips.tsx
CHANGED
|
@@ -17,7 +17,7 @@ export type Chip = {
|
|
|
17
17
|
export type ChipsProps = CommonProps &
|
|
18
18
|
AriaLabelProperty & {
|
|
19
19
|
/** List of chips with string labels and string/number values */
|
|
20
|
-
chips: Chip[];
|
|
20
|
+
chips: readonly Chip[];
|
|
21
21
|
/** Callback which is invoked when a chip is selected or deselected */
|
|
22
22
|
onChange: ({
|
|
23
23
|
isEnabled,
|
|
@@ -27,7 +27,7 @@ export type ChipsProps = CommonProps &
|
|
|
27
27
|
selectedValue: ChipValue;
|
|
28
28
|
}) => void;
|
|
29
29
|
/** Used to manage which chips are selected */
|
|
30
|
-
selected: ChipValue | ChipValue[];
|
|
30
|
+
selected: ChipValue | readonly ChipValue[];
|
|
31
31
|
/** Used to activate multi-selection */
|
|
32
32
|
multiple?: boolean;
|
|
33
33
|
};
|
|
@@ -253,6 +253,7 @@ class DateLookup extends PureComponent {
|
|
|
253
253
|
return (
|
|
254
254
|
<div // eslint-disable-line jsx-a11y/no-static-element-interactions
|
|
255
255
|
ref={this.element}
|
|
256
|
+
id={this.props.id}
|
|
256
257
|
aria-labelledby={ariaLabelledBy}
|
|
257
258
|
className="input-group"
|
|
258
259
|
onKeyDown={this.handleKeyDown}
|
|
@@ -277,6 +278,7 @@ class DateLookup extends PureComponent {
|
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
DateLookup.propTypes = {
|
|
281
|
+
id: PropTypes.string,
|
|
280
282
|
value: PropTypes.instanceOf(Date),
|
|
281
283
|
min: PropTypes.instanceOf(Date),
|
|
282
284
|
max: PropTypes.instanceOf(Date),
|
|
@@ -25,12 +25,14 @@ export const Basic = () => {
|
|
|
25
25
|
const monthFormat = select('monthFormat', ['long', 'short']);
|
|
26
26
|
const placeholder = text('placeholder', 'placeholder');
|
|
27
27
|
const size = select('size', Object.values(Size), Size.MEDIUM);
|
|
28
|
+
const id = text('id', 'date-lookup');
|
|
28
29
|
|
|
29
30
|
const clearable = boolean('clearable', false);
|
|
30
31
|
|
|
31
32
|
return (
|
|
32
33
|
<DateLookup
|
|
33
34
|
disabled={disabled}
|
|
35
|
+
id={id}
|
|
34
36
|
label={label}
|
|
35
37
|
min={thePast}
|
|
36
38
|
monthFormat={monthFormat}
|
|
@@ -81,6 +83,7 @@ export const RightAligned = () => {
|
|
|
81
83
|
</div>
|
|
82
84
|
<div className="col-xs-6">
|
|
83
85
|
<DateLookup
|
|
86
|
+
id="right-aligned"
|
|
84
87
|
disabled={disabled}
|
|
85
88
|
label={label}
|
|
86
89
|
min={new Date(minvalue)}
|
|
@@ -37,6 +37,7 @@ describe('DateLookup view', () => {
|
|
|
37
37
|
placeholder: 'Asd..',
|
|
38
38
|
label: 'Date..',
|
|
39
39
|
onChange: jest.fn(),
|
|
40
|
+
id: '123456',
|
|
40
41
|
};
|
|
41
42
|
component = shallow(<DateLookup {...props} />);
|
|
42
43
|
});
|
|
@@ -45,6 +46,10 @@ describe('DateLookup view', () => {
|
|
|
45
46
|
expect(dateTrigger()).toHaveLength(1);
|
|
46
47
|
});
|
|
47
48
|
|
|
49
|
+
it('passes id to the component', () => {
|
|
50
|
+
expect(component.prop('id')).toBe('123456');
|
|
51
|
+
});
|
|
52
|
+
|
|
48
53
|
it('passes props forward to open button', () => {
|
|
49
54
|
expect(+dateTrigger().prop('selectedDate')).toBe(+date);
|
|
50
55
|
expect(dateTrigger().prop('size')).toBe('lg');
|
|
@@ -62,7 +62,7 @@ const DateTrigger = ({
|
|
|
62
62
|
<span className="input-group-addon">
|
|
63
63
|
<CloseButton
|
|
64
64
|
className={`clear-btn clear-btn--${size}`}
|
|
65
|
-
aria-label={formatMessage(messages.ariaLabel)}
|
|
65
|
+
aria-label={`${formatMessage(messages.ariaLabel)} ${label}`}
|
|
66
66
|
size={Size.SMALL}
|
|
67
67
|
onClick={(event) => {
|
|
68
68
|
event.stopPropagation();
|
|
@@ -6,10 +6,12 @@ import { fakeKeyDownEventForKey } from '../../common/fakeEvents';
|
|
|
6
6
|
|
|
7
7
|
import DateTrigger from '.';
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const locale = 'en-GB';
|
|
10
|
+
const formatMessage = (message) => message.id;
|
|
11
|
+
|
|
10
12
|
jest.mock('react-intl', () => ({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
...jest.requireActual('react-intl'),
|
|
14
|
+
useIntl: jest.fn(() => ({ locale, formatMessage })),
|
|
13
15
|
}));
|
|
14
16
|
|
|
15
17
|
jest.mock('@transferwise/formatting', () => ({
|
|
@@ -73,6 +75,12 @@ describe('DateTrigger', () => {
|
|
|
73
75
|
expect(label().text()).toBe('hello');
|
|
74
76
|
});
|
|
75
77
|
|
|
78
|
+
it('adds label to clear button aria-label', () => {
|
|
79
|
+
const onClear = jest.fn();
|
|
80
|
+
component.setProps({ label: 'hello', onClear });
|
|
81
|
+
expect(clearButton().prop('aria-label')).toBe('neptune.ClearButton.ariaLabel hello');
|
|
82
|
+
});
|
|
83
|
+
|
|
76
84
|
it('calls on click handler on button click', () => {
|
|
77
85
|
button().simulate('click');
|
|
78
86
|
expect(props.onClick).toHaveBeenCalledTimes(1);
|
|
@@ -2,7 +2,7 @@ interface FocusableTimeProps {
|
|
|
2
2
|
isActive: (time: number) => boolean;
|
|
3
3
|
isNow: (time: number) => boolean;
|
|
4
4
|
isDisabled: (time: number) => boolean;
|
|
5
|
-
timeSpan: number[];
|
|
5
|
+
timeSpan: readonly number[];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function getFocusableTime(props: FocusableTimeProps): number | undefined {
|
|
@@ -30,7 +30,7 @@ export enum DecisionType {
|
|
|
30
30
|
|
|
31
31
|
export interface DecisionProps {
|
|
32
32
|
/** A list of elements to be rendered */
|
|
33
|
-
options: DecisionOption[];
|
|
33
|
+
options: readonly DecisionOption[];
|
|
34
34
|
/** Handles the display mode of the component */
|
|
35
35
|
presentation?: `${DecisionPresentation}`;
|
|
36
36
|
/** Size currently affects only Tile dimension */
|
|
@@ -24,7 +24,7 @@ export interface FlowNavigationProps {
|
|
|
24
24
|
/** Called when the back button is clicked. If not provided the back button won't show. The back button only shows on small screens */
|
|
25
25
|
onGoBack?: () => void;
|
|
26
26
|
/** Steps to be displayed in stepper. If you don't need the stepper, please use OverlayHeader instead */
|
|
27
|
-
steps: Step[];
|
|
27
|
+
steps: readonly Step[];
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const FlowNavigation = ({
|
|
@@ -75,6 +75,7 @@ exports[`FlowNavigation on mobile renders as expected 1`] = `
|
|
|
75
75
|
class="tw-stepper-steps p-t-1 m-b-0"
|
|
76
76
|
>
|
|
77
77
|
<li
|
|
78
|
+
aria-current="false"
|
|
78
79
|
class="hidden-xs tw-stepper__step np-text-body-default"
|
|
79
80
|
style="left: 0%;"
|
|
80
81
|
>
|
|
@@ -85,6 +86,7 @@ exports[`FlowNavigation on mobile renders as expected 1`] = `
|
|
|
85
86
|
</span>
|
|
86
87
|
</li>
|
|
87
88
|
<li
|
|
89
|
+
aria-current="step"
|
|
88
90
|
class="hidden-xs tw-stepper__step np-text-body-default-bold tw-stepper__step--active"
|
|
89
91
|
style="left: 50%;"
|
|
90
92
|
>
|
|
@@ -95,6 +97,7 @@ exports[`FlowNavigation on mobile renders as expected 1`] = `
|
|
|
95
97
|
</span>
|
|
96
98
|
</li>
|
|
97
99
|
<li
|
|
100
|
+
aria-current="false"
|
|
98
101
|
class="hidden-xs tw-stepper__step np-text-body-default"
|
|
99
102
|
style="left: 100%;"
|
|
100
103
|
>
|
|
@@ -188,6 +191,7 @@ exports[`FlowNavigation renders as expected 1`] = `
|
|
|
188
191
|
class="tw-stepper-steps p-t-1 m-b-0"
|
|
189
192
|
>
|
|
190
193
|
<li
|
|
194
|
+
aria-current="step"
|
|
191
195
|
class="hidden-xs tw-stepper__step np-text-body-default-bold tw-stepper__step--active"
|
|
192
196
|
style="left: 0%;"
|
|
193
197
|
>
|
|
@@ -198,6 +202,7 @@ exports[`FlowNavigation renders as expected 1`] = `
|
|
|
198
202
|
</span>
|
|
199
203
|
</li>
|
|
200
204
|
<li
|
|
205
|
+
aria-current="false"
|
|
201
206
|
class="hidden-xs tw-stepper__step np-text-body-default"
|
|
202
207
|
style="left: 50%;"
|
|
203
208
|
>
|
|
@@ -208,6 +213,7 @@ exports[`FlowNavigation renders as expected 1`] = `
|
|
|
208
213
|
</span>
|
|
209
214
|
</li>
|
|
210
215
|
<li
|
|
216
|
+
aria-current="false"
|
|
211
217
|
class="hidden-xs tw-stepper__step np-text-body-default"
|
|
212
218
|
style="left: 100%;"
|
|
213
219
|
>
|
|
@@ -7,7 +7,7 @@ import { Typography } from '../../common';
|
|
|
7
7
|
export interface AnimatedLabelProps {
|
|
8
8
|
activeLabel: number;
|
|
9
9
|
className?: string;
|
|
10
|
-
labels: React.ReactNode[];
|
|
10
|
+
labels: readonly React.ReactNode[];
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const AnimatedLabel = ({ activeLabel, className, labels }: AnimatedLabelProps) => {
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Types
|
|
3
3
|
*/
|
|
4
|
+
export type { AccordionProps, AccordionItem } from './accordion';
|
|
4
5
|
export type { DecisionProps } from './decision/Decision';
|
|
5
6
|
export type { InfoProps } from './info';
|
|
6
7
|
export type { SummaryProps } from './summary';
|
|
@@ -21,7 +22,7 @@ export type {
|
|
|
21
22
|
export type { TextAreaProps } from './inputs/TextArea';
|
|
22
23
|
export type { PhoneNumberInputProps } from './phoneNumberInput/PhoneNumberInput';
|
|
23
24
|
export type { RadioProps } from './radio';
|
|
24
|
-
export type { RadioGroupProps } from './radioGroup';
|
|
25
|
+
export type { RadioGroupProps, RadioGroupRadio } from './radioGroup';
|
|
25
26
|
export type { RadioOptionProps } from './radioOption';
|
|
26
27
|
export type { SnackbarProps } from './snackbar/Snackbar';
|
|
27
28
|
export type { SnackbarContextType } from './snackbar/SnackbarContext';
|
|
@@ -12,13 +12,13 @@ type InstructionNode = {
|
|
|
12
12
|
export type InstructionsListProps = CommonProps &
|
|
13
13
|
(
|
|
14
14
|
| {
|
|
15
|
-
dos?: ReactNode[];
|
|
16
|
-
donts?: ReactNode[];
|
|
15
|
+
dos?: readonly ReactNode[];
|
|
16
|
+
donts?: readonly ReactNode[];
|
|
17
17
|
sort?: 'dosFirst' | 'dontsFirst';
|
|
18
18
|
}
|
|
19
19
|
| {
|
|
20
|
-
dos?: InstructionNode[];
|
|
21
|
-
donts?: InstructionNode[];
|
|
20
|
+
dos?: readonly InstructionNode[];
|
|
21
|
+
donts?: readonly InstructionNode[];
|
|
22
22
|
sort?: 'dosFirst' | 'dontsFirst';
|
|
23
23
|
}
|
|
24
24
|
);
|
|
@@ -49,14 +49,14 @@ const InstructionsList = ({ dos, donts, sort = 'dosFirst' }: InstructionsListPro
|
|
|
49
49
|
</>
|
|
50
50
|
);
|
|
51
51
|
|
|
52
|
-
return <
|
|
52
|
+
return <ul className="tw-instructions">{orderedInstructions}</ul>;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
function Instruction({ item, type }: { item: ReactNode | InstructionNode; type: 'do' | 'dont' }) {
|
|
56
56
|
const isInstructionNode =
|
|
57
57
|
typeof item === 'object' && item !== null && 'content' in item && 'aria-label' in item;
|
|
58
58
|
return (
|
|
59
|
-
<
|
|
59
|
+
<li
|
|
60
60
|
className="instruction"
|
|
61
61
|
aria-label={isInstructionNode ? (item['aria-label'] as string) : undefined}
|
|
62
62
|
>
|
|
@@ -68,7 +68,7 @@ function Instruction({ item, type }: { item: ReactNode | InstructionNode; type:
|
|
|
68
68
|
<Body className="text-primary" type={Typography.BODY_LARGE}>
|
|
69
69
|
{isInstructionNode ? item.content : item}
|
|
70
70
|
</Body>
|
|
71
|
-
</
|
|
71
|
+
</li>
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
74
|
|
package/src/main.css
CHANGED
|
@@ -2665,6 +2665,10 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
2665
2665
|
color: var(--color-content-tertiary);
|
|
2666
2666
|
}
|
|
2667
2667
|
.tw-instructions {
|
|
2668
|
+
/* Reset */
|
|
2669
|
+
margin: 0;
|
|
2670
|
+
padding: 0;
|
|
2671
|
+
list-style: none;
|
|
2668
2672
|
display: flex;
|
|
2669
2673
|
flex-direction: column;
|
|
2670
2674
|
}
|
|
@@ -17,12 +17,12 @@ export type MarkdownProps = {
|
|
|
17
17
|
children?: string;
|
|
18
18
|
} & (
|
|
19
19
|
| {
|
|
20
|
-
allowList?: `${MarkdownNodeType}`[];
|
|
20
|
+
allowList?: readonly `${MarkdownNodeType}`[];
|
|
21
21
|
blockList?: never;
|
|
22
22
|
}
|
|
23
23
|
| {
|
|
24
24
|
allowList?: never;
|
|
25
|
-
blockList?: `${MarkdownNodeType}`[];
|
|
25
|
+
blockList?: readonly `${MarkdownNodeType}`[];
|
|
26
26
|
}
|
|
27
27
|
);
|
|
28
28
|
|
|
@@ -61,7 +61,7 @@ export default function Markdown({
|
|
|
61
61
|
return <Element className={className} dangerouslySetInnerHTML={{ __html: createMarkup() }} />;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function stripNodes({ blockList, parsed }: { blockList: string[]; parsed: MarkdownNode }) {
|
|
64
|
+
function stripNodes({ blockList, parsed }: { blockList: readonly string[]; parsed: MarkdownNode }) {
|
|
65
65
|
if (!parsed) {
|
|
66
66
|
return parsed;
|
|
67
67
|
}
|
|
@@ -462,7 +462,7 @@ function filterCurrenciesForQuery(
|
|
|
462
462
|
return sortOptionsLabelsToFirst(filteredOptions, query);
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
-
function removeDuplicateValueOptions(options: CurrencyOptionItem[]) {
|
|
465
|
+
function removeDuplicateValueOptions(options: readonly CurrencyOptionItem[]) {
|
|
466
466
|
const uniqueValues = new Set<string>();
|
|
467
467
|
return options.filter((option) => {
|
|
468
468
|
if (!uniqueValues.has(option.value)) {
|
|
@@ -489,8 +489,8 @@ function contains(property: string | undefined, query: string) {
|
|
|
489
489
|
return property && property.toLowerCase().includes(query.toLowerCase());
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
-
function sortOptionsLabelsToFirst(options: CurrencyOptionItem[], query: string) {
|
|
493
|
-
return options.sort((first, second) => {
|
|
492
|
+
function sortOptionsLabelsToFirst(options: readonly CurrencyOptionItem[], query: string) {
|
|
493
|
+
return [...options].sort((first, second) => {
|
|
494
494
|
const firstContains = contains(first.label, query);
|
|
495
495
|
const secondContains = contains(second.label, query);
|
|
496
496
|
|
|
@@ -34,7 +34,7 @@ export interface PhoneNumberInputProps {
|
|
|
34
34
|
placeholder?: string;
|
|
35
35
|
selectProps?: Partial<SelectInputProps<string | null>>;
|
|
36
36
|
/** List of iso3 codes of countries to remove from the list */
|
|
37
|
-
disabledCountries?: string[];
|
|
37
|
+
disabledCountries?: readonly string[];
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const defaultSelectProps = {} satisfies PhoneNumberInputProps['selectProps'];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Country } from '../../data/countries';
|
|
2
2
|
|
|
3
3
|
// Reference fro localeCompare : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
|
|
4
|
-
const filterCountriesByIso3 = (countries: Country[], iso3Codes: string[]) => {
|
|
4
|
+
const filterCountriesByIso3 = (countries: readonly Country[], iso3Codes: readonly string[]) => {
|
|
5
5
|
const iso3CodesSet = new Set(iso3Codes);
|
|
6
6
|
return countries.filter((country) => !iso3CodesSet.has(country.iso3));
|
|
7
7
|
};
|
|
@@ -12,7 +12,10 @@ const filterCountriesByIso3 = (countries: Country[], iso3Codes: string[]) => {
|
|
|
12
12
|
* @param countries list of country metadata objects
|
|
13
13
|
* @param disabledCountries list of iso3 country codes to remove from the list
|
|
14
14
|
*/
|
|
15
|
-
export const excludeCountries = (
|
|
15
|
+
export const excludeCountries = (
|
|
16
|
+
countries: readonly Country[],
|
|
17
|
+
disabledCountries: readonly string[],
|
|
18
|
+
) => {
|
|
16
19
|
return disabledCountries.length > 0
|
|
17
20
|
? filterCountriesByIso3(countries, disabledCountries)
|
|
18
21
|
: countries;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Country } from '../../data/countries';
|
|
2
2
|
|
|
3
|
-
export const groupCountriesByPrefix = (countries: Country[]) => {
|
|
3
|
+
export const groupCountriesByPrefix = (countries: readonly Country[]) => {
|
|
4
4
|
const countriesByPrefix = new Map<string, Country[]>();
|
|
5
5
|
countries.forEach((country) => {
|
|
6
6
|
countriesByPrefix.set(country.phone, [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Country } from '../../data/countries';
|
|
2
2
|
|
|
3
|
-
export const longestMatchingPrefix = (matchingCodes: Country[]) =>
|
|
3
|
+
export const longestMatchingPrefix = (matchingCodes: readonly Country[]) =>
|
|
4
4
|
matchingCodes.reduce((a, b) => (a.phone.length > b.phone.length ? a : b));
|
|
@@ -106,7 +106,7 @@ const PromoCardGroup: FunctionComponent<PromoCardGroupProps> = ({
|
|
|
106
106
|
setState(defaultChecked);
|
|
107
107
|
|
|
108
108
|
// Collect an array of types from the children PromoCard components
|
|
109
|
-
const types
|
|
109
|
+
const types =
|
|
110
110
|
React.Children.map(children, (child) => {
|
|
111
111
|
if (React.isValidElement<PromoCardProps>(child) && child.props.type) {
|
|
112
112
|
return child.props.type;
|
|
@@ -3,9 +3,14 @@ import { useState } from 'react';
|
|
|
3
3
|
import Radio from '../radio';
|
|
4
4
|
import { RadioProps } from '../radio/Radio';
|
|
5
5
|
|
|
6
|
+
export type RadioGroupRadio<T extends string | number = string> = Omit<
|
|
7
|
+
RadioProps<T>,
|
|
8
|
+
'name' | 'checked' | 'onChange' | 'className'
|
|
9
|
+
>;
|
|
10
|
+
|
|
6
11
|
export interface RadioGroupProps<T extends string | number = string> {
|
|
7
12
|
name: string;
|
|
8
|
-
radios:
|
|
13
|
+
radios: readonly RadioGroupRadio<T>[];
|
|
9
14
|
selectedValue?: T; // TODO: `NoInfer<T>` from TypeScript 5.4
|
|
10
15
|
onChange: NonNullable<RadioProps<T>['onChange']>;
|
|
11
16
|
}
|
package/src/radioGroup/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default } from './RadioGroup';
|
|
2
|
-
export type { RadioGroupProps } from './RadioGroup';
|
|
2
|
+
export type { RadioGroupProps, RadioGroupRadio } from './RadioGroup';
|
|
@@ -9,7 +9,7 @@ type SegmentBase = { id: string; label: string; value: string };
|
|
|
9
9
|
type Segment = SegmentBase & { controls?: never };
|
|
10
10
|
type SegmentWithControls = SegmentBase & { controls: string };
|
|
11
11
|
|
|
12
|
-
export type Segments = Segment[] | SegmentWithControls[];
|
|
12
|
+
export type Segments = readonly Segment[] | readonly SegmentWithControls[];
|
|
13
13
|
|
|
14
14
|
type SegmentedControlPropsBase = {
|
|
15
15
|
name: string;
|
|
@@ -20,12 +20,12 @@ type SegmentedControlPropsBase = {
|
|
|
20
20
|
|
|
21
21
|
type SegmentedControlViewProps = {
|
|
22
22
|
mode: 'view';
|
|
23
|
-
segments: SegmentWithControls[];
|
|
23
|
+
segments: readonly SegmentWithControls[];
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
type SegmentedControlInputProps = {
|
|
27
27
|
mode: 'input';
|
|
28
|
-
segments: Segment[];
|
|
28
|
+
segments: readonly Segment[];
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export type SegmentedControlProps = SegmentedControlPropsBase &
|
|
@@ -162,6 +162,22 @@ describe('Stepper', () => {
|
|
|
162
162
|
expect(step(1).clickable).toBe(true);
|
|
163
163
|
expect(step(2).clickable).toBe(true);
|
|
164
164
|
});
|
|
165
|
+
|
|
166
|
+
it('are aria-current=step when active', () => {
|
|
167
|
+
const stepCurrent = (index) =>
|
|
168
|
+
component.find('.tw-stepper__step').at(index).props()['aria-current'];
|
|
169
|
+
steps(4);
|
|
170
|
+
activeStep(1);
|
|
171
|
+
expect(stepCurrent(0)).toBe(false);
|
|
172
|
+
expect(stepCurrent(1)).toBe('step');
|
|
173
|
+
expect(stepCurrent(2)).toBe(false);
|
|
174
|
+
expect(stepCurrent(3)).toBe(false);
|
|
175
|
+
activeStep(2);
|
|
176
|
+
expect(stepCurrent(0)).toBe(false);
|
|
177
|
+
expect(stepCurrent(1)).toBe(false);
|
|
178
|
+
expect(stepCurrent(2)).toBe('step');
|
|
179
|
+
expect(stepCurrent(3)).toBe(false);
|
|
180
|
+
});
|
|
165
181
|
});
|
|
166
182
|
|
|
167
183
|
describe('hover labels', () => {
|
package/src/stepper/Stepper.tsx
CHANGED
|
@@ -18,7 +18,7 @@ export interface Step {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface StepperProps {
|
|
21
|
-
steps: Step[];
|
|
21
|
+
steps: readonly Step[];
|
|
22
22
|
activeStep?: number;
|
|
23
23
|
className?: string;
|
|
24
24
|
}
|
|
@@ -60,6 +60,7 @@ const Stepper = ({ steps, activeStep = 0, className }: StepperProps) => {
|
|
|
60
60
|
clickable && 'tw-stepper__step--clickable',
|
|
61
61
|
step.hoverLabel && 'tw-stepper__step--has-tooltip',
|
|
62
62
|
)}
|
|
63
|
+
aria-current={active ? 'step' : false}
|
|
63
64
|
style={
|
|
64
65
|
isRTL
|
|
65
66
|
? { right: `${index * stepPercentage * 100}%` }
|