@cimplify/sdk 0.30.0 → 0.35.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.
Files changed (33) hide show
  1. package/dist/advanced.d.mts +6 -2
  2. package/dist/advanced.d.ts +6 -2
  3. package/dist/advanced.js +21 -21
  4. package/dist/advanced.mjs +2 -2
  5. package/dist/{chunk-WGAVNFEQ.mjs → chunk-2X6P5WJZ.mjs} +117 -32
  6. package/dist/{chunk-E3HC2YAE.mjs → chunk-6TVQQYQ5.mjs} +14 -1
  7. package/dist/{chunk-2CGA3MUW.js → chunk-HKVRUGM6.js} +142 -91
  8. package/dist/{chunk-3J4PPSMI.mjs → chunk-TFHKVQLL.mjs} +123 -72
  9. package/dist/{chunk-PEDLCL72.js → chunk-V2O5AO7I.js} +15 -0
  10. package/dist/{chunk-F47XFKYP.js → chunk-ZYACIPKO.js} +169 -84
  11. package/dist/{index-DaXyvlxk.d.mts → client-CkGlXZRd.d.mts} +122 -72
  12. package/dist/{index-DTdtu4OO.d.ts → client-lvLvB1_K.d.ts} +122 -72
  13. package/dist/{index-D4oNCc37.d.mts → index-CC1JPhB2.d.mts} +2 -2
  14. package/dist/{index-BHVJgyqM.d.ts → index-CPcFayQg.d.ts} +2 -2
  15. package/dist/index.d.mts +6 -5
  16. package/dist/index.d.ts +6 -5
  17. package/dist/index.js +117 -109
  18. package/dist/index.mjs +3 -3
  19. package/dist/{payment-DnU_eLuT.d.mts → payment-DA1i5hhk.d.mts} +13 -12
  20. package/dist/{payment-DnU_eLuT.d.ts → payment-DA1i5hhk.d.ts} +13 -12
  21. package/dist/{price-DUVmRTaz.d.ts → price-Bv4G8aOO.d.ts} +1 -1
  22. package/dist/{price-D-hso3np.d.mts → price-s1XN0edJ.d.mts} +1 -1
  23. package/dist/react.d.mts +21 -5
  24. package/dist/react.d.ts +21 -5
  25. package/dist/react.js +908 -728
  26. package/dist/react.mjs +798 -618
  27. package/dist/styles.css +1 -1
  28. package/dist/utils.d.mts +3 -3
  29. package/dist/utils.d.ts +3 -3
  30. package/dist/utils.js +28 -28
  31. package/dist/utils.mjs +1 -1
  32. package/package.json +8 -8
  33. package/registry/cart-summary.json +1 -1
package/dist/react.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkF47XFKYP_js = require('./chunk-F47XFKYP.js');
5
- var chunk2CGA3MUW_js = require('./chunk-2CGA3MUW.js');
6
- var chunkPEDLCL72_js = require('./chunk-PEDLCL72.js');
4
+ var chunkZYACIPKO_js = require('./chunk-ZYACIPKO.js');
5
+ var chunkHKVRUGM6_js = require('./chunk-HKVRUGM6.js');
6
+ var chunkV2O5AO7I_js = require('./chunk-V2O5AO7I.js');
7
7
  var React10 = require('react');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
  var clsx = require('clsx');
@@ -403,19 +403,114 @@ function transformToCheckoutCart(cart, fx) {
403
403
  currency: fx?.displayCurrency ?? cart.pricing.currency
404
404
  };
405
405
  }
406
- var CART_STORAGE_PREFIX = "cimplify:cart:v2";
407
- var DEFAULT_TAX_RATE = 0;
408
- var cartStores = /* @__PURE__ */ new Map();
409
- function clearAllCartStores() {
410
- for (const [, store] of cartStores) {
411
- void store.clearCart();
406
+
407
+ // src/internal/collection.ts
408
+ function newOpId() {
409
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
410
+ return `op_${crypto.randomUUID()}`;
412
411
  }
413
- cartStores.clear();
412
+ return `op_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
414
413
  }
415
- function toNumber(value) {
416
- if (typeof value === "number" && Number.isFinite(value)) {
417
- return value;
414
+ function createCollection(config) {
415
+ let base = config.initialBase ?? null;
416
+ let ops = [];
417
+ const listeners = /* @__PURE__ */ new Set();
418
+ let cachedView;
419
+ let cachedBaseRef;
420
+ let cachedOpsVersion = -1;
421
+ let opsVersion = 0;
422
+ function notify() {
423
+ for (const listener of listeners) {
424
+ listener();
425
+ }
418
426
  }
427
+ function recompute() {
428
+ if (cachedView !== void 0 && cachedBaseRef === base && cachedOpsVersion === opsVersion) {
429
+ return cachedView;
430
+ }
431
+ const view = config.toView(base, ops);
432
+ cachedView = view;
433
+ cachedBaseRef = base;
434
+ cachedOpsVersion = opsVersion;
435
+ return view;
436
+ }
437
+ return {
438
+ subscribe(listener) {
439
+ listeners.add(listener);
440
+ return () => {
441
+ listeners.delete(listener);
442
+ };
443
+ },
444
+ getSnapshot() {
445
+ return recompute();
446
+ },
447
+ setBase(next) {
448
+ base = next;
449
+ opsVersion++;
450
+ notify();
451
+ },
452
+ enqueue(patch, idempotencyKey) {
453
+ const op = {
454
+ id: newOpId(),
455
+ idempotencyKey,
456
+ patch,
457
+ status: "pending",
458
+ attemptCount: 0,
459
+ enqueuedAt: Date.now()
460
+ };
461
+ ops = [...ops, op];
462
+ opsVersion++;
463
+ notify();
464
+ return op.id;
465
+ },
466
+ confirm(opId, newBase) {
467
+ const idx = ops.findIndex((op) => op.id === opId);
468
+ if (idx === -1 && newBase === void 0) {
469
+ return;
470
+ }
471
+ if (idx !== -1) {
472
+ ops = ops.filter((op) => op.id !== opId);
473
+ }
474
+ if (newBase !== void 0) {
475
+ base = newBase;
476
+ }
477
+ opsVersion++;
478
+ notify();
479
+ },
480
+ fail(opId, error) {
481
+ const idx = ops.findIndex((op) => op.id === opId);
482
+ if (idx === -1) return;
483
+ ops = ops.map(
484
+ (op, i) => i === idx ? {
485
+ ...op,
486
+ status: "failed",
487
+ attemptCount: op.attemptCount + 1,
488
+ lastError: error
489
+ } : op
490
+ );
491
+ opsVersion++;
492
+ notify();
493
+ },
494
+ remove(opId) {
495
+ const next = ops.filter((op) => op.id !== opId);
496
+ if (next.length === ops.length) return;
497
+ ops = next;
498
+ opsVersion++;
499
+ notify();
500
+ },
501
+ getOps() {
502
+ return ops;
503
+ },
504
+ getBase() {
505
+ return base;
506
+ }
507
+ };
508
+ }
509
+
510
+ // src/internal/cart-patches.ts
511
+ var DEFAULT_TAX_RATE = 0;
512
+ function toNumber(value) {
513
+ if (typeof value === "number" && Number.isFinite(value)) return value;
419
514
  if (typeof value === "string") {
420
515
  const parsed = Number.parseFloat(value);
421
516
  return Number.isFinite(parsed) ? parsed : 0;
@@ -426,30 +521,20 @@ function roundMoney(value) {
426
521
  return Math.max(0, Number(value.toFixed(2)));
427
522
  }
428
523
  function clampQuantity(quantity) {
429
- if (!Number.isFinite(quantity)) {
430
- return 1;
431
- }
524
+ if (!Number.isFinite(quantity)) return 1;
432
525
  return Math.max(1, Math.floor(quantity));
433
526
  }
434
527
  function normalizeOptionIds(value) {
435
- if (!value || value.length === 0) {
436
- return void 0;
437
- }
528
+ if (!value || value.length === 0) return void 0;
438
529
  const normalized = Array.from(
439
- new Set(
440
- value.map((entry) => entry.trim()).filter((entry) => entry.length > 0)
441
- )
530
+ new Set(value.map((entry) => entry.trim()).filter((entry) => entry.length > 0))
442
531
  ).sort();
443
532
  return normalized.length > 0 ? normalized : void 0;
444
533
  }
445
534
  function buildLineKey(productId, options) {
446
535
  const parts = [productId];
447
- if (options.locationId) {
448
- parts.push(`l:${options.locationId}`);
449
- }
450
- if (options.variantId) {
451
- parts.push(`v:${options.variantId}`);
452
- }
536
+ if (options.locationId) parts.push(`l:${options.locationId}`);
537
+ if (options.variantId) parts.push(`v:${options.variantId}`);
453
538
  const addOnOptionIds = normalizeOptionIds(options.addOnOptionIds);
454
539
  if (addOnOptionIds && addOnOptionIds.length > 0) {
455
540
  parts.push(`a:${addOnOptionIds.join(",")}`);
@@ -460,41 +545,12 @@ function buildLineKey(productId, options) {
460
545
  if (options.compositeSelections && options.compositeSelections.length > 0) {
461
546
  parts.push(`c:${JSON.stringify(options.compositeSelections)}`);
462
547
  }
463
- if (options.quoteId) {
464
- parts.push(`q:${options.quoteId}`);
465
- }
466
- if (options.scheduledStart) {
467
- parts.push(`ss:${options.scheduledStart}`);
468
- }
469
- if (options.staffId) {
470
- parts.push(`st:${options.staffId}`);
471
- }
472
- if (options.resourceId) {
473
- parts.push(`r:${options.resourceId}`);
474
- }
548
+ if (options.quoteId) parts.push(`q:${options.quoteId}`);
549
+ if (options.scheduledStart) parts.push(`ss:${options.scheduledStart}`);
550
+ if (options.staffId) parts.push(`st:${options.staffId}`);
551
+ if (options.resourceId) parts.push(`r:${options.resourceId}`);
475
552
  return parts.join("|");
476
553
  }
477
- function calculateLineSubtotal(item) {
478
- let unitPrice = chunkPEDLCL72_js.parsePrice(item.product.default_price);
479
- if (item.variant?.price_adjustment) {
480
- unitPrice += chunkPEDLCL72_js.parsePrice(item.variant.price_adjustment);
481
- }
482
- for (const option of item.addOnOptions || []) {
483
- if (option.default_price) {
484
- unitPrice += chunkPEDLCL72_js.parsePrice(option.default_price);
485
- }
486
- }
487
- return roundMoney(unitPrice * item.quantity);
488
- }
489
- function calculateSummary(items) {
490
- const subtotal = roundMoney(items.reduce((sum, item) => sum + calculateLineSubtotal(item), 0));
491
- const tax = roundMoney(subtotal * DEFAULT_TAX_RATE);
492
- return {
493
- subtotal,
494
- tax,
495
- total: roundMoney(subtotal + tax)
496
- };
497
- }
498
554
  function lineKeyFromItem(item) {
499
555
  return buildLineKey(item.product.id, {
500
556
  locationId: item.locationId,
@@ -508,13 +564,103 @@ function lineKeyFromItem(item) {
508
564
  });
509
565
  }
510
566
  function attachInternalItemMetadata(item) {
511
- return {
512
- ...item,
513
- _lineKey: lineKeyFromItem(item)
514
- };
567
+ return { ...item, _lineKey: lineKeyFromItem(item) };
568
+ }
569
+ function calculateLineSubtotal(item) {
570
+ let unitPrice = chunkV2O5AO7I_js.parsePrice(item.product.default_price);
571
+ if (item.variant?.price_adjustment) {
572
+ unitPrice += chunkV2O5AO7I_js.parsePrice(item.variant.price_adjustment);
573
+ }
574
+ for (const option of item.addOnOptions || []) {
575
+ if (option.default_price) unitPrice += chunkV2O5AO7I_js.parsePrice(option.default_price);
576
+ }
577
+ return roundMoney(unitPrice * item.quantity);
578
+ }
579
+ function calculateSummary(items) {
580
+ const subtotal = roundMoney(items.reduce((sum, item) => sum + calculateLineSubtotal(item), 0));
581
+ const tax = roundMoney(subtotal * DEFAULT_TAX_RATE);
582
+ return { subtotal, tax, total: roundMoney(subtotal + tax) };
583
+ }
584
+ function applyCartPatch(base, patch) {
585
+ switch (patch.kind) {
586
+ case "add_item": {
587
+ const existingIndex = base.items.findIndex(
588
+ (item) => (item._lineKey ?? lineKeyFromItem(item)) === patch.lineKey
589
+ );
590
+ const nextItems = [...base.items];
591
+ if (existingIndex >= 0) {
592
+ const existing = nextItems[existingIndex];
593
+ nextItems[existingIndex] = {
594
+ ...existing,
595
+ quantity: existing.quantity + patch.tempItem.quantity
596
+ };
597
+ } else {
598
+ nextItems.push(patch.tempItem);
599
+ }
600
+ return { ...base, items: nextItems, ...calculateSummary(nextItems) };
601
+ }
602
+ case "remove_item": {
603
+ const nextItems = base.items.filter((item) => item.id !== patch.itemId);
604
+ return { ...base, items: nextItems, ...calculateSummary(nextItems) };
605
+ }
606
+ case "set_quantity": {
607
+ const resolved = clampQuantity(patch.quantity);
608
+ const nextItems = base.items.map(
609
+ (item) => item.id === patch.itemId ? { ...item, quantity: resolved } : item
610
+ );
611
+ return { ...base, items: nextItems, ...calculateSummary(nextItems) };
612
+ }
613
+ case "clear": {
614
+ return { ...base, items: [], subtotal: 0, tax: 0, total: 0 };
615
+ }
616
+ }
617
+ }
618
+ function useCollectionStore(collection) {
619
+ return React10.useSyncExternalStore(
620
+ (listener) => collection.subscribe(listener),
621
+ () => collection.getSnapshot(),
622
+ () => collection.getSnapshot()
623
+ );
624
+ }
625
+
626
+ // src/react/hooks/use-cart.ts
627
+ var CART_STORAGE_PREFIX = "cimplify:cart:v3";
628
+ var cartStores = /* @__PURE__ */ new Map();
629
+ var ROLLBACK_VISIBLE_DELAY_MS = 3e3;
630
+ function clearAllCartStores() {
631
+ for (const [, entry] of cartStores) {
632
+ entry.collection.setBase(emptyBase(entry.currency));
633
+ for (const handle of entry.failedOpRemovers) {
634
+ clearTimeout(handle);
635
+ }
636
+ entry.failedOpRemovers.clear();
637
+ if (entry.persistTimer) {
638
+ clearTimeout(entry.persistTimer);
639
+ entry.persistTimer = null;
640
+ }
641
+ }
642
+ cartStores.clear();
643
+ }
644
+ function emptyBase(currency, isLoading = true) {
645
+ return { items: [], subtotal: 0, tax: 0, total: 0, currency, isLoading };
646
+ }
647
+ function advanceBaseWithPatch(entry, patch) {
648
+ const current = entry.collection.getBase() ?? emptyBase(entry.currency, false);
649
+ entry.collection.setBase({ ...applyCartPatch(current, patch), isLoading: false });
650
+ persistBase(entry);
651
+ }
652
+ function buildStoreKey(client, locationId, isDemoMode) {
653
+ return [
654
+ client.getPublicKey() || "__demo__",
655
+ locationId || "__no_location__",
656
+ isDemoMode ? "demo" : "live"
657
+ ].join(":");
658
+ }
659
+ function buildStorageKey(storeKey) {
660
+ return `${CART_STORAGE_PREFIX}:${storeKey}`;
515
661
  }
516
662
  function stripInternalItemMetadata(item) {
517
- const { _lineKey, ...rest } = item;
663
+ const { _lineKey, isOptimistic, ...rest } = item;
518
664
  return rest;
519
665
  }
520
666
  function toProductFromServerItem(item, businessId) {
@@ -533,12 +679,10 @@ function toProductFromServerItem(item, businessId) {
533
679
  is_active: item.is_available,
534
680
  created_at: item.created_at,
535
681
  updated_at: item.updated_at,
536
- metadata: {
537
- from_sdk: true
538
- }
682
+ metadata: { from_sdk: true }
539
683
  };
540
684
  }
541
- function mapServerCart(serverCart) {
685
+ function mapServerCart(serverCart, fallbackCurrency) {
542
686
  const items = serverCart.items.map((item) => {
543
687
  const variant = item.variant_info || item.variant_name ? {
544
688
  id: item.variant_info?.id || item.variant_id || "",
@@ -579,207 +723,219 @@ function mapServerCart(serverCart) {
579
723
  subtotal: roundMoney(toNumber(serverCart.pricing.subtotal)),
580
724
  tax: roundMoney(toNumber(serverCart.pricing.tax_amount)),
581
725
  total: roundMoney(toNumber(serverCart.pricing.total_price)),
582
- currency: serverCart.pricing.currency || "USD"
726
+ currency: serverCart.pricing.currency || fallbackCurrency,
727
+ isLoading: false
583
728
  };
584
729
  }
585
- function buildStorageKey(storeKey) {
586
- return `${CART_STORAGE_PREFIX}:${storeKey}`;
587
- }
588
- function createEmptySnapshot(currency) {
730
+ function annotateOptimisticItems(base, ops) {
731
+ if (ops.length === 0) return base;
732
+ const optimisticIds = /* @__PURE__ */ new Set();
733
+ for (const op of ops) {
734
+ if (op.patch.kind === "add_item") {
735
+ optimisticIds.add(op.patch.tempItem.id);
736
+ }
737
+ }
738
+ if (optimisticIds.size === 0) return base;
589
739
  return {
590
- items: [],
591
- subtotal: 0,
592
- tax: 0,
593
- total: 0,
594
- currency,
595
- isLoading: true
740
+ ...base,
741
+ items: base.items.map(
742
+ (item) => optimisticIds.has(item.id) ? { ...item, isOptimistic: true } : item
743
+ )
596
744
  };
597
745
  }
598
- function createCartStore(params) {
599
- const { client, storeKey, locationId, isDemoMode, currency } = params;
600
- const storageKey = buildStorageKey(storeKey);
601
- const listeners = /* @__PURE__ */ new Set();
602
- let snapshot = createEmptySnapshot(currency);
603
- let initialized = false;
604
- let initializePromise = null;
605
- let persistTimer = null;
606
- function emit() {
607
- listeners.forEach((listener) => {
608
- listener();
609
- });
610
- }
611
- function setSnapshot(nextSnapshot) {
612
- snapshot = nextSnapshot;
613
- schedulePersist();
614
- emit();
615
- }
616
- function updateSnapshot(updater) {
617
- setSnapshot(updater(snapshot));
746
+ function deriveView(base, ops) {
747
+ const start = base ?? emptyBase("USD");
748
+ let folded = start;
749
+ for (const op of ops) {
750
+ folded = applyCartPatch(folded, op.patch);
618
751
  }
619
- function persistSnapshot() {
620
- if (typeof window === "undefined" || !window.localStorage) {
621
- return;
622
- }
752
+ folded = annotateOptimisticItems(folded, ops);
753
+ return {
754
+ ...folded,
755
+ isOptimistic: ops.length > 0,
756
+ pendingOpCount: ops.length
757
+ };
758
+ }
759
+ function persistBase(entry) {
760
+ if (typeof window === "undefined" || !window.localStorage) return;
761
+ if (entry.persistTimer) return;
762
+ entry.persistTimer = setTimeout(() => {
763
+ entry.persistTimer = null;
764
+ if (typeof window === "undefined" || !window.localStorage) return;
765
+ const base = entry.collection.getBase();
766
+ if (!base) return;
623
767
  try {
624
768
  window.localStorage.setItem(
625
- storageKey,
769
+ entry.storageKey,
626
770
  JSON.stringify({
627
- items: snapshot.items.map((item) => stripInternalItemMetadata(item)),
628
- subtotal: snapshot.subtotal,
629
- tax: snapshot.tax,
630
- total: snapshot.total,
631
- currency: snapshot.currency
771
+ items: base.items.map((item) => stripInternalItemMetadata(item)),
772
+ subtotal: base.subtotal,
773
+ tax: base.tax,
774
+ total: base.total,
775
+ currency: base.currency
632
776
  })
633
777
  );
634
778
  } catch {
635
779
  }
780
+ }, 100);
781
+ }
782
+ function hydrateFromStorage(entry) {
783
+ if (typeof window === "undefined" || !window.localStorage) return;
784
+ try {
785
+ const raw = window.localStorage.getItem(entry.storageKey);
786
+ if (!raw) return;
787
+ const parsed = JSON.parse(raw);
788
+ if (!parsed || !Array.isArray(parsed.items)) return;
789
+ const items = parsed.items.map((item) => attachInternalItemMetadata(item));
790
+ entry.collection.setBase({
791
+ items,
792
+ subtotal: toNumber(parsed.subtotal),
793
+ tax: toNumber(parsed.tax),
794
+ total: toNumber(parsed.total),
795
+ currency: typeof parsed.currency === "string" && parsed.currency ? parsed.currency : entry.currency,
796
+ isLoading: !entry.isDemoMode
797
+ });
798
+ } catch {
636
799
  }
637
- function schedulePersist() {
638
- if (persistTimer) {
639
- return;
640
- }
641
- persistTimer = setTimeout(() => {
642
- persistTimer = null;
643
- persistSnapshot();
644
- }, 100);
800
+ }
801
+ async function syncFromServer(entry) {
802
+ if (entry.isDemoMode) {
803
+ const base = entry.collection.getBase() ?? emptyBase(entry.currency);
804
+ entry.collection.setBase({ ...base, isLoading: false });
805
+ return;
645
806
  }
646
- function hydrateFromStorage() {
647
- if (typeof window === "undefined" || !window.localStorage) {
648
- return;
649
- }
650
- try {
651
- const raw = window.localStorage.getItem(storageKey);
652
- if (!raw) {
653
- return;
654
- }
655
- const parsed = JSON.parse(raw);
656
- if (!parsed || !Array.isArray(parsed.items)) {
657
- return;
658
- }
659
- snapshot = {
660
- items: parsed.items.map((item) => attachInternalItemMetadata(item)),
661
- subtotal: toNumber(parsed.subtotal),
662
- tax: toNumber(parsed.tax),
663
- total: toNumber(parsed.total),
664
- currency: typeof parsed.currency === "string" && parsed.currency ? parsed.currency : currency,
665
- isLoading: !isDemoMode
666
- };
667
- emit();
668
- } catch {
669
- }
807
+ if (entry.syncing) return;
808
+ entry.syncing = true;
809
+ try {
810
+ const result = await entry.client.cart.get();
811
+ if (!result.ok) throw result.error;
812
+ entry.collection.setBase(mapServerCart(result.value, entry.currency));
813
+ persistBase(entry);
814
+ } finally {
815
+ entry.syncing = false;
816
+ }
817
+ }
818
+ function emitMutationError(entry, operation, opId, idempotencyKey, error) {
819
+ entry.client.events.emit("mutation:error", {
820
+ service: "cart",
821
+ operation,
822
+ opId,
823
+ idempotencyKey,
824
+ error
825
+ });
826
+ }
827
+ function scheduleFailedOpRemoval(entry, opId) {
828
+ const handle = setTimeout(() => {
829
+ entry.failedOpRemovers.delete(handle);
830
+ entry.collection.remove(opId);
831
+ }, ROLLBACK_VISIBLE_DELAY_MS);
832
+ entry.failedOpRemovers.add(handle);
833
+ }
834
+ function getOrCreateStore(params) {
835
+ const { client, locationId, isDemoMode, currency, optimisticEnabled } = params;
836
+ const storeKey = buildStoreKey(client, locationId, isDemoMode);
837
+ const existing = cartStores.get(storeKey);
838
+ if (existing) {
839
+ existing.optimisticEnabled = optimisticEnabled;
840
+ return existing;
670
841
  }
671
- async function sync() {
672
- if (isDemoMode) {
673
- updateSnapshot((current) => ({
674
- ...current,
675
- isLoading: false
676
- }));
677
- return;
678
- }
679
- updateSnapshot((current) => ({
680
- ...current,
681
- isLoading: true
682
- }));
683
- const result = await client.cart.get();
684
- if (!result.ok) {
685
- updateSnapshot((current) => ({
686
- ...current,
687
- isLoading: false
688
- }));
689
- throw result.error;
690
- }
691
- const next = mapServerCart(result.value);
692
- setSnapshot({
693
- ...next,
694
- isLoading: false
695
- });
842
+ const collection = createCollection({
843
+ applyPatch: applyCartPatch,
844
+ toView: (base, ops) => deriveView(base, ops),
845
+ initialBase: emptyBase(currency)
846
+ });
847
+ const entry = {
848
+ collection,
849
+ client,
850
+ storageKey: buildStorageKey(storeKey),
851
+ locationId,
852
+ currency,
853
+ isDemoMode,
854
+ optimisticEnabled,
855
+ initialized: false,
856
+ initializePromise: null,
857
+ persistTimer: null,
858
+ syncing: false,
859
+ failedOpRemovers: /* @__PURE__ */ new Set()
860
+ };
861
+ cartStores.set(storeKey, entry);
862
+ return entry;
863
+ }
864
+ async function ensureInitialized(entry) {
865
+ if (entry.initialized) {
866
+ if (entry.initializePromise) await entry.initializePromise;
867
+ return;
696
868
  }
697
- async function maybeResolveQuoteId(product, quantity, options) {
698
- if (options.quoteId) {
699
- return options.quoteId;
700
- }
701
- const addOnOptionIds = normalizeOptionIds(options.addOnOptionIds);
702
- const requiresQuote = Boolean(
703
- options.variantId || addOnOptionIds && addOnOptionIds.length > 0 || options.bundleSelections && options.bundleSelections.length > 0 || options.compositeSelections && options.compositeSelections.length > 0
704
- );
705
- if (!requiresQuote || isDemoMode) {
706
- return void 0;
707
- }
708
- const quoteResult = await client.catalogue.fetchQuote({
709
- product_id: product.id,
710
- quantity,
711
- location_id: options.locationId || locationId || void 0,
712
- variant_id: options.variantId,
713
- add_on_option_ids: addOnOptionIds,
714
- bundle_selections: options.bundleSelections,
715
- composite_selections: options.compositeSelections
716
- });
717
- if (!quoteResult.ok) {
718
- throw quoteResult.error;
719
- }
720
- return quoteResult.value.quote_id;
869
+ entry.initialized = true;
870
+ hydrateFromStorage(entry);
871
+ if (entry.isDemoMode) {
872
+ const base = entry.collection.getBase() ?? emptyBase(entry.currency);
873
+ entry.collection.setBase({ ...base, isLoading: false });
874
+ return;
721
875
  }
722
- async function addItem(product, quantity = 1, options = {}) {
723
- const resolvedQuantity = clampQuantity(quantity);
724
- const normalizedOptions = {
725
- ...options,
726
- locationId: options.locationId || locationId || void 0,
727
- addOnOptionIds: normalizeOptionIds(options.addOnOptionIds)
728
- };
729
- const maybeProductWithVariants = product;
730
- if (Array.isArray(maybeProductWithVariants.variants) && maybeProductWithVariants.variants.length > 0 && !normalizedOptions.variantId) {
731
- console.warn(
732
- "[Cimplify] addItem() called without variantId for a product that has variants. Default variant pricing will be used."
733
- );
734
- }
735
- const previousSnapshot = snapshot;
736
- const lineKey = buildLineKey(product.id, normalizedOptions);
737
- const optimisticItem = attachInternalItemMetadata({
738
- id: `tmp_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
739
- product,
740
- quantity: resolvedQuantity,
741
- locationId: normalizedOptions.locationId,
742
- variantId: normalizedOptions.variantId,
743
- variant: normalizedOptions.variant,
744
- quoteId: normalizedOptions.quoteId,
745
- addOnOptionIds: normalizedOptions.addOnOptionIds,
746
- addOnOptions: normalizedOptions.addOnOptions,
747
- bundleSelections: normalizedOptions.bundleSelections,
748
- compositeSelections: normalizedOptions.compositeSelections,
749
- specialInstructions: normalizedOptions.specialInstructions,
750
- scheduledStart: normalizedOptions.scheduledStart,
751
- scheduledEnd: normalizedOptions.scheduledEnd,
752
- staffId: normalizedOptions.staffId
753
- });
754
- updateSnapshot((current) => {
755
- const existingIndex = current.items.findIndex(
756
- (item) => (item._lineKey ?? lineKeyFromItem(item)) === lineKey
757
- );
758
- const nextItems = [...current.items];
759
- if (existingIndex >= 0) {
760
- const existing = nextItems[existingIndex];
761
- nextItems[existingIndex] = {
762
- ...existing,
763
- quantity: existing.quantity + resolvedQuantity
764
- };
765
- } else {
766
- nextItems.push(optimisticItem);
767
- }
768
- const summary = calculateSummary(nextItems);
769
- return {
770
- ...current,
771
- items: nextItems,
772
- subtotal: summary.subtotal,
773
- tax: summary.tax,
774
- total: summary.total
775
- };
776
- });
777
- if (isDemoMode) {
778
- return;
779
- }
780
- try {
781
- const quoteId = await maybeResolveQuoteId(product, resolvedQuantity, normalizedOptions);
782
- const result = await client.cart.addItem({
876
+ entry.initializePromise = syncFromServer(entry).catch(() => {
877
+ const base = entry.collection.getBase() ?? emptyBase(entry.currency);
878
+ entry.collection.setBase({ ...base, isLoading: false });
879
+ });
880
+ await entry.initializePromise;
881
+ entry.initializePromise = null;
882
+ }
883
+ async function maybeResolveQuoteId(entry, product, quantity, options) {
884
+ if (options.quoteId) return options.quoteId;
885
+ const addOnOptionIds = normalizeOptionIds(options.addOnOptionIds);
886
+ const requiresQuote = Boolean(
887
+ options.variantId || addOnOptionIds && addOnOptionIds.length > 0 || options.bundleSelections && options.bundleSelections.length > 0 || options.compositeSelections && options.compositeSelections.length > 0
888
+ );
889
+ if (!requiresQuote || entry.isDemoMode) return void 0;
890
+ const quoteResult = await entry.client.catalogue.fetchQuote({
891
+ product_id: product.id,
892
+ quantity,
893
+ location_id: options.locationId || entry.locationId || void 0,
894
+ variant_id: options.variantId,
895
+ add_on_option_ids: addOnOptionIds,
896
+ bundle_selections: options.bundleSelections,
897
+ composite_selections: options.compositeSelections
898
+ });
899
+ if (!quoteResult.ok) throw quoteResult.error;
900
+ return quoteResult.value.quote_id;
901
+ }
902
+ async function performAddItem(entry, product, quantity, options) {
903
+ const resolvedQuantity = clampQuantity(quantity);
904
+ const normalizedOptions = {
905
+ ...options,
906
+ locationId: options.locationId || entry.locationId || void 0,
907
+ addOnOptionIds: normalizeOptionIds(options.addOnOptionIds)
908
+ };
909
+ const lineKey = buildLineKey(product.id, normalizedOptions);
910
+ const tempItem = attachInternalItemMetadata({
911
+ id: `tmp_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
912
+ product,
913
+ quantity: resolvedQuantity,
914
+ locationId: normalizedOptions.locationId,
915
+ variantId: normalizedOptions.variantId,
916
+ variant: normalizedOptions.variant,
917
+ quoteId: normalizedOptions.quoteId,
918
+ addOnOptionIds: normalizedOptions.addOnOptionIds,
919
+ addOnOptions: normalizedOptions.addOnOptions,
920
+ bundleSelections: normalizedOptions.bundleSelections,
921
+ compositeSelections: normalizedOptions.compositeSelections,
922
+ specialInstructions: normalizedOptions.specialInstructions,
923
+ scheduledStart: normalizedOptions.scheduledStart,
924
+ scheduledEnd: normalizedOptions.scheduledEnd,
925
+ staffId: normalizedOptions.staffId
926
+ });
927
+ const idempotencyKey = `idem_${typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`}`;
928
+ const patch = { kind: "add_item", tempItem, lineKey };
929
+ if (entry.isDemoMode) {
930
+ advanceBaseWithPatch(entry, patch);
931
+ return;
932
+ }
933
+ const useOptimistic = entry.optimisticEnabled;
934
+ const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
935
+ try {
936
+ const quoteId = await maybeResolveQuoteId(entry, product, resolvedQuantity, normalizedOptions);
937
+ const result = await entry.client.cart.addItem(
938
+ {
783
939
  item_id: product.id,
784
940
  quantity: resolvedQuantity,
785
941
  variant_id: normalizedOptions.variantId,
@@ -793,186 +949,103 @@ function createCartStore(params) {
793
949
  staff_id: normalizedOptions.staffId,
794
950
  resource_id: normalizedOptions.resourceId,
795
951
  customer_inputs: normalizedOptions.customerInputs
796
- });
797
- if (!result.ok) {
798
- throw result.error;
799
- }
800
- await sync();
801
- } catch (error) {
802
- snapshot = previousSnapshot;
803
- persistSnapshot();
804
- emit();
805
- throw error;
806
- }
807
- }
808
- async function removeItem(itemId) {
809
- const previousSnapshot = snapshot;
810
- updateSnapshot((current) => {
811
- const nextItems = current.items.filter((item) => item.id !== itemId);
812
- const summary = calculateSummary(nextItems);
813
- return {
814
- ...current,
815
- items: nextItems,
816
- subtotal: summary.subtotal,
817
- tax: summary.tax,
818
- total: summary.total
819
- };
820
- });
821
- if (isDemoMode) {
822
- return;
823
- }
824
- try {
825
- const result = await client.cart.removeItem(itemId);
826
- if (!result.ok) {
827
- throw result.error;
828
- }
829
- await sync();
830
- } catch (error) {
831
- snapshot = previousSnapshot;
832
- persistSnapshot();
833
- emit();
834
- throw error;
835
- }
952
+ },
953
+ { idempotencyKey }
954
+ );
955
+ if (!result.ok) throw result.error;
956
+ await syncFromServer(entry);
957
+ if (opId) entry.collection.confirm(opId);
958
+ } catch (error) {
959
+ const cimplifyError = error;
960
+ if (opId) {
961
+ entry.collection.fail(opId, cimplifyError);
962
+ emitMutationError(entry, "add_item", opId, idempotencyKey, cimplifyError);
963
+ scheduleFailedOpRemoval(entry, opId);
964
+ }
965
+ throw cimplifyError;
966
+ }
967
+ }
968
+ async function performRemoveItem(entry, itemId) {
969
+ const idempotencyKey = "";
970
+ const patch = { kind: "remove_item", itemId };
971
+ if (entry.isDemoMode) {
972
+ advanceBaseWithPatch(entry, patch);
973
+ return;
836
974
  }
837
- async function updateQuantity(itemId, quantity) {
838
- if (quantity <= 0) {
839
- await removeItem(itemId);
840
- return;
841
- }
842
- const resolvedQuantity = clampQuantity(quantity);
843
- const previousSnapshot = snapshot;
844
- updateSnapshot((current) => {
845
- const nextItems = current.items.map(
846
- (item) => item.id === itemId ? {
847
- ...item,
848
- quantity: resolvedQuantity
849
- } : item
850
- );
851
- const summary = calculateSummary(nextItems);
852
- return {
853
- ...current,
854
- items: nextItems,
855
- subtotal: summary.subtotal,
856
- tax: summary.tax,
857
- total: summary.total
858
- };
859
- });
860
- if (isDemoMode) {
861
- return;
862
- }
863
- try {
864
- const result = await client.cart.updateQuantity(itemId, resolvedQuantity);
865
- if (!result.ok) {
866
- throw result.error;
867
- }
868
- await sync();
869
- } catch (error) {
870
- snapshot = previousSnapshot;
871
- persistSnapshot();
872
- emit();
873
- throw error;
874
- }
875
- }
876
- async function clearCart() {
877
- const previousSnapshot = snapshot;
878
- updateSnapshot((current) => ({
879
- ...current,
880
- items: [],
881
- subtotal: 0,
882
- tax: 0,
883
- total: 0
884
- }));
885
- if (isDemoMode) {
886
- return;
887
- }
888
- try {
889
- const result = await client.cart.clear();
890
- if (!result.ok) {
891
- throw result.error;
892
- }
893
- await sync();
894
- } catch (error) {
895
- snapshot = previousSnapshot;
896
- persistSnapshot();
897
- emit();
898
- throw error;
899
- }
975
+ const useOptimistic = entry.optimisticEnabled;
976
+ const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
977
+ try {
978
+ const result = await entry.client.cart.removeItem(itemId);
979
+ if (!result.ok) throw result.error;
980
+ await syncFromServer(entry);
981
+ if (opId) entry.collection.confirm(opId);
982
+ } catch (error) {
983
+ const cimplifyError = error;
984
+ if (opId) {
985
+ entry.collection.fail(opId, cimplifyError);
986
+ emitMutationError(entry, "remove_item", opId, idempotencyKey, cimplifyError);
987
+ scheduleFailedOpRemoval(entry, opId);
988
+ }
989
+ throw cimplifyError;
990
+ }
991
+ }
992
+ async function performUpdateQuantity(entry, itemId, quantity) {
993
+ if (quantity <= 0) {
994
+ return performRemoveItem(entry, itemId);
995
+ }
996
+ const resolved = clampQuantity(quantity);
997
+ const idempotencyKey = "";
998
+ const patch = { kind: "set_quantity", itemId, quantity: resolved };
999
+ if (entry.isDemoMode) {
1000
+ advanceBaseWithPatch(entry, patch);
1001
+ return;
900
1002
  }
901
- async function initialize() {
902
- if (initialized) {
903
- if (initializePromise) {
904
- await initializePromise;
905
- }
906
- return;
907
- }
908
- initialized = true;
909
- hydrateFromStorage();
910
- if (isDemoMode) {
911
- updateSnapshot((current) => ({
912
- ...current,
913
- isLoading: false
914
- }));
915
- return;
916
- }
917
- initializePromise = sync().catch(() => {
918
- updateSnapshot((current) => ({
919
- ...current,
920
- isLoading: false
921
- }));
922
- });
923
- await initializePromise;
924
- initializePromise = null;
1003
+ const useOptimistic = entry.optimisticEnabled;
1004
+ const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
1005
+ try {
1006
+ const result = await entry.client.cart.updateQuantity(itemId, resolved);
1007
+ if (!result.ok) throw result.error;
1008
+ await syncFromServer(entry);
1009
+ if (opId) entry.collection.confirm(opId);
1010
+ } catch (error) {
1011
+ const cimplifyError = error;
1012
+ if (opId) {
1013
+ entry.collection.fail(opId, cimplifyError);
1014
+ emitMutationError(entry, "update_quantity", opId, idempotencyKey, cimplifyError);
1015
+ scheduleFailedOpRemoval(entry, opId);
1016
+ }
1017
+ throw cimplifyError;
1018
+ }
1019
+ }
1020
+ async function performClear(entry) {
1021
+ const idempotencyKey = "";
1022
+ const patch = { kind: "clear" };
1023
+ if (entry.isDemoMode) {
1024
+ advanceBaseWithPatch(entry, patch);
1025
+ return;
925
1026
  }
926
- async function reorder(orderId) {
927
- const result = await client.cart.reorderFromOrder(orderId);
928
- if (!result.ok) {
929
- throw result.error;
1027
+ const useOptimistic = entry.optimisticEnabled;
1028
+ const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
1029
+ try {
1030
+ const result = await entry.client.cart.clear();
1031
+ if (!result.ok) throw result.error;
1032
+ await syncFromServer(entry);
1033
+ if (opId) entry.collection.confirm(opId);
1034
+ } catch (error) {
1035
+ const cimplifyError = error;
1036
+ if (opId) {
1037
+ entry.collection.fail(opId, cimplifyError);
1038
+ emitMutationError(entry, "clear", opId, idempotencyKey, cimplifyError);
1039
+ scheduleFailedOpRemoval(entry, opId);
930
1040
  }
931
- await sync();
932
- return result.value;
1041
+ throw cimplifyError;
933
1042
  }
934
- return {
935
- subscribe(listener) {
936
- listeners.add(listener);
937
- return () => {
938
- listeners.delete(listener);
939
- };
940
- },
941
- getSnapshot() {
942
- return snapshot;
943
- },
944
- initialize,
945
- addItem,
946
- removeItem,
947
- updateQuantity,
948
- clearCart,
949
- sync,
950
- reorder
951
- };
952
1043
  }
953
- function getStoreKey(client, locationId, isDemoMode) {
954
- return [
955
- client.getPublicKey() || "__demo__",
956
- locationId || "__no_location__",
957
- isDemoMode ? "demo" : "live"
958
- ].join(":");
959
- }
960
- function getOrCreateStore(params) {
961
- const { client, locationId, isDemoMode, currency } = params;
962
- const storeKey = getStoreKey(client, locationId, isDemoMode);
963
- const existing = cartStores.get(storeKey);
964
- if (existing) {
965
- return existing;
966
- }
967
- const created = createCartStore({
968
- client,
969
- storeKey,
970
- locationId,
971
- isDemoMode,
972
- currency
973
- });
974
- cartStores.set(storeKey, created);
975
- return created;
1044
+ async function performReorder(entry, orderId) {
1045
+ const result = await entry.client.cart.reorderFromOrder(orderId);
1046
+ if (!result.ok) throw result.error;
1047
+ await syncFromServer(entry);
1048
+ return result.value;
976
1049
  }
977
1050
  function useCart(options = {}) {
978
1051
  const context = useOptionalCimplifyClient();
@@ -983,77 +1056,92 @@ function useCart(options = {}) {
983
1056
  const locationId = options.locationId ?? client.getLocationId();
984
1057
  const isDemoMode = options.demoMode ?? context?.isDemoMode ?? client.getPublicKey().trim().length === 0;
985
1058
  const currency = options.currency ?? context?.currency ?? "USD";
986
- const store = React10.useMemo(
1059
+ const optimisticEnabled = context?.optimistic ?? true;
1060
+ const entry = React10.useMemo(
987
1061
  () => getOrCreateStore({
988
1062
  client,
989
1063
  locationId,
990
1064
  isDemoMode,
991
- currency
1065
+ currency,
1066
+ optimisticEnabled
992
1067
  }),
993
- [client, currency, isDemoMode, locationId]
994
- );
995
- const snapshot = React10.useSyncExternalStore(
996
- store.subscribe,
997
- store.getSnapshot,
998
- store.getSnapshot
1068
+ [client, currency, isDemoMode, locationId, optimisticEnabled]
999
1069
  );
1070
+ const view = useCollectionStore(entry.collection);
1000
1071
  React10.useEffect(() => {
1001
- void store.initialize();
1002
- }, [store]);
1072
+ void ensureInitialized(entry);
1073
+ }, [entry]);
1003
1074
  const addItem = React10.useCallback(
1004
1075
  async (product, quantity, addOptions) => {
1005
- await store.addItem(product, quantity, addOptions);
1076
+ await performAddItem(entry, product, quantity ?? 1, addOptions ?? {});
1006
1077
  },
1007
- [store]
1078
+ [entry]
1008
1079
  );
1009
1080
  const removeItem = React10.useCallback(
1010
1081
  async (itemId) => {
1011
- await store.removeItem(itemId);
1082
+ await performRemoveItem(entry, itemId);
1012
1083
  },
1013
- [store]
1084
+ [entry]
1014
1085
  );
1015
1086
  const updateQuantity = React10.useCallback(
1016
1087
  async (itemId, quantity) => {
1017
- await store.updateQuantity(itemId, quantity);
1088
+ await performUpdateQuantity(entry, itemId, quantity);
1018
1089
  },
1019
- [store]
1090
+ [entry]
1020
1091
  );
1021
1092
  const clearCart = React10.useCallback(async () => {
1022
- await store.clearCart();
1023
- }, [store]);
1093
+ await performClear(entry);
1094
+ }, [entry]);
1024
1095
  const sync = React10.useCallback(async () => {
1025
- try {
1026
- await store.sync();
1027
- } catch (syncError) {
1028
- throw syncError;
1029
- }
1030
- }, [store]);
1096
+ await syncFromServer(entry);
1097
+ }, [entry]);
1031
1098
  const reorder = React10.useCallback(
1032
1099
  async (orderId) => {
1033
- return store.reorder(orderId);
1100
+ return performReorder(entry, orderId);
1034
1101
  },
1035
- [store]
1102
+ [entry]
1036
1103
  );
1037
1104
  const itemCount = React10.useMemo(
1038
- () => snapshot.items.reduce((sum, item) => sum + item.quantity, 0),
1039
- [snapshot.items]
1105
+ () => view.items.reduce((sum, item) => sum + item.quantity, 0),
1106
+ [view.items]
1107
+ );
1108
+ return React10.useMemo(
1109
+ () => ({
1110
+ items: view.items,
1111
+ itemCount,
1112
+ subtotal: view.subtotal,
1113
+ tax: view.tax,
1114
+ total: view.total,
1115
+ currency: view.currency,
1116
+ isEmpty: itemCount === 0,
1117
+ isLoading: view.isLoading,
1118
+ isOptimistic: view.isOptimistic,
1119
+ pendingOpCount: view.pendingOpCount,
1120
+ addItem,
1121
+ removeItem,
1122
+ updateQuantity,
1123
+ clearCart,
1124
+ sync,
1125
+ reorder
1126
+ }),
1127
+ [
1128
+ view.items,
1129
+ itemCount,
1130
+ view.subtotal,
1131
+ view.tax,
1132
+ view.total,
1133
+ view.currency,
1134
+ view.isLoading,
1135
+ view.isOptimistic,
1136
+ view.pendingOpCount,
1137
+ addItem,
1138
+ removeItem,
1139
+ updateQuantity,
1140
+ clearCart,
1141
+ sync,
1142
+ reorder
1143
+ ]
1040
1144
  );
1041
- return React10.useMemo(() => ({
1042
- items: snapshot.items,
1043
- itemCount,
1044
- subtotal: snapshot.subtotal,
1045
- tax: snapshot.tax,
1046
- total: snapshot.total,
1047
- currency: snapshot.currency,
1048
- isEmpty: itemCount === 0,
1049
- isLoading: snapshot.isLoading,
1050
- addItem,
1051
- removeItem,
1052
- updateQuantity,
1053
- clearCart,
1054
- sync,
1055
- reorder
1056
- }), [snapshot.items, itemCount, snapshot.subtotal, snapshot.tax, snapshot.total, snapshot.currency, snapshot.isLoading, addItem, removeItem, updateQuantity, clearCart, sync, reorder]);
1057
1145
  }
1058
1146
  var LOCATION_STORAGE_KEY = "cimplify_location_id";
1059
1147
  var DISPLAY_CURRENCY_STORAGE_KEY = "cimplify_display_currency";
@@ -1063,7 +1151,7 @@ var DEFAULT_COUNTRY = "US";
1063
1151
  function createDefaultClient() {
1064
1152
  const processRef = globalThis.process;
1065
1153
  const envPublicKey = processRef?.env?.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || "";
1066
- return chunkF47XFKYP_js.createCimplifyClient({ publicKey: envPublicKey });
1154
+ return chunkZYACIPKO_js.createCimplifyClient({ publicKey: envPublicKey });
1067
1155
  }
1068
1156
  function getStoredLocationId() {
1069
1157
  if (typeof window === "undefined" || !window.localStorage) {
@@ -1125,7 +1213,8 @@ var CimplifyStateContext = React10.createContext(null);
1125
1213
  function CimplifyProvider({
1126
1214
  client,
1127
1215
  children,
1128
- onLocationChange
1216
+ onLocationChange,
1217
+ optimistic = true
1129
1218
  }) {
1130
1219
  const resolvedClient = React10.useMemo(() => client ?? createDefaultClient(), [client]);
1131
1220
  const onLocationChangeRef = React10.useRef(onLocationChange);
@@ -1146,7 +1235,7 @@ function CimplifyProvider({
1146
1235
  const setDisplayCurrency = React10.useCallback(
1147
1236
  (currency) => {
1148
1237
  const normalized = currency?.trim().toUpperCase() || null;
1149
- if (normalized && !chunkPEDLCL72_js.isSupportedCurrency(normalized)) {
1238
+ if (normalized && !chunkV2O5AO7I_js.isSupportedCurrency(normalized)) {
1150
1239
  return;
1151
1240
  }
1152
1241
  setDisplayCurrencyOverride(normalized);
@@ -1269,7 +1358,8 @@ function CimplifyProvider({
1269
1358
  locations,
1270
1359
  isReady,
1271
1360
  isDemoMode,
1272
- baseCurrency
1361
+ baseCurrency,
1362
+ optimistic
1273
1363
  }),
1274
1364
  [
1275
1365
  resolvedClient,
@@ -1277,7 +1367,8 @@ function CimplifyProvider({
1277
1367
  baseCurrency,
1278
1368
  locations,
1279
1369
  isReady,
1280
- isDemoMode
1370
+ isDemoMode,
1371
+ optimistic
1281
1372
  ]
1282
1373
  );
1283
1374
  const stateContextValue = React10.useMemo(
@@ -1806,7 +1897,7 @@ function Price({ amount, currency, className, prefix }) {
1806
1897
  const resolvedAmount = typeof convertedAmount === "string" ? parseFloat(convertedAmount) || 0 : convertedAmount;
1807
1898
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { className, children: [
1808
1899
  prefix,
1809
- chunkPEDLCL72_js.formatPrice(resolvedAmount, resolvedCurrency)
1900
+ chunkV2O5AO7I_js.formatPrice(resolvedAmount, resolvedCurrency)
1810
1901
  ] });
1811
1902
  }
1812
1903
  function createCachedQuery(config) {
@@ -2813,16 +2904,16 @@ function useProductPrice(input) {
2813
2904
  if (bundleTotalPrice != null) {
2814
2905
  unitPrice = bundleTotalPrice;
2815
2906
  } else if (compositePrice) {
2816
- unitPrice = chunkPEDLCL72_js.parsePrice(compositePrice.final_price);
2907
+ unitPrice = chunkV2O5AO7I_js.parsePrice(compositePrice.final_price);
2817
2908
  } else {
2818
- unitPrice = chunkPEDLCL72_js.parsePrice(product.default_price);
2909
+ unitPrice = chunkV2O5AO7I_js.parsePrice(product.default_price);
2819
2910
  if (variant?.price_adjustment) {
2820
- unitPrice += chunkPEDLCL72_js.parsePrice(variant.price_adjustment);
2911
+ unitPrice += chunkV2O5AO7I_js.parsePrice(variant.price_adjustment);
2821
2912
  }
2822
2913
  if (addOnOptions) {
2823
2914
  for (const option of addOnOptions) {
2824
2915
  if (option.default_price) {
2825
- unitPrice += chunkPEDLCL72_js.parsePrice(option.default_price);
2916
+ unitPrice += chunkV2O5AO7I_js.parsePrice(option.default_price);
2826
2917
  }
2827
2918
  }
2828
2919
  }
@@ -3318,6 +3409,8 @@ function useBootstrap(options = {}) {
3318
3409
  var POLL_INTERVAL_MS = 3e3;
3319
3410
  var POLL_IDLE_INTERVAL_MS = 15e3;
3320
3411
  var IDLE_TIMEOUT_MS = 6e4;
3412
+ var WS_MAX_RECONNECT_ATTEMPTS = 10;
3413
+ var WS_PATH = "/api/v1/support/conversation/ws";
3321
3414
  function useChat(options = {}) {
3322
3415
  const context = useOptionalCimplifyClient();
3323
3416
  const client = options.client ?? context?.client;
@@ -3330,26 +3423,34 @@ function useChat(options = {}) {
3330
3423
  const lastActivityRef = React10.useRef(Date.now());
3331
3424
  const openedRef = React10.useRef(false);
3332
3425
  const messagesRef = React10.useRef([]);
3426
+ const clientRef = React10.useRef(client);
3427
+ const wsRef = React10.useRef(null);
3428
+ const wsReconnectAttemptRef = React10.useRef(0);
3429
+ const wsReconnectTimerRef = React10.useRef(null);
3333
3430
  messagesRef.current = messages;
3431
+ clientRef.current = client;
3334
3432
  const pollInterval = options.pollInterval ?? POLL_INTERVAL_MS;
3335
3433
  const pollIdleInterval = options.pollIdleInterval ?? POLL_IDLE_INTERVAL_MS;
3434
+ const appendMessages = React10.useCallback((incoming) => {
3435
+ setMessages((prev) => {
3436
+ const ids = new Set(prev.map((m) => m.id));
3437
+ const fresh = incoming.filter((m) => !ids.has(m.id));
3438
+ return fresh.length > 0 ? [...prev, ...fresh] : prev;
3439
+ });
3440
+ }, []);
3336
3441
  const pollMessages = React10.useCallback(async () => {
3337
- if (!client) return;
3338
- const isIdle = Date.now() - lastActivityRef.current > IDLE_TIMEOUT_MS;
3339
- if (isIdle) return;
3442
+ const c = clientRef.current;
3443
+ if (!c) return;
3444
+ if (Date.now() - lastActivityRef.current > IDLE_TIMEOUT_MS) return;
3340
3445
  const last = messagesRef.current[messagesRef.current.length - 1];
3341
- const result = await client.support.getMessages({
3446
+ const result = await c.support.getMessages({
3342
3447
  after: last?.created_at,
3343
3448
  limit: 50
3344
3449
  });
3345
3450
  if (result.ok && result.value.length > 0) {
3346
- setMessages((prev) => {
3347
- const ids = new Set(prev.map((m) => m.id));
3348
- const fresh = result.value.filter((m) => !ids.has(m.id));
3349
- return fresh.length > 0 ? [...prev, ...fresh] : prev;
3350
- });
3451
+ appendMessages(result.value);
3351
3452
  }
3352
- }, [client]);
3453
+ }, [appendMessages]);
3353
3454
  const startPolling = React10.useCallback(() => {
3354
3455
  if (pollRef.current) clearInterval(pollRef.current);
3355
3456
  const interval = Date.now() - lastActivityRef.current > IDLE_TIMEOUT_MS ? pollIdleInterval : pollInterval;
@@ -3361,7 +3462,57 @@ function useChat(options = {}) {
3361
3462
  pollRef.current = null;
3362
3463
  }
3363
3464
  }, []);
3364
- React10.useEffect(() => stopPolling, [stopPolling]);
3465
+ const connectWebSocket = React10.useCallback(() => {
3466
+ const c = clientRef.current;
3467
+ if (!c || typeof WebSocket === "undefined") {
3468
+ startPolling();
3469
+ return;
3470
+ }
3471
+ if (wsRef.current) {
3472
+ wsRef.current.close();
3473
+ wsRef.current = null;
3474
+ }
3475
+ const url = c.buildWsUrl(WS_PATH);
3476
+ const ws = new WebSocket(url);
3477
+ ws.onopen = () => {
3478
+ wsReconnectAttemptRef.current = 0;
3479
+ stopPolling();
3480
+ };
3481
+ ws.onmessage = (event) => {
3482
+ try {
3483
+ const envelope = JSON.parse(event.data);
3484
+ if (envelope.type === "message.created" && envelope.data) {
3485
+ appendMessages([envelope.data]);
3486
+ }
3487
+ } catch {
3488
+ }
3489
+ };
3490
+ ws.onclose = () => {
3491
+ wsRef.current = null;
3492
+ if (!openedRef.current) return;
3493
+ pollMessages();
3494
+ if (wsReconnectAttemptRef.current < WS_MAX_RECONNECT_ATTEMPTS) {
3495
+ const attempt = wsReconnectAttemptRef.current++;
3496
+ const delay = Math.min(1e3 * Math.pow(2, attempt) + Math.random() * 500, 3e4);
3497
+ wsReconnectTimerRef.current = setTimeout(connectWebSocket, delay);
3498
+ } else {
3499
+ startPolling();
3500
+ }
3501
+ };
3502
+ ws.onerror = () => {
3503
+ };
3504
+ wsRef.current = ws;
3505
+ }, [appendMessages, startPolling, stopPolling, pollMessages]);
3506
+ React10.useEffect(() => {
3507
+ return () => {
3508
+ if (pollRef.current) clearInterval(pollRef.current);
3509
+ if (wsReconnectTimerRef.current) clearTimeout(wsReconnectTimerRef.current);
3510
+ if (wsRef.current) {
3511
+ wsRef.current.onclose = null;
3512
+ wsRef.current.close();
3513
+ }
3514
+ };
3515
+ }, []);
3365
3516
  const openConversation = React10.useCallback(async () => {
3366
3517
  if (openedRef.current || !client) return;
3367
3518
  openedRef.current = true;
@@ -3371,13 +3522,13 @@ function useChat(options = {}) {
3371
3522
  if (result.ok) {
3372
3523
  setMessages(result.value.messages);
3373
3524
  setConversationOpened(true);
3374
- startPolling();
3525
+ connectWebSocket();
3375
3526
  } else {
3376
3527
  openedRef.current = false;
3377
3528
  setError(result.error);
3378
3529
  }
3379
3530
  setIsLoading(false);
3380
- }, [client, startPolling]);
3531
+ }, [client, connectWebSocket]);
3381
3532
  const send = React10.useCallback(
3382
3533
  async (content) => {
3383
3534
  if (!client || !content.trim()) return;
@@ -3506,19 +3657,19 @@ function AuthElement({
3506
3657
  }, [onReady, onAuthenticated, onRequiresOtp, onError]);
3507
3658
  React10.useEffect(() => {
3508
3659
  if (!elements || !containerRef.current) return;
3509
- const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.AUTH, { prefillEmail });
3660
+ const element = elements.create(chunkHKVRUGM6_js.ELEMENT_TYPES.AUTH, { prefillEmail });
3510
3661
  elementRef.current = element;
3511
- element.on(chunk2CGA3MUW_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3662
+ element.on(chunkHKVRUGM6_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3512
3663
  element.on(
3513
- chunk2CGA3MUW_js.EVENT_TYPES.AUTHENTICATED,
3664
+ chunkHKVRUGM6_js.EVENT_TYPES.AUTHENTICATED,
3514
3665
  (data) => onAuthenticatedRef.current?.(data)
3515
3666
  );
3516
3667
  element.on(
3517
- chunk2CGA3MUW_js.EVENT_TYPES.REQUIRES_OTP,
3668
+ chunkHKVRUGM6_js.EVENT_TYPES.REQUIRES_OTP,
3518
3669
  (data) => onRequiresOtpRef.current?.(data)
3519
3670
  );
3520
3671
  element.on(
3521
- chunk2CGA3MUW_js.EVENT_TYPES.ERROR,
3672
+ chunkHKVRUGM6_js.EVENT_TYPES.ERROR,
3522
3673
  (data) => onErrorRef.current?.(data)
3523
3674
  );
3524
3675
  element.mount(containerRef.current);
@@ -3547,15 +3698,15 @@ function AddressElement({
3547
3698
  }, [onReady, onChange, onError]);
3548
3699
  React10.useEffect(() => {
3549
3700
  if (!elements || !containerRef.current) return;
3550
- const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.ADDRESS, { mode });
3701
+ const element = elements.create(chunkHKVRUGM6_js.ELEMENT_TYPES.ADDRESS, { mode });
3551
3702
  elementRef.current = element;
3552
- element.on(chunk2CGA3MUW_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3703
+ element.on(chunkHKVRUGM6_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3553
3704
  element.on(
3554
- chunk2CGA3MUW_js.EVENT_TYPES.CHANGE,
3705
+ chunkHKVRUGM6_js.EVENT_TYPES.CHANGE,
3555
3706
  (data) => onChangeRef.current?.(data)
3556
3707
  );
3557
3708
  element.on(
3558
- chunk2CGA3MUW_js.EVENT_TYPES.ERROR,
3709
+ chunkHKVRUGM6_js.EVENT_TYPES.ERROR,
3559
3710
  (data) => onErrorRef.current?.(data)
3560
3711
  );
3561
3712
  element.mount(containerRef.current);
@@ -3585,15 +3736,15 @@ function PaymentElement({
3585
3736
  }, [onReady, onChange, onError]);
3586
3737
  React10.useEffect(() => {
3587
3738
  if (!elements || !containerRef.current) return;
3588
- const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
3739
+ const element = elements.create(chunkHKVRUGM6_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
3589
3740
  elementRef.current = element;
3590
- element.on(chunk2CGA3MUW_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3741
+ element.on(chunkHKVRUGM6_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3591
3742
  element.on(
3592
- chunk2CGA3MUW_js.EVENT_TYPES.CHANGE,
3743
+ chunkHKVRUGM6_js.EVENT_TYPES.CHANGE,
3593
3744
  (data) => onChangeRef.current?.(data)
3594
3745
  );
3595
3746
  element.on(
3596
- chunk2CGA3MUW_js.EVENT_TYPES.ERROR,
3747
+ chunkHKVRUGM6_js.EVENT_TYPES.ERROR,
3597
3748
  (data) => onErrorRef.current?.(data)
3598
3749
  );
3599
3750
  element.mount(containerRef.current);
@@ -3749,7 +3900,7 @@ function VariantSelector({
3749
3900
  if (!variants || variants.length <= 1) {
3750
3901
  return null;
3751
3902
  }
3752
- basePrice != null ? chunkPEDLCL72_js.parsePrice(basePrice) : 0;
3903
+ basePrice != null ? chunkV2O5AO7I_js.parsePrice(basePrice) : 0;
3753
3904
  if (variantAxes && variantAxes.length > 0) {
3754
3905
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: variantAxes.map((axis) => {
3755
3906
  const labelId = `${idPrefix}-axis-${axis.id}`;
@@ -3825,7 +3976,7 @@ function VariantSelector({
3825
3976
  className: cn("divide-y divide-border", classNames?.list),
3826
3977
  children: variants.map((variant) => {
3827
3978
  const isSelected = selectedVariantId === variant.id;
3828
- const adjustment = chunkPEDLCL72_js.parsePrice(variant.price_adjustment);
3979
+ const adjustment = chunkV2O5AO7I_js.parsePrice(variant.price_adjustment);
3829
3980
  return /* @__PURE__ */ jsxRuntime.jsxs(
3830
3981
  radio.Radio.Root,
3831
3982
  {
@@ -3853,7 +4004,7 @@ function VariantSelector({
3853
4004
  {
3854
4005
  "data-cimplify-variant-name": true,
3855
4006
  className: cn("flex-1 min-w-0 text-sm", classNames?.name),
3856
- children: chunkF47XFKYP_js.getVariantDisplayName(variant, productName)
4007
+ children: chunkZYACIPKO_js.getVariantDisplayName(variant, productName)
3857
4008
  }
3858
4009
  ),
3859
4010
  /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm text-muted-foreground", classNames?.pricing), children: [
@@ -4091,16 +4242,16 @@ function BundleSelector({
4091
4242
  }, [components, selections, onReady]);
4092
4243
  const totalPrice = React10.useMemo(() => {
4093
4244
  if (pricingType === "fixed" && bundlePrice) {
4094
- return chunkPEDLCL72_js.parsePrice(bundlePrice);
4245
+ return chunkV2O5AO7I_js.parsePrice(bundlePrice);
4095
4246
  }
4096
4247
  const componentsTotal = components.reduce((sum, comp) => {
4097
4248
  return sum + getComponentPrice(comp, variantChoices[comp.id]) * comp.quantity;
4098
4249
  }, 0);
4099
4250
  if (pricingType === "percentage_discount" && discountValue) {
4100
- return componentsTotal * (1 - chunkPEDLCL72_js.parsePrice(discountValue) / 100);
4251
+ return componentsTotal * (1 - chunkV2O5AO7I_js.parsePrice(discountValue) / 100);
4101
4252
  }
4102
4253
  if (pricingType === "fixed_discount" && discountValue) {
4103
- return componentsTotal - chunkPEDLCL72_js.parsePrice(discountValue);
4254
+ return componentsTotal - chunkV2O5AO7I_js.parsePrice(discountValue);
4104
4255
  }
4105
4256
  return componentsTotal;
4106
4257
  }, [components, variantChoices, pricingType, bundlePrice, discountValue]);
@@ -4161,15 +4312,15 @@ function BundleSelector({
4161
4312
  }
4162
4313
  function getComponentPrice(component, selectedVariantId) {
4163
4314
  if (!selectedVariantId || component.available_variants.length === 0) {
4164
- return chunkPEDLCL72_js.parsePrice(component.effective_price);
4315
+ return chunkV2O5AO7I_js.parsePrice(component.effective_price);
4165
4316
  }
4166
4317
  if (selectedVariantId === component.variant_id) {
4167
- return chunkPEDLCL72_js.parsePrice(component.effective_price);
4318
+ return chunkV2O5AO7I_js.parsePrice(component.effective_price);
4168
4319
  }
4169
4320
  const bakedAdj = component.variant_id ? component.available_variants.find((v) => v.id === component.variant_id) : void 0;
4170
4321
  const selectedAdj = component.available_variants.find((v) => v.id === selectedVariantId);
4171
- if (!selectedAdj) return chunkPEDLCL72_js.parsePrice(component.effective_price);
4172
- return chunkPEDLCL72_js.parsePrice(component.effective_price) - chunkPEDLCL72_js.parsePrice(bakedAdj?.price_adjustment ?? "0") + chunkPEDLCL72_js.parsePrice(selectedAdj.price_adjustment);
4322
+ if (!selectedAdj) return chunkV2O5AO7I_js.parsePrice(component.effective_price);
4323
+ return chunkV2O5AO7I_js.parsePrice(component.effective_price) - chunkV2O5AO7I_js.parsePrice(bakedAdj?.price_adjustment ?? "0") + chunkV2O5AO7I_js.parsePrice(selectedAdj.price_adjustment);
4173
4324
  }
4174
4325
  function formatDuration(minutes, unit) {
4175
4326
  if (unit === "hours" || !unit && minutes >= 60 && minutes % 60 === 0) {
@@ -4282,7 +4433,7 @@ function BundleComponentCard({
4282
4433
  className: cn("mt-3 divide-y divide-border", classNames?.variantPicker),
4283
4434
  children: component.available_variants.map((variant) => {
4284
4435
  const isSelected = selectedVariantId === variant.id;
4285
- const adjustment = chunkPEDLCL72_js.parsePrice(variant.price_adjustment);
4436
+ const adjustment = chunkV2O5AO7I_js.parsePrice(variant.price_adjustment);
4286
4437
  return /* @__PURE__ */ jsxRuntime.jsxs(
4287
4438
  radio.Radio.Root,
4288
4439
  {
@@ -4728,7 +4879,7 @@ function CompositeSelector({
4728
4879
  "data-cimplify-composite-summary": true,
4729
4880
  className: cn("border-t border-border pt-4 space-y-1 text-sm", classNames?.summary),
4730
4881
  children: [
4731
- chunkPEDLCL72_js.parsePrice(priceResult.base_price) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
4882
+ chunkV2O5AO7I_js.parsePrice(priceResult.base_price) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
4732
4883
  "div",
4733
4884
  {
4734
4885
  "data-cimplify-composite-summary-line": true,
@@ -4739,7 +4890,7 @@ function CompositeSelector({
4739
4890
  ]
4740
4891
  }
4741
4892
  ),
4742
- chunkPEDLCL72_js.parsePrice(priceResult.components_total) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
4893
+ chunkV2O5AO7I_js.parsePrice(priceResult.components_total) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
4743
4894
  "div",
4744
4895
  {
4745
4896
  "data-cimplify-composite-summary-line": true,
@@ -5035,7 +5186,7 @@ function InputField({
5035
5186
  onFileUpload,
5036
5187
  classNames
5037
5188
  }) {
5038
- const hasPriceAdjustment = field.price_adjustment != null && chunkPEDLCL72_js.parsePrice(field.price_adjustment) > 0;
5189
+ const hasPriceAdjustment = field.price_adjustment != null && chunkV2O5AO7I_js.parsePrice(field.price_adjustment) > 0;
5039
5190
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customer-input": true, "data-field-type": field.field_type, className: classNames?.field, children: [
5040
5191
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
5041
5192
  /* @__PURE__ */ jsxRuntime.jsx("label", { className: cn("text-sm font-semibold", classNames?.label), children: field.name }),
@@ -5070,12 +5221,12 @@ function FieldInput({
5070
5221
  classNames?.input
5071
5222
  );
5072
5223
  switch (field.field_type) {
5073
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Text:
5074
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Url:
5224
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Text:
5225
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Url:
5075
5226
  return /* @__PURE__ */ jsxRuntime.jsx(
5076
5227
  "input",
5077
5228
  {
5078
- type: field.field_type === chunkF47XFKYP_js.INPUT_FIELD_TYPE.Url ? "url" : "text",
5229
+ type: field.field_type === chunkZYACIPKO_js.INPUT_FIELD_TYPE.Url ? "url" : "text",
5079
5230
  value: typeof value === "string" ? value : "",
5080
5231
  onChange: (e) => onValueChange(e.target.value),
5081
5232
  placeholder: field.placeholder,
@@ -5084,7 +5235,7 @@ function FieldInput({
5084
5235
  className: inputClass
5085
5236
  }
5086
5237
  );
5087
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Textarea:
5238
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Textarea:
5088
5239
  return /* @__PURE__ */ jsxRuntime.jsx(
5089
5240
  "textarea",
5090
5241
  {
@@ -5097,7 +5248,7 @@ function FieldInput({
5097
5248
  className: cn(inputClass, "resize-none", classNames?.textarea)
5098
5249
  }
5099
5250
  );
5100
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Number:
5251
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Number:
5101
5252
  return /* @__PURE__ */ jsxRuntime.jsx(
5102
5253
  "input",
5103
5254
  {
@@ -5111,7 +5262,7 @@ function FieldInput({
5111
5262
  className: inputClass
5112
5263
  }
5113
5264
  );
5114
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Select:
5265
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Select:
5115
5266
  return /* @__PURE__ */ jsxRuntime.jsxs(
5116
5267
  "select",
5117
5268
  {
@@ -5125,7 +5276,7 @@ function FieldInput({
5125
5276
  ]
5126
5277
  }
5127
5278
  );
5128
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Radio:
5279
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Radio:
5129
5280
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", classNames?.radioGroup), children: (field.options || []).map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
5130
5281
  "label",
5131
5282
  {
@@ -5150,7 +5301,7 @@ function FieldInput({
5150
5301
  },
5151
5302
  opt
5152
5303
  )) });
5153
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Checkbox:
5304
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Checkbox:
5154
5305
  return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: cn("flex items-center gap-2 text-sm cursor-pointer", classNames?.checkboxLabel), children: [
5155
5306
  /* @__PURE__ */ jsxRuntime.jsx(
5156
5307
  "input",
@@ -5163,7 +5314,7 @@ function FieldInput({
5163
5314
  ),
5164
5315
  field.placeholder || field.name
5165
5316
  ] });
5166
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Color:
5317
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Color:
5167
5318
  return /* @__PURE__ */ jsxRuntime.jsx(
5168
5319
  "input",
5169
5320
  {
@@ -5173,7 +5324,7 @@ function FieldInput({
5173
5324
  className: cn("w-12 h-10 rounded-md border border-input cursor-pointer", classNames?.colorInput)
5174
5325
  }
5175
5326
  );
5176
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Date:
5327
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Date:
5177
5328
  return /* @__PURE__ */ jsxRuntime.jsx(
5178
5329
  "input",
5179
5330
  {
@@ -5184,8 +5335,8 @@ function FieldInput({
5184
5335
  className: inputClass
5185
5336
  }
5186
5337
  );
5187
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.File:
5188
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Image:
5338
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.File:
5339
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Image:
5189
5340
  return /* @__PURE__ */ jsxRuntime.jsx(
5190
5341
  FileUploadInput,
5191
5342
  {
@@ -5196,7 +5347,7 @@ function FieldInput({
5196
5347
  classNames
5197
5348
  }
5198
5349
  );
5199
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Email:
5350
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Email:
5200
5351
  return /* @__PURE__ */ jsxRuntime.jsx(
5201
5352
  "input",
5202
5353
  {
@@ -5208,7 +5359,7 @@ function FieldInput({
5208
5359
  className: inputClass
5209
5360
  }
5210
5361
  );
5211
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.DateTime: {
5362
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.DateTime: {
5212
5363
  const dtLocalValue = typeof value === "string" && value.includes("T") ? value.slice(0, 16) : typeof value === "string" ? value : "";
5213
5364
  return /* @__PURE__ */ jsxRuntime.jsx(
5214
5365
  "input",
@@ -5228,7 +5379,7 @@ function FieldInput({
5228
5379
  }
5229
5380
  );
5230
5381
  }
5231
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Time:
5382
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Time:
5232
5383
  return /* @__PURE__ */ jsxRuntime.jsx(
5233
5384
  "input",
5234
5385
  {
@@ -5239,7 +5390,7 @@ function FieldInput({
5239
5390
  className: inputClass
5240
5391
  }
5241
5392
  );
5242
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.MultiSelect:
5393
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.MultiSelect:
5243
5394
  return /* @__PURE__ */ jsxRuntime.jsx(
5244
5395
  MultiSelectInput,
5245
5396
  {
@@ -5249,7 +5400,7 @@ function FieldInput({
5249
5400
  classNames
5250
5401
  }
5251
5402
  );
5252
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.DateRange:
5403
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.DateRange:
5253
5404
  return /* @__PURE__ */ jsxRuntime.jsx(
5254
5405
  DateRangeInput,
5255
5406
  {
@@ -5260,7 +5411,7 @@ function FieldInput({
5260
5411
  inputClass
5261
5412
  }
5262
5413
  );
5263
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Address:
5414
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Address:
5264
5415
  return /* @__PURE__ */ jsxRuntime.jsx(
5265
5416
  AddressInput,
5266
5417
  {
@@ -5271,7 +5422,7 @@ function FieldInput({
5271
5422
  inputClass
5272
5423
  }
5273
5424
  );
5274
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Location:
5425
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Location:
5275
5426
  return /* @__PURE__ */ jsxRuntime.jsx(
5276
5427
  LocationInput,
5277
5428
  {
@@ -5282,7 +5433,7 @@ function FieldInput({
5282
5433
  inputClass
5283
5434
  }
5284
5435
  );
5285
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Phone:
5436
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Phone:
5286
5437
  return /* @__PURE__ */ jsxRuntime.jsx(
5287
5438
  PhoneInput,
5288
5439
  {
@@ -5293,7 +5444,7 @@ function FieldInput({
5293
5444
  inputClass
5294
5445
  }
5295
5446
  );
5296
- case chunkF47XFKYP_js.INPUT_FIELD_TYPE.Signature:
5447
+ case chunkZYACIPKO_js.INPUT_FIELD_TYPE.Signature:
5297
5448
  return /* @__PURE__ */ jsxRuntime.jsx(
5298
5449
  SignatureInput,
5299
5450
  {
@@ -5326,7 +5477,7 @@ function FileUploadInput({
5326
5477
  const [isUploading, setIsUploading] = React10__default.default.useState(false);
5327
5478
  const fileUrl = typeof value === "string" ? value : void 0;
5328
5479
  const acceptedFormats = field.validation?.accepted_formats;
5329
- const accept = acceptedFormats ? acceptedFormats.map((f) => `.${f}`).join(",") : field.field_type === chunkF47XFKYP_js.INPUT_FIELD_TYPE.Image ? "image/*" : void 0;
5480
+ const accept = acceptedFormats ? acceptedFormats.map((f) => `.${f}`).join(",") : field.field_type === chunkZYACIPKO_js.INPUT_FIELD_TYPE.Image ? "image/*" : void 0;
5330
5481
  const handleFile = async (file) => {
5331
5482
  if (!onFileUpload) return;
5332
5483
  if (field.validation?.max_size_mb) {
@@ -5344,7 +5495,7 @@ function FileUploadInput({
5344
5495
  }
5345
5496
  };
5346
5497
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", classNames?.fileInput), children: fileUrl ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
5347
- field.field_type === chunkF47XFKYP_js.INPUT_FIELD_TYPE.Image && /* @__PURE__ */ jsxRuntime.jsx("img", { src: fileUrl, alt: "Uploaded", className: "w-16 h-16 object-cover rounded-md border border-border" }),
5498
+ field.field_type === chunkZYACIPKO_js.INPUT_FIELD_TYPE.Image && /* @__PURE__ */ jsxRuntime.jsx("img", { src: fileUrl, alt: "Uploaded", className: "w-16 h-16 object-cover rounded-md border border-border" }),
5348
5499
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground truncate", children: fileUrl.split("/").pop() }) }),
5349
5500
  /* @__PURE__ */ jsxRuntime.jsx(
5350
5501
  "button",
@@ -5370,7 +5521,7 @@ function FileUploadInput({
5370
5521
  }
5371
5522
  ),
5372
5523
  isUploading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Uploading..." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5373
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: field.placeholder || `Upload ${field.field_type === chunkF47XFKYP_js.INPUT_FIELD_TYPE.Image ? "image" : "file"}` }),
5524
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: field.placeholder || `Upload ${field.field_type === chunkZYACIPKO_js.INPUT_FIELD_TYPE.Image ? "image" : "file"}` }),
5374
5525
  acceptedFormats && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground/60 mt-1", children: [
5375
5526
  acceptedFormats.map((f) => f.toUpperCase()).join(", "),
5376
5527
  field.validation?.max_size_mb && ` \xB7 Max ${field.validation.max_size_mb}MB`
@@ -5929,18 +6080,18 @@ function ProductCustomizer({
5929
6080
  }, [selectedAddOnOptionIds]);
5930
6081
  const localTotalPrice = React10.useMemo(() => {
5931
6082
  if (isComposite && compositePrice) {
5932
- return chunkPEDLCL72_js.parsePrice(compositePrice.final_price) * quantity;
6083
+ return chunkV2O5AO7I_js.parsePrice(compositePrice.final_price) * quantity;
5933
6084
  }
5934
6085
  if (isBundle && bundleTotalPrice != null) {
5935
6086
  return bundleTotalPrice * quantity;
5936
6087
  }
5937
- let price = chunkPEDLCL72_js.parsePrice(product.default_price);
6088
+ let price = chunkV2O5AO7I_js.parsePrice(product.default_price);
5938
6089
  if (selectedVariant?.price_adjustment) {
5939
- price += chunkPEDLCL72_js.parsePrice(selectedVariant.price_adjustment);
6090
+ price += chunkV2O5AO7I_js.parsePrice(selectedVariant.price_adjustment);
5940
6091
  }
5941
6092
  for (const option of selectedAddOnOptions) {
5942
6093
  if (option.default_price) {
5943
- price += chunkPEDLCL72_js.parsePrice(option.default_price);
6094
+ price += chunkV2O5AO7I_js.parsePrice(option.default_price);
5944
6095
  }
5945
6096
  }
5946
6097
  return price * quantity;
@@ -5989,7 +6140,7 @@ function ProductCustomizer({
5989
6140
  const priceInfo = quote.quoted_total_price_info ?? quote.final_price_info;
5990
6141
  const perUnit = priceInfo.pre_tax_price;
5991
6142
  if (perUnit === void 0 || perUnit === null) return void 0;
5992
- return chunkPEDLCL72_js.parsePrice(perUnit) * quantity;
6143
+ return chunkV2O5AO7I_js.parsePrice(perUnit) * quantity;
5993
6144
  }, [quote, quantity]);
5994
6145
  const displayTotalPrice = quotedTotalPrice ?? localTotalPrice;
5995
6146
  const handleVariantChange = React10.useCallback(
@@ -6111,7 +6262,7 @@ function ProductCustomizer({
6111
6262
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.deposit_amount })
6112
6263
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6113
6264
  "Deposit required: ",
6114
- chunkPEDLCL72_js.parsePrice(product.deposit_amount),
6265
+ chunkV2O5AO7I_js.parsePrice(product.deposit_amount),
6115
6266
  "%"
6116
6267
  ] }) }),
6117
6268
  product.allergies && product.allergies.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-customizer-allergens": true, className: cn("flex flex-wrap gap-1.5", classNames?.allergens), children: product.allergies.map((allergen) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -6172,7 +6323,7 @@ function ProductCustomizer({
6172
6323
  ] })
6173
6324
  ] }),
6174
6325
  product.quantity_pricing && product.quantity_pricing.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer-unit-price": true, className: "text-sm text-muted-foreground text-right shrink-0", children: [
6175
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkPEDLCL72_js.getUnitPriceAtQuantity(product.quantity_pricing, quantity, chunkPEDLCL72_js.parsePrice(product.default_price)), className: "font-medium text-foreground" }),
6326
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkV2O5AO7I_js.getUnitPriceAtQuantity(product.quantity_pricing, quantity, chunkV2O5AO7I_js.parsePrice(product.default_price)), className: "font-medium text-foreground" }),
6176
6327
  " ea."
6177
6328
  ] }),
6178
6329
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6295,85 +6446,94 @@ function CartLineItemRow({
6295
6446
  });
6296
6447
  const hasComposite = item.compositeSelections && item.compositeSelections.length > 0;
6297
6448
  const hasBundle = item.bundleSelections && item.bundleSelections.length > 0;
6298
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item": true, className: classNames?.item, children: [
6299
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item-info": true, children: [
6300
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-name": true, className: classNames?.itemName, children: item.product.name }),
6301
- item.variant && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-variant": true, children: chunkF47XFKYP_js.getVariantDisplayName(item.variant, item.product.name) }),
6302
- item.addOnOptions && item.addOnOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-cart-item-addons": true, children: [
6303
- "+ ",
6304
- item.addOnOptions.map((opt) => opt.name).join(", ")
6305
- ] }),
6306
- (hasComposite || hasBundle) && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-badge": true, children: hasComposite ? "Custom" : "Bundle" }),
6307
- item.specialInstructions && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-instructions": true, className: "text-xs text-muted-foreground", children: item.specialInstructions }),
6308
- item.customerInputs && item.customerInputs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-customer-inputs": true, className: classNames?.customerInputs, children: item.customerInputs.map((input) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-input": true, children: [
6309
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-input-label": true, children: input.field_name }),
6310
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-input-value": true, children: input.field_type === chunkF47XFKYP_js.INPUT_FIELD_TYPE.File || input.field_type === chunkF47XFKYP_js.INPUT_FIELD_TYPE.Image ? String(input.value).split("/").pop() || "Uploaded file" : String(input.value) })
6311
- ] }, input.field_id)) }),
6312
- (item.lineType === "service" || item.product.type === "service") && item.scheduledStart && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-service-info": true, className: classNames?.serviceInfo, children: [
6313
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6314
- "\u{1F4C5}",
6315
- " ",
6316
- new Date(item.scheduledStart).toLocaleDateString(),
6317
- " at ",
6318
- new Date(item.scheduledStart).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
6319
- ] }),
6320
- item.confirmationCode && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6321
- "Confirmation: ",
6322
- item.confirmationCode
6323
- ] }),
6324
- item.serviceStatus && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-status": item.serviceStatus, children: item.serviceStatus })
6325
- ] }),
6326
- (item.lineType === "digital" || item.product.type === "digital") && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-digital-info": true, className: classNames?.digitalInfo, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6327
- "\u26A1",
6328
- " Instant digital delivery"
6329
- ] }) }),
6330
- item.bundleResolved && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-bundle-breakdown": true, className: classNames?.bundleBreakdown, children: item.bundleResolved.selections.map((sel) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-product-type": sel.product_type, children: [
6331
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6332
- sel.quantity,
6333
- "\xD7 ",
6334
- sel.product_name
6335
- ] }),
6336
- sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6337
- " \u2014 ",
6338
- new Date(sel.scheduling.scheduled_start).toLocaleDateString()
6339
- ] }),
6340
- sel.product_type === "digital" && /* @__PURE__ */ jsxRuntime.jsx("span", { children: " \u2014 Digital" })
6341
- ] }, sel.component_id)) }),
6342
- item.compositeResolved && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-composite-breakdown": true, className: classNames?.compositeBreakdown, children: item.compositeResolved.selections.map((sel) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-product-type": sel.product_type, children: [
6343
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6344
- sel.quantity,
6345
- "\xD7 ",
6346
- sel.component_name
6449
+ const isOptimistic = item.isOptimistic === true;
6450
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6451
+ "div",
6452
+ {
6453
+ "data-cimplify-cart-item": true,
6454
+ "data-optimistic": isOptimistic ? "true" : void 0,
6455
+ className: classNames?.item,
6456
+ children: [
6457
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item-info": true, children: [
6458
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-name": true, className: classNames?.itemName, children: item.product.name }),
6459
+ item.variant && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-variant": true, children: chunkZYACIPKO_js.getVariantDisplayName(item.variant, item.product.name) }),
6460
+ item.addOnOptions && item.addOnOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-cart-item-addons": true, children: [
6461
+ "+ ",
6462
+ item.addOnOptions.map((opt) => opt.name).join(", ")
6463
+ ] }),
6464
+ (hasComposite || hasBundle) && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-badge": true, children: hasComposite ? "Custom" : "Bundle" }),
6465
+ item.specialInstructions && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-instructions": true, className: "text-xs text-muted-foreground", children: item.specialInstructions }),
6466
+ item.customerInputs && item.customerInputs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-customer-inputs": true, className: classNames?.customerInputs, children: item.customerInputs.map((input) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-input": true, children: [
6467
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-input-label": true, children: input.field_name }),
6468
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-input-value": true, children: input.field_type === chunkZYACIPKO_js.INPUT_FIELD_TYPE.File || input.field_type === chunkZYACIPKO_js.INPUT_FIELD_TYPE.Image ? String(input.value).split("/").pop() || "Uploaded file" : String(input.value) })
6469
+ ] }, input.field_id)) }),
6470
+ (item.lineType === "service" || item.product.type === "service") && item.scheduledStart && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-service-info": true, className: classNames?.serviceInfo, children: [
6471
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6472
+ "\u{1F4C5}",
6473
+ " ",
6474
+ new Date(item.scheduledStart).toLocaleDateString(),
6475
+ " at ",
6476
+ new Date(item.scheduledStart).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
6477
+ ] }),
6478
+ item.confirmationCode && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6479
+ "Confirmation: ",
6480
+ item.confirmationCode
6481
+ ] }),
6482
+ item.serviceStatus && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-status": item.serviceStatus, children: item.serviceStatus })
6483
+ ] }),
6484
+ (item.lineType === "digital" || item.product.type === "digital") && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-digital-info": true, className: classNames?.digitalInfo, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6485
+ "\u26A1",
6486
+ " Instant digital delivery"
6487
+ ] }) }),
6488
+ item.bundleResolved && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-bundle-breakdown": true, className: classNames?.bundleBreakdown, children: item.bundleResolved.selections.map((sel) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-product-type": sel.product_type, children: [
6489
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6490
+ sel.quantity,
6491
+ "\xD7 ",
6492
+ sel.product_name
6493
+ ] }),
6494
+ sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6495
+ " \u2014 ",
6496
+ new Date(sel.scheduling.scheduled_start).toLocaleDateString()
6497
+ ] }),
6498
+ sel.product_type === "digital" && /* @__PURE__ */ jsxRuntime.jsx("span", { children: " \u2014 Digital" })
6499
+ ] }, sel.component_id)) }),
6500
+ item.compositeResolved && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-composite-breakdown": true, className: classNames?.compositeBreakdown, children: item.compositeResolved.selections.map((sel) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-product-type": sel.product_type, children: [
6501
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6502
+ sel.quantity,
6503
+ "\xD7 ",
6504
+ sel.component_name
6505
+ ] }),
6506
+ sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6507
+ " \u2014 ",
6508
+ new Date(sel.scheduling.scheduled_start).toLocaleDateString()
6509
+ ] })
6510
+ ] }, sel.component_id)) }),
6511
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: unitPrice, className: classNames?.itemPrice })
6347
6512
  ] }),
6348
- sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6349
- " \u2014 ",
6350
- new Date(sel.scheduling.scheduled_start).toLocaleDateString()
6513
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item-controls": true, className: classNames?.quantity, children: [
6514
+ /* @__PURE__ */ jsxRuntime.jsx(
6515
+ QuantitySelector,
6516
+ {
6517
+ value: item.quantity,
6518
+ onChange: (qty) => onQuantityChange(item.id, qty),
6519
+ min: 0
6520
+ }
6521
+ ),
6522
+ /* @__PURE__ */ jsxRuntime.jsx(
6523
+ "button",
6524
+ {
6525
+ type: "button",
6526
+ onClick: () => onRemove(item.id),
6527
+ "data-cimplify-cart-item-remove": true,
6528
+ className: classNames?.removeButton,
6529
+ "aria-label": `Remove ${item.product.name}`,
6530
+ children: "Remove"
6531
+ }
6532
+ )
6351
6533
  ] })
6352
- ] }, sel.component_id)) }),
6353
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: unitPrice, className: classNames?.itemPrice })
6354
- ] }),
6355
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item-controls": true, className: classNames?.quantity, children: [
6356
- /* @__PURE__ */ jsxRuntime.jsx(
6357
- QuantitySelector,
6358
- {
6359
- value: item.quantity,
6360
- onChange: (qty) => onQuantityChange(item.id, qty),
6361
- min: 0
6362
- }
6363
- ),
6364
- /* @__PURE__ */ jsxRuntime.jsx(
6365
- "button",
6366
- {
6367
- type: "button",
6368
- onClick: () => onRemove(item.id),
6369
- "data-cimplify-cart-item-remove": true,
6370
- className: classNames?.removeButton,
6371
- "aria-label": `Remove ${item.product.name}`,
6372
- children: "Remove"
6373
- }
6374
- )
6375
- ] })
6376
- ] });
6534
+ ]
6535
+ }
6536
+ );
6377
6537
  }
6378
6538
  function CartSummary({
6379
6539
  cart: serverCart,
@@ -6384,7 +6544,18 @@ function CartSummary({
6384
6544
  className,
6385
6545
  classNames
6386
6546
  }) {
6387
- const { items, itemCount, subtotal, tax, total, isEmpty, removeItem, updateQuantity } = useCart();
6547
+ const {
6548
+ items,
6549
+ itemCount,
6550
+ subtotal,
6551
+ tax,
6552
+ total,
6553
+ isEmpty,
6554
+ isOptimistic,
6555
+ pendingOpCount,
6556
+ removeItem,
6557
+ updateQuantity
6558
+ } = useCart();
6388
6559
  const deliveryFee = serverCart?.delivery_fee;
6389
6560
  const serviceCharge = serverCart?.service_charge;
6390
6561
  const totalDiscounts = serverCart?.total_discounts;
@@ -6402,60 +6573,69 @@ function CartSummary({
6402
6573
  void updateQuantity(itemId, qty);
6403
6574
  }
6404
6575
  };
6405
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-summary": true, className: cn(className, classNames?.root), children: isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: emptyMessage }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6406
- /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-items": true, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
6407
- CartLineItemRow,
6408
- {
6409
- item,
6410
- onRemove: handleRemove,
6411
- onQuantityChange: handleQuantityChange,
6412
- classNames
6413
- },
6414
- item.id
6415
- )) }),
6416
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-totals": true, className: classNames?.totals, children: [
6417
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-subtotal": true, className: classNames?.subtotal, children: [
6418
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6419
- "Subtotal (",
6420
- itemCount,
6421
- " ",
6422
- itemCount === 1 ? "item" : "items",
6423
- ")"
6576
+ return /* @__PURE__ */ jsxRuntime.jsx(
6577
+ "div",
6578
+ {
6579
+ "data-cimplify-cart-summary": true,
6580
+ "data-optimistic": isOptimistic ? "true" : void 0,
6581
+ "data-pending-ops": pendingOpCount > 0 ? pendingOpCount : void 0,
6582
+ className: cn(className, classNames?.root),
6583
+ children: isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: emptyMessage }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6584
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-items": true, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
6585
+ CartLineItemRow,
6586
+ {
6587
+ item,
6588
+ onRemove: handleRemove,
6589
+ onQuantityChange: handleQuantityChange,
6590
+ classNames
6591
+ },
6592
+ item.id
6593
+ )) }),
6594
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-totals": true, className: classNames?.totals, children: [
6595
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-subtotal": true, className: classNames?.subtotal, children: [
6596
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6597
+ "Subtotal (",
6598
+ itemCount,
6599
+ " ",
6600
+ itemCount === 1 ? "item" : "items",
6601
+ ")"
6602
+ ] }),
6603
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: subtotal })
6604
+ ] }),
6605
+ totalDiscounts != null && chunkV2O5AO7I_js.parsePrice(totalDiscounts) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-discount": true, className: classNames?.discount, children: [
6606
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Discount" }),
6607
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: totalDiscounts, prefix: "-" })
6608
+ ] }),
6609
+ deliveryFee != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-delivery-fee": true, className: classNames?.deliveryFee, children: [
6610
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delivery fee" }),
6611
+ chunkV2O5AO7I_js.parsePrice(deliveryFee) > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: deliveryFee }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Free delivery" })
6612
+ ] }),
6613
+ serviceCharge != null && chunkV2O5AO7I_js.parsePrice(serviceCharge) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-service-charge": true, className: classNames?.serviceCharge, children: [
6614
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Service charge" }),
6615
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: serviceCharge })
6616
+ ] }),
6617
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-tax": true, className: classNames?.tax, children: [
6618
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Tax" }),
6619
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: tax })
6620
+ ] }),
6621
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-total": true, className: classNames?.total, children: [
6622
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Total" }),
6623
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: total })
6624
+ ] })
6424
6625
  ] }),
6425
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: subtotal })
6426
- ] }),
6427
- totalDiscounts != null && chunkPEDLCL72_js.parsePrice(totalDiscounts) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-discount": true, className: classNames?.discount, children: [
6428
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Discount" }),
6429
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: totalDiscounts, prefix: "-" })
6430
- ] }),
6431
- deliveryFee != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-delivery-fee": true, className: classNames?.deliveryFee, children: [
6432
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delivery fee" }),
6433
- chunkPEDLCL72_js.parsePrice(deliveryFee) > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: deliveryFee }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Free delivery" })
6434
- ] }),
6435
- serviceCharge != null && chunkPEDLCL72_js.parsePrice(serviceCharge) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-service-charge": true, className: classNames?.serviceCharge, children: [
6436
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Service charge" }),
6437
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: serviceCharge })
6438
- ] }),
6439
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-tax": true, className: classNames?.tax, children: [
6440
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Tax" }),
6441
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: tax })
6442
- ] }),
6443
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-total": true, className: classNames?.total, children: [
6444
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Total" }),
6445
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: total })
6626
+ onCheckout && /* @__PURE__ */ jsxRuntime.jsx(
6627
+ "button",
6628
+ {
6629
+ type: "button",
6630
+ onClick: onCheckout,
6631
+ "data-cimplify-cart-checkout": true,
6632
+ className: classNames?.checkout,
6633
+ children: "Proceed to Checkout"
6634
+ }
6635
+ )
6446
6636
  ] })
6447
- ] }),
6448
- onCheckout && /* @__PURE__ */ jsxRuntime.jsx(
6449
- "button",
6450
- {
6451
- type: "button",
6452
- onClick: onCheckout,
6453
- "data-cimplify-cart-checkout": true,
6454
- className: classNames?.checkout,
6455
- children: "Proceed to Checkout"
6456
- }
6457
- )
6458
- ] }) });
6637
+ }
6638
+ );
6459
6639
  }
6460
6640
  function AvailabilityBadge({
6461
6641
  product,
@@ -6515,16 +6695,16 @@ function SaleBadge({
6515
6695
  className,
6516
6696
  classNames
6517
6697
  }) {
6518
- const onSale = chunkPEDLCL72_js.isOnSale(product);
6698
+ const onSale = chunkV2O5AO7I_js.isOnSale(product);
6519
6699
  const hasDeal = dealInfo !== void 0;
6520
6700
  if (!hasDeal && !onSale && !label) {
6521
6701
  return null;
6522
6702
  }
6523
6703
  let percentage = null;
6524
6704
  if (hasDeal && dealInfo.benefit_type === "percentage") {
6525
- percentage = chunkPEDLCL72_js.parsePrice(dealInfo.value);
6705
+ percentage = chunkV2O5AO7I_js.parsePrice(dealInfo.value);
6526
6706
  } else if (onSale) {
6527
- percentage = chunkPEDLCL72_js.getDiscountPercentage(product);
6707
+ percentage = chunkV2O5AO7I_js.getDiscountPercentage(product);
6528
6708
  }
6529
6709
  const badgeText = label ?? dealInfo?.label ?? (percentage != null && percentage > 0 ? `${percentage}% off` : null);
6530
6710
  if (!badgeText) {
@@ -6543,7 +6723,7 @@ function SaleBadge({
6543
6723
  "%"
6544
6724
  ] }),
6545
6725
  /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-sale-label": true, className: classNames?.label, children: badgeText }),
6546
- showOriginalPrice && onSale && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-sale-original-price": true, className: classNames?.originalPrice, children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkPEDLCL72_js.getBasePrice(product) }) })
6726
+ showOriginalPrice && onSale && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-sale-original-price": true, className: classNames?.originalPrice, children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkV2O5AO7I_js.getBasePrice(product) }) })
6547
6727
  ]
6548
6728
  }
6549
6729
  );
@@ -6786,8 +6966,8 @@ function SoldOutOverlay() {
6786
6966
  );
6787
6967
  }
6788
6968
  function SaleBadge2({ product }) {
6789
- if (!chunkPEDLCL72_js.isOnSale(product)) return null;
6790
- const pct = chunkPEDLCL72_js.getDiscountPercentage(product);
6969
+ if (!chunkV2O5AO7I_js.isOnSale(product)) return null;
6970
+ const pct = chunkV2O5AO7I_js.getDiscountPercentage(product);
6791
6971
  if (!pct || pct <= 0) return null;
6792
6972
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-card-sale-badge": true, className: "inline-flex items-center text-[11px] font-semibold tracking-wide bg-destructive text-destructive-foreground px-2 py-0.5 rounded-md", children: [
6793
6973
  "-",
@@ -6827,7 +7007,7 @@ function FoodProductCard({
6827
7007
  const tags = product.tags || [];
6828
7008
  const isSignature = product.metadata?.is_signature === true;
6829
7009
  const isNew = product.metadata?.is_new === true;
6830
- const isComposite = product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Composite;
7010
+ const isComposite = product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Composite;
6831
7011
  return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
6832
7012
  /* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
6833
7013
  isSignature && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 left-3 inline-flex items-center gap-1 text-[11px] font-semibold tracking-wide bg-amber-50 text-amber-700 border border-amber-200/60 px-2 py-0.5 rounded-md", children: [
@@ -6880,7 +7060,7 @@ function RetailProductCard({
6880
7060
  }) {
6881
7061
  const image = product.image_url || product.images?.[0] || "";
6882
7062
  const outOfStock = product.inventory_status?.in_stock === false;
6883
- const onSale = chunkPEDLCL72_js.isOnSale(product);
7063
+ const onSale = chunkV2O5AO7I_js.isOnSale(product);
6884
7064
  const swatches = getColorSwatches(product);
6885
7065
  return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, disabled: outOfStock, className, children: [
6886
7066
  outOfStock && /* @__PURE__ */ jsxRuntime.jsx(SoldOutOverlay, {}),
@@ -6898,7 +7078,7 @@ function RetailProductCard({
6898
7078
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[14.5px] font-semibold text-foreground leading-snug tracking-tight mt-1 truncate", children: product.name }),
6899
7079
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
6900
7080
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-sm font-bold" }),
6901
- onSale && /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkPEDLCL72_js.getBasePrice(product), className: "text-xs text-muted-foreground line-through" })
7081
+ onSale && /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkV2O5AO7I_js.getBasePrice(product), className: "text-xs text-muted-foreground line-through" })
6902
7082
  ] }),
6903
7083
  swatches.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1.5 mt-2.5", children: swatches.map((name) => /* @__PURE__ */ jsxRuntime.jsx(
6904
7084
  "span",
@@ -6915,9 +7095,9 @@ function RetailProductCard({
6915
7095
  function PriceRange({ product, currency, className }) {
6916
7096
  const context = useOptionalCimplify();
6917
7097
  const resolvedCurrency = currency ?? context?.displayCurrency ?? "USD";
6918
- const range = chunkPEDLCL72_js.getPriceRange(product);
7098
+ const range = chunkV2O5AO7I_js.getPriceRange(product);
6919
7099
  if (!range) return null;
6920
- return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-price-range": true, className, children: chunkPEDLCL72_js.formatPriceRange(range.min, range.max, resolvedCurrency) });
7100
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-price-range": true, className, children: chunkV2O5AO7I_js.formatPriceRange(range.min, range.max, resolvedCurrency) });
6921
7101
  }
6922
7102
  function WholesaleProductCard({
6923
7103
  product,
@@ -7006,8 +7186,8 @@ function BundleProductCard({
7006
7186
  const image = product.image_url || product.images?.[0] || "";
7007
7187
  const components = product.components || [];
7008
7188
  const componentCount = components.length;
7009
- const onSale = chunkPEDLCL72_js.isOnSale(product);
7010
- const discount = chunkPEDLCL72_js.getDiscountPercentage(product);
7189
+ const onSale = chunkV2O5AO7I_js.isOnSale(product);
7190
+ const discount = chunkV2O5AO7I_js.getDiscountPercentage(product);
7011
7191
  const hasVariantChoice = components.some((c) => c.allow_variant_choice);
7012
7192
  return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
7013
7193
  /* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
@@ -7034,7 +7214,7 @@ function BundleProductCard({
7034
7214
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2.5", children: [
7035
7215
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-sm font-bold" }),
7036
7216
  onSale && product.bundle_price && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7037
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkPEDLCL72_js.getBasePrice(product), className: "text-xs text-muted-foreground line-through" }),
7217
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkV2O5AO7I_js.getBasePrice(product), className: "text-xs text-muted-foreground line-through" }),
7038
7218
  discount != null && discount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-semibold text-emerald-600", children: [
7039
7219
  "Save ",
7040
7220
  discount,
@@ -7580,26 +7760,26 @@ var BUILT_IN_CARDS = {
7580
7760
  ["composite" /* Composite */]: CompositeProductCard,
7581
7761
  ["subscription" /* Subscription */]: SubscriptionCard
7582
7762
  };
7583
- var RENTAL_UNITS = /* @__PURE__ */ new Set([chunkF47XFKYP_js.DURATION_UNIT.Days, chunkF47XFKYP_js.DURATION_UNIT.Hours]);
7584
- var LEASE_UNITS = /* @__PURE__ */ new Set([chunkF47XFKYP_js.DURATION_UNIT.Weeks, chunkF47XFKYP_js.DURATION_UNIT.Months, chunkF47XFKYP_js.DURATION_UNIT.Years]);
7763
+ var RENTAL_UNITS = /* @__PURE__ */ new Set([chunkZYACIPKO_js.DURATION_UNIT.Days, chunkZYACIPKO_js.DURATION_UNIT.Hours]);
7764
+ var LEASE_UNITS = /* @__PURE__ */ new Set([chunkZYACIPKO_js.DURATION_UNIT.Weeks, chunkZYACIPKO_js.DURATION_UNIT.Months, chunkZYACIPKO_js.DURATION_UNIT.Years]);
7585
7765
  function resolveCardVariant(product) {
7586
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Bundle) {
7766
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Bundle) {
7587
7767
  return "bundle" /* Bundle */;
7588
7768
  }
7589
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Composite) {
7769
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Composite) {
7590
7770
  return "composite" /* Composite */;
7591
7771
  }
7592
7772
  if (product.quantity_pricing && product.quantity_pricing.length > 1) {
7593
7773
  return "wholesale" /* Wholesale */;
7594
7774
  }
7595
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Digital) {
7775
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Digital) {
7596
7776
  return "digital" /* Digital */;
7597
7777
  }
7598
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Service) {
7778
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Service) {
7599
7779
  if (product.duration_unit && RENTAL_UNITS.has(product.duration_unit)) {
7600
7780
  return "rental" /* Rental */;
7601
7781
  }
7602
- if (product.duration_unit === chunkF47XFKYP_js.DURATION_UNIT.Nights) {
7782
+ if (product.duration_unit === chunkZYACIPKO_js.DURATION_UNIT.Nights) {
7603
7783
  return "accommodation" /* Accommodation */;
7604
7784
  }
7605
7785
  if (product.duration_unit && LEASE_UNITS.has(product.duration_unit)) {
@@ -7610,10 +7790,10 @@ function resolveCardVariant(product) {
7610
7790
  }
7611
7791
  return "standard" /* Standard */;
7612
7792
  }
7613
- if (product.render_hint === chunkF47XFKYP_js.RENDER_HINT.Food) {
7793
+ if (product.render_hint === chunkZYACIPKO_js.RENDER_HINT.Food) {
7614
7794
  return "food" /* Food */;
7615
7795
  }
7616
- if (product.render_hint === chunkF47XFKYP_js.RENDER_HINT.Physical) {
7796
+ if (product.render_hint === chunkZYACIPKO_js.RENDER_HINT.Physical) {
7617
7797
  return "retail" /* Retail */;
7618
7798
  }
7619
7799
  return "retail" /* Retail */;
@@ -7946,7 +8126,7 @@ function SearchInput({
7946
8126
  }
7947
8127
  ),
7948
8128
  /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-search-result-name": true, className: classNames?.resultName, style: { flex: 1, textAlign: "left" }, children: product.name }),
7949
- product.default_price !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-search-result-price": true, className: classNames?.resultPrice, style: { flexShrink: 0 }, children: chunkPEDLCL72_js.formatPrice(product.default_price) })
8129
+ product.default_price !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-search-result-price": true, className: classNames?.resultPrice, style: { flexShrink: 0 }, children: chunkV2O5AO7I_js.formatPrice(product.default_price) })
7950
8130
  ] })
7951
8131
  },
7952
8132
  product.id
@@ -8440,19 +8620,19 @@ function OrderSummary({
8440
8620
  order.customer_notes.map((note, index) => /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-order-note": true, children: note }, index))
8441
8621
  ] }),
8442
8622
  /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-totals": true, className: classNames?.totals, children: [
8443
- order.total_discount != null && chunkPEDLCL72_js.parsePrice(order.total_discount) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-discount": true, children: [
8623
+ order.total_discount != null && chunkV2O5AO7I_js.parsePrice(order.total_discount) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-discount": true, children: [
8444
8624
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Discount" }),
8445
8625
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: order.total_discount, prefix: "-" })
8446
8626
  ] }),
8447
- order.delivery_fee != null && chunkPEDLCL72_js.parsePrice(order.delivery_fee) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-delivery-fee": true, children: [
8627
+ order.delivery_fee != null && chunkV2O5AO7I_js.parsePrice(order.delivery_fee) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-delivery-fee": true, children: [
8448
8628
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delivery fee" }),
8449
8629
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: order.delivery_fee })
8450
8630
  ] }),
8451
- order.service_charge != null && chunkPEDLCL72_js.parsePrice(order.service_charge) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-service-charge": true, children: [
8631
+ order.service_charge != null && chunkV2O5AO7I_js.parsePrice(order.service_charge) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-service-charge": true, children: [
8452
8632
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Service charge" }),
8453
8633
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: order.service_charge })
8454
8634
  ] }),
8455
- order.tax != null && chunkPEDLCL72_js.parsePrice(order.tax) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-tax": true, children: [
8635
+ order.tax != null && chunkV2O5AO7I_js.parsePrice(order.tax) !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-tax": true, children: [
8456
8636
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Tax" }),
8457
8637
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: order.tax })
8458
8638
  ] }),
@@ -9741,7 +9921,7 @@ function DefaultProductLayout({
9741
9921
  }) {
9742
9922
  const images = product.images || (product.image_url ? [product.image_url] : []);
9743
9923
  const hasRange = product.quantity_pricing && product.quantity_pricing.length > 1 || product.variants && product.variants.length > 1;
9744
- const onSale = chunkPEDLCL72_js.isOnSale(product);
9924
+ const onSale = chunkV2O5AO7I_js.isOnSale(product);
9745
9925
  const hasPhysicalDetails = product.sku || product.vendor || product.material;
9746
9926
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-product-layout": "default", className: cn("space-y-8", className), children: [
9747
9927
  renderBreadcrumb?.(product),
@@ -9763,10 +9943,10 @@ function DefaultProductLayout({
9763
9943
  /* @__PURE__ */ jsxRuntime.jsx("h1", { "data-cimplify-product-layout-name": true, className: "text-3xl lg:text-4xl font-extrabold tracking-tight", children: product.name }),
9764
9944
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-baseline gap-3", children: hasRange ? /* @__PURE__ */ jsxRuntime.jsx(PriceRange, { product, className: "text-2xl font-extrabold" }) : onSale ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9765
9945
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-2xl font-extrabold" }),
9766
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkPEDLCL72_js.getBasePrice(product), className: "text-lg text-muted-foreground line-through" }),
9946
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkV2O5AO7I_js.getBasePrice(product), className: "text-lg text-muted-foreground line-through" }),
9767
9947
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-bold text-destructive bg-destructive/10 px-2 py-0.5", children: [
9768
9948
  "Save ",
9769
- chunkPEDLCL72_js.getDiscountPercentage(product),
9949
+ chunkV2O5AO7I_js.getDiscountPercentage(product),
9770
9950
  "%"
9771
9951
  ] })
9772
9952
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-2xl font-semibold" }) }),
@@ -9985,7 +10165,7 @@ function ServiceProductLayout({
9985
10165
  }) {
9986
10166
  const images = product.images || (product.image_url ? [product.image_url] : []);
9987
10167
  const hasDeposit = product.deposit_type && product.deposit_type !== "none" && product.deposit_amount;
9988
- const depositAmount = hasDeposit ? chunkPEDLCL72_js.parsePrice(product.deposit_amount) : 0;
10168
+ const depositAmount = hasDeposit ? chunkV2O5AO7I_js.parsePrice(product.deposit_amount) : 0;
9989
10169
  const cancellationHours = product.cancellation_window_minutes ? Math.floor(product.cancellation_window_minutes / 60) : null;
9990
10170
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-product-layout": "service", className: cn("space-y-8", className), children: [
9991
10171
  renderBreadcrumb?.(product),
@@ -10053,7 +10233,7 @@ function ServiceProductLayout({
10053
10233
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: depositAmount, className: "font-medium text-foreground" }),
10054
10234
  " deposit charged at booking"
10055
10235
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10056
- chunkPEDLCL72_js.parsePrice(product.deposit_amount),
10236
+ chunkV2O5AO7I_js.parsePrice(product.deposit_amount),
10057
10237
  "% deposit charged at booking"
10058
10238
  ] }) })
10059
10239
  ] })
@@ -10212,13 +10392,13 @@ function BundleProductLayout({
10212
10392
  }) {
10213
10393
  const images = product.images || (product.image_url ? [product.image_url] : []);
10214
10394
  const components = product.components || [];
10215
- const onSale = chunkPEDLCL72_js.isOnSale(product);
10216
- const discount = chunkPEDLCL72_js.getDiscountPercentage(product);
10395
+ const onSale = chunkV2O5AO7I_js.isOnSale(product);
10396
+ const discount = chunkV2O5AO7I_js.getDiscountPercentage(product);
10217
10397
  const baseTotal = components.reduce(
10218
- (sum, c) => sum + chunkPEDLCL72_js.parsePrice(c.effective_price ?? 0) * (c.quantity ?? 1),
10398
+ (sum, c) => sum + chunkV2O5AO7I_js.parsePrice(c.effective_price ?? 0) * (c.quantity ?? 1),
10219
10399
  0
10220
10400
  );
10221
- const bundlePrice = chunkPEDLCL72_js.parsePrice(product.default_price);
10401
+ const bundlePrice = chunkV2O5AO7I_js.parsePrice(product.default_price);
10222
10402
  const savings = baseTotal > bundlePrice ? baseTotal - bundlePrice : 0;
10223
10403
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-product-layout": "bundle", className: cn("space-y-8", className), children: [
10224
10404
  renderBreadcrumb?.(product),
@@ -10374,25 +10554,25 @@ function resolveTemplateKey(product) {
10374
10554
  if (typeof metaTemplate === "string" && metaTemplate.trim()) {
10375
10555
  return metaTemplate.trim();
10376
10556
  }
10377
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Bundle) {
10557
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Bundle) {
10378
10558
  return "bundle" /* Bundle */;
10379
10559
  }
10380
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Composite) {
10560
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Composite) {
10381
10561
  return "composite" /* Composite */;
10382
10562
  }
10383
10563
  if (product.quantity_pricing && product.quantity_pricing.length > 1) {
10384
10564
  return "wholesale" /* Wholesale */;
10385
10565
  }
10386
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Service) {
10566
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Service) {
10387
10567
  return "service" /* Service */;
10388
10568
  }
10389
- if (product.type === chunkF47XFKYP_js.PRODUCT_TYPE.Digital) {
10569
+ if (product.type === chunkZYACIPKO_js.PRODUCT_TYPE.Digital) {
10390
10570
  return "digital" /* Digital */;
10391
10571
  }
10392
- if (product.render_hint === chunkF47XFKYP_js.RENDER_HINT.Food) {
10572
+ if (product.render_hint === chunkZYACIPKO_js.RENDER_HINT.Food) {
10393
10573
  return "food" /* Food */;
10394
10574
  }
10395
- if (product.render_hint === chunkF47XFKYP_js.RENDER_HINT.Physical) {
10575
+ if (product.render_hint === chunkZYACIPKO_js.RENDER_HINT.Physical) {
10396
10576
  return "physical" /* Physical */;
10397
10577
  }
10398
10578
  return "default" /* Default */;
@@ -10845,9 +11025,9 @@ function CatalogueCollectionLayout({
10845
11025
  result = result.filter((p) => p.tags?.includes(activeCategory));
10846
11026
  }
10847
11027
  if (sortBy === "price-asc") {
10848
- result = [...result].sort((a, b) => chunkPEDLCL72_js.parsePrice(a.default_price) - chunkPEDLCL72_js.parsePrice(b.default_price));
11028
+ result = [...result].sort((a, b) => chunkV2O5AO7I_js.parsePrice(a.default_price) - chunkV2O5AO7I_js.parsePrice(b.default_price));
10849
11029
  } else if (sortBy === "price-desc") {
10850
- result = [...result].sort((a, b) => chunkPEDLCL72_js.parsePrice(b.default_price) - chunkPEDLCL72_js.parsePrice(a.default_price));
11030
+ result = [...result].sort((a, b) => chunkV2O5AO7I_js.parsePrice(b.default_price) - chunkV2O5AO7I_js.parsePrice(a.default_price));
10851
11031
  } else if (sortBy === "name") {
10852
11032
  result = [...result].sort((a, b) => a.name.localeCompare(b.name));
10853
11033
  }
@@ -12456,7 +12636,7 @@ function SparkleIcon({ className }) {
12456
12636
 
12457
12637
  Object.defineProperty(exports, "getVariantDisplayName", {
12458
12638
  enumerable: true,
12459
- get: function () { return chunkF47XFKYP_js.getVariantDisplayName; }
12639
+ get: function () { return chunkZYACIPKO_js.getVariantDisplayName; }
12460
12640
  });
12461
12641
  exports.AccommodationCard = AccommodationCard;
12462
12642
  exports.Ad = Ad;