@cimplify/sdk 0.8.1 → 0.8.3

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;
@@ -3583,6 +3680,14 @@ var CimplifyClient = class {
3583
3680
  );
3584
3681
  }
3585
3682
  }
3683
+ /** Build a full URL, appending context params (e.g. location_id) as query parameters. */
3684
+ buildUrl(base, path) {
3685
+ const url = `${base}${path}`;
3686
+ const locationId = this.context.location_id;
3687
+ if (!locationId) return url;
3688
+ const separator = url.includes("?") ? "&" : "?";
3689
+ return `${url}${separator}location_id=${encodeURIComponent(locationId)}`;
3690
+ }
3586
3691
  /** @deprecated Use getAccessToken() instead */
3587
3692
  getSessionToken() {
3588
3693
  return this.accessToken;
@@ -3626,12 +3731,27 @@ var CimplifyClient = class {
3626
3731
  }
3627
3732
  setOrderToken(orderId, token) {
3628
3733
  if (typeof window !== "undefined" && window.localStorage) {
3629
- localStorage.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, token);
3734
+ try {
3735
+ const entry = JSON.stringify({ token, storedAt: Date.now() });
3736
+ localStorage.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, entry);
3737
+ } catch {
3738
+ }
3630
3739
  }
3631
3740
  }
3632
3741
  getOrderToken(orderId) {
3633
3742
  if (typeof window !== "undefined" && window.localStorage) {
3634
- return localStorage.getItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
3743
+ try {
3744
+ const raw = localStorage.getItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
3745
+ if (!raw) return null;
3746
+ const entry = JSON.parse(raw);
3747
+ if (Date.now() - entry.storedAt > ORDER_TOKEN_TTL_MS) {
3748
+ localStorage.removeItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
3749
+ return null;
3750
+ }
3751
+ return entry.token;
3752
+ } catch {
3753
+ return null;
3754
+ }
3635
3755
  }
3636
3756
  return null;
3637
3757
  }
@@ -3707,10 +3827,13 @@ var CimplifyClient = class {
3707
3827
  }
3708
3828
  saveAccessToken(token) {
3709
3829
  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);
3830
+ try {
3831
+ if (token) {
3832
+ localStorage.setItem(ACCESS_TOKEN_STORAGE_KEY, token);
3833
+ } else {
3834
+ localStorage.removeItem(ACCESS_TOKEN_STORAGE_KEY);
3835
+ }
3836
+ } catch {
3714
3837
  }
3715
3838
  }
3716
3839
  }
@@ -3783,6 +3906,19 @@ var CimplifyClient = class {
3783
3906
  });
3784
3907
  return response;
3785
3908
  }
3909
+ if (response.status === 429 && attempt < this.maxRetries) {
3910
+ retryCount++;
3911
+ const retryAfter = response.headers.get("Retry-After");
3912
+ const delay = retryAfter ? Math.min(parseInt(retryAfter, 10) * 1e3, 3e4) || this.retryDelay * Math.pow(2, attempt) : this.retryDelay * Math.pow(2, attempt);
3913
+ this.hooks.onRetry?.({
3914
+ ...context,
3915
+ attempt: retryCount,
3916
+ delayMs: delay,
3917
+ error: new Error(`Rate limited: ${response.status}`)
3918
+ });
3919
+ await sleep(delay);
3920
+ continue;
3921
+ }
3786
3922
  if (response.status >= 400 && response.status < 500) {
3787
3923
  this.hooks.onRequestError?.({
3788
3924
  ...context,
@@ -3875,7 +4011,7 @@ var CimplifyClient = class {
3875
4011
  async get(path) {
3876
4012
  const key = this.getDedupeKey("get", path);
3877
4013
  return this.deduplicatedRequest(key, async () => {
3878
- const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
4014
+ const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
3879
4015
  method: "GET",
3880
4016
  credentials: this.credentials,
3881
4017
  headers: this.getHeaders()
@@ -3884,7 +4020,7 @@ var CimplifyClient = class {
3884
4020
  });
3885
4021
  }
3886
4022
  async post(path, body) {
3887
- const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
4023
+ const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
3888
4024
  method: "POST",
3889
4025
  credentials: this.credentials,
3890
4026
  headers: this.getHeaders(),
@@ -3893,7 +4029,7 @@ var CimplifyClient = class {
3893
4029
  return this.handleRestResponse(response);
3894
4030
  }
3895
4031
  async patch(path, body) {
3896
- const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
4032
+ const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
3897
4033
  method: "PATCH",
3898
4034
  credentials: this.credentials,
3899
4035
  headers: this.getHeaders(),
@@ -3902,7 +4038,7 @@ var CimplifyClient = class {
3902
4038
  return this.handleRestResponse(response);
3903
4039
  }
3904
4040
  async delete(path) {
3905
- const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
4041
+ const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
3906
4042
  method: "DELETE",
3907
4043
  credentials: this.credentials,
3908
4044
  headers: this.getHeaders()
@@ -4106,23 +4242,23 @@ function resolveInitialLocation(locations) {
4106
4242
  }
4107
4243
  return locations[0];
4108
4244
  }
4109
- var CimplifyContext = react.createContext(null);
4245
+ var CimplifyContext = React2.createContext(null);
4110
4246
  function CimplifyProvider({
4111
4247
  client,
4112
4248
  children,
4113
4249
  onLocationChange
4114
4250
  }) {
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(() => {
4251
+ const resolvedClient = React2.useMemo(() => client ?? createDefaultClient(), [client]);
4252
+ const onLocationChangeRef = React2.useRef(onLocationChange);
4253
+ const [business, setBusiness] = React2.useState(null);
4254
+ const [locations, setLocations] = React2.useState([]);
4255
+ const [currentLocation, setCurrentLocationState] = React2.useState(null);
4256
+ const [isReady, setIsReady] = React2.useState(false);
4257
+ React2.useEffect(() => {
4122
4258
  onLocationChangeRef.current = onLocationChange;
4123
4259
  }, [onLocationChange]);
4124
4260
  const isDemoMode = resolvedClient.getPublicKey().trim().length === 0;
4125
- const setCurrentLocation = react.useCallback(
4261
+ const setCurrentLocation = React2.useCallback(
4126
4262
  (location) => {
4127
4263
  setCurrentLocationState(location);
4128
4264
  resolvedClient.setLocationId(location.id);
@@ -4131,7 +4267,7 @@ function CimplifyProvider({
4131
4267
  },
4132
4268
  [resolvedClient]
4133
4269
  );
4134
- react.useEffect(() => {
4270
+ React2.useEffect(() => {
4135
4271
  let cancelled = false;
4136
4272
  async function bootstrap() {
4137
4273
  setIsReady(false);
@@ -4187,7 +4323,7 @@ function CimplifyProvider({
4187
4323
  cancelled = true;
4188
4324
  };
4189
4325
  }, [resolvedClient, isDemoMode]);
4190
- const contextValue = react.useMemo(
4326
+ const contextValue = React2.useMemo(
4191
4327
  () => ({
4192
4328
  client: resolvedClient,
4193
4329
  business,
@@ -4212,14 +4348,14 @@ function CimplifyProvider({
4212
4348
  return /* @__PURE__ */ jsxRuntime.jsx(CimplifyContext.Provider, { value: contextValue, children });
4213
4349
  }
4214
4350
  function useCimplify() {
4215
- const context = react.useContext(CimplifyContext);
4351
+ const context = React2.useContext(CimplifyContext);
4216
4352
  if (!context) {
4217
4353
  throw new Error("useCimplify must be used within CimplifyProvider");
4218
4354
  }
4219
4355
  return context;
4220
4356
  }
4221
4357
  function useOptionalCimplify() {
4222
- return react.useContext(CimplifyContext);
4358
+ return React2.useContext(CimplifyContext);
4223
4359
  }
4224
4360
  var productsCache = /* @__PURE__ */ new Map();
4225
4361
  var productsInflight = /* @__PURE__ */ new Map();
@@ -4238,9 +4374,9 @@ function useProducts(options = {}) {
4238
4374
  }
4239
4375
  const enabled = options.enabled ?? true;
4240
4376
  const locationId = client.getLocationId();
4241
- const previousLocationIdRef = react.useRef(locationId);
4242
- const requestIdRef = react.useRef(0);
4243
- const queryOptions = react.useMemo(
4377
+ const previousLocationIdRef = React2.useRef(locationId);
4378
+ const requestIdRef = React2.useRef(0);
4379
+ const queryOptions = React2.useMemo(
4244
4380
  () => ({
4245
4381
  category: options.category,
4246
4382
  collection: options.collection,
@@ -4250,25 +4386,25 @@ function useProducts(options = {}) {
4250
4386
  }),
4251
4387
  [options.category, options.collection, options.featured, options.limit, options.search]
4252
4388
  );
4253
- const cacheKey = react.useMemo(
4389
+ const cacheKey = React2.useMemo(
4254
4390
  () => buildProductsCacheKey(client, locationId, queryOptions),
4255
4391
  [client, locationId, queryOptions]
4256
4392
  );
4257
4393
  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(() => {
4394
+ const [products, setProducts] = React2.useState(cached?.products ?? []);
4395
+ const [isComplete, setIsComplete] = React2.useState(cached?.is_complete ?? true);
4396
+ const [totalAvailable, setTotalAvailable] = React2.useState(cached?.total_available);
4397
+ const [pagination, setPagination] = React2.useState(cached?.pagination);
4398
+ const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
4399
+ const [error, setError] = React2.useState(null);
4400
+ React2.useEffect(() => {
4265
4401
  if (previousLocationIdRef.current !== locationId) {
4266
4402
  productsCache.clear();
4267
4403
  productsInflight.clear();
4268
4404
  previousLocationIdRef.current = locationId;
4269
4405
  }
4270
4406
  }, [locationId]);
4271
- const load = react.useCallback(
4407
+ const load = React2.useCallback(
4272
4408
  async (force = false) => {
4273
4409
  if (!enabled) {
4274
4410
  setIsLoading(false);
@@ -4331,10 +4467,10 @@ function useProducts(options = {}) {
4331
4467
  },
4332
4468
  [cacheKey, client, enabled, queryOptions]
4333
4469
  );
4334
- react.useEffect(() => {
4470
+ React2.useEffect(() => {
4335
4471
  void load(false);
4336
4472
  }, [load]);
4337
- const refetch = react.useCallback(async () => {
4473
+ const refetch = React2.useCallback(async () => {
4338
4474
  productsCache.delete(cacheKey);
4339
4475
  await load(true);
4340
4476
  }, [cacheKey, load]);
@@ -4368,27 +4504,27 @@ function useProduct(slugOrId, options = {}) {
4368
4504
  }
4369
4505
  const enabled = options.enabled ?? true;
4370
4506
  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(
4507
+ const previousLocationIdRef = React2.useRef(locationId);
4508
+ const requestIdRef = React2.useRef(0);
4509
+ const normalizedSlugOrId = React2.useMemo(() => (slugOrId || "").trim(), [slugOrId]);
4510
+ const cacheKey = React2.useMemo(
4375
4511
  () => buildProductCacheKey(client, locationId, normalizedSlugOrId),
4376
4512
  [client, locationId, normalizedSlugOrId]
4377
4513
  );
4378
4514
  const cached = productCache.get(cacheKey);
4379
- const [product, setProduct] = react.useState(cached?.product ?? null);
4380
- const [isLoading, setIsLoading] = react.useState(
4515
+ const [product, setProduct] = React2.useState(cached?.product ?? null);
4516
+ const [isLoading, setIsLoading] = React2.useState(
4381
4517
  enabled && normalizedSlugOrId.length > 0 && !cached
4382
4518
  );
4383
- const [error, setError] = react.useState(null);
4384
- react.useEffect(() => {
4519
+ const [error, setError] = React2.useState(null);
4520
+ React2.useEffect(() => {
4385
4521
  if (previousLocationIdRef.current !== locationId) {
4386
4522
  productCache.clear();
4387
4523
  productInflight.clear();
4388
4524
  previousLocationIdRef.current = locationId;
4389
4525
  }
4390
4526
  }, [locationId]);
4391
- const load = react.useCallback(
4527
+ const load = React2.useCallback(
4392
4528
  async (force = false) => {
4393
4529
  if (!enabled || normalizedSlugOrId.length === 0) {
4394
4530
  setProduct(null);
@@ -4441,10 +4577,10 @@ function useProduct(slugOrId, options = {}) {
4441
4577
  },
4442
4578
  [cacheKey, client, enabled, normalizedSlugOrId]
4443
4579
  );
4444
- react.useEffect(() => {
4580
+ React2.useEffect(() => {
4445
4581
  void load(false);
4446
4582
  }, [load]);
4447
- const refetch = react.useCallback(async () => {
4583
+ const refetch = React2.useCallback(async () => {
4448
4584
  productCache.delete(cacheKey);
4449
4585
  await load(true);
4450
4586
  }, [cacheKey, load]);
@@ -4462,12 +4598,12 @@ function useCategories(options = {}) {
4462
4598
  throw new Error("useCategories must be used within CimplifyProvider or passed { client }.");
4463
4599
  }
4464
4600
  const enabled = options.enabled ?? true;
4465
- const cacheKey = react.useMemo(() => buildCategoriesCacheKey(client), [client]);
4601
+ const cacheKey = React2.useMemo(() => buildCategoriesCacheKey(client), [client]);
4466
4602
  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(
4603
+ const [categories, setCategories] = React2.useState(cached ?? []);
4604
+ const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
4605
+ const [error, setError] = React2.useState(null);
4606
+ const load = React2.useCallback(
4471
4607
  async (force = false) => {
4472
4608
  if (!enabled) {
4473
4609
  setIsLoading(false);
@@ -4511,10 +4647,10 @@ function useCategories(options = {}) {
4511
4647
  },
4512
4648
  [cacheKey, client, enabled]
4513
4649
  );
4514
- react.useEffect(() => {
4650
+ React2.useEffect(() => {
4515
4651
  void load(false);
4516
4652
  }, [load]);
4517
- const refetch = react.useCallback(async () => {
4653
+ const refetch = React2.useCallback(async () => {
4518
4654
  categoriesCache.delete(cacheKey);
4519
4655
  await load(true);
4520
4656
  }, [cacheKey, load]);
@@ -5035,7 +5171,7 @@ function useCart(options = {}) {
5035
5171
  const locationId = options.locationId ?? client.getLocationId();
5036
5172
  const isDemoMode = options.demoMode ?? context?.isDemoMode ?? client.getPublicKey().trim().length === 0;
5037
5173
  const currency = options.currency ?? context?.currency ?? "USD";
5038
- const store = react.useMemo(
5174
+ const store = React2.useMemo(
5039
5175
  () => getOrCreateStore({
5040
5176
  client,
5041
5177
  locationId,
@@ -5044,43 +5180,43 @@ function useCart(options = {}) {
5044
5180
  }),
5045
5181
  [client, currency, isDemoMode, locationId]
5046
5182
  );
5047
- const snapshot = react.useSyncExternalStore(
5183
+ const snapshot = React2.useSyncExternalStore(
5048
5184
  store.subscribe,
5049
5185
  store.getSnapshot,
5050
5186
  store.getSnapshot
5051
5187
  );
5052
- react.useEffect(() => {
5188
+ React2.useEffect(() => {
5053
5189
  void store.initialize();
5054
5190
  }, [store]);
5055
- const addItem = react.useCallback(
5191
+ const addItem = React2.useCallback(
5056
5192
  async (product, quantity, addOptions) => {
5057
5193
  await store.addItem(product, quantity, addOptions);
5058
5194
  },
5059
5195
  [store]
5060
5196
  );
5061
- const removeItem = react.useCallback(
5197
+ const removeItem = React2.useCallback(
5062
5198
  async (itemId) => {
5063
5199
  await store.removeItem(itemId);
5064
5200
  },
5065
5201
  [store]
5066
5202
  );
5067
- const updateQuantity = react.useCallback(
5203
+ const updateQuantity = React2.useCallback(
5068
5204
  async (itemId, quantity) => {
5069
5205
  await store.updateQuantity(itemId, quantity);
5070
5206
  },
5071
5207
  [store]
5072
5208
  );
5073
- const clearCart = react.useCallback(async () => {
5209
+ const clearCart = React2.useCallback(async () => {
5074
5210
  await store.clearCart();
5075
5211
  }, [store]);
5076
- const sync = react.useCallback(async () => {
5212
+ const sync = React2.useCallback(async () => {
5077
5213
  try {
5078
5214
  await store.sync();
5079
5215
  } catch (syncError) {
5080
5216
  throw syncError;
5081
5217
  }
5082
5218
  }, [store]);
5083
- const itemCount = react.useMemo(
5219
+ const itemCount = React2.useMemo(
5084
5220
  () => snapshot.items.reduce((sum, item) => sum + item.quantity, 0),
5085
5221
  [snapshot.items]
5086
5222
  );
@@ -5111,22 +5247,22 @@ function useOrder(orderId, options = {}) {
5111
5247
  if (!client) {
5112
5248
  throw new Error("useOrder must be used within CimplifyProvider or passed { client }.");
5113
5249
  }
5114
- const normalizedOrderId = react.useMemo(() => (orderId || "").trim(), [orderId]);
5250
+ const normalizedOrderId = React2.useMemo(() => (orderId || "").trim(), [orderId]);
5115
5251
  const enabled = options.enabled ?? true;
5116
5252
  const poll = options.poll ?? false;
5117
5253
  const pollInterval = options.pollInterval ?? 5e3;
5118
- const requestIdRef = react.useRef(0);
5119
- const cacheKey = react.useMemo(
5254
+ const requestIdRef = React2.useRef(0);
5255
+ const cacheKey = React2.useMemo(
5120
5256
  () => buildOrderCacheKey(client, normalizedOrderId),
5121
5257
  [client, normalizedOrderId]
5122
5258
  );
5123
5259
  const cached = orderCache.get(cacheKey);
5124
- const [order, setOrder] = react.useState(cached?.order ?? null);
5125
- const [isLoading, setIsLoading] = react.useState(
5260
+ const [order, setOrder] = React2.useState(cached?.order ?? null);
5261
+ const [isLoading, setIsLoading] = React2.useState(
5126
5262
  enabled && normalizedOrderId.length > 0 && !cached
5127
5263
  );
5128
- const [error, setError] = react.useState(null);
5129
- const load = react.useCallback(
5264
+ const [error, setError] = React2.useState(null);
5265
+ const load = React2.useCallback(
5130
5266
  async (force = false) => {
5131
5267
  if (!enabled || normalizedOrderId.length === 0) {
5132
5268
  setOrder(null);
@@ -5179,10 +5315,10 @@ function useOrder(orderId, options = {}) {
5179
5315
  },
5180
5316
  [cacheKey, client, enabled, normalizedOrderId]
5181
5317
  );
5182
- react.useEffect(() => {
5318
+ React2.useEffect(() => {
5183
5319
  void load(false);
5184
5320
  }, [load]);
5185
- react.useEffect(() => {
5321
+ React2.useEffect(() => {
5186
5322
  if (!poll || !enabled || normalizedOrderId.length === 0) {
5187
5323
  return;
5188
5324
  }
@@ -5193,7 +5329,7 @@ function useOrder(orderId, options = {}) {
5193
5329
  window.clearInterval(timer);
5194
5330
  };
5195
5331
  }, [enabled, load, normalizedOrderId.length, poll, pollInterval]);
5196
- const refetch = react.useCallback(async () => {
5332
+ const refetch = React2.useCallback(async () => {
5197
5333
  orderCache.delete(cacheKey);
5198
5334
  await load(true);
5199
5335
  }, [cacheKey, load]);
@@ -5244,10 +5380,10 @@ function useLocations(options = {}) {
5244
5380
  };
5245
5381
  }
5246
5382
  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(
5383
+ const [locations, setLocations] = React2.useState([]);
5384
+ const [currentLocation, setCurrentLocationState] = React2.useState(null);
5385
+ const [isLoading, setIsLoading] = React2.useState(true);
5386
+ const setCurrentLocation = React2.useCallback(
5251
5387
  (location) => {
5252
5388
  setCurrentLocationState(location);
5253
5389
  if (client) {
@@ -5257,7 +5393,7 @@ function useLocations(options = {}) {
5257
5393
  },
5258
5394
  [client]
5259
5395
  );
5260
- react.useEffect(() => {
5396
+ React2.useEffect(() => {
5261
5397
  if (!client) {
5262
5398
  setLocations([]);
5263
5399
  setCurrentLocationState(null);
@@ -5315,24 +5451,24 @@ function useCollections(options = {}) {
5315
5451
  }
5316
5452
  const enabled = options.enabled ?? true;
5317
5453
  const locationId = client.getLocationId();
5318
- const previousLocationIdRef = react.useRef(locationId);
5319
- const requestIdRef = react.useRef(0);
5320
- const cacheKey = react.useMemo(
5454
+ const previousLocationIdRef = React2.useRef(locationId);
5455
+ const requestIdRef = React2.useRef(0);
5456
+ const cacheKey = React2.useMemo(
5321
5457
  () => buildCollectionsCacheKey(client, locationId),
5322
5458
  [client, locationId]
5323
5459
  );
5324
5460
  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(() => {
5461
+ const [collections, setCollections] = React2.useState(cached?.collections ?? []);
5462
+ const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
5463
+ const [error, setError] = React2.useState(null);
5464
+ React2.useEffect(() => {
5329
5465
  if (previousLocationIdRef.current !== locationId) {
5330
5466
  collectionsCache.clear();
5331
5467
  collectionsInflight.clear();
5332
5468
  previousLocationIdRef.current = locationId;
5333
5469
  }
5334
5470
  }, [locationId]);
5335
- const load = react.useCallback(
5471
+ const load = React2.useCallback(
5336
5472
  async (force = false) => {
5337
5473
  if (!enabled) {
5338
5474
  setIsLoading(false);
@@ -5382,10 +5518,10 @@ function useCollections(options = {}) {
5382
5518
  },
5383
5519
  [cacheKey, client, enabled]
5384
5520
  );
5385
- react.useEffect(() => {
5521
+ React2.useEffect(() => {
5386
5522
  void load(false);
5387
5523
  }, [load]);
5388
- const refetch = react.useCallback(async () => {
5524
+ const refetch = React2.useCallback(async () => {
5389
5525
  collectionsCache.delete(cacheKey);
5390
5526
  await load(true);
5391
5527
  }, [cacheKey, load]);
@@ -5411,28 +5547,28 @@ function useCollection(idOrSlug, options = {}) {
5411
5547
  }
5412
5548
  const enabled = options.enabled ?? true;
5413
5549
  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(
5550
+ const previousLocationIdRef = React2.useRef(locationId);
5551
+ const requestIdRef = React2.useRef(0);
5552
+ const normalizedIdOrSlug = React2.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5553
+ const cacheKey = React2.useMemo(
5418
5554
  () => buildCollectionCacheKey(client, locationId, normalizedIdOrSlug),
5419
5555
  [client, locationId, normalizedIdOrSlug]
5420
5556
  );
5421
5557
  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(
5558
+ const [collection, setCollection] = React2.useState(cached?.collection ?? null);
5559
+ const [products, setProducts] = React2.useState(cached?.products ?? []);
5560
+ const [isLoading, setIsLoading] = React2.useState(
5425
5561
  enabled && normalizedIdOrSlug.length > 0 && !cached
5426
5562
  );
5427
- const [error, setError] = react.useState(null);
5428
- react.useEffect(() => {
5563
+ const [error, setError] = React2.useState(null);
5564
+ React2.useEffect(() => {
5429
5565
  if (previousLocationIdRef.current !== locationId) {
5430
5566
  collectionCache.clear();
5431
5567
  collectionInflight.clear();
5432
5568
  previousLocationIdRef.current = locationId;
5433
5569
  }
5434
5570
  }, [locationId]);
5435
- const load = react.useCallback(
5571
+ const load = React2.useCallback(
5436
5572
  async (force = false) => {
5437
5573
  if (!enabled || normalizedIdOrSlug.length === 0) {
5438
5574
  setCollection(null);
@@ -5495,10 +5631,10 @@ function useCollection(idOrSlug, options = {}) {
5495
5631
  },
5496
5632
  [cacheKey, client, enabled, normalizedIdOrSlug]
5497
5633
  );
5498
- react.useEffect(() => {
5634
+ React2.useEffect(() => {
5499
5635
  void load(false);
5500
5636
  }, [load]);
5501
- const refetch = react.useCallback(async () => {
5637
+ const refetch = React2.useCallback(async () => {
5502
5638
  collectionCache.delete(cacheKey);
5503
5639
  await load(true);
5504
5640
  }, [cacheKey, load]);
@@ -5524,27 +5660,27 @@ function useBundle(idOrSlug, options = {}) {
5524
5660
  }
5525
5661
  const enabled = options.enabled ?? true;
5526
5662
  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(
5663
+ const previousLocationIdRef = React2.useRef(locationId);
5664
+ const requestIdRef = React2.useRef(0);
5665
+ const normalizedIdOrSlug = React2.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5666
+ const cacheKey = React2.useMemo(
5531
5667
  () => buildBundleCacheKey(client, locationId, normalizedIdOrSlug),
5532
5668
  [client, locationId, normalizedIdOrSlug]
5533
5669
  );
5534
5670
  const cached = bundleCache.get(cacheKey);
5535
- const [bundle, setBundle] = react.useState(cached?.bundle ?? null);
5536
- const [isLoading, setIsLoading] = react.useState(
5671
+ const [bundle, setBundle] = React2.useState(cached?.bundle ?? null);
5672
+ const [isLoading, setIsLoading] = React2.useState(
5537
5673
  enabled && normalizedIdOrSlug.length > 0 && !cached
5538
5674
  );
5539
- const [error, setError] = react.useState(null);
5540
- react.useEffect(() => {
5675
+ const [error, setError] = React2.useState(null);
5676
+ React2.useEffect(() => {
5541
5677
  if (previousLocationIdRef.current !== locationId) {
5542
5678
  bundleCache.clear();
5543
5679
  bundleInflight.clear();
5544
5680
  previousLocationIdRef.current = locationId;
5545
5681
  }
5546
5682
  }, [locationId]);
5547
- const load = react.useCallback(
5683
+ const load = React2.useCallback(
5548
5684
  async (force = false) => {
5549
5685
  if (!enabled || normalizedIdOrSlug.length === 0) {
5550
5686
  setBundle(null);
@@ -5595,10 +5731,10 @@ function useBundle(idOrSlug, options = {}) {
5595
5731
  },
5596
5732
  [cacheKey, client, enabled, normalizedIdOrSlug]
5597
5733
  );
5598
- react.useEffect(() => {
5734
+ React2.useEffect(() => {
5599
5735
  void load(false);
5600
5736
  }, [load]);
5601
- const refetch = react.useCallback(async () => {
5737
+ const refetch = React2.useCallback(async () => {
5602
5738
  bundleCache.delete(cacheKey);
5603
5739
  await load(true);
5604
5740
  }, [cacheKey, load]);
@@ -5628,37 +5764,37 @@ function useComposite(idOrProductId, options = {}) {
5628
5764
  }
5629
5765
  const enabled = options.enabled ?? true;
5630
5766
  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(
5767
+ const previousLocationIdRef = React2.useRef(locationId);
5768
+ const requestIdRef = React2.useRef(0);
5769
+ const priceRequestIdRef = React2.useRef(0);
5770
+ const normalizedIdOrProductId = React2.useMemo(
5635
5771
  () => (idOrProductId || "").trim(),
5636
5772
  [idOrProductId]
5637
5773
  );
5638
- const byProductId = react.useMemo(
5774
+ const byProductId = React2.useMemo(
5639
5775
  () => shouldFetchByProductId(normalizedIdOrProductId, options.byProductId),
5640
5776
  [normalizedIdOrProductId, options.byProductId]
5641
5777
  );
5642
- const cacheKey = react.useMemo(
5778
+ const cacheKey = React2.useMemo(
5643
5779
  () => buildCompositeCacheKey(client, locationId, normalizedIdOrProductId, byProductId),
5644
5780
  [byProductId, client, locationId, normalizedIdOrProductId]
5645
5781
  );
5646
5782
  const cached = compositeCache.get(cacheKey);
5647
- const [composite, setComposite] = react.useState(cached?.composite ?? null);
5648
- const [isLoading, setIsLoading] = react.useState(
5783
+ const [composite, setComposite] = React2.useState(cached?.composite ?? null);
5784
+ const [isLoading, setIsLoading] = React2.useState(
5649
5785
  enabled && normalizedIdOrProductId.length > 0 && !cached
5650
5786
  );
5651
- const [error, setError] = react.useState(null);
5652
- const [priceResult, setPriceResult] = react.useState(null);
5653
- const [isPriceLoading, setIsPriceLoading] = react.useState(false);
5654
- react.useEffect(() => {
5787
+ const [error, setError] = React2.useState(null);
5788
+ const [priceResult, setPriceResult] = React2.useState(null);
5789
+ const [isPriceLoading, setIsPriceLoading] = React2.useState(false);
5790
+ React2.useEffect(() => {
5655
5791
  if (previousLocationIdRef.current !== locationId) {
5656
5792
  compositeCache.clear();
5657
5793
  compositeInflight.clear();
5658
5794
  previousLocationIdRef.current = locationId;
5659
5795
  }
5660
5796
  }, [locationId]);
5661
- const load = react.useCallback(
5797
+ const load = React2.useCallback(
5662
5798
  async (force = false) => {
5663
5799
  if (!enabled || normalizedIdOrProductId.length === 0) {
5664
5800
  setComposite(null);
@@ -5711,10 +5847,10 @@ function useComposite(idOrProductId, options = {}) {
5711
5847
  },
5712
5848
  [byProductId, cacheKey, client, enabled, normalizedIdOrProductId]
5713
5849
  );
5714
- react.useEffect(() => {
5850
+ React2.useEffect(() => {
5715
5851
  void load(false);
5716
5852
  }, [load]);
5717
- const calculatePrice = react.useCallback(
5853
+ const calculatePrice = React2.useCallback(
5718
5854
  async (selections, overrideLocationId) => {
5719
5855
  if (!composite) {
5720
5856
  return null;
@@ -5748,7 +5884,7 @@ function useComposite(idOrProductId, options = {}) {
5748
5884
  },
5749
5885
  [client, composite]
5750
5886
  );
5751
- const refetch = react.useCallback(async () => {
5887
+ const refetch = React2.useCallback(async () => {
5752
5888
  compositeCache.delete(cacheKey);
5753
5889
  await load(true);
5754
5890
  }, [cacheKey, load]);
@@ -5763,13 +5899,13 @@ function useSearch(options = {}) {
5763
5899
  const minLength = Math.max(0, options.minLength ?? 2);
5764
5900
  const debounceMs = Math.max(0, options.debounceMs ?? 300);
5765
5901
  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(() => {
5902
+ const [query, setQueryState] = React2.useState("");
5903
+ const [results, setResults] = React2.useState([]);
5904
+ const [isLoading, setIsLoading] = React2.useState(false);
5905
+ const [error, setError] = React2.useState(null);
5906
+ const requestIdRef = React2.useRef(0);
5907
+ const timerRef = React2.useRef(null);
5908
+ React2.useEffect(() => {
5773
5909
  if (timerRef.current) {
5774
5910
  clearTimeout(timerRef.current);
5775
5911
  timerRef.current = null;
@@ -5816,10 +5952,10 @@ function useSearch(options = {}) {
5816
5952
  }
5817
5953
  };
5818
5954
  }, [client, debounceMs, limit, minLength, options.category, query]);
5819
- const setQuery = react.useCallback((nextQuery) => {
5955
+ const setQuery = React2.useCallback((nextQuery) => {
5820
5956
  setQueryState(nextQuery);
5821
5957
  }, []);
5822
- const clear = react.useCallback(() => {
5958
+ const clear = React2.useCallback(() => {
5823
5959
  requestIdRef.current += 1;
5824
5960
  if (timerRef.current) {
5825
5961
  clearTimeout(timerRef.current);
@@ -5875,28 +6011,28 @@ function useQuote(input, options = {}) {
5875
6011
  const autoRefresh = options.autoRefresh ?? true;
5876
6012
  const refreshBeforeExpiryMs = Math.max(0, options.refreshBeforeExpiryMs ?? 3e4);
5877
6013
  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(() => {
6014
+ const requestIdRef = React2.useRef(0);
6015
+ const refreshTimerRef = React2.useRef(null);
6016
+ const expiryTimerRef = React2.useRef(null);
6017
+ const inputSignature = React2.useMemo(() => JSON.stringify(input ?? null), [input]);
6018
+ const normalizedInput = React2.useMemo(() => {
5883
6019
  if (!input) {
5884
6020
  return null;
5885
6021
  }
5886
6022
  const normalized = normalizeInput(input, locationId);
5887
6023
  return normalized.product_id.length > 0 ? normalized : null;
5888
6024
  }, [inputSignature, locationId]);
5889
- const cacheKey = react.useMemo(
6025
+ const cacheKey = React2.useMemo(
5890
6026
  () => buildQuoteCacheKey(client, locationId, inputSignature),
5891
6027
  [client, inputSignature, locationId]
5892
6028
  );
5893
6029
  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(
6030
+ const [quote, setQuote] = React2.useState(cached?.quote ?? null);
6031
+ const [isLoading, setIsLoading] = React2.useState(enabled && normalizedInput !== null && !cached);
6032
+ const [error, setError] = React2.useState(null);
6033
+ const [isExpired, setIsExpired] = React2.useState(isQuoteExpired(cached?.quote ?? null));
6034
+ const [messages, setMessages] = React2.useState(cached?.quote?.ui_messages ?? []);
6035
+ const load = React2.useCallback(
5900
6036
  async (force = false) => {
5901
6037
  if (!enabled || !normalizedInput) {
5902
6038
  setQuote(null);
@@ -5954,10 +6090,10 @@ function useQuote(input, options = {}) {
5954
6090
  },
5955
6091
  [cacheKey, client, enabled, normalizedInput]
5956
6092
  );
5957
- react.useEffect(() => {
6093
+ React2.useEffect(() => {
5958
6094
  void load(false);
5959
6095
  }, [load]);
5960
- const refresh = react.useCallback(async () => {
6096
+ const refresh = React2.useCallback(async () => {
5961
6097
  if (!enabled || !normalizedInput) {
5962
6098
  return;
5963
6099
  }
@@ -5994,7 +6130,7 @@ function useQuote(input, options = {}) {
5994
6130
  }
5995
6131
  }
5996
6132
  }, [cacheKey, client, enabled, load, normalizedInput, quote]);
5997
- react.useEffect(() => {
6133
+ React2.useEffect(() => {
5998
6134
  if (expiryTimerRef.current) {
5999
6135
  clearTimeout(expiryTimerRef.current);
6000
6136
  expiryTimerRef.current = null;
@@ -6018,7 +6154,7 @@ function useQuote(input, options = {}) {
6018
6154
  }
6019
6155
  };
6020
6156
  }, [quote?.expires_at, quote?.quote_id]);
6021
- react.useEffect(() => {
6157
+ React2.useEffect(() => {
6022
6158
  if (refreshTimerRef.current) {
6023
6159
  clearTimeout(refreshTimerRef.current);
6024
6160
  refreshTimerRef.current = null;
@@ -6043,15 +6179,15 @@ function useQuote(input, options = {}) {
6043
6179
  }, [autoRefresh, enabled, quote?.expires_at, quote?.quote_id, refresh, refreshBeforeExpiryMs]);
6044
6180
  return { quote, isLoading, error, refresh, isExpired, messages };
6045
6181
  }
6046
- var ElementsContext = react.createContext({
6182
+ var ElementsContext = React2.createContext({
6047
6183
  elements: null,
6048
6184
  isReady: false
6049
6185
  });
6050
6186
  function useElements() {
6051
- return react.useContext(ElementsContext).elements;
6187
+ return React2.useContext(ElementsContext).elements;
6052
6188
  }
6053
6189
  function useElementsReady() {
6054
- return react.useContext(ElementsContext).isReady;
6190
+ return React2.useContext(ElementsContext).isReady;
6055
6191
  }
6056
6192
  function ElementsProvider({
6057
6193
  client,
@@ -6059,10 +6195,10 @@ function ElementsProvider({
6059
6195
  options,
6060
6196
  children
6061
6197
  }) {
6062
- const [elements, setElements] = react.useState(null);
6063
- const [isReady, setIsReady] = react.useState(false);
6064
- const initialOptionsRef = react.useRef(options);
6065
- react.useEffect(() => {
6198
+ const [elements, setElements] = React2.useState(null);
6199
+ const [isReady, setIsReady] = React2.useState(false);
6200
+ const initialOptionsRef = React2.useRef(options);
6201
+ React2.useEffect(() => {
6066
6202
  let cancelled = false;
6067
6203
  let instance = null;
6068
6204
  setIsReady(false);
@@ -6103,20 +6239,20 @@ function AuthElement({
6103
6239
  onRequiresOtp,
6104
6240
  onError
6105
6241
  }) {
6106
- const containerRef = react.useRef(null);
6107
- const elementRef = react.useRef(null);
6242
+ const containerRef = React2.useRef(null);
6243
+ const elementRef = React2.useRef(null);
6108
6244
  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(() => {
6245
+ const onReadyRef = React2.useRef(onReady);
6246
+ const onAuthenticatedRef = React2.useRef(onAuthenticated);
6247
+ const onRequiresOtpRef = React2.useRef(onRequiresOtp);
6248
+ const onErrorRef = React2.useRef(onError);
6249
+ React2.useEffect(() => {
6114
6250
  onReadyRef.current = onReady;
6115
6251
  onAuthenticatedRef.current = onAuthenticated;
6116
6252
  onRequiresOtpRef.current = onRequiresOtp;
6117
6253
  onErrorRef.current = onError;
6118
6254
  }, [onReady, onAuthenticated, onRequiresOtp, onError]);
6119
- react.useEffect(() => {
6255
+ React2.useEffect(() => {
6120
6256
  if (!elements || !containerRef.current) return;
6121
6257
  const element = elements.create(ELEMENT_TYPES.AUTH, { prefillEmail });
6122
6258
  elementRef.current = element;
@@ -6146,18 +6282,18 @@ function AddressElement({
6146
6282
  onChange,
6147
6283
  onError
6148
6284
  }) {
6149
- const containerRef = react.useRef(null);
6150
- const elementRef = react.useRef(null);
6285
+ const containerRef = React2.useRef(null);
6286
+ const elementRef = React2.useRef(null);
6151
6287
  const elements = useElements();
6152
- const onReadyRef = react.useRef(onReady);
6153
- const onChangeRef = react.useRef(onChange);
6154
- const onErrorRef = react.useRef(onError);
6155
- react.useEffect(() => {
6288
+ const onReadyRef = React2.useRef(onReady);
6289
+ const onChangeRef = React2.useRef(onChange);
6290
+ const onErrorRef = React2.useRef(onError);
6291
+ React2.useEffect(() => {
6156
6292
  onReadyRef.current = onReady;
6157
6293
  onChangeRef.current = onChange;
6158
6294
  onErrorRef.current = onError;
6159
6295
  }, [onReady, onChange, onError]);
6160
- react.useEffect(() => {
6296
+ React2.useEffect(() => {
6161
6297
  if (!elements || !containerRef.current) return;
6162
6298
  const element = elements.create(ELEMENT_TYPES.ADDRESS, { mode });
6163
6299
  elementRef.current = element;
@@ -6184,18 +6320,18 @@ function PaymentElement({
6184
6320
  onChange,
6185
6321
  onError
6186
6322
  }) {
6187
- const containerRef = react.useRef(null);
6188
- const elementRef = react.useRef(null);
6323
+ const containerRef = React2.useRef(null);
6324
+ const elementRef = React2.useRef(null);
6189
6325
  const elements = useElements();
6190
- const onReadyRef = react.useRef(onReady);
6191
- const onChangeRef = react.useRef(onChange);
6192
- const onErrorRef = react.useRef(onError);
6193
- react.useEffect(() => {
6326
+ const onReadyRef = React2.useRef(onReady);
6327
+ const onChangeRef = React2.useRef(onChange);
6328
+ const onErrorRef = React2.useRef(onError);
6329
+ React2.useEffect(() => {
6194
6330
  onReadyRef.current = onReady;
6195
6331
  onChangeRef.current = onChange;
6196
6332
  onErrorRef.current = onError;
6197
6333
  }, [onReady, onChange, onError]);
6198
- react.useEffect(() => {
6334
+ React2.useEffect(() => {
6199
6335
  if (!elements || !containerRef.current) return;
6200
6336
  const element = elements.create(ELEMENT_TYPES.PAYMENT, { amount, currency });
6201
6337
  elementRef.current = element;
@@ -6215,8 +6351,8 @@ function PaymentElement({
6215
6351
  }
6216
6352
  function useCheckout() {
6217
6353
  const elements = useElements();
6218
- const [isLoading, setIsLoading] = react.useState(false);
6219
- const submit = react.useCallback(
6354
+ const [isLoading, setIsLoading] = React2.useState(false);
6355
+ const submit = React2.useCallback(
6220
6356
  async (data) => {
6221
6357
  if (!elements) {
6222
6358
  return { success: false, error: { code: "NO_ELEMENTS", message: "Elements not initialized" } };
@@ -6230,7 +6366,7 @@ function useCheckout() {
6230
6366
  },
6231
6367
  [elements]
6232
6368
  );
6233
- const process = react.useCallback(
6369
+ const process = React2.useCallback(
6234
6370
  async (options) => {
6235
6371
  if (!elements) {
6236
6372
  return {