UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

347 lines (346 loc) 15.8 kB
"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