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.

960 lines (959 loc) 36 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] = "943f2245-913a-4cd3-b141-77e037aa579a", e._sentryDebugIdIdentifier = "sentry-dbid-943f2245-913a-4cd3-b141-77e037aa579a"); } catch (e) {} import { a as Icon, o as createLogger, r as useTranslation } from "./translation-BYvhW5zA.js"; import { $ as hasRepeatedCharacters, C as useDataset, G as SPECIAL_CHARS, H as NO_ALPHABET_REGEX, K as chomeAndBanchiValidator, Q as hasMaximumTwoRepeatedCharacters, R as ADDRESS_VALID_CHAR_REGEX, U as NO_ALPHABET_UNICODE_REGEX, X as getMaxLengthByFieldAndCountry, Y as getFormattingRegEx, et as hasText, it as isInvalidName, j as useToggleContext, ot as isValidMinLength, st as matchesRegex, ut as trimValWithOneSpace, w as datasetIdentifier, z as EMOJI_REGEX } from "./resolveEnvironment-DNmu53Rr.js"; import { n as httpGet, r as httpPost, s as useApiContext } from "./http-8qgzqVqk.js"; import { c as entriesOf } from "./AnalyticsContext-BFrJmsp0.js"; import { t as CountryCodes } from "./country-code-CJk2hdPu.js"; import { i as useAnalyticsContext } from "./Modal-BLP2aF-u.js"; import { n as translateTranslatable } from "./utils-C1buyvRw.js"; import { t as createFormUtils } from "./formUtils-DVc3a6gf.js"; import { c as COUNTRIES_WITH_STATES_DATASET, o as CONDENSED_ADDRESS_FIELDS, r as getKeyForField, s as COUNTRIES_WITH_HOUSE_NUMBER_FIRST, t as getAddressSchemaForCountry } from "./utils-DNIZ6F6L.js"; import { a as validateNotEmptyOnBlur } from "./patternValidators-DFve5Dzt.js"; import { t as Field } from "./Field-DoXLi6EY.js"; import { t as Select } from "./Select-DUo2rOfa.js"; import { n as useDebouncedCallback } from "./debouncedInputEvent-Fwwp_K_-.js"; import { t as useForm } from "./useForm-C5EykRLY.js"; import { t as InputText } from "./InputText-B0N7am-q.js"; import { n as CountryField } from "./CountryField-D-Q958WF.js"; import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; import { Fragment, jsx, jsxs } from "preact/jsx-runtime"; import { useQuery } from "@tanstack/preact-query"; //#region src/api/providersConfiguration/useProviderStatus.ts var getProvidersStatus = async (legalEntityId, baseUrl, data) => { return httpPost({ baseUrl, path: `legalEntities/${legalEntityId}/configurations/providers/status` }, data); }; /** * Asks the backend if 3rd party providers like Loqate and Onfido are available. * * Bank verification providers are not included, as these are handled by Open Banking. */ var useProviderStatus = (data, options) => { const { rootLegalEntityId, baseUrl } = useApiContext(); return useQuery({ queryKey: ["providersStatus", data], queryFn: () => getProvidersStatus(rootLegalEntityId.value, baseUrl.value, data), ...options }); }; //#endregion //#region src/api/address/useAddressCleanse.ts /** * Utilizing the Cleanse API from Loqate provider, determine if retrieved address is a PO Box * @param data Object containing country and text fields * @returns Promise with RetrieveAddressSuccessResponse as a response */ var cleanseAddress = async (legalEntityId, baseUrl, data) => { return httpPost({ baseUrl, path: `legalEntities/${legalEntityId}/addresses/cleanse` }, data); }; var useAddressCleanse = (data, options) => { const { rootLegalEntityId, baseUrl } = useApiContext(); return useQuery({ queryKey: ["addressCleanse", data], queryFn: () => cleanseAddress(rootLegalEntityId.value, baseUrl.value, data), ...options }); }; var useAddressCleanseImperatively = () => { const { rootLegalEntityId, baseUrl } = useApiContext(); return useCallback((data) => cleanseAddress(rootLegalEntityId.value, baseUrl.value, data), [baseUrl.value, rootLegalEntityId.value]); }; var formatAddressForCleanse = ({ address, otherAddressInformation, city, country, postalCode }) => { if (!address || !country) return void 0; return [ address, otherAddressInformation, city, country, postalCode ].filter(Boolean).join(" "); }; //#endregion //#region src/utils/regex/postalCodePatterns.ts var createRegExpByDigits = (digits) => new RegExp(`^\\d{${digits}}$`); var postalCodePatterns = { [CountryCodes.Australia]: createRegExpByDigits(4), [CountryCodes.Austria]: createRegExpByDigits(4), [CountryCodes.Belgium]: /^[1-9]\d{3}$/, [CountryCodes.Brazil]: createRegExpByDigits(8), [CountryCodes.Bulgaria]: createRegExpByDigits(4), [CountryCodes.Canada]: /^[ABCEGHJKLMNPRSTVXY]\d[A-Z][ -]?(?:\d[A-Z]\d)?$/, [CountryCodes.Croatia]: /^([1-5])\d{4}$/, [CountryCodes.Cyprus]: createRegExpByDigits(4), [CountryCodes.CzechRepublic]: /^\d{3} ?\d{2}$/, [CountryCodes.Denmark]: /^(?:DK-)?\d{4}$/, [CountryCodes.Estonia]: createRegExpByDigits(5), [CountryCodes.Finland]: createRegExpByDigits(5), [CountryCodes.France]: createRegExpByDigits(5), [CountryCodes.Georgia]: createRegExpByDigits(4), [CountryCodes.Germany]: createRegExpByDigits(5), [CountryCodes.Gibraltar]: /^GX11[ -]?1AA$/, [CountryCodes.Greece]: /^\d{3} ?\d{2}$/, [CountryCodes.Hungary]: createRegExpByDigits(4), [CountryCodes.Iceland]: createRegExpByDigits(3), [CountryCodes.Ireland]: /^(?:[ACDEFHKNPRTVWXY]\d{2}|D6W)[ -]?[0-9ACDEFHKNPRTVWXY]{4}$/, [CountryCodes.Italy]: createRegExpByDigits(5), [CountryCodes.Japan]: createRegExpByDigits(7), [CountryCodes.Latvia]: /^(?:LV-)?\d{4}$/, [CountryCodes.Liechtenstein]: createRegExpByDigits(4), [CountryCodes.Lithuania]: /^(?:LT-)?\d{4,5}$/, [CountryCodes.Luxembourg]: createRegExpByDigits(4), [CountryCodes.Malaysia]: createRegExpByDigits(5), [CountryCodes.Malta]: /^[A-Za-z]{2,3} ?\d{2}(?:\d{2})?$/, [CountryCodes.Monaco]: /^980\d{2}$/, [CountryCodes.Netherlands]: /^(?:NL-)?[1-9]\d{3} ?(?:[ABCDEFGHIJKLMNOPQRTUVWXYZ][A-Z]|S[BCEFGHIJKLMNOPQRTUVWXYZ])$/, [CountryCodes.NewZealand]: createRegExpByDigits(4), [CountryCodes.Norway]: createRegExpByDigits(4), [CountryCodes.Poland]: /^\d{2}-\d{3}$/, [CountryCodes.Portugal]: /^[1-9]\d{3}([- ]?\d{3})?$/, [CountryCodes.PuertoRico]: /^\d{5}(?:[ -]?\d{4})?$/, [CountryCodes.Romania]: createRegExpByDigits(6), [CountryCodes.Slovakia]: /^(SK-)?\d{5}$/, [CountryCodes.Slovenia]: /^(SI-)?\d{4}$/, [CountryCodes.Singapore]: createRegExpByDigits(6), [CountryCodes.Spain]: /(?:0[1-9]|[1-4]\d|5[0-2])\d{3}/, [CountryCodes.Sweden]: createRegExpByDigits(5), [CountryCodes.Switzerland]: /^[1-9]\d{3}$/, [CountryCodes.UnitedKingdom]: /^[ABCDEFGHIJKLMNOPRSTUWYZ](?:[ABCDEFGHKLMNOPQRSTUVWXY][0-9][ABEHMNPRVWXY0-9]?|[0-9][ABCDEFGHJKPSTUW0-9]?)(?: ?[0-9][ABDEFGHJLNPQRSTUWXYZ]{1,2})?$/, [CountryCodes.UnitedStates]: /^\d{5}(?:[ -]?\d{4})?$/ }; //#endregion //#region src/components/Shared/forms/Address/validate.formats.ts var createFormatByDigits = (digits) => { return { formatter: (val) => val ? val.replace(getFormattingRegEx("^\\d", "g"), "").substring(0, digits) : void 0, format: new Array(digits).fill("9").join(""), maxlength: digits }; }; var addressDisallowedChars = getFormattingRegEx(SPECIAL_CHARS.replace(/[-(\\/)]/g, "")); var addressFormatters = { postalCode: { formatter: (val, context) => { const specificRule = countrySpecificFormatters[context?.state.data.country]?.postalCode?.formatter; if (specificRule) return specificRule(val); return val; } }, address: { formatter: (val) => val ? trimValWithOneSpace(val).replace(addressDisallowedChars, "") : void 0 }, otherAddressInformation: { formatter: (val) => val ? trimValWithOneSpace(val).replace(addressDisallowedChars, "") : void 0 }, city: { formatter: (val) => val ? trimValWithOneSpace(val).replace(addressDisallowedChars, "") : void 0 } }; var countrySpecificFormatters = { [CountryCodes.Australia]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Austria]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Belgium]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Brazil]: { postalCode: createFormatByDigits(8) }, [CountryCodes.Bulgaria]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Canada]: { postalCode: { format: "A9A 9A9 or A9A9A9", maxlength: 7 } }, [CountryCodes.Croatia]: { postalCode: { format: "[1-5]9999", maxlength: 5 } }, [CountryCodes.Cyprus]: { postalCode: createFormatByDigits(4) }, [CountryCodes.CzechRepublic]: { postalCode: { format: "999 99", maxlength: 6 } }, [CountryCodes.Denmark]: { postalCode: { format: "9999", maxlength: 7 } }, [CountryCodes.Estonia]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Finland]: { postalCode: createFormatByDigits(5) }, [CountryCodes.France]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Germany]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Gibraltar]: { postalCode: { format: "GX11 1AA", maxlength: 8 } }, [CountryCodes.Greece]: { postalCode: { format: "999 99", maxlength: 6 } }, [CountryCodes.Hungary]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Iceland]: { postalCode: createFormatByDigits(3) }, [CountryCodes.Ireland]: { postalCode: { format: "A99 A999", maxlength: 8 } }, [CountryCodes.Italy]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Japan]: { postalCode: createFormatByDigits(7) }, [CountryCodes.Latvia]: { postalCode: { format: "9999 or LV-9999", maxlength: 7 } }, [CountryCodes.Liechtenstein]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Lithuania]: { postalCode: { format: "9999 or 99999 or LT-99999", maxlength: 8 } }, [CountryCodes.Luxembourg]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Malaysia]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Malta]: { postalCode: { format: "2 or 3 letters + 2 or 4 digits (with optional space)", maxlength: 8 } }, [CountryCodes.Monaco]: { postalCode: { format: "980NN", maxlength: 5 } }, [CountryCodes.Netherlands]: { postalCode: { format: "9999AA", maxlength: 7 } }, [CountryCodes.NewZealand]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Norway]: { postalCode: createFormatByDigits(4) }, [CountryCodes.Poland]: { postalCode: { formatter: (val) => { if (!val) return void 0; const nuVal = val.replace(getFormattingRegEx("^\\d-", "g"), ""); const maxlength = nuVal.includes("-") ? 6 : 5; return nuVal.substring(0, maxlength); }, format: "99-999", maxlength: 6 } }, [CountryCodes.Portugal]: { postalCode: { formatter: (val) => { if (!val) return void 0; return val.replace(getFormattingRegEx("^\\d-", "g"), "").substring(0, 8); }, format: "9999-999", maxlength: 8 } }, [CountryCodes.PuertoRico]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Romania]: { postalCode: createFormatByDigits(6) }, [CountryCodes.Singapore]: { postalCode: createFormatByDigits(6) }, [CountryCodes.Slovakia]: { postalCode: { format: "99999 or SK-99999", maxlength: 8 } }, [CountryCodes.Slovenia]: { postalCode: { format: "9999 or SI-9999", maxlength: 7 } }, [CountryCodes.Spain]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Sweden]: { postalCode: createFormatByDigits(5) }, [CountryCodes.Switzerland]: { postalCode: createFormatByDigits(4) }, [CountryCodes.UnitedKingdom]: { postalCode: { formatter: (val) => val ? val.replace(getFormattingRegEx(SPECIAL_CHARS), "").substring(0, 8) : void 0, format: "AA99 9AA or A99 9AA or A9 9AA", maxlength: 8 } }, [CountryCodes.UnitedStates]: { postalCode: { format: "12345 or 12345-6789", maxlength: 10 } } }; //#endregion //#region src/components/Shared/forms/Address/validate.ts var logger = createLogger(); var addressValidationRules = (country) => { const postalCodeFormat = country ? countrySpecificFormatters[country]?.postalCode?.format : void 0; return { address: [{ modes: ["blur"], validate: (val) => hasText(val), errorMessage: "fieldIsRequired" }], postalCode: { modes: ["blur"], validate: (val) => { const pattern = country ? postalCodePatterns[country] : void 0; return pattern ? !!val && pattern.test(val) : !!val; }, errorMessage: postalCodeFormat ? { key: "invalidFormatExpects", values: { format: postalCodeFormat } } : "invalidFormat" }, city: { modes: ["blur"], validate: hasText, errorMessage: "fieldIsRequired" }, stateOrProvince: { modes: ["blur"], validate: (val) => !!val, errorMessage: "fieldIsRequired" }, country: { modes: ["blur"], validate: (val) => !!val, errorMessage: "fieldIsRequired" } }; }; var countrySpecificOtherAddressInformationValidators = (country) => { switch (country) { case CountryCodes.Japan: return [{ modes: ["blur"], validate: (input) => { return hasText(input); }, errorMessage: "checkForTypos" }, { modes: ["blur"], validate: (input) => { return chomeAndBanchiValidator(input); }, errorMessage: "pleaseUseOnlyNumbersAndDashes" }]; default: return; } }; var addressValidationRulesV4 = (country, t) => { const postalCodeFormat = country ? countrySpecificFormatters[country]?.postalCode?.format : void 0; const MIN_LENGTH_3 = 3; const MIN_LENGTH_2 = 2; const otherAddressInformation = countrySpecificOtherAddressInformationValidators(country); return { address: [ { modes: ["blur"], validate: (val) => hasText(val), errorMessage: "fieldIsRequired" }, { modes: ["blur"], validate: (input) => !matchesRegex(NO_ALPHABET_UNICODE_REGEX, input), errorMessage: "nameMustContainLetters" }, { modes: ["blur"], validate: (val) => !matchesRegex(EMOJI_REGEX, val) && !hasRepeatedCharacters(val) && !isInvalidName(val) && matchesRegex(ADDRESS_VALID_CHAR_REGEX, val), errorMessage: "checkForTypos" }, { modes: ["blur"], validate: (val) => isValidMinLength(val, MIN_LENGTH_3), errorMessage: { key: "fieldMustContainAtLeast", values: { fieldName: t(($) => $["address"]), minLength: String(MIN_LENGTH_3) } } } ], postalCode: { modes: ["blur"], validate: (val) => { const pattern = country ? postalCodePatterns[country] : void 0; return pattern ? !!val && pattern.test(val) : !!val; }, errorMessage: postalCodeFormat ? { key: "invalidFormatExpects", values: { format: postalCodeFormat } } : "invalidFormat" }, city: [ { modes: ["blur"], validate: hasText, errorMessage: "fieldIsRequired" }, { modes: ["blur"], validate: (input) => !matchesRegex(NO_ALPHABET_UNICODE_REGEX, input), errorMessage: "nameMustContainLetters" }, { modes: ["blur"], validate: (val) => !matchesRegex(EMOJI_REGEX, val) && !hasMaximumTwoRepeatedCharacters(val) && !isInvalidName(val), errorMessage: "checkForTypos" }, { modes: ["blur"], validate: (val) => isValidMinLength(val, MIN_LENGTH_2), errorMessage: { key: "fieldMustContainAtLeast", values: { fieldName: t(($) => $["city"]), minLength: String(MIN_LENGTH_2) } } } ], stateOrProvince: [ { modes: ["blur"], validate: (val) => !!val, errorMessage: "fieldIsRequired" }, { modes: ["blur"], validate: (input) => !matchesRegex(NO_ALPHABET_UNICODE_REGEX, input), errorMessage: "nameMustContainLetters" }, { modes: ["blur"], validate: (val) => !hasMaximumTwoRepeatedCharacters(val) && !isInvalidName(val), errorMessage: "checkForTypos" } ], country: [ { modes: ["blur"], validate: (val) => !!val, errorMessage: "fieldIsRequired" }, { modes: ["blur"], validate: (input) => !matchesRegex(NO_ALPHABET_REGEX, input), errorMessage: "nameMustContainLetters" }, { modes: ["blur"], validate: (val) => !matchesRegex(EMOJI_REGEX, val) && !isInvalidName(val) && matchesRegex(ADDRESS_VALID_CHAR_REGEX, val), errorMessage: "checkForTypos" } ], otherAddressInformation }; }; var addressValidators = ({ isFeatureEnabled = () => false, country, t }) => ({ ...isFeatureEnabled?.("StrictNameAndAddressValidationV4") ? addressValidationRulesV4(country, t) : addressValidationRules(country) }); var preventPoBoxValidation = (cleanseAddress) => ({ address: { modes: ["blur"], errorMessage: "addressPoBoxError", asyncValidate: async (address, context) => { const formData = context?.state?.data ?? {}; const { country } = formData; if (!address || !country) return true; const text = formatAddressForCleanse({ ...formData, address }); if (!text) return true; try { const { poBox } = await cleanseAddress({ text, country }); return !poBox; } catch (error) { logger.error("Error while checking if address is PO box", error); return true; } } } }); //#endregion //#region src/api/address/useRetrieveAddress.ts var retrieveAddress = async (legalEntityId, baseUrl, addressId) => { return httpGet({ baseUrl, path: `legalEntities/${legalEntityId}/addresses/${addressId}` }); }; /** * @param addressId * @param options additional options passed to Tanstack Query, eg; refetchInterval for polling */ var useRetrieveAddress = (addressId, options) => { const { rootLegalEntityId, baseUrl } = useApiContext(); return useQuery({ queryKey: ["retrieveAddress", addressId], queryFn: () => retrieveAddress(rootLegalEntityId.value, baseUrl.value, addressId), ...options }); }; //#endregion //#region src/api/address/useSearchAddress.ts var searchAddress = async (legalEntityId, baseUrl, data) => { return httpPost({ baseUrl, path: `legalEntities/${legalEntityId}/addresses` }, data); }; /** * @param data * @param options additional options passed to Tanstack Query, eg; refetchInterval for polling */ var useSearchAddress = (data, options) => { const { rootLegalEntityId, baseUrl } = useApiContext(); return useQuery({ queryKey: ["searchAddress", data], queryFn: () => searchAddress(rootLegalEntityId.value, baseUrl.value, data), ...options }); }; //#endregion //#region src/components/Shared/forms/Address/SearchAddressItem.tsx var getFormattedText = (highlightItems, text) => { const formattedText = []; let lastHighlightIndex = 0; if (highlightItems[0] === "") return [text]; highlightItems.forEach((highlightValue) => { const highlightRange = highlightValue.split("-"); const highlightInit = parseInt(highlightRange[0]); const highlightEnd = parseInt(highlightRange[1]); if (lastHighlightIndex < highlightInit) { const remain = text.substring(lastHighlightIndex, highlightInit); formattedText.push(`${remain}`); } const boldText = text.substring(highlightInit, highlightEnd); formattedText.push(/* @__PURE__ */ jsx("span", { className: "adyen-kyc-dropdown-search-element__description--highlight", children: boldText })); lastHighlightIndex = highlightEnd; }); if (lastHighlightIndex < text.length) formattedText.push(`${text.substring(lastHighlightIndex)}`); return formattedText; }; var getHighlightedText = ({ text = "", highlight = "", description = "" }) => { let formattedText = []; if (highlight === "") if (description) formattedText.push(`${text}, ${description}`); else formattedText.push(text); else { const highlightItems = highlight.split(";"); formattedText = getFormattedText(highlightItems[0].split(","), text); if (highlightItems.length > 1) { formattedText.push(`, `); formattedText.push(/* @__PURE__ */ jsx(Fragment, { children: getFormattedText(highlightItems[1].split(","), description) })); } else if (description) formattedText.push(`, ${description}`); } return formattedText; }; var SearchAddressItem = (item) => { const { t } = useTranslation("common"); const { addressAmount } = item; return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", { className: "adyen-kyc-dropdown-search-element__description", children: getHighlightedText(item) }), addressAmount && /* @__PURE__ */ jsxs("div", { className: "adyen-kyc-dropdown-search-element__addresses", children: [ addressAmount, " ", /* @__PURE__ */ jsxs("span", { className: "adyen-kyc-dropdown-search-element__addresses--text", children: [" ", t(($) => $["addresses"])] }), /* @__PURE__ */ jsx(Icon, { name: "arrow-right", className: "adyen-kyc-dropdown-search-element__addresses--icon" }) ] })] }); }; //#endregion //#region src/components/Shared/forms/Address/SearchAddress.tsx var SearchAddress = ({ addressText, country, labelKey, errorMessage, isValid, readOnly, optional, handleBlur, onAddressTextChange, onAutofillAddress }) => { const { t } = useTranslation("common"); const userEvents = useAnalyticsContext(); const [textToSearch, setTextToSearch] = useState(); const [showSearchList, setShowSearchList] = useState(false); const [selectedAddress, setSelectedAddress] = useState(); const [drilldownContainerId, setDrilldownContainerId] = useState(); const debouncedSetTextToSearch = useDebouncedCallback(setTextToSearch, 500); const searchAddressQuery = useSearchAddress({ text: textToSearch, country, container: drilldownContainerId }, { enabled: showSearchList && Boolean(textToSearch) && Boolean(country) }); const retrieveAddressQuery = useRetrieveAddress(selectedAddress?.id ?? "", { enabled: Boolean(selectedAddress) }); const results = useMemo(() => searchAddressQuery.data?.results?.map(formatAddressResult) ?? [], [searchAddressQuery.data?.results]); useEffect(() => { if (retrieveAddressQuery.data) { userEvents.addPageEvent("Success", { actionType: "select", actionLevel: "field", returnType: "backend", returnValue: "retrieveAddress" }); onAutofillAddress(retrieveAddressQuery.data); } }, [retrieveAddressQuery.data]); const onSelectItem = useCallback((selected) => { const selectedResult = results.find((i) => i.id === selected.id); if (!selectedResult) return; if (selectedResult.type === "Address") { setSelectedAddress(selected); setDrilldownContainerId(void 0); } else { setDrilldownContainerId(selectedResult.id); setTextToSearch(`${selectedResult.text}`); setTimeout(() => setShowSearchList(true)); } }, [results]); const items = useMemo(() => results.map((item) => ({ ...item, name: item.text })), [results]); return /* @__PURE__ */ jsx(Field, { name: "address", label: translateTranslatable(t, labelKey), errorMessage, isValid, optional, children: (childProps) => /* @__PURE__ */ jsx(Select, { ...childProps, name: "address", filterable: "prefiltered", items, selected: selectedAddress, loading: searchAddressQuery.isLoading || retrieveAddressQuery.isLoading, onSelect: onSelectItem, getSearchItem: SearchAddressItem, behaviour: "textIsData", text: addressText, setText: (text) => { onAddressTextChange(text); debouncedSetTextToSearch(text); }, showList: showSearchList, setShowList: setShowSearchList, readonly: Boolean(readOnly), placeholder: t(($) => $["address__placeHolder"]), onBlur: handleBlur }) }); }; var formatAddressResult = (item) => { if (item.description.includes("Addresses")) { const splitDescription = item.description.split(" - "); if (splitDescription.length === 1) return { ...item, description: "", addressAmount: splitDescription[0].replace("Addresses", "") }; return { ...item, description: splitDescription[0], addressAmount: splitDescription[1].replace("Addresses", "") }; } return item; }; //#endregion //#region src/components/Shared/fields/StateField/fieldConfig.ts var defaultFieldMetadata = { label: "stateOrProvince", validators: validateNotEmptyOnBlur }; var defaultFieldConfig = { [CountryCodes.Australia]: { label: "state", validators: validateNotEmptyOnBlur }, [CountryCodes.Brazil]: { label: "state", validators: validateNotEmptyOnBlur }, [CountryCodes.Canada]: { label: "provinceOrTerritory", validators: validateNotEmptyOnBlur }, [CountryCodes.NewZealand]: { label: "region", validators: validateNotEmptyOnBlur }, [CountryCodes.UnitedStates]: ({ isBusiness }) => ({ label: isBusiness ? "whereIsYourBusinessRegistered" : "state", validators: validateNotEmptyOnBlur }) }; /** * Returns the placeholder text for state field based on country. */ var getStatePlaceholderText = (t, { country }) => { switch (country) { case CountryCodes.Australia: case CountryCodes.Brazil: return t(($) => $["selectState"]); case CountryCodes.Canada: return t(($) => $["selectProvinceOrTerritory"]); case CountryCodes.UnitedStates: return t(($) => $[`selectAState`]); default: return t(($) => $["stateOrProvince__placeHolder"]); } }; //#endregion //#region src/components/Shared/fields/StateField/StateField.tsx var STATE_FIELD = ["stateOrProvince"]; function StateField({ data, valid, errors, labels, readonly, handleChangeFor, selectedCountry, handleBlur }) { const { t } = useTranslation("common"); const { dataset: states, loaded } = useDataset(datasetIdentifier.state(selectedCountry), !selectedCountry || !COUNTRIES_WITH_STATES_DATASET.includes(selectedCountry)); const labelKey = getKeyForField("stateOrProvince", selectedCountry); if (!loaded || !states.length) return null; return /* @__PURE__ */ jsx(Field, { name: "stateOrProvince", label: labels?.stateOrProvince || t(($) => $[labelKey]), errorMessage: errors.stateOrProvince, isValid: valid.stateOrProvince, dataTestId: "stateOrProvince", children: (childProps) => /* @__PURE__ */ jsx(Select, { ...childProps, name: "stateOrProvince", selected: data.stateOrProvince, placeholder: getStatePlaceholderText(t, { country: selectedCountry }), items: states, readonly: readonly && !!data.stateOrProvince, onChange: handleChangeFor("stateOrProvince"), onBlur: handleBlur }) }); } //#endregion //#region src/components/Shared/forms/Address/AddressField.tsx /** * USAGE: Specifically defined as a util to provide a wrapper for fields created within the Address component * * NOT TO BE USED: if you just want to add a Country or State dropdown outside of an Address component * - then you should implement <CountryField> or <StateField> directly */ function AddressField({ schema, data, valid, errors, fieldProblems, fieldName, trimOnBlur, hideField, maxlength, readOnly, optional, handleChangeFor, handleBlur }) { const { t } = useTranslation("common"); const { data: providerStatus } = useProviderStatus({ providers: ["address"] }); const addressSearchEnabled = providerStatus?.statuses?.address?.enabled ?? false; const formUtils = createFormUtils({ data }, t); const errorMessage = formUtils.getErrorMessage(fieldName, errors ?? {}, fieldProblems); const value = data[fieldName]; const labelKey = getKeyForField(fieldName, data.country); const setAddressFieldFromFoundAddress = useCallback(({ houseNumberOrName, street, line1 }) => { const hasHouseNumber = !!houseNumberOrName; if (!street && line1) return handleChangeFor("address", "input")(line1); if (hasHouseNumber) { const formattedAddress = (data.country ? COUNTRIES_WITH_HOUSE_NUMBER_FIRST.includes(data.country) : false) ? `${houseNumberOrName} ${street}` : `${street} ${houseNumberOrName}`; return handleChangeFor("address", "input")(formattedAddress); } return handleChangeFor("address", "input")(street); }, [data.country, handleChangeFor]); const onAutofillAddress = useCallback((foundAddress) => { schema?.forEach((field) => { switch (field) { case "country": handleChangeFor("country", "input")(foundAddress.country ?? " "); break; case "address": setAddressFieldFromFoundAddress(foundAddress); break; case "otherAddressInformation": handleChangeFor("otherAddressInformation", "blur")(foundAddress.street2 ?? " "); break; case "city": handleChangeFor("city", "input")(foundAddress.city ?? " "); break; case "postalCode": handleChangeFor("postalCode", "input")(foundAddress.postalCode ?? " "); break; case "stateOrProvince": handleChangeFor("stateOrProvince", "input")(foundAddress.stateOrProvince ?? " "); break; default: break; } }); }, [ handleChangeFor, schema, setAddressFieldFromFoundAddress ]); if (hideField) return null; switch (fieldName) { case "address": return addressSearchEnabled ? /* @__PURE__ */ jsx(SearchAddress, { addressText: data.address, country: data.country, labelKey, errorMessage, isValid: valid?.address, readOnly, optional, handleBlur: (e) => { handleChangeFor("address", "blur")(data.address); handleBlur?.(e); }, onAddressTextChange: handleChangeFor("address", "input"), onAutofillAddress }) : /* @__PURE__ */ jsx(Field, { name: fieldName, label: t(($) => $[labelKey]), errorMessage, isValid: valid?.[fieldName], optional, children: (childProps) => /* @__PURE__ */ jsx(InputText, { ...childProps, name: fieldName, value, onInput: handleChangeFor(fieldName, "input"), onBlur: (e) => { handleChangeFor(fieldName, "blur")(e); handleBlur?.(e); }, maxLength: maxlength, "aria-required": true, "aria-invalid": !valid?.[fieldName], trimOnBlur, readonly: Boolean(readOnly) }) }); case "country": return /* @__PURE__ */ jsx(CountryField, { data: { country: value }, valid: { country: valid?.country }, errors: { country: errorMessage }, labels: { country: formUtils.getLabel(fieldName, labelKey) }, readonly: Boolean(readOnly), handleChangeFor, handleBlur }); case "stateOrProvince": return /* @__PURE__ */ jsx(StateField, { data: { stateOrProvince: value }, valid: { stateOrProvince: valid?.stateOrProvince }, errors: { stateOrProvince: errorMessage }, labels: { stateOrProvince: formUtils.getLabel(fieldName, labelKey) }, readonly: Boolean(readOnly), selectedCountry: data.country, handleChangeFor, handleBlur }); default: return /* @__PURE__ */ jsx(Field, { name: fieldName, label: t(($) => $[labelKey]), errorMessage, isValid: valid?.[fieldName], optional, children: (childProps) => /* @__PURE__ */ jsx(InputText, { ...childProps, name: fieldName, value: fieldName === "postalCode" ? value?.toUpperCase() : value, onInput: handleChangeFor(fieldName, "input"), onBlur: (e) => { handleChangeFor(fieldName, "blur")(e); handleBlur?.(e); }, maxLength: maxlength, "aria-required": true, "aria-invalid": !valid?.[fieldName], trimOnBlur, readonly: Boolean(readOnly) }) }); } } //#endregion //#region src/components/Shared/forms/Address/Address.tsx function Address({ data: dataProp, labels, readOnly, hideCountry, fieldValidationErrors: propFieldValidationErrors, allFields, requiredFields, optionalFields = ["otherAddressInformation"], readOnlyFields, obscuredFields, trustedFields, shouldValidate, onChange, verifiedAddress, condensed, handleFieldChange, errors: errorProp, valid: validProp, addressType }) { const { t } = useTranslation("common"); const { isFeatureEnabled } = useToggleContext(); const isStrictNameAndAddressValidationEnabled = isFeatureEnabled("StrictNameAndAddressValidationV4"); const preventPoBoxes = addressType === "operationalAddress"; const schema = useMemo(() => { if (requiredFields?.length) return requiredFields?.includes("stateOrProvince") || dataProp?.country && COUNTRIES_WITH_STATES_DATASET.includes(dataProp?.country) ? requiredFields : requiredFields?.filter((field) => field !== "stateOrProvince"); return dataProp?.country && COUNTRIES_WITH_STATES_DATASET.includes(dataProp?.country) ? getAddressSchemaForCountry(dataProp?.country) : getAddressSchemaForCountry(dataProp?.country).filter((ad) => ad !== "stateOrProvince"); }, [dataProp?.country, requiredFields]); const rules = useMemo(() => addressValidationRules(dataProp?.country), [dataProp?.country]); const rulesV4 = useMemo(() => addressValidationRulesV4(dataProp?.country, t), [dataProp?.country, t]); const cleanseAddress = useAddressCleanseImperatively(); const asyncRules = useMemo(() => preventPoBoxes ? preventPoBoxValidation(cleanseAddress) : void 0, [cleanseAddress, preventPoBoxes]); const form = useForm({ schema, defaultData: dataProp, formatters: addressFormatters, rules: isStrictNameAndAddressValidationEnabled ? rulesV4 : rules, asyncRules, fieldProblems: propFieldValidationErrors, optionalFields, obscuredFields, trustedFields, shouldValidate }); let { schema: formSchema, data: formData, errors: formErrors, valid: formValid, fieldProblems: formFieldProblems, handleChangeFor } = form; const { isValid } = form; if (handleFieldChange && requiredFields && propFieldValidationErrors) { const allFields = [...requiredFields, ...optionalFields]; const fieldsInOrder = getAddressSchemaForCountry(dataProp?.country).filter((field) => allFields.includes(field)); handleChangeFor = handleFieldChange; formData = dataProp ?? {}; formErrors = errorProp; formValid = validProp; formFieldProblems = propFieldValidationErrors; formSchema = fieldsInOrder; } /** * Updates local useForm data with either the verified address data or the default data */ useEffect(() => { if (verifiedAddress) entriesOf(verifiedAddress).forEach(([key, value]) => { if (formData[key] !== value) handleChangeFor(key, "input")(value); }); }, [verifiedAddress]); const formUtils = createFormUtils({ data: dataProp, labels, readOnly, allFields, requiredFields: schema, optionalFields, readOnlyFields, trustedFields }, t); useEffect(() => { if (hideCountry && dataProp?.country && dataProp.country !== formData.country) schema.forEach((field) => { return field === "country" ? handleChangeFor("country", "input")(dataProp.country) : handleChangeFor(field, "input")(" "); }); }, [dataProp?.country, hideCountry]); useEffect(() => { onChange?.({ schema: formSchema, data: formData, valid: formValid, errors: formErrors, fieldProblems: formFieldProblems, isValid }); }, [ formData, formErrors, formFieldProblems, formSchema, formValid, isValid ]); const createField = (fieldName) => { if (!formUtils.isRequiredField(fieldName) && !formUtils.isOptionalField(fieldName)) return null; const hideField = fieldName === "country" && hideCountry; return /* @__PURE__ */ jsx(AddressField, { schema: formSchema, data: formData, valid: formValid, errors: formErrors, fieldProblems: formFieldProblems, fieldName, maxlength: getMaxLengthByFieldAndCountry(countrySpecificFormatters, fieldName, formData.country, true), hideField, readOnly: formUtils.isReadOnly(fieldName) || formUtils.isTrusted(fieldName), optional: formUtils.isOptionalField(fieldName), trimOnBlur: true, handleChangeFor }, fieldName); }; if (condensed && formData?.country) { const condensedFields = CONDENSED_ADDRESS_FIELDS[formData.country] ?? []; switch (formData?.country) { case "US": return /* @__PURE__ */ jsxs("fieldset", { "aria-label": t(($) => $[addressType]), children: [formSchema.filter((field) => !condensedFields.includes(field)).map((filteredField) => createField(filteredField)), condensedFields.length > 0 && /* @__PURE__ */ jsx("div", { className: "adyen-kyc-address__condensed-fields", children: condensedFields.map((field) => createField(field)) })] }); default: return /* @__PURE__ */ jsx("fieldset", { "aria-label": t(($) => $[addressType]), children: formSchema.map((field) => createField(field)) }); } } return /* @__PURE__ */ jsx("fieldset", { "aria-label": t(($) => $[addressType]), children: formSchema.map((field) => createField(field)) }); } //#endregion export { defaultFieldMetadata as a, addressValidators as c, useProviderStatus as d, defaultFieldConfig as i, formatAddressForCleanse as l, STATE_FIELD as n, addressValidationRules as o, StateField as r, addressValidationRulesV4 as s, Address as t, useAddressCleanse as u };