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