@input-kit/phone 0.3.0 → 0.4.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 +8 -2
- package/dist/index.cjs +44 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +44 -16
- package/dist/index.js.map +1 -1
- package/package.json +90 -85
package/dist/index.js
CHANGED
|
@@ -388,9 +388,11 @@ function addDialCode(phone, country) {
|
|
|
388
388
|
if (!normalized) return "";
|
|
389
389
|
if (normalized === "+") return "";
|
|
390
390
|
if (normalized.startsWith("+")) return normalized;
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
391
|
+
const parsed = parsePhoneNumberFromString(normalized, getCountryCode(country));
|
|
392
|
+
if (parsed) {
|
|
393
|
+
return parsed.number;
|
|
394
|
+
}
|
|
395
|
+
return `${country.dialCode}${cleanPhone(normalized)}`;
|
|
394
396
|
}
|
|
395
397
|
function removeDialCode(phone, country) {
|
|
396
398
|
if (!country) return phone;
|
|
@@ -683,13 +685,21 @@ function usePhoneInput(options = {}) {
|
|
|
683
685
|
() => validatePhoneNumber(phone, country, required, validator),
|
|
684
686
|
[phone, country, required, validator]
|
|
685
687
|
);
|
|
688
|
+
const onValidationChangeRef = useRef(onValidationChange);
|
|
689
|
+
useIsomorphicLayoutEffect(() => {
|
|
690
|
+
onValidationChangeRef.current = onValidationChange;
|
|
691
|
+
});
|
|
686
692
|
useEffect(() => {
|
|
687
|
-
|
|
688
|
-
}, [validation
|
|
693
|
+
onValidationChangeRef.current?.(validation);
|
|
694
|
+
}, [validation]);
|
|
689
695
|
const localizedCountry = useMemo(
|
|
690
696
|
() => localizeCountry(country, locale),
|
|
691
697
|
[country, locale]
|
|
692
698
|
);
|
|
699
|
+
const countryButtonAriaLabel = useMemo(
|
|
700
|
+
() => localizedCountry ? `${resolvedLabels.countryButtonAriaLabel}, ${localizedCountry.name} ${localizedCountry.dialCode}` : resolvedLabels.countryButtonAriaLabel,
|
|
701
|
+
[localizedCountry, resolvedLabels.countryButtonAriaLabel]
|
|
702
|
+
);
|
|
693
703
|
const filteredCountries = useMemo(
|
|
694
704
|
() => filterCountries(localizedCountries, searchQuery, preferredCountries),
|
|
695
705
|
[localizedCountries, searchQuery, preferredCountries]
|
|
@@ -739,16 +749,20 @@ function usePhoneInput(options = {}) {
|
|
|
739
749
|
(selectedCountry) => {
|
|
740
750
|
const rawCountry = getCountryByCode(selectedCountry.code) ?? selectedCountry;
|
|
741
751
|
manualCountrySelectionRef.current = true;
|
|
752
|
+
const rewritten = phone.trim().startsWith("+") ? addDialCode(removeDialCode(phone, country), rawCountry) : phone;
|
|
753
|
+
if (rewritten !== phone && !isControlled) {
|
|
754
|
+
setInternalPhone(rewritten);
|
|
755
|
+
}
|
|
742
756
|
setCountry(rawCountry);
|
|
743
757
|
setIsOpen(false);
|
|
744
758
|
setSearchQuery("");
|
|
745
759
|
onCountryChange?.(getOutputCountry(rawCountry));
|
|
746
760
|
onChange?.(
|
|
747
|
-
includeDialCode ? addDialCode(
|
|
761
|
+
includeDialCode ? addDialCode(rewritten, rawCountry) : rewritten,
|
|
748
762
|
getOutputCountry(rawCountry)
|
|
749
763
|
);
|
|
750
764
|
},
|
|
751
|
-
[phone, onChange, onCountryChange, includeDialCode, getOutputCountry]
|
|
765
|
+
[phone, country, isControlled, onChange, onCountryChange, includeDialCode, getOutputCountry]
|
|
752
766
|
);
|
|
753
767
|
const toggleDropdown = useCallback(() => {
|
|
754
768
|
setIsOpen((prev) => !prev);
|
|
@@ -774,18 +788,23 @@ function usePhoneInput(options = {}) {
|
|
|
774
788
|
const rawValue = event.target.value;
|
|
775
789
|
const caretPosition = event.target.selectionStart ?? rawValue.length;
|
|
776
790
|
const unformatted = rawValue.trim().startsWith("+") ? `+${rawValue.replace(/\D/g, "")}` : unformatPhone(rawValue);
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
const
|
|
791
|
+
const isInternationalEntry = unformatted.startsWith("+") || unformatted.startsWith("00");
|
|
792
|
+
if (!isInternationalEntry && cleanPhone(unformatted).length > cleanPhone(phone).length && isPhoneTooLong(unformatted, country)) {
|
|
793
|
+
const truncated = limitInputLength(unformatted, country);
|
|
794
|
+
const truncatedDisplay = formatPhone(truncated, country);
|
|
795
|
+
event.target.value = truncatedDisplay;
|
|
796
|
+
const restoredCaret = Math.min(Math.max(caretPosition - 1, 0), truncatedDisplay.length);
|
|
780
797
|
if (typeof event.target.setSelectionRange === "function") {
|
|
781
798
|
event.target.setSelectionRange(restoredCaret, restoredCaret);
|
|
782
799
|
}
|
|
800
|
+
pendingCaretDigitIndexRef.current = countDigitsBeforePosition(truncatedDisplay, restoredCaret);
|
|
801
|
+
setPhone(truncated);
|
|
783
802
|
return;
|
|
784
803
|
}
|
|
785
804
|
pendingCaretDigitIndexRef.current = countDigitsBeforePosition(rawValue, caretPosition);
|
|
786
805
|
setPhone(unformatted);
|
|
787
806
|
},
|
|
788
|
-
[setPhone, phone, country
|
|
807
|
+
[setPhone, phone, country]
|
|
789
808
|
);
|
|
790
809
|
const handleFocus = useCallback(() => {
|
|
791
810
|
onFocus?.();
|
|
@@ -859,13 +878,13 @@ function usePhoneInput(options = {}) {
|
|
|
859
878
|
onClick: toggleDropdown,
|
|
860
879
|
"aria-expanded": isOpen,
|
|
861
880
|
"aria-haspopup": "listbox",
|
|
862
|
-
"aria-label":
|
|
881
|
+
"aria-label": countryButtonAriaLabel
|
|
863
882
|
},
|
|
864
883
|
countrySelectorProps: {
|
|
865
884
|
onClick: toggleDropdown,
|
|
866
885
|
"aria-expanded": isOpen,
|
|
867
886
|
"aria-haspopup": "listbox",
|
|
868
|
-
"aria-label":
|
|
887
|
+
"aria-label": countryButtonAriaLabel
|
|
869
888
|
},
|
|
870
889
|
dropdownProps: {
|
|
871
890
|
role: "listbox",
|
|
@@ -904,6 +923,7 @@ var PhoneInput = forwardRef(
|
|
|
904
923
|
const containerRef = useRef(null);
|
|
905
924
|
const inputRef = useRef(null);
|
|
906
925
|
const optionRefs = useRef([]);
|
|
926
|
+
const countryButtonRef = useRef(null);
|
|
907
927
|
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
|
908
928
|
const listboxId = useId();
|
|
909
929
|
const {
|
|
@@ -946,10 +966,14 @@ var PhoneInput = forwardRef(
|
|
|
946
966
|
const blur = useCallback(() => {
|
|
947
967
|
inputRef.current?.blur();
|
|
948
968
|
}, []);
|
|
969
|
+
const returnFocusToButton = useCallback(() => {
|
|
970
|
+
countryButtonRef.current?.focus();
|
|
971
|
+
}, []);
|
|
949
972
|
const handleCountryClick = useCallback((c) => {
|
|
950
973
|
selectCountry(c);
|
|
951
974
|
setHighlightedIndex(0);
|
|
952
|
-
|
|
975
|
+
returnFocusToButton();
|
|
976
|
+
}, [selectCountry, returnFocusToButton]);
|
|
953
977
|
const handleCountryKeyDown = useCallback((e, c, index) => {
|
|
954
978
|
switch (e.key) {
|
|
955
979
|
case "Enter":
|
|
@@ -957,6 +981,7 @@ var PhoneInput = forwardRef(
|
|
|
957
981
|
e.preventDefault();
|
|
958
982
|
selectCountry(c);
|
|
959
983
|
setHighlightedIndex(0);
|
|
984
|
+
returnFocusToButton();
|
|
960
985
|
break;
|
|
961
986
|
case "ArrowDown":
|
|
962
987
|
e.preventDefault();
|
|
@@ -989,9 +1014,10 @@ var PhoneInput = forwardRef(
|
|
|
989
1014
|
case "Escape":
|
|
990
1015
|
e.preventDefault();
|
|
991
1016
|
closeDropdown();
|
|
1017
|
+
returnFocusToButton();
|
|
992
1018
|
break;
|
|
993
1019
|
}
|
|
994
|
-
}, [selectCountry, filteredCountries.length, closeDropdown]);
|
|
1020
|
+
}, [selectCountry, filteredCountries.length, closeDropdown, returnFocusToButton]);
|
|
995
1021
|
useEffect(() => {
|
|
996
1022
|
if (!isOpen) {
|
|
997
1023
|
return;
|
|
@@ -1043,13 +1069,15 @@ var PhoneInput = forwardRef(
|
|
|
1043
1069
|
} else if (e.key === "Escape") {
|
|
1044
1070
|
e.preventDefault();
|
|
1045
1071
|
closeDropdown();
|
|
1072
|
+
returnFocusToButton();
|
|
1046
1073
|
}
|
|
1047
|
-
}, [closeDropdown]);
|
|
1074
|
+
}, [closeDropdown, returnFocusToButton]);
|
|
1048
1075
|
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: containerClassName, "data-valid": isValid, children: [
|
|
1049
1076
|
/* @__PURE__ */ jsxs(
|
|
1050
1077
|
"button",
|
|
1051
1078
|
{
|
|
1052
1079
|
...countryButtonProps,
|
|
1080
|
+
ref: countryButtonRef,
|
|
1053
1081
|
type: "button",
|
|
1054
1082
|
className: selectorClassName,
|
|
1055
1083
|
disabled,
|