UNPKG

@adyen/kyc-components

Version:

This guide assumes that you have already an account with Adyen. A legalEntity needs to be created, and you need to have a `legalEntityId` to instatiate a Component.

293 lines (292 loc) 11.8 kB
try { let e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack; n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "49700cd8-0269-461a-822b-d637dc58d9c1", e._sentryDebugIdIdentifier = "sentry-dbid-49700cd8-0269-461a-822b-d637dc58d9c1"); } catch (e) {} import { o as createLogger, r as useTranslation } from "./translation-BFxyJ1c5.js"; import { r as httpPost, s as useApiContext } from "./http-D1NDkBxF.js"; import { u as entriesOf } from "./useAnalyticsContext-BVFDMrVE.js"; import { y as isEmpty } from "./validatorUtils-DRapRJ6z.js"; import { t as Header } from "./Header-CPmJyuoP.js"; import { t as CountryCodes } from "./country-code-CX5KqMBr.js"; import { t as useDataset } from "./useDataset-ZHrWhmsh.js"; import { t as datasetIdentifier } from "./datasetUtil-Zd4TCTDn.js"; import { n as mergeFieldMetadataIntoProps, t as createFormUtils } from "./formUtils-DCvL3uZG.js"; import { c as nonInputs, l as numericInputs, n as InputEmail, s as makeMask, t as MaskedInput, u as spacer } from "./MaskedInput-BFPSwRto.js"; import { n as emailPattern } from "./basePatterns-VqSYMnkh.js"; import { t as resolveFieldMetadata } from "./fieldConfigurations-m7oWP1DZ.js"; import { t as Field } from "./Field-pcJkjIG_.js"; import { t as Select } from "./Select-CcSRI-H0.js"; import { t as InputGroup } from "./InputGroup-CVYzCygf.js"; import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; import { jsx, jsxs } from "preact/jsx-runtime"; import "@tanstack/preact-query"; //#region src/api/validation/useValidatePhoneNumber.ts var validatePhoneNumber = (baseUrl, data) => { return httpPost({ baseUrl, path: `validations/phonenumber` }, data); }; var useValidatePhoneNumberImperatively = () => { const { baseUrl } = useApiContext(); return useCallback((data) => validatePhoneNumber(baseUrl.value, data), [baseUrl.value]); }; //#endregion //#region src/components/Shared/fields/PhoneField/fieldConfig.ts var validatePhoneCountryCodeNotEmptyOnBlur = { modes: ["blur"], validate: (phone) => !isEmpty(phone?.phoneCountryCode), errorMessage: "missingPhoneCountryCode" }; var validatePhoneNumberNotEmpty = { modes: ["blur"], validate: (phone) => !isEmpty(phone?.number), errorMessage: "invalidPhoneNumber" }; var getAsyncPhoneValidationRules = (validatePhoneNumber) => ({ phoneNumber: { asyncValidate: async (phone) => { if (!phone?.number) return false; return (await validatePhoneNumber({ number: phone.number })).valid; }, errorMessage: "invalidPhoneNumber", modes: ["blur"] } }); var defaultValidators = [validatePhoneCountryCodeNotEmptyOnBlur, validatePhoneNumberNotEmpty]; var defaultFieldMetadata = { validators: defaultValidators }; var fieldConfig = { [CountryCodes.Albania]: { validators: defaultValidators, mask: { mask: makeMask(...numericInputs(2), spacer, ...numericInputs(3), spacer, ...numericInputs(4)) } }, [CountryCodes.AmericanSamoa]: { validators: defaultValidators, mask: { mask: makeMask(...numericInputs(3), ...nonInputs("-"), ...numericInputs(4)) } }, [CountryCodes.Netherlands]: { validators: defaultValidators, mask: { mask: makeMask(...numericInputs(1), spacer, ...numericInputs(8)) } }, [CountryCodes.Singapore]: { validators: defaultValidators, mask: { mask: makeMask(...numericInputs(4), spacer, ...numericInputs(4)) } }, [CountryCodes.Japan]: { validators: defaultValidators, mask: { mask: makeMask(...numericInputs(2), ...nonInputs("-"), ...numericInputs(4), ...nonInputs("-"), ...numericInputs(4)) } }, [CountryCodes.UnitedStates]: { validators: defaultValidators, mask: { mask: makeMask(...nonInputs("(", { displayEagerly: false }), ...numericInputs(3), ...nonInputs(")"), spacer, ...numericInputs(3), ...nonInputs("-"), ...numericInputs(4)) } } }; /** * Returns the placeholder text for the phone field based on country. */ var getPhonePlaceholder = (country) => { switch (country) { case CountryCodes.Albania: return "00 000 0000"; case CountryCodes.AmericanSamoa: return "000-0000"; case CountryCodes.Netherlands: return "0 00000000"; case CountryCodes.Singapore: return "0000 0000"; case CountryCodes.Japan: return "00-0000-0000"; case CountryCodes.UnitedStates: return "(000) 000-0000"; default: return; } }; //#endregion //#region src/components/Shared/forms/ContactDetails/validate.ts var contactDetailsValidationRules = { email: [{ modes: ["blur"], validate: (email) => email ? emailPattern.test(email) : false, errorMessage: "invalidEmail" }] }; //#endregion //#region src/components/Shared/fields/PhoneField/PhoneField.tsx var PHONE_FIELD = ["phoneNumber"]; var logger = createLogger(); var usePhonePrefixes = () => { const [phonePrefixes, setPhonePrefixes] = useState(); useEffect(() => { const loadPhonePrefixes = async () => { const loaded = (await import("./phonePrefixes-DcdX_CFz.js").then((n) => n.n)).default; setPhonePrefixes(loaded); }; loadPhonePrefixes().catch(logger.error); }, []); return phonePrefixes; }; function PhoneField({ country, name = "phoneNumber", data, valid, errors, label, mask, readonly, optional, placeholder, helper, helperPosition, handleChangeFor }) { const { t } = useTranslation("common"); const { dataset: countries } = useDataset(datasetIdentifier.country); const [isFocused, setIsFocused] = useState(false); const phonePrefixes = usePhonePrefixes(); const currentPrefix = phonePrefixes?.[data.phoneNumber?.phoneCountryCode ?? country]; const numberStrippedOfCountryCode = useMemo(() => { if (!phonePrefixes || !data.phoneNumber?.number) return ""; return currentPrefix && data.phoneNumber?.number.startsWith(currentPrefix) ? data.phoneNumber.number.slice(currentPrefix.length) : data.phoneNumber.number; }, [ phonePrefixes, data.phoneNumber?.number, currentPrefix ]); const selectItems = useMemo(() => { const countryMap = new Map(countries.map((entry) => [entry.id, entry.name])); return entriesOf(phonePrefixes ?? {}).map(([countryCode, prefix]) => { return { id: countryCode, name: `${countryMap.get(countryCode) ?? countryCode} (${prefix})`, selectedOptionName: `${countryCode} (${prefix})` }; }).sort((a, b) => a.name.localeCompare(b.name)); }, [phonePrefixes, countries]); const handleSelectChange = useCallback((event) => { const newCC = phonePrefixes?.[event.target.value]; const withoutCC = currentPrefix && data.phoneNumber?.number?.startsWith(currentPrefix) ? data.phoneNumber?.number?.slice(currentPrefix.length) : data.phoneNumber?.number?.replace(/\D+/g, ""); handleChangeFor("phoneNumber", "input")({ phoneCountryCode: event.target.value, number: withoutCC ? newCC + withoutCC : newCC, type: "mobile" }); }, [ currentPrefix, data.phoneNumber?.number, handleChangeFor, phonePrefixes ]); const handleOnInput = useCallback((event) => { const onlyDigits = (currentPrefix ? event.replace(currentPrefix, "") : event).replace(/\D+/g, ""); const number = currentPrefix ? `${currentPrefix}${onlyDigits}` : onlyDigits; handleChangeFor("phoneNumber", "input")({ ...data.phoneNumber, number, type: "mobile" }); }, [ currentPrefix, data.phoneNumber, handleChangeFor ]); const handleOnBlur = useCallback((event) => { const onlyDigits = event.currentTarget.value.replace(/\D+/g, ""); const number = currentPrefix ? `${currentPrefix}${onlyDigits}` : onlyDigits; setIsFocused(false); handleChangeFor("phoneNumber", "blur")({ ...data.phoneNumber, number, type: "mobile" }); }, [ currentPrefix, data.phoneNumber, handleChangeFor ]); const transformOnType = useCallback((value) => currentPrefix ? value.startsWith(currentPrefix) ? value.slice(currentPrefix.length) : value : value, [currentPrefix]); useEffect(() => { if (!data.phoneNumber?.phoneCountryCode && country) handleChangeFor("phoneNumber", "input")({ ...data.phoneNumber, phoneCountryCode: country, type: "mobile" }); }, [ country, data.phoneNumber?.phoneCountryCode, data?.phoneNumber, handleChangeFor ]); return /* @__PURE__ */ jsx(Field, { el: "fieldset", name, label: label ?? t(($) => $["phoneNumber"]), errorMessage: errors.phoneNumber, isValid: Boolean(valid.phoneNumber), optional: Boolean(optional), disabled: Boolean(readonly), helper, helperPosition, children: (childProps) => /* @__PURE__ */ jsxs(InputGroup, { ...childProps, id: "phoneInputGroup", isFocused, isInvalid: Boolean(!valid.phoneNumber && errors.phoneNumber), children: [/* @__PURE__ */ jsx(Select, { name: "phoneCountryCode", "aria-label": t(($) => $["phoneNumberPrefix"]), isMulti: false, items: selectItems, selected: data.phoneNumber?.phoneCountryCode, placeholder: t(($) => $["select"]), onChange: handleSelectChange, minimal: true }), /* @__PURE__ */ jsx(MaskedInput, { useFieldComponent: false, name: "phoneNumber", type: "tel", label: label ?? t(($) => $["phoneNumber"]), value: numberStrippedOfCountryCode, "aria-invalid": Boolean(!valid.phoneNumber), isValid: Boolean(valid.phoneNumber), placeholder, shouldValidate: true, errorMessage: errors.phoneNumber, readonly, disabled: readonly, transformOnType, ...mask, stripNonAllowedInputs: true, onInput: handleOnInput, onBlur: handleOnBlur, onFocus: () => setIsFocused(true) })] }) }); } //#endregion //#region src/components/Shared/forms/ContactDetails/ContactDetails.tsx var contactDetailFields = [...PHONE_FIELD, "email"]; function ContactDetails(props) { const { t } = useTranslation("common"); const { country, data, errors = {}, handleFieldChange, fieldValidationErrors, valid = {}, ...newProps } = props; let mergedProps = newProps; if (!handleFieldChange) return; mergedProps = mergeFieldMetadataIntoProps("phoneNumber", resolveFieldMetadata(fieldConfig[data?.phoneNumber?.phoneCountryCode ?? country], {}, defaultFieldMetadata), mergedProps); const formUtils = createFormUtils(mergedProps, t); return /* @__PURE__ */ jsxs("div", { role: "form", className: "adyen-kyc-individual__contact-details", children: [ mergedProps.heading && /* @__PURE__ */ jsx(Header, { title: mergedProps.heading }), formUtils.isRequiredField("email") && /* @__PURE__ */ jsx("div", { className: "adyen-kyc-email", children: /* @__PURE__ */ jsx(Field, { name: "email", label: formUtils.getLabel("email"), errorMessage: formUtils.getErrorMessage("email", errors, fieldValidationErrors), isValid: valid.email, children: (childProps) => /* @__PURE__ */ jsx(InputEmail, { ...childProps, name: "email", value: data?.email, readonly: formUtils.isReadOnly("email"), onInput: handleFieldChange("email", "input"), onBlur: handleFieldChange("email", "blur"), "aria-required": true, "aria-invalid": !valid?.email }) }) }), formUtils.isRequiredField("phoneNumber") && /* @__PURE__ */ jsx(PhoneField, { country, data: formUtils.getFieldData(data ?? {}, PHONE_FIELD), valid: formUtils.getFieldValid(valid, PHONE_FIELD), errors: formUtils.getFieldErrors(errors, {}, PHONE_FIELD), placeholder: getPhonePlaceholder(country), optional: formUtils.isOptionalField("phoneNumber"), readonly: formUtils.isReadOnly("phoneNumber"), mask: formUtils.getMask("phoneNumber"), handleChangeFor: handleFieldChange }) ] }); } //#endregion export { defaultFieldMetadata as a, getPhonePlaceholder as c, contactDetailsValidationRules as i, useValidatePhoneNumberImperatively as l, contactDetailFields as n, fieldConfig as o, PhoneField as r, getAsyncPhoneValidationRules as s, ContactDetails as t };