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.

237 lines (236 loc) 10.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] = "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 };