@cimplify/sdk 0.7.10 → 0.7.12

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
@@ -339,6 +339,18 @@ function Ad({
339
339
  }
340
340
  );
341
341
  }
342
+ var SPACE = { sm: 8, md: 12, lg: 16, xl: 24 };
343
+ function shellColors(isDark, primaryColor) {
344
+ return {
345
+ text: isDark ? "#f4f4f5" : "#1a1a1a",
346
+ textSecondary: isDark ? "#a1a1aa" : "#52525b",
347
+ textMuted: isDark ? "#71717a" : "#a1a1aa",
348
+ border: isDark ? "#27272a" : "#e4e4e7",
349
+ surface: isDark ? "#18181b" : "#fafafa",
350
+ error: "#dc2626",
351
+ primary: primaryColor
352
+ };
353
+ }
342
354
  function labelForOrderType(orderType) {
343
355
  if (orderType === "dine_in") {
344
356
  return "Dine In";
@@ -631,11 +643,12 @@ function CimplifyCheckout({
631
643
  onError,
632
644
  orderType
633
645
  ]);
646
+ const colors = shellColors(isDark ?? false, primaryColor);
634
647
  if (isInitializing) {
635
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { fontSize: "14px", color: "#52525b" }, children: "Preparing checkout..." }) });
648
+ 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..." }) });
636
649
  }
637
650
  if (!isDemoCheckout && (!resolvedBusinessId || !resolvedCartId)) {
638
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { fontSize: "14px", color: "#b91c1c" }, children: errorMessage || "Unable to initialize checkout. Please refresh and try again." }) });
651
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { fontSize: 13, color: colors.error }, children: errorMessage || "Unable to initialize checkout. Please refresh and try again." }) });
639
652
  }
640
653
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-cimplify-checkout": "", children: [
641
654
  isTestMode && !isDemoCheckout && /* @__PURE__ */ jsxRuntime.jsx(
@@ -652,38 +665,47 @@ function CimplifyCheckout({
652
665
  }
653
666
  ),
654
667
  /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-section": "payment", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: isDemoCheckout ? void 0 : paymentMountRef }) }),
655
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-section": "order-type", style: { marginTop: "20px" }, children: [
656
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "13px", fontWeight: 500, color: isDark ? "#a1a1aa" : "#71717a", marginBottom: "8px" }, children: "Order type" }),
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" }),
657
670
  /* @__PURE__ */ jsxRuntime.jsx(
658
671
  "div",
659
672
  {
660
673
  role: "group",
661
674
  "aria-label": "Order type",
662
- style: { display: "flex", gap: "8px", flexWrap: "wrap" },
663
- children: resolvedOrderTypes.map((type) => /* @__PURE__ */ jsxRuntime.jsx(
664
- "button",
665
- {
666
- type: "button",
667
- onClick: () => setOrderType(type),
668
- disabled: isSubmitting,
669
- "data-selected": orderType === type ? "true" : "false",
670
- style: {
671
- padding: "10px 18px",
672
- borderRadius: "8px",
673
- border: orderType === type ? "1px solid transparent" : `1px solid ${isDark ? "#3f3f46" : "#d4d4d8"}`,
674
- background: orderType === type ? primaryColor : "transparent",
675
- color: orderType === type ? "#ffffff" : isDark ? "#e4e4e7" : "#3f3f46",
676
- cursor: isSubmitting ? "not-allowed" : "pointer",
677
- opacity: isSubmitting ? 0.6 : 1,
678
- fontSize: "15px",
679
- fontWeight: 500,
680
- transition: "all 150ms ease",
681
- WebkitTapHighlightColor: "transparent"
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)
682
705
  },
683
- children: labelForOrderType(type)
684
- },
685
- type
686
- ))
706
+ type
707
+ );
708
+ })
687
709
  }
688
710
  )
689
711
  ] }),
@@ -691,11 +713,11 @@ function CimplifyCheckout({
691
713
  "div",
692
714
  {
693
715
  "data-cimplify-section": "address",
694
- style: { marginTop: "16px", display: orderType === "delivery" ? "block" : "none" },
716
+ style: { marginTop: SPACE.lg, display: orderType === "delivery" ? "block" : "none" },
695
717
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: isDemoCheckout ? void 0 : addressMountRef })
696
718
  }
697
719
  ),
698
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "24px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
720
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: SPACE.xl }, children: /* @__PURE__ */ jsxRuntime.jsx(
699
721
  "button",
700
722
  {
701
723
  type: "button",
@@ -703,23 +725,22 @@ function CimplifyCheckout({
703
725
  disabled: isSubmitting,
704
726
  style: {
705
727
  width: "100%",
706
- padding: "14px 16px",
707
- borderRadius: "10px",
728
+ padding: `${SPACE.md}px ${SPACE.lg}px`,
729
+ borderRadius: 8,
708
730
  border: "none",
709
- background: isSubmitting ? "#a1a1aa" : primaryColor,
731
+ background: isSubmitting ? colors.textMuted : primaryColor,
710
732
  color: "#ffffff",
711
733
  cursor: isSubmitting ? "not-allowed" : "pointer",
712
734
  fontWeight: 600,
713
- fontSize: "16px",
714
- boxShadow: isSubmitting ? "none" : "0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px -1px rgba(0,0,0,0.1)",
735
+ fontSize: 16,
715
736
  transition: "all 150ms ease",
716
737
  WebkitTapHighlightColor: "transparent"
717
738
  },
718
739
  children: isSubmitting ? "Processing..." : "Complete Order"
719
740
  }
720
741
  ) }),
721
- status && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { marginTop: "10px", fontSize: "14px", color: "#52525b" }, children: statusText || statusToLabel(status) }),
722
- errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { marginTop: "8px", fontSize: "14px", color: "#b91c1c" }, children: errorMessage })
742
+ status && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.textSecondary }, children: statusText || statusToLabel(status) }),
743
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.error }, children: errorMessage })
723
744
  ] });
724
745
  }
725
746
 
@@ -2948,6 +2969,12 @@ var CimplifyElements = class {
2948
2969
  getElement(type) {
2949
2970
  return this.elements.get(type);
2950
2971
  }
2972
+ _removeElement(type, instance) {
2973
+ const current = this.elements.get(type);
2974
+ if (current === instance) {
2975
+ this.elements.delete(type);
2976
+ }
2977
+ }
2951
2978
  destroy() {
2952
2979
  this.elements.forEach((element) => element.destroy());
2953
2980
  this.elements.clear();
@@ -2986,7 +3013,9 @@ var CimplifyElements = class {
2986
3013
  processCheckout(options) {
2987
3014
  let abortFn = null;
2988
3015
  const task = (async () => {
3016
+ console.debug("[cimplify:checkout] processCheckout called", { cart_id: options.cart_id, order_type: options.order_type, location_id: options.location_id });
2989
3017
  if (this.checkoutInProgress) {
3018
+ console.debug("[cimplify:checkout] BLOCKED: already processing");
2990
3019
  return toCheckoutError(
2991
3020
  "ALREADY_PROCESSING",
2992
3021
  "Checkout is already in progress.",
@@ -2994,6 +3023,7 @@ var CimplifyElements = class {
2994
3023
  );
2995
3024
  }
2996
3025
  if (!options.cart_id) {
3026
+ console.debug("[cimplify:checkout] BLOCKED: no cart_id");
2997
3027
  return toCheckoutError(
2998
3028
  "INVALID_CART",
2999
3029
  "A valid cart is required before checkout can start.",
@@ -3001,6 +3031,7 @@ var CimplifyElements = class {
3001
3031
  );
3002
3032
  }
3003
3033
  if (!options.order_type) {
3034
+ console.debug("[cimplify:checkout] BLOCKED: no order_type");
3004
3035
  return toCheckoutError(
3005
3036
  "ORDER_TYPE_REQUIRED",
3006
3037
  "Order type is required before checkout can start.",
@@ -3009,6 +3040,7 @@ var CimplifyElements = class {
3009
3040
  }
3010
3041
  const paymentElement = this.elements.get(ELEMENT_TYPES.PAYMENT);
3011
3042
  if (!paymentElement) {
3043
+ console.debug("[cimplify:checkout] BLOCKED: no payment element");
3012
3044
  return toCheckoutError(
3013
3045
  "NO_PAYMENT_ELEMENT",
3014
3046
  "Payment element must be mounted before checkout.",
@@ -3016,6 +3048,7 @@ var CimplifyElements = class {
3016
3048
  );
3017
3049
  }
3018
3050
  if (!paymentElement.isMounted()) {
3051
+ console.debug("[cimplify:checkout] BLOCKED: payment element not mounted");
3019
3052
  return toCheckoutError(
3020
3053
  "PAYMENT_NOT_MOUNTED",
3021
3054
  "Payment element must be mounted before checkout.",
@@ -3024,6 +3057,7 @@ var CimplifyElements = class {
3024
3057
  }
3025
3058
  const authElement = this.elements.get(ELEMENT_TYPES.AUTH);
3026
3059
  if (authElement && !this.accessToken) {
3060
+ console.debug("[cimplify:checkout] BLOCKED: auth incomplete");
3027
3061
  return toCheckoutError(
3028
3062
  "AUTH_INCOMPLETE",
3029
3063
  "Authentication must complete before checkout can start.",
@@ -3032,9 +3066,12 @@ var CimplifyElements = class {
3032
3066
  }
3033
3067
  const addressElement = this.elements.get(ELEMENT_TYPES.ADDRESS);
3034
3068
  if (addressElement) {
3069
+ console.debug("[cimplify:checkout] getting address data...");
3035
3070
  await addressElement.getData();
3071
+ console.debug("[cimplify:checkout] address data resolved", this.addressData);
3036
3072
  }
3037
3073
  await this.hydrateCustomerData();
3074
+ console.debug("[cimplify:checkout] customer data hydrated", { customerData: this.customerData, accountId: this.accountId });
3038
3075
  const processMessage = {
3039
3076
  type: MESSAGE_TYPES.PROCESS_CHECKOUT,
3040
3077
  cart_id: options.cart_id,
@@ -3111,6 +3148,7 @@ var CimplifyElements = class {
3111
3148
  return;
3112
3149
  }
3113
3150
  if (message.type === MESSAGE_TYPES.CHECKOUT_COMPLETE) {
3151
+ console.debug("[cimplify:checkout] received checkout_complete", { success: message.success, error: message.error });
3114
3152
  settle({
3115
3153
  success: message.success,
3116
3154
  order: message.order,
@@ -3133,7 +3171,9 @@ var CimplifyElements = class {
3133
3171
  );
3134
3172
  };
3135
3173
  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 });
3136
3175
  paymentElement.sendMessage(processMessage);
3176
+ console.debug("[cimplify:checkout] postMessage sent, waiting for checkout_complete...");
3137
3177
  });
3138
3178
  })();
3139
3179
  const abortable = task;
@@ -3274,6 +3314,7 @@ var CimplifyElement = class {
3274
3314
  this.mounted = false;
3275
3315
  this.eventHandlers = /* @__PURE__ */ new Map();
3276
3316
  this.resolvers = /* @__PURE__ */ new Map();
3317
+ this.listening = false;
3277
3318
  this.type = type;
3278
3319
  this.businessId = businessId;
3279
3320
  this.linkUrl = linkUrl;
@@ -3283,6 +3324,7 @@ var CimplifyElement = class {
3283
3324
  this.boundHandleMessage = this.handleMessage.bind(this);
3284
3325
  if (typeof window !== "undefined") {
3285
3326
  window.addEventListener("message", this.boundHandleMessage);
3327
+ this.listening = true;
3286
3328
  }
3287
3329
  }
3288
3330
  mount(container) {
@@ -3297,6 +3339,10 @@ var CimplifyElement = class {
3297
3339
  }
3298
3340
  this.container = target;
3299
3341
  this.mounted = true;
3342
+ if (!this.listening && typeof window !== "undefined") {
3343
+ window.addEventListener("message", this.boundHandleMessage);
3344
+ this.listening = true;
3345
+ }
3300
3346
  void this.createIframe();
3301
3347
  }
3302
3348
  destroy() {
@@ -3309,9 +3355,11 @@ var CimplifyElement = class {
3309
3355
  this.eventHandlers.clear();
3310
3356
  this.resolvers.forEach((entry) => clearTimeout(entry.timeoutId));
3311
3357
  this.resolvers.clear();
3312
- if (typeof window !== "undefined") {
3358
+ if (this.listening && typeof window !== "undefined") {
3313
3359
  window.removeEventListener("message", this.boundHandleMessage);
3360
+ this.listening = false;
3314
3361
  }
3362
+ this.parent._removeElement(this.type, this);
3315
3363
  }
3316
3364
  on(event, handler) {
3317
3365
  if (!this.eventHandlers.has(event)) {
@@ -6106,17 +6154,36 @@ function AuthElement({
6106
6154
  const containerRef = react.useRef(null);
6107
6155
  const elementRef = react.useRef(null);
6108
6156
  const elements = useElements();
6157
+ const onReadyRef = react.useRef(onReady);
6158
+ const onAuthenticatedRef = react.useRef(onAuthenticated);
6159
+ const onRequiresOtpRef = react.useRef(onRequiresOtp);
6160
+ const onErrorRef = react.useRef(onError);
6161
+ react.useEffect(() => {
6162
+ onReadyRef.current = onReady;
6163
+ onAuthenticatedRef.current = onAuthenticated;
6164
+ onRequiresOtpRef.current = onRequiresOtp;
6165
+ onErrorRef.current = onError;
6166
+ }, [onReady, onAuthenticated, onRequiresOtp, onError]);
6109
6167
  react.useEffect(() => {
6110
6168
  if (!elements || !containerRef.current) return;
6111
6169
  const element = elements.create(ELEMENT_TYPES.AUTH, { prefillEmail });
6112
6170
  elementRef.current = element;
6113
- element.on(EVENT_TYPES.READY, () => onReady?.());
6114
- element.on(EVENT_TYPES.AUTHENTICATED, (data) => onAuthenticated?.(data));
6115
- element.on(EVENT_TYPES.REQUIRES_OTP, (data) => onRequiresOtp?.(data));
6116
- element.on(EVENT_TYPES.ERROR, (data) => onError?.(data));
6171
+ element.on(EVENT_TYPES.READY, () => onReadyRef.current?.());
6172
+ element.on(
6173
+ EVENT_TYPES.AUTHENTICATED,
6174
+ (data) => onAuthenticatedRef.current?.(data)
6175
+ );
6176
+ element.on(
6177
+ EVENT_TYPES.REQUIRES_OTP,
6178
+ (data) => onRequiresOtpRef.current?.(data)
6179
+ );
6180
+ element.on(
6181
+ EVENT_TYPES.ERROR,
6182
+ (data) => onErrorRef.current?.(data)
6183
+ );
6117
6184
  element.mount(containerRef.current);
6118
6185
  return () => element.destroy();
6119
- }, [elements, prefillEmail, onReady, onAuthenticated, onRequiresOtp, onError]);
6186
+ }, [elements, prefillEmail]);
6120
6187
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className, style });
6121
6188
  }
6122
6189
  function AddressElement({
@@ -6130,16 +6197,30 @@ function AddressElement({
6130
6197
  const containerRef = react.useRef(null);
6131
6198
  const elementRef = react.useRef(null);
6132
6199
  const elements = useElements();
6200
+ const onReadyRef = react.useRef(onReady);
6201
+ const onChangeRef = react.useRef(onChange);
6202
+ const onErrorRef = react.useRef(onError);
6203
+ react.useEffect(() => {
6204
+ onReadyRef.current = onReady;
6205
+ onChangeRef.current = onChange;
6206
+ onErrorRef.current = onError;
6207
+ }, [onReady, onChange, onError]);
6133
6208
  react.useEffect(() => {
6134
6209
  if (!elements || !containerRef.current) return;
6135
6210
  const element = elements.create(ELEMENT_TYPES.ADDRESS, { mode });
6136
6211
  elementRef.current = element;
6137
- element.on(EVENT_TYPES.READY, () => onReady?.());
6138
- element.on(EVENT_TYPES.CHANGE, (data) => onChange?.(data));
6139
- element.on(EVENT_TYPES.ERROR, (data) => onError?.(data));
6212
+ element.on(EVENT_TYPES.READY, () => onReadyRef.current?.());
6213
+ element.on(
6214
+ EVENT_TYPES.CHANGE,
6215
+ (data) => onChangeRef.current?.(data)
6216
+ );
6217
+ element.on(
6218
+ EVENT_TYPES.ERROR,
6219
+ (data) => onErrorRef.current?.(data)
6220
+ );
6140
6221
  element.mount(containerRef.current);
6141
6222
  return () => element.destroy();
6142
- }, [elements, mode, onReady, onChange, onError]);
6223
+ }, [elements, mode]);
6143
6224
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className, style });
6144
6225
  }
6145
6226
  function PaymentElement({
@@ -6154,16 +6235,30 @@ function PaymentElement({
6154
6235
  const containerRef = react.useRef(null);
6155
6236
  const elementRef = react.useRef(null);
6156
6237
  const elements = useElements();
6238
+ const onReadyRef = react.useRef(onReady);
6239
+ const onChangeRef = react.useRef(onChange);
6240
+ const onErrorRef = react.useRef(onError);
6241
+ react.useEffect(() => {
6242
+ onReadyRef.current = onReady;
6243
+ onChangeRef.current = onChange;
6244
+ onErrorRef.current = onError;
6245
+ }, [onReady, onChange, onError]);
6157
6246
  react.useEffect(() => {
6158
6247
  if (!elements || !containerRef.current) return;
6159
6248
  const element = elements.create(ELEMENT_TYPES.PAYMENT, { amount, currency });
6160
6249
  elementRef.current = element;
6161
- element.on(EVENT_TYPES.READY, () => onReady?.());
6162
- element.on(EVENT_TYPES.CHANGE, (data) => onChange?.(data));
6163
- element.on(EVENT_TYPES.ERROR, (data) => onError?.(data));
6250
+ element.on(EVENT_TYPES.READY, () => onReadyRef.current?.());
6251
+ element.on(
6252
+ EVENT_TYPES.CHANGE,
6253
+ (data) => onChangeRef.current?.(data)
6254
+ );
6255
+ element.on(
6256
+ EVENT_TYPES.ERROR,
6257
+ (data) => onErrorRef.current?.(data)
6258
+ );
6164
6259
  element.mount(containerRef.current);
6165
6260
  return () => element.destroy();
6166
- }, [elements, amount, currency, onReady, onChange, onError]);
6261
+ }, [elements, amount, currency]);
6167
6262
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className, style });
6168
6263
  }
6169
6264
  function useCheckout() {