@ozura/elements 1.0.1 → 1.0.2-next.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +1192 -1130
- package/dist/frame/element-frame.html +22 -22
- package/dist/frame/element-frame.js +31 -4
- package/dist/frame/element-frame.js.map +1 -1
- package/dist/frame/tokenizer-frame.html +11 -11
- package/dist/frame/tokenizer-frame.js +19 -6
- package/dist/frame/tokenizer-frame.js.map +1 -1
- package/dist/oz-elements.esm.js +27 -8
- package/dist/oz-elements.esm.js.map +1 -1
- package/dist/oz-elements.umd.js +27 -8
- package/dist/oz-elements.umd.js.map +1 -1
- package/dist/react/frame/elementFrame.d.ts +59 -1
- package/dist/react/frame/protocol.d.ts +12 -0
- package/dist/react/index.cjs.js +137 -113
- package/dist/react/index.cjs.js.map +1 -1
- package/dist/react/index.esm.js +138 -114
- package/dist/react/index.esm.js.map +1 -1
- package/dist/react/types/index.d.ts +6 -3
- package/dist/server/frame/elementFrame.d.ts +59 -1
- package/dist/server/frame/protocol.d.ts +12 -0
- package/dist/server/index.cjs.js +6 -3
- package/dist/server/index.cjs.js.map +1 -1
- package/dist/server/index.esm.js +6 -3
- package/dist/server/index.esm.js.map +1 -1
- package/dist/server/types/index.d.ts +6 -3
- package/dist/types/frame/elementFrame.d.ts +59 -1
- package/dist/types/frame/protocol.d.ts +12 -0
- package/dist/types/types/index.d.ts +6 -3
- package/package.json +1 -1
package/dist/react/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext, useRef,
|
|
2
|
+
import { createContext, useContext, useRef, useCallback, useState, useMemo, useEffect } from 'react';
|
|
3
3
|
|
|
4
4
|
const THEME_DEFAULT = {
|
|
5
5
|
base: {
|
|
@@ -819,13 +819,26 @@ function validateBilling(billing) {
|
|
|
819
819
|
return { valid: errors.length === 0, errors, normalized };
|
|
820
820
|
}
|
|
821
821
|
|
|
822
|
+
/**
|
|
823
|
+
* Shared postMessage protocol constants.
|
|
824
|
+
*
|
|
825
|
+
* PROTOCOL_VERSION must be incremented any time a breaking change is made to
|
|
826
|
+
* the postMessage message shape (new required fields, renamed types, removed
|
|
827
|
+
* fields, changed semantics). The SDK reads this value from OZ_FRAME_READY
|
|
828
|
+
* messages and warns when the frame and SDK are out of sync.
|
|
829
|
+
*
|
|
830
|
+
* Non-breaking additions (new optional fields, new message types that old
|
|
831
|
+
* frames can safely ignore) do NOT require a version bump.
|
|
832
|
+
*/
|
|
833
|
+
const PROTOCOL_VERSION = 1;
|
|
834
|
+
|
|
822
835
|
function isCardMetadata(v) {
|
|
823
836
|
return !!v && typeof v === 'object' && typeof v.last4 === 'string';
|
|
824
837
|
}
|
|
825
838
|
function isBankAccountMetadata(v) {
|
|
826
839
|
return !!v && typeof v === 'object' && typeof v.last4 === 'string';
|
|
827
840
|
}
|
|
828
|
-
const DEFAULT_FRAME_BASE_URL = "https://
|
|
841
|
+
const DEFAULT_FRAME_BASE_URL = "https://lively-hill-097170c0f.4.azurestaticapps.net";
|
|
829
842
|
/**
|
|
830
843
|
* The main entry point for OzElements. Creates and manages iframe-based
|
|
831
844
|
* card input elements that keep raw card data isolated from the merchant page.
|
|
@@ -1391,6 +1404,11 @@ class OzVault {
|
|
|
1391
1404
|
// the previous session and justCompleted never fires, breaking auto-advance.
|
|
1392
1405
|
if (msg.type === 'OZ_FRAME_READY') {
|
|
1393
1406
|
this.completionState.set(frameId, false);
|
|
1407
|
+
if (msg.__ozVersion !== PROTOCOL_VERSION) {
|
|
1408
|
+
console.warn(`[OzVault] Protocol version mismatch on element frame "${frameId}" — ` +
|
|
1409
|
+
`SDK expects v${PROTOCOL_VERSION}, frame reported v${typeof msg.__ozVersion === 'number' ? msg.__ozVersion : '(none)'}. ` +
|
|
1410
|
+
'Deploy the matching frame assets to elements.ozura.com and purge the Azure CDN cache.');
|
|
1411
|
+
}
|
|
1394
1412
|
}
|
|
1395
1413
|
// Intercept OZ_CHANGE before forwarding — handle auto-advance and CVV sync
|
|
1396
1414
|
if (msg.type === 'OZ_CHANGE') {
|
|
@@ -1436,6 +1454,12 @@ class OzVault {
|
|
|
1436
1454
|
var _a, _b, _c;
|
|
1437
1455
|
switch (msg.type) {
|
|
1438
1456
|
case 'OZ_FRAME_READY':
|
|
1457
|
+
if (msg.__ozVersion !== PROTOCOL_VERSION) {
|
|
1458
|
+
console.warn(`[OzVault] Protocol version mismatch — SDK expects v${PROTOCOL_VERSION}, ` +
|
|
1459
|
+
`tokenizer frame reported v${typeof msg.__ozVersion === 'number' ? msg.__ozVersion : '(none)'}. ` +
|
|
1460
|
+
'This usually means the deployed frame files are stale. ' +
|
|
1461
|
+
'Deploy the matching frame assets to elements.ozura.com and purge the Azure CDN cache.');
|
|
1462
|
+
}
|
|
1439
1463
|
this.tokenizerReady = true;
|
|
1440
1464
|
if (this.loadErrorTimeoutId != null) {
|
|
1441
1465
|
clearTimeout(this.loadErrorTimeoutId);
|
|
@@ -1469,13 +1493,8 @@ class OzVault {
|
|
|
1469
1493
|
pending.reject(new OzError('Vault returned a token result without a cvcSession — possible vault misconfiguration or API change.', undefined, 'server'));
|
|
1470
1494
|
break;
|
|
1471
1495
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
break;
|
|
1475
|
-
}
|
|
1476
|
-
pending.resolve(Object.assign({ token,
|
|
1477
|
-
cvcSession,
|
|
1478
|
-
card }, (pending.billing ? { billing: pending.billing } : {})));
|
|
1496
|
+
pending.resolve(Object.assign(Object.assign({ token,
|
|
1497
|
+
cvcSession }, (card ? { card } : {})), (pending.billing ? { billing: pending.billing } : {})));
|
|
1479
1498
|
// Increment the per-key success counter and proactively refresh once
|
|
1480
1499
|
// the budget is exhausted so the next createToken() call uses a fresh
|
|
1481
1500
|
// key without waiting for a vault rejection.
|
|
@@ -1841,9 +1860,25 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
|
|
|
1841
1860
|
// proactive, or visibility-change proactive). Without this the React
|
|
1842
1861
|
// counter accumulates across key refreshes and diverges from the vault's
|
|
1843
1862
|
// internal _tokenizeSuccessCount, which resets to 0 on every refresh.
|
|
1863
|
+
//
|
|
1864
|
+
// The reset is deferred via Promise.resolve().then() rather than being
|
|
1865
|
+
// called synchronously. In the proactive-refresh case (budget exhausted
|
|
1866
|
+
// after a successful tokenization), the vault's message handler calls
|
|
1867
|
+
// onWaxRefresh synchronously before the Promise microtask that resumes
|
|
1868
|
+
// the awaiting createToken() wrapper (and its notifyTokenize() call).
|
|
1869
|
+
// A synchronous setTokenizeCount(0) would therefore fire BEFORE
|
|
1870
|
+
// notifyTokenize's setTokenizeCount(n => n + 1), causing React to batch
|
|
1871
|
+
// them as: reset to 0, then +1 = 1 — a persistent off-by-one.
|
|
1872
|
+
// Deferring by one microtask flips the order: notifyTokenize fires first
|
|
1873
|
+
// (increment), then the deferred reset fires (set 0), so the final
|
|
1874
|
+
// batched result is 0 — correct for a just-exhausted key.
|
|
1875
|
+
// In the reactive-refresh case the deferred reset still fires well before
|
|
1876
|
+
// the retry tokenization completes (a full fetchWaxKey + tokenize round-
|
|
1877
|
+
// trip separates them), so the count correctly resets to 0 then rises to
|
|
1878
|
+
// 1 after the retry notifyTokenize fires.
|
|
1844
1879
|
onWaxRefresh: () => {
|
|
1845
1880
|
var _a;
|
|
1846
|
-
setTokenizeCount(0);
|
|
1881
|
+
Promise.resolve().then(() => setTokenizeCount(0));
|
|
1847
1882
|
(_a = onWaxRefreshRef.current) === null || _a === void 0 ? void 0 : _a.call(onWaxRefreshRef);
|
|
1848
1883
|
} }), (onReadyRef.current ? { onReady: () => { var _a; return (_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef); } } : {})), (maxTokenizeCalls !== undefined ? { maxTokenizeCalls } : {})), abortController.signal).then(v => {
|
|
1849
1884
|
if (cancelled) {
|
|
@@ -2007,6 +2042,71 @@ const OzCardNumber = (props) => jsx(OzFieldBase, Object.assign({ type: "cardNumb
|
|
|
2007
2042
|
const OzExpiry = (props) => jsx(OzFieldBase, Object.assign({ type: "expirationDate", variant: "card" }, props));
|
|
2008
2043
|
/** Renders a PCI-isolated CVV input inside an Ozura iframe. */
|
|
2009
2044
|
const OzCvv = (props) => jsx(OzFieldBase, Object.assign({ type: "cvv", variant: "card" }, props));
|
|
2045
|
+
// ─── Shared composite-component hook ─────────────────────────────────────────
|
|
2046
|
+
/**
|
|
2047
|
+
* Shared plumbing for OzCard and OzBankCard.
|
|
2048
|
+
*
|
|
2049
|
+
* Manages:
|
|
2050
|
+
* - Callback refs (onChange, onReady, onFocus, onBlur) kept in sync on every render
|
|
2051
|
+
* - Vault-change detection: resets `readyFieldTypes` and `onReadyFiredRef` when the
|
|
2052
|
+
* vault instance is replaced (e.g. after fetchWaxKey changes or the provider remounts)
|
|
2053
|
+
* - Per-field ready tracking: creates one stable handler per named field; fires the
|
|
2054
|
+
* `onReady` callback once all `fieldNames.length` fields have reported ready
|
|
2055
|
+
* - Error state
|
|
2056
|
+
* - Layout helpers: `gapStr`, `resolvedLabelStyle`, `renderLabel`
|
|
2057
|
+
*
|
|
2058
|
+
* @internal — not exported; used only by OzCard and OzBankCard.
|
|
2059
|
+
*/
|
|
2060
|
+
function useCardBase({ vault, fieldNames, onChange, onReady, onFocus, onBlur, gap = 8, labelStyle, labelClassName, }) {
|
|
2061
|
+
const totalFields = fieldNames.length;
|
|
2062
|
+
const readyFieldTypes = useRef(new Set());
|
|
2063
|
+
const onReadyFiredRef = useRef(false);
|
|
2064
|
+
const vaultRef = useRef(vault);
|
|
2065
|
+
const onChangeRef = useRef(onChange);
|
|
2066
|
+
const onReadyRef = useRef(onReady);
|
|
2067
|
+
const onFocusRef = useRef(onFocus);
|
|
2068
|
+
const onBlurRef = useRef(onBlur);
|
|
2069
|
+
useEffect(() => { onChangeRef.current = onChange; }, [onChange]);
|
|
2070
|
+
useEffect(() => { onReadyRef.current = onReady; }, [onReady]);
|
|
2071
|
+
useEffect(() => { onFocusRef.current = onFocus; }, [onFocus]);
|
|
2072
|
+
useEffect(() => { onBlurRef.current = onBlur; }, [onBlur]);
|
|
2073
|
+
useEffect(() => {
|
|
2074
|
+
if (vault !== vaultRef.current) {
|
|
2075
|
+
vaultRef.current = vault;
|
|
2076
|
+
readyFieldTypes.current = new Set();
|
|
2077
|
+
onReadyFiredRef.current = false;
|
|
2078
|
+
}
|
|
2079
|
+
return () => {
|
|
2080
|
+
readyFieldTypes.current = new Set();
|
|
2081
|
+
onReadyFiredRef.current = false;
|
|
2082
|
+
};
|
|
2083
|
+
}, [vault]);
|
|
2084
|
+
// One stable handler per named field — recreated only when total field count changes.
|
|
2085
|
+
// Field names are static (card = 3 fields, bank = 2 fields) so `totalFields` alone
|
|
2086
|
+
// is a sufficient dependency; a JSON dep would create a new map on every render.
|
|
2087
|
+
// CONTRACT: `fieldNames` must be a static literal — callers must not pass a dynamic
|
|
2088
|
+
// array that changes length without also changing field count.
|
|
2089
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2090
|
+
const readyHandlers = useMemo(() => {
|
|
2091
|
+
const handlers = {};
|
|
2092
|
+
for (const name of fieldNames) {
|
|
2093
|
+
handlers[name] = () => {
|
|
2094
|
+
var _a;
|
|
2095
|
+
readyFieldTypes.current.add(name);
|
|
2096
|
+
if (readyFieldTypes.current.size >= totalFields && !onReadyFiredRef.current) {
|
|
2097
|
+
onReadyFiredRef.current = true;
|
|
2098
|
+
(_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef);
|
|
2099
|
+
}
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
return handlers;
|
|
2103
|
+
}, [totalFields]); // totalFields captures fieldNames.length; field names are static
|
|
2104
|
+
const [error, setError] = useState();
|
|
2105
|
+
const gapStr = typeof gap === 'string' ? gap : `${gap}px`;
|
|
2106
|
+
const resolvedLabelStyle = useMemo(() => (labelStyle ? Object.assign(Object.assign({}, DEFAULT_LABEL_STYLE), labelStyle) : DEFAULT_LABEL_STYLE), [labelStyle]);
|
|
2107
|
+
const renderLabel = useCallback((text) => renderFieldLabel(text, labelClassName, resolvedLabelStyle), [labelClassName, resolvedLabelStyle]);
|
|
2108
|
+
return { onChangeRef, onFocusRef, onBlurRef, readyHandlers, error, setError, gapStr, resolvedLabelStyle, renderLabel };
|
|
2109
|
+
}
|
|
2010
2110
|
const DEFAULT_ERROR_STYLE = {
|
|
2011
2111
|
color: '#dc2626',
|
|
2012
2112
|
fontSize: 13,
|
|
@@ -2049,62 +2149,22 @@ function mergeStyles(base, override) {
|
|
|
2049
2149
|
function OzCard({ style, styles, classNames, labels, labelStyle, labelClassName, layout = 'default', gap = 8, hideErrors = false, errorStyle, errorClassName, renderError, onChange, onReady, onFocus, onBlur, disabled, className, placeholders, }) {
|
|
2050
2150
|
var _a, _b, _c;
|
|
2051
2151
|
const { vault } = useContext(OzContext);
|
|
2152
|
+
const { onChangeRef, onFocusRef, onBlurRef, readyHandlers, error, setError, gapStr, renderLabel, } = useCardBase({
|
|
2153
|
+
vault,
|
|
2154
|
+
fieldNames: ['cardNumber', 'expiry', 'cvv'],
|
|
2155
|
+
onChange,
|
|
2156
|
+
onReady,
|
|
2157
|
+
onFocus,
|
|
2158
|
+
onBlur,
|
|
2159
|
+
gap,
|
|
2160
|
+
labelStyle,
|
|
2161
|
+
labelClassName,
|
|
2162
|
+
});
|
|
2052
2163
|
const fieldState = useRef({
|
|
2053
2164
|
cardNumber: null,
|
|
2054
2165
|
expiry: null,
|
|
2055
2166
|
cvv: null,
|
|
2056
2167
|
});
|
|
2057
|
-
const readyFieldTypes = useRef(new Set());
|
|
2058
|
-
const onReadyFiredRef = useRef(false);
|
|
2059
|
-
const vaultRef = useRef(vault);
|
|
2060
|
-
const onChangeRef = useRef(onChange);
|
|
2061
|
-
const onReadyRef = useRef(onReady);
|
|
2062
|
-
const onFocusRef = useRef(onFocus);
|
|
2063
|
-
const onBlurRef = useRef(onBlur);
|
|
2064
|
-
useEffect(() => { onChangeRef.current = onChange; }, [onChange]);
|
|
2065
|
-
useEffect(() => { onReadyRef.current = onReady; }, [onReady]);
|
|
2066
|
-
useEffect(() => { onFocusRef.current = onFocus; }, [onFocus]);
|
|
2067
|
-
useEffect(() => { onBlurRef.current = onBlur; }, [onBlur]);
|
|
2068
|
-
// When the vault is recreated (e.g. appearance/fonts props change on OzElements),
|
|
2069
|
-
// context readyCount is reset but this ref is not. Reset so onReady fires once when all 3 are ready.
|
|
2070
|
-
// The cleanup resets readyFieldTypes when the component unmounts (covers React StrictMode double-invoke
|
|
2071
|
-
// and SPA scenarios where the parent re-mounts this component).
|
|
2072
|
-
useEffect(() => {
|
|
2073
|
-
if (vault !== vaultRef.current) {
|
|
2074
|
-
vaultRef.current = vault;
|
|
2075
|
-
readyFieldTypes.current = new Set();
|
|
2076
|
-
onReadyFiredRef.current = false;
|
|
2077
|
-
}
|
|
2078
|
-
return () => {
|
|
2079
|
-
readyFieldTypes.current = new Set();
|
|
2080
|
-
onReadyFiredRef.current = false;
|
|
2081
|
-
};
|
|
2082
|
-
}, [vault]);
|
|
2083
|
-
const [error, setError] = useState();
|
|
2084
|
-
const handleCardNumberReady = useCallback(() => {
|
|
2085
|
-
var _a;
|
|
2086
|
-
readyFieldTypes.current.add('cardNumber');
|
|
2087
|
-
if (readyFieldTypes.current.size >= 3 && !onReadyFiredRef.current) {
|
|
2088
|
-
onReadyFiredRef.current = true;
|
|
2089
|
-
(_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef);
|
|
2090
|
-
}
|
|
2091
|
-
}, []);
|
|
2092
|
-
const handleExpiryReady = useCallback(() => {
|
|
2093
|
-
var _a;
|
|
2094
|
-
readyFieldTypes.current.add('expiry');
|
|
2095
|
-
if (readyFieldTypes.current.size >= 3 && !onReadyFiredRef.current) {
|
|
2096
|
-
onReadyFiredRef.current = true;
|
|
2097
|
-
(_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef);
|
|
2098
|
-
}
|
|
2099
|
-
}, []);
|
|
2100
|
-
const handleCvvReady = useCallback(() => {
|
|
2101
|
-
var _a;
|
|
2102
|
-
readyFieldTypes.current.add('cvv');
|
|
2103
|
-
if (readyFieldTypes.current.size >= 3 && !onReadyFiredRef.current) {
|
|
2104
|
-
onReadyFiredRef.current = true;
|
|
2105
|
-
(_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef);
|
|
2106
|
-
}
|
|
2107
|
-
}, []);
|
|
2108
2168
|
const emitChange = useCallback(() => {
|
|
2109
2169
|
var _a;
|
|
2110
2170
|
const { cardNumber, expiry, cvv } = fieldState.current;
|
|
@@ -2119,20 +2179,16 @@ function OzCard({ style, styles, classNames, labels, labelStyle, labelClassName,
|
|
|
2119
2179
|
error: err,
|
|
2120
2180
|
fields: Object.assign({}, fieldState.current),
|
|
2121
2181
|
});
|
|
2122
|
-
}, []);
|
|
2123
|
-
const gapStr = typeof gap === 'string' ? gap : `${gap}px`;
|
|
2124
|
-
const resolvedLabelStyle = labelStyle
|
|
2125
|
-
? Object.assign(Object.assign({}, DEFAULT_LABEL_STYLE), labelStyle) : DEFAULT_LABEL_STYLE;
|
|
2126
|
-
const renderLabel = (text) => renderFieldLabel(text, labelClassName, resolvedLabelStyle);
|
|
2182
|
+
}, [setError, onChangeRef]);
|
|
2127
2183
|
const showError = !hideErrors && error;
|
|
2128
2184
|
const errorNode = showError
|
|
2129
2185
|
? renderError
|
|
2130
2186
|
? renderError(error)
|
|
2131
2187
|
: (jsx("div", { role: "alert", className: errorClassName, style: errorStyle ? Object.assign(Object.assign({}, DEFAULT_ERROR_STYLE), errorStyle) : DEFAULT_ERROR_STYLE, children: error }))
|
|
2132
2188
|
: null;
|
|
2133
|
-
const cardNumberField = (jsxs("div", { children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.cardNumber), jsx(OzCardNumber, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.cardNumber), className: classNames === null || classNames === void 0 ? void 0 : classNames.cardNumber, placeholder: (_a = placeholders === null || placeholders === void 0 ? void 0 : placeholders.cardNumber) !== null && _a !== void 0 ? _a : 'Card number', disabled: disabled, onChange: (e) => { fieldState.current.cardNumber = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'cardNumber'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'cardNumber'); }, onReady:
|
|
2134
|
-
const expiryField = (jsxs("div", { style: layout === 'default' ? { flex: 1 } : undefined, children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.expiry), jsx(OzExpiry, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.expiry), className: classNames === null || classNames === void 0 ? void 0 : classNames.expiry, placeholder: (_b = placeholders === null || placeholders === void 0 ? void 0 : placeholders.expiry) !== null && _b !== void 0 ? _b : 'MM / YY', disabled: disabled, onChange: (e) => { fieldState.current.expiry = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'expiry'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'expiry'); }, onReady:
|
|
2135
|
-
const cvvField = (jsxs("div", { style: layout === 'default' ? { flex: 1 } : undefined, children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.cvv), jsx(OzCvv, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.cvv), className: classNames === null || classNames === void 0 ? void 0 : classNames.cvv, placeholder: (_c = placeholders === null || placeholders === void 0 ? void 0 : placeholders.cvv) !== null && _c !== void 0 ? _c : 'CVV', disabled: disabled, onChange: (e) => { fieldState.current.cvv = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'cvv'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'cvv'); }, onReady:
|
|
2189
|
+
const cardNumberField = (jsxs("div", { children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.cardNumber), jsx(OzCardNumber, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.cardNumber), className: classNames === null || classNames === void 0 ? void 0 : classNames.cardNumber, placeholder: (_a = placeholders === null || placeholders === void 0 ? void 0 : placeholders.cardNumber) !== null && _a !== void 0 ? _a : 'Card number', disabled: disabled, onChange: (e) => { fieldState.current.cardNumber = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'cardNumber'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'cardNumber'); }, onReady: readyHandlers['cardNumber'] })] }));
|
|
2190
|
+
const expiryField = (jsxs("div", { style: layout === 'default' ? { flex: 1 } : undefined, children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.expiry), jsx(OzExpiry, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.expiry), className: classNames === null || classNames === void 0 ? void 0 : classNames.expiry, placeholder: (_b = placeholders === null || placeholders === void 0 ? void 0 : placeholders.expiry) !== null && _b !== void 0 ? _b : 'MM / YY', disabled: disabled, onChange: (e) => { fieldState.current.expiry = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'expiry'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'expiry'); }, onReady: readyHandlers['expiry'] })] }));
|
|
2191
|
+
const cvvField = (jsxs("div", { style: layout === 'default' ? { flex: 1 } : undefined, children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.cvv), jsx(OzCvv, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.cvv), className: classNames === null || classNames === void 0 ? void 0 : classNames.cvv, placeholder: (_c = placeholders === null || placeholders === void 0 ? void 0 : placeholders.cvv) !== null && _c !== void 0 ? _c : 'CVV', disabled: disabled, onChange: (e) => { fieldState.current.cvv = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'cvv'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'cvv'); }, onReady: readyHandlers['cvv'] })] }));
|
|
2136
2192
|
if (layout === 'rows') {
|
|
2137
2193
|
return (jsxs("div", { className: className, style: { width: '100%', display: 'flex', flexDirection: 'column', gap: gapStr }, children: [cardNumberField, expiryField, cvvField, errorNode] }));
|
|
2138
2194
|
}
|
|
@@ -2153,49 +2209,21 @@ const OzBankRoutingNumber = (props) => jsx(OzFieldBase, Object.assign({ type: "r
|
|
|
2153
2209
|
function OzBankCard({ style, styles, classNames, labels, labelStyle, labelClassName, gap = 8, hideErrors = false, errorStyle, errorClassName, renderError, onChange, onReady, onFocus, onBlur, disabled, className, placeholders, }) {
|
|
2154
2210
|
var _a, _b;
|
|
2155
2211
|
const { vault } = useContext(OzContext);
|
|
2212
|
+
const { onChangeRef, onFocusRef, onBlurRef, readyHandlers, error, setError, gapStr, renderLabel, } = useCardBase({
|
|
2213
|
+
vault,
|
|
2214
|
+
fieldNames: ['accountNumber', 'routingNumber'],
|
|
2215
|
+
onChange,
|
|
2216
|
+
onReady,
|
|
2217
|
+
onFocus,
|
|
2218
|
+
onBlur,
|
|
2219
|
+
gap,
|
|
2220
|
+
labelStyle,
|
|
2221
|
+
labelClassName,
|
|
2222
|
+
});
|
|
2156
2223
|
const fieldState = useRef({
|
|
2157
2224
|
accountNumber: null,
|
|
2158
2225
|
routingNumber: null,
|
|
2159
2226
|
});
|
|
2160
|
-
const readyFieldTypes = useRef(new Set());
|
|
2161
|
-
const onReadyFiredRef = useRef(false);
|
|
2162
|
-
const vaultRef = useRef(vault);
|
|
2163
|
-
const onChangeRef = useRef(onChange);
|
|
2164
|
-
const onReadyRef = useRef(onReady);
|
|
2165
|
-
const onFocusRef = useRef(onFocus);
|
|
2166
|
-
const onBlurRef = useRef(onBlur);
|
|
2167
|
-
useEffect(() => { onChangeRef.current = onChange; }, [onChange]);
|
|
2168
|
-
useEffect(() => { onReadyRef.current = onReady; }, [onReady]);
|
|
2169
|
-
useEffect(() => { onFocusRef.current = onFocus; }, [onFocus]);
|
|
2170
|
-
useEffect(() => { onBlurRef.current = onBlur; }, [onBlur]);
|
|
2171
|
-
useEffect(() => {
|
|
2172
|
-
if (vault !== vaultRef.current) {
|
|
2173
|
-
vaultRef.current = vault;
|
|
2174
|
-
readyFieldTypes.current = new Set();
|
|
2175
|
-
onReadyFiredRef.current = false;
|
|
2176
|
-
}
|
|
2177
|
-
return () => {
|
|
2178
|
-
readyFieldTypes.current = new Set();
|
|
2179
|
-
onReadyFiredRef.current = false;
|
|
2180
|
-
};
|
|
2181
|
-
}, [vault]);
|
|
2182
|
-
const [error, setError] = useState();
|
|
2183
|
-
const handleAccountReady = useCallback(() => {
|
|
2184
|
-
var _a;
|
|
2185
|
-
readyFieldTypes.current.add('accountNumber');
|
|
2186
|
-
if (readyFieldTypes.current.size >= 2 && !onReadyFiredRef.current) {
|
|
2187
|
-
onReadyFiredRef.current = true;
|
|
2188
|
-
(_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef);
|
|
2189
|
-
}
|
|
2190
|
-
}, []);
|
|
2191
|
-
const handleRoutingReady = useCallback(() => {
|
|
2192
|
-
var _a;
|
|
2193
|
-
readyFieldTypes.current.add('routingNumber');
|
|
2194
|
-
if (readyFieldTypes.current.size >= 2 && !onReadyFiredRef.current) {
|
|
2195
|
-
onReadyFiredRef.current = true;
|
|
2196
|
-
(_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef);
|
|
2197
|
-
}
|
|
2198
|
-
}, []);
|
|
2199
2227
|
const emitChange = useCallback(() => {
|
|
2200
2228
|
var _a;
|
|
2201
2229
|
const { accountNumber, routingNumber } = fieldState.current;
|
|
@@ -2208,18 +2236,14 @@ function OzBankCard({ style, styles, classNames, labels, labelStyle, labelClassN
|
|
|
2208
2236
|
error: err,
|
|
2209
2237
|
fields: Object.assign({}, fieldState.current),
|
|
2210
2238
|
});
|
|
2211
|
-
}, []);
|
|
2212
|
-
const gapStr = typeof gap === 'string' ? gap : `${gap}px`;
|
|
2213
|
-
const resolvedLabelStyle = labelStyle
|
|
2214
|
-
? Object.assign(Object.assign({}, DEFAULT_LABEL_STYLE), labelStyle) : DEFAULT_LABEL_STYLE;
|
|
2215
|
-
const renderLabel = (text) => renderFieldLabel(text, labelClassName, resolvedLabelStyle);
|
|
2239
|
+
}, [setError, onChangeRef]);
|
|
2216
2240
|
const showError = !hideErrors && error;
|
|
2217
2241
|
const errorNode = showError
|
|
2218
2242
|
? renderError
|
|
2219
2243
|
? renderError(error)
|
|
2220
2244
|
: (jsx("div", { role: "alert", className: errorClassName, style: errorStyle ? Object.assign(Object.assign({}, DEFAULT_ERROR_STYLE), errorStyle) : DEFAULT_ERROR_STYLE, children: error }))
|
|
2221
2245
|
: null;
|
|
2222
|
-
return (jsxs("div", { className: className, style: { width: '100%', display: 'flex', flexDirection: 'column', gap: gapStr }, children: [jsxs("div", { children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.accountNumber), jsx(OzBankAccountNumber, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.accountNumber), className: classNames === null || classNames === void 0 ? void 0 : classNames.accountNumber, placeholder: (_a = placeholders === null || placeholders === void 0 ? void 0 : placeholders.accountNumber) !== null && _a !== void 0 ? _a : 'Account number', disabled: disabled, onChange: (e) => { fieldState.current.accountNumber = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'accountNumber'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'accountNumber'); }, onReady:
|
|
2246
|
+
return (jsxs("div", { className: className, style: { width: '100%', display: 'flex', flexDirection: 'column', gap: gapStr }, children: [jsxs("div", { children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.accountNumber), jsx(OzBankAccountNumber, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.accountNumber), className: classNames === null || classNames === void 0 ? void 0 : classNames.accountNumber, placeholder: (_a = placeholders === null || placeholders === void 0 ? void 0 : placeholders.accountNumber) !== null && _a !== void 0 ? _a : 'Account number', disabled: disabled, onChange: (e) => { fieldState.current.accountNumber = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'accountNumber'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'accountNumber'); }, onReady: readyHandlers['accountNumber'] })] }), jsxs("div", { children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.routingNumber), jsx(OzBankRoutingNumber, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.routingNumber), className: classNames === null || classNames === void 0 ? void 0 : classNames.routingNumber, placeholder: (_b = placeholders === null || placeholders === void 0 ? void 0 : placeholders.routingNumber) !== null && _b !== void 0 ? _b : 'Routing number', disabled: disabled, onChange: (e) => { fieldState.current.routingNumber = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'routingNumber'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'routingNumber'); }, onReady: readyHandlers['routingNumber'] })] }), errorNode] }));
|
|
2223
2247
|
}
|
|
2224
2248
|
|
|
2225
2249
|
export { OzBankAccountNumber, OzBankCard, OzBankRoutingNumber, OzCard, OzCardNumber, OzCvv, OzElements, OzExpiry, createFetchWaxKey, useOzElements };
|