@trackunit/react-form-components 0.0.142 → 0.0.144
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/index.cjs.js +83 -58
- package/index.esm.js +84 -59
- package/package.json +1 -1
- package/src/components/PhoneInput/PhoneInput.d.ts +16 -7
- package/src/utilities/usePhoneInput.d.ts +13 -49
package/index.cjs.js
CHANGED
|
@@ -6294,54 +6294,43 @@ const getPhoneNumberWithPlus = (phoneNumber) => {
|
|
|
6294
6294
|
* A custom hook for managing phone number input state and validation.
|
|
6295
6295
|
*
|
|
6296
6296
|
* @returns {object} - An object containing state values and event handler functions.
|
|
6297
|
-
* @property {
|
|
6298
|
-
* @property {
|
|
6299
|
-
* @property {
|
|
6300
|
-
*
|
|
6301
|
-
* @property {Function} handleCountryCodeChange - A function for handling changes to the country code input.
|
|
6302
|
-
* @property {Function} handlePhoneNumberChange - A function for handling changes to the phone number input.
|
|
6297
|
+
* @property {Function} getIsCountryCodeInvalid - A function for check if country code is valid
|
|
6298
|
+
* @property {Function} getIsNumberInvalid- A function for check if number part of phone number is valid
|
|
6299
|
+
* @property {Function} getIsPhoneNumberValid- A function for check if phone number is valid
|
|
6300
|
+
* @property {Function} getPhoneNumber - A function for get formatted phone number with country code and plus sign
|
|
6303
6301
|
* @property {string} combinedValue - The combined country code and phone number value.
|
|
6304
6302
|
*/
|
|
6305
|
-
const usePhoneInput = (
|
|
6306
|
-
const
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
const [isPhoneNumberInvalid, setIsPhoneNumberInvalid] = React.useState(false);
|
|
6310
|
-
const [isCombinedValueInvalid, setIsCombinedValueInvalid] = React.useState(false);
|
|
6311
|
-
const [combinedValue, setCombinedValue] = React.useState(value !== null && value !== void 0 ? value : "");
|
|
6312
|
-
React.useEffect(() => {
|
|
6313
|
-
var _a, _b;
|
|
6314
|
-
if (value && ((!countryCode && !phoneNumber) || !combinedValue)) {
|
|
6315
|
-
const safePhoneNumber = getPhoneNumberWithPlus(value);
|
|
6316
|
-
const number = parsePhoneNumber(safePhoneNumber);
|
|
6317
|
-
setCountryCode((_a = number === null || number === void 0 ? void 0 : number.countryCallingCode.toString()) !== null && _a !== void 0 ? _a : "");
|
|
6318
|
-
setPhoneNumber((_b = number === null || number === void 0 ? void 0 : number.nationalNumber.toString()) !== null && _b !== void 0 ? _b : "");
|
|
6319
|
-
setCombinedValue(`${countryCode}${phoneNumber}`);
|
|
6320
|
-
combinedValue && setIsCombinedValueInvalid(isPossiblePhoneNumber(combinedValue.toString()));
|
|
6303
|
+
const usePhoneInput = () => {
|
|
6304
|
+
const getIsCountryCodeInvalid = (code) => {
|
|
6305
|
+
if (code) {
|
|
6306
|
+
return false;
|
|
6321
6307
|
}
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6308
|
+
return true;
|
|
6309
|
+
};
|
|
6310
|
+
const getIsNumberInvalid = (number) => {
|
|
6311
|
+
if (number) {
|
|
6312
|
+
return false;
|
|
6313
|
+
}
|
|
6314
|
+
return true;
|
|
6315
|
+
};
|
|
6316
|
+
const getIsPhoneNumberInvalid = (phone) => {
|
|
6317
|
+
if (phone) {
|
|
6318
|
+
const normalized = getPhoneNumberWithPlus(phone.toString());
|
|
6319
|
+
return isPossiblePhoneNumber(normalized);
|
|
6320
|
+
}
|
|
6321
|
+
return true;
|
|
6329
6322
|
};
|
|
6330
|
-
const
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6323
|
+
const getPhoneNumber = ({ country, phone }) => {
|
|
6324
|
+
if (country) {
|
|
6325
|
+
return getPhoneNumberWithPlus(`${country}${phone || ""}`);
|
|
6326
|
+
}
|
|
6327
|
+
return phone || "";
|
|
6335
6328
|
};
|
|
6336
6329
|
return {
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
handleCountryCodeChange,
|
|
6342
|
-
handlePhoneNumberChange,
|
|
6343
|
-
combinedValue,
|
|
6344
|
-
isCombinedValueInvalid,
|
|
6330
|
+
getIsCountryCodeInvalid,
|
|
6331
|
+
getIsNumberInvalid,
|
|
6332
|
+
getIsPhoneNumberInvalid,
|
|
6333
|
+
getPhoneNumber,
|
|
6345
6334
|
};
|
|
6346
6335
|
};
|
|
6347
6336
|
|
|
@@ -14503,7 +14492,7 @@ const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, onChange
|
|
|
14503
14492
|
const filteredCodes = countryCodes.filter(code => {
|
|
14504
14493
|
return !(excludedCountries === null || excludedCountries === void 0 ? void 0 : excludedCountries.some(excludedCode => excludedCode.value === code.value));
|
|
14505
14494
|
});
|
|
14506
|
-
return (jsxRuntime.jsx(Select, { dataTestId: dataTestId, className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value }) => value === `+${countryCode}`), placeholder: placeholder, hasError: isCountryCodeMissing || isInvalid, maxMenuHeight: 200, onChange: onChange, disabled: disabled, readOnly: readOnly, onBlur: onBlur, menuIsOpen: readOnly ? false : undefined }));
|
|
14495
|
+
return (jsxRuntime.jsx(Select, { dataTestId: dataTestId, className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value }) => value === `+${countryCode}`), placeholder: placeholder, hasError: isCountryCodeMissing || isInvalid, maxMenuHeight: 200, onChange: onChange, disabled: disabled, readOnly: readOnly, onBlur: onBlur, closeMenuOnSelect: true, menuIsOpen: readOnly ? false : undefined }));
|
|
14507
14496
|
};
|
|
14508
14497
|
|
|
14509
14498
|
/**
|
|
@@ -14517,9 +14506,43 @@ const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, onChange
|
|
|
14517
14506
|
* @returns {JSX.Element} - The PhoneInput component.
|
|
14518
14507
|
*/
|
|
14519
14508
|
const PhoneInput = React.forwardRef((_a, ref) => {
|
|
14520
|
-
var
|
|
14509
|
+
var _b, _c;
|
|
14510
|
+
var { dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, onBlurCountryCode, readOnly, countryCodePlaceholder, onChangeCountryCode, onBlur, onFieldsBlur, onChangeValue } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "value", "defaultValue", "fieldSize", "disableAction", "onChange", "onBlurCountryCode", "readOnly", "countryCodePlaceholder", "onChangeCountryCode", "onBlur", "onFieldsBlur", "onChangeValue"]);
|
|
14511
|
+
const DEFAULT_COUNTRY_CODE = "+45";
|
|
14512
|
+
const { getIsCountryCodeInvalid, getIsPhoneNumberInvalid, getPhoneNumber } = usePhoneInput();
|
|
14513
|
+
const countryCodePlaceholderValue = countryCodePlaceholder || DEFAULT_COUNTRY_CODE;
|
|
14514
|
+
const safePhoneNumber = getPhoneNumberWithPlus(value || "");
|
|
14515
|
+
const number = parsePhoneNumber(safePhoneNumber);
|
|
14516
|
+
const [phone, setPhone] = React.useState((_b = number === null || number === void 0 ? void 0 : number.nationalNumber.toString()) !== null && _b !== void 0 ? _b : "");
|
|
14517
|
+
const [code, setCode] = React.useState((_c = number === null || number === void 0 ? void 0 : number.countryCallingCode.toString()) !== null && _c !== void 0 ? _c : "");
|
|
14518
|
+
const codeRef = React.useRef(code); // synchronus reliable source of truth (country code is calling onblur just after onchange, useState is too slow for this)
|
|
14519
|
+
const phoneRef = React.useRef(phone); // synchronus reliable source of truth
|
|
14520
|
+
const onChangeHandler = React__default["default"].useCallback(({ newPhone, newCode }) => {
|
|
14521
|
+
onChangeValue &&
|
|
14522
|
+
onChangeValue({
|
|
14523
|
+
phone: getPhoneNumber({ country: newCode, phone: newPhone || "" }),
|
|
14524
|
+
countryCode: newCode,
|
|
14525
|
+
national: newPhone,
|
|
14526
|
+
});
|
|
14527
|
+
}, [onChangeValue, getPhoneNumber]);
|
|
14528
|
+
const onCodeChangeHandler = React__default["default"].useCallback((codeNumber) => {
|
|
14529
|
+
setCode(codeNumber);
|
|
14530
|
+
onChangeHandler({ newPhone: phone, newCode: codeNumber });
|
|
14531
|
+
}, [phone, onChangeHandler]);
|
|
14532
|
+
const onPhoneChangeHandler = React__default["default"].useCallback((phoneNumber) => {
|
|
14533
|
+
setPhone(phoneNumber);
|
|
14534
|
+
onChangeHandler({ newPhone: phoneNumber, newCode: code });
|
|
14535
|
+
}, [onChangeHandler, code]);
|
|
14536
|
+
const onBlurHandler = React__default["default"].useCallback(() => {
|
|
14537
|
+
onFieldsBlur &&
|
|
14538
|
+
onFieldsBlur({
|
|
14539
|
+
phone: getPhoneNumber({ country: codeRef.current, phone: phoneRef.current }),
|
|
14540
|
+
countryCode: codeRef.current,
|
|
14541
|
+
national: phoneRef.current,
|
|
14542
|
+
});
|
|
14543
|
+
}, [onFieldsBlur, getPhoneNumber]);
|
|
14521
14544
|
const hiddenInputRef = React.useRef(null);
|
|
14522
|
-
const
|
|
14545
|
+
const phoneNumber = getPhoneNumber({ country: code, phone });
|
|
14523
14546
|
React.useEffect(() => {
|
|
14524
14547
|
const element = hiddenInputRef.current;
|
|
14525
14548
|
const event = new Event("change");
|
|
@@ -14527,15 +14550,19 @@ const PhoneInput = React.forwardRef((_a, ref) => {
|
|
|
14527
14550
|
// The event as unknown as ChangeEvent<HTMLInputElement> assertion is needed because
|
|
14528
14551
|
// the event's type is inferred as Event, which doesn't have a target property, whereas ChangeEvent does.
|
|
14529
14552
|
onChange && onChange(event);
|
|
14530
|
-
}, [
|
|
14531
|
-
|
|
14532
|
-
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14553
|
+
}, [phoneNumber, onChange]);
|
|
14554
|
+
return (jsxRuntime.jsxs("div", { className: "grid grid-cols-min-fr gap-2", "data-testid": dataTestId && `${dataTestId}-container`, children: [jsxRuntime.jsx("input", { hidden: true, id: "phone-input", "data-testid": dataTestId, value: phoneNumber, ref: hiddenInputRef, onChange: onChange, "aria-invalid": isInvalid }), jsxRuntime.jsx(CountryCodeSelect, { dataTestId: dataTestId && `${dataTestId}-countryCodeSelect`, countryCode: code, onBlur: e => {
|
|
14555
|
+
onBlurHandler();
|
|
14556
|
+
}, onChange: e => {
|
|
14557
|
+
(e === null || e === void 0 ? void 0 : e.value) && onCodeChangeHandler(e === null || e === void 0 ? void 0 : e.value);
|
|
14558
|
+
codeRef.current = (e === null || e === void 0 ? void 0 : e.value) || "";
|
|
14559
|
+
}, disabled: disabled, readOnly: readOnly, isInvalid: isInvalid, placeholder: countryCodePlaceholderValue }), jsxRuntime.jsx(BaseInput, Object.assign({ id: "phoneInput-number", dataTestId: dataTestId && `${dataTestId}-phoneNumberInput`, fieldSize: fieldSize, type: "tel", value: phone, disabled: disabled, readOnly: readOnly, isInvalid: isInvalid, onChange: e => {
|
|
14560
|
+
(e === null || e === void 0 ? void 0 : e.target.value) && setPhone(e.target.value);
|
|
14561
|
+
onPhoneChangeHandler(e.target.value);
|
|
14562
|
+
phoneRef.current = e === null || e === void 0 ? void 0 : e.target.value;
|
|
14563
|
+
}, onBlur: () => {
|
|
14564
|
+
onBlurHandler();
|
|
14565
|
+
}, actions: !disableAction && (jsxRuntime.jsx(ActionButton, { disabled: disabled || isInvalid || getIsCountryCodeInvalid(code || "") || getIsPhoneNumberInvalid(phone || " "), value: phoneNumber, type: "PHONE_NUMBER", dataTestId: dataTestId && `${dataTestId}-phoneIcon`, iconSize: fieldSize })) }, rest))] }));
|
|
14539
14566
|
});
|
|
14540
14567
|
|
|
14541
14568
|
/**
|
|
@@ -14555,11 +14582,9 @@ const PhoneInput = React.forwardRef((_a, ref) => {
|
|
|
14555
14582
|
* @returns {JSX.Element} - The PhoneField component.
|
|
14556
14583
|
*/
|
|
14557
14584
|
const PhoneField = React.forwardRef((_a, ref) => {
|
|
14558
|
-
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
14559
|
-
const { isCombinedValueInvalid, isPhoneNumberInvalid, isCountryCodeInvalid, combinedValue } = usePhoneInput(value);
|
|
14560
|
-
const renderAsInvalid = isCombinedValueInvalid || isPhoneNumberInvalid || isCountryCodeInvalid || isInvalid || Boolean(errorMessage);
|
|
14585
|
+
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId, onChangeValue, onFieldsBlur } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId", "onChangeValue", "onFieldsBlur"]);
|
|
14561
14586
|
const htmlForId = id ? id : "phoneField-" + v4();
|
|
14562
|
-
return (jsxRuntime.jsx(FormGroup, { htmlFor: htmlForId, label: label, tip: tip, isInvalid:
|
|
14587
|
+
return (jsxRuntime.jsx(FormGroup, { htmlFor: htmlForId, label: label, tip: tip, isInvalid: isInvalid, helpText: (isInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup`, children: jsxRuntime.jsx(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value, defaultValue: defaultValue, ref: ref, dataTestId: dataTestId, onChangeValue: onChangeValue, onFieldsBlur: onFieldsBlur }, rest)) }));
|
|
14563
14588
|
});
|
|
14564
14589
|
|
|
14565
14590
|
const cvaRadioGroup = cssClassVarianceUtilities.cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
|
package/index.esm.js
CHANGED
|
@@ -3,7 +3,7 @@ import { registerTranslations } from '@trackunit/i18n-library-translation';
|
|
|
3
3
|
import { IconButton, Icon, Tip, Heading, Text, MenuItem, Tag, Spinner } from '@trackunit/react-components';
|
|
4
4
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
5
5
|
import * as React from 'react';
|
|
6
|
-
import React__default, { useMemo, forwardRef, useState, cloneElement,
|
|
6
|
+
import React__default, { useMemo, forwardRef, useState, cloneElement, useCallback, useLayoutEffect, useContext, createElement, Fragment, createContext, useRef, useEffect, Component } from 'react';
|
|
7
7
|
import { createPortal } from 'react-dom';
|
|
8
8
|
|
|
9
9
|
var defaultTranslations = {
|
|
@@ -6268,54 +6268,43 @@ const getPhoneNumberWithPlus = (phoneNumber) => {
|
|
|
6268
6268
|
* A custom hook for managing phone number input state and validation.
|
|
6269
6269
|
*
|
|
6270
6270
|
* @returns {object} - An object containing state values and event handler functions.
|
|
6271
|
-
* @property {
|
|
6272
|
-
* @property {
|
|
6273
|
-
* @property {
|
|
6274
|
-
*
|
|
6275
|
-
* @property {Function} handleCountryCodeChange - A function for handling changes to the country code input.
|
|
6276
|
-
* @property {Function} handlePhoneNumberChange - A function for handling changes to the phone number input.
|
|
6271
|
+
* @property {Function} getIsCountryCodeInvalid - A function for check if country code is valid
|
|
6272
|
+
* @property {Function} getIsNumberInvalid- A function for check if number part of phone number is valid
|
|
6273
|
+
* @property {Function} getIsPhoneNumberValid- A function for check if phone number is valid
|
|
6274
|
+
* @property {Function} getPhoneNumber - A function for get formatted phone number with country code and plus sign
|
|
6277
6275
|
* @property {string} combinedValue - The combined country code and phone number value.
|
|
6278
6276
|
*/
|
|
6279
|
-
const usePhoneInput = (
|
|
6280
|
-
const
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
const [isPhoneNumberInvalid, setIsPhoneNumberInvalid] = useState(false);
|
|
6284
|
-
const [isCombinedValueInvalid, setIsCombinedValueInvalid] = useState(false);
|
|
6285
|
-
const [combinedValue, setCombinedValue] = useState(value !== null && value !== void 0 ? value : "");
|
|
6286
|
-
useEffect(() => {
|
|
6287
|
-
var _a, _b;
|
|
6288
|
-
if (value && ((!countryCode && !phoneNumber) || !combinedValue)) {
|
|
6289
|
-
const safePhoneNumber = getPhoneNumberWithPlus(value);
|
|
6290
|
-
const number = parsePhoneNumber(safePhoneNumber);
|
|
6291
|
-
setCountryCode((_a = number === null || number === void 0 ? void 0 : number.countryCallingCode.toString()) !== null && _a !== void 0 ? _a : "");
|
|
6292
|
-
setPhoneNumber((_b = number === null || number === void 0 ? void 0 : number.nationalNumber.toString()) !== null && _b !== void 0 ? _b : "");
|
|
6293
|
-
setCombinedValue(`${countryCode}${phoneNumber}`);
|
|
6294
|
-
combinedValue && setIsCombinedValueInvalid(isPossiblePhoneNumber(combinedValue.toString()));
|
|
6277
|
+
const usePhoneInput = () => {
|
|
6278
|
+
const getIsCountryCodeInvalid = (code) => {
|
|
6279
|
+
if (code) {
|
|
6280
|
+
return false;
|
|
6295
6281
|
}
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6282
|
+
return true;
|
|
6283
|
+
};
|
|
6284
|
+
const getIsNumberInvalid = (number) => {
|
|
6285
|
+
if (number) {
|
|
6286
|
+
return false;
|
|
6287
|
+
}
|
|
6288
|
+
return true;
|
|
6289
|
+
};
|
|
6290
|
+
const getIsPhoneNumberInvalid = (phone) => {
|
|
6291
|
+
if (phone) {
|
|
6292
|
+
const normalized = getPhoneNumberWithPlus(phone.toString());
|
|
6293
|
+
return isPossiblePhoneNumber(normalized);
|
|
6294
|
+
}
|
|
6295
|
+
return true;
|
|
6303
6296
|
};
|
|
6304
|
-
const
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6297
|
+
const getPhoneNumber = ({ country, phone }) => {
|
|
6298
|
+
if (country) {
|
|
6299
|
+
return getPhoneNumberWithPlus(`${country}${phone || ""}`);
|
|
6300
|
+
}
|
|
6301
|
+
return phone || "";
|
|
6309
6302
|
};
|
|
6310
6303
|
return {
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
handleCountryCodeChange,
|
|
6316
|
-
handlePhoneNumberChange,
|
|
6317
|
-
combinedValue,
|
|
6318
|
-
isCombinedValueInvalid,
|
|
6304
|
+
getIsCountryCodeInvalid,
|
|
6305
|
+
getIsNumberInvalid,
|
|
6306
|
+
getIsPhoneNumberInvalid,
|
|
6307
|
+
getPhoneNumber,
|
|
6319
6308
|
};
|
|
6320
6309
|
};
|
|
6321
6310
|
|
|
@@ -14477,7 +14466,7 @@ const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, onChange
|
|
|
14477
14466
|
const filteredCodes = countryCodes.filter(code => {
|
|
14478
14467
|
return !(excludedCountries === null || excludedCountries === void 0 ? void 0 : excludedCountries.some(excludedCode => excludedCode.value === code.value));
|
|
14479
14468
|
});
|
|
14480
|
-
return (jsx$1(Select, { dataTestId: dataTestId, className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value }) => value === `+${countryCode}`), placeholder: placeholder, hasError: isCountryCodeMissing || isInvalid, maxMenuHeight: 200, onChange: onChange, disabled: disabled, readOnly: readOnly, onBlur: onBlur, menuIsOpen: readOnly ? false : undefined }));
|
|
14469
|
+
return (jsx$1(Select, { dataTestId: dataTestId, className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value }) => value === `+${countryCode}`), placeholder: placeholder, hasError: isCountryCodeMissing || isInvalid, maxMenuHeight: 200, onChange: onChange, disabled: disabled, readOnly: readOnly, onBlur: onBlur, closeMenuOnSelect: true, menuIsOpen: readOnly ? false : undefined }));
|
|
14481
14470
|
};
|
|
14482
14471
|
|
|
14483
14472
|
/**
|
|
@@ -14491,9 +14480,43 @@ const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, onChange
|
|
|
14491
14480
|
* @returns {JSX.Element} - The PhoneInput component.
|
|
14492
14481
|
*/
|
|
14493
14482
|
const PhoneInput = forwardRef((_a, ref) => {
|
|
14494
|
-
var
|
|
14483
|
+
var _b, _c;
|
|
14484
|
+
var { dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, onBlurCountryCode, readOnly, countryCodePlaceholder, onChangeCountryCode, onBlur, onFieldsBlur, onChangeValue } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "value", "defaultValue", "fieldSize", "disableAction", "onChange", "onBlurCountryCode", "readOnly", "countryCodePlaceholder", "onChangeCountryCode", "onBlur", "onFieldsBlur", "onChangeValue"]);
|
|
14485
|
+
const DEFAULT_COUNTRY_CODE = "+45";
|
|
14486
|
+
const { getIsCountryCodeInvalid, getIsPhoneNumberInvalid, getPhoneNumber } = usePhoneInput();
|
|
14487
|
+
const countryCodePlaceholderValue = countryCodePlaceholder || DEFAULT_COUNTRY_CODE;
|
|
14488
|
+
const safePhoneNumber = getPhoneNumberWithPlus(value || "");
|
|
14489
|
+
const number = parsePhoneNumber(safePhoneNumber);
|
|
14490
|
+
const [phone, setPhone] = useState((_b = number === null || number === void 0 ? void 0 : number.nationalNumber.toString()) !== null && _b !== void 0 ? _b : "");
|
|
14491
|
+
const [code, setCode] = useState((_c = number === null || number === void 0 ? void 0 : number.countryCallingCode.toString()) !== null && _c !== void 0 ? _c : "");
|
|
14492
|
+
const codeRef = useRef(code); // synchronus reliable source of truth (country code is calling onblur just after onchange, useState is too slow for this)
|
|
14493
|
+
const phoneRef = useRef(phone); // synchronus reliable source of truth
|
|
14494
|
+
const onChangeHandler = React__default.useCallback(({ newPhone, newCode }) => {
|
|
14495
|
+
onChangeValue &&
|
|
14496
|
+
onChangeValue({
|
|
14497
|
+
phone: getPhoneNumber({ country: newCode, phone: newPhone || "" }),
|
|
14498
|
+
countryCode: newCode,
|
|
14499
|
+
national: newPhone,
|
|
14500
|
+
});
|
|
14501
|
+
}, [onChangeValue, getPhoneNumber]);
|
|
14502
|
+
const onCodeChangeHandler = React__default.useCallback((codeNumber) => {
|
|
14503
|
+
setCode(codeNumber);
|
|
14504
|
+
onChangeHandler({ newPhone: phone, newCode: codeNumber });
|
|
14505
|
+
}, [phone, onChangeHandler]);
|
|
14506
|
+
const onPhoneChangeHandler = React__default.useCallback((phoneNumber) => {
|
|
14507
|
+
setPhone(phoneNumber);
|
|
14508
|
+
onChangeHandler({ newPhone: phoneNumber, newCode: code });
|
|
14509
|
+
}, [onChangeHandler, code]);
|
|
14510
|
+
const onBlurHandler = React__default.useCallback(() => {
|
|
14511
|
+
onFieldsBlur &&
|
|
14512
|
+
onFieldsBlur({
|
|
14513
|
+
phone: getPhoneNumber({ country: codeRef.current, phone: phoneRef.current }),
|
|
14514
|
+
countryCode: codeRef.current,
|
|
14515
|
+
national: phoneRef.current,
|
|
14516
|
+
});
|
|
14517
|
+
}, [onFieldsBlur, getPhoneNumber]);
|
|
14495
14518
|
const hiddenInputRef = useRef(null);
|
|
14496
|
-
const
|
|
14519
|
+
const phoneNumber = getPhoneNumber({ country: code, phone });
|
|
14497
14520
|
useEffect(() => {
|
|
14498
14521
|
const element = hiddenInputRef.current;
|
|
14499
14522
|
const event = new Event("change");
|
|
@@ -14501,15 +14524,19 @@ const PhoneInput = forwardRef((_a, ref) => {
|
|
|
14501
14524
|
// The event as unknown as ChangeEvent<HTMLInputElement> assertion is needed because
|
|
14502
14525
|
// the event's type is inferred as Event, which doesn't have a target property, whereas ChangeEvent does.
|
|
14503
14526
|
onChange && onChange(event);
|
|
14504
|
-
}, [
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
14510
|
-
|
|
14511
|
-
|
|
14512
|
-
|
|
14527
|
+
}, [phoneNumber, onChange]);
|
|
14528
|
+
return (jsxs("div", { className: "grid grid-cols-min-fr gap-2", "data-testid": dataTestId && `${dataTestId}-container`, children: [jsx$1("input", { hidden: true, id: "phone-input", "data-testid": dataTestId, value: phoneNumber, ref: hiddenInputRef, onChange: onChange, "aria-invalid": isInvalid }), jsx$1(CountryCodeSelect, { dataTestId: dataTestId && `${dataTestId}-countryCodeSelect`, countryCode: code, onBlur: e => {
|
|
14529
|
+
onBlurHandler();
|
|
14530
|
+
}, onChange: e => {
|
|
14531
|
+
(e === null || e === void 0 ? void 0 : e.value) && onCodeChangeHandler(e === null || e === void 0 ? void 0 : e.value);
|
|
14532
|
+
codeRef.current = (e === null || e === void 0 ? void 0 : e.value) || "";
|
|
14533
|
+
}, disabled: disabled, readOnly: readOnly, isInvalid: isInvalid, placeholder: countryCodePlaceholderValue }), jsx$1(BaseInput, Object.assign({ id: "phoneInput-number", dataTestId: dataTestId && `${dataTestId}-phoneNumberInput`, fieldSize: fieldSize, type: "tel", value: phone, disabled: disabled, readOnly: readOnly, isInvalid: isInvalid, onChange: e => {
|
|
14534
|
+
(e === null || e === void 0 ? void 0 : e.target.value) && setPhone(e.target.value);
|
|
14535
|
+
onPhoneChangeHandler(e.target.value);
|
|
14536
|
+
phoneRef.current = e === null || e === void 0 ? void 0 : e.target.value;
|
|
14537
|
+
}, onBlur: () => {
|
|
14538
|
+
onBlurHandler();
|
|
14539
|
+
}, actions: !disableAction && (jsx$1(ActionButton, { disabled: disabled || isInvalid || getIsCountryCodeInvalid(code || "") || getIsPhoneNumberInvalid(phone || " "), value: phoneNumber, type: "PHONE_NUMBER", dataTestId: dataTestId && `${dataTestId}-phoneIcon`, iconSize: fieldSize })) }, rest))] }));
|
|
14513
14540
|
});
|
|
14514
14541
|
|
|
14515
14542
|
/**
|
|
@@ -14529,11 +14556,9 @@ const PhoneInput = forwardRef((_a, ref) => {
|
|
|
14529
14556
|
* @returns {JSX.Element} - The PhoneField component.
|
|
14530
14557
|
*/
|
|
14531
14558
|
const PhoneField = forwardRef((_a, ref) => {
|
|
14532
|
-
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
14533
|
-
const { isCombinedValueInvalid, isPhoneNumberInvalid, isCountryCodeInvalid, combinedValue } = usePhoneInput(value);
|
|
14534
|
-
const renderAsInvalid = isCombinedValueInvalid || isPhoneNumberInvalid || isCountryCodeInvalid || isInvalid || Boolean(errorMessage);
|
|
14559
|
+
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId, onChangeValue, onFieldsBlur } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId", "onChangeValue", "onFieldsBlur"]);
|
|
14535
14560
|
const htmlForId = id ? id : "phoneField-" + v4();
|
|
14536
|
-
return (jsx$1(FormGroup, { htmlFor: htmlForId, label: label, tip: tip, isInvalid:
|
|
14561
|
+
return (jsx$1(FormGroup, { htmlFor: htmlForId, label: label, tip: tip, isInvalid: isInvalid, helpText: (isInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup`, children: jsx$1(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value, defaultValue: defaultValue, ref: ref, dataTestId: dataTestId, onChangeValue: onChangeValue, onFieldsBlur: onFieldsBlur }, rest)) }));
|
|
14537
14562
|
});
|
|
14538
14563
|
|
|
14539
14564
|
const cvaRadioGroup = cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { FocusEventHandler } from "react";
|
|
2
|
-
import { BaseInputProps } from "../BaseInput";
|
|
1
|
+
import React, { FocusEventHandler } from "react";
|
|
3
2
|
import { SingleValue } from "react-select";
|
|
3
|
+
import { BaseInputProps } from "../BaseInput";
|
|
4
4
|
type BaseInputExposedProps = Omit<BaseInputProps, "actions">;
|
|
5
5
|
export interface PhoneNumberProps {
|
|
6
6
|
countryCode: string;
|
|
7
7
|
phoneNumber: string;
|
|
8
8
|
}
|
|
9
|
+
interface PhoneNumberValue {
|
|
10
|
+
phone: string;
|
|
11
|
+
national?: string;
|
|
12
|
+
countryCode?: string;
|
|
13
|
+
}
|
|
9
14
|
export interface PhoneInputProps extends BaseInputExposedProps {
|
|
10
15
|
/**
|
|
11
16
|
* To disable the action button.
|
|
@@ -16,10 +21,6 @@ export interface PhoneInputProps extends BaseInputExposedProps {
|
|
|
16
21
|
* <PhoneInput disableAction />
|
|
17
22
|
*/
|
|
18
23
|
disableAction?: boolean;
|
|
19
|
-
/**
|
|
20
|
-
* A callback function that gives you the country code and phone number as separate values.
|
|
21
|
-
*/
|
|
22
|
-
onChangeGetSeparateValues?: (params: PhoneNumberProps) => void;
|
|
23
24
|
/**
|
|
24
25
|
* On blur handler for country code component.
|
|
25
26
|
*/
|
|
@@ -35,6 +36,14 @@ export interface PhoneInputProps extends BaseInputExposedProps {
|
|
|
35
36
|
* A placeholder value for country code.
|
|
36
37
|
*/
|
|
37
38
|
countryCodePlaceholder?: string;
|
|
39
|
+
/**
|
|
40
|
+
* An custom handler will be called when country code select or phone number input lost focus
|
|
41
|
+
*/
|
|
42
|
+
onFieldsBlur?: ({ phone, national, countryCode }: PhoneNumberValue) => void;
|
|
43
|
+
/**
|
|
44
|
+
* An custom handler will be called when country code select or phone number input were changed
|
|
45
|
+
*/
|
|
46
|
+
onChangeValue?: ({ phone, national, countryCode }: PhoneNumberValue) => void;
|
|
38
47
|
}
|
|
39
48
|
/**
|
|
40
49
|
* A component for inputting phone numbers with an optional action button for initiating a phone call.
|
|
@@ -46,5 +55,5 @@ export interface PhoneInputProps extends BaseInputExposedProps {
|
|
|
46
55
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
47
56
|
* @returns {JSX.Element} - The PhoneInput component.
|
|
48
57
|
*/
|
|
49
|
-
export declare const PhoneInput:
|
|
58
|
+
export declare const PhoneInput: React.ForwardRefExoticComponent<PhoneInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
50
59
|
export {};
|
|
@@ -1,56 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
phoneNumber: string;
|
|
11
|
-
/**
|
|
12
|
-
* Whether the country code value is invalid.
|
|
13
|
-
*/
|
|
14
|
-
isCountryCodeInvalid: boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Whether the phone number value is invalid.
|
|
17
|
-
*/
|
|
18
|
-
isPhoneNumberInvalid: boolean;
|
|
19
|
-
/**
|
|
20
|
-
* Whether the full phone number value is valid.
|
|
21
|
-
*
|
|
22
|
-
* @returns {boolean} Whether the full phone number value is valid.
|
|
23
|
-
*/
|
|
24
|
-
isCombinedValueInvalid: boolean;
|
|
25
|
-
/**
|
|
26
|
-
* A function for handling changes to the country code input.
|
|
27
|
-
*/
|
|
28
|
-
handleCountryCodeChange: (option: {
|
|
29
|
-
label: string;
|
|
30
|
-
value: string;
|
|
31
|
-
} | null) => void;
|
|
32
|
-
/**
|
|
33
|
-
* A function for handling changes to the phone number input.
|
|
34
|
-
*/
|
|
35
|
-
handlePhoneNumberChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
36
|
-
/**
|
|
37
|
-
* The combined country code and phone number value.
|
|
38
|
-
*
|
|
39
|
-
* @example "+123456789"
|
|
40
|
-
* @returns {string} Combined phone number
|
|
41
|
-
*/
|
|
42
|
-
combinedValue: string | number | readonly string[] | undefined;
|
|
1
|
+
export interface UsePhoneInput {
|
|
2
|
+
getIsCountryCodeInvalid: (phone?: string) => boolean;
|
|
3
|
+
getIsNumberInvalid: (phone: string) => boolean;
|
|
4
|
+
getIsPhoneNumberInvalid: (phone: string | number | readonly string[] | undefined) => boolean;
|
|
5
|
+
getPhoneNumber: ({ country, phone }: {
|
|
6
|
+
country?: string;
|
|
7
|
+
phone?: string;
|
|
8
|
+
}) => string;
|
|
43
9
|
}
|
|
44
10
|
/**
|
|
45
11
|
* A custom hook for managing phone number input state and validation.
|
|
46
12
|
*
|
|
47
13
|
* @returns {object} - An object containing state values and event handler functions.
|
|
48
|
-
* @property {
|
|
49
|
-
* @property {
|
|
50
|
-
* @property {
|
|
51
|
-
*
|
|
52
|
-
* @property {Function} handleCountryCodeChange - A function for handling changes to the country code input.
|
|
53
|
-
* @property {Function} handlePhoneNumberChange - A function for handling changes to the phone number input.
|
|
14
|
+
* @property {Function} getIsCountryCodeInvalid - A function for check if country code is valid
|
|
15
|
+
* @property {Function} getIsNumberInvalid- A function for check if number part of phone number is valid
|
|
16
|
+
* @property {Function} getIsPhoneNumberValid- A function for check if phone number is valid
|
|
17
|
+
* @property {Function} getPhoneNumber - A function for get formatted phone number with country code and plus sign
|
|
54
18
|
* @property {string} combinedValue - The combined country code and phone number value.
|
|
55
19
|
*/
|
|
56
|
-
export declare const usePhoneInput: (
|
|
20
|
+
export declare const usePhoneInput: () => UsePhoneInput;
|