@ozura/elements 1.0.1 → 1.0.2-next.10

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.
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { createContext, useContext, useRef, useEffect, useState, useCallback, useMemo } from 'react';
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://elements.ozura.com";
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
- if (!card) {
1473
- pending.reject(new OzError('Vault returned a token result without card metadata possible vault API change.', undefined, 'server'));
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: handleCardNumberReady })] }));
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: handleExpiryReady })] }));
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: handleCvvReady })] }));
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: handleAccountReady })] }), 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: handleRoutingReady })] }), errorNode] }));
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 };