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