@transferwise/components 46.162.1 → 46.163.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/Calendar/DateHeader/DateHeader.js +2 -6
- package/build/Calendar/DateHeader/DateHeader.js.map +1 -1
- package/build/Calendar/DateHeader/DateHeader.mjs +3 -7
- package/build/Calendar/DateHeader/DateHeader.mjs.map +1 -1
- package/build/Carousel/Carousel.js +2 -2
- package/build/Carousel/Carousel.js.map +1 -1
- package/build/Carousel/Carousel.mjs +3 -3
- package/build/Carousel/Carousel.mjs.map +1 -1
- package/build/Chips/Chip/Chip.js +11 -4
- package/build/Chips/Chip/Chip.js.map +1 -1
- package/build/Chips/Chip/Chip.mjs +11 -4
- package/build/Chips/Chip/Chip.mjs.map +1 -1
- package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.js +4 -3
- package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.js.map +1 -1
- package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.mjs +4 -3
- package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.mjs.map +1 -1
- package/build/ListItem/Navigation/ListItemNavigation.js +1 -1
- package/build/ListItem/Navigation/ListItemNavigation.js.map +1 -1
- package/build/ListItem/Navigation/ListItemNavigation.mjs +2 -2
- package/build/ListItem/Navigation/ListItemNavigation.mjs.map +1 -1
- package/build/PhoneNumberInput/PhoneNumberInput.js +2 -1
- package/build/PhoneNumberInput/PhoneNumberInput.js.map +1 -1
- package/build/PhoneNumberInput/PhoneNumberInput.mjs +2 -1
- package/build/PhoneNumberInput/PhoneNumberInput.mjs.map +1 -1
- package/build/PromoCard/Indicator/PromoCardIndicator.js +1 -1
- package/build/PromoCard/Indicator/PromoCardIndicator.js.map +1 -1
- package/build/PromoCard/Indicator/PromoCardIndicator.mjs +2 -2
- package/build/PromoCard/Indicator/PromoCardIndicator.mjs.map +1 -1
- package/build/Typeahead/Typeahead.js +17 -4
- package/build/Typeahead/Typeahead.js.map +1 -1
- package/build/Typeahead/Typeahead.mjs +17 -4
- package/build/Typeahead/Typeahead.mjs.map +1 -1
- package/build/Typeahead/TypeaheadInput/TypeaheadInput.js +2 -0
- package/build/Typeahead/TypeaheadInput/TypeaheadInput.js.map +1 -1
- package/build/Typeahead/TypeaheadInput/TypeaheadInput.mjs +2 -0
- package/build/Typeahead/TypeaheadInput/TypeaheadInput.mjs.map +1 -1
- package/build/i18n/es.json +1 -0
- package/build/i18n/es.json.js +1 -0
- package/build/i18n/es.json.js.map +1 -1
- package/build/i18n/es.json.mjs +1 -0
- package/build/i18n/es.json.mjs.map +1 -1
- package/build/i18n/hu.json +1 -0
- package/build/i18n/hu.json.js +1 -0
- package/build/i18n/hu.json.js.map +1 -1
- package/build/i18n/hu.json.mjs +1 -0
- package/build/i18n/hu.json.mjs.map +1 -1
- package/build/i18n/id.json +1 -0
- package/build/i18n/id.json.js +1 -0
- package/build/i18n/id.json.js.map +1 -1
- package/build/i18n/id.json.mjs +1 -0
- package/build/i18n/id.json.mjs.map +1 -1
- package/build/i18n/it.json +1 -0
- package/build/i18n/it.json.js +1 -0
- package/build/i18n/it.json.js.map +1 -1
- package/build/i18n/it.json.mjs +1 -0
- package/build/i18n/it.json.mjs.map +1 -1
- package/build/i18n/ja.json +1 -0
- package/build/i18n/ja.json.js +1 -0
- package/build/i18n/ja.json.js.map +1 -1
- package/build/i18n/ja.json.mjs +1 -0
- package/build/i18n/ja.json.mjs.map +1 -1
- package/build/i18n/nl.json +1 -0
- package/build/i18n/nl.json.js +1 -0
- package/build/i18n/nl.json.js.map +1 -1
- package/build/i18n/nl.json.mjs +1 -0
- package/build/i18n/nl.json.mjs.map +1 -1
- package/build/i18n/pl.json +1 -0
- package/build/i18n/pl.json.js +1 -0
- package/build/i18n/pl.json.js.map +1 -1
- package/build/i18n/pl.json.mjs +1 -0
- package/build/i18n/pl.json.mjs.map +1 -1
- package/build/i18n/ro.json +1 -0
- package/build/i18n/ro.json.js +1 -0
- package/build/i18n/ro.json.js.map +1 -1
- package/build/i18n/ro.json.mjs +1 -0
- package/build/i18n/ro.json.mjs.map +1 -1
- package/build/i18n/uk.json +1 -0
- package/build/i18n/uk.json.js +1 -0
- package/build/i18n/uk.json.js.map +1 -1
- package/build/i18n/uk.json.mjs +1 -0
- package/build/i18n/uk.json.mjs.map +1 -1
- package/build/i18n/zh-HK.json +1 -0
- package/build/i18n/zh-HK.json.js +1 -0
- package/build/i18n/zh-HK.json.js.map +1 -1
- package/build/i18n/zh-HK.json.mjs +1 -0
- package/build/i18n/zh-HK.json.mjs.map +1 -1
- package/build/main.css +20 -7
- package/build/styles/Button/Button.css +0 -3
- package/build/styles/DateInput/DateInput.css +13 -0
- package/build/styles/ListItem/ListItem.css +1 -1
- package/build/styles/PhoneNumberInput/PhoneNumberInput.css +3 -0
- package/build/styles/PromoCard/PromoCard.css +0 -3
- package/build/styles/Typeahead/Typeahead.css +3 -0
- package/build/styles/main.css +20 -7
- package/build/types/Body/Body.d.ts +2 -2
- package/build/types/Chips/Chip/Chip.d.ts +3 -1
- package/build/types/Chips/Chip/Chip.d.ts.map +1 -1
- package/build/types/IconButton/IconButton.d.ts +1 -1
- package/build/types/Inputs/SelectInput/OptionContent/SelectInputOptionContent.d.ts +2 -1
- package/build/types/Inputs/SelectInput/OptionContent/SelectInputOptionContent.d.ts.map +1 -1
- package/build/types/MoneyInput/MoneyInput.d.ts +1 -1
- package/build/types/MoneyInput/MoneyInput.d.ts.map +1 -1
- package/build/types/PhoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/build/types/Title/Title.d.ts +2 -2
- package/build/types/Typeahead/Typeahead.d.ts +2 -0
- 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/Upload/Steps/UploadImageStep/UploadImageStep.d.ts +1 -1
- package/build/types/UploadInput/UploadItem/UploadItemLink.d.ts +1 -1
- package/package.json +5 -5
- package/src/Button/Button.css +0 -3
- package/src/Button/Button.less +0 -16
- package/src/Button/_stories/Button.test.story.tsx +12 -12
- package/src/Calendar/DateHeader/DateHeader.tsx +3 -3
- package/src/Carousel/Carousel.tsx +3 -3
- package/src/Chips/Chip/Chip.test.tsx +34 -0
- package/src/Chips/Chip/Chip.tsx +11 -3
- package/src/DateInput/DateInput.css +13 -0
- package/src/DateInput/DateInput.less +10 -2
- package/src/DateInput/_stories/DateInput.rtl.test.story.tsx +36 -0
- package/src/DateInput/_stories/DateInput.test.story.tsx +0 -13
- package/src/ExpressiveMoneyInput/_stories/ExpressiveMoneyInput.rtl.test.story.tsx +1 -1
- package/src/InputWithDisplayFormat/_stories/InputWithDisplayFormat.test.story.tsx +52 -0
- package/src/Inputs/SelectInput/OptionContent/SelectInputOptionContent.tsx +4 -1
- package/src/Inputs/SelectInput/SelectInput.test.tsx +74 -0
- package/src/ListItem/ListItem.css +1 -1
- package/src/ListItem/ListItem.grid.less +4 -4
- package/src/ListItem/ListItem.less +1 -1
- package/src/ListItem/Navigation/ListItemNavigation.tsx +2 -2
- package/src/PhoneNumberInput/PhoneNumberInput.css +3 -0
- package/src/PhoneNumberInput/PhoneNumberInput.less +10 -2
- package/src/PhoneNumberInput/PhoneNumberInput.tsx +1 -0
- package/src/PhoneNumberInput/_stories/PhoneNumberInput.rtl.test.story.tsx +1 -1
- package/src/PromoCard/Indicator/PromoCardIndicator.tsx +2 -2
- package/src/PromoCard/PromoCard.css +0 -3
- package/src/PromoCard/PromoCard.less +0 -5
- package/src/Prompt/CriticalBanner/_stories/CriticalBanner.test.story.tsx +1 -1
- package/src/Typeahead/Typeahead.css +3 -0
- package/src/Typeahead/Typeahead.less +4 -0
- package/src/Typeahead/Typeahead.test.tsx +73 -0
- package/src/Typeahead/Typeahead.tsx +18 -3
- package/src/Typeahead/TypeaheadInput/TypeaheadInput.tsx +6 -1
- package/src/Typeahead/_stories/Typeahead.story.tsx +1 -0
- package/src/Typeahead/_stories/Typeahead.test.story.tsx +41 -0
- package/src/i18n/en.json +1 -0
- package/src/i18n/es.json +1 -0
- package/src/i18n/hu.json +1 -0
- package/src/i18n/id.json +1 -0
- package/src/i18n/it.json +1 -0
- package/src/i18n/ja.json +1 -0
- package/src/i18n/nl.json +1 -0
- package/src/i18n/pl.json +1 -0
- package/src/i18n/ro.json +1 -0
- package/src/i18n/uk.json +1 -0
- package/src/i18n/zh-HK.json +1 -0
- package/src/main.css +20 -7
|
@@ -7,6 +7,7 @@ export interface SelectInputOptionContentProps {
|
|
|
7
7
|
note?: string;
|
|
8
8
|
description?: string;
|
|
9
9
|
icon?: React.ReactNode;
|
|
10
|
+
className?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -19,6 +20,7 @@ export function SelectInputOptionContent({
|
|
|
19
20
|
note,
|
|
20
21
|
description,
|
|
21
22
|
icon,
|
|
23
|
+
className,
|
|
22
24
|
}: SelectInputOptionContentProps) {
|
|
23
25
|
const withinTrigger = useContext(SelectInputOptionContentWithinTriggerContext);
|
|
24
26
|
|
|
@@ -27,6 +29,7 @@ export function SelectInputOptionContent({
|
|
|
27
29
|
className={clsx(
|
|
28
30
|
'np-select-input-option-content-container',
|
|
29
31
|
(note || description) && 'np-text-body-large',
|
|
32
|
+
className,
|
|
30
33
|
)}
|
|
31
34
|
>
|
|
32
35
|
{icon ? (
|
|
@@ -47,7 +50,7 @@ export function SelectInputOptionContent({
|
|
|
47
50
|
withinTrigger && 'np-select-input-option-content-text-within-trigger',
|
|
48
51
|
)}
|
|
49
52
|
>
|
|
50
|
-
<div className="d-inline">{title}</div>
|
|
53
|
+
<div className="d-inline np-select-input-option-content-title">{title}</div>
|
|
51
54
|
{note ? (
|
|
52
55
|
<span className="np-select-input-option-content-text-secondary np-text-body-default">
|
|
53
56
|
{note}
|
|
@@ -721,6 +721,80 @@ describe('SelectInput', () => {
|
|
|
721
721
|
expect(descriptionElement).toHaveClass('np-select-input-option-description-in-trigger');
|
|
722
722
|
});
|
|
723
723
|
|
|
724
|
+
it('applies custom className to option content container in the trigger', () => {
|
|
725
|
+
render(
|
|
726
|
+
<SelectInput
|
|
727
|
+
items={[
|
|
728
|
+
{ type: 'option', value: 'USD' },
|
|
729
|
+
{ type: 'option', value: 'EUR' },
|
|
730
|
+
]}
|
|
731
|
+
renderValue={(currency) => (
|
|
732
|
+
<SelectInputOptionContent title={currency} className="custom-option-class" />
|
|
733
|
+
)}
|
|
734
|
+
value="USD"
|
|
735
|
+
/>,
|
|
736
|
+
);
|
|
737
|
+
|
|
738
|
+
const triggerContent = screen
|
|
739
|
+
.getByText('USD')
|
|
740
|
+
.closest('.np-select-input-option-content-container');
|
|
741
|
+
expect(triggerContent).toHaveClass('custom-option-class');
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
it('applies custom className to option content container in dropdown options', async () => {
|
|
745
|
+
render(
|
|
746
|
+
<SelectInput
|
|
747
|
+
items={[
|
|
748
|
+
{ type: 'option', value: 'USD' },
|
|
749
|
+
{ type: 'option', value: 'EUR' },
|
|
750
|
+
]}
|
|
751
|
+
renderValue={(currency) => (
|
|
752
|
+
<SelectInputOptionContent title={currency} className="custom-option-class" />
|
|
753
|
+
)}
|
|
754
|
+
value="USD"
|
|
755
|
+
/>,
|
|
756
|
+
);
|
|
757
|
+
|
|
758
|
+
const trigger = screen.getByRole('combobox');
|
|
759
|
+
await userEvent.click(trigger);
|
|
760
|
+
|
|
761
|
+
const listbox = screen.getByRole('listbox');
|
|
762
|
+
const options = within(listbox).getAllByRole('option');
|
|
763
|
+
const optionContent = options[0].querySelector('.np-select-input-option-content-container');
|
|
764
|
+
expect(optionContent).toHaveClass('custom-option-class');
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
it('supports conditional className based on withinTrigger', async () => {
|
|
768
|
+
render(
|
|
769
|
+
<SelectInput
|
|
770
|
+
items={[
|
|
771
|
+
{ type: 'option', value: 'USD' },
|
|
772
|
+
{ type: 'option', value: 'EUR' },
|
|
773
|
+
]}
|
|
774
|
+
renderValue={(currency, withinTrigger) => (
|
|
775
|
+
<SelectInputOptionContent
|
|
776
|
+
title={currency}
|
|
777
|
+
className={withinTrigger ? undefined : 'dropdown-only-class'}
|
|
778
|
+
/>
|
|
779
|
+
)}
|
|
780
|
+
value="USD"
|
|
781
|
+
/>,
|
|
782
|
+
);
|
|
783
|
+
|
|
784
|
+
const triggerContent = screen
|
|
785
|
+
.getByText('USD')
|
|
786
|
+
.closest('.np-select-input-option-content-container');
|
|
787
|
+
expect(triggerContent).not.toHaveClass('dropdown-only-class');
|
|
788
|
+
|
|
789
|
+
const trigger = screen.getByRole('combobox');
|
|
790
|
+
await userEvent.click(trigger);
|
|
791
|
+
|
|
792
|
+
const listbox = screen.getByRole('listbox');
|
|
793
|
+
const options = within(listbox).getAllByRole('option');
|
|
794
|
+
const optionContent = options[0].querySelector('.np-select-input-option-content-container');
|
|
795
|
+
expect(optionContent).toHaveClass('dropdown-only-class');
|
|
796
|
+
});
|
|
797
|
+
|
|
724
798
|
describe('listbox label', () => {
|
|
725
799
|
const fieldLabel = 'Fruits';
|
|
726
800
|
const triggerLabel = 'Select fruit';
|
|
@@ -567,7 +567,7 @@
|
|
|
567
567
|
.wds-list-item-control-wrapper {
|
|
568
568
|
grid-area: control;
|
|
569
569
|
}
|
|
570
|
-
.wds-list-item-navigation .tw-icon-chevron-
|
|
570
|
+
.wds-list-item-navigation .tw-icon-chevron-end {
|
|
571
571
|
color: #c9cbce;
|
|
572
572
|
color: var(--color-interactive-secondary);
|
|
573
573
|
display: block;
|
|
@@ -169,10 +169,10 @@
|
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
// LESS struggles with ranged container queries so
|
|
173
|
-
//
|
|
174
|
-
@container (
|
|
175
|
-
.wds-list-item-media-image{
|
|
172
|
+
// LESS struggles with ranged container queries so we need to
|
|
173
|
+
// escape the interpolated expression using `e()` function.
|
|
174
|
+
@container (e("@{wds-list-item-cq-min} < width <= @{wds-list-item-cq-max}")) {
|
|
175
|
+
.wds-list-item-media-image {
|
|
176
176
|
object-position: bottom left;
|
|
177
177
|
}
|
|
178
178
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChevronEnd } from '@transferwise/icons';
|
|
2
2
|
import type { ButtonProps } from '../../Button/Button.types';
|
|
3
3
|
import { useListItemControl } from '../useListItemControl';
|
|
4
4
|
import { PrimitiveButton } from '../../Primitives';
|
|
@@ -32,7 +32,7 @@ export const Navigation = function Navigation({
|
|
|
32
32
|
}: ListItemNavigationProps) {
|
|
33
33
|
const { baseItemProps } = useListItemControl('navigation', { href, hideIndicator, ...props });
|
|
34
34
|
const { ids, describedByIds } = useContext(ListItemContext);
|
|
35
|
-
const icon = hideIndicator ? null : <
|
|
35
|
+
const icon = hideIndicator ? null : <ChevronEnd size={16} data-testid="NavigationIndicator" />;
|
|
36
36
|
|
|
37
37
|
return href ? (
|
|
38
38
|
<>{icon}</>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
margin-left: var(--size-12);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
&__number-input-field{
|
|
10
|
+
&__number-input-field {
|
|
11
11
|
[dir="rtl"] & {
|
|
12
12
|
text-align: end;
|
|
13
13
|
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
width: 100%;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
.np-select-input-content{
|
|
25
|
+
.np-select-input-content {
|
|
26
26
|
[dir="rtl"] & {
|
|
27
27
|
text-align: end;
|
|
28
28
|
direction: ltr;
|
|
@@ -40,3 +40,11 @@
|
|
|
40
40
|
.tw-telephone__number-input {
|
|
41
41
|
flex: auto 1 1;
|
|
42
42
|
}
|
|
43
|
+
|
|
44
|
+
// Prevent bidi algorithm from flipping "+{country-code}" to "{country-code}+"
|
|
45
|
+
// in RTL dropdown options as phone numbers are universally read as LTR.
|
|
46
|
+
.tw-telephone__prefix-option .np-select-input-option-content-title {
|
|
47
|
+
[dir="rtl"] & {
|
|
48
|
+
direction: ltr;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ArrowEnd, Check, Download } from '@transferwise/icons';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { ReactElement, ReactNode } from 'react';
|
|
4
4
|
|
|
@@ -57,7 +57,7 @@ const PromoCardIndicator: React.FC<PromoCardIndicatorProps> = ({
|
|
|
57
57
|
isIconString &&
|
|
58
58
|
{
|
|
59
59
|
check: Check,
|
|
60
|
-
arrow:
|
|
60
|
+
arrow: ArrowEnd,
|
|
61
61
|
download: Download,
|
|
62
62
|
}[icon];
|
|
63
63
|
|
|
@@ -256,4 +256,77 @@ describe('Typeahead', () => {
|
|
|
256
256
|
expect.arrayContaining([{ label: 'foo' }, { label: 'bar' }]),
|
|
257
257
|
);
|
|
258
258
|
});
|
|
259
|
+
|
|
260
|
+
describe('when disabled', () => {
|
|
261
|
+
it('disables the input', () => {
|
|
262
|
+
render(<Typeahead id="test" name="test" options={[]} disabled onChange={() => {}} />);
|
|
263
|
+
expect(screen.getByRole('combobox')).toBeDisabled();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('does not show the clear button when there is a value', () => {
|
|
267
|
+
render(
|
|
268
|
+
<Typeahead
|
|
269
|
+
id="test"
|
|
270
|
+
name="test"
|
|
271
|
+
options={[]}
|
|
272
|
+
initialValue={[{ label: 'Chip' }]}
|
|
273
|
+
disabled
|
|
274
|
+
onChange={() => {}}
|
|
275
|
+
/>,
|
|
276
|
+
);
|
|
277
|
+
expect(screen.queryByRole('button', { name: /clear/i })).not.toBeInTheDocument();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('keeps chips but does not let them be removed', () => {
|
|
281
|
+
render(
|
|
282
|
+
<Typeahead
|
|
283
|
+
id="test"
|
|
284
|
+
name="test"
|
|
285
|
+
options={[]}
|
|
286
|
+
multiple
|
|
287
|
+
initialValue={[{ label: 'Chip' }]}
|
|
288
|
+
disabled
|
|
289
|
+
onChange={() => {}}
|
|
290
|
+
/>,
|
|
291
|
+
);
|
|
292
|
+
expect(screen.getByText('Chip').closest('.np-chip')).toHaveClass('disabled');
|
|
293
|
+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('does not open the suggestions when the input is clicked', async () => {
|
|
297
|
+
render(
|
|
298
|
+
<Typeahead
|
|
299
|
+
id="test"
|
|
300
|
+
name="test"
|
|
301
|
+
options={[{ label: 'Option 1' }]}
|
|
302
|
+
minQueryLength={0}
|
|
303
|
+
disabled
|
|
304
|
+
onChange={() => {}}
|
|
305
|
+
/>,
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
await userEvent.click(screen.getByRole('combobox'));
|
|
309
|
+
|
|
310
|
+
expect(screen.getByRole('combobox')).toHaveAttribute('aria-expanded', 'false');
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('closes the open menu when it becomes disabled', async () => {
|
|
314
|
+
const onChange = jest.fn();
|
|
315
|
+
const props = {
|
|
316
|
+
id: 'test',
|
|
317
|
+
name: 'test',
|
|
318
|
+
options: [],
|
|
319
|
+
allowNew: true,
|
|
320
|
+
minQueryLength: 0,
|
|
321
|
+
onChange,
|
|
322
|
+
};
|
|
323
|
+
const { rerender } = render(<Typeahead {...props} />);
|
|
324
|
+
|
|
325
|
+
await userEvent.type(screen.getByRole('combobox'), 'New thing');
|
|
326
|
+
rerender(<Typeahead {...props} disabled />);
|
|
327
|
+
await userEvent.click(document.body);
|
|
328
|
+
|
|
329
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
330
|
+
});
|
|
331
|
+
});
|
|
259
332
|
});
|
|
@@ -61,6 +61,8 @@ export interface TypeaheadProps<T> extends Partial<WrappedComponentProps> {
|
|
|
61
61
|
chipSeparators?: readonly string[];
|
|
62
62
|
/** @default true */
|
|
63
63
|
clearable?: boolean;
|
|
64
|
+
/** @default false */
|
|
65
|
+
disabled?: boolean;
|
|
64
66
|
footer?: ReactNode;
|
|
65
67
|
/** @default [] */
|
|
66
68
|
initialValue?: readonly TypeaheadOption<T>[];
|
|
@@ -112,6 +114,7 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
112
114
|
autoFocus: false,
|
|
113
115
|
chipSeparators: [],
|
|
114
116
|
clearable: true,
|
|
117
|
+
disabled: false,
|
|
115
118
|
initialValue: [],
|
|
116
119
|
inputAutoComplete: 'new-password',
|
|
117
120
|
minQueryLength: DEFAULT_MIN_QUERY_LENGTH,
|
|
@@ -160,6 +163,12 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
160
163
|
}
|
|
161
164
|
}
|
|
162
165
|
|
|
166
|
+
componentDidUpdate(previousProps: TypeaheadPropsWithInputAttributes<T>) {
|
|
167
|
+
if (this.props.disabled && !previousProps.disabled) {
|
|
168
|
+
this.hideMenu();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
163
172
|
componentWillUnmount() {
|
|
164
173
|
this.handleSearchDebounced.cancel();
|
|
165
174
|
}
|
|
@@ -398,6 +407,7 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
398
407
|
};
|
|
399
408
|
|
|
400
409
|
renderChip = (option: TypeaheadOption<T>, idx: number): ReactNode => {
|
|
410
|
+
const { disabled } = this.props;
|
|
401
411
|
const valid = this.props.validateChip?.(option);
|
|
402
412
|
|
|
403
413
|
return (
|
|
@@ -408,7 +418,8 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
408
418
|
'has-error': !valid,
|
|
409
419
|
'np-chip--valid': valid,
|
|
410
420
|
})}
|
|
411
|
-
|
|
421
|
+
disabled={disabled}
|
|
422
|
+
onRemove={disabled ? undefined : () => this.removeChip(option)}
|
|
412
423
|
/>
|
|
413
424
|
);
|
|
414
425
|
};
|
|
@@ -486,6 +497,7 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
486
497
|
addon,
|
|
487
498
|
name,
|
|
488
499
|
clearable,
|
|
500
|
+
disabled,
|
|
489
501
|
allowNew,
|
|
490
502
|
footer,
|
|
491
503
|
showSuggestions,
|
|
@@ -501,9 +513,10 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
501
513
|
|
|
502
514
|
const { errorState, query, selected, optionsShown, keyboardFocusedOptionIndex } = this.state;
|
|
503
515
|
|
|
504
|
-
const clearButton = clearable && (query || selected.length > 0);
|
|
516
|
+
const clearButton = !disabled && clearable && (query || selected.length > 0);
|
|
505
517
|
|
|
506
|
-
const dropdownOpen =
|
|
518
|
+
const dropdownOpen =
|
|
519
|
+
!disabled && optionsShown && showSuggestions && query.length >= minQueryLength;
|
|
507
520
|
|
|
508
521
|
const menu = this.renderMenu({
|
|
509
522
|
footer,
|
|
@@ -556,6 +569,7 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
556
569
|
<div
|
|
557
570
|
className={clsx(`input-group input-group-${size}`, {
|
|
558
571
|
'input-group--has-error': hasError,
|
|
572
|
+
disabled,
|
|
559
573
|
})}
|
|
560
574
|
>
|
|
561
575
|
{addon && <span className="input-group-addon input-group-addon--search">{addon}</span>}
|
|
@@ -563,6 +577,7 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
563
577
|
<TypeaheadInput
|
|
564
578
|
{...{
|
|
565
579
|
autoFocus,
|
|
580
|
+
disabled,
|
|
566
581
|
multiple,
|
|
567
582
|
dropdownOpen,
|
|
568
583
|
placeholder,
|
|
@@ -23,7 +23,10 @@ export type TypeaheadInputProps<T> = {
|
|
|
23
23
|
onPaste: React.ClipboardEventHandler<HTMLInputElement>;
|
|
24
24
|
renderChip: (chip: TypeaheadOption<T>, index: number) => ReactNode;
|
|
25
25
|
ariaActivedescendant?: string;
|
|
26
|
-
} & Pick<
|
|
26
|
+
} & Pick<
|
|
27
|
+
TypeaheadProps<T>,
|
|
28
|
+
'id' | 'name' | 'autoFocus' | 'disabled' | 'multiple' | 'placeholder' | 'maxHeight'
|
|
29
|
+
>;
|
|
27
30
|
|
|
28
31
|
type TypeaheadInputState = {
|
|
29
32
|
inputWidth: number;
|
|
@@ -73,6 +76,7 @@ export default class TypeaheadInput<T> extends Component<
|
|
|
73
76
|
const {
|
|
74
77
|
typeaheadId,
|
|
75
78
|
autoFocus,
|
|
79
|
+
disabled,
|
|
76
80
|
multiple,
|
|
77
81
|
name,
|
|
78
82
|
dropdownOpen,
|
|
@@ -98,6 +102,7 @@ export default class TypeaheadInput<T> extends Component<
|
|
|
98
102
|
id={`input-${typeaheadId}`}
|
|
99
103
|
aria-activedescendant={ariaActivedescendant}
|
|
100
104
|
autoFocus={autoFocus}
|
|
105
|
+
disabled={disabled}
|
|
101
106
|
placeholder={hasPlaceholder ? placeholder : ''}
|
|
102
107
|
aria-autocomplete="list"
|
|
103
108
|
aria-expanded={dropdownOpen}
|
|
@@ -3,6 +3,7 @@ import { Search as SearchIcon } from '@transferwise/icons';
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import Button from '../../Button';
|
|
6
|
+
import Field from '../../Field/Field';
|
|
6
7
|
import Modal from '../../Modal';
|
|
7
8
|
import Typeahead from '../Typeahead';
|
|
8
9
|
|
|
@@ -17,6 +18,46 @@ const meta: Meta<typeof Typeahead> = {
|
|
|
17
18
|
};
|
|
18
19
|
export default meta;
|
|
19
20
|
|
|
21
|
+
export const Disabled: Story = {
|
|
22
|
+
render: () => (
|
|
23
|
+
<div className="d-flex flex-column">
|
|
24
|
+
<Field id="typeahead-disabled-empty" label="Empty">
|
|
25
|
+
<Typeahead
|
|
26
|
+
id="typeahead-disabled-empty"
|
|
27
|
+
name="typeahead-disabled-empty"
|
|
28
|
+
disabled
|
|
29
|
+
placeholder="Search currencies"
|
|
30
|
+
addon={<SearchIcon size={24} />}
|
|
31
|
+
options={[]}
|
|
32
|
+
onChange={() => {}}
|
|
33
|
+
/>
|
|
34
|
+
</Field>
|
|
35
|
+
<Field id="typeahead-disabled-value" label="With a value">
|
|
36
|
+
<Typeahead
|
|
37
|
+
id="typeahead-disabled-value"
|
|
38
|
+
name="typeahead-disabled-value"
|
|
39
|
+
disabled
|
|
40
|
+
addon={<SearchIcon size={24} />}
|
|
41
|
+
initialValue={[{ label: 'British pound' }]}
|
|
42
|
+
options={[]}
|
|
43
|
+
onChange={() => {}}
|
|
44
|
+
/>
|
|
45
|
+
</Field>
|
|
46
|
+
<Field id="typeahead-disabled-chips" label="With chips">
|
|
47
|
+
<Typeahead
|
|
48
|
+
id="typeahead-disabled-chips"
|
|
49
|
+
name="typeahead-disabled-chips"
|
|
50
|
+
disabled
|
|
51
|
+
multiple
|
|
52
|
+
initialValue={[{ label: 'British pound' }, { label: 'Euro' }]}
|
|
53
|
+
options={[]}
|
|
54
|
+
onChange={() => {}}
|
|
55
|
+
/>
|
|
56
|
+
</Field>
|
|
57
|
+
</div>
|
|
58
|
+
),
|
|
59
|
+
};
|
|
60
|
+
|
|
20
61
|
export const AutoFocusInModal: Story = {
|
|
21
62
|
parameters: {
|
|
22
63
|
docs: {
|
package/src/i18n/en.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Select an option...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Country code",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Phone number",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Prefix",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Search...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "No results found",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Error:",
|
package/src/i18n/es.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Selecciona una opción...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Código de país",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Número de teléfono",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Prefijo",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Buscar...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "No se han encontrado resultados",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Error:",
|
package/src/i18n/hu.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Válassz ki egy lehetőséget...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Országazonosító",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Telefonszám",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Előtag",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Keresés...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "Nincs találat",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Hiba:",
|
package/src/i18n/id.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Pilih opsi...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Kode negara",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Nomor telepon",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Awalan",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Cari...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "Hasil tidak ditemukan",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Kesalahan:",
|
package/src/i18n/it.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Seleziona un'opzione...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Prefisso",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Numero di telefono",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Prefisso",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Cerca...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "Nessun risultato trovato",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Errore:",
|
package/src/i18n/ja.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "選択してください…",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "国コード",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "電話番号",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "プレフィックス",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "検索する... ",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "結果が見つかりませんでした",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "エラー:",
|
package/src/i18n/nl.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Selecteer een optie...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Landcode",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Telefoonnummer",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Voorvoegsel",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Zoeken...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "Geen resultaten gevonden",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Fout:",
|
package/src/i18n/pl.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Wybierz opcję...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Numer kierunkowy",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Numer telefonu",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Prefiks",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Wyszukaj...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "Nie znaleziono wyników",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Błąd:",
|
package/src/i18n/ro.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Selectează o opțiune...",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Codul țării",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Număr de telefon",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Prefix",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Caută...",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "Nu s-a găsit niciun rezultat",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Eroare:",
|
package/src/i18n/uk.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "Виберіть варіант…",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "Код країни",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "Номер телефону",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "Префікс",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "Пошук…",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "Нічого не знайдено",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "Помилка:",
|
package/src/i18n/zh-HK.json
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "選擇其中一項…",
|
|
36
36
|
"neptune.PhoneNumberInput.countryCodeLabel": "國家/地區代碼",
|
|
37
37
|
"neptune.PhoneNumberInput.phoneNumberLabel": "電話號碼",
|
|
38
|
+
"neptune.PhoneNumberInput.phoneNumberPrefix": "前綴",
|
|
38
39
|
"neptune.Select.searchPlaceholder": "搜尋…",
|
|
39
40
|
"neptune.SelectInput.noResultsFound": "找不到任何結果",
|
|
40
41
|
"neptune.StatusIcon.iconLabel.error": "錯誤:",
|