@cimplify/sdk 0.8.1 → 0.8.2

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/dist/react.js CHANGED
@@ -1,8 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
3
+ var React2 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React2__default = /*#__PURE__*/_interopDefault(React2);
9
+
6
10
  // src/react/index.tsx
7
11
 
8
12
  // src/types/elements.ts
@@ -16,6 +20,7 @@ var MESSAGE_TYPES = {
16
20
  // Parent → Iframe
17
21
  INIT: "init",
18
22
  SET_TOKEN: "set_token",
23
+ SET_CART: "set_cart",
19
24
  GET_DATA: "get_data",
20
25
  PROCESS_CHECKOUT: "process_checkout",
21
26
  ABORT_CHECKOUT: "abort_checkout",
@@ -196,7 +201,7 @@ function deriveAdsApiUrl() {
196
201
  }
197
202
  return "https://api.cimplify.io";
198
203
  }
199
- var AdContext = react.createContext({
204
+ var AdContext = React2.createContext({
200
205
  siteId: null,
201
206
  config: null,
202
207
  isLoading: true,
@@ -204,7 +209,7 @@ var AdContext = react.createContext({
204
209
  apiBase: "https://api.cimplify.io"
205
210
  });
206
211
  function useAds() {
207
- return react.useContext(AdContext);
212
+ return React2.useContext(AdContext);
208
213
  }
209
214
  function AdProvider({
210
215
  siteId,
@@ -213,10 +218,10 @@ function AdProvider({
213
218
  children
214
219
  }) {
215
220
  const resolvedApiBase = apiBase || deriveAdsApiUrl();
216
- const [config, setConfig] = react.useState(null);
217
- const [isLoading, setIsLoading] = react.useState(true);
218
- const [identity, setIdentity] = react.useState(null);
219
- react.useEffect(() => {
221
+ const [config, setConfig] = React2.useState(null);
222
+ const [isLoading, setIsLoading] = React2.useState(true);
223
+ const [identity, setIdentity] = React2.useState(null);
224
+ React2.useEffect(() => {
220
225
  const userIdentity = getUserIdentity(authenticatedAccountId);
221
226
  setIdentity(userIdentity);
222
227
  fetch(`${resolvedApiBase}/ads/config/${siteId}`).then((r) => r.json()).then((data) => {
@@ -239,11 +244,11 @@ function Ad({
239
244
  onClick
240
245
  }) {
241
246
  const { siteId, config, isLoading, identity, apiBase } = useAds();
242
- const [ad, setAd] = react.useState(null);
243
- const [error, setError] = react.useState(false);
244
- const impressionTracked = react.useRef(false);
245
- const containerRef = react.useRef(null);
246
- react.useEffect(() => {
247
+ const [ad, setAd] = React2.useState(null);
248
+ const [error, setError] = React2.useState(false);
249
+ const impressionTracked = React2.useRef(false);
250
+ const containerRef = React2.useRef(null);
251
+ React2.useEffect(() => {
247
252
  if (isLoading || !config?.enabled || !siteId || !identity) return;
248
253
  const path = typeof window !== "undefined" ? window.location.pathname : "/";
249
254
  const referrer = typeof document !== "undefined" ? document.referrer : "";
@@ -286,7 +291,7 @@ function Ad({
286
291
  }
287
292
  }).catch(() => setError(true));
288
293
  }, [siteId, config, isLoading, slot, identity, apiBase]);
289
- react.useEffect(() => {
294
+ React2.useEffect(() => {
290
295
  if (!ad || impressionTracked.current || typeof window === "undefined" || !identity) return;
291
296
  const observer = new IntersectionObserver(
292
297
  ([entry]) => {
@@ -345,6 +350,61 @@ function Ad({
345
350
  }
346
351
  );
347
352
  }
353
+
354
+ // src/utils/cart-transform.ts
355
+ function getSelections(item) {
356
+ if (item.bundle_resolved?.selections?.length) {
357
+ return item.bundle_resolved.selections.map((s) => ({
358
+ name: s.product_name || s.component_id,
359
+ quantity: s.quantity,
360
+ variant_name: s.variant_name
361
+ }));
362
+ }
363
+ if (item.composite_resolved?.selections?.length) {
364
+ return item.composite_resolved.selections.map((s) => ({
365
+ name: s.component_name || s.component_id,
366
+ quantity: s.quantity
367
+ }));
368
+ }
369
+ return void 0;
370
+ }
371
+ function mapItem(item) {
372
+ const result = {
373
+ name: item.name,
374
+ quantity: item.quantity,
375
+ unit_price: String(item.base_price),
376
+ total_price: String(item.total_price),
377
+ line_type: item.line_type
378
+ };
379
+ if (item.image_url) result.image_url = item.image_url;
380
+ const variantName = item.variant_info?.name || item.variant_name || void 0;
381
+ if (variantName) result.variant_name = variantName;
382
+ if (item.scheduled_start) result.scheduled_start = item.scheduled_start;
383
+ if (item.scheduled_end) result.scheduled_end = item.scheduled_end;
384
+ const selections = getSelections(item);
385
+ if (selections) result.selections = selections;
386
+ if (item.add_on_options?.length) {
387
+ result.add_ons = item.add_on_options.map((opt) => ({
388
+ name: opt.name,
389
+ price: String(opt.price ?? "0")
390
+ }));
391
+ }
392
+ if (item.special_instructions) {
393
+ result.special_instructions = item.special_instructions;
394
+ }
395
+ return result;
396
+ }
397
+ function transformToCheckoutCart(cart) {
398
+ return {
399
+ items: cart.items.map(mapItem),
400
+ subtotal: String(cart.pricing.subtotal),
401
+ tax_amount: String(cart.pricing.tax_amount),
402
+ total_discounts: String(cart.pricing.total_discounts),
403
+ service_charge: String(cart.pricing.service_charge),
404
+ total: String(cart.pricing.total_price),
405
+ currency: cart.pricing.currency
406
+ };
407
+ }
348
408
  var SPACE = { sm: 8};
349
409
  function shellColors(isDark, primaryColor) {
350
410
  return {
@@ -399,51 +459,48 @@ function CimplifyCheckout({
399
459
  demoMode,
400
460
  className
401
461
  }) {
402
- const resolvedOrderTypes = react.useMemo(
462
+ const resolvedOrderTypes = React2.useMemo(
403
463
  () => orderTypes && orderTypes.length > 0 ? orderTypes : ["pickup", "delivery"],
404
464
  [orderTypes]
405
465
  );
406
- const [orderType, setOrderType] = react.useState(resolvedOrderTypes[0] || "pickup");
407
- const [status, setStatus] = react.useState(null);
408
- const [statusText, setStatusText] = react.useState("");
409
- const [isSubmitting, setIsSubmitting] = react.useState(false);
410
- const [isInitializing, setIsInitializing] = react.useState(false);
411
- const [errorMessage, setErrorMessage] = react.useState(null);
412
- const [resolvedBusinessId, setResolvedBusinessId] = react.useState(businessId ?? null);
413
- const [resolvedCartId, setResolvedCartId] = react.useState(cartId ?? null);
414
- const checkoutMountRef = react.useRef(null);
415
- const elementsRef = react.useRef(null);
416
- const activeCheckoutRef = react.useRef(null);
417
- const initialAppearanceRef = react.useRef(appearance);
418
- const hasWarnedInlineAppearanceRef = react.useRef(false);
419
- const isMountedRef = react.useRef(true);
420
- const demoRunRef = react.useRef(0);
421
- const onCompleteRef = react.useRef(onComplete);
422
- const onErrorRef = react.useRef(onError);
423
- const onStatusChangeRef = react.useRef(onStatusChange);
424
- const handleSubmitRef = react.useRef(async () => {
425
- });
426
- onCompleteRef.current = onComplete;
427
- onErrorRef.current = onError;
428
- onStatusChangeRef.current = onStatusChange;
466
+ const [orderType, setOrderType] = React2.useState(resolvedOrderTypes[0] || "pickup");
467
+ const [status, setStatus] = React2.useState(null);
468
+ const [statusText, setStatusText] = React2.useState("");
469
+ const [isSubmitting, setIsSubmitting] = React2.useState(false);
470
+ const [isInitializing, setIsInitializing] = React2.useState(false);
471
+ const [errorMessage, setErrorMessage] = React2.useState(null);
472
+ const [resolvedBusinessId, setResolvedBusinessId] = React2.useState(businessId ?? null);
473
+ const [resolvedCartId, setResolvedCartId] = React2.useState(cartId ?? null);
474
+ const [resolvedCart, setResolvedCart] = React2.useState(null);
475
+ const checkoutMountRef = React2.useRef(null);
476
+ const elementsRef = React2.useRef(null);
477
+ const activeCheckoutRef = React2.useRef(null);
478
+ const initialAppearanceRef = React2.useRef(appearance);
479
+ const hasWarnedInlineAppearanceRef = React2.useRef(false);
480
+ const isMountedRef = React2.useRef(true);
481
+ const demoRunRef = React2.useRef(0);
429
482
  const isDemoCheckout = demoMode ?? client.getPublicKey().trim().length === 0;
430
483
  const isTestMode = client.isTestMode();
431
484
  const primaryColor = appearance?.variables?.primaryColor || "#0a2540";
432
485
  const isDark = appearance?.theme === "dark";
433
- const emitStatus = react.useCallback(
486
+ const emitStatus = React2__default.default.useEffectEvent(
434
487
  (nextStatus, context = {}) => {
435
488
  setStatus(nextStatus);
436
489
  setStatusText(context.display_text || "");
437
- onStatusChangeRef.current?.(nextStatus, context);
438
- },
439
- []
490
+ onStatusChange?.(nextStatus, context);
491
+ }
440
492
  );
441
- react.useEffect(() => {
493
+ const fireError = React2__default.default.useEffectEvent(
494
+ (error) => {
495
+ onError?.(error);
496
+ }
497
+ );
498
+ React2.useEffect(() => {
442
499
  if (!resolvedOrderTypes.includes(orderType)) {
443
500
  setOrderType(resolvedOrderTypes[0] || "pickup");
444
501
  }
445
502
  }, [resolvedOrderTypes, orderType]);
446
- react.useEffect(() => {
503
+ React2.useEffect(() => {
447
504
  if (appearance && appearance !== initialAppearanceRef.current && !hasWarnedInlineAppearanceRef.current) {
448
505
  hasWarnedInlineAppearanceRef.current = true;
449
506
  console.warn(
@@ -451,7 +508,7 @@ function CimplifyCheckout({
451
508
  );
452
509
  }
453
510
  }, [appearance]);
454
- react.useEffect(() => {
511
+ React2.useEffect(() => {
455
512
  let cancelled = false;
456
513
  async function bootstrap() {
457
514
  if (isDemoCheckout) {
@@ -472,6 +529,12 @@ function CimplifyCheckout({
472
529
  setIsInitializing(false);
473
530
  setErrorMessage(null);
474
531
  }
532
+ client.cart.get().then((cartResult) => {
533
+ if (!cancelled && cartResult.ok && cartResult.value) {
534
+ setResolvedCart(cartResult.value);
535
+ }
536
+ }).catch(() => {
537
+ });
475
538
  return;
476
539
  }
477
540
  if (!cancelled) {
@@ -489,7 +552,7 @@ function CimplifyCheckout({
489
552
  setResolvedCartId(null);
490
553
  setErrorMessage(message);
491
554
  setIsInitializing(false);
492
- onErrorRef.current?.({ code: "BUSINESS_ID_REQUIRED", message });
555
+ fireError({ code: "BUSINESS_ID_REQUIRED", message });
493
556
  }
494
557
  return;
495
558
  }
@@ -504,11 +567,14 @@ function CimplifyCheckout({
504
567
  setResolvedCartId(null);
505
568
  setErrorMessage(message);
506
569
  setIsInitializing(false);
507
- onErrorRef.current?.({ code: "CART_EMPTY", message });
570
+ fireError({ code: "CART_EMPTY", message });
508
571
  }
509
572
  return;
510
573
  }
511
574
  nextCartId = cartResult.value.id;
575
+ if (!cancelled) {
576
+ setResolvedCart(cartResult.value);
577
+ }
512
578
  }
513
579
  if (!cancelled) {
514
580
  setResolvedBusinessId(nextBusinessId);
@@ -522,7 +588,7 @@ function CimplifyCheckout({
522
588
  cancelled = true;
523
589
  };
524
590
  }, [businessId, cartId, client, isDemoCheckout]);
525
- react.useEffect(() => {
591
+ React2.useEffect(() => {
526
592
  return () => {
527
593
  isMountedRef.current = false;
528
594
  demoRunRef.current += 1;
@@ -530,45 +596,12 @@ function CimplifyCheckout({
530
596
  activeCheckoutRef.current = null;
531
597
  };
532
598
  }, []);
533
- react.useEffect(() => {
534
- if (isDemoCheckout || !resolvedBusinessId) {
535
- elementsRef.current = null;
536
- return;
537
- }
538
- const elements = client.elements(resolvedBusinessId, {
539
- appearance: initialAppearanceRef.current,
540
- linkUrl
541
- });
542
- elementsRef.current = elements;
543
- const checkout = elements.create("checkout", {
544
- orderTypes: resolvedOrderTypes,
545
- defaultOrderType: resolvedOrderTypes[0]
546
- });
547
- if (checkoutMountRef.current) {
548
- checkout.mount(checkoutMountRef.current);
549
- }
550
- checkout.on("order_type_changed", (data) => {
551
- const typed = data;
552
- if (typed.orderType) {
553
- setOrderType(typed.orderType);
554
- }
555
- });
556
- checkout.on("request_submit", () => {
557
- void handleSubmitRef.current();
558
- });
559
- return () => {
560
- activeCheckoutRef.current?.abort();
561
- activeCheckoutRef.current = null;
562
- elements.destroy();
563
- elementsRef.current = null;
564
- };
565
- }, [client, resolvedBusinessId, isDemoCheckout]);
566
- const handleSubmit = react.useCallback(async () => {
599
+ const handleSubmit = React2__default.default.useEffectEvent(async () => {
567
600
  if (isSubmitting || isInitializing || !resolvedCartId) {
568
601
  if (!resolvedCartId && !isInitializing) {
569
602
  const message = "Your cart is empty. Add items before checkout.";
570
603
  setErrorMessage(message);
571
- onErrorRef.current?.({ code: "CART_EMPTY", message });
604
+ fireError({ code: "CART_EMPTY", message });
572
605
  }
573
606
  return;
574
607
  }
@@ -603,7 +636,7 @@ function CimplifyCheckout({
603
636
  order_number: result.order?.order_number,
604
637
  display_text: statusToLabel("success")
605
638
  });
606
- onCompleteRef.current(result);
639
+ onComplete(result);
607
640
  } finally {
608
641
  if (isMountedRef.current && runId === demoRunRef.current) {
609
642
  setIsSubmitting(false);
@@ -614,7 +647,7 @@ function CimplifyCheckout({
614
647
  if (!elementsRef.current) {
615
648
  const message = "Checkout is still initializing. Please try again.";
616
649
  setErrorMessage(message);
617
- onErrorRef.current?.({ code: "CHECKOUT_NOT_READY", message });
650
+ fireError({ code: "CHECKOUT_NOT_READY", message });
618
651
  setIsSubmitting(false);
619
652
  return;
620
653
  }
@@ -629,31 +662,65 @@ function CimplifyCheckout({
629
662
  try {
630
663
  const result = await checkout;
631
664
  if (result.success) {
632
- onCompleteRef.current(result);
665
+ onComplete(result);
633
666
  return;
634
667
  }
635
668
  const code = result.error?.code || "CHECKOUT_FAILED";
636
669
  const message = result.error?.message || "Payment failed.";
637
670
  setErrorMessage(message);
638
- onErrorRef.current?.({ code, message });
671
+ fireError({ code, message });
639
672
  } finally {
640
673
  if (isMountedRef.current) {
641
674
  activeCheckoutRef.current = null;
642
675
  setIsSubmitting(false);
643
676
  }
644
677
  }
645
- }, [
646
- resolvedCartId,
647
- client,
648
- enrollInLink,
649
- emitStatus,
650
- isDemoCheckout,
651
- isInitializing,
652
- isSubmitting,
653
- locationId,
654
- orderType
655
- ]);
656
- handleSubmitRef.current = handleSubmit;
678
+ });
679
+ React2.useEffect(() => {
680
+ if (isDemoCheckout || !resolvedBusinessId) {
681
+ elementsRef.current = null;
682
+ return;
683
+ }
684
+ const elements = client.elements(resolvedBusinessId, {
685
+ appearance: initialAppearanceRef.current,
686
+ linkUrl
687
+ });
688
+ elementsRef.current = elements;
689
+ const checkout = elements.create("checkout", {
690
+ orderTypes: resolvedOrderTypes,
691
+ defaultOrderType: resolvedOrderTypes[0]
692
+ });
693
+ if (checkoutMountRef.current) {
694
+ checkout.mount(checkoutMountRef.current);
695
+ }
696
+ checkout.on("ready", () => {
697
+ if (resolvedCart) {
698
+ checkout.setCart(transformToCheckoutCart(resolvedCart));
699
+ }
700
+ });
701
+ checkout.on("order_type_changed", (data) => {
702
+ const typed = data;
703
+ if (typed.orderType) {
704
+ setOrderType(typed.orderType);
705
+ }
706
+ });
707
+ checkout.on("request_submit", () => {
708
+ void handleSubmit();
709
+ });
710
+ return () => {
711
+ activeCheckoutRef.current?.abort();
712
+ activeCheckoutRef.current = null;
713
+ elements.destroy();
714
+ elementsRef.current = null;
715
+ };
716
+ }, [client, resolvedBusinessId, isDemoCheckout]);
717
+ React2.useEffect(() => {
718
+ if (!resolvedCart || !elementsRef.current) return;
719
+ const checkoutElement = elementsRef.current.getElement("checkout");
720
+ if (checkoutElement) {
721
+ checkoutElement.setCart(transformToCheckoutCart(resolvedCart));
722
+ }
723
+ }, [resolvedCart]);
657
724
  const colors = shellColors(isDark ?? false, primaryColor);
658
725
  if (isInitializing) {
659
726
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { fontSize: 13, color: colors.textSecondary }, children: "Preparing checkout..." }) });
@@ -1285,6 +1352,13 @@ var CartOperations = class {
1285
1352
  }
1286
1353
  };
1287
1354
 
1355
+ // src/constants.ts
1356
+ var MOBILE_MONEY_PROVIDER = {
1357
+ MTN: "mtn",
1358
+ VODAFONE: "vodafone",
1359
+ AIRTEL: "airtel"
1360
+ };
1361
+
1288
1362
  // src/utils/price.ts
1289
1363
  function parsePrice(value) {
1290
1364
  if (value === void 0 || value === null) {
@@ -1523,6 +1597,10 @@ async function openCardPopup(provider, checkoutResult, email, currency, signal)
1523
1597
  }
1524
1598
  return { success: false, error: "PROVIDER_UNAVAILABLE" };
1525
1599
  }
1600
+ var VALID_MOBILE_MONEY_PROVIDERS = new Set(Object.values(MOBILE_MONEY_PROVIDER));
1601
+ function isValidMobileMoneyProvider(value) {
1602
+ return VALID_MOBILE_MONEY_PROVIDERS.has(value);
1603
+ }
1526
1604
  function normalizeAuthorizationType(value) {
1527
1605
  return value === "otp" || value === "pin" ? value : void 0;
1528
1606
  }
@@ -1755,6 +1833,16 @@ var CheckoutResolver = class {
1755
1833
  }
1756
1834
  await this.wait(this.pollIntervalMs);
1757
1835
  }
1836
+ try {
1837
+ const finalResult = await this.client.checkout.pollPaymentStatus(input.orderId);
1838
+ if (finalResult.ok) {
1839
+ const normalized = normalizeStatusResponse(finalResult.value);
1840
+ if (normalized.paid || isPaymentStatusSuccess(normalized.status)) {
1841
+ return this.finalizeSuccess(latestCheckoutResult);
1842
+ }
1843
+ }
1844
+ } catch {
1845
+ }
1758
1846
  return this.fail(
1759
1847
  "PAYMENT_TIMEOUT",
1760
1848
  "Payment confirmation timed out. Please retry checkout.",
@@ -1885,7 +1973,7 @@ var CheckoutResolver = class {
1885
1973
  };
1886
1974
  }
1887
1975
  getEnrollmentMobileMoney() {
1888
- if (this.paymentData?.type === "mobile_money" && this.paymentData.phone_number && this.paymentData.provider) {
1976
+ if (this.paymentData?.type === "mobile_money" && this.paymentData.phone_number && this.paymentData.provider && isValidMobileMoneyProvider(this.paymentData.provider)) {
1889
1977
  return {
1890
1978
  phone_number: this.paymentData.phone_number,
1891
1979
  provider: this.paymentData.provider,
@@ -2959,8 +3047,10 @@ var CimplifyElements = class {
2959
3047
  false
2960
3048
  );
2961
3049
  }
3050
+ this.checkoutInProgress = true;
2962
3051
  if (!options.cart_id) {
2963
3052
  console.debug("[cimplify:checkout] BLOCKED: no cart_id");
3053
+ this.checkoutInProgress = false;
2964
3054
  return toCheckoutError(
2965
3055
  "INVALID_CART",
2966
3056
  "A valid cart is required before checkout can start.",
@@ -2969,6 +3059,7 @@ var CimplifyElements = class {
2969
3059
  }
2970
3060
  if (!options.order_type) {
2971
3061
  console.debug("[cimplify:checkout] BLOCKED: no order_type");
3062
+ this.checkoutInProgress = false;
2972
3063
  return toCheckoutError(
2973
3064
  "ORDER_TYPE_REQUIRED",
2974
3065
  "Order type is required before checkout can start.",
@@ -2978,6 +3069,7 @@ var CimplifyElements = class {
2978
3069
  const checkoutElement = this.elements.get(ELEMENT_TYPES.CHECKOUT) || this.elements.get(ELEMENT_TYPES.PAYMENT);
2979
3070
  if (!checkoutElement) {
2980
3071
  console.debug("[cimplify:checkout] BLOCKED: no checkout element");
3072
+ this.checkoutInProgress = false;
2981
3073
  return toCheckoutError(
2982
3074
  "NO_PAYMENT_ELEMENT",
2983
3075
  "Checkout element must be mounted before checkout.",
@@ -2986,6 +3078,7 @@ var CimplifyElements = class {
2986
3078
  }
2987
3079
  if (!checkoutElement.isMounted()) {
2988
3080
  console.debug("[cimplify:checkout] BLOCKED: checkout element not mounted");
3081
+ this.checkoutInProgress = false;
2989
3082
  return toCheckoutError(
2990
3083
  "PAYMENT_NOT_MOUNTED",
2991
3084
  "Checkout element must be mounted before checkout.",
@@ -2997,6 +3090,7 @@ var CimplifyElements = class {
2997
3090
  const authElement = this.elements.get(ELEMENT_TYPES.AUTH);
2998
3091
  if (authElement && !this.accessToken) {
2999
3092
  console.debug("[cimplify:checkout] BLOCKED: auth incomplete");
3093
+ this.checkoutInProgress = false;
3000
3094
  return toCheckoutError(
3001
3095
  "AUTH_INCOMPLETE",
3002
3096
  "Authentication must complete before checkout can start.",
@@ -3034,7 +3128,6 @@ var CimplifyElements = class {
3034
3128
  };
3035
3129
  const timeoutMs = options.timeout_ms ?? 18e4;
3036
3130
  const paymentWindow = checkoutElement.getContentWindow();
3037
- this.checkoutInProgress = true;
3038
3131
  return new Promise((resolve) => {
3039
3132
  let settled = false;
3040
3133
  const cleanup = () => {
@@ -3329,6 +3422,9 @@ var CimplifyElement = class {
3329
3422
  this.sendMessage({ type: MESSAGE_TYPES.GET_DATA });
3330
3423
  });
3331
3424
  }
3425
+ setCart(cart) {
3426
+ this.sendMessage({ type: MESSAGE_TYPES.SET_CART, cart });
3427
+ }
3332
3428
  sendMessage(message) {
3333
3429
  if (this.iframe?.contentWindow) {
3334
3430
  this.iframe.contentWindow.postMessage(message, this.linkUrl);
@@ -3477,6 +3573,7 @@ var ACCESS_TOKEN_STORAGE_KEY = "cimplify_access_token";
3477
3573
  var SESSION_TOKEN_STORAGE_KEY = "cimplify_session_token";
3478
3574
  var ORDER_TOKEN_PREFIX = "cimplify_ot_";
3479
3575
  var SESSION_TOKEN_HEADER = "x-session-token";
3576
+ var ORDER_TOKEN_TTL_MS = 24 * 60 * 60 * 1e3;
3480
3577
  var DEFAULT_TIMEOUT_MS = 3e4;
3481
3578
  var DEFAULT_MAX_RETRIES = 3;
3482
3579
  var DEFAULT_RETRY_DELAY_MS = 1e3;
@@ -3626,12 +3723,27 @@ var CimplifyClient = class {
3626
3723
  }
3627
3724
  setOrderToken(orderId, token) {
3628
3725
  if (typeof window !== "undefined" && window.localStorage) {
3629
- localStorage.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, token);
3726
+ try {
3727
+ const entry = JSON.stringify({ token, storedAt: Date.now() });
3728
+ localStorage.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, entry);
3729
+ } catch {
3730
+ }
3630
3731
  }
3631
3732
  }
3632
3733
  getOrderToken(orderId) {
3633
3734
  if (typeof window !== "undefined" && window.localStorage) {
3634
- return localStorage.getItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
3735
+ try {
3736
+ const raw = localStorage.getItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
3737
+ if (!raw) return null;
3738
+ const entry = JSON.parse(raw);
3739
+ if (Date.now() - entry.storedAt > ORDER_TOKEN_TTL_MS) {
3740
+ localStorage.removeItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
3741
+ return null;
3742
+ }
3743
+ return entry.token;
3744
+ } catch {
3745
+ return null;
3746
+ }
3635
3747
  }
3636
3748
  return null;
3637
3749
  }
@@ -3707,10 +3819,13 @@ var CimplifyClient = class {
3707
3819
  }
3708
3820
  saveAccessToken(token) {
3709
3821
  if (typeof window !== "undefined" && window.localStorage) {
3710
- if (token) {
3711
- localStorage.setItem(ACCESS_TOKEN_STORAGE_KEY, token);
3712
- } else {
3713
- localStorage.removeItem(ACCESS_TOKEN_STORAGE_KEY);
3822
+ try {
3823
+ if (token) {
3824
+ localStorage.setItem(ACCESS_TOKEN_STORAGE_KEY, token);
3825
+ } else {
3826
+ localStorage.removeItem(ACCESS_TOKEN_STORAGE_KEY);
3827
+ }
3828
+ } catch {
3714
3829
  }
3715
3830
  }
3716
3831
  }
@@ -3783,6 +3898,19 @@ var CimplifyClient = class {
3783
3898
  });
3784
3899
  return response;
3785
3900
  }
3901
+ if (response.status === 429 && attempt < this.maxRetries) {
3902
+ retryCount++;
3903
+ const retryAfter = response.headers.get("Retry-After");
3904
+ const delay = retryAfter ? Math.min(parseInt(retryAfter, 10) * 1e3, 3e4) || this.retryDelay * Math.pow(2, attempt) : this.retryDelay * Math.pow(2, attempt);
3905
+ this.hooks.onRetry?.({
3906
+ ...context,
3907
+ attempt: retryCount,
3908
+ delayMs: delay,
3909
+ error: new Error(`Rate limited: ${response.status}`)
3910
+ });
3911
+ await sleep(delay);
3912
+ continue;
3913
+ }
3786
3914
  if (response.status >= 400 && response.status < 500) {
3787
3915
  this.hooks.onRequestError?.({
3788
3916
  ...context,
@@ -4106,23 +4234,23 @@ function resolveInitialLocation(locations) {
4106
4234
  }
4107
4235
  return locations[0];
4108
4236
  }
4109
- var CimplifyContext = react.createContext(null);
4237
+ var CimplifyContext = React2.createContext(null);
4110
4238
  function CimplifyProvider({
4111
4239
  client,
4112
4240
  children,
4113
4241
  onLocationChange
4114
4242
  }) {
4115
- const resolvedClient = react.useMemo(() => client ?? createDefaultClient(), [client]);
4116
- const onLocationChangeRef = react.useRef(onLocationChange);
4117
- const [business, setBusiness] = react.useState(null);
4118
- const [locations, setLocations] = react.useState([]);
4119
- const [currentLocation, setCurrentLocationState] = react.useState(null);
4120
- const [isReady, setIsReady] = react.useState(false);
4121
- react.useEffect(() => {
4243
+ const resolvedClient = React2.useMemo(() => client ?? createDefaultClient(), [client]);
4244
+ const onLocationChangeRef = React2.useRef(onLocationChange);
4245
+ const [business, setBusiness] = React2.useState(null);
4246
+ const [locations, setLocations] = React2.useState([]);
4247
+ const [currentLocation, setCurrentLocationState] = React2.useState(null);
4248
+ const [isReady, setIsReady] = React2.useState(false);
4249
+ React2.useEffect(() => {
4122
4250
  onLocationChangeRef.current = onLocationChange;
4123
4251
  }, [onLocationChange]);
4124
4252
  const isDemoMode = resolvedClient.getPublicKey().trim().length === 0;
4125
- const setCurrentLocation = react.useCallback(
4253
+ const setCurrentLocation = React2.useCallback(
4126
4254
  (location) => {
4127
4255
  setCurrentLocationState(location);
4128
4256
  resolvedClient.setLocationId(location.id);
@@ -4131,7 +4259,7 @@ function CimplifyProvider({
4131
4259
  },
4132
4260
  [resolvedClient]
4133
4261
  );
4134
- react.useEffect(() => {
4262
+ React2.useEffect(() => {
4135
4263
  let cancelled = false;
4136
4264
  async function bootstrap() {
4137
4265
  setIsReady(false);
@@ -4187,7 +4315,7 @@ function CimplifyProvider({
4187
4315
  cancelled = true;
4188
4316
  };
4189
4317
  }, [resolvedClient, isDemoMode]);
4190
- const contextValue = react.useMemo(
4318
+ const contextValue = React2.useMemo(
4191
4319
  () => ({
4192
4320
  client: resolvedClient,
4193
4321
  business,
@@ -4212,14 +4340,14 @@ function CimplifyProvider({
4212
4340
  return /* @__PURE__ */ jsxRuntime.jsx(CimplifyContext.Provider, { value: contextValue, children });
4213
4341
  }
4214
4342
  function useCimplify() {
4215
- const context = react.useContext(CimplifyContext);
4343
+ const context = React2.useContext(CimplifyContext);
4216
4344
  if (!context) {
4217
4345
  throw new Error("useCimplify must be used within CimplifyProvider");
4218
4346
  }
4219
4347
  return context;
4220
4348
  }
4221
4349
  function useOptionalCimplify() {
4222
- return react.useContext(CimplifyContext);
4350
+ return React2.useContext(CimplifyContext);
4223
4351
  }
4224
4352
  var productsCache = /* @__PURE__ */ new Map();
4225
4353
  var productsInflight = /* @__PURE__ */ new Map();
@@ -4238,9 +4366,9 @@ function useProducts(options = {}) {
4238
4366
  }
4239
4367
  const enabled = options.enabled ?? true;
4240
4368
  const locationId = client.getLocationId();
4241
- const previousLocationIdRef = react.useRef(locationId);
4242
- const requestIdRef = react.useRef(0);
4243
- const queryOptions = react.useMemo(
4369
+ const previousLocationIdRef = React2.useRef(locationId);
4370
+ const requestIdRef = React2.useRef(0);
4371
+ const queryOptions = React2.useMemo(
4244
4372
  () => ({
4245
4373
  category: options.category,
4246
4374
  collection: options.collection,
@@ -4250,25 +4378,25 @@ function useProducts(options = {}) {
4250
4378
  }),
4251
4379
  [options.category, options.collection, options.featured, options.limit, options.search]
4252
4380
  );
4253
- const cacheKey = react.useMemo(
4381
+ const cacheKey = React2.useMemo(
4254
4382
  () => buildProductsCacheKey(client, locationId, queryOptions),
4255
4383
  [client, locationId, queryOptions]
4256
4384
  );
4257
4385
  const cached = productsCache.get(cacheKey);
4258
- const [products, setProducts] = react.useState(cached?.products ?? []);
4259
- const [isComplete, setIsComplete] = react.useState(cached?.is_complete ?? true);
4260
- const [totalAvailable, setTotalAvailable] = react.useState(cached?.total_available);
4261
- const [pagination, setPagination] = react.useState(cached?.pagination);
4262
- const [isLoading, setIsLoading] = react.useState(enabled && !cached);
4263
- const [error, setError] = react.useState(null);
4264
- react.useEffect(() => {
4386
+ const [products, setProducts] = React2.useState(cached?.products ?? []);
4387
+ const [isComplete, setIsComplete] = React2.useState(cached?.is_complete ?? true);
4388
+ const [totalAvailable, setTotalAvailable] = React2.useState(cached?.total_available);
4389
+ const [pagination, setPagination] = React2.useState(cached?.pagination);
4390
+ const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
4391
+ const [error, setError] = React2.useState(null);
4392
+ React2.useEffect(() => {
4265
4393
  if (previousLocationIdRef.current !== locationId) {
4266
4394
  productsCache.clear();
4267
4395
  productsInflight.clear();
4268
4396
  previousLocationIdRef.current = locationId;
4269
4397
  }
4270
4398
  }, [locationId]);
4271
- const load = react.useCallback(
4399
+ const load = React2.useCallback(
4272
4400
  async (force = false) => {
4273
4401
  if (!enabled) {
4274
4402
  setIsLoading(false);
@@ -4331,10 +4459,10 @@ function useProducts(options = {}) {
4331
4459
  },
4332
4460
  [cacheKey, client, enabled, queryOptions]
4333
4461
  );
4334
- react.useEffect(() => {
4462
+ React2.useEffect(() => {
4335
4463
  void load(false);
4336
4464
  }, [load]);
4337
- const refetch = react.useCallback(async () => {
4465
+ const refetch = React2.useCallback(async () => {
4338
4466
  productsCache.delete(cacheKey);
4339
4467
  await load(true);
4340
4468
  }, [cacheKey, load]);
@@ -4368,27 +4496,27 @@ function useProduct(slugOrId, options = {}) {
4368
4496
  }
4369
4497
  const enabled = options.enabled ?? true;
4370
4498
  const locationId = client.getLocationId();
4371
- const previousLocationIdRef = react.useRef(locationId);
4372
- const requestIdRef = react.useRef(0);
4373
- const normalizedSlugOrId = react.useMemo(() => (slugOrId || "").trim(), [slugOrId]);
4374
- const cacheKey = react.useMemo(
4499
+ const previousLocationIdRef = React2.useRef(locationId);
4500
+ const requestIdRef = React2.useRef(0);
4501
+ const normalizedSlugOrId = React2.useMemo(() => (slugOrId || "").trim(), [slugOrId]);
4502
+ const cacheKey = React2.useMemo(
4375
4503
  () => buildProductCacheKey(client, locationId, normalizedSlugOrId),
4376
4504
  [client, locationId, normalizedSlugOrId]
4377
4505
  );
4378
4506
  const cached = productCache.get(cacheKey);
4379
- const [product, setProduct] = react.useState(cached?.product ?? null);
4380
- const [isLoading, setIsLoading] = react.useState(
4507
+ const [product, setProduct] = React2.useState(cached?.product ?? null);
4508
+ const [isLoading, setIsLoading] = React2.useState(
4381
4509
  enabled && normalizedSlugOrId.length > 0 && !cached
4382
4510
  );
4383
- const [error, setError] = react.useState(null);
4384
- react.useEffect(() => {
4511
+ const [error, setError] = React2.useState(null);
4512
+ React2.useEffect(() => {
4385
4513
  if (previousLocationIdRef.current !== locationId) {
4386
4514
  productCache.clear();
4387
4515
  productInflight.clear();
4388
4516
  previousLocationIdRef.current = locationId;
4389
4517
  }
4390
4518
  }, [locationId]);
4391
- const load = react.useCallback(
4519
+ const load = React2.useCallback(
4392
4520
  async (force = false) => {
4393
4521
  if (!enabled || normalizedSlugOrId.length === 0) {
4394
4522
  setProduct(null);
@@ -4441,10 +4569,10 @@ function useProduct(slugOrId, options = {}) {
4441
4569
  },
4442
4570
  [cacheKey, client, enabled, normalizedSlugOrId]
4443
4571
  );
4444
- react.useEffect(() => {
4572
+ React2.useEffect(() => {
4445
4573
  void load(false);
4446
4574
  }, [load]);
4447
- const refetch = react.useCallback(async () => {
4575
+ const refetch = React2.useCallback(async () => {
4448
4576
  productCache.delete(cacheKey);
4449
4577
  await load(true);
4450
4578
  }, [cacheKey, load]);
@@ -4462,12 +4590,12 @@ function useCategories(options = {}) {
4462
4590
  throw new Error("useCategories must be used within CimplifyProvider or passed { client }.");
4463
4591
  }
4464
4592
  const enabled = options.enabled ?? true;
4465
- const cacheKey = react.useMemo(() => buildCategoriesCacheKey(client), [client]);
4593
+ const cacheKey = React2.useMemo(() => buildCategoriesCacheKey(client), [client]);
4466
4594
  const cached = categoriesCache.get(cacheKey);
4467
- const [categories, setCategories] = react.useState(cached ?? []);
4468
- const [isLoading, setIsLoading] = react.useState(enabled && !cached);
4469
- const [error, setError] = react.useState(null);
4470
- const load = react.useCallback(
4595
+ const [categories, setCategories] = React2.useState(cached ?? []);
4596
+ const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
4597
+ const [error, setError] = React2.useState(null);
4598
+ const load = React2.useCallback(
4471
4599
  async (force = false) => {
4472
4600
  if (!enabled) {
4473
4601
  setIsLoading(false);
@@ -4511,10 +4639,10 @@ function useCategories(options = {}) {
4511
4639
  },
4512
4640
  [cacheKey, client, enabled]
4513
4641
  );
4514
- react.useEffect(() => {
4642
+ React2.useEffect(() => {
4515
4643
  void load(false);
4516
4644
  }, [load]);
4517
- const refetch = react.useCallback(async () => {
4645
+ const refetch = React2.useCallback(async () => {
4518
4646
  categoriesCache.delete(cacheKey);
4519
4647
  await load(true);
4520
4648
  }, [cacheKey, load]);
@@ -5035,7 +5163,7 @@ function useCart(options = {}) {
5035
5163
  const locationId = options.locationId ?? client.getLocationId();
5036
5164
  const isDemoMode = options.demoMode ?? context?.isDemoMode ?? client.getPublicKey().trim().length === 0;
5037
5165
  const currency = options.currency ?? context?.currency ?? "USD";
5038
- const store = react.useMemo(
5166
+ const store = React2.useMemo(
5039
5167
  () => getOrCreateStore({
5040
5168
  client,
5041
5169
  locationId,
@@ -5044,43 +5172,43 @@ function useCart(options = {}) {
5044
5172
  }),
5045
5173
  [client, currency, isDemoMode, locationId]
5046
5174
  );
5047
- const snapshot = react.useSyncExternalStore(
5175
+ const snapshot = React2.useSyncExternalStore(
5048
5176
  store.subscribe,
5049
5177
  store.getSnapshot,
5050
5178
  store.getSnapshot
5051
5179
  );
5052
- react.useEffect(() => {
5180
+ React2.useEffect(() => {
5053
5181
  void store.initialize();
5054
5182
  }, [store]);
5055
- const addItem = react.useCallback(
5183
+ const addItem = React2.useCallback(
5056
5184
  async (product, quantity, addOptions) => {
5057
5185
  await store.addItem(product, quantity, addOptions);
5058
5186
  },
5059
5187
  [store]
5060
5188
  );
5061
- const removeItem = react.useCallback(
5189
+ const removeItem = React2.useCallback(
5062
5190
  async (itemId) => {
5063
5191
  await store.removeItem(itemId);
5064
5192
  },
5065
5193
  [store]
5066
5194
  );
5067
- const updateQuantity = react.useCallback(
5195
+ const updateQuantity = React2.useCallback(
5068
5196
  async (itemId, quantity) => {
5069
5197
  await store.updateQuantity(itemId, quantity);
5070
5198
  },
5071
5199
  [store]
5072
5200
  );
5073
- const clearCart = react.useCallback(async () => {
5201
+ const clearCart = React2.useCallback(async () => {
5074
5202
  await store.clearCart();
5075
5203
  }, [store]);
5076
- const sync = react.useCallback(async () => {
5204
+ const sync = React2.useCallback(async () => {
5077
5205
  try {
5078
5206
  await store.sync();
5079
5207
  } catch (syncError) {
5080
5208
  throw syncError;
5081
5209
  }
5082
5210
  }, [store]);
5083
- const itemCount = react.useMemo(
5211
+ const itemCount = React2.useMemo(
5084
5212
  () => snapshot.items.reduce((sum, item) => sum + item.quantity, 0),
5085
5213
  [snapshot.items]
5086
5214
  );
@@ -5111,22 +5239,22 @@ function useOrder(orderId, options = {}) {
5111
5239
  if (!client) {
5112
5240
  throw new Error("useOrder must be used within CimplifyProvider or passed { client }.");
5113
5241
  }
5114
- const normalizedOrderId = react.useMemo(() => (orderId || "").trim(), [orderId]);
5242
+ const normalizedOrderId = React2.useMemo(() => (orderId || "").trim(), [orderId]);
5115
5243
  const enabled = options.enabled ?? true;
5116
5244
  const poll = options.poll ?? false;
5117
5245
  const pollInterval = options.pollInterval ?? 5e3;
5118
- const requestIdRef = react.useRef(0);
5119
- const cacheKey = react.useMemo(
5246
+ const requestIdRef = React2.useRef(0);
5247
+ const cacheKey = React2.useMemo(
5120
5248
  () => buildOrderCacheKey(client, normalizedOrderId),
5121
5249
  [client, normalizedOrderId]
5122
5250
  );
5123
5251
  const cached = orderCache.get(cacheKey);
5124
- const [order, setOrder] = react.useState(cached?.order ?? null);
5125
- const [isLoading, setIsLoading] = react.useState(
5252
+ const [order, setOrder] = React2.useState(cached?.order ?? null);
5253
+ const [isLoading, setIsLoading] = React2.useState(
5126
5254
  enabled && normalizedOrderId.length > 0 && !cached
5127
5255
  );
5128
- const [error, setError] = react.useState(null);
5129
- const load = react.useCallback(
5256
+ const [error, setError] = React2.useState(null);
5257
+ const load = React2.useCallback(
5130
5258
  async (force = false) => {
5131
5259
  if (!enabled || normalizedOrderId.length === 0) {
5132
5260
  setOrder(null);
@@ -5179,10 +5307,10 @@ function useOrder(orderId, options = {}) {
5179
5307
  },
5180
5308
  [cacheKey, client, enabled, normalizedOrderId]
5181
5309
  );
5182
- react.useEffect(() => {
5310
+ React2.useEffect(() => {
5183
5311
  void load(false);
5184
5312
  }, [load]);
5185
- react.useEffect(() => {
5313
+ React2.useEffect(() => {
5186
5314
  if (!poll || !enabled || normalizedOrderId.length === 0) {
5187
5315
  return;
5188
5316
  }
@@ -5193,7 +5321,7 @@ function useOrder(orderId, options = {}) {
5193
5321
  window.clearInterval(timer);
5194
5322
  };
5195
5323
  }, [enabled, load, normalizedOrderId.length, poll, pollInterval]);
5196
- const refetch = react.useCallback(async () => {
5324
+ const refetch = React2.useCallback(async () => {
5197
5325
  orderCache.delete(cacheKey);
5198
5326
  await load(true);
5199
5327
  }, [cacheKey, load]);
@@ -5244,10 +5372,10 @@ function useLocations(options = {}) {
5244
5372
  };
5245
5373
  }
5246
5374
  const client = options.client;
5247
- const [locations, setLocations] = react.useState([]);
5248
- const [currentLocation, setCurrentLocationState] = react.useState(null);
5249
- const [isLoading, setIsLoading] = react.useState(true);
5250
- const setCurrentLocation = react.useCallback(
5375
+ const [locations, setLocations] = React2.useState([]);
5376
+ const [currentLocation, setCurrentLocationState] = React2.useState(null);
5377
+ const [isLoading, setIsLoading] = React2.useState(true);
5378
+ const setCurrentLocation = React2.useCallback(
5251
5379
  (location) => {
5252
5380
  setCurrentLocationState(location);
5253
5381
  if (client) {
@@ -5257,7 +5385,7 @@ function useLocations(options = {}) {
5257
5385
  },
5258
5386
  [client]
5259
5387
  );
5260
- react.useEffect(() => {
5388
+ React2.useEffect(() => {
5261
5389
  if (!client) {
5262
5390
  setLocations([]);
5263
5391
  setCurrentLocationState(null);
@@ -5315,24 +5443,24 @@ function useCollections(options = {}) {
5315
5443
  }
5316
5444
  const enabled = options.enabled ?? true;
5317
5445
  const locationId = client.getLocationId();
5318
- const previousLocationIdRef = react.useRef(locationId);
5319
- const requestIdRef = react.useRef(0);
5320
- const cacheKey = react.useMemo(
5446
+ const previousLocationIdRef = React2.useRef(locationId);
5447
+ const requestIdRef = React2.useRef(0);
5448
+ const cacheKey = React2.useMemo(
5321
5449
  () => buildCollectionsCacheKey(client, locationId),
5322
5450
  [client, locationId]
5323
5451
  );
5324
5452
  const cached = collectionsCache.get(cacheKey);
5325
- const [collections, setCollections] = react.useState(cached?.collections ?? []);
5326
- const [isLoading, setIsLoading] = react.useState(enabled && !cached);
5327
- const [error, setError] = react.useState(null);
5328
- react.useEffect(() => {
5453
+ const [collections, setCollections] = React2.useState(cached?.collections ?? []);
5454
+ const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
5455
+ const [error, setError] = React2.useState(null);
5456
+ React2.useEffect(() => {
5329
5457
  if (previousLocationIdRef.current !== locationId) {
5330
5458
  collectionsCache.clear();
5331
5459
  collectionsInflight.clear();
5332
5460
  previousLocationIdRef.current = locationId;
5333
5461
  }
5334
5462
  }, [locationId]);
5335
- const load = react.useCallback(
5463
+ const load = React2.useCallback(
5336
5464
  async (force = false) => {
5337
5465
  if (!enabled) {
5338
5466
  setIsLoading(false);
@@ -5382,10 +5510,10 @@ function useCollections(options = {}) {
5382
5510
  },
5383
5511
  [cacheKey, client, enabled]
5384
5512
  );
5385
- react.useEffect(() => {
5513
+ React2.useEffect(() => {
5386
5514
  void load(false);
5387
5515
  }, [load]);
5388
- const refetch = react.useCallback(async () => {
5516
+ const refetch = React2.useCallback(async () => {
5389
5517
  collectionsCache.delete(cacheKey);
5390
5518
  await load(true);
5391
5519
  }, [cacheKey, load]);
@@ -5411,28 +5539,28 @@ function useCollection(idOrSlug, options = {}) {
5411
5539
  }
5412
5540
  const enabled = options.enabled ?? true;
5413
5541
  const locationId = client.getLocationId();
5414
- const previousLocationIdRef = react.useRef(locationId);
5415
- const requestIdRef = react.useRef(0);
5416
- const normalizedIdOrSlug = react.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5417
- const cacheKey = react.useMemo(
5542
+ const previousLocationIdRef = React2.useRef(locationId);
5543
+ const requestIdRef = React2.useRef(0);
5544
+ const normalizedIdOrSlug = React2.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5545
+ const cacheKey = React2.useMemo(
5418
5546
  () => buildCollectionCacheKey(client, locationId, normalizedIdOrSlug),
5419
5547
  [client, locationId, normalizedIdOrSlug]
5420
5548
  );
5421
5549
  const cached = collectionCache.get(cacheKey);
5422
- const [collection, setCollection] = react.useState(cached?.collection ?? null);
5423
- const [products, setProducts] = react.useState(cached?.products ?? []);
5424
- const [isLoading, setIsLoading] = react.useState(
5550
+ const [collection, setCollection] = React2.useState(cached?.collection ?? null);
5551
+ const [products, setProducts] = React2.useState(cached?.products ?? []);
5552
+ const [isLoading, setIsLoading] = React2.useState(
5425
5553
  enabled && normalizedIdOrSlug.length > 0 && !cached
5426
5554
  );
5427
- const [error, setError] = react.useState(null);
5428
- react.useEffect(() => {
5555
+ const [error, setError] = React2.useState(null);
5556
+ React2.useEffect(() => {
5429
5557
  if (previousLocationIdRef.current !== locationId) {
5430
5558
  collectionCache.clear();
5431
5559
  collectionInflight.clear();
5432
5560
  previousLocationIdRef.current = locationId;
5433
5561
  }
5434
5562
  }, [locationId]);
5435
- const load = react.useCallback(
5563
+ const load = React2.useCallback(
5436
5564
  async (force = false) => {
5437
5565
  if (!enabled || normalizedIdOrSlug.length === 0) {
5438
5566
  setCollection(null);
@@ -5495,10 +5623,10 @@ function useCollection(idOrSlug, options = {}) {
5495
5623
  },
5496
5624
  [cacheKey, client, enabled, normalizedIdOrSlug]
5497
5625
  );
5498
- react.useEffect(() => {
5626
+ React2.useEffect(() => {
5499
5627
  void load(false);
5500
5628
  }, [load]);
5501
- const refetch = react.useCallback(async () => {
5629
+ const refetch = React2.useCallback(async () => {
5502
5630
  collectionCache.delete(cacheKey);
5503
5631
  await load(true);
5504
5632
  }, [cacheKey, load]);
@@ -5524,27 +5652,27 @@ function useBundle(idOrSlug, options = {}) {
5524
5652
  }
5525
5653
  const enabled = options.enabled ?? true;
5526
5654
  const locationId = client.getLocationId();
5527
- const previousLocationIdRef = react.useRef(locationId);
5528
- const requestIdRef = react.useRef(0);
5529
- const normalizedIdOrSlug = react.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5530
- const cacheKey = react.useMemo(
5655
+ const previousLocationIdRef = React2.useRef(locationId);
5656
+ const requestIdRef = React2.useRef(0);
5657
+ const normalizedIdOrSlug = React2.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5658
+ const cacheKey = React2.useMemo(
5531
5659
  () => buildBundleCacheKey(client, locationId, normalizedIdOrSlug),
5532
5660
  [client, locationId, normalizedIdOrSlug]
5533
5661
  );
5534
5662
  const cached = bundleCache.get(cacheKey);
5535
- const [bundle, setBundle] = react.useState(cached?.bundle ?? null);
5536
- const [isLoading, setIsLoading] = react.useState(
5663
+ const [bundle, setBundle] = React2.useState(cached?.bundle ?? null);
5664
+ const [isLoading, setIsLoading] = React2.useState(
5537
5665
  enabled && normalizedIdOrSlug.length > 0 && !cached
5538
5666
  );
5539
- const [error, setError] = react.useState(null);
5540
- react.useEffect(() => {
5667
+ const [error, setError] = React2.useState(null);
5668
+ React2.useEffect(() => {
5541
5669
  if (previousLocationIdRef.current !== locationId) {
5542
5670
  bundleCache.clear();
5543
5671
  bundleInflight.clear();
5544
5672
  previousLocationIdRef.current = locationId;
5545
5673
  }
5546
5674
  }, [locationId]);
5547
- const load = react.useCallback(
5675
+ const load = React2.useCallback(
5548
5676
  async (force = false) => {
5549
5677
  if (!enabled || normalizedIdOrSlug.length === 0) {
5550
5678
  setBundle(null);
@@ -5595,10 +5723,10 @@ function useBundle(idOrSlug, options = {}) {
5595
5723
  },
5596
5724
  [cacheKey, client, enabled, normalizedIdOrSlug]
5597
5725
  );
5598
- react.useEffect(() => {
5726
+ React2.useEffect(() => {
5599
5727
  void load(false);
5600
5728
  }, [load]);
5601
- const refetch = react.useCallback(async () => {
5729
+ const refetch = React2.useCallback(async () => {
5602
5730
  bundleCache.delete(cacheKey);
5603
5731
  await load(true);
5604
5732
  }, [cacheKey, load]);
@@ -5628,37 +5756,37 @@ function useComposite(idOrProductId, options = {}) {
5628
5756
  }
5629
5757
  const enabled = options.enabled ?? true;
5630
5758
  const locationId = client.getLocationId();
5631
- const previousLocationIdRef = react.useRef(locationId);
5632
- const requestIdRef = react.useRef(0);
5633
- const priceRequestIdRef = react.useRef(0);
5634
- const normalizedIdOrProductId = react.useMemo(
5759
+ const previousLocationIdRef = React2.useRef(locationId);
5760
+ const requestIdRef = React2.useRef(0);
5761
+ const priceRequestIdRef = React2.useRef(0);
5762
+ const normalizedIdOrProductId = React2.useMemo(
5635
5763
  () => (idOrProductId || "").trim(),
5636
5764
  [idOrProductId]
5637
5765
  );
5638
- const byProductId = react.useMemo(
5766
+ const byProductId = React2.useMemo(
5639
5767
  () => shouldFetchByProductId(normalizedIdOrProductId, options.byProductId),
5640
5768
  [normalizedIdOrProductId, options.byProductId]
5641
5769
  );
5642
- const cacheKey = react.useMemo(
5770
+ const cacheKey = React2.useMemo(
5643
5771
  () => buildCompositeCacheKey(client, locationId, normalizedIdOrProductId, byProductId),
5644
5772
  [byProductId, client, locationId, normalizedIdOrProductId]
5645
5773
  );
5646
5774
  const cached = compositeCache.get(cacheKey);
5647
- const [composite, setComposite] = react.useState(cached?.composite ?? null);
5648
- const [isLoading, setIsLoading] = react.useState(
5775
+ const [composite, setComposite] = React2.useState(cached?.composite ?? null);
5776
+ const [isLoading, setIsLoading] = React2.useState(
5649
5777
  enabled && normalizedIdOrProductId.length > 0 && !cached
5650
5778
  );
5651
- const [error, setError] = react.useState(null);
5652
- const [priceResult, setPriceResult] = react.useState(null);
5653
- const [isPriceLoading, setIsPriceLoading] = react.useState(false);
5654
- react.useEffect(() => {
5779
+ const [error, setError] = React2.useState(null);
5780
+ const [priceResult, setPriceResult] = React2.useState(null);
5781
+ const [isPriceLoading, setIsPriceLoading] = React2.useState(false);
5782
+ React2.useEffect(() => {
5655
5783
  if (previousLocationIdRef.current !== locationId) {
5656
5784
  compositeCache.clear();
5657
5785
  compositeInflight.clear();
5658
5786
  previousLocationIdRef.current = locationId;
5659
5787
  }
5660
5788
  }, [locationId]);
5661
- const load = react.useCallback(
5789
+ const load = React2.useCallback(
5662
5790
  async (force = false) => {
5663
5791
  if (!enabled || normalizedIdOrProductId.length === 0) {
5664
5792
  setComposite(null);
@@ -5711,10 +5839,10 @@ function useComposite(idOrProductId, options = {}) {
5711
5839
  },
5712
5840
  [byProductId, cacheKey, client, enabled, normalizedIdOrProductId]
5713
5841
  );
5714
- react.useEffect(() => {
5842
+ React2.useEffect(() => {
5715
5843
  void load(false);
5716
5844
  }, [load]);
5717
- const calculatePrice = react.useCallback(
5845
+ const calculatePrice = React2.useCallback(
5718
5846
  async (selections, overrideLocationId) => {
5719
5847
  if (!composite) {
5720
5848
  return null;
@@ -5748,7 +5876,7 @@ function useComposite(idOrProductId, options = {}) {
5748
5876
  },
5749
5877
  [client, composite]
5750
5878
  );
5751
- const refetch = react.useCallback(async () => {
5879
+ const refetch = React2.useCallback(async () => {
5752
5880
  compositeCache.delete(cacheKey);
5753
5881
  await load(true);
5754
5882
  }, [cacheKey, load]);
@@ -5763,13 +5891,13 @@ function useSearch(options = {}) {
5763
5891
  const minLength = Math.max(0, options.minLength ?? 2);
5764
5892
  const debounceMs = Math.max(0, options.debounceMs ?? 300);
5765
5893
  const limit = Math.max(1, options.limit ?? 20);
5766
- const [query, setQueryState] = react.useState("");
5767
- const [results, setResults] = react.useState([]);
5768
- const [isLoading, setIsLoading] = react.useState(false);
5769
- const [error, setError] = react.useState(null);
5770
- const requestIdRef = react.useRef(0);
5771
- const timerRef = react.useRef(null);
5772
- react.useEffect(() => {
5894
+ const [query, setQueryState] = React2.useState("");
5895
+ const [results, setResults] = React2.useState([]);
5896
+ const [isLoading, setIsLoading] = React2.useState(false);
5897
+ const [error, setError] = React2.useState(null);
5898
+ const requestIdRef = React2.useRef(0);
5899
+ const timerRef = React2.useRef(null);
5900
+ React2.useEffect(() => {
5773
5901
  if (timerRef.current) {
5774
5902
  clearTimeout(timerRef.current);
5775
5903
  timerRef.current = null;
@@ -5816,10 +5944,10 @@ function useSearch(options = {}) {
5816
5944
  }
5817
5945
  };
5818
5946
  }, [client, debounceMs, limit, minLength, options.category, query]);
5819
- const setQuery = react.useCallback((nextQuery) => {
5947
+ const setQuery = React2.useCallback((nextQuery) => {
5820
5948
  setQueryState(nextQuery);
5821
5949
  }, []);
5822
- const clear = react.useCallback(() => {
5950
+ const clear = React2.useCallback(() => {
5823
5951
  requestIdRef.current += 1;
5824
5952
  if (timerRef.current) {
5825
5953
  clearTimeout(timerRef.current);
@@ -5875,28 +6003,28 @@ function useQuote(input, options = {}) {
5875
6003
  const autoRefresh = options.autoRefresh ?? true;
5876
6004
  const refreshBeforeExpiryMs = Math.max(0, options.refreshBeforeExpiryMs ?? 3e4);
5877
6005
  const locationId = client.getLocationId();
5878
- const requestIdRef = react.useRef(0);
5879
- const refreshTimerRef = react.useRef(null);
5880
- const expiryTimerRef = react.useRef(null);
5881
- const inputSignature = react.useMemo(() => JSON.stringify(input ?? null), [input]);
5882
- const normalizedInput = react.useMemo(() => {
6006
+ const requestIdRef = React2.useRef(0);
6007
+ const refreshTimerRef = React2.useRef(null);
6008
+ const expiryTimerRef = React2.useRef(null);
6009
+ const inputSignature = React2.useMemo(() => JSON.stringify(input ?? null), [input]);
6010
+ const normalizedInput = React2.useMemo(() => {
5883
6011
  if (!input) {
5884
6012
  return null;
5885
6013
  }
5886
6014
  const normalized = normalizeInput(input, locationId);
5887
6015
  return normalized.product_id.length > 0 ? normalized : null;
5888
6016
  }, [inputSignature, locationId]);
5889
- const cacheKey = react.useMemo(
6017
+ const cacheKey = React2.useMemo(
5890
6018
  () => buildQuoteCacheKey(client, locationId, inputSignature),
5891
6019
  [client, inputSignature, locationId]
5892
6020
  );
5893
6021
  const cached = quoteCache.get(cacheKey);
5894
- const [quote, setQuote] = react.useState(cached?.quote ?? null);
5895
- const [isLoading, setIsLoading] = react.useState(enabled && normalizedInput !== null && !cached);
5896
- const [error, setError] = react.useState(null);
5897
- const [isExpired, setIsExpired] = react.useState(isQuoteExpired(cached?.quote ?? null));
5898
- const [messages, setMessages] = react.useState(cached?.quote?.ui_messages ?? []);
5899
- const load = react.useCallback(
6022
+ const [quote, setQuote] = React2.useState(cached?.quote ?? null);
6023
+ const [isLoading, setIsLoading] = React2.useState(enabled && normalizedInput !== null && !cached);
6024
+ const [error, setError] = React2.useState(null);
6025
+ const [isExpired, setIsExpired] = React2.useState(isQuoteExpired(cached?.quote ?? null));
6026
+ const [messages, setMessages] = React2.useState(cached?.quote?.ui_messages ?? []);
6027
+ const load = React2.useCallback(
5900
6028
  async (force = false) => {
5901
6029
  if (!enabled || !normalizedInput) {
5902
6030
  setQuote(null);
@@ -5954,10 +6082,10 @@ function useQuote(input, options = {}) {
5954
6082
  },
5955
6083
  [cacheKey, client, enabled, normalizedInput]
5956
6084
  );
5957
- react.useEffect(() => {
6085
+ React2.useEffect(() => {
5958
6086
  void load(false);
5959
6087
  }, [load]);
5960
- const refresh = react.useCallback(async () => {
6088
+ const refresh = React2.useCallback(async () => {
5961
6089
  if (!enabled || !normalizedInput) {
5962
6090
  return;
5963
6091
  }
@@ -5994,7 +6122,7 @@ function useQuote(input, options = {}) {
5994
6122
  }
5995
6123
  }
5996
6124
  }, [cacheKey, client, enabled, load, normalizedInput, quote]);
5997
- react.useEffect(() => {
6125
+ React2.useEffect(() => {
5998
6126
  if (expiryTimerRef.current) {
5999
6127
  clearTimeout(expiryTimerRef.current);
6000
6128
  expiryTimerRef.current = null;
@@ -6018,7 +6146,7 @@ function useQuote(input, options = {}) {
6018
6146
  }
6019
6147
  };
6020
6148
  }, [quote?.expires_at, quote?.quote_id]);
6021
- react.useEffect(() => {
6149
+ React2.useEffect(() => {
6022
6150
  if (refreshTimerRef.current) {
6023
6151
  clearTimeout(refreshTimerRef.current);
6024
6152
  refreshTimerRef.current = null;
@@ -6043,15 +6171,15 @@ function useQuote(input, options = {}) {
6043
6171
  }, [autoRefresh, enabled, quote?.expires_at, quote?.quote_id, refresh, refreshBeforeExpiryMs]);
6044
6172
  return { quote, isLoading, error, refresh, isExpired, messages };
6045
6173
  }
6046
- var ElementsContext = react.createContext({
6174
+ var ElementsContext = React2.createContext({
6047
6175
  elements: null,
6048
6176
  isReady: false
6049
6177
  });
6050
6178
  function useElements() {
6051
- return react.useContext(ElementsContext).elements;
6179
+ return React2.useContext(ElementsContext).elements;
6052
6180
  }
6053
6181
  function useElementsReady() {
6054
- return react.useContext(ElementsContext).isReady;
6182
+ return React2.useContext(ElementsContext).isReady;
6055
6183
  }
6056
6184
  function ElementsProvider({
6057
6185
  client,
@@ -6059,10 +6187,10 @@ function ElementsProvider({
6059
6187
  options,
6060
6188
  children
6061
6189
  }) {
6062
- const [elements, setElements] = react.useState(null);
6063
- const [isReady, setIsReady] = react.useState(false);
6064
- const initialOptionsRef = react.useRef(options);
6065
- react.useEffect(() => {
6190
+ const [elements, setElements] = React2.useState(null);
6191
+ const [isReady, setIsReady] = React2.useState(false);
6192
+ const initialOptionsRef = React2.useRef(options);
6193
+ React2.useEffect(() => {
6066
6194
  let cancelled = false;
6067
6195
  let instance = null;
6068
6196
  setIsReady(false);
@@ -6103,20 +6231,20 @@ function AuthElement({
6103
6231
  onRequiresOtp,
6104
6232
  onError
6105
6233
  }) {
6106
- const containerRef = react.useRef(null);
6107
- const elementRef = react.useRef(null);
6234
+ const containerRef = React2.useRef(null);
6235
+ const elementRef = React2.useRef(null);
6108
6236
  const elements = useElements();
6109
- const onReadyRef = react.useRef(onReady);
6110
- const onAuthenticatedRef = react.useRef(onAuthenticated);
6111
- const onRequiresOtpRef = react.useRef(onRequiresOtp);
6112
- const onErrorRef = react.useRef(onError);
6113
- react.useEffect(() => {
6237
+ const onReadyRef = React2.useRef(onReady);
6238
+ const onAuthenticatedRef = React2.useRef(onAuthenticated);
6239
+ const onRequiresOtpRef = React2.useRef(onRequiresOtp);
6240
+ const onErrorRef = React2.useRef(onError);
6241
+ React2.useEffect(() => {
6114
6242
  onReadyRef.current = onReady;
6115
6243
  onAuthenticatedRef.current = onAuthenticated;
6116
6244
  onRequiresOtpRef.current = onRequiresOtp;
6117
6245
  onErrorRef.current = onError;
6118
6246
  }, [onReady, onAuthenticated, onRequiresOtp, onError]);
6119
- react.useEffect(() => {
6247
+ React2.useEffect(() => {
6120
6248
  if (!elements || !containerRef.current) return;
6121
6249
  const element = elements.create(ELEMENT_TYPES.AUTH, { prefillEmail });
6122
6250
  elementRef.current = element;
@@ -6146,18 +6274,18 @@ function AddressElement({
6146
6274
  onChange,
6147
6275
  onError
6148
6276
  }) {
6149
- const containerRef = react.useRef(null);
6150
- const elementRef = react.useRef(null);
6277
+ const containerRef = React2.useRef(null);
6278
+ const elementRef = React2.useRef(null);
6151
6279
  const elements = useElements();
6152
- const onReadyRef = react.useRef(onReady);
6153
- const onChangeRef = react.useRef(onChange);
6154
- const onErrorRef = react.useRef(onError);
6155
- react.useEffect(() => {
6280
+ const onReadyRef = React2.useRef(onReady);
6281
+ const onChangeRef = React2.useRef(onChange);
6282
+ const onErrorRef = React2.useRef(onError);
6283
+ React2.useEffect(() => {
6156
6284
  onReadyRef.current = onReady;
6157
6285
  onChangeRef.current = onChange;
6158
6286
  onErrorRef.current = onError;
6159
6287
  }, [onReady, onChange, onError]);
6160
- react.useEffect(() => {
6288
+ React2.useEffect(() => {
6161
6289
  if (!elements || !containerRef.current) return;
6162
6290
  const element = elements.create(ELEMENT_TYPES.ADDRESS, { mode });
6163
6291
  elementRef.current = element;
@@ -6184,18 +6312,18 @@ function PaymentElement({
6184
6312
  onChange,
6185
6313
  onError
6186
6314
  }) {
6187
- const containerRef = react.useRef(null);
6188
- const elementRef = react.useRef(null);
6315
+ const containerRef = React2.useRef(null);
6316
+ const elementRef = React2.useRef(null);
6189
6317
  const elements = useElements();
6190
- const onReadyRef = react.useRef(onReady);
6191
- const onChangeRef = react.useRef(onChange);
6192
- const onErrorRef = react.useRef(onError);
6193
- react.useEffect(() => {
6318
+ const onReadyRef = React2.useRef(onReady);
6319
+ const onChangeRef = React2.useRef(onChange);
6320
+ const onErrorRef = React2.useRef(onError);
6321
+ React2.useEffect(() => {
6194
6322
  onReadyRef.current = onReady;
6195
6323
  onChangeRef.current = onChange;
6196
6324
  onErrorRef.current = onError;
6197
6325
  }, [onReady, onChange, onError]);
6198
- react.useEffect(() => {
6326
+ React2.useEffect(() => {
6199
6327
  if (!elements || !containerRef.current) return;
6200
6328
  const element = elements.create(ELEMENT_TYPES.PAYMENT, { amount, currency });
6201
6329
  elementRef.current = element;
@@ -6215,8 +6343,8 @@ function PaymentElement({
6215
6343
  }
6216
6344
  function useCheckout() {
6217
6345
  const elements = useElements();
6218
- const [isLoading, setIsLoading] = react.useState(false);
6219
- const submit = react.useCallback(
6346
+ const [isLoading, setIsLoading] = React2.useState(false);
6347
+ const submit = React2.useCallback(
6220
6348
  async (data) => {
6221
6349
  if (!elements) {
6222
6350
  return { success: false, error: { code: "NO_ELEMENTS", message: "Elements not initialized" } };
@@ -6230,7 +6358,7 @@ function useCheckout() {
6230
6358
  },
6231
6359
  [elements]
6232
6360
  );
6233
- const process = react.useCallback(
6361
+ const process = React2.useCallback(
6234
6362
  async (options) => {
6235
6363
  if (!elements) {
6236
6364
  return {