@transferwise/components 0.0.0-experimental-28734fb → 0.0.0-experimental-25d8a30
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/common/panel/Panel.js +1 -0
- package/build/common/panel/Panel.js.map +1 -1
- package/build/common/panel/Panel.mjs +1 -0
- package/build/common/panel/Panel.mjs.map +1 -1
- package/build/common/responsivePanel/ResponsivePanel.js +6 -1
- package/build/common/responsivePanel/ResponsivePanel.js.map +1 -1
- package/build/common/responsivePanel/ResponsivePanel.mjs +6 -1
- package/build/common/responsivePanel/ResponsivePanel.mjs.map +1 -1
- package/build/dateInput/DateInput.js +33 -8
- package/build/dateInput/DateInput.js.map +1 -1
- package/build/dateInput/DateInput.mjs +35 -10
- package/build/dateInput/DateInput.mjs.map +1 -1
- package/build/dateLookup/DateLookup.js +5 -2
- package/build/dateLookup/DateLookup.js.map +1 -1
- package/build/dateLookup/DateLookup.mjs +5 -2
- package/build/dateLookup/DateLookup.mjs.map +1 -1
- package/build/dateLookup/dateTrigger/DateTrigger.js +2 -0
- package/build/dateLookup/dateTrigger/DateTrigger.js.map +1 -1
- package/build/dateLookup/dateTrigger/DateTrigger.mjs +2 -0
- package/build/dateLookup/dateTrigger/DateTrigger.mjs.map +1 -1
- package/build/field/Field.js +7 -2
- package/build/field/Field.js.map +1 -1
- package/build/field/Field.mjs +13 -8
- package/build/field/Field.mjs.map +1 -1
- package/build/inputs/InputGroup.js +1 -1
- package/build/inputs/InputGroup.js.map +1 -1
- package/build/inputs/InputGroup.mjs +2 -2
- package/build/inputs/InputGroup.mjs.map +1 -1
- package/build/inputs/SelectInput.js +9 -3
- package/build/inputs/SelectInput.js.map +1 -1
- package/build/inputs/SelectInput.mjs +9 -3
- package/build/inputs/SelectInput.mjs.map +1 -1
- package/build/inputs/contexts.js +8 -4
- package/build/inputs/contexts.js.map +1 -1
- package/build/inputs/contexts.mjs +7 -4
- package/build/inputs/contexts.mjs.map +1 -1
- package/build/label/Label.js +14 -8
- package/build/label/Label.js.map +1 -1
- package/build/label/Label.mjs +14 -8
- package/build/label/Label.mjs.map +1 -1
- package/build/moneyInput/MoneyInput.js +6 -5
- package/build/moneyInput/MoneyInput.js.map +1 -1
- package/build/moneyInput/MoneyInput.mjs +6 -5
- package/build/moneyInput/MoneyInput.mjs.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.js +24 -2
- package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.mjs +26 -4
- package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
- package/build/types/common/panel/Panel.d.ts +2 -0
- package/build/types/common/panel/Panel.d.ts.map +1 -1
- package/build/types/common/responsivePanel/ResponsivePanel.d.ts +1 -0
- package/build/types/common/responsivePanel/ResponsivePanel.d.ts.map +1 -1
- package/build/types/dateInput/DateInput.d.ts +2 -2
- package/build/types/dateInput/DateInput.d.ts.map +1 -1
- package/build/types/dateLookup/DateLookup.d.ts.map +1 -1
- package/build/types/dateLookup/dateTrigger/DateTrigger.d.ts +1 -0
- package/build/types/dateLookup/dateTrigger/DateTrigger.d.ts.map +1 -1
- package/build/types/field/Field.d.ts.map +1 -1
- package/build/types/inputs/InputGroup.d.ts.map +1 -1
- package/build/types/inputs/SelectInput.d.ts +3 -1
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/inputs/contexts.d.ts +6 -1
- package/build/types/inputs/contexts.d.ts.map +1 -1
- package/build/types/label/Label.d.ts +5 -15
- package/build/types/label/Label.d.ts.map +1 -1
- package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/common/panel/Panel.tsx +2 -0
- package/src/common/responsivePanel/ResponsivePanel.tsx +7 -1
- package/src/dateInput/DateInput.tsx +43 -13
- package/src/dateLookup/DateLookup.tsx +6 -3
- package/src/dateLookup/dateTrigger/DateTrigger.tsx +3 -0
- package/src/field/Field.tsx +6 -5
- package/src/inputs/InputGroup.tsx +3 -4
- package/src/inputs/SelectInput.tsx +13 -3
- package/src/inputs/contexts.tsx +12 -3
- package/src/label/Label.tsx +26 -20
- package/src/moneyInput/MoneyInput.spec.tsx +2 -1
- package/src/moneyInput/MoneyInput.tsx +7 -6
- package/src/phoneNumberInput/PhoneNumberInput.tsx +31 -10
package/src/field/Field.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
|
-
import { useId } from 'react';
|
|
2
|
+
import { useId, useRef } from 'react';
|
|
3
3
|
|
|
4
4
|
import { Sentiment } from '../common';
|
|
5
5
|
import InlineAlert from '../inlineAlert/InlineAlert';
|
|
6
6
|
import {
|
|
7
|
-
|
|
7
|
+
FieldLabelContextProvider,
|
|
8
8
|
InputDescribedByProvider,
|
|
9
9
|
InputIdContextProvider,
|
|
10
10
|
InputInvalidProvider,
|
|
@@ -46,6 +46,7 @@ export const Field = ({
|
|
|
46
46
|
children,
|
|
47
47
|
...props
|
|
48
48
|
}: FieldProps) => {
|
|
49
|
+
const labelRef = useRef<HTMLLabelElement>(null);
|
|
49
50
|
const sentiment = props.error ? Sentiment.NEGATIVE : propType;
|
|
50
51
|
const message = propMessage || props.error;
|
|
51
52
|
const hasError = sentiment === Sentiment.NEGATIVE;
|
|
@@ -74,7 +75,7 @@ export const Field = ({
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
return (
|
|
77
|
-
<
|
|
78
|
+
<FieldLabelContextProvider value={{ id: labelId, ref: labelRef }}>
|
|
78
79
|
<InputIdContextProvider value={inputId}>
|
|
79
80
|
<InputDescribedByProvider value={ariaDescribedbyByIds()}>
|
|
80
81
|
<InputInvalidProvider value={hasError}>
|
|
@@ -92,7 +93,7 @@ export const Field = ({
|
|
|
92
93
|
>
|
|
93
94
|
{label != null ? (
|
|
94
95
|
<>
|
|
95
|
-
<Label id={labelId} htmlFor={inputId}>
|
|
96
|
+
<Label ref={labelRef} id={labelId} htmlFor={inputId}>
|
|
96
97
|
{required ? label : <Label.Optional>{label}</Label.Optional>}
|
|
97
98
|
</Label>
|
|
98
99
|
<Label.Description id={descriptionId}>{description}</Label.Description>
|
|
@@ -111,6 +112,6 @@ export const Field = ({
|
|
|
111
112
|
</InputInvalidProvider>
|
|
112
113
|
</InputDescribedByProvider>
|
|
113
114
|
</InputIdContextProvider>
|
|
114
|
-
</
|
|
115
|
+
</FieldLabelContextProvider>
|
|
115
116
|
);
|
|
116
117
|
};
|
|
@@ -4,11 +4,10 @@ import { createContext, useContext, useMemo, useRef, useState } from 'react';
|
|
|
4
4
|
import { useResizeObserver } from '../common/hooks/useResizeObserver';
|
|
5
5
|
import { cssValueWithUnit } from '../utilities/cssValueWithUnit';
|
|
6
6
|
import {
|
|
7
|
-
|
|
7
|
+
FieldLabelContextProvider,
|
|
8
8
|
InputDescribedByProvider,
|
|
9
9
|
InputIdContextProvider,
|
|
10
10
|
InputInvalidProvider,
|
|
11
|
-
useInputAttributes,
|
|
12
11
|
} from './contexts';
|
|
13
12
|
|
|
14
13
|
type InputPaddingContextType = [
|
|
@@ -129,7 +128,7 @@ function InputAddon({
|
|
|
129
128
|
|
|
130
129
|
return (
|
|
131
130
|
/* Prevent nested controls from being labeled redundantly */
|
|
132
|
-
<
|
|
131
|
+
<FieldLabelContextProvider value={undefined}>
|
|
133
132
|
<InputIdContextProvider value={undefined}>
|
|
134
133
|
<InputDescribedByProvider value={undefined}>
|
|
135
134
|
<InputInvalidProvider value={undefined}>
|
|
@@ -153,6 +152,6 @@ function InputAddon({
|
|
|
153
152
|
</InputInvalidProvider>
|
|
154
153
|
</InputDescribedByProvider>
|
|
155
154
|
</InputIdContextProvider>
|
|
156
|
-
</
|
|
155
|
+
</FieldLabelContextProvider>
|
|
157
156
|
);
|
|
158
157
|
}
|
|
@@ -181,6 +181,8 @@ export interface SelectInputProps<T = string, M extends boolean = false> {
|
|
|
181
181
|
UNSAFE_triggerButtonProps?: WithInputAttributesProps['inputAttributes'] & {
|
|
182
182
|
'aria-label'?: string;
|
|
183
183
|
};
|
|
184
|
+
/** Ref to the select trigger button element. */
|
|
185
|
+
triggerRef?: React.MutableRefObject<HTMLButtonElement | null>;
|
|
184
186
|
onFilterChange?: (args: { query: string; queryNormalized: string | null }) => void;
|
|
185
187
|
onChange?: (value: M extends true ? T[] : T) => void;
|
|
186
188
|
onOpen?: () => void;
|
|
@@ -268,6 +270,7 @@ export function SelectInput<T = string, M extends boolean = false>({
|
|
|
268
270
|
size = 'md',
|
|
269
271
|
className,
|
|
270
272
|
UNSAFE_triggerButtonProps,
|
|
273
|
+
triggerRef: externalTriggerRef,
|
|
271
274
|
onFilterChange = noop,
|
|
272
275
|
onChange,
|
|
273
276
|
onOpen,
|
|
@@ -306,7 +309,7 @@ export function SelectInput<T = string, M extends boolean = false>({
|
|
|
306
309
|
}
|
|
307
310
|
});
|
|
308
311
|
|
|
309
|
-
const
|
|
312
|
+
const internalTriggerRef = useRef<HTMLButtonElement | null>(null);
|
|
310
313
|
|
|
311
314
|
const screenSm = useScreenSize(Breakpoint.SMALL);
|
|
312
315
|
const OptionsOverlay = screenSm ? Popover : BottomSheet;
|
|
@@ -374,7 +377,12 @@ export function SelectInput<T = string, M extends boolean = false>({
|
|
|
374
377
|
value={{
|
|
375
378
|
ref: (node) => {
|
|
376
379
|
ref(node);
|
|
377
|
-
|
|
380
|
+
if (externalTriggerRef) {
|
|
381
|
+
// eslint-disable-next-line no-param-reassign
|
|
382
|
+
externalTriggerRef.current = node;
|
|
383
|
+
} else {
|
|
384
|
+
internalTriggerRef.current = node;
|
|
385
|
+
}
|
|
378
386
|
},
|
|
379
387
|
...inputAttributes,
|
|
380
388
|
...UNSAFE_triggerButtonProps,
|
|
@@ -417,7 +425,9 @@ export function SelectInput<T = string, M extends boolean = false>({
|
|
|
417
425
|
onClear != null
|
|
418
426
|
? () => {
|
|
419
427
|
onClear();
|
|
420
|
-
|
|
428
|
+
(externalTriggerRef?.current ?? internalTriggerRef.current)?.focus({
|
|
429
|
+
preventScroll: true,
|
|
430
|
+
});
|
|
421
431
|
}
|
|
422
432
|
: undefined,
|
|
423
433
|
disabled: uiDisabled,
|
package/src/inputs/contexts.tsx
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { createContext, useContext } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type FieldLabelContextType = {
|
|
4
|
+
id?: string;
|
|
5
|
+
ref?: React.RefObject<HTMLLabelElement>;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const FieldLabelContext = createContext<FieldLabelContextType | undefined>(undefined);
|
|
9
|
+
export const FieldLabelContextProvider = FieldLabelContext.Provider;
|
|
5
10
|
|
|
6
11
|
const InputIdContext = createContext<string | undefined>(undefined);
|
|
7
12
|
export const InputIdContextProvider = InputIdContext.Provider;
|
|
@@ -18,7 +23,7 @@ interface UseInputAttributesArgs {
|
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
export function useInputAttributes({ nonLabelable }: UseInputAttributesArgs = {}) {
|
|
21
|
-
const labelId = useContext(
|
|
26
|
+
const labelId = useContext(FieldLabelContext)?.id;
|
|
22
27
|
return {
|
|
23
28
|
id: useContext(InputIdContext),
|
|
24
29
|
'aria-labelledby': nonLabelable ? labelId : undefined,
|
|
@@ -27,6 +32,10 @@ export function useInputAttributes({ nonLabelable }: UseInputAttributesArgs = {}
|
|
|
27
32
|
} satisfies React.HTMLAttributes<HTMLElement>;
|
|
28
33
|
}
|
|
29
34
|
|
|
35
|
+
export function useFieldLabelRef() {
|
|
36
|
+
return useContext(FieldLabelContext)?.ref;
|
|
37
|
+
}
|
|
38
|
+
|
|
30
39
|
export interface WithInputAttributesProps {
|
|
31
40
|
inputAttributes: ReturnType<typeof useInputAttributes>;
|
|
32
41
|
}
|
package/src/label/Label.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import messages from './Label.messages';
|
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
4
|
import Body from '../body';
|
|
5
5
|
import { CommonProps } from '../common';
|
|
6
|
-
import { PropsWithChildren } from 'react';
|
|
6
|
+
import { forwardRef, PropsWithChildren } from 'react';
|
|
7
7
|
|
|
8
8
|
export type LabelProps = {
|
|
9
9
|
id?: string;
|
|
@@ -21,25 +21,29 @@ export type LabelProps = {
|
|
|
21
21
|
* <Field label={..} description={..} required={..}>..</Field>
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
const Label =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
className
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
const Label = forwardRef<HTMLLabelElement, LabelProps>(
|
|
25
|
+
({ className, children, htmlFor, id }: LabelProps, ref) => {
|
|
26
|
+
return (
|
|
27
|
+
<label
|
|
28
|
+
ref={ref}
|
|
29
|
+
id={id}
|
|
30
|
+
htmlFor={htmlFor}
|
|
31
|
+
className={clsx(
|
|
32
|
+
'np-label d-flex flex-column np-text-body-default-bold text-primary m-b-0',
|
|
33
|
+
className,
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
{children}
|
|
37
|
+
</label>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
Label.displayName = 'Label';
|
|
38
43
|
|
|
39
44
|
export type LabelOptionalProps = PropsWithChildren<CommonProps>;
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
Label.Optional = function Optional({ children, className }: LabelOptionalProps) {
|
|
46
|
+
const Optional = function Optional({ children, className }: LabelOptionalProps) {
|
|
43
47
|
const { formatMessage } = useIntl();
|
|
44
48
|
return (
|
|
45
49
|
<div>
|
|
@@ -53,8 +57,7 @@ Label.Optional = function Optional({ children, className }: LabelOptionalProps)
|
|
|
53
57
|
|
|
54
58
|
export type LabelDescriptionProps = PropsWithChildren<CommonProps> & { id?: string };
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
Label.Description = function Description({ id, children, className }: LabelDescriptionProps) {
|
|
60
|
+
const Description = function Description({ id, children, className }: LabelDescriptionProps) {
|
|
58
61
|
return children ? (
|
|
59
62
|
<Body id={id} className={clsx('text-secondary', className)}>
|
|
60
63
|
{children}
|
|
@@ -62,4 +65,7 @@ Label.Description = function Description({ id, children, className }: LabelDescr
|
|
|
62
65
|
) : null;
|
|
63
66
|
};
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
// eslint-disable-next-line functional/immutable-data
|
|
69
|
+
const LabelNamespace = Object.assign(Label, { Optional, Description });
|
|
70
|
+
|
|
71
|
+
export { LabelNamespace as Label };
|
|
@@ -406,7 +406,7 @@ describe('Money Input', () => {
|
|
|
406
406
|
</>,
|
|
407
407
|
);
|
|
408
408
|
|
|
409
|
-
expect(screen.getAllByLabelText('Prioritized label')[0]).toHaveClass('
|
|
409
|
+
expect(screen.getAllByLabelText('Prioritized label')[0]).toHaveClass('np-form-control');
|
|
410
410
|
});
|
|
411
411
|
|
|
412
412
|
it('supports `Field` for labeling', () => {
|
|
@@ -415,6 +415,7 @@ describe('Money Input', () => {
|
|
|
415
415
|
<MoneyInput {...initialProps} />
|
|
416
416
|
</Field>,
|
|
417
417
|
);
|
|
418
|
+
|
|
418
419
|
expect(screen.getAllByRole('group')[0]).toHaveAccessibleName(/^Recipient gets/);
|
|
419
420
|
});
|
|
420
421
|
|
|
@@ -313,10 +313,10 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
|
|
|
313
313
|
const selectedCurrencyElementId = `${inputAttributes?.id ?? amountInputId}SelectedCurrency`;
|
|
314
314
|
|
|
315
315
|
return (
|
|
316
|
-
<
|
|
317
|
-
|
|
318
|
-
{
|
|
319
|
-
aria-labelledby={
|
|
316
|
+
<fieldset
|
|
317
|
+
aria-invalid={inputAttributes?.['aria-invalid']}
|
|
318
|
+
aria-describedby={inputAttributes?.['aria-describedby']}
|
|
319
|
+
aria-labelledby={inputAttributes?.id ?? amountInputId}
|
|
320
320
|
className={clsx(
|
|
321
321
|
this.style('tw-money-input'),
|
|
322
322
|
this.style('input-group'),
|
|
@@ -324,7 +324,8 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
|
|
|
324
324
|
)}
|
|
325
325
|
>
|
|
326
326
|
<Input
|
|
327
|
-
id={amountInputId}
|
|
327
|
+
id={inputAttributes?.id ?? amountInputId}
|
|
328
|
+
aria-labelledby={ariaLabelledBy}
|
|
328
329
|
value={this.state.formattedAmount}
|
|
329
330
|
inputMode="decimal"
|
|
330
331
|
disabled={disabled}
|
|
@@ -430,7 +431,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
|
|
|
430
431
|
/>
|
|
431
432
|
</div>
|
|
432
433
|
)}
|
|
433
|
-
</
|
|
434
|
+
</fieldset>
|
|
434
435
|
);
|
|
435
436
|
}
|
|
436
437
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
1
|
+
import { useState, useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { useIntl } from 'react-intl';
|
|
3
3
|
|
|
4
4
|
import { Size, SizeLarge, SizeMedium, SizeSmall } from '../common';
|
|
5
|
-
import { useInputAttributes } from '../inputs/contexts';
|
|
5
|
+
import { useFieldLabelRef, useInputAttributes } from '../inputs/contexts';
|
|
6
6
|
import { SelectInput, SelectInputOptionContent, SelectInputProps } from '../inputs/SelectInput';
|
|
7
7
|
import messages from './PhoneNumberInput.messages';
|
|
8
8
|
import countries from './data/countries';
|
|
@@ -58,7 +58,10 @@ const PhoneNumberInput = ({
|
|
|
58
58
|
selectProps = defaultSelectProps,
|
|
59
59
|
disabledCountries = defaultDisabledCountries,
|
|
60
60
|
}: PhoneNumberInputProps) => {
|
|
61
|
+
const countryCodeSelectRef = useRef<HTMLButtonElement>(null);
|
|
62
|
+
const phoneNumberInputRef = useRef<HTMLInputElement>(null);
|
|
61
63
|
const inputAttributes = useInputAttributes({ nonLabelable: true });
|
|
64
|
+
const fieldLabelRef = useFieldLabelRef();
|
|
62
65
|
const ariaLabelledBy = ariaLabelledByProp ?? inputAttributes['aria-labelledby'];
|
|
63
66
|
|
|
64
67
|
const { locale, formatMessage } = useIntl();
|
|
@@ -71,6 +74,7 @@ const PhoneNumberInput = ({
|
|
|
71
74
|
return `${backup}-${random}`;
|
|
72
75
|
};
|
|
73
76
|
|
|
77
|
+
// Link the first non-disabled input to the the Field label, if present
|
|
74
78
|
const ids = {
|
|
75
79
|
countryCode: {
|
|
76
80
|
label: createId(id, 'country-code-label'),
|
|
@@ -162,18 +166,34 @@ const PhoneNumberInput = ({
|
|
|
162
166
|
setBroadcastedValue(internalValue);
|
|
163
167
|
}, [onChange, broadcastedValue, internalValue]);
|
|
164
168
|
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
const labelRef = fieldLabelRef?.current;
|
|
171
|
+
|
|
172
|
+
if (labelRef) {
|
|
173
|
+
const handleLabelClick = () => {
|
|
174
|
+
if (!selectProps.disabled) {
|
|
175
|
+
countryCodeSelectRef.current?.click();
|
|
176
|
+
} else {
|
|
177
|
+
phoneNumberInputRef.current?.focus();
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
labelRef.addEventListener('click', handleLabelClick);
|
|
182
|
+
|
|
183
|
+
return () => {
|
|
184
|
+
labelRef?.removeEventListener('click', handleLabelClick);
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}, [fieldLabelRef, selectProps.disabled]);
|
|
188
|
+
|
|
165
189
|
return (
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
{...inputAttributes}
|
|
169
|
-
aria-labelledby={ariaLabelledBy}
|
|
170
|
-
className="tw-telephone"
|
|
171
|
-
>
|
|
172
|
-
<label className="sr-only" id={ids.countryCode.label}>
|
|
190
|
+
<fieldset {...inputAttributes} aria-labelledby={ariaLabelledBy} className="tw-telephone">
|
|
191
|
+
<label className="sr-only" id={ids.countryCode.label} htmlFor={ids.countryCode.select}>
|
|
173
192
|
{formatMessage(messages.countryCodeLabel)}
|
|
174
193
|
</label>
|
|
175
194
|
<div className="tw-telephone__country-select">
|
|
176
195
|
<SelectInput
|
|
196
|
+
triggerRef={countryCodeSelectRef}
|
|
177
197
|
placeholder={formatMessage(messages.selectInputPlaceholder)}
|
|
178
198
|
items={[...countriesByPrefix].map(([prefix, countries]) => ({
|
|
179
199
|
type: 'option',
|
|
@@ -227,6 +247,7 @@ const PhoneNumberInput = ({
|
|
|
227
247
|
<div className="tw-telephone__number-input">
|
|
228
248
|
<div className={`input-group input-group-${size}`}>
|
|
229
249
|
<Input
|
|
250
|
+
ref={phoneNumberInputRef}
|
|
230
251
|
id={ids.phoneNumber.input}
|
|
231
252
|
autoComplete="tel-national"
|
|
232
253
|
name="phoneNumber"
|
|
@@ -243,7 +264,7 @@ const PhoneNumberInput = ({
|
|
|
243
264
|
/>
|
|
244
265
|
</div>
|
|
245
266
|
</div>
|
|
246
|
-
</
|
|
267
|
+
</fieldset>
|
|
247
268
|
);
|
|
248
269
|
};
|
|
249
270
|
|