@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.
237 lines (236 loc) • 10.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] = "bd570808-319b-4e67-9e8a-386dc7e456b7", e._sentryDebugIdIdentifier = "sentry-dbid-bd570808-319b-4e67-9e8a-386dc7e456b7");
} catch (e) {}
import { i as Typography, r as useTranslation } from "./translation-BYvhW5zA.js";
import { P as listToRecord, x as Alert } from "./resolveEnvironment-DNmu53Rr.js";
import { t as Button } from "./Button-i8I2dHP8.js";
import { l as keysOf } from "./AnalyticsContext-BFrJmsp0.js";
import { t as Modal } from "./Modal-BLP2aF-u.js";
import { t as Confirm } from "./Confirm-CA-gL38n.js";
import { n as RadioWithLabel } from "./RadioGroup-qV8mGGwm.js";
import { t as isEmpty } from "./isEmpty-BVlBH98t.js";
import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
import cx from "classnames";
import { jsx, jsxs } from "preact/jsx-runtime";
var ConflictRow_module_default = {
"conflict-row-table": "_conflict-row-table_y7ii4_1",
conflictRowTable: "_conflict-row-table_y7ii4_1",
"conflict-row-list": "_conflict-row-list_y7ii4_12",
conflictRowList: "_conflict-row-list_y7ii4_12",
"conflict-row-list-option-label": "_conflict-row-list-option-label_y7ii4_29",
conflictRowListOptionLabel: "_conflict-row-list-option-label_y7ii4_29"
};
//#endregion
//#region src/components/Shared/DataConflictsModal/ConflictRow.tsx
var ConflictRow = ({ provided, detected, label, formatter = (val) => val, selected, onSelect, showAs }) => {
const { t } = useTranslation("common");
const hasOnlyProvided = !isEmpty(provided) && isEmpty(detected);
const hasOnlyDetected = isEmpty(provided) && !isEmpty(detected);
useEffect(() => {
if (selected !== void 0) return;
if (hasOnlyProvided) onSelect("provided");
else if (hasOnlyDetected) onSelect("detected");
}, [
hasOnlyProvided,
hasOnlyDetected,
onSelect,
selected
]);
if (hasOnlyProvided || hasOnlyDetected) return;
return showAs === "listItem" ? /* @__PURE__ */ jsxs("div", {
className: ConflictRow_module_default.conflictRowList,
children: [/* @__PURE__ */ jsx("dt", { children: /* @__PURE__ */ jsx(Typography, {
variant: "caption",
children: t(($) => $[label])
}) }), /* @__PURE__ */ jsxs("dd", { children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
variant: "caption",
color: "tertiary",
className: ConflictRow_module_default.conflictRowListOptionLabel,
children: t(($) => $["youEntered"])
}), /* @__PURE__ */ jsx(RadioWithLabel, {
label: formatter(provided),
value: "provided",
checked: selected === "provided",
onClick: () => onSelect("provided")
})] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
variant: "caption",
color: "tertiary",
className: ConflictRow_module_default.conflictRowListOptionLabel,
children: t(($) => $["weDetected"])
}), /* @__PURE__ */ jsx(RadioWithLabel, {
label: formatter(detected),
value: "detected",
checked: selected === "detected",
onClick: () => onSelect("detected")
})] })] })]
}) : /* @__PURE__ */ jsxs("tr", {
className: ConflictRow_module_default.conflictRowTable,
children: [
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Typography, {
variant: "caption",
children: t(($) => $[label])
}) }),
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(RadioWithLabel, {
label: formatter(provided),
value: "provided",
checked: selected === "provided",
onClick: () => onSelect("provided")
}) }),
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(RadioWithLabel, {
label: formatter(detected),
value: "detected",
checked: selected === "detected",
onClick: () => onSelect("detected")
}) })
]
});
};
var DataConflictsModal_module_default = {
"data-conflicts-wrapper": "_data-conflicts-wrapper_c81aq_1",
dataConflictsWrapper: "_data-conflicts-wrapper_c81aq_1",
"data-conflicts-header": "_data-conflicts-header_c81aq_7",
dataConflictsHeader: "_data-conflicts-header_c81aq_7",
"data-conflicts-table": "_data-conflicts-table_c81aq_15",
dataConflictsTable: "_data-conflicts-table_c81aq_15",
"data-conflicts-list": "_data-conflicts-list_c81aq_26",
dataConflictsList: "_data-conflicts-list_c81aq_26",
"data-conflicts-list-forced": "_data-conflicts-list-forced_c81aq_46",
dataConflictsListForced: "_data-conflicts-list-forced_c81aq_46",
"data-conflicts-table-hidden": "_data-conflicts-table-hidden_c81aq_50",
dataConflictsTableHidden: "_data-conflicts-table-hidden_c81aq_50"
};
//#endregion
//#region src/components/Shared/DataConflictsModal/DataConflictsModal.tsx
/**
* A modal component for resolving data conflicts between two data sources.
*
* This component is typically used in a KYC (Know Your Customer) flow where user-provided data
* is compared against data extracted from a document (e.g., via OCR).
*
* It identifies differing fields, presents them to the user, and allows them to select the
* correct version for each field before proceeding.
*
* @template Data The shape of the data objects being compared.
* @template Property A union of keys from the `Data` object, constrained to `NsTranslationKey<'common'>`.
*/
var DataConflictsModal = ({ providedData, detectedData, conflictingProperties, formatters, title, explanation, onContinue, labels, onCancel, cancelConfirmation, listOnly = false }) => {
const { t: commonT } = useTranslation("common");
const [showCancelModal, setShowCancelModal] = useState(false);
const [showError, setShowError] = useState(false);
/**
* A record object that maps each conflicting property key to its `provided` and `detected` values.
* This is memoized for performance, as it's derived from `conflictingProperties` and only needs
* to be recalculated if the list of conflicts changes.
*
* @example
* // returns: { firstName: { provided: 'Jon', detected: 'John' } }
*/
const conflictItems = useMemo(() => listToRecord(conflictingProperties, (property) => ({
provided: providedData[property],
detected: detectedData[property]
})), [
conflictingProperties,
providedData,
detectedData
]);
const [resolutions, setResolutions] = useState(() => listToRecord(conflictingProperties, () => void 0));
const resolveProperty = useCallback((property, selected) => {
setShowError(false);
setResolutions((prev) => ({
...prev,
[property]: selected
}));
}, []);
return /* @__PURE__ */ jsxs(Modal, {
ariaLabel: title,
onClose: () => cancelConfirmation ? setShowCancelModal(true) : onCancel(),
inset: true,
children: [/* @__PURE__ */ jsxs("div", {
className: DataConflictsModal_module_default.dataConflictsWrapper,
children: [
/* @__PURE__ */ jsxs("div", {
className: DataConflictsModal_module_default.dataConflictsHeader,
children: [/* @__PURE__ */ jsx(Typography, {
variant: "title-l",
el: "h1",
children: title
}), /* @__PURE__ */ jsx(Typography, {
variant: "body",
children: explanation
})]
}),
showError ? /* @__PURE__ */ jsx(Alert, {
variant: "error",
title: commonT(($) => $["chooseTheCorrectDetailsBeforeProceeding"])
}) : void 0,
/* @__PURE__ */ jsx("dl", {
className: cx(DataConflictsModal_module_default.dataConflictsList, { [DataConflictsModal_module_default.dataConflictsListForced]: listOnly }),
children: keysOf(conflictItems).map((property) => /* @__PURE__ */ jsx(ConflictRow, {
showAs: "listItem",
label: labels?.[property] ?? property,
formatter: formatters[property],
provided: conflictItems[property].provided,
detected: conflictItems[property].detected,
selected: resolutions[property],
onSelect: (selected) => resolveProperty(property, selected)
}, property))
}),
/* @__PURE__ */ jsxs("table", {
className: cx(DataConflictsModal_module_default.dataConflictsTable, { [DataConflictsModal_module_default.dataConflictsTableHidden]: listOnly }),
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
/* @__PURE__ */ jsx("th", {}),
/* @__PURE__ */ jsx("th", { children: /* @__PURE__ */ jsx(Typography, {
variant: "caption",
color: "tertiary",
children: commonT(($) => $["youEntered"])
}) }),
/* @__PURE__ */ jsx("th", { children: /* @__PURE__ */ jsx(Typography, {
variant: "caption",
color: "tertiary",
children: commonT(($) => $["weDetected"])
}) })
] }) }), /* @__PURE__ */ jsx("tbody", { children: keysOf(conflictItems).map((property) => /* @__PURE__ */ jsx(ConflictRow, {
showAs: "tableRow",
label: labels?.[property] ?? property,
formatter: formatters[property],
provided: conflictItems[property].provided,
detected: conflictItems[property].detected,
selected: resolutions[property],
onSelect: (selected) => resolveProperty(property, selected)
}, property)) })]
}),
/* @__PURE__ */ jsx(Button, {
fullWidth: true,
onClick: () => {
if (!conflictingProperties.every((p) => resolutions[p])) {
setShowError(true);
return;
}
/**
* 2. Build an object containing only the user's selections for the conflicting properties.
* This intermediate object will only contain the keys that had a mismatch.
*/
const resolvedConflicts = listToRecord(conflictingProperties, (property) => {
return resolutions[property] === "provided" ? providedData[property] : detectedData[property];
});
onContinue({
...providedData,
...resolvedConflicts
});
},
children: commonT(($) => $["confirmSelection"])
})
]
}), cancelConfirmation && showCancelModal && /* @__PURE__ */ jsx(Confirm, {
title: cancelConfirmation.title,
confirmText: cancelConfirmation.confirmText,
description: cancelConfirmation.description,
onConfirm: onCancel,
onCancel: () => setShowCancelModal(false),
critical: false
})]
});
};
//#endregion
export { DataConflictsModal as t };