@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
347 lines (346 loc) • 15.8 kB
JavaScript
"use strict";
"use client";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
require("core-js/modules/es.string.replace.js");
require("core-js/modules/web.dom-collections.iterator.js");
var _react = _interopRequireWildcard(require("react"));
var _components = require("../../../../components");
var _classnames = _interopRequireDefault(require("classnames"));
var _countries = _interopRequireDefault(require("../../constants/countries"));
var _String = _interopRequireDefault(require("../String"));
var _FieldBlock = _interopRequireDefault(require("../../FieldBlock"));
var _hooks = require("../../hooks");
var _utils = require("../../../../components/flex/utils");
var _Context = _interopRequireDefault(require("../../../../shared/Context"));
var _SelectCountry = require("../SelectCountry");
var _useTranslation = _interopRequireDefault(require("../../hooks/useTranslation"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
const defaultCountryCode = '+47';
const defaultPlaceholder = '00 00 00 00';
const defaultMask = [/\d/, /\d/, ' ', /\d/, /\d/, ' ', /\d/, /\d/, ' ', /\d/, /\d/];
function PhoneNumber(props) {
var _sharedContext$locale, _props$inputRef, _countryCodeRef$curre, _props$width;
const sharedContext = (0, _react.useContext)(_Context.default);
const {
label: defaultLabel,
countryCodeLabel: defaultCountryCodeLabel,
errorRequired
} = (0, _useTranslation.default)().PhoneNumber;
const lang = (_sharedContext$locale = sharedContext.locale) === null || _sharedContext$locale === void 0 ? void 0 : _sharedContext$locale.split('-')[0];
const countryCodeRef = (0, _react.useRef)(props === null || props === void 0 ? void 0 : props.emptyValue);
const prevCountryCodeRef = (0, _react.useRef)(countryCodeRef.current);
const numberRef = (0, _react.useRef)(props === null || props === void 0 ? void 0 : props.emptyValue);
const dataRef = (0, _react.useRef)(null);
const langRef = (0, _react.useRef)(lang);
const wasFilled = (0, _react.useRef)(false);
const currentCountryRef = (0, _react.useRef)();
const errorMessages = (0, _react.useMemo)(() => _objectSpread({
'Field.errorRequired': errorRequired,
'Field.errorPattern': errorRequired
}, props.errorMessages), [errorRequired, props.errorMessages]);
const validateRequired = (0, _react.useCallback)((value, _ref) => {
let {
required,
isChanged,
error
} = _ref;
if (required) {
const [countryCode, phoneNumber] = splitValue(value);
if (countryCode !== prevCountryCodeRef.current) {
if (countryCode) {
prevCountryCodeRef.current = countryCode;
}
return undefined;
}
if (isChanged && !phoneNumber) {
return error;
}
}
return undefined;
}, []);
const fromExternal = (0, _react.useCallback)(external => {
const [, phoneNumber] = splitValue(external);
if (!phoneNumber && !props.omitCountryCodeField) {
return countryCodeRef.current;
}
return external;
}, [props.omitCountryCodeField]);
const toEvent = (0, _react.useCallback)(value => {
const [, phoneNumber] = splitValue(value);
if (!phoneNumber) {
return props.emptyValue;
}
return value;
}, [props.emptyValue]);
const schema = (0, _react.useMemo)(() => {
var _props$schema;
return (_props$schema = props.schema) !== null && _props$schema !== void 0 ? _props$schema : {
type: 'string',
pattern: props.pattern
};
}, [props.schema, props.pattern]);
const defaultProps = {
schema,
errorMessages
};
const ref = (0, _react.useRef)();
const preparedProps = _objectSpread(_objectSpread(_objectSpread({}, props), defaultProps), {}, {
validateRequired,
fromExternal,
toEvent,
inputRef: (_props$inputRef = props.inputRef) !== null && _props$inputRef !== void 0 ? _props$inputRef : ref
});
const {
id,
path,
itemPath,
value,
className,
inputRef,
countryCodeFieldClassName,
numberFieldClassName,
countryCodePlaceholder,
placeholder,
countryCodeLabel,
label = defaultLabel,
numberMask,
countries: ccFilter = 'Prioritized',
emptyValue,
info,
warning,
size,
error,
hasError,
disabled,
width = 'large',
help,
required,
validateInitially,
continuousValidation,
validateContinuously,
validateUnchanged,
omitCountryCodeField,
setHasFocus,
handleChange,
setDisplayValue,
onCountryCodeChange,
onNumberChange,
filterCountries
} = (0, _hooks.useFieldProps)(preparedProps);
(0, _react.useEffect)(() => {
if (path || itemPath) {
var _inputRef$current;
const number = (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.value;
setDisplayValue((number === null || number === void 0 ? void 0 : number.length) > 0 ? joinValue([countryCodeRef.current, number]) : undefined);
}
}, [inputRef, itemPath, path, setDisplayValue, value]);
const filter = (0, _react.useCallback)(country => {
return (0, _SelectCountry.countryFilter)(country, filterCountries, ccFilter);
}, [ccFilter, filterCountries]);
const updateCurrentDataSet = (0, _react.useCallback)(() => {
dataRef.current = (0, _SelectCountry.getCountryData)({
lang,
filter: ccFilter === 'Prioritized' && !wasFilled.current ? country => `${formatCountryCode(country.cdc)}` === countryCodeRef.current : filter,
sort: ccFilter,
makeObject
});
}, [lang, filter, ccFilter]);
const prepareEventValues = (0, _react.useCallback)(function () {
var _currentCountryRef$cu;
let {
countryCode = countryCodeRef.current || emptyValue,
phoneNumber = numberRef.current || emptyValue
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
if (!currentCountryRef.current) {
const cdcVal = countryCode === null || countryCode === void 0 ? void 0 : countryCode.replace(/^\+/, '');
const item = dataRef.current.find(item => {
var _item$country;
const cdc = item === null || item === void 0 ? void 0 : (_item$country = item.country) === null || _item$country === void 0 ? void 0 : _item$country.cdc;
return cdc === cdcVal;
});
currentCountryRef.current = item === null || item === void 0 ? void 0 : item.country;
}
return _objectSpread(_objectSpread({}, !omitCountryCodeField ? {
countryCode
} : {}), {}, {
phoneNumber,
iso: (_currentCountryRef$cu = currentCountryRef.current) === null || _currentCountryRef$cu === void 0 ? void 0 : _currentCountryRef$cu.iso
});
}, [emptyValue, omitCountryCodeField]);
const callOnChange = (0, _react.useCallback)(data => {
const eventValues = prepareEventValues(data);
handleChange(joinValue([eventValues.countryCode, eventValues.phoneNumber]), eventValues);
}, [prepareEventValues, handleChange]);
const callOnBlurOrFocus = (0, _react.useCallback)(hasFocus => {
setHasFocus(hasFocus, undefined, prepareEventValues());
}, [prepareEventValues, setHasFocus]);
(0, _react.useMemo)(() => {
const [countryCode, phoneNumber] = splitValue(props.value || value);
numberRef.current = phoneNumber;
if (lang !== langRef.current || !wasFilled.current) {
if (!countryCodeRef.current || countryCode) {
countryCodeRef.current = countryCode || defaultCountryCode;
}
langRef.current = lang;
updateCurrentDataSet();
}
}, [value, props.value, lang, updateCurrentDataSet]);
const handleCountryCodeChange = (0, _react.useCallback)(_ref2 => {
var _data$selectedKey;
let {
data
} = _ref2;
const countryCode = countryCodeRef.current = (data === null || data === void 0 ? void 0 : (_data$selectedKey = data.selectedKey) === null || _data$selectedKey === void 0 ? void 0 : _data$selectedKey.trim()) || emptyValue;
currentCountryRef.current = data === null || data === void 0 ? void 0 : data.country;
callOnChange({
countryCode
});
onCountryCodeChange === null || onCountryCodeChange === void 0 ? void 0 : onCountryCodeChange(countryCode);
}, [emptyValue, callOnChange, onCountryCodeChange]);
const handleNumberChange = (0, _react.useCallback)(value => {
const phoneNumber = numberRef.current = value || emptyValue;
callOnChange({
phoneNumber
});
onNumberChange === null || onNumberChange === void 0 ? void 0 : onNumberChange(phoneNumber);
}, [emptyValue, callOnChange, onNumberChange]);
const handleOnBlur = (0, _react.useCallback)(() => {
callOnBlurOrFocus(false);
}, [callOnBlurOrFocus]);
const handleOnFocus = (0, _react.useCallback)(() => {
callOnBlurOrFocus(true);
}, [callOnBlurOrFocus]);
const handleCountryCodeFocus = (0, _react.useCallback)(_ref3 => {
let {
updateData
} = _ref3;
if (!wasFilled.current) {
wasFilled.current = true;
updateCurrentDataSet();
updateData(dataRef.current);
}
handleOnFocus();
}, [handleOnFocus, updateCurrentDataSet]);
const onTypeHandler = (0, _react.useCallback)(_ref4 => {
var _event$nativeEvent;
let {
value,
updateData,
revalidateInputValue,
event
} = _ref4;
if (typeof (event === null || event === void 0 ? void 0 : (_event$nativeEvent = event.nativeEvent) === null || _event$nativeEvent === void 0 ? void 0 : _event$nativeEvent.data) === 'undefined') {
const cdcVal = /\+\d{1,3}\s{1}\d+/.test(value) ? splitValue(value)[0] : value;
const country = _countries.default.find(_ref5 => {
let {
cdc
} = _ref5;
return cdc === cdcVal;
});
if (country !== null && country !== void 0 && country.cdc) {
const countryCode = countryCodeRef.current = formatCountryCode(country.cdc);
updateCurrentDataSet();
updateData(dataRef.current);
callOnChange({
countryCode
});
window.requestAnimationFrame(() => {
revalidateInputValue();
});
}
}
}, [callOnChange, updateCurrentDataSet]);
const isDefault = (_countryCodeRef$curre = countryCodeRef.current) === null || _countryCodeRef$curre === void 0 ? void 0 : _countryCodeRef$curre.includes(defaultCountryCode);
const fieldBlockProps = _objectSpread({
id,
className: (0, _classnames.default)('dnb-forms-field-phone-number', className),
width: omitCountryCodeField || props.width ? undefined : width,
label: undefined,
help: undefined
}, (0, _utils.pickSpacingProps)(props));
return _react.default.createElement(_FieldBlock.default, fieldBlockProps, _react.default.createElement(_components.Flex.Horizontal, {
align: "flex-end"
}, !omitCountryCodeField && _react.default.createElement(_components.Autocomplete, {
className: (0, _classnames.default)('dnb-forms-field-phone-number__country-code', countryCodeFieldClassName),
mode: "async",
placeholder: countryCodePlaceholder,
label_direction: "vertical",
label: countryCodeLabel !== null && countryCodeLabel !== void 0 ? countryCodeLabel : defaultCountryCodeLabel,
data: dataRef.current,
value: countryCodeRef.current,
status: hasError ? 'error' : undefined,
disabled: disabled,
on_focus: handleCountryCodeFocus,
on_blur: handleOnBlur,
on_change: handleCountryCodeChange,
on_type: onTypeHandler,
independent_width: true,
search_numbers: true,
keep_selection: true,
autoComplete: "tel-country-code",
no_animation: props.noAnimation,
stretch: width === 'stretch',
size: size
}), _react.default.createElement(_String.default, {
className: (0, _classnames.default)('dnb-forms-field-phone-number__number', numberFieldClassName),
type: "tel",
autoComplete: "tel-national",
emptyValue: emptyValue,
layout: "vertical",
label: label,
placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : isDefault ? defaultPlaceholder : undefined,
mask: numberMask !== null && numberMask !== void 0 ? numberMask : isDefault ? defaultMask : Array(12).fill(/\d/),
onFocus: handleOnFocus,
onBlur: handleOnBlur,
onChange: handleNumberChange,
value: numberRef.current,
innerRef: inputRef,
info: info,
warning: warning,
error: error,
disabled: disabled,
width: omitCountryCodeField ? 'medium' : (_props$width = props.width) !== null && _props$width !== void 0 ? _props$width : 'stretch',
help: _objectSpread(_objectSpread({}, help), {}, {
breakout: false,
outset: false
}),
required: required,
errorMessages: errorMessages,
validateInitially: validateInitially,
validateContinuously: continuousValidation || validateContinuously,
validateUnchanged: validateUnchanged,
inputMode: "tel",
size: size
})));
}
function makeObject(country, lang) {
var _country$i18n$lang;
return {
selectedKey: formatCountryCode(country.cdc),
selected_value: `${country.iso} (${formatCountryCode(country.cdc)})`,
content: `${formatCountryCode(country.cdc)} ${(_country$i18n$lang = country.i18n[lang]) !== null && _country$i18n$lang !== void 0 ? _country$i18n$lang : country.i18n.en}`,
country
};
}
function formatCountryCode(value) {
return `+${value}`;
}
function splitValue(value) {
return (typeof value === 'string' ? value.match(/^(\+[^ ]+)? ?(.*)$/) : [undefined, '', '']).slice(1);
}
function joinValue(array) {
return array.filter(Boolean).join(' ');
}
PhoneNumber._supportsSpacingProps = true;
var _default = exports.default = PhoneNumber;
//# sourceMappingURL=PhoneNumber.js.map