@cimplify/sdk 0.46.3 → 0.48.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 (39) hide show
  1. package/dist/advanced.d.mts +1 -1
  2. package/dist/advanced.d.ts +1 -1
  3. package/dist/advanced.js +20 -20
  4. package/dist/advanced.mjs +1 -1
  5. package/dist/{chunk-6HYKWYUF.mjs → chunk-24FK7VFL.mjs} +1 -1
  6. package/dist/{chunk-Z2MLAIID.js → chunk-CYGLTD7D.js} +35 -35
  7. package/dist/{chunk-TW4OFRWV.js → chunk-D22UVSFN.js} +2 -2
  8. package/dist/{chunk-7ZACMER7.js → chunk-DR4UPU6P.js} +0 -1
  9. package/dist/{chunk-WUIERJ6J.mjs → chunk-MBR2DBEN.mjs} +1 -1
  10. package/dist/{chunk-CKRMA5F7.mjs → chunk-OFNVLUH4.mjs} +0 -1
  11. package/dist/{client-QVINYu1X.d.ts → client-B8tJnOde.d.ts} +0 -1
  12. package/dist/{client-G2WCoxv2.d.mts → client-BZZK1txR.d.mts} +0 -1
  13. package/dist/{client-B76ZNW5r.d.ts → client-BdbvMtOU.d.ts} +1 -1
  14. package/dist/{client-CT9NwIDX.d.mts → client-BqCAm5vI.d.mts} +1 -1
  15. package/dist/index.d.mts +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +61 -61
  18. package/dist/index.mjs +2 -2
  19. package/dist/react.d.mts +113 -10
  20. package/dist/react.d.ts +113 -10
  21. package/dist/react.js +420 -248
  22. package/dist/react.mjs +405 -235
  23. package/dist/server.d.mts +2 -2
  24. package/dist/server.d.ts +2 -2
  25. package/dist/server.js +3 -3
  26. package/dist/server.mjs +2 -2
  27. package/dist/styles.css +1 -1
  28. package/dist/testing/suite.d.mts +2 -2
  29. package/dist/testing/suite.d.ts +2 -2
  30. package/dist/testing/suite.js +22 -22
  31. package/dist/testing/suite.mjs +3 -3
  32. package/dist/testing.d.mts +2 -2
  33. package/dist/testing.d.ts +2 -2
  34. package/dist/testing.js +78 -78
  35. package/dist/testing.mjs +4 -4
  36. package/package.json +3 -1
  37. package/registry/customer-input-fields.json +1 -1
  38. package/registry/date-slot-picker.json +1 -1
  39. package/registry/slot-picker.json +1 -1
package/dist/react.js CHANGED
@@ -2,8 +2,8 @@
2
2
  'use strict';
3
3
 
4
4
  var chunkMN4PNKJA_js = require('./chunk-MN4PNKJA.js');
5
- var chunkZ2MLAIID_js = require('./chunk-Z2MLAIID.js');
6
- var chunk7ZACMER7_js = require('./chunk-7ZACMER7.js');
5
+ var chunkCYGLTD7D_js = require('./chunk-CYGLTD7D.js');
6
+ var chunkDR4UPU6P_js = require('./chunk-DR4UPU6P.js');
7
7
  var chunk6RP6OPYO_js = require('./chunk-6RP6OPYO.js');
8
8
  var chunkTKOTACKZ_js = require('./chunk-TKOTACKZ.js');
9
9
  var React10 = require('react');
@@ -15,6 +15,9 @@ var radioGroup = require('@base-ui/react/radio-group');
15
15
  var radio = require('@base-ui/react/radio');
16
16
  var checkbox = require('@base-ui/react/checkbox');
17
17
  var button = require('@base-ui/react/button');
18
+ var popover = require('@base-ui/react/popover');
19
+ var reactDayPicker = require('react-day-picker');
20
+ var dateFns = require('date-fns');
18
21
  var tabs = require('@base-ui/react/tabs');
19
22
  var dialog = require('@base-ui/react/dialog');
20
23
  var field = require('@base-ui/react/field');
@@ -626,7 +629,8 @@ function useCollectionStore(collection) {
626
629
  }
627
630
 
628
631
  // src/react/hooks/use-cart.ts
629
- var CART_STORAGE_PREFIX = "cimplify:cart:v3";
632
+ var LEGACY_CART_STORAGE_PREFIX = "cimplify:cart:v3";
633
+ var legacyCachesPurged = false;
630
634
  var cartStores = /* @__PURE__ */ new Map();
631
635
  var ROLLBACK_VISIBLE_DELAY_MS = 3e3;
632
636
  function clearAllCartStores() {
@@ -636,34 +640,35 @@ function clearAllCartStores() {
636
640
  clearTimeout(handle);
637
641
  }
638
642
  entry.failedOpRemovers.clear();
639
- if (entry.persistTimer) {
640
- clearTimeout(entry.persistTimer);
641
- entry.persistTimer = null;
642
- }
643
643
  }
644
644
  cartStores.clear();
645
645
  }
646
646
  function emptyBase(currency, isLoading = true) {
647
647
  return { items: [], subtotal: 0, tax: 0, total: 0, currency, isLoading };
648
648
  }
649
- function advanceBaseWithPatch(entry, patch) {
650
- const current = entry.collection.getBase() ?? emptyBase(entry.currency, false);
651
- entry.collection.setBase({ ...applyCartPatch(current, patch), isLoading: false });
652
- persistBase(entry);
653
- }
654
- function buildStoreKey(client, locationId, isDemoMode) {
649
+ function buildStoreKey(client, locationId) {
655
650
  return [
656
- client.getPublicKey() || "__demo__",
657
- locationId || "__no_location__",
658
- isDemoMode ? "demo" : "live"
651
+ client.getPublicKey() || "__no_public_key__",
652
+ locationId || "__no_location__"
659
653
  ].join(":");
660
654
  }
661
- function buildStorageKey(storeKey) {
662
- return `${CART_STORAGE_PREFIX}:${storeKey}`;
663
- }
664
- function stripInternalItemMetadata(item) {
665
- const { _lineKey, isOptimistic, ...rest } = item;
666
- return rest;
655
+ function purgeLegacyCartCachesOnce() {
656
+ if (legacyCachesPurged) return;
657
+ legacyCachesPurged = true;
658
+ if (typeof window === "undefined" || !window.localStorage) return;
659
+ try {
660
+ const keys = [];
661
+ for (let i = 0; i < window.localStorage.length; i += 1) {
662
+ const key = window.localStorage.key(i);
663
+ if (key && key.startsWith(LEGACY_CART_STORAGE_PREFIX)) {
664
+ keys.push(key);
665
+ }
666
+ }
667
+ for (const key of keys) {
668
+ window.localStorage.removeItem(key);
669
+ }
670
+ } catch {
671
+ }
667
672
  }
668
673
  function toProductFromServerItem(item, businessId) {
669
674
  return {
@@ -758,69 +763,13 @@ function deriveView(base, ops) {
758
763
  pendingOpCount: ops.length
759
764
  };
760
765
  }
761
- function persistBase(entry) {
762
- if (typeof window === "undefined" || !window.localStorage) return;
763
- if (!entry.isDemoMode) return;
764
- if (entry.persistTimer) return;
765
- entry.persistTimer = setTimeout(() => {
766
- entry.persistTimer = null;
767
- if (typeof window === "undefined" || !window.localStorage) return;
768
- const base = entry.collection.getBase();
769
- if (!base) return;
770
- try {
771
- window.localStorage.setItem(
772
- entry.storageKey,
773
- JSON.stringify({
774
- items: base.items.map((item) => stripInternalItemMetadata(item)),
775
- subtotal: base.subtotal,
776
- tax: base.tax,
777
- total: base.total,
778
- currency: base.currency
779
- })
780
- );
781
- } catch {
782
- }
783
- }, 100);
784
- }
785
- function hydrateFromStorage(entry) {
786
- if (typeof window === "undefined" || !window.localStorage) return;
787
- if (!entry.isDemoMode) {
788
- try {
789
- window.localStorage.removeItem(entry.storageKey);
790
- } catch {
791
- }
792
- return;
793
- }
794
- try {
795
- const raw = window.localStorage.getItem(entry.storageKey);
796
- if (!raw) return;
797
- const parsed = JSON.parse(raw);
798
- if (!parsed || !Array.isArray(parsed.items)) return;
799
- const items = parsed.items.map((item) => attachInternalItemMetadata(item));
800
- entry.collection.setBase({
801
- items,
802
- subtotal: toNumber(parsed.subtotal),
803
- tax: toNumber(parsed.tax),
804
- total: toNumber(parsed.total),
805
- currency: typeof parsed.currency === "string" && parsed.currency ? parsed.currency : entry.currency,
806
- isLoading: !entry.isDemoMode
807
- });
808
- } catch {
809
- }
810
- }
811
766
  async function syncFromServer(entry) {
812
- if (entry.isDemoMode) {
813
- const base = entry.collection.getBase() ?? emptyBase(entry.currency);
814
- entry.collection.setBase({ ...base, isLoading: false });
815
- return;
816
- }
817
767
  if (entry.syncing) return;
818
768
  entry.syncing = true;
819
769
  try {
820
770
  const result = await entry.client.cart.get();
821
771
  if (!result.ok) throw result.error;
822
772
  entry.collection.setBase(mapServerCart(result.value, entry.currency));
823
- persistBase(entry);
824
773
  } finally {
825
774
  entry.syncing = false;
826
775
  }
@@ -842,8 +791,9 @@ function scheduleFailedOpRemoval(entry, opId) {
842
791
  entry.failedOpRemovers.add(handle);
843
792
  }
844
793
  function getOrCreateStore(params) {
845
- const { client, locationId, isDemoMode, currency, optimisticEnabled } = params;
846
- const storeKey = buildStoreKey(client, locationId, isDemoMode);
794
+ const { client, locationId, currency, optimisticEnabled } = params;
795
+ purgeLegacyCartCachesOnce();
796
+ const storeKey = buildStoreKey(client, locationId);
847
797
  const existing = cartStores.get(storeKey);
848
798
  if (existing) {
849
799
  existing.optimisticEnabled = optimisticEnabled;
@@ -857,14 +807,11 @@ function getOrCreateStore(params) {
857
807
  const entry = {
858
808
  collection,
859
809
  client,
860
- storageKey: buildStorageKey(storeKey),
861
810
  locationId,
862
811
  currency,
863
- isDemoMode,
864
812
  optimisticEnabled,
865
813
  initialized: false,
866
814
  initializePromise: null,
867
- persistTimer: null,
868
815
  syncing: false,
869
816
  failedOpRemovers: /* @__PURE__ */ new Set()
870
817
  };
@@ -877,12 +824,6 @@ async function ensureInitialized(entry) {
877
824
  return;
878
825
  }
879
826
  entry.initialized = true;
880
- hydrateFromStorage(entry);
881
- if (entry.isDemoMode) {
882
- const base = entry.collection.getBase() ?? emptyBase(entry.currency);
883
- entry.collection.setBase({ ...base, isLoading: false });
884
- return;
885
- }
886
827
  entry.initializePromise = syncFromServer(entry).catch(() => {
887
828
  const base = entry.collection.getBase() ?? emptyBase(entry.currency);
888
829
  entry.collection.setBase({ ...base, isLoading: false });
@@ -896,7 +837,7 @@ async function maybeResolveQuoteId(entry, product, quantity, options) {
896
837
  const requiresQuote = Boolean(
897
838
  options.variantId || addOnOptionIds && addOnOptionIds.length > 0 || options.bundleSelections && options.bundleSelections.length > 0 || options.compositeSelections && options.compositeSelections.length > 0
898
839
  );
899
- if (!requiresQuote || entry.isDemoMode) return void 0;
840
+ if (!requiresQuote) return void 0;
900
841
  const quoteResult = await entry.client.catalogue.fetchQuote({
901
842
  product_id: product.id,
902
843
  quantity,
@@ -936,10 +877,6 @@ async function performAddItem(entry, product, quantity, options) {
936
877
  });
937
878
  const idempotencyKey = `idem_${typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`}`;
938
879
  const patch = { kind: "add_item", tempItem, lineKey };
939
- if (entry.isDemoMode) {
940
- advanceBaseWithPatch(entry, patch);
941
- return;
942
- }
943
880
  const useOptimistic = entry.optimisticEnabled;
944
881
  const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
945
882
  try {
@@ -978,10 +915,6 @@ async function performAddItem(entry, product, quantity, options) {
978
915
  async function performRemoveItem(entry, itemId) {
979
916
  const idempotencyKey = "";
980
917
  const patch = { kind: "remove_item", itemId };
981
- if (entry.isDemoMode) {
982
- advanceBaseWithPatch(entry, patch);
983
- return;
984
- }
985
918
  const useOptimistic = entry.optimisticEnabled;
986
919
  const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
987
920
  try {
@@ -1006,10 +939,6 @@ async function performUpdateQuantity(entry, itemId, quantity) {
1006
939
  const resolved = clampQuantity(quantity);
1007
940
  const idempotencyKey = "";
1008
941
  const patch = { kind: "set_quantity", itemId, quantity: resolved };
1009
- if (entry.isDemoMode) {
1010
- advanceBaseWithPatch(entry, patch);
1011
- return;
1012
- }
1013
942
  const useOptimistic = entry.optimisticEnabled;
1014
943
  const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
1015
944
  try {
@@ -1030,10 +959,6 @@ async function performUpdateQuantity(entry, itemId, quantity) {
1030
959
  async function performClear(entry) {
1031
960
  const idempotencyKey = "";
1032
961
  const patch = { kind: "clear" };
1033
- if (entry.isDemoMode) {
1034
- advanceBaseWithPatch(entry, patch);
1035
- return;
1036
- }
1037
962
  const useOptimistic = entry.optimisticEnabled;
1038
963
  const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
1039
964
  try {
@@ -1064,18 +989,16 @@ function useCart(options = {}) {
1064
989
  throw new Error("useCart must be used within CimplifyProvider or passed { client }.");
1065
990
  }
1066
991
  const locationId = options.locationId ?? client.getLocationId();
1067
- const isDemoMode = options.demoMode ?? context?.isDemoMode ?? client.getPublicKey().trim().length === 0;
1068
992
  const currency = options.currency ?? context?.currency ?? "USD";
1069
993
  const optimisticEnabled = context?.optimistic ?? true;
1070
994
  const entry = React10.useMemo(
1071
995
  () => getOrCreateStore({
1072
996
  client,
1073
997
  locationId,
1074
- isDemoMode,
1075
998
  currency,
1076
999
  optimisticEnabled
1077
1000
  }),
1078
- [client, currency, isDemoMode, locationId, optimisticEnabled]
1001
+ [client, currency, locationId, optimisticEnabled]
1079
1002
  );
1080
1003
  const view = useCollectionStore(entry.collection);
1081
1004
  React10.useEffect(() => {
@@ -1161,7 +1084,7 @@ var DEFAULT_COUNTRY = "US";
1161
1084
  function createDefaultClient() {
1162
1085
  const processRef = globalThis.process;
1163
1086
  const envPublicKey = processRef?.env?.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || "";
1164
- return chunkZ2MLAIID_js.createCimplifyClient({ publicKey: envPublicKey });
1087
+ return chunkCYGLTD7D_js.createCimplifyClient({ publicKey: envPublicKey });
1165
1088
  }
1166
1089
  function getStoredLocationId() {
1167
1090
  if (typeof window === "undefined" || !window.localStorage) {
@@ -1235,7 +1158,6 @@ function CimplifyProvider({
1235
1158
  React10.useEffect(() => {
1236
1159
  onLocationChangeRef.current = onLocationChange;
1237
1160
  }, [onLocationChange]);
1238
- const isDemoMode = resolvedClient.getPublicKey().trim().length === 0;
1239
1161
  const baseCurrency = business?.default_currency || DEFAULT_CURRENCY;
1240
1162
  const [displayCurrencyOverride, setDisplayCurrencyOverride] = React10.useState(
1241
1163
  () => getStoredDisplayCurrency()
@@ -1257,7 +1179,7 @@ function CimplifyProvider({
1257
1179
  [baseCurrency]
1258
1180
  );
1259
1181
  React10.useEffect(() => {
1260
- if (displayCurrency === baseCurrency || isDemoMode) {
1182
+ if (displayCurrency === baseCurrency) {
1261
1183
  setFxRate(null);
1262
1184
  return;
1263
1185
  }
@@ -1280,7 +1202,7 @@ function CimplifyProvider({
1280
1202
  cancelled = true;
1281
1203
  clearInterval(intervalId);
1282
1204
  };
1283
- }, [resolvedClient, baseCurrency, displayCurrency, isDemoMode]);
1205
+ }, [resolvedClient, baseCurrency, displayCurrency]);
1284
1206
  const convertPrice = React10.useCallback(
1285
1207
  (amount) => {
1286
1208
  const num = typeof amount === "string" ? parseFloat(amount) : amount;
@@ -1307,17 +1229,6 @@ function CimplifyProvider({
1307
1229
  let cancelled = false;
1308
1230
  async function bootstrap() {
1309
1231
  setIsReady(false);
1310
- if (isDemoMode) {
1311
- if (!cancelled) {
1312
- setBusiness(null);
1313
- setLocations([]);
1314
- setCurrentLocationState(null);
1315
- resolvedClient.setLocationId(null);
1316
- setStoredLocationId(null);
1317
- setIsReady(true);
1318
- }
1319
- return;
1320
- }
1321
1232
  const [businessResult, locationsResult] = await Promise.all([
1322
1233
  resolvedClient.business.getInfo(),
1323
1234
  resolvedClient.business.getLocations()
@@ -1358,7 +1269,7 @@ function CimplifyProvider({
1358
1269
  return () => {
1359
1270
  cancelled = true;
1360
1271
  };
1361
- }, [resolvedClient, isDemoMode]);
1272
+ }, [resolvedClient]);
1362
1273
  const clientContextValue = React10.useMemo(
1363
1274
  () => ({
1364
1275
  client: resolvedClient,
@@ -1367,7 +1278,6 @@ function CimplifyProvider({
1367
1278
  country: business?.country_code || DEFAULT_COUNTRY,
1368
1279
  locations,
1369
1280
  isReady,
1370
- isDemoMode,
1371
1281
  baseCurrency,
1372
1282
  optimistic
1373
1283
  }),
@@ -1377,7 +1287,6 @@ function CimplifyProvider({
1377
1287
  baseCurrency,
1378
1288
  locations,
1379
1289
  isReady,
1380
- isDemoMode,
1381
1290
  optimistic
1382
1291
  ]
1383
1292
  );
@@ -1432,16 +1341,10 @@ function useCimplifyClient() {
1432
1341
  function useOptionalCimplifyClient() {
1433
1342
  return React10.useContext(CimplifyClientContext);
1434
1343
  }
1435
- var SPACE = { sm: 8};
1436
- function shellColors(isDark, primaryColor) {
1344
+ function shellColors(isDark) {
1437
1345
  return {
1438
- text: isDark ? "#f4f4f5" : "#1a1a1a",
1439
1346
  textSecondary: isDark ? "#a1a1aa" : "#52525b",
1440
- textMuted: isDark ? "#71717a" : "#a1a1aa",
1441
- border: isDark ? "#27272a" : "#e4e4e7",
1442
- surface: isDark ? "#18181b" : "#fafafa",
1443
- error: "#dc2626",
1444
- primary: primaryColor
1347
+ error: "#dc2626"
1445
1348
  };
1446
1349
  }
1447
1350
  function statusToLabel(status) {
@@ -1485,7 +1388,6 @@ function CimplifyCheckout({
1485
1388
  onError,
1486
1389
  onStatusChange,
1487
1390
  appearance,
1488
- demoMode,
1489
1391
  className
1490
1392
  }) {
1491
1393
  const resolvedOrderTypes = React10.useMemo(
@@ -1513,8 +1415,6 @@ function CimplifyCheckout({
1513
1415
  const initialAppearanceRef = React10.useRef(appearance);
1514
1416
  const hasWarnedInlineAppearanceRef = React10.useRef(false);
1515
1417
  const isMountedRef = React10.useRef(true);
1516
- const demoRunRef = React10.useRef(0);
1517
- const isDemoCheckout = demoMode ?? client.getPublicKey().trim().length === 0;
1518
1418
  const isTestMode = client.isTestMode();
1519
1419
  const cimplifyCtx = useOptionalCimplify();
1520
1420
  const fxOptions = React10.useMemo(() => {
@@ -1529,7 +1429,6 @@ function CimplifyCheckout({
1529
1429
  fxOptionsRef.current = fxOptions;
1530
1430
  const resolvedCartRef = React10.useRef(resolvedCart);
1531
1431
  resolvedCartRef.current = resolvedCart;
1532
- const primaryColor = appearance?.variables?.primaryColor || "#0a2540";
1533
1432
  const isDark = appearance?.theme === "dark";
1534
1433
  const emitStatus = React10__default.default.useEffectEvent(
1535
1434
  (nextStatus, context = {}) => {
@@ -1559,15 +1458,6 @@ function CimplifyCheckout({
1559
1458
  React10.useEffect(() => {
1560
1459
  let cancelled = false;
1561
1460
  async function bootstrap() {
1562
- if (isDemoCheckout) {
1563
- if (!cancelled) {
1564
- setResolvedBusinessId(businessId ?? null);
1565
- setResolvedCartId(cartId ?? "cart_demo");
1566
- setIsInitializing(false);
1567
- setErrorMessage(null);
1568
- }
1569
- return;
1570
- }
1571
1461
  const needsBusinessResolve = !businessId;
1572
1462
  const needsCartResolve = !cartId;
1573
1463
  if (!needsBusinessResolve && !needsCartResolve) {
@@ -1635,11 +1525,10 @@ function CimplifyCheckout({
1635
1525
  return () => {
1636
1526
  cancelled = true;
1637
1527
  };
1638
- }, [businessId, cartId, client, isDemoCheckout]);
1528
+ }, [businessId, cartId, client]);
1639
1529
  React10.useEffect(() => {
1640
1530
  return () => {
1641
1531
  isMountedRef.current = false;
1642
- demoRunRef.current += 1;
1643
1532
  activeCheckoutRef.current?.abort();
1644
1533
  activeCheckoutRef.current = null;
1645
1534
  };
@@ -1656,42 +1545,6 @@ function CimplifyCheckout({
1656
1545
  setErrorMessage(null);
1657
1546
  setIsSubmitting(true);
1658
1547
  emitStatus("preparing", { display_text: statusToLabel("preparing") });
1659
- if (isDemoCheckout) {
1660
- const runId = demoRunRef.current + 1;
1661
- demoRunRef.current = runId;
1662
- const wait = async (ms) => {
1663
- await new Promise((resolve) => setTimeout(resolve, ms));
1664
- return isMountedRef.current && runId === demoRunRef.current;
1665
- };
1666
- try {
1667
- if (!await wait(400)) return;
1668
- emitStatus("processing", { display_text: statusToLabel("processing") });
1669
- if (!await wait(900)) return;
1670
- emitStatus("polling", { display_text: statusToLabel("polling") });
1671
- if (!await wait(1200)) return;
1672
- const result = {
1673
- success: true,
1674
- order: {
1675
- id: `ord_demo_${Date.now()}`,
1676
- order_number: `DEMO-${Math.random().toString(36).slice(2, 8).toUpperCase()}`,
1677
- status: "confirmed",
1678
- total: "0.00",
1679
- currency: "USD"
1680
- }
1681
- };
1682
- emitStatus("success", {
1683
- order_id: result.order?.id,
1684
- order_number: result.order?.order_number,
1685
- display_text: statusToLabel("success")
1686
- });
1687
- onComplete(result);
1688
- } finally {
1689
- if (isMountedRef.current && runId === demoRunRef.current) {
1690
- setIsSubmitting(false);
1691
- }
1692
- }
1693
- return;
1694
- }
1695
1548
  if (!elementsRef.current) {
1696
1549
  const message = "Checkout is still initializing. Please try again.";
1697
1550
  setErrorMessage(message);
@@ -1726,7 +1579,7 @@ function CimplifyCheckout({
1726
1579
  }
1727
1580
  });
1728
1581
  React10.useEffect(() => {
1729
- if (isDemoCheckout || !resolvedBusinessId) {
1582
+ if (!resolvedBusinessId) {
1730
1583
  elementsRef.current = null;
1731
1584
  return;
1732
1585
  }
@@ -1767,7 +1620,6 @@ function CimplifyCheckout({
1767
1620
  }, [
1768
1621
  client,
1769
1622
  resolvedBusinessId,
1770
- isDemoCheckout,
1771
1623
  resolvedOrderTypes,
1772
1624
  resolvedDefaultOrderType,
1773
1625
  submitLabel
@@ -1779,15 +1631,15 @@ function CimplifyCheckout({
1779
1631
  checkoutElement.setCart(transformToCheckoutCart(resolvedCart, fxOptions));
1780
1632
  }
1781
1633
  }, [resolvedCart, fxOptions]);
1782
- const colors = shellColors(isDark ?? false, primaryColor);
1634
+ const colors = shellColors(isDark ?? false);
1783
1635
  if (isInitializing) {
1784
1636
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { fontSize: 13, color: colors.textSecondary }, children: "Preparing checkout..." }) });
1785
1637
  }
1786
- if (!isDemoCheckout && (!resolvedBusinessId || !resolvedCartId)) {
1638
+ if (!resolvedBusinessId || !resolvedCartId) {
1787
1639
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { fontSize: 13, color: colors.error }, children: errorMessage || "Unable to initialize checkout. Please refresh and try again." }) });
1788
1640
  }
1789
1641
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-cimplify-checkout": "", children: [
1790
- isTestMode && !isDemoCheckout && /* @__PURE__ */ jsxRuntime.jsx(
1642
+ isTestMode && /* @__PURE__ */ jsxRuntime.jsx(
1791
1643
  "p",
1792
1644
  {
1793
1645
  "data-cimplify-test-mode": "",
@@ -1800,9 +1652,9 @@ function CimplifyCheckout({
1800
1652
  children: "Test mode - no real charges"
1801
1653
  }
1802
1654
  ),
1803
- /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-section": "checkout", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: isDemoCheckout ? void 0 : checkoutMountRef }) }),
1804
- status && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.textSecondary }, children: statusText || statusToLabel(status) }),
1805
- errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.error }, children: errorMessage })
1655
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-section": "checkout", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: checkoutMountRef }) }),
1656
+ status && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { marginTop: 8, fontSize: 13, color: colors.textSecondary }, children: statusText || statusToLabel(status) }),
1657
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { marginTop: 8, fontSize: 13, color: colors.error }, children: errorMessage })
1806
1658
  ] });
1807
1659
  }
1808
1660
  function cn(...inputs) {
@@ -3667,19 +3519,19 @@ function AuthElement({
3667
3519
  }, [onReady, onAuthenticated, onRequiresOtp, onError]);
3668
3520
  React10.useEffect(() => {
3669
3521
  if (!elements || !containerRef.current) return;
3670
- const element = elements.create(chunk7ZACMER7_js.ELEMENT_TYPES.AUTH, { prefillEmail });
3522
+ const element = elements.create(chunkDR4UPU6P_js.ELEMENT_TYPES.AUTH, { prefillEmail });
3671
3523
  elementRef.current = element;
3672
- element.on(chunk7ZACMER7_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3524
+ element.on(chunkDR4UPU6P_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3673
3525
  element.on(
3674
- chunk7ZACMER7_js.EVENT_TYPES.AUTHENTICATED,
3526
+ chunkDR4UPU6P_js.EVENT_TYPES.AUTHENTICATED,
3675
3527
  (data) => onAuthenticatedRef.current?.(data)
3676
3528
  );
3677
3529
  element.on(
3678
- chunk7ZACMER7_js.EVENT_TYPES.REQUIRES_OTP,
3530
+ chunkDR4UPU6P_js.EVENT_TYPES.REQUIRES_OTP,
3679
3531
  (data) => onRequiresOtpRef.current?.(data)
3680
3532
  );
3681
3533
  element.on(
3682
- chunk7ZACMER7_js.EVENT_TYPES.ERROR,
3534
+ chunkDR4UPU6P_js.EVENT_TYPES.ERROR,
3683
3535
  (data) => onErrorRef.current?.(data)
3684
3536
  );
3685
3537
  element.mount(containerRef.current);
@@ -3708,15 +3560,15 @@ function AddressElement({
3708
3560
  }, [onReady, onChange, onError]);
3709
3561
  React10.useEffect(() => {
3710
3562
  if (!elements || !containerRef.current) return;
3711
- const element = elements.create(chunk7ZACMER7_js.ELEMENT_TYPES.ADDRESS, { mode });
3563
+ const element = elements.create(chunkDR4UPU6P_js.ELEMENT_TYPES.ADDRESS, { mode });
3712
3564
  elementRef.current = element;
3713
- element.on(chunk7ZACMER7_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3565
+ element.on(chunkDR4UPU6P_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3714
3566
  element.on(
3715
- chunk7ZACMER7_js.EVENT_TYPES.CHANGE,
3567
+ chunkDR4UPU6P_js.EVENT_TYPES.CHANGE,
3716
3568
  (data) => onChangeRef.current?.(data)
3717
3569
  );
3718
3570
  element.on(
3719
- chunk7ZACMER7_js.EVENT_TYPES.ERROR,
3571
+ chunkDR4UPU6P_js.EVENT_TYPES.ERROR,
3720
3572
  (data) => onErrorRef.current?.(data)
3721
3573
  );
3722
3574
  element.mount(containerRef.current);
@@ -3746,15 +3598,15 @@ function PaymentElement({
3746
3598
  }, [onReady, onChange, onError]);
3747
3599
  React10.useEffect(() => {
3748
3600
  if (!elements || !containerRef.current) return;
3749
- const element = elements.create(chunk7ZACMER7_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
3601
+ const element = elements.create(chunkDR4UPU6P_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
3750
3602
  elementRef.current = element;
3751
- element.on(chunk7ZACMER7_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3603
+ element.on(chunkDR4UPU6P_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3752
3604
  element.on(
3753
- chunk7ZACMER7_js.EVENT_TYPES.CHANGE,
3605
+ chunkDR4UPU6P_js.EVENT_TYPES.CHANGE,
3754
3606
  (data) => onChangeRef.current?.(data)
3755
3607
  );
3756
3608
  element.on(
3757
- chunk7ZACMER7_js.EVENT_TYPES.ERROR,
3609
+ chunkDR4UPU6P_js.EVENT_TYPES.ERROR,
3758
3610
  (data) => onErrorRef.current?.(data)
3759
3611
  );
3760
3612
  element.mount(containerRef.current);
@@ -5150,6 +5002,262 @@ function VolumePricing({
5150
5002
  }
5151
5003
  );
5152
5004
  }
5005
+ function parseValue(value) {
5006
+ if (!value) return void 0;
5007
+ const date = dateFns.parseISO(value);
5008
+ return dateFns.isValid(date) ? date : void 0;
5009
+ }
5010
+ function formatValue(date) {
5011
+ return dateFns.format(date, "yyyy-MM-dd");
5012
+ }
5013
+ function DatePicker({
5014
+ value,
5015
+ onChange,
5016
+ placeholder = "Select a date",
5017
+ minDate,
5018
+ maxDate,
5019
+ disabled,
5020
+ triggerDisabled,
5021
+ name,
5022
+ required,
5023
+ className,
5024
+ classNames,
5025
+ "aria-label": ariaLabel
5026
+ }) {
5027
+ const [open, setOpen] = React10.useState(false);
5028
+ const selected = parseValue(value);
5029
+ const disabledMatchers = [];
5030
+ if (minDate) disabledMatchers.push({ before: minDate });
5031
+ if (maxDate) disabledMatchers.push({ after: maxDate });
5032
+ if (Array.isArray(disabled)) {
5033
+ disabledMatchers.push(...disabled);
5034
+ } else if (disabled) {
5035
+ disabledMatchers.push(disabled);
5036
+ }
5037
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-date-picker": true, className: cn(className, classNames?.root), children: [
5038
+ /* @__PURE__ */ jsxRuntime.jsxs(popover.Popover.Root, { open, onOpenChange: setOpen, children: [
5039
+ /* @__PURE__ */ jsxRuntime.jsxs(
5040
+ popover.Popover.Trigger,
5041
+ {
5042
+ type: "button",
5043
+ "aria-label": ariaLabel ?? placeholder,
5044
+ disabled: triggerDisabled,
5045
+ className: cn(
5046
+ "w-full inline-flex items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-left text-sm transition-colors hover:bg-muted/40 focus:outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
5047
+ classNames?.trigger
5048
+ ),
5049
+ children: [
5050
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(!selected && "text-muted-foreground"), children: selected ? dateFns.format(selected, "EEE, MMM d, yyyy") : placeholder }),
5051
+ /* @__PURE__ */ jsxRuntime.jsxs(
5052
+ "svg",
5053
+ {
5054
+ width: "16",
5055
+ height: "16",
5056
+ viewBox: "0 0 24 24",
5057
+ fill: "none",
5058
+ stroke: "currentColor",
5059
+ strokeWidth: "2",
5060
+ strokeLinecap: "round",
5061
+ strokeLinejoin: "round",
5062
+ "aria-hidden": "true",
5063
+ className: "shrink-0 text-muted-foreground",
5064
+ children: [
5065
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
5066
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
5067
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
5068
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
5069
+ ]
5070
+ }
5071
+ )
5072
+ ]
5073
+ }
5074
+ ),
5075
+ /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Positioner, { sideOffset: 6, align: "start", children: /* @__PURE__ */ jsxRuntime.jsx(
5076
+ popover.Popover.Popup,
5077
+ {
5078
+ className: cn(
5079
+ "z-50 rounded-lg border border-border bg-background p-3 shadow-lg outline-none",
5080
+ classNames?.popup
5081
+ ),
5082
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5083
+ reactDayPicker.DayPicker,
5084
+ {
5085
+ mode: "single",
5086
+ selected,
5087
+ onSelect: (date) => {
5088
+ onChange?.(date ? formatValue(date) : "");
5089
+ if (date) setOpen(false);
5090
+ },
5091
+ disabled: disabledMatchers.length > 0 ? disabledMatchers : void 0,
5092
+ showOutsideDays: true,
5093
+ weekStartsOn: 0,
5094
+ className: cn("p-0", classNames?.calendar),
5095
+ classNames: {
5096
+ months: "flex flex-col gap-3",
5097
+ month: "flex flex-col gap-3",
5098
+ caption: "flex items-center justify-between px-1",
5099
+ caption_label: "text-sm font-semibold",
5100
+ nav: "flex items-center gap-1",
5101
+ nav_button: "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-muted transition-colors",
5102
+ table: "w-full border-collapse",
5103
+ head_row: "flex",
5104
+ head_cell: "w-9 text-center text-[10px] font-medium uppercase tracking-wider text-muted-foreground",
5105
+ row: "flex w-full mt-1",
5106
+ cell: "w-9 h-9 text-center text-sm p-0 relative",
5107
+ day: cn(
5108
+ "inline-flex h-9 w-9 items-center justify-center rounded-md text-sm font-normal text-foreground hover:bg-muted transition-colors",
5109
+ "aria-selected:bg-foreground aria-selected:text-background aria-selected:hover:bg-foreground/90"
5110
+ ),
5111
+ day_selected: cn(
5112
+ "bg-foreground text-background hover:bg-foreground/90 focus:bg-foreground",
5113
+ classNames?.daySelected
5114
+ ),
5115
+ day_today: cn(
5116
+ "ring-1 ring-inset ring-primary/40",
5117
+ classNames?.dayToday
5118
+ ),
5119
+ day_outside: "text-muted-foreground/50",
5120
+ day_disabled: cn(
5121
+ "text-muted-foreground/40 cursor-not-allowed line-through",
5122
+ classNames?.dayDisabled
5123
+ )
5124
+ }
5125
+ }
5126
+ )
5127
+ }
5128
+ ) }) })
5129
+ ] }),
5130
+ name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: value ?? "", required }) : null
5131
+ ] });
5132
+ }
5133
+ function parseHHmm(value) {
5134
+ if (!value) return null;
5135
+ const match = /^(\d{1,2}):(\d{2})$/.exec(value);
5136
+ if (!match) return null;
5137
+ const hour = Number.parseInt(match[1] ?? "", 10);
5138
+ const minute = Number.parseInt(match[2] ?? "", 10);
5139
+ if (Number.isNaN(hour) || Number.isNaN(minute)) return null;
5140
+ if (hour < 0 || hour > 23 || minute < 0 || minute > 59) return null;
5141
+ return { hour, minute };
5142
+ }
5143
+ function formatHHmm(hour, minute) {
5144
+ return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
5145
+ }
5146
+ function formatDisplay(hour, minute, displayFormat) {
5147
+ if (displayFormat === "24h") {
5148
+ return formatHHmm(hour, minute);
5149
+ }
5150
+ const period = hour >= 12 ? "PM" : "AM";
5151
+ const displayHour = hour % 12 || 12;
5152
+ return `${displayHour}:${String(minute).padStart(2, "0")} ${period}`;
5153
+ }
5154
+ function buildOptions(minTime, maxTime, stepMinutes) {
5155
+ const min = parseHHmm(minTime) ?? { hour: 0, minute: 0 };
5156
+ const max = parseHHmm(maxTime) ?? { hour: 23, minute: 59 };
5157
+ const minTotal = min.hour * 60 + min.minute;
5158
+ const maxTotal = max.hour * 60 + max.minute;
5159
+ const step = Math.max(1, stepMinutes);
5160
+ const out = [];
5161
+ for (let total = minTotal; total <= maxTotal; total += step) {
5162
+ out.push(formatHHmm(Math.floor(total / 60), total % 60));
5163
+ }
5164
+ return out;
5165
+ }
5166
+ function TimePicker({
5167
+ value,
5168
+ onChange,
5169
+ placeholder = "Select a time",
5170
+ minTime = "00:00",
5171
+ maxTime = "23:30",
5172
+ stepMinutes = 30,
5173
+ displayFormat = "12h",
5174
+ triggerDisabled,
5175
+ name,
5176
+ required,
5177
+ className,
5178
+ classNames,
5179
+ "aria-label": ariaLabel
5180
+ }) {
5181
+ const [open, setOpen] = React10.useState(false);
5182
+ const parsed = parseHHmm(value);
5183
+ const options = React10.useMemo(
5184
+ () => buildOptions(minTime, maxTime, stepMinutes),
5185
+ [minTime, maxTime, stepMinutes]
5186
+ );
5187
+ const triggerLabel = parsed ? formatDisplay(parsed.hour, parsed.minute, displayFormat) : placeholder;
5188
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-time-picker": true, className: cn(className, classNames?.root), children: [
5189
+ /* @__PURE__ */ jsxRuntime.jsxs(popover.Popover.Root, { open, onOpenChange: setOpen, children: [
5190
+ /* @__PURE__ */ jsxRuntime.jsxs(
5191
+ popover.Popover.Trigger,
5192
+ {
5193
+ type: "button",
5194
+ "aria-label": ariaLabel ?? placeholder,
5195
+ disabled: triggerDisabled,
5196
+ className: cn(
5197
+ "w-full inline-flex items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-left text-sm transition-colors hover:bg-muted/40 focus:outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
5198
+ classNames?.trigger
5199
+ ),
5200
+ children: [
5201
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(!parsed && "text-muted-foreground"), children: triggerLabel }),
5202
+ /* @__PURE__ */ jsxRuntime.jsxs(
5203
+ "svg",
5204
+ {
5205
+ width: "16",
5206
+ height: "16",
5207
+ viewBox: "0 0 24 24",
5208
+ fill: "none",
5209
+ stroke: "currentColor",
5210
+ strokeWidth: "2",
5211
+ strokeLinecap: "round",
5212
+ strokeLinejoin: "round",
5213
+ "aria-hidden": "true",
5214
+ className: "shrink-0 text-muted-foreground",
5215
+ children: [
5216
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
5217
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "12 7 12 12 15 14" })
5218
+ ]
5219
+ }
5220
+ )
5221
+ ]
5222
+ }
5223
+ ),
5224
+ /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Positioner, { sideOffset: 6, align: "start", children: /* @__PURE__ */ jsxRuntime.jsx(
5225
+ popover.Popover.Popup,
5226
+ {
5227
+ className: cn(
5228
+ "z-50 max-h-64 overflow-y-auto rounded-lg border border-border bg-background p-1 shadow-lg outline-none",
5229
+ classNames?.popup
5230
+ ),
5231
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "listbox", "aria-label": ariaLabel ?? placeholder, className: "flex flex-col", children: options.map((option) => {
5232
+ const isSelected = option === value;
5233
+ const opt = parseHHmm(option);
5234
+ if (!opt) return null;
5235
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
5236
+ "button",
5237
+ {
5238
+ type: "button",
5239
+ role: "option",
5240
+ "aria-selected": isSelected,
5241
+ onClick: () => {
5242
+ onChange?.(option);
5243
+ setOpen(false);
5244
+ },
5245
+ className: cn(
5246
+ "w-full rounded-md px-3 py-2 text-left text-sm transition-colors hover:bg-muted",
5247
+ isSelected && "bg-foreground text-background hover:bg-foreground/90",
5248
+ classNames?.option,
5249
+ isSelected && classNames?.optionSelected
5250
+ ),
5251
+ children: formatDisplay(opt.hour, opt.minute, displayFormat)
5252
+ }
5253
+ ) }, option);
5254
+ }) })
5255
+ }
5256
+ ) }) })
5257
+ ] }),
5258
+ name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: value ?? "", required }) : null
5259
+ ] });
5260
+ }
5153
5261
  function CustomerInputFields({
5154
5262
  fields,
5155
5263
  values,
@@ -5336,13 +5444,13 @@ function FieldInput({
5336
5444
  );
5337
5445
  case chunkMN4PNKJA_js.INPUT_FIELD_TYPE.Date:
5338
5446
  return /* @__PURE__ */ jsxRuntime.jsx(
5339
- "input",
5447
+ DatePicker,
5340
5448
  {
5341
- type: "date",
5342
5449
  value: typeof value === "string" ? value : "",
5343
- onChange: (e) => onValueChange(e.target.value || void 0),
5450
+ onChange: (next) => onValueChange(next || void 0),
5344
5451
  required: field.is_required,
5345
- className: inputClass
5452
+ placeholder: field.placeholder ?? "Select a date",
5453
+ "aria-label": field.name
5346
5454
  }
5347
5455
  );
5348
5456
  case chunkMN4PNKJA_js.INPUT_FIELD_TYPE.File:
@@ -5370,34 +5478,53 @@ function FieldInput({
5370
5478
  }
5371
5479
  );
5372
5480
  case chunkMN4PNKJA_js.INPUT_FIELD_TYPE.DateTime: {
5373
- const dtLocalValue = typeof value === "string" && value.includes("T") ? value.slice(0, 16) : typeof value === "string" ? value : "";
5374
- return /* @__PURE__ */ jsxRuntime.jsx(
5375
- "input",
5376
- {
5377
- type: "datetime-local",
5378
- value: dtLocalValue,
5379
- onChange: (e) => {
5380
- if (!e.target.value) {
5381
- onValueChange(void 0);
5382
- return;
5383
- }
5384
- const date = new Date(e.target.value);
5385
- onValueChange(Number.isNaN(date.getTime()) ? e.target.value : date.toISOString());
5386
- },
5387
- required: field.is_required,
5388
- className: inputClass
5481
+ const stringValue = typeof value === "string" ? value : "";
5482
+ const [datePart, timePartRaw] = stringValue.includes("T") ? stringValue.split("T", 2) : [stringValue, ""];
5483
+ const timePart = (timePartRaw ?? "").slice(0, 5);
5484
+ const commit = (nextDate, nextTime) => {
5485
+ if (!nextDate && !nextTime) {
5486
+ onValueChange(void 0);
5487
+ return;
5389
5488
  }
5390
- );
5489
+ if (!nextDate) {
5490
+ onValueChange(`${nextTime}`);
5491
+ return;
5492
+ }
5493
+ const combined = `${nextDate}T${nextTime || "00:00"}`;
5494
+ const parsed = new Date(combined);
5495
+ onValueChange(Number.isNaN(parsed.getTime()) ? combined : parsed.toISOString());
5496
+ };
5497
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-[1fr_auto] gap-2", children: [
5498
+ /* @__PURE__ */ jsxRuntime.jsx(
5499
+ DatePicker,
5500
+ {
5501
+ value: datePart ?? "",
5502
+ onChange: (next) => commit(next, timePart),
5503
+ placeholder: field.placeholder ?? "Select a date",
5504
+ "aria-label": `${field.name} date`,
5505
+ required: field.is_required
5506
+ }
5507
+ ),
5508
+ /* @__PURE__ */ jsxRuntime.jsx(
5509
+ TimePicker,
5510
+ {
5511
+ value: timePart,
5512
+ onChange: (next) => commit(datePart ?? "", next),
5513
+ placeholder: "Time",
5514
+ "aria-label": `${field.name} time`
5515
+ }
5516
+ )
5517
+ ] });
5391
5518
  }
5392
5519
  case chunkMN4PNKJA_js.INPUT_FIELD_TYPE.Time:
5393
5520
  return /* @__PURE__ */ jsxRuntime.jsx(
5394
- "input",
5521
+ TimePicker,
5395
5522
  {
5396
- type: "time",
5397
5523
  value: typeof value === "string" ? value : "",
5398
- onChange: (e) => onValueChange(e.target.value || void 0),
5524
+ onChange: (next) => onValueChange(next || void 0),
5399
5525
  required: field.is_required,
5400
- className: inputClass
5526
+ placeholder: field.placeholder ?? "Select a time",
5527
+ "aria-label": field.name
5401
5528
  }
5402
5529
  );
5403
5530
  case chunkMN4PNKJA_js.INPUT_FIELD_TYPE.MultiSelect:
@@ -5417,8 +5544,7 @@ function FieldInput({
5417
5544
  field,
5418
5545
  value,
5419
5546
  onValueChange,
5420
- classNames,
5421
- inputClass
5547
+ classNames
5422
5548
  }
5423
5549
  );
5424
5550
  case chunkMN4PNKJA_js.INPUT_FIELD_TYPE.Address:
@@ -5587,38 +5713,39 @@ function DateRangeInput({
5587
5713
  field,
5588
5714
  value,
5589
5715
  onValueChange,
5590
- classNames,
5591
- inputClass
5716
+ classNames
5592
5717
  }) {
5593
5718
  const range = value && typeof value === "object" ? value : {};
5594
5719
  const update = (key, v) => {
5595
5720
  const next = { ...range, [key]: v };
5596
5721
  onValueChange(next.start || next.end ? next : void 0);
5597
5722
  };
5598
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid grid-cols-2 gap-3", classNames?.dateRangeInput), children: [
5723
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid grid-cols-1 sm:grid-cols-2 gap-3", classNames?.dateRangeInput), children: [
5599
5724
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5600
5725
  /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-xs text-muted-foreground mb-1 block", children: "Start" }),
5601
5726
  /* @__PURE__ */ jsxRuntime.jsx(
5602
- "input",
5727
+ DatePicker,
5603
5728
  {
5604
- type: "date",
5605
5729
  value: range.start || "",
5606
- onChange: (e) => update("start", e.target.value),
5730
+ onChange: (next) => update("start", next),
5607
5731
  required: field.is_required,
5608
- className: inputClass
5732
+ placeholder: "Start date",
5733
+ "aria-label": `${field.name} start date`,
5734
+ maxDate: range.end ? /* @__PURE__ */ new Date(`${range.end}T00:00`) : void 0
5609
5735
  }
5610
5736
  )
5611
5737
  ] }),
5612
5738
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5613
5739
  /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-xs text-muted-foreground mb-1 block", children: "End" }),
5614
5740
  /* @__PURE__ */ jsxRuntime.jsx(
5615
- "input",
5741
+ DatePicker,
5616
5742
  {
5617
- type: "date",
5618
5743
  value: range.end || "",
5619
- onChange: (e) => update("end", e.target.value),
5744
+ onChange: (next) => update("end", next),
5620
5745
  required: field.is_required,
5621
- className: inputClass
5746
+ placeholder: "End date",
5747
+ "aria-label": `${field.name} end date`,
5748
+ minDate: range.start ? /* @__PURE__ */ new Date(`${range.start}T00:00`) : void 0
5622
5749
  }
5623
5750
  )
5624
5751
  ] })
@@ -6062,6 +6189,39 @@ function formatTime(timeStr) {
6062
6189
  }
6063
6190
  return timeStr;
6064
6191
  }
6192
+ function pluralizeUnit(unit, value) {
6193
+ if (!unit) return value === 1 ? "day" : "days";
6194
+ const v = value ?? 1;
6195
+ if (unit === "minutes") return v === 1 ? "minute" : "minutes";
6196
+ if (unit === "hours") return v === 1 ? "hour" : "hours";
6197
+ if (unit === "days") return v === 1 ? "day" : "days";
6198
+ if (unit === "weeks") return v === 1 ? "week" : "weeks";
6199
+ if (unit === "months") return v === 1 ? "month" : "months";
6200
+ return unit;
6201
+ }
6202
+ function formatStaySummary(slot, durationUnit, durationValue) {
6203
+ const start = new Date(slot.start_time);
6204
+ const end = new Date(slot.end_time);
6205
+ const startLabel = start.toLocaleString(void 0, {
6206
+ weekday: "short",
6207
+ month: "short",
6208
+ day: "numeric",
6209
+ hour: "numeric",
6210
+ minute: "2-digit"
6211
+ });
6212
+ const endLabel = end.toLocaleString(void 0, {
6213
+ weekday: "short",
6214
+ month: "short",
6215
+ day: "numeric",
6216
+ hour: "numeric",
6217
+ minute: "2-digit"
6218
+ });
6219
+ const unitLabel = pluralizeUnit(durationUnit, durationValue);
6220
+ if (durationValue !== void 0) {
6221
+ return `${durationValue} ${unitLabel}: ${startLabel} \u2192 ${endLabel}`;
6222
+ }
6223
+ return `${startLabel} \u2192 ${endLabel}`;
6224
+ }
6065
6225
  function slotToValue(slot) {
6066
6226
  return `${slot.start_time}|${slot.end_time}`;
6067
6227
  }
@@ -6074,10 +6234,14 @@ function SlotPicker({
6074
6234
  onSlotSelect,
6075
6235
  groupByTimeOfDay = true,
6076
6236
  showPrice = true,
6237
+ schedulingMode = "intraday",
6238
+ durationUnit,
6239
+ durationValue,
6077
6240
  emptyMessage = "No available slots",
6078
6241
  className,
6079
6242
  classNames
6080
6243
  }) {
6244
+ const isMultiDay = schedulingMode === "multi_day";
6081
6245
  const { slots: fetched, isLoading } = useAvailableSlots(
6082
6246
  serviceId ?? null,
6083
6247
  date ?? null,
@@ -6108,7 +6272,7 @@ function SlotPicker({
6108
6272
  }
6109
6273
  );
6110
6274
  }
6111
- const groups = groupByTimeOfDay ? groupSlots(slots) : [{ label: "", slots }];
6275
+ const groups = groupByTimeOfDay && !isMultiDay ? groupSlots(slots) : [{ label: "", slots }];
6112
6276
  const slotsByValue = /* @__PURE__ */ new Map();
6113
6277
  for (const slot of slots) {
6114
6278
  slotsByValue.set(slotToValue(slot), slot);
@@ -6141,7 +6305,7 @@ function SlotPicker({
6141
6305
  "data-unavailable": !slot.is_available || void 0,
6142
6306
  className: classNames?.slot,
6143
6307
  children: [
6144
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: formatTime(slot.start_time) }),
6308
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime(slot.start_time) }),
6145
6309
  showPrice && slot.price && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-slot-price": true, className: classNames?.slotPrice, children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: slot.price }) })
6146
6310
  ]
6147
6311
  },
@@ -6172,6 +6336,9 @@ function DateSlotPicker({
6172
6336
  onSlotSelect,
6173
6337
  availability: availabilityProp,
6174
6338
  showPrice = true,
6339
+ schedulingMode,
6340
+ durationUnit,
6341
+ durationValue,
6175
6342
  className,
6176
6343
  classNames
6177
6344
  }) {
@@ -6289,7 +6456,10 @@ function DateSlotPicker({
6289
6456
  participantCount,
6290
6457
  selectedSlot,
6291
6458
  onSlotSelect: handleSlotSelect,
6292
- showPrice
6459
+ showPrice,
6460
+ schedulingMode,
6461
+ durationUnit,
6462
+ durationValue
6293
6463
  }
6294
6464
  ) })
6295
6465
  ]
@@ -13424,6 +13594,7 @@ exports.CompositeSelector = CompositeSelector;
13424
13594
  exports.CurrencySelector = CurrencySelector;
13425
13595
  exports.CustomAttributesTable = CustomAttributesTable;
13426
13596
  exports.CustomerInputFields = CustomerInputFields;
13597
+ exports.DatePicker = DatePicker;
13427
13598
  exports.DateSlotPicker = DateSlotPicker;
13428
13599
  exports.DealBanner = DealBanner;
13429
13600
  exports.DealsPage = DealsPage;
@@ -13481,6 +13652,7 @@ exports.StandardServiceCard = StandardServiceCard;
13481
13652
  exports.StoreNav = StoreNav;
13482
13653
  exports.SubscriptionCard = SubscriptionCard;
13483
13654
  exports.TagPills = TagPills;
13655
+ exports.TimePicker = TimePicker;
13484
13656
  exports.TwoColumnGrid = TwoColumnGrid;
13485
13657
  exports.VariantSelector = VariantSelector;
13486
13658
  exports.VolumePricing = VolumePricing;