@input-kit/phone 0.5.0 → 0.6.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/README.md +240 -223
- package/dist/index.cjs +136 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +137 -48
- package/dist/index.js.map +1 -1
- package/package.json +91 -91
package/dist/index.d.cts
CHANGED
|
@@ -83,6 +83,7 @@ interface PhoneInputLabels {
|
|
|
83
83
|
searchCountriesAriaLabel: string;
|
|
84
84
|
countryOptionsAriaLabel: string;
|
|
85
85
|
countryButtonAriaLabel: string;
|
|
86
|
+
countryResultsAnnouncement: string;
|
|
86
87
|
}
|
|
87
88
|
interface PhoneInputOptions {
|
|
88
89
|
defaultCountry?: string;
|
|
@@ -132,11 +133,32 @@ interface UsePhoneInputReturn extends PhoneInputState, PhoneInputActions {
|
|
|
132
133
|
inputProps: InputHTMLAttributes<HTMLInputElement> & {
|
|
133
134
|
ref: RefObject<HTMLInputElement | null>;
|
|
134
135
|
};
|
|
136
|
+
highlightedIndex: number;
|
|
137
|
+
activeCountry: Country | undefined;
|
|
138
|
+
countryResultsText: string;
|
|
139
|
+
setHighlightedIndex: (index: number) => void;
|
|
140
|
+
moveHighlight: (nextIndex: number) => void;
|
|
135
141
|
countryButtonProps: {
|
|
136
142
|
onClick: () => void;
|
|
137
143
|
'aria-expanded': boolean;
|
|
138
144
|
'aria-haspopup': 'listbox';
|
|
139
145
|
'aria-label': string;
|
|
146
|
+
'aria-controls': string;
|
|
147
|
+
};
|
|
148
|
+
countrySearchProps: {
|
|
149
|
+
role: 'combobox';
|
|
150
|
+
value: string;
|
|
151
|
+
onChange: (event: {
|
|
152
|
+
target: {
|
|
153
|
+
value: string;
|
|
154
|
+
};
|
|
155
|
+
}) => void;
|
|
156
|
+
'aria-expanded': boolean;
|
|
157
|
+
'aria-controls': string;
|
|
158
|
+
'aria-autocomplete': 'list';
|
|
159
|
+
'aria-activedescendant': string | undefined;
|
|
160
|
+
'aria-label': string;
|
|
161
|
+
placeholder: string;
|
|
140
162
|
};
|
|
141
163
|
countrySelectorProps: {
|
|
142
164
|
onClick: () => void;
|
|
@@ -145,10 +167,12 @@ interface UsePhoneInputReturn extends PhoneInputState, PhoneInputActions {
|
|
|
145
167
|
'aria-label': string;
|
|
146
168
|
};
|
|
147
169
|
dropdownProps: {
|
|
170
|
+
id: string;
|
|
148
171
|
role: 'listbox';
|
|
149
172
|
'aria-label': string;
|
|
150
|
-
'aria-activedescendant'?: string;
|
|
151
173
|
};
|
|
174
|
+
listboxId: string;
|
|
175
|
+
activeOptionId: string | undefined;
|
|
152
176
|
filteredCountries: Country[];
|
|
153
177
|
countries: Country[];
|
|
154
178
|
selectCountry: (country: Country) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -83,6 +83,7 @@ interface PhoneInputLabels {
|
|
|
83
83
|
searchCountriesAriaLabel: string;
|
|
84
84
|
countryOptionsAriaLabel: string;
|
|
85
85
|
countryButtonAriaLabel: string;
|
|
86
|
+
countryResultsAnnouncement: string;
|
|
86
87
|
}
|
|
87
88
|
interface PhoneInputOptions {
|
|
88
89
|
defaultCountry?: string;
|
|
@@ -132,11 +133,32 @@ interface UsePhoneInputReturn extends PhoneInputState, PhoneInputActions {
|
|
|
132
133
|
inputProps: InputHTMLAttributes<HTMLInputElement> & {
|
|
133
134
|
ref: RefObject<HTMLInputElement | null>;
|
|
134
135
|
};
|
|
136
|
+
highlightedIndex: number;
|
|
137
|
+
activeCountry: Country | undefined;
|
|
138
|
+
countryResultsText: string;
|
|
139
|
+
setHighlightedIndex: (index: number) => void;
|
|
140
|
+
moveHighlight: (nextIndex: number) => void;
|
|
135
141
|
countryButtonProps: {
|
|
136
142
|
onClick: () => void;
|
|
137
143
|
'aria-expanded': boolean;
|
|
138
144
|
'aria-haspopup': 'listbox';
|
|
139
145
|
'aria-label': string;
|
|
146
|
+
'aria-controls': string;
|
|
147
|
+
};
|
|
148
|
+
countrySearchProps: {
|
|
149
|
+
role: 'combobox';
|
|
150
|
+
value: string;
|
|
151
|
+
onChange: (event: {
|
|
152
|
+
target: {
|
|
153
|
+
value: string;
|
|
154
|
+
};
|
|
155
|
+
}) => void;
|
|
156
|
+
'aria-expanded': boolean;
|
|
157
|
+
'aria-controls': string;
|
|
158
|
+
'aria-autocomplete': 'list';
|
|
159
|
+
'aria-activedescendant': string | undefined;
|
|
160
|
+
'aria-label': string;
|
|
161
|
+
placeholder: string;
|
|
140
162
|
};
|
|
141
163
|
countrySelectorProps: {
|
|
142
164
|
onClick: () => void;
|
|
@@ -145,10 +167,12 @@ interface UsePhoneInputReturn extends PhoneInputState, PhoneInputActions {
|
|
|
145
167
|
'aria-label': string;
|
|
146
168
|
};
|
|
147
169
|
dropdownProps: {
|
|
170
|
+
id: string;
|
|
148
171
|
role: 'listbox';
|
|
149
172
|
'aria-label': string;
|
|
150
|
-
'aria-activedescendant'?: string;
|
|
151
173
|
};
|
|
174
|
+
listboxId: string;
|
|
175
|
+
activeOptionId: string | undefined;
|
|
152
176
|
filteredCountries: Country[];
|
|
153
177
|
countries: Country[];
|
|
154
178
|
selectCountry: (country: Country) => void;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, useRef,
|
|
1
|
+
import { forwardRef, useRef, useCallback, useEffect, useImperativeHandle, useMemo, useState, useId, useLayoutEffect } from 'react';
|
|
2
2
|
import { getCountries, getCountryCallingCode, getExampleNumber, parsePhoneNumberFromString, AsYouType, validatePhoneNumberLength, isPossiblePhoneNumber, isValidPhoneNumber } from 'libphonenumber-js';
|
|
3
3
|
import examples from 'libphonenumber-js/mobile/examples';
|
|
4
4
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
@@ -2146,7 +2146,8 @@ var DEFAULT_PHONE_INPUT_LABELS = {
|
|
|
2146
2146
|
noCountriesFound: "No countries found",
|
|
2147
2147
|
searchCountriesAriaLabel: "Search countries",
|
|
2148
2148
|
countryOptionsAriaLabel: "Country options",
|
|
2149
|
-
countryButtonAriaLabel: "Open country selector"
|
|
2149
|
+
countryButtonAriaLabel: "Open country selector",
|
|
2150
|
+
countryResultsAnnouncement: "{count} countries"
|
|
2150
2151
|
};
|
|
2151
2152
|
var LABELS_BY_LANGUAGE = {
|
|
2152
2153
|
en: DEFAULT_PHONE_INPUT_LABELS,
|
|
@@ -2156,7 +2157,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2156
2157
|
noCountriesFound: "Aucun pays trouv\xE9",
|
|
2157
2158
|
searchCountriesAriaLabel: "Rechercher des pays",
|
|
2158
2159
|
countryOptionsAriaLabel: "Options de pays",
|
|
2159
|
-
countryButtonAriaLabel: "Ouvrir le s\xE9lecteur de pays"
|
|
2160
|
+
countryButtonAriaLabel: "Ouvrir le s\xE9lecteur de pays",
|
|
2161
|
+
countryResultsAnnouncement: "{count} pays"
|
|
2160
2162
|
},
|
|
2161
2163
|
de: {
|
|
2162
2164
|
selectCountry: "Land ausw\xE4hlen",
|
|
@@ -2164,7 +2166,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2164
2166
|
noCountriesFound: "Keine L\xE4nder gefunden",
|
|
2165
2167
|
searchCountriesAriaLabel: "L\xE4nder suchen",
|
|
2166
2168
|
countryOptionsAriaLabel: "L\xE4nderoptionen",
|
|
2167
|
-
countryButtonAriaLabel: "L\xE4nderauswahl \xF6ffnen"
|
|
2169
|
+
countryButtonAriaLabel: "L\xE4nderauswahl \xF6ffnen",
|
|
2170
|
+
countryResultsAnnouncement: "{count} L\xE4nder"
|
|
2168
2171
|
},
|
|
2169
2172
|
es: {
|
|
2170
2173
|
selectCountry: "Seleccionar pa\xEDs",
|
|
@@ -2172,7 +2175,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2172
2175
|
noCountriesFound: "No se encontraron pa\xEDses",
|
|
2173
2176
|
searchCountriesAriaLabel: "Buscar pa\xEDses",
|
|
2174
2177
|
countryOptionsAriaLabel: "Opciones de pa\xEDs",
|
|
2175
|
-
countryButtonAriaLabel: "Abrir selector de pa\xEDs"
|
|
2178
|
+
countryButtonAriaLabel: "Abrir selector de pa\xEDs",
|
|
2179
|
+
countryResultsAnnouncement: "{count} pa\xEDses"
|
|
2176
2180
|
},
|
|
2177
2181
|
pt: {
|
|
2178
2182
|
selectCountry: "Selecionar pa\xEDs",
|
|
@@ -2180,7 +2184,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2180
2184
|
noCountriesFound: "Nenhum pa\xEDs encontrado",
|
|
2181
2185
|
searchCountriesAriaLabel: "Pesquisar pa\xEDses",
|
|
2182
2186
|
countryOptionsAriaLabel: "Op\xE7\xF5es de pa\xEDs",
|
|
2183
|
-
countryButtonAriaLabel: "Abrir seletor de pa\xEDs"
|
|
2187
|
+
countryButtonAriaLabel: "Abrir seletor de pa\xEDs",
|
|
2188
|
+
countryResultsAnnouncement: "{count} pa\xEDses"
|
|
2184
2189
|
},
|
|
2185
2190
|
it: {
|
|
2186
2191
|
selectCountry: "Seleziona paese",
|
|
@@ -2188,7 +2193,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2188
2193
|
noCountriesFound: "Nessun paese trovato",
|
|
2189
2194
|
searchCountriesAriaLabel: "Cerca paesi",
|
|
2190
2195
|
countryOptionsAriaLabel: "Opzioni paese",
|
|
2191
|
-
countryButtonAriaLabel: "Apri selettore paese"
|
|
2196
|
+
countryButtonAriaLabel: "Apri selettore paese",
|
|
2197
|
+
countryResultsAnnouncement: "{count} paesi"
|
|
2192
2198
|
},
|
|
2193
2199
|
ja: {
|
|
2194
2200
|
selectCountry: "\u56FD\u3092\u9078\u629E",
|
|
@@ -2196,7 +2202,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2196
2202
|
noCountriesFound: "\u56FD\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
|
|
2197
2203
|
searchCountriesAriaLabel: "\u56FD\u3092\u691C\u7D22",
|
|
2198
2204
|
countryOptionsAriaLabel: "\u56FD\u306E\u5019\u88DC",
|
|
2199
|
-
countryButtonAriaLabel: "\u56FD\u306E\u30BB\u30EC\u30AF\u30BF\u30FC\u3092\u958B\u304F"
|
|
2205
|
+
countryButtonAriaLabel: "\u56FD\u306E\u30BB\u30EC\u30AF\u30BF\u30FC\u3092\u958B\u304F",
|
|
2206
|
+
countryResultsAnnouncement: "{count} \u4EF6\u306E\u56FD"
|
|
2200
2207
|
},
|
|
2201
2208
|
ko: {
|
|
2202
2209
|
selectCountry: "\uAD6D\uAC00 \uC120\uD0DD",
|
|
@@ -2204,7 +2211,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2204
2211
|
noCountriesFound: "\uAD6D\uAC00\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
2205
2212
|
searchCountriesAriaLabel: "\uAD6D\uAC00 \uAC80\uC0C9",
|
|
2206
2213
|
countryOptionsAriaLabel: "\uAD6D\uAC00 \uC635\uC158",
|
|
2207
|
-
countryButtonAriaLabel: "\uAD6D\uAC00 \uC120\uD0DD\uAE30 \uC5F4\uAE30"
|
|
2214
|
+
countryButtonAriaLabel: "\uAD6D\uAC00 \uC120\uD0DD\uAE30 \uC5F4\uAE30",
|
|
2215
|
+
countryResultsAnnouncement: "\uAD6D\uAC00 {count}\uAC1C"
|
|
2208
2216
|
},
|
|
2209
2217
|
zh: {
|
|
2210
2218
|
selectCountry: "\u9009\u62E9\u56FD\u5BB6",
|
|
@@ -2212,7 +2220,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2212
2220
|
noCountriesFound: "\u672A\u627E\u5230\u56FD\u5BB6",
|
|
2213
2221
|
searchCountriesAriaLabel: "\u641C\u7D22\u56FD\u5BB6",
|
|
2214
2222
|
countryOptionsAriaLabel: "\u56FD\u5BB6\u9009\u9879",
|
|
2215
|
-
countryButtonAriaLabel: "\u6253\u5F00\u56FD\u5BB6\u9009\u62E9\u5668"
|
|
2223
|
+
countryButtonAriaLabel: "\u6253\u5F00\u56FD\u5BB6\u9009\u62E9\u5668",
|
|
2224
|
+
countryResultsAnnouncement: "{count} \u4E2A\u56FD\u5BB6"
|
|
2216
2225
|
},
|
|
2217
2226
|
ar: {
|
|
2218
2227
|
selectCountry: "\u0627\u062E\u062A\u0631 \u0627\u0644\u062F\u0648\u0644\u0629",
|
|
@@ -2220,7 +2229,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2220
2229
|
noCountriesFound: "\u0644\u0645 \u064A\u062A\u0645 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u062F\u0648\u0644",
|
|
2221
2230
|
searchCountriesAriaLabel: "\u0627\u0628\u062D\u062B \u0639\u0646 \u0627\u0644\u062F\u0648\u0644",
|
|
2222
2231
|
countryOptionsAriaLabel: "\u062E\u064A\u0627\u0631\u0627\u062A \u0627\u0644\u062F\u0648\u0644",
|
|
2223
|
-
countryButtonAriaLabel: "\u0627\u0641\u062A\u062D \u0645\u062D\u062F\u062F \u0627\u0644\u062F\u0648\u0644\u0629"
|
|
2232
|
+
countryButtonAriaLabel: "\u0627\u0641\u062A\u062D \u0645\u062D\u062F\u062F \u0627\u0644\u062F\u0648\u0644\u0629",
|
|
2233
|
+
countryResultsAnnouncement: "{count} \u062F\u0648\u0644\u0629"
|
|
2224
2234
|
},
|
|
2225
2235
|
hi: {
|
|
2226
2236
|
selectCountry: "\u0926\u0947\u0936 \u091A\u0941\u0928\u0947\u0902",
|
|
@@ -2228,7 +2238,8 @@ var LABELS_BY_LANGUAGE = {
|
|
|
2228
2238
|
noCountriesFound: "\u0915\u094B\u0908 \u0926\u0947\u0936 \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E",
|
|
2229
2239
|
searchCountriesAriaLabel: "\u0926\u0947\u0936 \u0916\u094B\u091C\u0947\u0902",
|
|
2230
2240
|
countryOptionsAriaLabel: "\u0926\u0947\u0936 \u0935\u093F\u0915\u0932\u094D\u092A",
|
|
2231
|
-
countryButtonAriaLabel: "\u0926\u0947\u0936 \u091A\u092F\u0928 \u0916\u094B\u0932\u0947\u0902"
|
|
2241
|
+
countryButtonAriaLabel: "\u0926\u0947\u0936 \u091A\u092F\u0928 \u0916\u094B\u0932\u0947\u0902",
|
|
2242
|
+
countryResultsAnnouncement: "{count} \u0926\u0947\u0936"
|
|
2232
2243
|
}
|
|
2233
2244
|
};
|
|
2234
2245
|
function getPrimaryLanguage(locale) {
|
|
@@ -2570,6 +2581,8 @@ function usePhoneInput(options = {}) {
|
|
|
2570
2581
|
const [country, setCountry] = useState(initialCountry);
|
|
2571
2582
|
const [isOpen, setIsOpen] = useState(false);
|
|
2572
2583
|
const [searchQuery, setSearchQuery] = useState("");
|
|
2584
|
+
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
|
2585
|
+
const listboxId = useId();
|
|
2573
2586
|
const phone = isControlled ? controlledValue : internalPhone;
|
|
2574
2587
|
const getOutputCountry = useCallback(
|
|
2575
2588
|
(nextCountry) => localizeCountry(nextCountry, locale),
|
|
@@ -2640,6 +2653,26 @@ function usePhoneInput(options = {}) {
|
|
|
2640
2653
|
() => filterCountries(localizedCountries, searchQuery, preferredCountries),
|
|
2641
2654
|
[localizedCountries, searchQuery, preferredCountries]
|
|
2642
2655
|
);
|
|
2656
|
+
useEffect(() => {
|
|
2657
|
+
setHighlightedIndex(0);
|
|
2658
|
+
}, [searchQuery]);
|
|
2659
|
+
useEffect(() => {
|
|
2660
|
+
setHighlightedIndex((current) => {
|
|
2661
|
+
if (filteredCountries.length === 0) {
|
|
2662
|
+
return 0;
|
|
2663
|
+
}
|
|
2664
|
+
return current >= filteredCountries.length ? filteredCountries.length - 1 : current;
|
|
2665
|
+
});
|
|
2666
|
+
}, [filteredCountries.length]);
|
|
2667
|
+
const wasOpenRef = useRef(false);
|
|
2668
|
+
useEffect(() => {
|
|
2669
|
+
if (isOpen && !wasOpenRef.current) {
|
|
2670
|
+
const selectedIndex = filteredCountries.findIndex((candidate) => candidate.code === country?.code);
|
|
2671
|
+
setHighlightedIndex(selectedIndex >= 0 ? selectedIndex : 0);
|
|
2672
|
+
}
|
|
2673
|
+
wasOpenRef.current = isOpen;
|
|
2674
|
+
}, [isOpen, filteredCountries, country?.code]);
|
|
2675
|
+
const activeCountry = filteredCountries[highlightedIndex];
|
|
2643
2676
|
useIsomorphicLayoutEffect(() => {
|
|
2644
2677
|
const nextDigitIndex = pendingCaretDigitIndexRef.current;
|
|
2645
2678
|
const input = inputRef.current;
|
|
@@ -2752,11 +2785,22 @@ function usePhoneInput(options = {}) {
|
|
|
2752
2785
|
(code) => `phone-input-country-${code}`,
|
|
2753
2786
|
[]
|
|
2754
2787
|
);
|
|
2788
|
+
const activeOptionId = activeCountry ? getCountryOptionId(activeCountry.code) : void 0;
|
|
2789
|
+
const countryResultsText = filteredCountries.length === 0 ? resolvedLabels.noCountriesFound : resolvedLabels.countryResultsAnnouncement.replace("{count}", String(filteredCountries.length));
|
|
2790
|
+
const moveHighlight = useCallback(
|
|
2791
|
+
(nextIndex) => {
|
|
2792
|
+
const lastIndex = filteredCountries.length - 1;
|
|
2793
|
+
setHighlightedIndex(lastIndex < 0 ? 0 : Math.min(Math.max(nextIndex, 0), lastIndex));
|
|
2794
|
+
},
|
|
2795
|
+
[filteredCountries.length]
|
|
2796
|
+
);
|
|
2755
2797
|
const getCountryOptionProps = useCallback(
|
|
2756
2798
|
(optionCountry, index) => ({
|
|
2757
2799
|
id: getCountryOptionId(optionCountry.code),
|
|
2758
2800
|
role: "option",
|
|
2759
|
-
|
|
2801
|
+
// Selection follows the active option in a single-select listbox, so this
|
|
2802
|
+
// tracks the highlight rather than the committed country.
|
|
2803
|
+
"aria-selected": index === highlightedIndex,
|
|
2760
2804
|
onClick: () => selectCountry(optionCountry),
|
|
2761
2805
|
onKeyDown: (event) => {
|
|
2762
2806
|
if (event.key === "Enter" || event.key === " ") {
|
|
@@ -2770,7 +2814,7 @@ function usePhoneInput(options = {}) {
|
|
|
2770
2814
|
},
|
|
2771
2815
|
tabIndex: index === 0 ? 0 : -1
|
|
2772
2816
|
}),
|
|
2773
|
-
[closeDropdown,
|
|
2817
|
+
[closeDropdown, highlightedIndex, getCountryOptionId, selectCountry]
|
|
2774
2818
|
);
|
|
2775
2819
|
return {
|
|
2776
2820
|
// State
|
|
@@ -2785,6 +2829,9 @@ function usePhoneInput(options = {}) {
|
|
|
2785
2829
|
searchQuery,
|
|
2786
2830
|
labels: resolvedLabels,
|
|
2787
2831
|
formattedValue: formattedPhone,
|
|
2832
|
+
highlightedIndex,
|
|
2833
|
+
activeCountry,
|
|
2834
|
+
countryResultsText,
|
|
2788
2835
|
// Actions
|
|
2789
2836
|
setPhone,
|
|
2790
2837
|
setValue: setPhone,
|
|
@@ -2796,6 +2843,8 @@ function usePhoneInput(options = {}) {
|
|
|
2796
2843
|
closeDropdown,
|
|
2797
2844
|
close: closeDropdown,
|
|
2798
2845
|
setSearchQuery,
|
|
2846
|
+
setHighlightedIndex,
|
|
2847
|
+
moveHighlight,
|
|
2799
2848
|
clear,
|
|
2800
2849
|
// Props
|
|
2801
2850
|
inputProps: {
|
|
@@ -2814,7 +2863,21 @@ function usePhoneInput(options = {}) {
|
|
|
2814
2863
|
onClick: toggleDropdown,
|
|
2815
2864
|
"aria-expanded": isOpen,
|
|
2816
2865
|
"aria-haspopup": "listbox",
|
|
2817
|
-
"aria-label": countryButtonAriaLabel
|
|
2866
|
+
"aria-label": countryButtonAriaLabel,
|
|
2867
|
+
"aria-controls": listboxId
|
|
2868
|
+
},
|
|
2869
|
+
// The search field is the combobox: it keeps focus while the arrow keys
|
|
2870
|
+
// move `aria-activedescendant` through the listbox.
|
|
2871
|
+
countrySearchProps: {
|
|
2872
|
+
role: "combobox",
|
|
2873
|
+
value: searchQuery,
|
|
2874
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
2875
|
+
"aria-expanded": isOpen,
|
|
2876
|
+
"aria-controls": listboxId,
|
|
2877
|
+
"aria-autocomplete": "list",
|
|
2878
|
+
"aria-activedescendant": activeOptionId,
|
|
2879
|
+
"aria-label": resolvedLabels.searchCountriesAriaLabel,
|
|
2880
|
+
placeholder: resolvedLabels.countrySearchPlaceholder
|
|
2818
2881
|
},
|
|
2819
2882
|
countrySelectorProps: {
|
|
2820
2883
|
onClick: toggleDropdown,
|
|
@@ -2823,9 +2886,12 @@ function usePhoneInput(options = {}) {
|
|
|
2823
2886
|
"aria-label": countryButtonAriaLabel
|
|
2824
2887
|
},
|
|
2825
2888
|
dropdownProps: {
|
|
2889
|
+
id: listboxId,
|
|
2826
2890
|
role: "listbox",
|
|
2827
2891
|
"aria-label": resolvedLabels.countryOptionsAriaLabel
|
|
2828
2892
|
},
|
|
2893
|
+
listboxId,
|
|
2894
|
+
activeOptionId,
|
|
2829
2895
|
getCountryOptionId,
|
|
2830
2896
|
filteredCountries,
|
|
2831
2897
|
countries: filteredCountries,
|
|
@@ -2860,24 +2926,25 @@ var PhoneInput = forwardRef(
|
|
|
2860
2926
|
const inputRef = useRef(null);
|
|
2861
2927
|
const optionRefs = useRef([]);
|
|
2862
2928
|
const countryButtonRef = useRef(null);
|
|
2863
|
-
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
|
2864
|
-
const listboxId = useId();
|
|
2865
2929
|
const {
|
|
2866
2930
|
inputProps,
|
|
2867
2931
|
countryButtonProps,
|
|
2932
|
+
countrySearchProps,
|
|
2868
2933
|
dropdownProps,
|
|
2869
2934
|
country,
|
|
2870
2935
|
filteredCountries,
|
|
2871
2936
|
isOpen,
|
|
2872
2937
|
isValid,
|
|
2873
|
-
searchQuery,
|
|
2874
|
-
setSearchQuery,
|
|
2875
2938
|
setCountry,
|
|
2876
2939
|
selectCountry,
|
|
2877
2940
|
clear,
|
|
2878
2941
|
openDropdown,
|
|
2879
2942
|
closeDropdown,
|
|
2880
2943
|
getCountryOptionId,
|
|
2944
|
+
highlightedIndex,
|
|
2945
|
+
setHighlightedIndex,
|
|
2946
|
+
moveHighlight,
|
|
2947
|
+
countryResultsText,
|
|
2881
2948
|
labels
|
|
2882
2949
|
} = usePhoneInput({
|
|
2883
2950
|
value,
|
|
@@ -2907,7 +2974,6 @@ var PhoneInput = forwardRef(
|
|
|
2907
2974
|
}, []);
|
|
2908
2975
|
const handleCountryClick = useCallback((c) => {
|
|
2909
2976
|
selectCountry(c);
|
|
2910
|
-
setHighlightedIndex(0);
|
|
2911
2977
|
returnFocusToButton();
|
|
2912
2978
|
}, [selectCountry, returnFocusToButton]);
|
|
2913
2979
|
const handleCountryKeyDown = useCallback((e, c, index) => {
|
|
@@ -2916,7 +2982,6 @@ var PhoneInput = forwardRef(
|
|
|
2916
2982
|
case " ":
|
|
2917
2983
|
e.preventDefault();
|
|
2918
2984
|
selectCountry(c);
|
|
2919
|
-
setHighlightedIndex(0);
|
|
2920
2985
|
returnFocusToButton();
|
|
2921
2986
|
break;
|
|
2922
2987
|
case "ArrowDown":
|
|
@@ -2953,7 +3018,7 @@ var PhoneInput = forwardRef(
|
|
|
2953
3018
|
returnFocusToButton();
|
|
2954
3019
|
break;
|
|
2955
3020
|
}
|
|
2956
|
-
}, [selectCountry, filteredCountries.length, closeDropdown, returnFocusToButton]);
|
|
3021
|
+
}, [selectCountry, filteredCountries.length, closeDropdown, returnFocusToButton, setHighlightedIndex]);
|
|
2957
3022
|
useEffect(() => {
|
|
2958
3023
|
if (!isOpen) {
|
|
2959
3024
|
return;
|
|
@@ -2978,16 +3043,14 @@ var PhoneInput = forwardRef(
|
|
|
2978
3043
|
};
|
|
2979
3044
|
}, [isOpen, closeDropdown]);
|
|
2980
3045
|
useEffect(() => {
|
|
2981
|
-
if (
|
|
2982
|
-
if (highlightedIndex !== 0) {
|
|
2983
|
-
setHighlightedIndex(0);
|
|
2984
|
-
}
|
|
3046
|
+
if (!isOpen || !searchable) {
|
|
2985
3047
|
return;
|
|
2986
3048
|
}
|
|
2987
|
-
|
|
2988
|
-
|
|
3049
|
+
const activeOption = optionRefs.current[highlightedIndex];
|
|
3050
|
+
if (typeof activeOption?.scrollIntoView === "function") {
|
|
3051
|
+
activeOption.scrollIntoView({ block: "nearest" });
|
|
2989
3052
|
}
|
|
2990
|
-
}, [
|
|
3053
|
+
}, [isOpen, searchable, highlightedIndex]);
|
|
2991
3054
|
useImperativeHandle(ref, () => ({
|
|
2992
3055
|
focus,
|
|
2993
3056
|
blur,
|
|
@@ -2998,16 +3061,39 @@ var PhoneInput = forwardRef(
|
|
|
2998
3061
|
close: closeDropdown
|
|
2999
3062
|
}));
|
|
3000
3063
|
const handleSearchKeyDown = useCallback((e) => {
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3064
|
+
switch (e.key) {
|
|
3065
|
+
case "ArrowDown":
|
|
3066
|
+
e.preventDefault();
|
|
3067
|
+
moveHighlight(highlightedIndex + 1);
|
|
3068
|
+
break;
|
|
3069
|
+
case "ArrowUp":
|
|
3070
|
+
e.preventDefault();
|
|
3071
|
+
moveHighlight(highlightedIndex - 1);
|
|
3072
|
+
break;
|
|
3073
|
+
case "Home":
|
|
3074
|
+
e.preventDefault();
|
|
3075
|
+
moveHighlight(0);
|
|
3076
|
+
break;
|
|
3077
|
+
case "End":
|
|
3078
|
+
e.preventDefault();
|
|
3079
|
+
moveHighlight(filteredCountries.length - 1);
|
|
3080
|
+
break;
|
|
3081
|
+
case "Enter": {
|
|
3082
|
+
const active = filteredCountries[highlightedIndex];
|
|
3083
|
+
if (active) {
|
|
3084
|
+
e.preventDefault();
|
|
3085
|
+
selectCountry(active);
|
|
3086
|
+
returnFocusToButton();
|
|
3087
|
+
}
|
|
3088
|
+
break;
|
|
3089
|
+
}
|
|
3090
|
+
case "Escape":
|
|
3091
|
+
e.preventDefault();
|
|
3092
|
+
closeDropdown();
|
|
3093
|
+
returnFocusToButton();
|
|
3094
|
+
break;
|
|
3009
3095
|
}
|
|
3010
|
-
}, [closeDropdown, returnFocusToButton]);
|
|
3096
|
+
}, [closeDropdown, returnFocusToButton, moveHighlight, highlightedIndex, filteredCountries, selectCountry]);
|
|
3011
3097
|
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: containerClassName, "data-valid": isValid, children: [
|
|
3012
3098
|
/* @__PURE__ */ jsxs(
|
|
3013
3099
|
"button",
|
|
@@ -3018,7 +3104,6 @@ var PhoneInput = forwardRef(
|
|
|
3018
3104
|
className: selectorClassName,
|
|
3019
3105
|
disabled,
|
|
3020
3106
|
tabIndex: disabled ? -1 : 0,
|
|
3021
|
-
"aria-controls": listboxId,
|
|
3022
3107
|
children: [
|
|
3023
3108
|
country ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3024
3109
|
/* @__PURE__ */ jsx("span", { className: "phone-input-flag", children: country.flag }),
|
|
@@ -3047,22 +3132,26 @@ var PhoneInput = forwardRef(
|
|
|
3047
3132
|
searchable && /* @__PURE__ */ jsx("div", { className: "phone-input-search", children: /* @__PURE__ */ jsx(
|
|
3048
3133
|
"input",
|
|
3049
3134
|
{
|
|
3135
|
+
...countrySearchProps,
|
|
3050
3136
|
type: "text",
|
|
3051
|
-
value: searchQuery,
|
|
3052
|
-
onChange: (e) => setSearchQuery(e.target.value),
|
|
3053
3137
|
onKeyDown: handleSearchKeyDown,
|
|
3054
|
-
|
|
3055
|
-
autoFocus: true,
|
|
3056
|
-
"aria-controls": listboxId,
|
|
3057
|
-
"aria-label": labels.searchCountriesAriaLabel
|
|
3138
|
+
autoFocus: true
|
|
3058
3139
|
}
|
|
3059
3140
|
) }),
|
|
3141
|
+
/* @__PURE__ */ jsx(
|
|
3142
|
+
"div",
|
|
3143
|
+
{
|
|
3144
|
+
role: "status",
|
|
3145
|
+
"aria-live": "polite",
|
|
3146
|
+
style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0 0 0 0)", whiteSpace: "nowrap" },
|
|
3147
|
+
children: countryResultsText
|
|
3148
|
+
}
|
|
3149
|
+
),
|
|
3060
3150
|
/* @__PURE__ */ jsxs(
|
|
3061
3151
|
"ul",
|
|
3062
3152
|
{
|
|
3063
3153
|
...dropdownProps,
|
|
3064
3154
|
className: "phone-input-country-list",
|
|
3065
|
-
id: listboxId,
|
|
3066
3155
|
children: [
|
|
3067
3156
|
filteredCountries.map((c, index) => /* @__PURE__ */ jsxs(
|
|
3068
3157
|
"li",
|
|
@@ -3072,12 +3161,12 @@ var PhoneInput = forwardRef(
|
|
|
3072
3161
|
optionRefs.current[index] = element;
|
|
3073
3162
|
},
|
|
3074
3163
|
role: "option",
|
|
3075
|
-
"aria-selected":
|
|
3164
|
+
"aria-selected": index === highlightedIndex,
|
|
3076
3165
|
className: `phone-input-country-option ${c.code === country?.code ? "selected" : ""} ${index === highlightedIndex ? "highlighted" : ""}`,
|
|
3077
3166
|
onClick: () => handleCountryClick(c),
|
|
3078
3167
|
onKeyDown: (e) => handleCountryKeyDown(e, c, index),
|
|
3079
3168
|
onMouseEnter: () => setHighlightedIndex(index),
|
|
3080
|
-
tabIndex: index === highlightedIndex ? 0 : -1,
|
|
3169
|
+
tabIndex: searchable ? -1 : index === highlightedIndex ? 0 : -1,
|
|
3081
3170
|
children: [
|
|
3082
3171
|
/* @__PURE__ */ jsx("span", { className: "phone-input-flag", children: c.flag }),
|
|
3083
3172
|
/* @__PURE__ */ jsx("span", { className: "phone-input-country-name", children: getCountryDisplayName(c) }),
|