@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.
- package/dist/advanced.d.mts +1 -1
- package/dist/advanced.d.ts +1 -1
- package/dist/advanced.js +20 -20
- package/dist/advanced.mjs +1 -1
- package/dist/{chunk-6HYKWYUF.mjs → chunk-24FK7VFL.mjs} +1 -1
- package/dist/{chunk-Z2MLAIID.js → chunk-CYGLTD7D.js} +35 -35
- package/dist/{chunk-TW4OFRWV.js → chunk-D22UVSFN.js} +2 -2
- package/dist/{chunk-7ZACMER7.js → chunk-DR4UPU6P.js} +0 -1
- package/dist/{chunk-WUIERJ6J.mjs → chunk-MBR2DBEN.mjs} +1 -1
- package/dist/{chunk-CKRMA5F7.mjs → chunk-OFNVLUH4.mjs} +0 -1
- package/dist/{client-QVINYu1X.d.ts → client-B8tJnOde.d.ts} +0 -1
- package/dist/{client-G2WCoxv2.d.mts → client-BZZK1txR.d.mts} +0 -1
- package/dist/{client-B76ZNW5r.d.ts → client-BdbvMtOU.d.ts} +1 -1
- package/dist/{client-CT9NwIDX.d.mts → client-BqCAm5vI.d.mts} +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +61 -61
- package/dist/index.mjs +2 -2
- package/dist/react.d.mts +113 -10
- package/dist/react.d.ts +113 -10
- package/dist/react.js +420 -248
- package/dist/react.mjs +405 -235
- package/dist/server.d.mts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +3 -3
- package/dist/server.mjs +2 -2
- package/dist/styles.css +1 -1
- package/dist/testing/suite.d.mts +2 -2
- package/dist/testing/suite.d.ts +2 -2
- package/dist/testing/suite.js +22 -22
- package/dist/testing/suite.mjs +3 -3
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +78 -78
- package/dist/testing.mjs +4 -4
- package/package.json +3 -1
- package/registry/customer-input-fields.json +1 -1
- package/registry/date-slot-picker.json +1 -1
- package/registry/slot-picker.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { DURATION_UNIT, getVariantDisplayName, INPUT_FIELD_TYPE, PRODUCT_TYPE, RENDER_HINT } from './chunk-NRDRVZ62.mjs';
|
|
3
3
|
export { getVariantDisplayName } from './chunk-NRDRVZ62.mjs';
|
|
4
|
-
import { createCimplifyClient } from './chunk-
|
|
5
|
-
import { ELEMENT_TYPES, EVENT_TYPES } from './chunk-
|
|
4
|
+
import { createCimplifyClient } from './chunk-MBR2DBEN.mjs';
|
|
5
|
+
import { ELEMENT_TYPES, EVENT_TYPES } from './chunk-OFNVLUH4.mjs';
|
|
6
6
|
import { formatPrice, parsePrice, getUnitPriceAtQuantity, isOnSale, getDiscountPercentage, getBasePrice, getPriceRange, formatPriceRange } from './chunk-XY2DFX5K.mjs';
|
|
7
7
|
import { isSupportedCurrency } from './chunk-Z2AYLZDF.mjs';
|
|
8
8
|
import React10, { createContext, useRef, useState, useCallback, useEffect, useContext, useMemo, useId, useSyncExternalStore } from 'react';
|
|
@@ -14,6 +14,9 @@ import { RadioGroup } from '@base-ui/react/radio-group';
|
|
|
14
14
|
import { Radio } from '@base-ui/react/radio';
|
|
15
15
|
import { Checkbox } from '@base-ui/react/checkbox';
|
|
16
16
|
import { Button } from '@base-ui/react/button';
|
|
17
|
+
import { Popover } from '@base-ui/react/popover';
|
|
18
|
+
import { DayPicker } from 'react-day-picker';
|
|
19
|
+
import { format, parseISO, isValid } from 'date-fns';
|
|
17
20
|
import { Tabs } from '@base-ui/react/tabs';
|
|
18
21
|
import { Dialog } from '@base-ui/react/dialog';
|
|
19
22
|
import { Field } from '@base-ui/react/field';
|
|
@@ -621,7 +624,8 @@ function useCollectionStore(collection) {
|
|
|
621
624
|
}
|
|
622
625
|
|
|
623
626
|
// src/react/hooks/use-cart.ts
|
|
624
|
-
var
|
|
627
|
+
var LEGACY_CART_STORAGE_PREFIX = "cimplify:cart:v3";
|
|
628
|
+
var legacyCachesPurged = false;
|
|
625
629
|
var cartStores = /* @__PURE__ */ new Map();
|
|
626
630
|
var ROLLBACK_VISIBLE_DELAY_MS = 3e3;
|
|
627
631
|
function clearAllCartStores() {
|
|
@@ -631,34 +635,35 @@ function clearAllCartStores() {
|
|
|
631
635
|
clearTimeout(handle);
|
|
632
636
|
}
|
|
633
637
|
entry.failedOpRemovers.clear();
|
|
634
|
-
if (entry.persistTimer) {
|
|
635
|
-
clearTimeout(entry.persistTimer);
|
|
636
|
-
entry.persistTimer = null;
|
|
637
|
-
}
|
|
638
638
|
}
|
|
639
639
|
cartStores.clear();
|
|
640
640
|
}
|
|
641
641
|
function emptyBase(currency, isLoading = true) {
|
|
642
642
|
return { items: [], subtotal: 0, tax: 0, total: 0, currency, isLoading };
|
|
643
643
|
}
|
|
644
|
-
function
|
|
645
|
-
const current = entry.collection.getBase() ?? emptyBase(entry.currency, false);
|
|
646
|
-
entry.collection.setBase({ ...applyCartPatch(current, patch), isLoading: false });
|
|
647
|
-
persistBase(entry);
|
|
648
|
-
}
|
|
649
|
-
function buildStoreKey(client, locationId, isDemoMode) {
|
|
644
|
+
function buildStoreKey(client, locationId) {
|
|
650
645
|
return [
|
|
651
|
-
client.getPublicKey() || "
|
|
652
|
-
locationId || "__no_location__"
|
|
653
|
-
isDemoMode ? "demo" : "live"
|
|
646
|
+
client.getPublicKey() || "__no_public_key__",
|
|
647
|
+
locationId || "__no_location__"
|
|
654
648
|
].join(":");
|
|
655
649
|
}
|
|
656
|
-
function
|
|
657
|
-
return
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
650
|
+
function purgeLegacyCartCachesOnce() {
|
|
651
|
+
if (legacyCachesPurged) return;
|
|
652
|
+
legacyCachesPurged = true;
|
|
653
|
+
if (typeof window === "undefined" || !window.localStorage) return;
|
|
654
|
+
try {
|
|
655
|
+
const keys = [];
|
|
656
|
+
for (let i = 0; i < window.localStorage.length; i += 1) {
|
|
657
|
+
const key = window.localStorage.key(i);
|
|
658
|
+
if (key && key.startsWith(LEGACY_CART_STORAGE_PREFIX)) {
|
|
659
|
+
keys.push(key);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
for (const key of keys) {
|
|
663
|
+
window.localStorage.removeItem(key);
|
|
664
|
+
}
|
|
665
|
+
} catch {
|
|
666
|
+
}
|
|
662
667
|
}
|
|
663
668
|
function toProductFromServerItem(item, businessId) {
|
|
664
669
|
return {
|
|
@@ -753,69 +758,13 @@ function deriveView(base, ops) {
|
|
|
753
758
|
pendingOpCount: ops.length
|
|
754
759
|
};
|
|
755
760
|
}
|
|
756
|
-
function persistBase(entry) {
|
|
757
|
-
if (typeof window === "undefined" || !window.localStorage) return;
|
|
758
|
-
if (!entry.isDemoMode) return;
|
|
759
|
-
if (entry.persistTimer) return;
|
|
760
|
-
entry.persistTimer = setTimeout(() => {
|
|
761
|
-
entry.persistTimer = null;
|
|
762
|
-
if (typeof window === "undefined" || !window.localStorage) return;
|
|
763
|
-
const base = entry.collection.getBase();
|
|
764
|
-
if (!base) return;
|
|
765
|
-
try {
|
|
766
|
-
window.localStorage.setItem(
|
|
767
|
-
entry.storageKey,
|
|
768
|
-
JSON.stringify({
|
|
769
|
-
items: base.items.map((item) => stripInternalItemMetadata(item)),
|
|
770
|
-
subtotal: base.subtotal,
|
|
771
|
-
tax: base.tax,
|
|
772
|
-
total: base.total,
|
|
773
|
-
currency: base.currency
|
|
774
|
-
})
|
|
775
|
-
);
|
|
776
|
-
} catch {
|
|
777
|
-
}
|
|
778
|
-
}, 100);
|
|
779
|
-
}
|
|
780
|
-
function hydrateFromStorage(entry) {
|
|
781
|
-
if (typeof window === "undefined" || !window.localStorage) return;
|
|
782
|
-
if (!entry.isDemoMode) {
|
|
783
|
-
try {
|
|
784
|
-
window.localStorage.removeItem(entry.storageKey);
|
|
785
|
-
} catch {
|
|
786
|
-
}
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
try {
|
|
790
|
-
const raw = window.localStorage.getItem(entry.storageKey);
|
|
791
|
-
if (!raw) return;
|
|
792
|
-
const parsed = JSON.parse(raw);
|
|
793
|
-
if (!parsed || !Array.isArray(parsed.items)) return;
|
|
794
|
-
const items = parsed.items.map((item) => attachInternalItemMetadata(item));
|
|
795
|
-
entry.collection.setBase({
|
|
796
|
-
items,
|
|
797
|
-
subtotal: toNumber(parsed.subtotal),
|
|
798
|
-
tax: toNumber(parsed.tax),
|
|
799
|
-
total: toNumber(parsed.total),
|
|
800
|
-
currency: typeof parsed.currency === "string" && parsed.currency ? parsed.currency : entry.currency,
|
|
801
|
-
isLoading: !entry.isDemoMode
|
|
802
|
-
});
|
|
803
|
-
} catch {
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
761
|
async function syncFromServer(entry) {
|
|
807
|
-
if (entry.isDemoMode) {
|
|
808
|
-
const base = entry.collection.getBase() ?? emptyBase(entry.currency);
|
|
809
|
-
entry.collection.setBase({ ...base, isLoading: false });
|
|
810
|
-
return;
|
|
811
|
-
}
|
|
812
762
|
if (entry.syncing) return;
|
|
813
763
|
entry.syncing = true;
|
|
814
764
|
try {
|
|
815
765
|
const result = await entry.client.cart.get();
|
|
816
766
|
if (!result.ok) throw result.error;
|
|
817
767
|
entry.collection.setBase(mapServerCart(result.value, entry.currency));
|
|
818
|
-
persistBase(entry);
|
|
819
768
|
} finally {
|
|
820
769
|
entry.syncing = false;
|
|
821
770
|
}
|
|
@@ -837,8 +786,9 @@ function scheduleFailedOpRemoval(entry, opId) {
|
|
|
837
786
|
entry.failedOpRemovers.add(handle);
|
|
838
787
|
}
|
|
839
788
|
function getOrCreateStore(params) {
|
|
840
|
-
const { client, locationId,
|
|
841
|
-
|
|
789
|
+
const { client, locationId, currency, optimisticEnabled } = params;
|
|
790
|
+
purgeLegacyCartCachesOnce();
|
|
791
|
+
const storeKey = buildStoreKey(client, locationId);
|
|
842
792
|
const existing = cartStores.get(storeKey);
|
|
843
793
|
if (existing) {
|
|
844
794
|
existing.optimisticEnabled = optimisticEnabled;
|
|
@@ -852,14 +802,11 @@ function getOrCreateStore(params) {
|
|
|
852
802
|
const entry = {
|
|
853
803
|
collection,
|
|
854
804
|
client,
|
|
855
|
-
storageKey: buildStorageKey(storeKey),
|
|
856
805
|
locationId,
|
|
857
806
|
currency,
|
|
858
|
-
isDemoMode,
|
|
859
807
|
optimisticEnabled,
|
|
860
808
|
initialized: false,
|
|
861
809
|
initializePromise: null,
|
|
862
|
-
persistTimer: null,
|
|
863
810
|
syncing: false,
|
|
864
811
|
failedOpRemovers: /* @__PURE__ */ new Set()
|
|
865
812
|
};
|
|
@@ -872,12 +819,6 @@ async function ensureInitialized(entry) {
|
|
|
872
819
|
return;
|
|
873
820
|
}
|
|
874
821
|
entry.initialized = true;
|
|
875
|
-
hydrateFromStorage(entry);
|
|
876
|
-
if (entry.isDemoMode) {
|
|
877
|
-
const base = entry.collection.getBase() ?? emptyBase(entry.currency);
|
|
878
|
-
entry.collection.setBase({ ...base, isLoading: false });
|
|
879
|
-
return;
|
|
880
|
-
}
|
|
881
822
|
entry.initializePromise = syncFromServer(entry).catch(() => {
|
|
882
823
|
const base = entry.collection.getBase() ?? emptyBase(entry.currency);
|
|
883
824
|
entry.collection.setBase({ ...base, isLoading: false });
|
|
@@ -891,7 +832,7 @@ async function maybeResolveQuoteId(entry, product, quantity, options) {
|
|
|
891
832
|
const requiresQuote = Boolean(
|
|
892
833
|
options.variantId || addOnOptionIds && addOnOptionIds.length > 0 || options.bundleSelections && options.bundleSelections.length > 0 || options.compositeSelections && options.compositeSelections.length > 0
|
|
893
834
|
);
|
|
894
|
-
if (!requiresQuote
|
|
835
|
+
if (!requiresQuote) return void 0;
|
|
895
836
|
const quoteResult = await entry.client.catalogue.fetchQuote({
|
|
896
837
|
product_id: product.id,
|
|
897
838
|
quantity,
|
|
@@ -931,10 +872,6 @@ async function performAddItem(entry, product, quantity, options) {
|
|
|
931
872
|
});
|
|
932
873
|
const idempotencyKey = `idem_${typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`}`;
|
|
933
874
|
const patch = { kind: "add_item", tempItem, lineKey };
|
|
934
|
-
if (entry.isDemoMode) {
|
|
935
|
-
advanceBaseWithPatch(entry, patch);
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
875
|
const useOptimistic = entry.optimisticEnabled;
|
|
939
876
|
const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
|
|
940
877
|
try {
|
|
@@ -973,10 +910,6 @@ async function performAddItem(entry, product, quantity, options) {
|
|
|
973
910
|
async function performRemoveItem(entry, itemId) {
|
|
974
911
|
const idempotencyKey = "";
|
|
975
912
|
const patch = { kind: "remove_item", itemId };
|
|
976
|
-
if (entry.isDemoMode) {
|
|
977
|
-
advanceBaseWithPatch(entry, patch);
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
980
913
|
const useOptimistic = entry.optimisticEnabled;
|
|
981
914
|
const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
|
|
982
915
|
try {
|
|
@@ -1001,10 +934,6 @@ async function performUpdateQuantity(entry, itemId, quantity) {
|
|
|
1001
934
|
const resolved = clampQuantity(quantity);
|
|
1002
935
|
const idempotencyKey = "";
|
|
1003
936
|
const patch = { kind: "set_quantity", itemId, quantity: resolved };
|
|
1004
|
-
if (entry.isDemoMode) {
|
|
1005
|
-
advanceBaseWithPatch(entry, patch);
|
|
1006
|
-
return;
|
|
1007
|
-
}
|
|
1008
937
|
const useOptimistic = entry.optimisticEnabled;
|
|
1009
938
|
const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
|
|
1010
939
|
try {
|
|
@@ -1025,10 +954,6 @@ async function performUpdateQuantity(entry, itemId, quantity) {
|
|
|
1025
954
|
async function performClear(entry) {
|
|
1026
955
|
const idempotencyKey = "";
|
|
1027
956
|
const patch = { kind: "clear" };
|
|
1028
|
-
if (entry.isDemoMode) {
|
|
1029
|
-
advanceBaseWithPatch(entry, patch);
|
|
1030
|
-
return;
|
|
1031
|
-
}
|
|
1032
957
|
const useOptimistic = entry.optimisticEnabled;
|
|
1033
958
|
const opId = useOptimistic ? entry.collection.enqueue(patch, idempotencyKey) : null;
|
|
1034
959
|
try {
|
|
@@ -1059,18 +984,16 @@ function useCart(options = {}) {
|
|
|
1059
984
|
throw new Error("useCart must be used within CimplifyProvider or passed { client }.");
|
|
1060
985
|
}
|
|
1061
986
|
const locationId = options.locationId ?? client.getLocationId();
|
|
1062
|
-
const isDemoMode = options.demoMode ?? context?.isDemoMode ?? client.getPublicKey().trim().length === 0;
|
|
1063
987
|
const currency = options.currency ?? context?.currency ?? "USD";
|
|
1064
988
|
const optimisticEnabled = context?.optimistic ?? true;
|
|
1065
989
|
const entry = useMemo(
|
|
1066
990
|
() => getOrCreateStore({
|
|
1067
991
|
client,
|
|
1068
992
|
locationId,
|
|
1069
|
-
isDemoMode,
|
|
1070
993
|
currency,
|
|
1071
994
|
optimisticEnabled
|
|
1072
995
|
}),
|
|
1073
|
-
[client, currency,
|
|
996
|
+
[client, currency, locationId, optimisticEnabled]
|
|
1074
997
|
);
|
|
1075
998
|
const view = useCollectionStore(entry.collection);
|
|
1076
999
|
useEffect(() => {
|
|
@@ -1230,7 +1153,6 @@ function CimplifyProvider({
|
|
|
1230
1153
|
useEffect(() => {
|
|
1231
1154
|
onLocationChangeRef.current = onLocationChange;
|
|
1232
1155
|
}, [onLocationChange]);
|
|
1233
|
-
const isDemoMode = resolvedClient.getPublicKey().trim().length === 0;
|
|
1234
1156
|
const baseCurrency = business?.default_currency || DEFAULT_CURRENCY;
|
|
1235
1157
|
const [displayCurrencyOverride, setDisplayCurrencyOverride] = useState(
|
|
1236
1158
|
() => getStoredDisplayCurrency()
|
|
@@ -1252,7 +1174,7 @@ function CimplifyProvider({
|
|
|
1252
1174
|
[baseCurrency]
|
|
1253
1175
|
);
|
|
1254
1176
|
useEffect(() => {
|
|
1255
|
-
if (displayCurrency === baseCurrency
|
|
1177
|
+
if (displayCurrency === baseCurrency) {
|
|
1256
1178
|
setFxRate(null);
|
|
1257
1179
|
return;
|
|
1258
1180
|
}
|
|
@@ -1275,7 +1197,7 @@ function CimplifyProvider({
|
|
|
1275
1197
|
cancelled = true;
|
|
1276
1198
|
clearInterval(intervalId);
|
|
1277
1199
|
};
|
|
1278
|
-
}, [resolvedClient, baseCurrency, displayCurrency
|
|
1200
|
+
}, [resolvedClient, baseCurrency, displayCurrency]);
|
|
1279
1201
|
const convertPrice = useCallback(
|
|
1280
1202
|
(amount) => {
|
|
1281
1203
|
const num = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
@@ -1302,17 +1224,6 @@ function CimplifyProvider({
|
|
|
1302
1224
|
let cancelled = false;
|
|
1303
1225
|
async function bootstrap() {
|
|
1304
1226
|
setIsReady(false);
|
|
1305
|
-
if (isDemoMode) {
|
|
1306
|
-
if (!cancelled) {
|
|
1307
|
-
setBusiness(null);
|
|
1308
|
-
setLocations([]);
|
|
1309
|
-
setCurrentLocationState(null);
|
|
1310
|
-
resolvedClient.setLocationId(null);
|
|
1311
|
-
setStoredLocationId(null);
|
|
1312
|
-
setIsReady(true);
|
|
1313
|
-
}
|
|
1314
|
-
return;
|
|
1315
|
-
}
|
|
1316
1227
|
const [businessResult, locationsResult] = await Promise.all([
|
|
1317
1228
|
resolvedClient.business.getInfo(),
|
|
1318
1229
|
resolvedClient.business.getLocations()
|
|
@@ -1353,7 +1264,7 @@ function CimplifyProvider({
|
|
|
1353
1264
|
return () => {
|
|
1354
1265
|
cancelled = true;
|
|
1355
1266
|
};
|
|
1356
|
-
}, [resolvedClient
|
|
1267
|
+
}, [resolvedClient]);
|
|
1357
1268
|
const clientContextValue = useMemo(
|
|
1358
1269
|
() => ({
|
|
1359
1270
|
client: resolvedClient,
|
|
@@ -1362,7 +1273,6 @@ function CimplifyProvider({
|
|
|
1362
1273
|
country: business?.country_code || DEFAULT_COUNTRY,
|
|
1363
1274
|
locations,
|
|
1364
1275
|
isReady,
|
|
1365
|
-
isDemoMode,
|
|
1366
1276
|
baseCurrency,
|
|
1367
1277
|
optimistic
|
|
1368
1278
|
}),
|
|
@@ -1372,7 +1282,6 @@ function CimplifyProvider({
|
|
|
1372
1282
|
baseCurrency,
|
|
1373
1283
|
locations,
|
|
1374
1284
|
isReady,
|
|
1375
|
-
isDemoMode,
|
|
1376
1285
|
optimistic
|
|
1377
1286
|
]
|
|
1378
1287
|
);
|
|
@@ -1427,16 +1336,10 @@ function useCimplifyClient() {
|
|
|
1427
1336
|
function useOptionalCimplifyClient() {
|
|
1428
1337
|
return useContext(CimplifyClientContext);
|
|
1429
1338
|
}
|
|
1430
|
-
|
|
1431
|
-
function shellColors(isDark, primaryColor) {
|
|
1339
|
+
function shellColors(isDark) {
|
|
1432
1340
|
return {
|
|
1433
|
-
text: isDark ? "#f4f4f5" : "#1a1a1a",
|
|
1434
1341
|
textSecondary: isDark ? "#a1a1aa" : "#52525b",
|
|
1435
|
-
|
|
1436
|
-
border: isDark ? "#27272a" : "#e4e4e7",
|
|
1437
|
-
surface: isDark ? "#18181b" : "#fafafa",
|
|
1438
|
-
error: "#dc2626",
|
|
1439
|
-
primary: primaryColor
|
|
1342
|
+
error: "#dc2626"
|
|
1440
1343
|
};
|
|
1441
1344
|
}
|
|
1442
1345
|
function statusToLabel(status) {
|
|
@@ -1480,7 +1383,6 @@ function CimplifyCheckout({
|
|
|
1480
1383
|
onError,
|
|
1481
1384
|
onStatusChange,
|
|
1482
1385
|
appearance,
|
|
1483
|
-
demoMode,
|
|
1484
1386
|
className
|
|
1485
1387
|
}) {
|
|
1486
1388
|
const resolvedOrderTypes = useMemo(
|
|
@@ -1508,8 +1410,6 @@ function CimplifyCheckout({
|
|
|
1508
1410
|
const initialAppearanceRef = useRef(appearance);
|
|
1509
1411
|
const hasWarnedInlineAppearanceRef = useRef(false);
|
|
1510
1412
|
const isMountedRef = useRef(true);
|
|
1511
|
-
const demoRunRef = useRef(0);
|
|
1512
|
-
const isDemoCheckout = demoMode ?? client.getPublicKey().trim().length === 0;
|
|
1513
1413
|
const isTestMode = client.isTestMode();
|
|
1514
1414
|
const cimplifyCtx = useOptionalCimplify();
|
|
1515
1415
|
const fxOptions = useMemo(() => {
|
|
@@ -1524,7 +1424,6 @@ function CimplifyCheckout({
|
|
|
1524
1424
|
fxOptionsRef.current = fxOptions;
|
|
1525
1425
|
const resolvedCartRef = useRef(resolvedCart);
|
|
1526
1426
|
resolvedCartRef.current = resolvedCart;
|
|
1527
|
-
const primaryColor = appearance?.variables?.primaryColor || "#0a2540";
|
|
1528
1427
|
const isDark = appearance?.theme === "dark";
|
|
1529
1428
|
const emitStatus = React10.useEffectEvent(
|
|
1530
1429
|
(nextStatus, context = {}) => {
|
|
@@ -1554,15 +1453,6 @@ function CimplifyCheckout({
|
|
|
1554
1453
|
useEffect(() => {
|
|
1555
1454
|
let cancelled = false;
|
|
1556
1455
|
async function bootstrap() {
|
|
1557
|
-
if (isDemoCheckout) {
|
|
1558
|
-
if (!cancelled) {
|
|
1559
|
-
setResolvedBusinessId(businessId ?? null);
|
|
1560
|
-
setResolvedCartId(cartId ?? "cart_demo");
|
|
1561
|
-
setIsInitializing(false);
|
|
1562
|
-
setErrorMessage(null);
|
|
1563
|
-
}
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1566
1456
|
const needsBusinessResolve = !businessId;
|
|
1567
1457
|
const needsCartResolve = !cartId;
|
|
1568
1458
|
if (!needsBusinessResolve && !needsCartResolve) {
|
|
@@ -1630,11 +1520,10 @@ function CimplifyCheckout({
|
|
|
1630
1520
|
return () => {
|
|
1631
1521
|
cancelled = true;
|
|
1632
1522
|
};
|
|
1633
|
-
}, [businessId, cartId, client
|
|
1523
|
+
}, [businessId, cartId, client]);
|
|
1634
1524
|
useEffect(() => {
|
|
1635
1525
|
return () => {
|
|
1636
1526
|
isMountedRef.current = false;
|
|
1637
|
-
demoRunRef.current += 1;
|
|
1638
1527
|
activeCheckoutRef.current?.abort();
|
|
1639
1528
|
activeCheckoutRef.current = null;
|
|
1640
1529
|
};
|
|
@@ -1651,42 +1540,6 @@ function CimplifyCheckout({
|
|
|
1651
1540
|
setErrorMessage(null);
|
|
1652
1541
|
setIsSubmitting(true);
|
|
1653
1542
|
emitStatus("preparing", { display_text: statusToLabel("preparing") });
|
|
1654
|
-
if (isDemoCheckout) {
|
|
1655
|
-
const runId = demoRunRef.current + 1;
|
|
1656
|
-
demoRunRef.current = runId;
|
|
1657
|
-
const wait = async (ms) => {
|
|
1658
|
-
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
1659
|
-
return isMountedRef.current && runId === demoRunRef.current;
|
|
1660
|
-
};
|
|
1661
|
-
try {
|
|
1662
|
-
if (!await wait(400)) return;
|
|
1663
|
-
emitStatus("processing", { display_text: statusToLabel("processing") });
|
|
1664
|
-
if (!await wait(900)) return;
|
|
1665
|
-
emitStatus("polling", { display_text: statusToLabel("polling") });
|
|
1666
|
-
if (!await wait(1200)) return;
|
|
1667
|
-
const result = {
|
|
1668
|
-
success: true,
|
|
1669
|
-
order: {
|
|
1670
|
-
id: `ord_demo_${Date.now()}`,
|
|
1671
|
-
order_number: `DEMO-${Math.random().toString(36).slice(2, 8).toUpperCase()}`,
|
|
1672
|
-
status: "confirmed",
|
|
1673
|
-
total: "0.00",
|
|
1674
|
-
currency: "USD"
|
|
1675
|
-
}
|
|
1676
|
-
};
|
|
1677
|
-
emitStatus("success", {
|
|
1678
|
-
order_id: result.order?.id,
|
|
1679
|
-
order_number: result.order?.order_number,
|
|
1680
|
-
display_text: statusToLabel("success")
|
|
1681
|
-
});
|
|
1682
|
-
onComplete(result);
|
|
1683
|
-
} finally {
|
|
1684
|
-
if (isMountedRef.current && runId === demoRunRef.current) {
|
|
1685
|
-
setIsSubmitting(false);
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
return;
|
|
1689
|
-
}
|
|
1690
1543
|
if (!elementsRef.current) {
|
|
1691
1544
|
const message = "Checkout is still initializing. Please try again.";
|
|
1692
1545
|
setErrorMessage(message);
|
|
@@ -1721,7 +1574,7 @@ function CimplifyCheckout({
|
|
|
1721
1574
|
}
|
|
1722
1575
|
});
|
|
1723
1576
|
useEffect(() => {
|
|
1724
|
-
if (
|
|
1577
|
+
if (!resolvedBusinessId) {
|
|
1725
1578
|
elementsRef.current = null;
|
|
1726
1579
|
return;
|
|
1727
1580
|
}
|
|
@@ -1762,7 +1615,6 @@ function CimplifyCheckout({
|
|
|
1762
1615
|
}, [
|
|
1763
1616
|
client,
|
|
1764
1617
|
resolvedBusinessId,
|
|
1765
|
-
isDemoCheckout,
|
|
1766
1618
|
resolvedOrderTypes,
|
|
1767
1619
|
resolvedDefaultOrderType,
|
|
1768
1620
|
submitLabel
|
|
@@ -1774,15 +1626,15 @@ function CimplifyCheckout({
|
|
|
1774
1626
|
checkoutElement.setCart(transformToCheckoutCart(resolvedCart, fxOptions));
|
|
1775
1627
|
}
|
|
1776
1628
|
}, [resolvedCart, fxOptions]);
|
|
1777
|
-
const colors = shellColors(isDark ?? false
|
|
1629
|
+
const colors = shellColors(isDark ?? false);
|
|
1778
1630
|
if (isInitializing) {
|
|
1779
1631
|
return /* @__PURE__ */ jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsx("p", { "data-cimplify-status": "", style: { fontSize: 13, color: colors.textSecondary }, children: "Preparing checkout..." }) });
|
|
1780
1632
|
}
|
|
1781
|
-
if (!
|
|
1633
|
+
if (!resolvedBusinessId || !resolvedCartId) {
|
|
1782
1634
|
return /* @__PURE__ */ jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsx("p", { "data-cimplify-error": "", style: { fontSize: 13, color: colors.error }, children: errorMessage || "Unable to initialize checkout. Please refresh and try again." }) });
|
|
1783
1635
|
}
|
|
1784
1636
|
return /* @__PURE__ */ jsxs("div", { className, "data-cimplify-checkout": "", children: [
|
|
1785
|
-
isTestMode &&
|
|
1637
|
+
isTestMode && /* @__PURE__ */ jsx(
|
|
1786
1638
|
"p",
|
|
1787
1639
|
{
|
|
1788
1640
|
"data-cimplify-test-mode": "",
|
|
@@ -1795,9 +1647,9 @@ function CimplifyCheckout({
|
|
|
1795
1647
|
children: "Test mode - no real charges"
|
|
1796
1648
|
}
|
|
1797
1649
|
),
|
|
1798
|
-
/* @__PURE__ */ jsx("div", { "data-cimplify-section": "checkout", children: /* @__PURE__ */ jsx("div", { ref:
|
|
1799
|
-
status && /* @__PURE__ */ jsx("p", { "data-cimplify-status": "", style: { marginTop:
|
|
1800
|
-
errorMessage && /* @__PURE__ */ jsx("p", { "data-cimplify-error": "", style: { marginTop:
|
|
1650
|
+
/* @__PURE__ */ jsx("div", { "data-cimplify-section": "checkout", children: /* @__PURE__ */ jsx("div", { ref: checkoutMountRef }) }),
|
|
1651
|
+
status && /* @__PURE__ */ jsx("p", { "data-cimplify-status": "", style: { marginTop: 8, fontSize: 13, color: colors.textSecondary }, children: statusText || statusToLabel(status) }),
|
|
1652
|
+
errorMessage && /* @__PURE__ */ jsx("p", { "data-cimplify-error": "", style: { marginTop: 8, fontSize: 13, color: colors.error }, children: errorMessage })
|
|
1801
1653
|
] });
|
|
1802
1654
|
}
|
|
1803
1655
|
function cn(...inputs) {
|
|
@@ -5145,6 +4997,262 @@ function VolumePricing({
|
|
|
5145
4997
|
}
|
|
5146
4998
|
);
|
|
5147
4999
|
}
|
|
5000
|
+
function parseValue(value) {
|
|
5001
|
+
if (!value) return void 0;
|
|
5002
|
+
const date = parseISO(value);
|
|
5003
|
+
return isValid(date) ? date : void 0;
|
|
5004
|
+
}
|
|
5005
|
+
function formatValue(date) {
|
|
5006
|
+
return format(date, "yyyy-MM-dd");
|
|
5007
|
+
}
|
|
5008
|
+
function DatePicker({
|
|
5009
|
+
value,
|
|
5010
|
+
onChange,
|
|
5011
|
+
placeholder = "Select a date",
|
|
5012
|
+
minDate,
|
|
5013
|
+
maxDate,
|
|
5014
|
+
disabled,
|
|
5015
|
+
triggerDisabled,
|
|
5016
|
+
name,
|
|
5017
|
+
required,
|
|
5018
|
+
className,
|
|
5019
|
+
classNames,
|
|
5020
|
+
"aria-label": ariaLabel
|
|
5021
|
+
}) {
|
|
5022
|
+
const [open, setOpen] = useState(false);
|
|
5023
|
+
const selected = parseValue(value);
|
|
5024
|
+
const disabledMatchers = [];
|
|
5025
|
+
if (minDate) disabledMatchers.push({ before: minDate });
|
|
5026
|
+
if (maxDate) disabledMatchers.push({ after: maxDate });
|
|
5027
|
+
if (Array.isArray(disabled)) {
|
|
5028
|
+
disabledMatchers.push(...disabled);
|
|
5029
|
+
} else if (disabled) {
|
|
5030
|
+
disabledMatchers.push(disabled);
|
|
5031
|
+
}
|
|
5032
|
+
return /* @__PURE__ */ jsxs("div", { "data-cimplify-date-picker": true, className: cn(className, classNames?.root), children: [
|
|
5033
|
+
/* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
|
|
5034
|
+
/* @__PURE__ */ jsxs(
|
|
5035
|
+
Popover.Trigger,
|
|
5036
|
+
{
|
|
5037
|
+
type: "button",
|
|
5038
|
+
"aria-label": ariaLabel ?? placeholder,
|
|
5039
|
+
disabled: triggerDisabled,
|
|
5040
|
+
className: cn(
|
|
5041
|
+
"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",
|
|
5042
|
+
classNames?.trigger
|
|
5043
|
+
),
|
|
5044
|
+
children: [
|
|
5045
|
+
/* @__PURE__ */ jsx("span", { className: cn(!selected && "text-muted-foreground"), children: selected ? format(selected, "EEE, MMM d, yyyy") : placeholder }),
|
|
5046
|
+
/* @__PURE__ */ jsxs(
|
|
5047
|
+
"svg",
|
|
5048
|
+
{
|
|
5049
|
+
width: "16",
|
|
5050
|
+
height: "16",
|
|
5051
|
+
viewBox: "0 0 24 24",
|
|
5052
|
+
fill: "none",
|
|
5053
|
+
stroke: "currentColor",
|
|
5054
|
+
strokeWidth: "2",
|
|
5055
|
+
strokeLinecap: "round",
|
|
5056
|
+
strokeLinejoin: "round",
|
|
5057
|
+
"aria-hidden": "true",
|
|
5058
|
+
className: "shrink-0 text-muted-foreground",
|
|
5059
|
+
children: [
|
|
5060
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
|
|
5061
|
+
/* @__PURE__ */ jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
|
|
5062
|
+
/* @__PURE__ */ jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
|
|
5063
|
+
/* @__PURE__ */ jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
|
|
5064
|
+
]
|
|
5065
|
+
}
|
|
5066
|
+
)
|
|
5067
|
+
]
|
|
5068
|
+
}
|
|
5069
|
+
),
|
|
5070
|
+
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, { sideOffset: 6, align: "start", children: /* @__PURE__ */ jsx(
|
|
5071
|
+
Popover.Popup,
|
|
5072
|
+
{
|
|
5073
|
+
className: cn(
|
|
5074
|
+
"z-50 rounded-lg border border-border bg-background p-3 shadow-lg outline-none",
|
|
5075
|
+
classNames?.popup
|
|
5076
|
+
),
|
|
5077
|
+
children: /* @__PURE__ */ jsx(
|
|
5078
|
+
DayPicker,
|
|
5079
|
+
{
|
|
5080
|
+
mode: "single",
|
|
5081
|
+
selected,
|
|
5082
|
+
onSelect: (date) => {
|
|
5083
|
+
onChange?.(date ? formatValue(date) : "");
|
|
5084
|
+
if (date) setOpen(false);
|
|
5085
|
+
},
|
|
5086
|
+
disabled: disabledMatchers.length > 0 ? disabledMatchers : void 0,
|
|
5087
|
+
showOutsideDays: true,
|
|
5088
|
+
weekStartsOn: 0,
|
|
5089
|
+
className: cn("p-0", classNames?.calendar),
|
|
5090
|
+
classNames: {
|
|
5091
|
+
months: "flex flex-col gap-3",
|
|
5092
|
+
month: "flex flex-col gap-3",
|
|
5093
|
+
caption: "flex items-center justify-between px-1",
|
|
5094
|
+
caption_label: "text-sm font-semibold",
|
|
5095
|
+
nav: "flex items-center gap-1",
|
|
5096
|
+
nav_button: "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-muted transition-colors",
|
|
5097
|
+
table: "w-full border-collapse",
|
|
5098
|
+
head_row: "flex",
|
|
5099
|
+
head_cell: "w-9 text-center text-[10px] font-medium uppercase tracking-wider text-muted-foreground",
|
|
5100
|
+
row: "flex w-full mt-1",
|
|
5101
|
+
cell: "w-9 h-9 text-center text-sm p-0 relative",
|
|
5102
|
+
day: cn(
|
|
5103
|
+
"inline-flex h-9 w-9 items-center justify-center rounded-md text-sm font-normal text-foreground hover:bg-muted transition-colors",
|
|
5104
|
+
"aria-selected:bg-foreground aria-selected:text-background aria-selected:hover:bg-foreground/90"
|
|
5105
|
+
),
|
|
5106
|
+
day_selected: cn(
|
|
5107
|
+
"bg-foreground text-background hover:bg-foreground/90 focus:bg-foreground",
|
|
5108
|
+
classNames?.daySelected
|
|
5109
|
+
),
|
|
5110
|
+
day_today: cn(
|
|
5111
|
+
"ring-1 ring-inset ring-primary/40",
|
|
5112
|
+
classNames?.dayToday
|
|
5113
|
+
),
|
|
5114
|
+
day_outside: "text-muted-foreground/50",
|
|
5115
|
+
day_disabled: cn(
|
|
5116
|
+
"text-muted-foreground/40 cursor-not-allowed line-through",
|
|
5117
|
+
classNames?.dayDisabled
|
|
5118
|
+
)
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
)
|
|
5122
|
+
}
|
|
5123
|
+
) }) })
|
|
5124
|
+
] }),
|
|
5125
|
+
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: value ?? "", required }) : null
|
|
5126
|
+
] });
|
|
5127
|
+
}
|
|
5128
|
+
function parseHHmm(value) {
|
|
5129
|
+
if (!value) return null;
|
|
5130
|
+
const match = /^(\d{1,2}):(\d{2})$/.exec(value);
|
|
5131
|
+
if (!match) return null;
|
|
5132
|
+
const hour = Number.parseInt(match[1] ?? "", 10);
|
|
5133
|
+
const minute = Number.parseInt(match[2] ?? "", 10);
|
|
5134
|
+
if (Number.isNaN(hour) || Number.isNaN(minute)) return null;
|
|
5135
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) return null;
|
|
5136
|
+
return { hour, minute };
|
|
5137
|
+
}
|
|
5138
|
+
function formatHHmm(hour, minute) {
|
|
5139
|
+
return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
|
|
5140
|
+
}
|
|
5141
|
+
function formatDisplay(hour, minute, displayFormat) {
|
|
5142
|
+
if (displayFormat === "24h") {
|
|
5143
|
+
return formatHHmm(hour, minute);
|
|
5144
|
+
}
|
|
5145
|
+
const period = hour >= 12 ? "PM" : "AM";
|
|
5146
|
+
const displayHour = hour % 12 || 12;
|
|
5147
|
+
return `${displayHour}:${String(minute).padStart(2, "0")} ${period}`;
|
|
5148
|
+
}
|
|
5149
|
+
function buildOptions(minTime, maxTime, stepMinutes) {
|
|
5150
|
+
const min = parseHHmm(minTime) ?? { hour: 0, minute: 0 };
|
|
5151
|
+
const max = parseHHmm(maxTime) ?? { hour: 23, minute: 59 };
|
|
5152
|
+
const minTotal = min.hour * 60 + min.minute;
|
|
5153
|
+
const maxTotal = max.hour * 60 + max.minute;
|
|
5154
|
+
const step = Math.max(1, stepMinutes);
|
|
5155
|
+
const out = [];
|
|
5156
|
+
for (let total = minTotal; total <= maxTotal; total += step) {
|
|
5157
|
+
out.push(formatHHmm(Math.floor(total / 60), total % 60));
|
|
5158
|
+
}
|
|
5159
|
+
return out;
|
|
5160
|
+
}
|
|
5161
|
+
function TimePicker({
|
|
5162
|
+
value,
|
|
5163
|
+
onChange,
|
|
5164
|
+
placeholder = "Select a time",
|
|
5165
|
+
minTime = "00:00",
|
|
5166
|
+
maxTime = "23:30",
|
|
5167
|
+
stepMinutes = 30,
|
|
5168
|
+
displayFormat = "12h",
|
|
5169
|
+
triggerDisabled,
|
|
5170
|
+
name,
|
|
5171
|
+
required,
|
|
5172
|
+
className,
|
|
5173
|
+
classNames,
|
|
5174
|
+
"aria-label": ariaLabel
|
|
5175
|
+
}) {
|
|
5176
|
+
const [open, setOpen] = useState(false);
|
|
5177
|
+
const parsed = parseHHmm(value);
|
|
5178
|
+
const options = useMemo(
|
|
5179
|
+
() => buildOptions(minTime, maxTime, stepMinutes),
|
|
5180
|
+
[minTime, maxTime, stepMinutes]
|
|
5181
|
+
);
|
|
5182
|
+
const triggerLabel = parsed ? formatDisplay(parsed.hour, parsed.minute, displayFormat) : placeholder;
|
|
5183
|
+
return /* @__PURE__ */ jsxs("div", { "data-cimplify-time-picker": true, className: cn(className, classNames?.root), children: [
|
|
5184
|
+
/* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
|
|
5185
|
+
/* @__PURE__ */ jsxs(
|
|
5186
|
+
Popover.Trigger,
|
|
5187
|
+
{
|
|
5188
|
+
type: "button",
|
|
5189
|
+
"aria-label": ariaLabel ?? placeholder,
|
|
5190
|
+
disabled: triggerDisabled,
|
|
5191
|
+
className: cn(
|
|
5192
|
+
"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",
|
|
5193
|
+
classNames?.trigger
|
|
5194
|
+
),
|
|
5195
|
+
children: [
|
|
5196
|
+
/* @__PURE__ */ jsx("span", { className: cn(!parsed && "text-muted-foreground"), children: triggerLabel }),
|
|
5197
|
+
/* @__PURE__ */ jsxs(
|
|
5198
|
+
"svg",
|
|
5199
|
+
{
|
|
5200
|
+
width: "16",
|
|
5201
|
+
height: "16",
|
|
5202
|
+
viewBox: "0 0 24 24",
|
|
5203
|
+
fill: "none",
|
|
5204
|
+
stroke: "currentColor",
|
|
5205
|
+
strokeWidth: "2",
|
|
5206
|
+
strokeLinecap: "round",
|
|
5207
|
+
strokeLinejoin: "round",
|
|
5208
|
+
"aria-hidden": "true",
|
|
5209
|
+
className: "shrink-0 text-muted-foreground",
|
|
5210
|
+
children: [
|
|
5211
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
5212
|
+
/* @__PURE__ */ jsx("polyline", { points: "12 7 12 12 15 14" })
|
|
5213
|
+
]
|
|
5214
|
+
}
|
|
5215
|
+
)
|
|
5216
|
+
]
|
|
5217
|
+
}
|
|
5218
|
+
),
|
|
5219
|
+
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, { sideOffset: 6, align: "start", children: /* @__PURE__ */ jsx(
|
|
5220
|
+
Popover.Popup,
|
|
5221
|
+
{
|
|
5222
|
+
className: cn(
|
|
5223
|
+
"z-50 max-h-64 overflow-y-auto rounded-lg border border-border bg-background p-1 shadow-lg outline-none",
|
|
5224
|
+
classNames?.popup
|
|
5225
|
+
),
|
|
5226
|
+
children: /* @__PURE__ */ jsx("ul", { role: "listbox", "aria-label": ariaLabel ?? placeholder, className: "flex flex-col", children: options.map((option) => {
|
|
5227
|
+
const isSelected = option === value;
|
|
5228
|
+
const opt = parseHHmm(option);
|
|
5229
|
+
if (!opt) return null;
|
|
5230
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
5231
|
+
"button",
|
|
5232
|
+
{
|
|
5233
|
+
type: "button",
|
|
5234
|
+
role: "option",
|
|
5235
|
+
"aria-selected": isSelected,
|
|
5236
|
+
onClick: () => {
|
|
5237
|
+
onChange?.(option);
|
|
5238
|
+
setOpen(false);
|
|
5239
|
+
},
|
|
5240
|
+
className: cn(
|
|
5241
|
+
"w-full rounded-md px-3 py-2 text-left text-sm transition-colors hover:bg-muted",
|
|
5242
|
+
isSelected && "bg-foreground text-background hover:bg-foreground/90",
|
|
5243
|
+
classNames?.option,
|
|
5244
|
+
isSelected && classNames?.optionSelected
|
|
5245
|
+
),
|
|
5246
|
+
children: formatDisplay(opt.hour, opt.minute, displayFormat)
|
|
5247
|
+
}
|
|
5248
|
+
) }, option);
|
|
5249
|
+
}) })
|
|
5250
|
+
}
|
|
5251
|
+
) }) })
|
|
5252
|
+
] }),
|
|
5253
|
+
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: value ?? "", required }) : null
|
|
5254
|
+
] });
|
|
5255
|
+
}
|
|
5148
5256
|
function CustomerInputFields({
|
|
5149
5257
|
fields,
|
|
5150
5258
|
values,
|
|
@@ -5331,13 +5439,13 @@ function FieldInput({
|
|
|
5331
5439
|
);
|
|
5332
5440
|
case INPUT_FIELD_TYPE.Date:
|
|
5333
5441
|
return /* @__PURE__ */ jsx(
|
|
5334
|
-
|
|
5442
|
+
DatePicker,
|
|
5335
5443
|
{
|
|
5336
|
-
type: "date",
|
|
5337
5444
|
value: typeof value === "string" ? value : "",
|
|
5338
|
-
onChange: (
|
|
5445
|
+
onChange: (next) => onValueChange(next || void 0),
|
|
5339
5446
|
required: field.is_required,
|
|
5340
|
-
|
|
5447
|
+
placeholder: field.placeholder ?? "Select a date",
|
|
5448
|
+
"aria-label": field.name
|
|
5341
5449
|
}
|
|
5342
5450
|
);
|
|
5343
5451
|
case INPUT_FIELD_TYPE.File:
|
|
@@ -5365,34 +5473,53 @@ function FieldInput({
|
|
|
5365
5473
|
}
|
|
5366
5474
|
);
|
|
5367
5475
|
case INPUT_FIELD_TYPE.DateTime: {
|
|
5368
|
-
const
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
if (!e.target.value) {
|
|
5376
|
-
onValueChange(void 0);
|
|
5377
|
-
return;
|
|
5378
|
-
}
|
|
5379
|
-
const date = new Date(e.target.value);
|
|
5380
|
-
onValueChange(Number.isNaN(date.getTime()) ? e.target.value : date.toISOString());
|
|
5381
|
-
},
|
|
5382
|
-
required: field.is_required,
|
|
5383
|
-
className: inputClass
|
|
5476
|
+
const stringValue = typeof value === "string" ? value : "";
|
|
5477
|
+
const [datePart, timePartRaw] = stringValue.includes("T") ? stringValue.split("T", 2) : [stringValue, ""];
|
|
5478
|
+
const timePart = (timePartRaw ?? "").slice(0, 5);
|
|
5479
|
+
const commit = (nextDate, nextTime) => {
|
|
5480
|
+
if (!nextDate && !nextTime) {
|
|
5481
|
+
onValueChange(void 0);
|
|
5482
|
+
return;
|
|
5384
5483
|
}
|
|
5385
|
-
|
|
5484
|
+
if (!nextDate) {
|
|
5485
|
+
onValueChange(`${nextTime}`);
|
|
5486
|
+
return;
|
|
5487
|
+
}
|
|
5488
|
+
const combined = `${nextDate}T${nextTime || "00:00"}`;
|
|
5489
|
+
const parsed = new Date(combined);
|
|
5490
|
+
onValueChange(Number.isNaN(parsed.getTime()) ? combined : parsed.toISOString());
|
|
5491
|
+
};
|
|
5492
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-[1fr_auto] gap-2", children: [
|
|
5493
|
+
/* @__PURE__ */ jsx(
|
|
5494
|
+
DatePicker,
|
|
5495
|
+
{
|
|
5496
|
+
value: datePart ?? "",
|
|
5497
|
+
onChange: (next) => commit(next, timePart),
|
|
5498
|
+
placeholder: field.placeholder ?? "Select a date",
|
|
5499
|
+
"aria-label": `${field.name} date`,
|
|
5500
|
+
required: field.is_required
|
|
5501
|
+
}
|
|
5502
|
+
),
|
|
5503
|
+
/* @__PURE__ */ jsx(
|
|
5504
|
+
TimePicker,
|
|
5505
|
+
{
|
|
5506
|
+
value: timePart,
|
|
5507
|
+
onChange: (next) => commit(datePart ?? "", next),
|
|
5508
|
+
placeholder: "Time",
|
|
5509
|
+
"aria-label": `${field.name} time`
|
|
5510
|
+
}
|
|
5511
|
+
)
|
|
5512
|
+
] });
|
|
5386
5513
|
}
|
|
5387
5514
|
case INPUT_FIELD_TYPE.Time:
|
|
5388
5515
|
return /* @__PURE__ */ jsx(
|
|
5389
|
-
|
|
5516
|
+
TimePicker,
|
|
5390
5517
|
{
|
|
5391
|
-
type: "time",
|
|
5392
5518
|
value: typeof value === "string" ? value : "",
|
|
5393
|
-
onChange: (
|
|
5519
|
+
onChange: (next) => onValueChange(next || void 0),
|
|
5394
5520
|
required: field.is_required,
|
|
5395
|
-
|
|
5521
|
+
placeholder: field.placeholder ?? "Select a time",
|
|
5522
|
+
"aria-label": field.name
|
|
5396
5523
|
}
|
|
5397
5524
|
);
|
|
5398
5525
|
case INPUT_FIELD_TYPE.MultiSelect:
|
|
@@ -5412,8 +5539,7 @@ function FieldInput({
|
|
|
5412
5539
|
field,
|
|
5413
5540
|
value,
|
|
5414
5541
|
onValueChange,
|
|
5415
|
-
classNames
|
|
5416
|
-
inputClass
|
|
5542
|
+
classNames
|
|
5417
5543
|
}
|
|
5418
5544
|
);
|
|
5419
5545
|
case INPUT_FIELD_TYPE.Address:
|
|
@@ -5582,38 +5708,39 @@ function DateRangeInput({
|
|
|
5582
5708
|
field,
|
|
5583
5709
|
value,
|
|
5584
5710
|
onValueChange,
|
|
5585
|
-
classNames
|
|
5586
|
-
inputClass
|
|
5711
|
+
classNames
|
|
5587
5712
|
}) {
|
|
5588
5713
|
const range = value && typeof value === "object" ? value : {};
|
|
5589
5714
|
const update = (key, v) => {
|
|
5590
5715
|
const next = { ...range, [key]: v };
|
|
5591
5716
|
onValueChange(next.start || next.end ? next : void 0);
|
|
5592
5717
|
};
|
|
5593
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("grid grid-cols-2 gap-3", classNames?.dateRangeInput), children: [
|
|
5718
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("grid grid-cols-1 sm:grid-cols-2 gap-3", classNames?.dateRangeInput), children: [
|
|
5594
5719
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
5595
5720
|
/* @__PURE__ */ jsx("label", { className: "text-xs text-muted-foreground mb-1 block", children: "Start" }),
|
|
5596
5721
|
/* @__PURE__ */ jsx(
|
|
5597
|
-
|
|
5722
|
+
DatePicker,
|
|
5598
5723
|
{
|
|
5599
|
-
type: "date",
|
|
5600
5724
|
value: range.start || "",
|
|
5601
|
-
onChange: (
|
|
5725
|
+
onChange: (next) => update("start", next),
|
|
5602
5726
|
required: field.is_required,
|
|
5603
|
-
|
|
5727
|
+
placeholder: "Start date",
|
|
5728
|
+
"aria-label": `${field.name} start date`,
|
|
5729
|
+
maxDate: range.end ? /* @__PURE__ */ new Date(`${range.end}T00:00`) : void 0
|
|
5604
5730
|
}
|
|
5605
5731
|
)
|
|
5606
5732
|
] }),
|
|
5607
5733
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
5608
5734
|
/* @__PURE__ */ jsx("label", { className: "text-xs text-muted-foreground mb-1 block", children: "End" }),
|
|
5609
5735
|
/* @__PURE__ */ jsx(
|
|
5610
|
-
|
|
5736
|
+
DatePicker,
|
|
5611
5737
|
{
|
|
5612
|
-
type: "date",
|
|
5613
5738
|
value: range.end || "",
|
|
5614
|
-
onChange: (
|
|
5739
|
+
onChange: (next) => update("end", next),
|
|
5615
5740
|
required: field.is_required,
|
|
5616
|
-
|
|
5741
|
+
placeholder: "End date",
|
|
5742
|
+
"aria-label": `${field.name} end date`,
|
|
5743
|
+
minDate: range.start ? /* @__PURE__ */ new Date(`${range.start}T00:00`) : void 0
|
|
5617
5744
|
}
|
|
5618
5745
|
)
|
|
5619
5746
|
] })
|
|
@@ -6057,6 +6184,39 @@ function formatTime(timeStr) {
|
|
|
6057
6184
|
}
|
|
6058
6185
|
return timeStr;
|
|
6059
6186
|
}
|
|
6187
|
+
function pluralizeUnit(unit, value) {
|
|
6188
|
+
if (!unit) return value === 1 ? "day" : "days";
|
|
6189
|
+
const v = value ?? 1;
|
|
6190
|
+
if (unit === "minutes") return v === 1 ? "minute" : "minutes";
|
|
6191
|
+
if (unit === "hours") return v === 1 ? "hour" : "hours";
|
|
6192
|
+
if (unit === "days") return v === 1 ? "day" : "days";
|
|
6193
|
+
if (unit === "weeks") return v === 1 ? "week" : "weeks";
|
|
6194
|
+
if (unit === "months") return v === 1 ? "month" : "months";
|
|
6195
|
+
return unit;
|
|
6196
|
+
}
|
|
6197
|
+
function formatStaySummary(slot, durationUnit, durationValue) {
|
|
6198
|
+
const start = new Date(slot.start_time);
|
|
6199
|
+
const end = new Date(slot.end_time);
|
|
6200
|
+
const startLabel = start.toLocaleString(void 0, {
|
|
6201
|
+
weekday: "short",
|
|
6202
|
+
month: "short",
|
|
6203
|
+
day: "numeric",
|
|
6204
|
+
hour: "numeric",
|
|
6205
|
+
minute: "2-digit"
|
|
6206
|
+
});
|
|
6207
|
+
const endLabel = end.toLocaleString(void 0, {
|
|
6208
|
+
weekday: "short",
|
|
6209
|
+
month: "short",
|
|
6210
|
+
day: "numeric",
|
|
6211
|
+
hour: "numeric",
|
|
6212
|
+
minute: "2-digit"
|
|
6213
|
+
});
|
|
6214
|
+
const unitLabel = pluralizeUnit(durationUnit, durationValue);
|
|
6215
|
+
if (durationValue !== void 0) {
|
|
6216
|
+
return `${durationValue} ${unitLabel}: ${startLabel} \u2192 ${endLabel}`;
|
|
6217
|
+
}
|
|
6218
|
+
return `${startLabel} \u2192 ${endLabel}`;
|
|
6219
|
+
}
|
|
6060
6220
|
function slotToValue(slot) {
|
|
6061
6221
|
return `${slot.start_time}|${slot.end_time}`;
|
|
6062
6222
|
}
|
|
@@ -6069,10 +6229,14 @@ function SlotPicker({
|
|
|
6069
6229
|
onSlotSelect,
|
|
6070
6230
|
groupByTimeOfDay = true,
|
|
6071
6231
|
showPrice = true,
|
|
6232
|
+
schedulingMode = "intraday",
|
|
6233
|
+
durationUnit,
|
|
6234
|
+
durationValue,
|
|
6072
6235
|
emptyMessage = "No available slots",
|
|
6073
6236
|
className,
|
|
6074
6237
|
classNames
|
|
6075
6238
|
}) {
|
|
6239
|
+
const isMultiDay = schedulingMode === "multi_day";
|
|
6076
6240
|
const { slots: fetched, isLoading } = useAvailableSlots(
|
|
6077
6241
|
serviceId ?? null,
|
|
6078
6242
|
date ?? null,
|
|
@@ -6103,7 +6267,7 @@ function SlotPicker({
|
|
|
6103
6267
|
}
|
|
6104
6268
|
);
|
|
6105
6269
|
}
|
|
6106
|
-
const groups = groupByTimeOfDay ? groupSlots(slots) : [{ label: "", slots }];
|
|
6270
|
+
const groups = groupByTimeOfDay && !isMultiDay ? groupSlots(slots) : [{ label: "", slots }];
|
|
6107
6271
|
const slotsByValue = /* @__PURE__ */ new Map();
|
|
6108
6272
|
for (const slot of slots) {
|
|
6109
6273
|
slotsByValue.set(slotToValue(slot), slot);
|
|
@@ -6136,7 +6300,7 @@ function SlotPicker({
|
|
|
6136
6300
|
"data-unavailable": !slot.is_available || void 0,
|
|
6137
6301
|
className: classNames?.slot,
|
|
6138
6302
|
children: [
|
|
6139
|
-
/* @__PURE__ */ jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: formatTime(slot.start_time) }),
|
|
6303
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime(slot.start_time) }),
|
|
6140
6304
|
showPrice && slot.price && /* @__PURE__ */ jsx("span", { "data-cimplify-slot-price": true, className: classNames?.slotPrice, children: /* @__PURE__ */ jsx(Price, { amount: slot.price }) })
|
|
6141
6305
|
]
|
|
6142
6306
|
},
|
|
@@ -6167,6 +6331,9 @@ function DateSlotPicker({
|
|
|
6167
6331
|
onSlotSelect,
|
|
6168
6332
|
availability: availabilityProp,
|
|
6169
6333
|
showPrice = true,
|
|
6334
|
+
schedulingMode,
|
|
6335
|
+
durationUnit,
|
|
6336
|
+
durationValue,
|
|
6170
6337
|
className,
|
|
6171
6338
|
classNames
|
|
6172
6339
|
}) {
|
|
@@ -6284,7 +6451,10 @@ function DateSlotPicker({
|
|
|
6284
6451
|
participantCount,
|
|
6285
6452
|
selectedSlot,
|
|
6286
6453
|
onSlotSelect: handleSlotSelect,
|
|
6287
|
-
showPrice
|
|
6454
|
+
showPrice,
|
|
6455
|
+
schedulingMode,
|
|
6456
|
+
durationUnit,
|
|
6457
|
+
durationValue
|
|
6288
6458
|
}
|
|
6289
6459
|
) })
|
|
6290
6460
|
]
|
|
@@ -13370,4 +13540,4 @@ function SparkleIcon({ className }) {
|
|
|
13370
13540
|
);
|
|
13371
13541
|
}
|
|
13372
13542
|
|
|
13373
|
-
export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BundleProductCard, BundleProductLayout, BundleSelector, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckoutPage, CimplifyAccount, CimplifyCheckout, CimplifyProvider, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, CurrencySelector, CustomAttributesTable, CustomerInputFields, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FeaturedCollectionLayout, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, SubscriptionCard, TagPills, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
|
13543
|
+
export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BundleProductCard, BundleProductLayout, BundleSelector, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckoutPage, CimplifyAccount, CimplifyCheckout, CimplifyProvider, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, CurrencySelector, CustomAttributesTable, CustomerInputFields, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FeaturedCollectionLayout, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, SubscriptionCard, TagPills, TimePicker, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|