@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
JavaScript
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 };