@cimplify/sdk 0.7.13 → 0.8.0

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.mjs CHANGED
@@ -7,7 +7,8 @@ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
7
7
  var ELEMENT_TYPES = {
8
8
  AUTH: "auth",
9
9
  ADDRESS: "address",
10
- PAYMENT: "payment"
10
+ PAYMENT: "payment",
11
+ CHECKOUT: "checkout"
11
12
  };
12
13
  var MESSAGE_TYPES = {
13
14
  // Parent → Iframe
@@ -29,14 +30,17 @@ var MESSAGE_TYPES = {
29
30
  LOGOUT_COMPLETE: "logout_complete",
30
31
  CONTACT_PROVIDED: "contact_provided",
31
32
  CHECKOUT_STATUS: "checkout_status",
32
- CHECKOUT_COMPLETE: "checkout_complete"
33
+ CHECKOUT_COMPLETE: "checkout_complete",
34
+ ORDER_TYPE_CHANGED: "order_type_changed"
33
35
  };
34
36
  var EVENT_TYPES = {
35
37
  READY: "ready",
36
38
  AUTHENTICATED: "authenticated",
37
39
  REQUIRES_OTP: "requires_otp",
38
40
  ERROR: "error",
39
- CHANGE: "change"};
41
+ CHANGE: "change",
42
+ ORDER_TYPE_CHANGED: "order_type_changed"
43
+ };
40
44
 
41
45
  // src/ads/identity.ts
42
46
  var COOKIE_NAME = "_cimplify_uid";
@@ -349,15 +353,6 @@ function shellColors(isDark, primaryColor) {
349
353
  primary: primaryColor
350
354
  };
351
355
  }
352
- function labelForOrderType(orderType) {
353
- if (orderType === "dine_in") {
354
- return "Dine In";
355
- }
356
- if (orderType === "pickup") {
357
- return "Pickup";
358
- }
359
- return "Delivery";
360
- }
361
356
  function statusToLabel(status) {
362
357
  if (!status) {
363
358
  return "";
@@ -412,14 +407,19 @@ function CimplifyCheckout({
412
407
  const [errorMessage, setErrorMessage] = useState(null);
413
408
  const [resolvedBusinessId, setResolvedBusinessId] = useState(businessId ?? null);
414
409
  const [resolvedCartId, setResolvedCartId] = useState(cartId ?? null);
415
- const addressMountRef = useRef(null);
416
- const paymentMountRef = useRef(null);
410
+ const checkoutMountRef = useRef(null);
417
411
  const elementsRef = useRef(null);
418
412
  const activeCheckoutRef = useRef(null);
419
413
  const initialAppearanceRef = useRef(appearance);
420
414
  const hasWarnedInlineAppearanceRef = useRef(false);
421
415
  const isMountedRef = useRef(true);
422
416
  const demoRunRef = useRef(0);
417
+ const onCompleteRef = useRef(onComplete);
418
+ const onErrorRef = useRef(onError);
419
+ const onStatusChangeRef = useRef(onStatusChange);
420
+ onCompleteRef.current = onComplete;
421
+ onErrorRef.current = onError;
422
+ onStatusChangeRef.current = onStatusChange;
423
423
  const isDemoCheckout = demoMode ?? client.getPublicKey().trim().length === 0;
424
424
  const isTestMode = client.isTestMode();
425
425
  const primaryColor = appearance?.variables?.primaryColor || "#0a2540";
@@ -428,9 +428,9 @@ function CimplifyCheckout({
428
428
  (nextStatus, context = {}) => {
429
429
  setStatus(nextStatus);
430
430
  setStatusText(context.display_text || "");
431
- onStatusChange?.(nextStatus, context);
431
+ onStatusChangeRef.current?.(nextStatus, context);
432
432
  },
433
- [onStatusChange]
433
+ []
434
434
  );
435
435
  useEffect(() => {
436
436
  if (!resolvedOrderTypes.includes(orderType)) {
@@ -483,7 +483,7 @@ function CimplifyCheckout({
483
483
  setResolvedCartId(null);
484
484
  setErrorMessage(message);
485
485
  setIsInitializing(false);
486
- onError?.({ code: "BUSINESS_ID_REQUIRED", message });
486
+ onErrorRef.current?.({ code: "BUSINESS_ID_REQUIRED", message });
487
487
  }
488
488
  return;
489
489
  }
@@ -498,7 +498,7 @@ function CimplifyCheckout({
498
498
  setResolvedCartId(null);
499
499
  setErrorMessage(message);
500
500
  setIsInitializing(false);
501
- onError?.({ code: "CART_EMPTY", message });
501
+ onErrorRef.current?.({ code: "CART_EMPTY", message });
502
502
  }
503
503
  return;
504
504
  }
@@ -515,7 +515,7 @@ function CimplifyCheckout({
515
515
  return () => {
516
516
  cancelled = true;
517
517
  };
518
- }, [businessId, cartId, client, isDemoCheckout, onError]);
518
+ }, [businessId, cartId, client, isDemoCheckout]);
519
519
  useEffect(() => {
520
520
  return () => {
521
521
  isMountedRef.current = false;
@@ -534,14 +534,19 @@ function CimplifyCheckout({
534
534
  linkUrl
535
535
  });
536
536
  elementsRef.current = elements;
537
- const address = elements.create("address", { mode: "shipping" });
538
- const payment = elements.create("payment");
539
- if (addressMountRef.current) {
540
- address.mount(addressMountRef.current);
541
- }
542
- if (paymentMountRef.current) {
543
- payment.mount(paymentMountRef.current);
537
+ const checkout = elements.create("checkout", {
538
+ orderTypes: resolvedOrderTypes,
539
+ defaultOrderType: resolvedOrderTypes[0]
540
+ });
541
+ if (checkoutMountRef.current) {
542
+ checkout.mount(checkoutMountRef.current);
544
543
  }
544
+ checkout.on("order_type_changed", (data) => {
545
+ const typed = data;
546
+ if (typed.orderType) {
547
+ setOrderType(typed.orderType);
548
+ }
549
+ });
545
550
  return () => {
546
551
  activeCheckoutRef.current?.abort();
547
552
  activeCheckoutRef.current = null;
@@ -554,7 +559,7 @@ function CimplifyCheckout({
554
559
  if (!resolvedCartId && !isInitializing) {
555
560
  const message = "Your cart is empty. Add items before checkout.";
556
561
  setErrorMessage(message);
557
- onError?.({ code: "CART_EMPTY", message });
562
+ onErrorRef.current?.({ code: "CART_EMPTY", message });
558
563
  }
559
564
  return;
560
565
  }
@@ -589,7 +594,7 @@ function CimplifyCheckout({
589
594
  order_number: result.order?.order_number,
590
595
  display_text: statusToLabel("success")
591
596
  });
592
- onComplete(result);
597
+ onCompleteRef.current(result);
593
598
  } finally {
594
599
  if (isMountedRef.current && runId === demoRunRef.current) {
595
600
  setIsSubmitting(false);
@@ -600,7 +605,7 @@ function CimplifyCheckout({
600
605
  if (!elementsRef.current) {
601
606
  const message = "Checkout is still initializing. Please try again.";
602
607
  setErrorMessage(message);
603
- onError?.({ code: "CHECKOUT_NOT_READY", message });
608
+ onErrorRef.current?.({ code: "CHECKOUT_NOT_READY", message });
604
609
  setIsSubmitting(false);
605
610
  return;
606
611
  }
@@ -615,13 +620,13 @@ function CimplifyCheckout({
615
620
  try {
616
621
  const result = await checkout;
617
622
  if (result.success) {
618
- onComplete(result);
623
+ onCompleteRef.current(result);
619
624
  return;
620
625
  }
621
626
  const code = result.error?.code || "CHECKOUT_FAILED";
622
627
  const message = result.error?.message || "Payment failed.";
623
628
  setErrorMessage(message);
624
- onError?.({ code, message });
629
+ onErrorRef.current?.({ code, message });
625
630
  } finally {
626
631
  if (isMountedRef.current) {
627
632
  activeCheckoutRef.current = null;
@@ -637,8 +642,6 @@ function CimplifyCheckout({
637
642
  isInitializing,
638
643
  isSubmitting,
639
644
  locationId,
640
- onComplete,
641
- onError,
642
645
  orderType
643
646
  ]);
644
647
  const colors = shellColors(isDark ?? false, primaryColor);
@@ -662,59 +665,7 @@ function CimplifyCheckout({
662
665
  children: "Test mode - no real charges"
663
666
  }
664
667
  ),
665
- /* @__PURE__ */ jsx("div", { "data-cimplify-section": "payment", children: /* @__PURE__ */ jsx("div", { ref: isDemoCheckout ? void 0 : paymentMountRef }) }),
666
- /* @__PURE__ */ jsxs("div", { "data-cimplify-section": "order-type", style: { marginTop: SPACE.xl }, children: [
667
- /* @__PURE__ */ jsx("p", { style: { fontSize: 13, fontWeight: 500, color: colors.textMuted, marginBottom: SPACE.sm }, children: "Order type" }),
668
- /* @__PURE__ */ jsx(
669
- "div",
670
- {
671
- role: "group",
672
- "aria-label": "Order type",
673
- style: {
674
- display: "inline-flex",
675
- border: `1px solid ${colors.border}`,
676
- borderRadius: 8,
677
- padding: 3,
678
- background: colors.surface
679
- },
680
- children: resolvedOrderTypes.map((type) => {
681
- const active = orderType === type;
682
- return /* @__PURE__ */ jsx(
683
- "button",
684
- {
685
- type: "button",
686
- onClick: () => setOrderType(type),
687
- disabled: isSubmitting,
688
- "data-selected": active ? "true" : "false",
689
- style: {
690
- padding: `${SPACE.sm}px ${SPACE.lg}px`,
691
- borderRadius: 6,
692
- border: "none",
693
- background: active ? primaryColor : "transparent",
694
- color: active ? "#ffffff" : colors.textSecondary,
695
- cursor: isSubmitting ? "not-allowed" : "pointer",
696
- opacity: isSubmitting ? 0.6 : 1,
697
- fontSize: 14,
698
- fontWeight: 500,
699
- transition: "all 150ms ease",
700
- WebkitTapHighlightColor: "transparent"
701
- },
702
- children: labelForOrderType(type)
703
- },
704
- type
705
- );
706
- })
707
- }
708
- )
709
- ] }),
710
- /* @__PURE__ */ jsx(
711
- "div",
712
- {
713
- "data-cimplify-section": "address",
714
- style: { marginTop: SPACE.lg, display: orderType === "delivery" ? "block" : "none" },
715
- children: /* @__PURE__ */ jsx("div", { ref: isDemoCheckout ? void 0 : addressMountRef })
716
- }
717
- ),
668
+ /* @__PURE__ */ jsx("div", { "data-cimplify-section": "checkout", children: /* @__PURE__ */ jsx("div", { ref: isDemoCheckout ? void 0 : checkoutMountRef }) }),
718
669
  /* @__PURE__ */ jsx("div", { style: { marginTop: SPACE.xl }, children: /* @__PURE__ */ jsx(
719
670
  "button",
720
671
  {
@@ -3036,40 +2987,43 @@ var CimplifyElements = class {
3036
2987
  false
3037
2988
  );
3038
2989
  }
3039
- const paymentElement = this.elements.get(ELEMENT_TYPES.PAYMENT);
3040
- if (!paymentElement) {
3041
- console.debug("[cimplify:checkout] BLOCKED: no payment element");
2990
+ const checkoutElement = this.elements.get(ELEMENT_TYPES.CHECKOUT) || this.elements.get(ELEMENT_TYPES.PAYMENT);
2991
+ if (!checkoutElement) {
2992
+ console.debug("[cimplify:checkout] BLOCKED: no checkout element");
3042
2993
  return toCheckoutError(
3043
2994
  "NO_PAYMENT_ELEMENT",
3044
- "Payment element must be mounted before checkout.",
2995
+ "Checkout element must be mounted before checkout.",
3045
2996
  false
3046
2997
  );
3047
2998
  }
3048
- if (!paymentElement.isMounted()) {
3049
- console.debug("[cimplify:checkout] BLOCKED: payment element not mounted");
2999
+ if (!checkoutElement.isMounted()) {
3000
+ console.debug("[cimplify:checkout] BLOCKED: checkout element not mounted");
3050
3001
  return toCheckoutError(
3051
3002
  "PAYMENT_NOT_MOUNTED",
3052
- "Payment element must be mounted before checkout.",
3003
+ "Checkout element must be mounted before checkout.",
3053
3004
  false
3054
3005
  );
3055
3006
  }
3056
- const authElement = this.elements.get(ELEMENT_TYPES.AUTH);
3057
- if (authElement && !this.accessToken) {
3058
- console.debug("[cimplify:checkout] BLOCKED: auth incomplete");
3059
- return toCheckoutError(
3060
- "AUTH_INCOMPLETE",
3061
- "Authentication must complete before checkout can start.",
3062
- true
3063
- );
3064
- }
3065
- const addressElement = this.elements.get(ELEMENT_TYPES.ADDRESS);
3066
- if (addressElement) {
3067
- console.debug("[cimplify:checkout] getting address data...");
3068
- await addressElement.getData();
3069
- console.debug("[cimplify:checkout] address data resolved", this.addressData);
3007
+ const isUnifiedCheckout = this.elements.has(ELEMENT_TYPES.CHECKOUT);
3008
+ if (!isUnifiedCheckout) {
3009
+ const authElement = this.elements.get(ELEMENT_TYPES.AUTH);
3010
+ if (authElement && !this.accessToken) {
3011
+ console.debug("[cimplify:checkout] BLOCKED: auth incomplete");
3012
+ return toCheckoutError(
3013
+ "AUTH_INCOMPLETE",
3014
+ "Authentication must complete before checkout can start.",
3015
+ true
3016
+ );
3017
+ }
3018
+ const addressElement = this.elements.get(ELEMENT_TYPES.ADDRESS);
3019
+ if (addressElement) {
3020
+ console.debug("[cimplify:checkout] getting address data...");
3021
+ await addressElement.getData();
3022
+ console.debug("[cimplify:checkout] address data resolved", this.addressData);
3023
+ }
3024
+ await this.hydrateCustomerData();
3070
3025
  }
3071
- await this.hydrateCustomerData();
3072
- console.debug("[cimplify:checkout] customer data hydrated", { customerData: this.customerData, accountId: this.accountId });
3026
+ console.debug("[cimplify:checkout] customer data hydrated", { customerData: this.customerData, accountId: this.accountId, isUnifiedCheckout });
3073
3027
  const processMessage = {
3074
3028
  type: MESSAGE_TYPES.PROCESS_CHECKOUT,
3075
3029
  cart_id: options.cart_id,
@@ -3080,8 +3034,9 @@ var CimplifyElements = class {
3080
3034
  tip_amount: options.tip_amount,
3081
3035
  pay_currency: options.pay_currency,
3082
3036
  enroll_in_link: options.enroll_in_link ?? true,
3083
- address: this.addressData ?? void 0,
3084
- customer: this.customerData ? {
3037
+ // Unified checkout has its own address/customer state; only pass if available externally
3038
+ address: isUnifiedCheckout ? void 0 : this.addressData ?? void 0,
3039
+ customer: isUnifiedCheckout ? void 0 : this.customerData ? {
3085
3040
  name: this.customerData.name,
3086
3041
  email: this.customerData.email,
3087
3042
  phone: this.customerData.phone
@@ -3090,7 +3045,7 @@ var CimplifyElements = class {
3090
3045
  customer_id: this.customerId ?? void 0
3091
3046
  };
3092
3047
  const timeoutMs = options.timeout_ms ?? 18e4;
3093
- const paymentWindow = paymentElement.getContentWindow();
3048
+ const paymentWindow = checkoutElement.getContentWindow();
3094
3049
  this.checkoutInProgress = true;
3095
3050
  return new Promise((resolve) => {
3096
3051
  let settled = false;
@@ -3128,7 +3083,7 @@ var CimplifyElements = class {
3128
3083
  return;
3129
3084
  }
3130
3085
  if (message.type === MESSAGE_TYPES.LOGOUT_COMPLETE) {
3131
- paymentElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3086
+ checkoutElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3132
3087
  settle(
3133
3088
  toCheckoutError(
3134
3089
  "AUTH_LOST",
@@ -3159,7 +3114,7 @@ var CimplifyElements = class {
3159
3114
  window.addEventListener("message", handleCheckoutMessage);
3160
3115
  }
3161
3116
  abortFn = () => {
3162
- paymentElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3117
+ checkoutElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3163
3118
  settle(
3164
3119
  toCheckoutError(
3165
3120
  "CANCELLED",
@@ -3169,8 +3124,8 @@ var CimplifyElements = class {
3169
3124
  );
3170
3125
  };
3171
3126
  this.activeCheckoutAbort = abortFn;
3172
- console.debug("[cimplify:checkout] sending process_checkout to payment iframe", { cart_id: processMessage.cart_id, order_type: processMessage.order_type, hasCustomer: !!processMessage.customer, hasAddress: !!processMessage.address });
3173
- paymentElement.sendMessage(processMessage);
3127
+ console.debug("[cimplify:checkout] sending process_checkout to checkout iframe", { cart_id: processMessage.cart_id, order_type: processMessage.order_type, hasCustomer: !!processMessage.customer, hasAddress: !!processMessage.address, isUnifiedCheckout });
3128
+ checkoutElement.sendMessage(processMessage);
3174
3129
  console.debug("[cimplify:checkout] postMessage sent, waiting for checkout_complete...");
3175
3130
  });
3176
3131
  })();
@@ -3249,7 +3204,7 @@ var CimplifyElements = class {
3249
3204
  this.customerData = customer;
3250
3205
  this.client.setAccessToken(message.token);
3251
3206
  this.elements.forEach((element, type) => {
3252
- if (type !== ELEMENT_TYPES.AUTH) {
3207
+ if (type !== ELEMENT_TYPES.AUTH && type !== ELEMENT_TYPES.CHECKOUT) {
3253
3208
  element.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token: message.token });
3254
3209
  }
3255
3210
  });
@@ -3439,7 +3394,9 @@ var CimplifyElement = class {
3439
3394
  publicKey,
3440
3395
  demoMode: publicKey.length === 0,
3441
3396
  prefillEmail: this.options.prefillEmail,
3442
- appearance: this.parent.getAppearance()
3397
+ appearance: this.parent.getAppearance(),
3398
+ orderTypes: this.options.orderTypes,
3399
+ defaultOrderType: this.options.defaultOrderType
3443
3400
  });
3444
3401
  const token = this.parent.getAccessToken();
3445
3402
  if (token && this.type !== ELEMENT_TYPES.AUTH) {
@@ -3503,6 +3460,9 @@ var CimplifyElement = class {
3503
3460
  case MESSAGE_TYPES.CONTACT_PROVIDED:
3504
3461
  this.parent._setGuestContact(message.contact, message.contactType);
3505
3462
  break;
3463
+ case MESSAGE_TYPES.ORDER_TYPE_CHANGED:
3464
+ this.emit(EVENT_TYPES.ORDER_TYPE_CHANGED, { orderType: message.orderType });
3465
+ break;
3506
3466
  }
3507
3467
  }
3508
3468
  emit(event, data) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cimplify/sdk",
3
- "version": "0.7.13",
3
+ "version": "0.8.0",
4
4
  "description": "Cimplify Commerce SDK for storefronts",
5
5
  "keywords": [
6
6
  "cimplify",