@ozura/elements 1.3.1-next.70 → 1.3.1-next.72

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.
@@ -219,6 +219,26 @@ export interface UseOzElementsReturn {
219
219
  * Clears all mounted element fields without destroying the vault.
220
220
  */
221
221
  reset: () => void;
222
+ /**
223
+ * `true` when every mounted field has reported `complete && valid`.
224
+ * Use this to gate the pay button without wiring individual `@change`
225
+ * listeners — reacts in real time as the customer fills in fields.
226
+ *
227
+ * @example
228
+ * const { ready, isComplete, createToken } = useOzElements();
229
+ * // <button :disabled="!ready || !isComplete" @click="createToken()">Pay</button>
230
+ */
231
+ isComplete: ComputedRef<boolean>;
232
+ /**
233
+ * `true` while `createToken()` or `createBankToken()` is in progress,
234
+ * including the transparent wax-key refresh phase. Use this to keep the
235
+ * pay button disabled and prevent double-submission.
236
+ *
237
+ * @example
238
+ * const { isTokenizing, createToken } = useOzElements();
239
+ * // <button :disabled="isTokenizing" @click="createToken()">Pay</button>
240
+ */
241
+ isTokenizing: ComputedRef<boolean>;
222
242
  }
223
243
  /**
224
244
  * Returns createToken, createBankToken, ready, initError, tokenizeCount, and reset.
@@ -219,6 +219,26 @@ export interface UseOzElementsReturn {
219
219
  * Clears all mounted element fields without destroying the vault.
220
220
  */
221
221
  reset: () => void;
222
+ /**
223
+ * `true` when every mounted field has reported `complete && valid`.
224
+ * Use this to gate the pay button without wiring individual `@change`
225
+ * listeners — reacts in real time as the customer fills in fields.
226
+ *
227
+ * @example
228
+ * const { ready, isComplete, createToken } = useOzElements();
229
+ * // <button :disabled="!ready || !isComplete" @click="createToken()">Pay</button>
230
+ */
231
+ isComplete: ComputedRef<boolean>;
232
+ /**
233
+ * `true` while `createToken()` or `createBankToken()` is in progress,
234
+ * including the transparent wax-key refresh phase. Use this to keep the
235
+ * pay button disabled and prevent double-submission.
236
+ *
237
+ * @example
238
+ * const { isTokenizing, createToken } = useOzElements();
239
+ * // <button :disabled="isTokenizing" @click="createToken()">Pay</button>
240
+ */
241
+ isTokenizing: ComputedRef<boolean>;
222
242
  }
223
243
  /**
224
244
  * Returns createToken, createBankToken, ready, initError, tokenizeCount, and reset.
@@ -2322,6 +2322,8 @@ const OzElements = vue.defineComponent({
2322
2322
  const mountedCount = vue.ref(0);
2323
2323
  const readyCount = vue.ref(0);
2324
2324
  const tokenizeCount = vue.ref(0);
2325
+ const changeTick = vue.ref(0);
2326
+ const notifyChange = () => { changeTick.value++; };
2325
2327
  const notifyMount = () => { mountedCount.value++; };
2326
2328
  let readyEmitted = false;
2327
2329
  const notifyReady = () => {
@@ -2347,10 +2349,12 @@ const OzElements = vue.defineComponent({
2347
2349
  mountedCount,
2348
2350
  readyCount,
2349
2351
  tokenizeCount,
2352
+ changeTick,
2350
2353
  notifyMount,
2351
2354
  notifyReady,
2352
2355
  notifyUnmount,
2353
2356
  notifyTokenize,
2357
+ notifyChange,
2354
2358
  });
2355
2359
  let createdVault = null;
2356
2360
  let abortController = null;
@@ -2419,7 +2423,7 @@ function useOzElements() {
2419
2423
  if (!ctx) {
2420
2424
  throw new Error('[OzVault] useOzElements() must be called inside <OzElements>');
2421
2425
  }
2422
- const { vault, initError, mountedCount, readyCount, tokenizeCount, notifyTokenize } = ctx;
2426
+ const { vault, initError, mountedCount, readyCount, tokenizeCount, changeTick, notifyTokenize, notifyChange } = ctx;
2423
2427
  const ready = vue.computed(() => vault.value !== null &&
2424
2428
  vault.value.isReady &&
2425
2429
  mountedCount.value > 0 &&
@@ -2428,20 +2432,42 @@ function useOzElements() {
2428
2432
  if (!vault.value) {
2429
2433
  throw new Error('[OzVault] vault is not ready — wait for ready before calling createToken()');
2430
2434
  }
2431
- const result = await vault.value.createToken(options);
2432
- notifyTokenize();
2433
- return result;
2435
+ // Start the call so vault._tokenizing flips synchronously, then bump changeTick
2436
+ // so `isTokenizing` recomputes as `true`; bump again on settle. (vault.isTokenizing
2437
+ // is a plain getter — nothing else would recompute the computed while in flight.)
2438
+ const promise = vault.value.createToken(options);
2439
+ notifyChange();
2440
+ try {
2441
+ const result = await promise;
2442
+ notifyTokenize();
2443
+ return result;
2444
+ }
2445
+ finally {
2446
+ notifyChange();
2447
+ }
2434
2448
  };
2435
2449
  const createBankToken = async (options) => {
2436
2450
  if (!vault.value) {
2437
2451
  throw new Error('[OzVault] vault is not ready — wait for ready before calling createBankToken()');
2438
2452
  }
2439
- const result = await vault.value.createBankToken(options);
2440
- notifyTokenize();
2441
- return result;
2453
+ const promise = vault.value.createBankToken(options);
2454
+ notifyChange();
2455
+ try {
2456
+ const result = await promise;
2457
+ notifyTokenize();
2458
+ return result;
2459
+ }
2460
+ finally {
2461
+ notifyChange();
2462
+ }
2442
2463
  };
2443
2464
  const reset = () => { var _a; (_a = vault.value) === null || _a === void 0 ? void 0 : _a.reset(); };
2444
- return { createToken, createBankToken, ready, initError, tokenizeCount, reset };
2465
+ // `void changeTick.value` registers a reactive dependency so these recompute when
2466
+ // notifyChange() fires (field change / tokenize start-stop). vault.isComplete and
2467
+ // vault.isTokenizing read non-reactive internal Maps/flags that Vue cannot track.
2468
+ const isComplete = vue.computed(() => { var _a, _b; void changeTick.value; return (_b = (_a = vault.value) === null || _a === void 0 ? void 0 : _a.isComplete) !== null && _b !== void 0 ? _b : false; });
2469
+ const isTokenizing = vue.computed(() => { var _a, _b; void changeTick.value; return (_b = (_a = vault.value) === null || _a === void 0 ? void 0 : _a.isTokenizing) !== null && _b !== void 0 ? _b : false; });
2470
+ return { createToken, createBankToken, ready, initError, tokenizeCount, reset, isComplete, isTokenizing };
2445
2471
  }
2446
2472
  function createFieldComponent(displayName, mountElement) {
2447
2473
  return vue.defineComponent({
@@ -2457,7 +2483,7 @@ function createFieldComponent(displayName, mountElement) {
2457
2483
  if (!ctx) {
2458
2484
  throw new Error('[OzVault] useOzElements() must be called inside <OzElements>');
2459
2485
  }
2460
- const { vault, notifyMount, notifyReady, notifyUnmount } = ctx;
2486
+ const { vault, notifyMount, notifyReady, notifyUnmount, notifyChange } = ctx;
2461
2487
  const containerRef = vue.ref(null);
2462
2488
  let element = null;
2463
2489
  let notifyMountCalled = false;
@@ -2472,7 +2498,7 @@ function createFieldComponent(displayName, mountElement) {
2472
2498
  notifyMountCalled = true;
2473
2499
  notifyMount();
2474
2500
  element.on('ready', () => notifyReady());
2475
- element.on('change', (e) => emit('change', e));
2501
+ element.on('change', (e) => { emit('change', e); notifyChange(); });
2476
2502
  element.on('focus', () => emit('focus'));
2477
2503
  element.on('blur', () => emit('blur'));
2478
2504
  element.mount(containerRef.value);