@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.
1,177 lines (1,176 loc) • 41.2 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] = "513e60b7-9336-46b7-bb24-3f0d67f6207a", e._sentryDebugIdIdentifier = "sentry-dbid-513e60b7-9336-46b7-bb24-3f0d67f6207a");
} catch (e) {}
import { n as addResourceBundles, o as createLogger, r as useTranslation, s as initReactI18next } from "./translation-BFxyJ1c5.js";
import { r as Loader, t as Button } from "./Button-oj6H8OrC.js";
import { a as setSdkTokenHandler, i as refreshSession, n as httpGet, o as ApiProvider, r as httpPost, s as useApiContext } from "./http-D1NDkBxF.js";
import { r as useLegalEntity, t as ROOT_LE } from "./useLegalEntity-yxi9XhLi.js";
import { t as getLegalEntityCountry } from "./getLegalEntityCountry-C6bSV6sB.js";
import { t as useAccountHolder } from "./useAccountHolder-ClppK4-L.js";
import { n as SettingsContext, t as useSettingsContext } from "./useSettingsContext-DzwVt0W0.js";
import { d as keysOf, n as AnalyticsContext, o as listify, s as noop, t as useAnalyticsContext } from "./useAnalyticsContext-BVFDMrVE.js";
import { n as ToggleContext, t as useToggleContext } from "./useToggleContext-DaQUBF8O.js";
import { i as parseLocale, o as FALLBACK_LOCALE, r as getTranslationByKey, s as defaultTranslation, t as formatLocale } from "./utils-B807QaDx.js";
import { t as StateContext } from "./StateContext-BToC3V53.js";
import { y as isEmpty } from "./validatorUtils-DRapRJ6z.js";
import { t as ToastContextProvider } from "./ToastContextProvider-C-7n4Tu6.js";
import { t as listToRecord } from "./listToRecord-4wGOf00H.js";
import { t as _rolldown_dynamic_import_helper_default } from "./_rolldown_dynamic_import_helper-rq_tsyLP.js";
import { t as Header } from "./Header-CPmJyuoP.js";
import { t as useAllowedCountries } from "./useAllowedCountries-x3yZO5Qw.js";
import { t as useDataset } from "./useDataset-ZHrWhmsh.js";
import { t as datasetIdentifier } from "./datasetUtil-Zd4TCTDn.js";
import { n as Skeleton } from "./Accordion-Btxq6sGi.js";
import { n as AlertIcon } from "./Alert-C6gL3JIt.js";
import { t as DropinLayout } from "./DropinLayout-Ce8IeTl4.js";
import { n as createGlobalStore, t as StoreContext } from "./globalStore-BjMds47R.js";
import i18n from "i18next";
import { Suspense, lazy } from "preact/compat";
import { useCallback as useCallback$1, useContext as useContext$1, useEffect as useEffect$1, useMemo as useMemo$1, useReducer, useState as useState$1 } from "preact/hooks";
import { Fragment as Fragment$1, jsx, jsxs } from "preact/jsx-runtime";
import { QueryCache, QueryClient, QueryClientProvider, useMutation, useQuery } from "@tanstack/preact-query";
import { createContext as createContext$1 } from "preact";
//#region node_modules/.pnpm/vite-plugin-shadow-styles@0.0.3_vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_sass@1.99.0_/node_modules/vite-plugin-shadow-styles/dist/stylesheets.js
var sheet = new CSSStyleSheet();
var stylesheets = [sheet];
import("./styles-BKzp-1_V.js").then(({ css }) => {
sheet.replaceSync(css);
}).catch((err) => console.error("Error loading styles", err));
//#endregion
//#region src/language/i18n.ts
/**
* Initializes i18next and defines configurations
* i18next-resources-to-backend is a simple plugin used for the lazy loading of translation resources
*/
i18n.use(initReactI18next).init({
defaultNS: false,
fallbackLng: "en-US",
load: "currentOnly",
resources: {},
showSupportNotice: false,
react: {
transSupportBasicHtmlNodes: true,
transKeepBasicHtmlNodesFor: [
"strong",
"i",
"em"
],
bindI18n: "languageChanged",
bindI18nStore: "added"
},
interpolation: {
prefix: "%{",
suffix: "}"
}
});
//#endregion
//#region src/api/configurations/useVersionConfiguration.ts
/**
* Retrieves information about the onboarding version and version-specific features to enable
* linked to the legalEntityId
*/
var getVersionConfiguration = async (legalEntityId, baseUrl) => {
return httpGet({
baseUrl,
path: `legalEntities/${legalEntityId}/configurations/version`
});
};
var useVersionConfiguration = (options) => {
const { rootLegalEntityId, baseUrl } = useApiContext();
return useQuery({
queryKey: ["versionConfiguration"],
queryFn: () => getVersionConfiguration(rootLegalEntityId.value, baseUrl.value),
...options
});
};
//#endregion
//#region src/api/uiAnalytics/useAnalyticsSession.ts
/**
* @description Request to get an analytics session ID and fire an "Initiate session" event on Mixpanel
* @param data.userData Sets user profile properties on Mixpanel
* @returns a session id that is sent with every subsequent log event request
*/
var getAnalyticsSession = async (baseUrl, data) => {
return httpPost({
baseUrl,
path: `analytics/ui`
}, data);
};
var useAnalyticsSession = (sessionData, onboardingVersion, options) => {
const { baseUrl } = useApiContext();
return useQuery({
queryKey: ["analyticsSession", onboardingVersion],
queryFn: () => getAnalyticsSession(baseUrl.value, sessionData),
enabled: Boolean(onboardingVersion),
...options
});
};
//#endregion
//#region src/core/user-events.ts
var UserEvents = class {
queue = [];
subscriptions = /* @__PURE__ */ new Set();
/** payload of commmon props sent in every event */
baseTrackingPayload;
/** properties not set with every event but that may be shared between some events
* ex. `page` value for `Interacted with form field` events
*/
sharedEventProperties;
constructor() {
this.baseTrackingPayload = {
category: "onboarding",
subCategory: "hosted onboarding"
};
this.sharedEventProperties = {};
}
add(...args) {
this.queue.push(...args);
}
notifySubscribers() {
while (this.queue.length > 0) {
const lastEvent = this.queue.pop();
this.subscriptions.forEach((callback) => callback(lastEvent));
}
}
/**
* Adds an analytics event with all base event properties.
*/
addEvent(eventName, properties) {
const completeEvent = {
...this.baseTrackingPayload,
...properties
};
this.add({
type: "add_event",
name: eventName,
properties: completeEvent
});
this.notifySubscribers();
}
/**
* Adds an event with context specific to journey-related events
*/
addJourneyEvent(eventName, properties) {
this.addEvent(eventName, {
actionLevel: "journey",
...properties
});
}
/**
* Adds an event with context specific to task-related events
*/
addTaskEvent(eventName, properties) {
this.addEvent(eventName, {
actionLevel: "task",
...properties
});
}
/**
* Adds an event with context specific to page-related events
*/
addPageEvent(eventName, properties) {
this.addEvent(eventName, {
actionLevel: "page",
page: this.sharedEventProperties.page,
...properties
});
}
/**
* Adds an event with context specific to field-related events
*/
addFieldEvent(eventName, properties) {
this.addEvent(eventName, {
actionLevel: "field",
page: this.sharedEventProperties.page,
...properties
});
}
/**
* Tracks an experiment for Mixpanel experiment reporting
*/
trackExperiment({ name, variant }) {
this.add({
type: "add_event",
name: "$experiment_started",
properties: {
...this.baseTrackingPayload,
"Experiment name": name,
"Variant name": variant
}
});
}
/**
* Subscribes a callback to analytics events. It gets called every time
* one of the above public methods get called, and the event data is passed back as an array.
* The callback must have a single argument which is an array of [eventName, eventPayload?].
* @example
* ```js
* const callback = ([eventName, eventPayload]) => console.log(eventName, eventPayload);
* this.subscribe(callback);
*
* const exampleEventPayload = { count: 1, segmentation: { foo: 'bar' } };
* this.addEvent('exampleEventDidOccur', exampleEventPayload);
*
* // `callback` will get called with `['exampleEventDidOccur', exampleEventPayload]`
* ```
*/
subscribe(callback) {
this.subscriptions.add(callback);
}
/**
* Sets params that are sent on every event
* */
updateBaseTrackingPayload(baseTrackingPayload) {
this.baseTrackingPayload = {
...this.baseTrackingPayload,
...baseTrackingPayload
};
}
/**
* Sets params that may be shared between events
* */
updateSharedEventProperties = (props) => {
this.sharedEventProperties = {
...this.sharedEventProperties,
...props
};
};
/**
* Removes a subscribed callback
*/
unsubscribe(callback) {
if (this.subscriptions.has(callback)) this.subscriptions.delete(callback);
}
};
var createUserEvents = () => {
return new UserEvents();
};
//#endregion
//#region src/api/uiAnalytics/usePushAnalyticEvent.ts
var pushAnalyticEvent = async (baseUrl, sessionId, data) => {
return httpPost({
baseUrl,
path: `analytics/ui/${sessionId}`
}, data);
};
var usePushAnalyticEvent = (sessionId, options) => {
const { baseUrl } = useApiContext();
return useMutation({
mutationFn: (data) => pushAnalyticEvent(baseUrl.value, sessionId, data),
...options
});
};
//#endregion
//#region src/utils/analytics/convertToEmbeddedEvent.ts
var convertToEmbeddedEvent = (eventQueueItem, sessionData) => {
const { type, name, properties } = eventQueueItem;
return {
eventName: name,
eventType: type,
eventData: properties || {},
legalEntityId: sessionData.legalEntityId,
userAgent: sessionData.userAgent,
componentName: sessionData.componentName,
sdkVersion: sessionData.sdkVersion
};
};
//#endregion
//#region src/utils/analytics/getAnalyticsAssociatedEntityDetails.ts
/**
* Gets associated legal entity type and ID for the base tracking payload
* Based on selected account holder type
*/
var getAnalyticsAssociatedEntityDetails = (rootLegalEntity, accountHolderType) => {
let associatedLegalEntityType;
switch (accountHolderType) {
case "aTrust":
associatedLegalEntityType = "trust";
break;
case "mySoleProprietorName":
associatedLegalEntityType = "soleProprietorship";
break;
case "anUnincorporatedPartnership":
associatedLegalEntityType = "unincorporatedPartnership";
break;
default: associatedLegalEntityType = void 0;
}
const associatedLegalEntity = rootLegalEntity.entityAssociations?.find((ea) => ea.type === associatedLegalEntityType);
return {
associatedLegalEntityType,
associatedLegalEntityId: associatedLegalEntity?.legalEntityId
};
};
//#endregion
//#region src/hooks/useAnalytics/useAnalytics.ts
var useAnalytics = ({ userEvents, sessionId, sessionData }) => {
const sdkVersion = "4.9.0";
const { data: rootLegalEntity } = useLegalEntity(ROOT_LE);
const { mutateAsync } = usePushAnalyticEvent(sessionId ?? "");
const { accountHolder } = useAccountHolder();
useEffect$1(() => {
if (!rootLegalEntity) return;
const countryCode = getLegalEntityCountry(rootLegalEntity);
const capabilities = Object.keys(rootLegalEntity?.capabilities ?? {});
userEvents.updateBaseTrackingPayload({
entityType: rootLegalEntity.type,
countryCode,
capabilities,
sdkVersion,
componentName: sessionData.componentName,
userAgent: navigator.userAgent,
...getAnalyticsAssociatedEntityDetails(rootLegalEntity, accountHolder)
});
}, [
rootLegalEntity,
accountHolder,
sdkVersion,
sessionData.componentName,
userEvents
]);
const pushEvents = useCallback$1((data) => {
mutateAsync(convertToEmbeddedEvent(data, sessionData));
}, [mutateAsync, sessionData]);
useEffect$1(() => {
if (!sessionId) return;
userEvents.subscribe(pushEvents);
return () => {
userEvents.unsubscribe(pushEvents);
};
}, [
sessionId,
mutateAsync,
userEvents,
sessionData,
pushEvents
]);
};
//#endregion
//#region src/utils/analytics/getPrefilledDetails.ts
var getOrganizationPrefilledFields = (organization) => {
const { dateOfIncorporation, financialReports, registeredAddress, registrationNumber, support, taxInformation, type, vatNumber } = organization;
const financialReport = financialReports?.[0];
return {
dateOfIncorporation: !!dateOfIncorporation,
financialReport: {
annualTurnover: !!financialReport?.annualTurnover,
balanceSheetTotal: !!financialReport?.balanceSheetTotal,
dateOfFinancialData: !!financialReport?.dateOfFinancialData,
employeeCount: !!financialReport?.employeeCount
},
registeredAddress: {
city: !!registeredAddress?.city,
postalCode: !!registeredAddress?.postalCode,
stateOrProvince: !!registeredAddress?.stateOrProvince,
street: !!registeredAddress?.street
},
registrationNumber: !!registrationNumber,
support: {
email: !!support?.email,
phone: !!support?.phone
},
taxInformation: !!taxInformation?.some((taxInfo) => taxInfo.country && taxInfo.number),
type: !!type,
vatNumber: !!vatNumber
};
};
var getPrefilledDetails = (legalEntity) => {
if (!legalEntity) return;
const { organization, transferInstruments, entityAssociations } = legalEntity;
return {
transferInstrumentCount: transferInstruments?.length || 0,
entityAssociations: entityAssociations?.map((entity) => entity.type) || [],
organization: organization && getOrganizationPrefilledFields(organization)
};
};
//#endregion
//#region src/context/AnalyticsContext/AnalyticsProvider.tsx
/**
* The provider exists to scope analytics to one application instance.
* This would otherwise be problematic when a consumer might have several
* instantiations of a embedded Component for instance on the same page
*/
var AnalyticsProvider = ({ componentName, children, rootLegalEntityId }) => {
const { settings } = useSettingsContext();
const { data: rootLegalEntity } = useLegalEntity(ROOT_LE);
const { data: versionData, isError, isLoading } = useVersionConfiguration();
const userEvents = useMemo$1(() => createUserEvents(), []);
const onboardingVersion = isLoading ? void 0 : isError ? 1 : versionData?.version;
const capabilities = rootLegalEntity?.capabilities && Object.keys(rootLegalEntity.capabilities);
const shouldTrackPrefilledDetails = capabilities?.includes("receivePayments") && onboardingVersion && onboardingVersion > 1;
const sessionData = {
sdkVersion: "4.9.0",
componentName,
userAgent: navigator.userAgent,
legalEntityId: rootLegalEntityId,
capabilities,
entityType: rootLegalEntity?.type,
eventData: shouldTrackPrefilledDetails ? getPrefilledDetails(rootLegalEntity) : void 0,
userData: {
onboardingVersion,
isDirectMerchant: settings.merchantType === "direct",
settings,
country: rootLegalEntity && getLegalEntityCountry(rootLegalEntity)
}
};
const { data } = useAnalyticsSession(sessionData, onboardingVersion);
useAnalytics({
userEvents,
sessionId: data?.id,
sessionData
});
return /* @__PURE__ */ jsx(AnalyticsContext.Provider, {
value: userEvents,
children
});
};
//#endregion
//#region src/language/loadLocale.ts
var localeImports = /* @__PURE__ */ Object.assign({
"./locales/bg-BG.json": () => import("./bg-BG-COHRuTI-.js"),
"./locales/cs-CZ.json": () => import("./cs-CZ-CmcYZLZp.js"),
"./locales/da-DK.json": () => import("./da-DK-C_oe1bpM.js"),
"./locales/de-DE.json": () => import("./de-DE-CMc1Fpfl.js"),
"./locales/el-GR.json": () => import("./el-GR-Bv2QgmVV.js"),
"./locales/en-US.instructions.json": () => import("./en-US.instructions-DJharl6b.js"),
"./locales/en-US.json": () => import("./en-US-cJAmQhFR.js").then((n) => n.n),
"./locales/es-ES.json": () => import("./es-ES-DtlXpZ_5.js"),
"./locales/et-EE.json": () => import("./et-EE-PTcJ2hRW.js"),
"./locales/fi-FI.json": () => import("./fi-FI-C1Ns3CEo.js"),
"./locales/fr-FR.json": () => import("./fr-FR-DgPRYmmJ.js"),
"./locales/hr-HR.json": () => import("./hr-HR-BQfjrcPC.js"),
"./locales/hu-HU.json": () => import("./hu-HU-DfYPelYo.js"),
"./locales/it-IT.json": () => import("./it-IT-cnETv3Cg.js"),
"./locales/ja-JP.json": () => import("./ja-JP-D0gz56Ni.js"),
"./locales/lt-LT.json": () => import("./lt-LT-Bbh9MWxc.js"),
"./locales/lv-LV.json": () => import("./lv-LV-C8fqHR2g.js"),
"./locales/nl-NL.json": () => import("./nl-NL-CQSu4iNn.js"),
"./locales/no-NO.json": () => import("./no-NO-C0DXekH-.js"),
"./locales/pl-PL.json": () => import("./pl-PL-10KUcobm.js"),
"./locales/pt-BR.json": () => import("./pt-BR-DWKF33yP.js"),
"./locales/pt-PT.json": () => import("./pt-PT-CjIFIi4R.js"),
"./locales/ro-RO.json": () => import("./ro-RO-DQFRJwp8.js"),
"./locales/sk-SK.json": () => import("./sk-SK-BfoXFhAL.js"),
"./locales/sl-SI.json": () => import("./sl-SI-CyIN1sc5.js"),
"./locales/sv-SE.json": () => import("./sv-SE-Xh17T6yC.js")
});
var loadLocale = async (locale) => {
const importForLocale = localeImports[`./locales/${locale}.json`];
if (!importForLocale) throw new Error(`Locale ${locale} is not supported.`);
return (await importForLocale()).default;
};
//#endregion
//#region src/hooks/useTranslations.ts
var logger$1 = createLogger();
var useTranslations = ({ locale, allowedLocales }) => {
const [loaded, setLoaded] = useState$1({
translations: defaultTranslation,
locale: FALLBACK_LOCALE
});
useEffect$1(() => {
if (!allowedLocales) return;
const isLocaleAllowed = allowedLocales.includes(locale);
const localeToUse = isLocaleAllowed ? locale : FALLBACK_LOCALE;
if (loaded.locale === localeToUse) return;
if (!isLocaleAllowed) logger$1.error(`\n"${locale}" isn't a supported locale. Please use one of the following:\n- ${listify(allowedLocales)}. falling back to "${FALLBACK_LOCALE}"`);
if (localeToUse === "en-US") {
setLoaded({
translations: defaultTranslation,
locale: FALLBACK_LOCALE
});
return;
}
loadLocale(localeToUse).then((dataset) => {
setLoaded({
translations: dataset,
locale: localeToUse
});
}).catch((err) => {
logger$1.error("Error while loading translations", err);
});
}, [
locale,
allowedLocales,
loaded.locale
]);
return loaded;
};
//#endregion
//#region src/language/Language.ts
var Language = class {
supportedLocales;
translations;
/**
* @deprecated in favor of the `language` property returned from the
* i18n instance from i18next
*
* @example
* ```tsx
* const { i18n } = useTranslation('common');
* console.log(`${i18n.language} is the selected language code`); // ex. "en-US"
* ```
*/
locale;
constructor({ locale = FALLBACK_LOCALE, translations = defaultTranslation, allowedLocales = [FALLBACK_LOCALE] }) {
this.supportedLocales = [...new Set([FALLBACK_LOCALE, ...allowedLocales])];
const determinedLocale = formatLocale(locale) ?? parseLocale(locale, this.supportedLocales);
this.locale = determinedLocale && this.supportedLocales.includes(determinedLocale) ? determinedLocale : FALLBACK_LOCALE;
this.translations = {
...defaultTranslation,
...translations
};
}
/**
* Returns a translated string from a key in the current {@link Language.locale}
* @returns Translated string in the user's locale
* @deprecated we now have i18next for i18n, check out {@link /src/language/README.md} for more details and examples
*/
get(translatable, translationOptions) {
const key = typeof translatable === "object" ? translatable.key : translatable;
const options = typeof translatable === "object" ? {
...translationOptions,
values: {
...translatable.values,
...translationOptions?.values
}
} : translationOptions;
const translation = getTranslationByKey(this.translations, key, options);
if (translation !== null) return translation;
return key;
}
};
var I18nContext = createContext$1({
i18n: new Language({}),
setLocale: noop
});
/**
* @deprecated in favor of I18next's `useTranslation`
*/
var useI18nContext = () => useContext$1(I18nContext);
//#endregion
//#region src/context/I18nProvider/I18nProvider.tsx
var allowedLocales = [
"bg-BG",
"cs-CZ",
"da-DK",
"de-DE",
"el-GR",
"en-US",
"es-ES",
"et-EE",
"fi-FI",
"fr-FR",
"hr-HR",
"hu-HU",
"it-IT",
"lt-LT",
"lv-LV",
"nl-NL",
"no-NO",
"pl-PL",
"pt-PT",
"pt-BR",
"ro-RO",
"sk-SK",
"sl-SI",
"sv-SE"
];
/** Translations provider, reacts on language change */
var I18nProvider = ({ locale: propLocale, eventEmitter, children }) => {
const userEvents = useAnalyticsContext();
const { isFeatureEnabled } = useToggleContext();
const { i18n: i18next } = useTranslation("common");
const [locale, setLocale] = useState$1(propLocale);
const [prevPropLocale, setPrevPropLocale] = useState$1(propLocale);
if (isFeatureEnabled("EnableJapanLocalization")) allowedLocales.push("ja-JP");
const { translations, locale: loadedLocale } = useTranslations({
locale,
allowedLocales
});
const i18n = useMemo$1(() => new Language({
locale: loadedLocale,
translations,
allowedLocales
}), [loadedLocale, translations]);
useEffect$1(() => {
userEvents.updateBaseTrackingPayload({ locale });
}, [locale, userEvents]);
useEffect$1(() => {
(async () => {
if (locale === "ja-JP" && !isFeatureEnabled("EnableJapanLocalization")) return;
i18next.changeLanguage(locale);
})();
}, [
locale,
i18next,
isFeatureEnabled
]);
const contextValue = useMemo$1(() => ({
i18n,
setLocale
}), [i18n, setLocale]);
if (propLocale !== prevPropLocale) {
setLocale(propLocale);
setPrevPropLocale(propLocale);
}
useEffect$1(() => {
if (!eventEmitter) return;
eventEmitter.on("updateLocale", setLocale);
return () => eventEmitter.off("updateLocale", setLocale);
}, [eventEmitter]);
return /* @__PURE__ */ jsx(I18nContext.Provider, {
value: contextValue,
children: /* @__PURE__ */ jsx(Suspense, {
fallback: /* @__PURE__ */ jsx(Loader, {}),
children
})
});
};
//#endregion
//#region src/context/QueryContext/QueryClient.ts
var QueryClient$1 = new QueryClient({
defaultOptions: {
queries: {
staleTime: 300 * 1e3,
refetchOnWindowFocus: false,
refetchOnReconnect: true,
refetchOnMount: true,
retry: 2
},
mutations: { retry: 1 }
},
queryCache: new QueryCache({
onSuccess: (data, query) => {
if (query.meta?.onSuccess && typeof query.meta.onSuccess === "function") query.meta.onSuccess(data);
},
onError: (data, query) => {
if (query.meta?.onError && typeof query.meta.onError === "function") query.meta.onError(data);
}
})
});
//#endregion
//#region src/context/QueryContext/QueryClientProvider.tsx
/** Standard tanstack query provider, needed for it to work */
var QueryClientProvider$1 = ({ children }) => /* @__PURE__ */ jsx(QueryClientProvider, {
client: QueryClient$1,
children
});
//#endregion
//#region src/context/SettingsContext/SettingsProvider.tsx
var settingsDefaults = {
acceptedCountries: void 0,
allowBankAccountFormatSelection: false,
allowDebugUi: false,
allowIntraRegionCrossBorderPayout: false,
changeLegalEntityType: true,
editPrefilledCountry: true,
requirePciSignEcomMoto: false,
requirePciSignEcommerce: false,
requirePciSignPos: false,
requirePciSignPosMoto: false,
hideOnboardingIntroductionIndividual: true,
hideOnboardingIntroductionOrganization: true,
hideOnboardingIntroductionTrust: true,
hideOnboardingIntroductionSoleProprietor: true,
viewOnboardingGuidance: false,
transferInstrumentLimit: 0,
instantBankVerification: true,
showServiceAgreementsFirst: false,
showBusinessFinancingFirst: false,
enforceLegalAge: false,
merchantType: void 0,
allowBusinessLines: false,
allowCrossBorderPayout: false
};
/**
* Consumers can pass settings @see settingsDefaults, which can alter on runtime
* the behaviour of our library
* The settings are dynamically passed during SDK initialization (same as legalEntityId)
* @param settings - dictionary of type Settings
*/
function SettingsProvider({ children, settings }) {
const mergedSettings = {
...settingsDefaults,
...settings
};
const contextValue = useMemo$1(() => ({
isSettingEnabled: (settingName) => mergedSettings[settingName],
getSetting: (settingName) => mergedSettings[settingName],
settings: mergedSettings
}), [settings]);
return /* @__PURE__ */ jsx(SettingsContext.Provider, {
value: contextValue,
children
});
}
//#endregion
//#region src/utils/removeObjectEmptyValues.ts
function removeObjectPropsWithEmptyValues(obj) {
keysOf(obj).forEach((key) => {
if (obj[key] === null || isEmpty(obj[key])) delete obj[key];
});
return obj;
}
//#endregion
//#region src/context/StateContext/StateReducer.ts
var INITIAL_STATE = {
data: {},
allData: {},
initialData: {},
errors: {},
valid: {},
fieldProblems: {},
isValid: false,
allValid: false
};
var logger = createLogger();
function StateReducer() {
const [schemas, setSchemas] = useState$1({});
const [activeForms, setActiveForms] = useState$1([]);
const setCurrentForms = (forms) => {
setActiveForms(forms);
};
function reducer({ currentState: currState, prevState }, action) {
switch (action.type) {
case "addToState": {
if (!action.value.dataStoreId) {
logger.warn("No dataStoreId provided, hence no update can be done");
return {
currentState: currState,
prevState
};
}
const dataStoreId = action.value.dataStoreId;
const state = structuredClone(currState);
const schema = action.value.schema || null;
const schemaHasChanged = schema && schemas?.[dataStoreId]?.toString() !== schema.toString();
const mergedState = {
...state,
data: {
...state.data,
[dataStoreId]: {
...state.data[dataStoreId],
...action.value.data
}
},
allData: {
...state.allData,
[dataStoreId]: {
...state.allData[dataStoreId],
...removeObjectPropsWithEmptyValues(action.value.data)
}
},
errors: {
...state.errors,
[dataStoreId]: {
...state.errors[dataStoreId],
...action.value.errors
}
},
valid: {
...state.valid,
[dataStoreId]: {
...state.valid[dataStoreId],
...action.value.valid
}
},
fieldProblems: {
...state.fieldProblems,
[dataStoreId]: {
...state.fieldProblems[dataStoreId],
...action.value.fieldProblems
}
}
};
/**
* Some components e.g. personalDetails, are parents for other components and the data from these children is collected
* under the parent's id (aka dataStoreId) i.e. 'personalDetails.
*
* With these parents sometimes their schema for their useForm implementation updates at run time - so this fny checks
* if a schema has changed and if so ensures that the keys output in the data, valid, errors, fieldProblems objects
* match those of the parent schema
*/
if (schemaHasChanged) {
setSchemas({
...schemas,
[dataStoreId]: schema
});
const processedBySchema = schema.reduce((acc, fieldKey) => {
const dataObjByFormId = mergedState.data[dataStoreId];
const allDataObjByFormId = mergedState.allData[dataStoreId];
const validObjByFormId = mergedState.valid[dataStoreId];
const errorsObjByFormId = mergedState.errors[dataStoreId];
const fieldProblemsObjByFormId = mergedState.fieldProblems[dataStoreId];
return {
data: {
...acc.data,
[fieldKey]: dataObjByFormId[fieldKey] ?? allDataObjByFormId[fieldKey]
},
valid: {
...acc.valid,
[fieldKey]: validObjByFormId[fieldKey]
},
errors: {
...acc.errors,
[fieldKey]: errorsObjByFormId[fieldKey]
},
fieldProblems: {
...acc.fieldProblems,
[fieldKey]: fieldProblemsObjByFormId[fieldKey]
}
};
}, {
data: {},
valid: {},
errors: {},
fieldProblems: {}
});
mergedState.data[dataStoreId] = processedBySchema.data;
mergedState.valid[dataStoreId] = processedBySchema.valid;
mergedState.errors[dataStoreId] = processedBySchema.errors;
mergedState.fieldProblems[dataStoreId] = processedBySchema.fieldProblems;
}
mergedState.validityByForm = {
...mergedState.validityByForm,
[dataStoreId]: Object.values(mergedState.valid[dataStoreId]).every((isValid) => isValid)
};
mergedState.allValid = Object.values(mergedState.validityByForm).every((isValid) => isValid);
mergedState.isValid = !activeForms.length ? mergedState.allValid : activeForms.every((item) => mergedState.validityByForm?.[item]);
mergedState.initialData = structuredClone(state.initialData);
return {
currentState: mergedState,
prevState: state
};
}
case "removeFromState": {
if (!action.value.dataStoreId) {
logger.warn("No dataStoreId provided, hence no update can be done");
return {
currentState: currState,
prevState
};
}
const dataStoreId = action.value.dataStoreId;
const state = structuredClone(currState);
const mergedState = {
...state,
data: {
...state.data,
[dataStoreId]: {}
},
allData: {
...state.allData,
[dataStoreId]: {}
},
errors: {
...state.errors,
[dataStoreId]: {}
},
valid: {
...state.valid,
[dataStoreId]: false
},
fieldProblems: {
...state.fieldProblems,
[dataStoreId]: {}
}
};
mergedState.validityByForm = {
...mergedState.validityByForm,
[dataStoreId]: false
};
mergedState.allValid = Object.values(mergedState.validityByForm).every((isValid) => isValid);
mergedState.isValid = !activeForms.length ? mergedState.allValid : activeForms.every((item) => mergedState.validityByForm?.[item]);
mergedState.initialData = structuredClone(state.initialData);
return {
currentState: mergedState,
prevState: state
};
}
case "resetState": return {
currentState: INITIAL_STATE,
prevState: currState
};
default: throw new Error(`Unhandled action type: ${action.type}`);
}
}
return {
reducer,
setCurrentForms
};
}
//#endregion
//#region src/context/StateContext/StateProvider.tsx
function StateProvider({ defaultData = {}, children }) {
const defaultState = {
currentState: {
data: defaultData,
allData: defaultData,
valid: {},
errors: {},
fieldProblems: {},
validityByForm: {},
initialData: defaultData
},
prevState: {}
};
const reducerObj = StateReducer();
const [state, dispatch] = useReducer(reducerObj.reducer, defaultState);
/**
* Create an object from the returned reducer props
* - the state property in this object will be available to any handler functions set on StateContextWatcher
* - the dispatch property is made available to the StateContextSetter
*/
const contextValue = useMemo$1(() => ({
state,
dispatch,
setActiveForms: reducerObj.setCurrentForms,
getData: () => state?.currentState?.data ?? {},
getState: () => state?.currentState
}), [reducerObj, state]);
return /* @__PURE__ */ jsx(StateContext.Provider, {
value: contextValue,
children
});
}
//#endregion
//#region src/api/toggles/useToggles.ts
/**
* Retrieves experiments and onboardingcomponents-specific feature flags
* as defined in `OnboardingcomponentsFeatures.java` linked to the legalEntityId
*/
var getToggles = async (legalEntityId, baseUrl) => {
const { experiments, features } = await httpGet({
baseUrl,
path: `legalEntities/${legalEntityId}/flags`
});
return {
experiments: experiments ? Object.values(experiments).reduce((acc, val) => {
return {
...acc,
[val]: true
};
}, {}) : {},
features
};
};
var useToggles = (options) => {
const { rootLegalEntityId, baseUrl } = useApiContext();
const { features } = useToggleContext();
return useQuery({
queryKey: ["toggles"],
queryFn: () => getToggles(rootLegalEntityId.value, baseUrl.value),
enabled: !!features.EnableOnboardingTogglesEndpoint,
...options
});
};
//#endregion
//#region src/context/ToggleContext/ToggleContextProvider.tsx
/**
* To manage accessing non-production-ready features of SDK
* or features under active experimentation/testing.
* @param children - components rendered
* @param features - dictionary of type Features
* @param refreshExperiments - handler to refresh experiments for the legal entity
*/
function ToggleContextProvider({ children, features: propFeatures, refreshExperiments }) {
const { data: toggleData } = useToggles();
const { data: versionData } = useVersionConfiguration();
const features = useMemo$1(() => ({
...toggleData?.features,
...propFeatures,
...listToRecord(versionData?.features ?? [], () => true)
}), [
versionData,
propFeatures,
toggleData?.features
]);
const experiments = useMemo$1(() => ({ ...toggleData?.experiments }), [toggleData?.experiments]);
const contextValue = useMemo$1(() => ({
features,
isFeatureEnabled: (feature) => features[feature] ?? false,
experiments,
isExperimentEnabled: (experiment) => experiments[experiment] ?? false,
refreshExperiments
}), [
features,
experiments,
refreshExperiments
]);
return /* @__PURE__ */ jsx(ToggleContext.Provider, {
value: contextValue,
children
});
}
//#endregion
//#region src/components/Shared/AllowedCountryGate/AllowedCountryGate.tsx
/**
* Blocks the user from onboarding if they are from a disallowed country.
*/
var AllowedCountryGate = ({ children }) => {
const allowedCountries = useAllowedCountries();
const { t, i18n } = useTranslation("common");
const { data: rootLegalEntity } = useLegalEntity(ROOT_LE);
const { dataset: countries } = useDataset(datasetIdentifier.country);
addResourceBundles(i18n, [{
ns: "common",
importFn: (lang) => _rolldown_dynamic_import_helper_default(/* @__PURE__ */ Object.assign({
"../../../language/locales/bg-BG.json": () => import("./bg-BG-COHRuTI-.js"),
"../../../language/locales/cs-CZ.json": () => import("./cs-CZ-CmcYZLZp.js"),
"../../../language/locales/da-DK.json": () => import("./da-DK-C_oe1bpM.js"),
"../../../language/locales/de-DE.json": () => import("./de-DE-CMc1Fpfl.js"),
"../../../language/locales/el-GR.json": () => import("./el-GR-Bv2QgmVV.js"),
"../../../language/locales/en-US.instructions.json": () => import("./en-US.instructions-DJharl6b.js"),
"../../../language/locales/en-US.json": () => import("./en-US-cJAmQhFR.js").then((n) => n.n),
"../../../language/locales/es-ES.json": () => import("./es-ES-DtlXpZ_5.js"),
"../../../language/locales/et-EE.json": () => import("./et-EE-PTcJ2hRW.js"),
"../../../language/locales/fi-FI.json": () => import("./fi-FI-C1Ns3CEo.js"),
"../../../language/locales/fr-FR.json": () => import("./fr-FR-DgPRYmmJ.js"),
"../../../language/locales/hr-HR.json": () => import("./hr-HR-BQfjrcPC.js"),
"../../../language/locales/hu-HU.json": () => import("./hu-HU-DfYPelYo.js"),
"../../../language/locales/it-IT.json": () => import("./it-IT-cnETv3Cg.js"),
"../../../language/locales/ja-JP.json": () => import("./ja-JP-D0gz56Ni.js"),
"../../../language/locales/lt-LT.json": () => import("./lt-LT-Bbh9MWxc.js"),
"../../../language/locales/lv-LV.json": () => import("./lv-LV-C8fqHR2g.js"),
"../../../language/locales/nl-NL.json": () => import("./nl-NL-CQSu4iNn.js"),
"../../../language/locales/no-NO.json": () => import("./no-NO-C0DXekH-.js"),
"../../../language/locales/pl-PL.json": () => import("./pl-PL-10KUcobm.js"),
"../../../language/locales/pt-BR.json": () => import("./pt-BR-DWKF33yP.js"),
"../../../language/locales/pt-PT.json": () => import("./pt-PT-CjIFIi4R.js"),
"../../../language/locales/ro-RO.json": () => import("./ro-RO-DQFRJwp8.js"),
"../../../language/locales/sk-SK.json": () => import("./sk-SK-BfoXFhAL.js"),
"../../../language/locales/sl-SI.json": () => import("./sl-SI-CyIN1sc5.js"),
"../../../language/locales/sv-SE.json": () => import("./sv-SE-Xh17T6yC.js")
}), `../../../language/locales/${lang}.json`, 6)
}]);
if (!rootLegalEntity || !allowedCountries) return /* @__PURE__ */ jsx(Loader, {});
const country = getLegalEntityCountry(rootLegalEntity);
const isAllowed = allowedCountries.includes(country);
const countryName = countries.find(({ id }) => id === country)?.name ?? country;
if (!isAllowed) return /* @__PURE__ */ jsx(DropinLayout, { content: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(AlertIcon, { variant: "error" }), /* @__PURE__ */ jsx(Header, {
title: t(($) => $["countryNotSupported"]),
description: t(($) => $["weDontSupportOnboardingInCountry"], { country: countryName })
})] }) });
return /* @__PURE__ */ jsx(Fragment$1, { children });
};
//#endregion
//#region src/components/Shared/devex/DebugListener/DebugListener.tsx
var DebugModal = lazy(async () => (await import("./DebugModal-B6JV7Oib.js")).DebugModal);
/**
* Adds a listener on the page to open the debug modal when the
* debug modal key combination is pressed to open it
*/
var DebugListener = () => {
const [debugUiOpen, setDebugUiOpen] = useState$1(false);
const { isSettingEnabled } = useSettingsContext();
const debugUiAllowed = isSettingEnabled("allowDebugUi");
useEffect$1(() => {
if (!debugUiAllowed) return;
const handleKeyDown = ({ code, ctrlKey, altKey, shiftKey }) => {
if (ctrlKey && (altKey || shiftKey) && code === "Backslash") setDebugUiOpen(true);
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [debugUiAllowed]);
return /* @__PURE__ */ jsx(Fragment$1, { children: debugUiAllowed && debugUiOpen ? /* @__PURE__ */ jsx(Suspense, {
fallback: /* @__PURE__ */ jsx("div", {}),
children: /* @__PURE__ */ jsx(DebugModal, { onExit: () => setDebugUiOpen(false) })
}) : null });
};
//#endregion
//#region src/stores/globalStore/StoreProvider.tsx
/**
* `<StoreProvider>` postpones render of the remaining tree until root legal entity data has been
* retrieved and the {@link GlobalStore} has been initialized.
*
* This provider can (and should) also be used from tests and stories.
* If you prefer to mock global state, see {@link MockedStoreProvider}.
*/
var StoreProvider = ({ children }) => {
const [store, setStore] = useState$1();
const { data: rootLegalEntity } = useLegalEntity(ROOT_LE);
useEffect$1(() => {
if (!rootLegalEntity || store) return;
setStore(createGlobalStore({ rootLegalEntity }));
}, [rootLegalEntity, store]);
if (!store) return /* @__PURE__ */ jsx(Skeleton, {});
return /* @__PURE__ */ jsx(StoreContext.Provider, {
value: store,
children
});
};
//#endregion
//#region src/core/EmbedShell/EmbedShell.tsx
/** conditional polyfill for container queries */
if (CSS.supports("container", "foo / inline-size") === false) import("container-query-polyfill");
/**
* Bootstraps any component for external usage by consumers
* Import it in your component and wrap it inside the EmbedShell, eg:
*
* @example
* ```jsx
* <EmbedShell {...consumerProps}>
* <MyReadyToGoForm {...consumerProps} />
* </EmbedShell>
* ```
*
* @param props given by consumer, be it HO, merchant using library or a TaskList component
* @returns
*/
var EmbedShell = ({ children, rootLegalEntityId, settings, features, refreshExperiments, baseUrl, getSdkToken, componentName, locale }) => {
const [isLoading, setIsLoading] = useState$1(true);
const [hasError, setHasError] = useState$1(false);
setSdkTokenHandler(getSdkToken);
useEffect$1(() => {
refreshSession().then((hasRefreshed) => {
if (!hasRefreshed) setHasError(true);
setIsLoading(false);
});
}, []);
if (hasError) return /* @__PURE__ */ jsxs("div", { children: ["Something went wrong, please", /* @__PURE__ */ jsx(Button, {
onClick: () => location.reload(),
children: "refresh the page."
})] });
if (isLoading) return /* @__PURE__ */ jsx(Loader, {});
return /* @__PURE__ */ jsx(SettingsProvider, {
settings,
children: /* @__PURE__ */ jsx(QueryClientProvider$1, { children: /* @__PURE__ */ jsx(ApiProvider, {
rootLegalEntityId,
baseUrl,
children: /* @__PURE__ */ jsx(ToggleContextProvider, {
features,
refreshExperiments,
children: /* @__PURE__ */ jsxs(StoreProvider, { children: [/* @__PURE__ */ jsx("span", {
className: "adyen-kyc__sdk-version",
hidden: true,
children: "4.9.0"
}), /* @__PURE__ */ jsx(AnalyticsProvider, {
componentName,
rootLegalEntityId,
children: /* @__PURE__ */ jsx(I18nProvider, {
locale,
children: /* @__PURE__ */ jsxs(AllowedCountryGate, { children: [/* @__PURE__ */ jsx(DebugListener, {}), /* @__PURE__ */ jsx("div", {
className: "adyen-kyc-ui-element-container-wrapper",
children: /* @__PURE__ */ jsx("div", {
className: "adyen-kyc-ui-element-container",
children: /* @__PURE__ */ jsx(ToastContextProvider, { children: /* @__PURE__ */ jsx(StateProvider, { children }) })
})
})] })
})
})] })
})
}) })
});
};
//#endregion
//#region src/core/environment/normalizeEnvironment.ts
var normalizeEnvironment = (env) => env.endsWith("/") ? env : `${env}/`;
//#endregion
//#region src/core/environment/resolveEnvironment.ts
var environmentMap = Object.freeze({
live: "https://onboardingcomponents-live.adyen.com/",
test: "https://test.adyen.com/"
});
var resolveEnvironment = (environment) => environmentMap[environment] ?? normalizeEnvironment(environment);
//#endregion
export { stylesheets as a, useI18nContext as i, EmbedShell as n, useToggles as r, resolveEnvironment as t };