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.

1,177 lines (1,176 loc) 41.2 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] = "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 };