@cimplify/sdk 0.9.7 → 0.9.9
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 +0 -20
- package/dist/advanced.mjs +0 -20
- package/dist/{client-DmDEP_yB.d.ts → client-CYRL8s1S.d.ts} +1 -5
- package/dist/{client-mOiGkyoT.d.mts → client-D4EiM667.d.mts} +1 -5
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -20
- package/dist/index.mjs +0 -20
- package/dist/react.d.mts +27 -46
- package/dist/react.d.ts +27 -46
- package/dist/react.js +136 -403
- package/dist/react.mjs +137 -402
- package/package.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -793,14 +793,6 @@ var CatalogueQueries = class {
|
|
|
793
793
|
async getBundles() {
|
|
794
794
|
return safe(this.client.get("/api/v1/catalogue/bundles"));
|
|
795
795
|
}
|
|
796
|
-
async getBundle(id) {
|
|
797
|
-
const encodedId = encodeURIComponent(id);
|
|
798
|
-
return safe(this.client.get(`/api/v1/catalogue/bundles/${encodedId}`));
|
|
799
|
-
}
|
|
800
|
-
async getBundleBySlug(slug) {
|
|
801
|
-
const encodedSlug = encodeURIComponent(slug);
|
|
802
|
-
return safe(this.client.get(`/api/v1/catalogue/bundles/slug/${encodedSlug}`));
|
|
803
|
-
}
|
|
804
796
|
async searchBundles(query, limit = 20) {
|
|
805
797
|
const path = withQuery("/api/v1/catalogue/bundles", { search: query, limit });
|
|
806
798
|
return safe(this.client.get(path));
|
|
@@ -809,18 +801,6 @@ var CatalogueQueries = class {
|
|
|
809
801
|
const path = withQuery("/api/v1/catalogue/composites", { limit: options?.limit });
|
|
810
802
|
return safe(this.client.get(path));
|
|
811
803
|
}
|
|
812
|
-
async getComposite(id) {
|
|
813
|
-
const encodedId = encodeURIComponent(id);
|
|
814
|
-
return safe(this.client.get(`/api/v1/catalogue/composites/${encodedId}`));
|
|
815
|
-
}
|
|
816
|
-
async getCompositeByProductId(productId) {
|
|
817
|
-
const encodedId = encodeURIComponent(productId);
|
|
818
|
-
return safe(
|
|
819
|
-
this.client.get(
|
|
820
|
-
`/api/v1/catalogue/composites/by-product/${encodedId}`
|
|
821
|
-
)
|
|
822
|
-
);
|
|
823
|
-
}
|
|
824
804
|
async calculateCompositePrice(compositeId, selections, locationId) {
|
|
825
805
|
const encodedId = encodeURIComponent(compositeId);
|
|
826
806
|
return safe(
|
|
@@ -6013,256 +5993,6 @@ function useCollection(idOrSlug, options = {}) {
|
|
|
6013
5993
|
}, [cacheKey, load]);
|
|
6014
5994
|
return { collection, products, isLoading, error, refetch };
|
|
6015
5995
|
}
|
|
6016
|
-
var bundleCache = /* @__PURE__ */ new Map();
|
|
6017
|
-
var bundleInflight = /* @__PURE__ */ new Map();
|
|
6018
|
-
function isLikelySlug3(value) {
|
|
6019
|
-
return /^[a-z0-9-]+$/.test(value);
|
|
6020
|
-
}
|
|
6021
|
-
function buildBundleCacheKey(client, locationId, idOrSlug) {
|
|
6022
|
-
return JSON.stringify({
|
|
6023
|
-
key: client.getPublicKey(),
|
|
6024
|
-
location_id: locationId || "__none__",
|
|
6025
|
-
bundle: idOrSlug
|
|
6026
|
-
});
|
|
6027
|
-
}
|
|
6028
|
-
function useBundle(idOrSlug, options = {}) {
|
|
6029
|
-
const context = useOptionalCimplify();
|
|
6030
|
-
const client = options.client ?? context?.client;
|
|
6031
|
-
if (!client) {
|
|
6032
|
-
throw new Error("useBundle must be used within CimplifyProvider or passed { client }.");
|
|
6033
|
-
}
|
|
6034
|
-
const enabled = options.enabled ?? true;
|
|
6035
|
-
const locationId = client.getLocationId();
|
|
6036
|
-
const previousLocationIdRef = useRef(locationId);
|
|
6037
|
-
const requestIdRef = useRef(0);
|
|
6038
|
-
const normalizedIdOrSlug = useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
|
|
6039
|
-
const cacheKey = useMemo(
|
|
6040
|
-
() => buildBundleCacheKey(client, locationId, normalizedIdOrSlug),
|
|
6041
|
-
[client, locationId, normalizedIdOrSlug]
|
|
6042
|
-
);
|
|
6043
|
-
const cached = bundleCache.get(cacheKey);
|
|
6044
|
-
const [bundle, setBundle] = useState(cached?.bundle ?? null);
|
|
6045
|
-
const [isLoading, setIsLoading] = useState(
|
|
6046
|
-
enabled && normalizedIdOrSlug.length > 0 && !cached
|
|
6047
|
-
);
|
|
6048
|
-
const [error, setError] = useState(null);
|
|
6049
|
-
useEffect(() => {
|
|
6050
|
-
if (previousLocationIdRef.current !== locationId) {
|
|
6051
|
-
bundleCache.clear();
|
|
6052
|
-
bundleInflight.clear();
|
|
6053
|
-
previousLocationIdRef.current = locationId;
|
|
6054
|
-
}
|
|
6055
|
-
}, [locationId]);
|
|
6056
|
-
const load = useCallback(
|
|
6057
|
-
async (force = false) => {
|
|
6058
|
-
if (!enabled || normalizedIdOrSlug.length === 0) {
|
|
6059
|
-
setBundle(null);
|
|
6060
|
-
setIsLoading(false);
|
|
6061
|
-
return;
|
|
6062
|
-
}
|
|
6063
|
-
const nextRequestId = ++requestIdRef.current;
|
|
6064
|
-
setError(null);
|
|
6065
|
-
if (!force) {
|
|
6066
|
-
const cacheEntry = bundleCache.get(cacheKey);
|
|
6067
|
-
if (cacheEntry) {
|
|
6068
|
-
setBundle(cacheEntry.bundle);
|
|
6069
|
-
setIsLoading(false);
|
|
6070
|
-
return;
|
|
6071
|
-
}
|
|
6072
|
-
}
|
|
6073
|
-
setIsLoading(true);
|
|
6074
|
-
try {
|
|
6075
|
-
const existing = bundleInflight.get(cacheKey);
|
|
6076
|
-
const promise = existing ?? (async () => {
|
|
6077
|
-
const result = isLikelySlug3(normalizedIdOrSlug) ? await client.catalogue.getBundleBySlug(normalizedIdOrSlug) : await client.catalogue.getBundle(normalizedIdOrSlug);
|
|
6078
|
-
if (!result.ok) {
|
|
6079
|
-
throw result.error;
|
|
6080
|
-
}
|
|
6081
|
-
return result.value;
|
|
6082
|
-
})();
|
|
6083
|
-
if (!existing) {
|
|
6084
|
-
bundleInflight.set(cacheKey, promise);
|
|
6085
|
-
promise.finally(() => {
|
|
6086
|
-
bundleInflight.delete(cacheKey);
|
|
6087
|
-
}).catch(() => void 0);
|
|
6088
|
-
}
|
|
6089
|
-
const value = await promise;
|
|
6090
|
-
bundleCache.set(cacheKey, { bundle: value });
|
|
6091
|
-
if (nextRequestId === requestIdRef.current) {
|
|
6092
|
-
setBundle(value);
|
|
6093
|
-
setError(null);
|
|
6094
|
-
}
|
|
6095
|
-
} catch (loadError) {
|
|
6096
|
-
if (nextRequestId === requestIdRef.current) {
|
|
6097
|
-
setError(loadError);
|
|
6098
|
-
}
|
|
6099
|
-
} finally {
|
|
6100
|
-
if (nextRequestId === requestIdRef.current) {
|
|
6101
|
-
setIsLoading(false);
|
|
6102
|
-
}
|
|
6103
|
-
}
|
|
6104
|
-
},
|
|
6105
|
-
[cacheKey, client, enabled, normalizedIdOrSlug]
|
|
6106
|
-
);
|
|
6107
|
-
useEffect(() => {
|
|
6108
|
-
void load(false);
|
|
6109
|
-
}, [load]);
|
|
6110
|
-
const refetch = useCallback(async () => {
|
|
6111
|
-
bundleCache.delete(cacheKey);
|
|
6112
|
-
await load(true);
|
|
6113
|
-
}, [cacheKey, load]);
|
|
6114
|
-
return { bundle, isLoading, error, refetch };
|
|
6115
|
-
}
|
|
6116
|
-
var compositeCache = /* @__PURE__ */ new Map();
|
|
6117
|
-
var compositeInflight = /* @__PURE__ */ new Map();
|
|
6118
|
-
function shouldFetchByProductId(idOrProductId, byProductId) {
|
|
6119
|
-
if (typeof byProductId === "boolean") {
|
|
6120
|
-
return byProductId;
|
|
6121
|
-
}
|
|
6122
|
-
return idOrProductId.startsWith("prod_");
|
|
6123
|
-
}
|
|
6124
|
-
function buildCompositeCacheKey(client, locationId, idOrProductId, byProductId) {
|
|
6125
|
-
return JSON.stringify({
|
|
6126
|
-
key: client.getPublicKey(),
|
|
6127
|
-
location_id: locationId || "__none__",
|
|
6128
|
-
composite: idOrProductId,
|
|
6129
|
-
by_product_id: byProductId
|
|
6130
|
-
});
|
|
6131
|
-
}
|
|
6132
|
-
function useComposite(idOrProductId, options = {}) {
|
|
6133
|
-
const context = useOptionalCimplify();
|
|
6134
|
-
const client = options.client ?? context?.client;
|
|
6135
|
-
if (!client) {
|
|
6136
|
-
throw new Error("useComposite must be used within CimplifyProvider or passed { client }.");
|
|
6137
|
-
}
|
|
6138
|
-
const enabled = options.enabled ?? true;
|
|
6139
|
-
const locationId = client.getLocationId();
|
|
6140
|
-
const previousLocationIdRef = useRef(locationId);
|
|
6141
|
-
const requestIdRef = useRef(0);
|
|
6142
|
-
const priceRequestIdRef = useRef(0);
|
|
6143
|
-
const normalizedIdOrProductId = useMemo(
|
|
6144
|
-
() => (idOrProductId || "").trim(),
|
|
6145
|
-
[idOrProductId]
|
|
6146
|
-
);
|
|
6147
|
-
const byProductId = useMemo(
|
|
6148
|
-
() => shouldFetchByProductId(normalizedIdOrProductId, options.byProductId),
|
|
6149
|
-
[normalizedIdOrProductId, options.byProductId]
|
|
6150
|
-
);
|
|
6151
|
-
const cacheKey = useMemo(
|
|
6152
|
-
() => buildCompositeCacheKey(client, locationId, normalizedIdOrProductId, byProductId),
|
|
6153
|
-
[byProductId, client, locationId, normalizedIdOrProductId]
|
|
6154
|
-
);
|
|
6155
|
-
const cached = compositeCache.get(cacheKey);
|
|
6156
|
-
const [composite, setComposite] = useState(cached?.composite ?? null);
|
|
6157
|
-
const [isLoading, setIsLoading] = useState(
|
|
6158
|
-
enabled && normalizedIdOrProductId.length > 0 && !cached
|
|
6159
|
-
);
|
|
6160
|
-
const [error, setError] = useState(null);
|
|
6161
|
-
const [priceResult, setPriceResult] = useState(null);
|
|
6162
|
-
const [isPriceLoading, setIsPriceLoading] = useState(false);
|
|
6163
|
-
useEffect(() => {
|
|
6164
|
-
if (previousLocationIdRef.current !== locationId) {
|
|
6165
|
-
compositeCache.clear();
|
|
6166
|
-
compositeInflight.clear();
|
|
6167
|
-
previousLocationIdRef.current = locationId;
|
|
6168
|
-
}
|
|
6169
|
-
}, [locationId]);
|
|
6170
|
-
const load = useCallback(
|
|
6171
|
-
async (force = false) => {
|
|
6172
|
-
if (!enabled || normalizedIdOrProductId.length === 0) {
|
|
6173
|
-
setComposite(null);
|
|
6174
|
-
setPriceResult(null);
|
|
6175
|
-
setIsLoading(false);
|
|
6176
|
-
return;
|
|
6177
|
-
}
|
|
6178
|
-
const nextRequestId = ++requestIdRef.current;
|
|
6179
|
-
setError(null);
|
|
6180
|
-
if (!force) {
|
|
6181
|
-
const cacheEntry = compositeCache.get(cacheKey);
|
|
6182
|
-
if (cacheEntry) {
|
|
6183
|
-
setComposite(cacheEntry.composite);
|
|
6184
|
-
setIsLoading(false);
|
|
6185
|
-
return;
|
|
6186
|
-
}
|
|
6187
|
-
}
|
|
6188
|
-
setIsLoading(true);
|
|
6189
|
-
try {
|
|
6190
|
-
const existing = compositeInflight.get(cacheKey);
|
|
6191
|
-
const promise = existing ?? (async () => {
|
|
6192
|
-
const result = byProductId ? await client.catalogue.getCompositeByProductId(normalizedIdOrProductId) : await client.catalogue.getComposite(normalizedIdOrProductId);
|
|
6193
|
-
if (!result.ok) {
|
|
6194
|
-
throw result.error;
|
|
6195
|
-
}
|
|
6196
|
-
return result.value;
|
|
6197
|
-
})();
|
|
6198
|
-
if (!existing) {
|
|
6199
|
-
compositeInflight.set(cacheKey, promise);
|
|
6200
|
-
promise.finally(() => {
|
|
6201
|
-
compositeInflight.delete(cacheKey);
|
|
6202
|
-
}).catch(() => void 0);
|
|
6203
|
-
}
|
|
6204
|
-
const value = await promise;
|
|
6205
|
-
compositeCache.set(cacheKey, { composite: value });
|
|
6206
|
-
if (nextRequestId === requestIdRef.current) {
|
|
6207
|
-
setComposite(value);
|
|
6208
|
-
setPriceResult(null);
|
|
6209
|
-
setError(null);
|
|
6210
|
-
}
|
|
6211
|
-
} catch (loadError) {
|
|
6212
|
-
if (nextRequestId === requestIdRef.current) {
|
|
6213
|
-
setError(loadError);
|
|
6214
|
-
}
|
|
6215
|
-
} finally {
|
|
6216
|
-
if (nextRequestId === requestIdRef.current) {
|
|
6217
|
-
setIsLoading(false);
|
|
6218
|
-
}
|
|
6219
|
-
}
|
|
6220
|
-
},
|
|
6221
|
-
[byProductId, cacheKey, client, enabled, normalizedIdOrProductId]
|
|
6222
|
-
);
|
|
6223
|
-
useEffect(() => {
|
|
6224
|
-
void load(false);
|
|
6225
|
-
}, [load]);
|
|
6226
|
-
const calculatePrice = useCallback(
|
|
6227
|
-
async (selections, overrideLocationId) => {
|
|
6228
|
-
if (!composite) {
|
|
6229
|
-
return null;
|
|
6230
|
-
}
|
|
6231
|
-
const nextRequestId = ++priceRequestIdRef.current;
|
|
6232
|
-
setIsPriceLoading(true);
|
|
6233
|
-
try {
|
|
6234
|
-
const result = await client.catalogue.calculateCompositePrice(
|
|
6235
|
-
composite.id,
|
|
6236
|
-
selections,
|
|
6237
|
-
overrideLocationId
|
|
6238
|
-
);
|
|
6239
|
-
if (!result.ok) {
|
|
6240
|
-
throw result.error;
|
|
6241
|
-
}
|
|
6242
|
-
if (nextRequestId === priceRequestIdRef.current) {
|
|
6243
|
-
setPriceResult(result.value);
|
|
6244
|
-
setError(null);
|
|
6245
|
-
}
|
|
6246
|
-
return result.value;
|
|
6247
|
-
} catch (loadError) {
|
|
6248
|
-
if (nextRequestId === priceRequestIdRef.current) {
|
|
6249
|
-
setError(loadError);
|
|
6250
|
-
}
|
|
6251
|
-
return null;
|
|
6252
|
-
} finally {
|
|
6253
|
-
if (nextRequestId === priceRequestIdRef.current) {
|
|
6254
|
-
setIsPriceLoading(false);
|
|
6255
|
-
}
|
|
6256
|
-
}
|
|
6257
|
-
},
|
|
6258
|
-
[client, composite]
|
|
6259
|
-
);
|
|
6260
|
-
const refetch = useCallback(async () => {
|
|
6261
|
-
compositeCache.delete(cacheKey);
|
|
6262
|
-
await load(true);
|
|
6263
|
-
}, [cacheKey, load]);
|
|
6264
|
-
return { composite, isLoading, error, refetch, calculatePrice, priceResult, isPriceLoading };
|
|
6265
|
-
}
|
|
6266
5996
|
function useSearch(options = {}) {
|
|
6267
5997
|
const context = useOptionalCimplify();
|
|
6268
5998
|
const client = options.client ?? context?.client;
|
|
@@ -7016,15 +6746,122 @@ function AddOnSelector({
|
|
|
7016
6746
|
] }, addOn.id);
|
|
7017
6747
|
}) });
|
|
7018
6748
|
}
|
|
6749
|
+
function BundleSelector({
|
|
6750
|
+
components,
|
|
6751
|
+
bundlePrice,
|
|
6752
|
+
discountValue,
|
|
6753
|
+
onSelectionsChange,
|
|
6754
|
+
onReady,
|
|
6755
|
+
className
|
|
6756
|
+
}) {
|
|
6757
|
+
const [variantChoices, setVariantChoices] = useState({});
|
|
6758
|
+
useEffect(() => {
|
|
6759
|
+
const defaults = {};
|
|
6760
|
+
for (const comp of components) {
|
|
6761
|
+
if (comp.variant_id) {
|
|
6762
|
+
defaults[comp.id] = comp.variant_id;
|
|
6763
|
+
} else if (comp.available_variants.length > 0) {
|
|
6764
|
+
const defaultVariant = comp.available_variants.find((v) => v.is_default) || comp.available_variants[0];
|
|
6765
|
+
if (defaultVariant) {
|
|
6766
|
+
defaults[comp.id] = defaultVariant.id;
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
}
|
|
6770
|
+
setVariantChoices(defaults);
|
|
6771
|
+
}, [components]);
|
|
6772
|
+
const selections = useMemo(() => {
|
|
6773
|
+
return components.map((comp) => ({
|
|
6774
|
+
component_id: comp.id,
|
|
6775
|
+
variant_id: variantChoices[comp.id],
|
|
6776
|
+
quantity: comp.quantity
|
|
6777
|
+
}));
|
|
6778
|
+
}, [components, variantChoices]);
|
|
6779
|
+
useEffect(() => {
|
|
6780
|
+
onSelectionsChange(selections);
|
|
6781
|
+
}, [selections, onSelectionsChange]);
|
|
6782
|
+
useEffect(() => {
|
|
6783
|
+
onReady?.(components.length > 0 && selections.length > 0);
|
|
6784
|
+
}, [components, selections, onReady]);
|
|
6785
|
+
const handleVariantChange = useCallback(
|
|
6786
|
+
(componentId, variantId) => {
|
|
6787
|
+
setVariantChoices((prev) => ({ ...prev, [componentId]: variantId }));
|
|
6788
|
+
},
|
|
6789
|
+
[]
|
|
6790
|
+
);
|
|
6791
|
+
if (components.length === 0) {
|
|
6792
|
+
return null;
|
|
6793
|
+
}
|
|
6794
|
+
return /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-selector": true, className, children: [
|
|
6795
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-bundle-heading": true, children: "Included in this bundle" }),
|
|
6796
|
+
/* @__PURE__ */ jsx("div", { "data-cimplify-bundle-components": true, children: components.map((comp) => /* @__PURE__ */ jsx(
|
|
6797
|
+
BundleComponentCard,
|
|
6798
|
+
{
|
|
6799
|
+
component: comp,
|
|
6800
|
+
selectedVariantId: variantChoices[comp.id],
|
|
6801
|
+
onVariantChange: (variantId) => handleVariantChange(comp.id, variantId)
|
|
6802
|
+
},
|
|
6803
|
+
comp.id
|
|
6804
|
+
)) }),
|
|
6805
|
+
bundlePrice && /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-summary": true, children: [
|
|
6806
|
+
/* @__PURE__ */ jsx("span", { children: "Bundle price" }),
|
|
6807
|
+
/* @__PURE__ */ jsx(Price, { amount: bundlePrice })
|
|
6808
|
+
] }),
|
|
6809
|
+
discountValue && /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-savings": true, children: [
|
|
6810
|
+
/* @__PURE__ */ jsx("span", { children: "You save" }),
|
|
6811
|
+
/* @__PURE__ */ jsx(Price, { amount: discountValue })
|
|
6812
|
+
] })
|
|
6813
|
+
] });
|
|
6814
|
+
}
|
|
6815
|
+
function BundleComponentCard({
|
|
6816
|
+
component,
|
|
6817
|
+
selectedVariantId,
|
|
6818
|
+
onVariantChange
|
|
6819
|
+
}) {
|
|
6820
|
+
const showVariantPicker = component.allow_variant_choice && component.available_variants.length > 1;
|
|
6821
|
+
return /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-component": true, children: [
|
|
6822
|
+
/* @__PURE__ */ jsx("div", { "data-cimplify-bundle-component-header": true, children: /* @__PURE__ */ jsxs("div", { children: [
|
|
6823
|
+
component.quantity > 1 && /* @__PURE__ */ jsxs("span", { "data-cimplify-bundle-component-qty": true, children: [
|
|
6824
|
+
"\xD7",
|
|
6825
|
+
component.quantity
|
|
6826
|
+
] }),
|
|
6827
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-bundle-component-name": true, children: component.product_name })
|
|
6828
|
+
] }) }),
|
|
6829
|
+
showVariantPicker && /* @__PURE__ */ jsx("div", { "data-cimplify-bundle-variant-picker": true, children: component.available_variants.map((variant) => {
|
|
6830
|
+
const isSelected = selectedVariantId === variant.id;
|
|
6831
|
+
const adjustment = parsePrice(variant.price_adjustment);
|
|
6832
|
+
return /* @__PURE__ */ jsxs(
|
|
6833
|
+
"button",
|
|
6834
|
+
{
|
|
6835
|
+
type: "button",
|
|
6836
|
+
"aria-selected": isSelected,
|
|
6837
|
+
onClick: () => onVariantChange(variant.id),
|
|
6838
|
+
"data-cimplify-bundle-variant-option": true,
|
|
6839
|
+
"data-selected": isSelected || void 0,
|
|
6840
|
+
children: [
|
|
6841
|
+
variant.display_name,
|
|
6842
|
+
adjustment !== 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-bundle-variant-adjustment": true, children: [
|
|
6843
|
+
adjustment > 0 ? "+" : "",
|
|
6844
|
+
/* @__PURE__ */ jsx(Price, { amount: variant.price_adjustment })
|
|
6845
|
+
] })
|
|
6846
|
+
]
|
|
6847
|
+
},
|
|
6848
|
+
variant.id
|
|
6849
|
+
);
|
|
6850
|
+
}) })
|
|
6851
|
+
] });
|
|
6852
|
+
}
|
|
7019
6853
|
function CompositeSelector({
|
|
7020
|
-
|
|
6854
|
+
compositeId,
|
|
6855
|
+
groups,
|
|
7021
6856
|
onSelectionsChange,
|
|
7022
6857
|
onPriceChange,
|
|
7023
6858
|
onReady,
|
|
7024
6859
|
className
|
|
7025
6860
|
}) {
|
|
7026
|
-
const {
|
|
6861
|
+
const { client } = useCimplify();
|
|
7027
6862
|
const [groupSelections, setGroupSelections] = useState({});
|
|
6863
|
+
const [priceResult, setPriceResult] = useState(null);
|
|
6864
|
+
const [isPriceLoading, setIsPriceLoading] = useState(false);
|
|
7028
6865
|
const selections = useMemo(() => {
|
|
7029
6866
|
const result = [];
|
|
7030
6867
|
for (const groupSels of Object.values(groupSelections)) {
|
|
@@ -7043,22 +6880,32 @@ function CompositeSelector({
|
|
|
7043
6880
|
onPriceChange?.(priceResult);
|
|
7044
6881
|
}, [priceResult, onPriceChange]);
|
|
7045
6882
|
const allGroupsSatisfied = useMemo(() => {
|
|
7046
|
-
|
|
7047
|
-
for (const group of composite.groups) {
|
|
6883
|
+
for (const group of groups) {
|
|
7048
6884
|
const groupSels = groupSelections[group.id] || {};
|
|
7049
6885
|
const totalSelected = Object.values(groupSels).reduce((sum, q) => sum + q, 0);
|
|
7050
6886
|
if (totalSelected < group.min_selections) return false;
|
|
7051
6887
|
}
|
|
7052
6888
|
return true;
|
|
7053
|
-
}, [
|
|
6889
|
+
}, [groups, groupSelections]);
|
|
7054
6890
|
useEffect(() => {
|
|
7055
6891
|
onReady?.(allGroupsSatisfied);
|
|
7056
6892
|
}, [allGroupsSatisfied, onReady]);
|
|
7057
6893
|
useEffect(() => {
|
|
7058
|
-
if (allGroupsSatisfied
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
6894
|
+
if (!allGroupsSatisfied || selections.length === 0) return;
|
|
6895
|
+
let cancelled = false;
|
|
6896
|
+
setIsPriceLoading(true);
|
|
6897
|
+
void client.catalogue.calculateCompositePrice(compositeId, selections).then((result) => {
|
|
6898
|
+
if (cancelled) return;
|
|
6899
|
+
if (result.ok) {
|
|
6900
|
+
setPriceResult(result.value);
|
|
6901
|
+
}
|
|
6902
|
+
}).finally(() => {
|
|
6903
|
+
if (!cancelled) setIsPriceLoading(false);
|
|
6904
|
+
});
|
|
6905
|
+
return () => {
|
|
6906
|
+
cancelled = true;
|
|
6907
|
+
};
|
|
6908
|
+
}, [selections, allGroupsSatisfied, compositeId, client]);
|
|
7062
6909
|
const toggleComponent = useCallback(
|
|
7063
6910
|
(group, component) => {
|
|
7064
6911
|
setGroupSelections((prev) => {
|
|
@@ -7106,14 +6953,11 @@ function CompositeSelector({
|
|
|
7106
6953
|
},
|
|
7107
6954
|
[]
|
|
7108
6955
|
);
|
|
7109
|
-
if (
|
|
7110
|
-
return /* @__PURE__ */ jsx("div", { "data-cimplify-composite-selector": true, "data-loading": true, className, children: "Loading options..." });
|
|
7111
|
-
}
|
|
7112
|
-
if (error || !composite) {
|
|
6956
|
+
if (groups.length === 0) {
|
|
7113
6957
|
return null;
|
|
7114
6958
|
}
|
|
7115
6959
|
return /* @__PURE__ */ jsxs("div", { "data-cimplify-composite-selector": true, className, children: [
|
|
7116
|
-
|
|
6960
|
+
[...groups].sort((a, b) => a.display_order - b.display_order).map((group) => {
|
|
7117
6961
|
const groupSels = groupSelections[group.id] || {};
|
|
7118
6962
|
const totalSelected = Object.values(groupSels).reduce((sum, q) => sum + q, 0);
|
|
7119
6963
|
const minMet = totalSelected >= group.min_selections;
|
|
@@ -7133,7 +6977,7 @@ function CompositeSelector({
|
|
|
7133
6977
|
/* @__PURE__ */ jsx("div", { "data-cimplify-composite-components": true, children: group.components.filter((c) => c.is_available && !c.is_archived).sort((a, b) => a.display_order - b.display_order).map((component) => {
|
|
7134
6978
|
const qty = groupSels[component.id] || 0;
|
|
7135
6979
|
const isSelected = qty > 0;
|
|
7136
|
-
const displayName = component.display_name || component.
|
|
6980
|
+
const displayName = component.display_name || component.id;
|
|
7137
6981
|
return /* @__PURE__ */ jsxs(
|
|
7138
6982
|
"button",
|
|
7139
6983
|
{
|
|
@@ -7207,118 +7051,6 @@ function CompositeSelector({
|
|
|
7207
7051
|
isPriceLoading && /* @__PURE__ */ jsx("div", { "data-cimplify-composite-calculating": true, children: "Calculating price..." })
|
|
7208
7052
|
] });
|
|
7209
7053
|
}
|
|
7210
|
-
function BundleSelector({
|
|
7211
|
-
bundleIdOrSlug,
|
|
7212
|
-
onSelectionsChange,
|
|
7213
|
-
onReady,
|
|
7214
|
-
className
|
|
7215
|
-
}) {
|
|
7216
|
-
const { bundle, isLoading, error } = useBundle(bundleIdOrSlug);
|
|
7217
|
-
const [variantChoices, setVariantChoices] = useState({});
|
|
7218
|
-
useEffect(() => {
|
|
7219
|
-
if (!bundle) return;
|
|
7220
|
-
const defaults = {};
|
|
7221
|
-
for (const comp of bundle.components) {
|
|
7222
|
-
if (comp.component.variant_id) {
|
|
7223
|
-
defaults[comp.component.id] = comp.component.variant_id;
|
|
7224
|
-
} else if (comp.variants.length > 0) {
|
|
7225
|
-
const defaultVariant = comp.variants.find((v) => v.is_default) || comp.variants[0];
|
|
7226
|
-
if (defaultVariant) {
|
|
7227
|
-
defaults[comp.component.id] = defaultVariant.id;
|
|
7228
|
-
}
|
|
7229
|
-
}
|
|
7230
|
-
}
|
|
7231
|
-
setVariantChoices(defaults);
|
|
7232
|
-
}, [bundle]);
|
|
7233
|
-
const selections = useMemo(() => {
|
|
7234
|
-
if (!bundle) return [];
|
|
7235
|
-
return bundle.components.map((comp) => ({
|
|
7236
|
-
component_id: comp.component.id,
|
|
7237
|
-
variant_id: variantChoices[comp.component.id],
|
|
7238
|
-
quantity: comp.component.quantity
|
|
7239
|
-
}));
|
|
7240
|
-
}, [bundle, variantChoices]);
|
|
7241
|
-
useEffect(() => {
|
|
7242
|
-
onSelectionsChange(selections);
|
|
7243
|
-
}, [selections, onSelectionsChange]);
|
|
7244
|
-
useEffect(() => {
|
|
7245
|
-
onReady?.(bundle != null && selections.length > 0);
|
|
7246
|
-
}, [bundle, selections, onReady]);
|
|
7247
|
-
const handleVariantChange = useCallback(
|
|
7248
|
-
(componentId, variantId) => {
|
|
7249
|
-
setVariantChoices((prev) => ({ ...prev, [componentId]: variantId }));
|
|
7250
|
-
},
|
|
7251
|
-
[]
|
|
7252
|
-
);
|
|
7253
|
-
if (isLoading) {
|
|
7254
|
-
return /* @__PURE__ */ jsx("div", { "data-cimplify-bundle-selector": true, "data-loading": true, className, children: "Loading bundle..." });
|
|
7255
|
-
}
|
|
7256
|
-
if (error || !bundle) {
|
|
7257
|
-
return null;
|
|
7258
|
-
}
|
|
7259
|
-
return /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-selector": true, className, children: [
|
|
7260
|
-
/* @__PURE__ */ jsx("span", { "data-cimplify-bundle-heading": true, children: "Included in this bundle" }),
|
|
7261
|
-
/* @__PURE__ */ jsx("div", { "data-cimplify-bundle-components": true, children: bundle.components.map((comp) => /* @__PURE__ */ jsx(
|
|
7262
|
-
BundleComponentCard,
|
|
7263
|
-
{
|
|
7264
|
-
data: comp,
|
|
7265
|
-
selectedVariantId: variantChoices[comp.component.id],
|
|
7266
|
-
onVariantChange: (variantId) => handleVariantChange(comp.component.id, variantId)
|
|
7267
|
-
},
|
|
7268
|
-
comp.component.id
|
|
7269
|
-
)) }),
|
|
7270
|
-
bundle.bundle_price && /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-summary": true, children: [
|
|
7271
|
-
/* @__PURE__ */ jsx("span", { children: "Bundle price" }),
|
|
7272
|
-
/* @__PURE__ */ jsx(Price, { amount: bundle.bundle_price })
|
|
7273
|
-
] }),
|
|
7274
|
-
bundle.discount_value && /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-savings": true, children: [
|
|
7275
|
-
/* @__PURE__ */ jsx("span", { children: "You save" }),
|
|
7276
|
-
/* @__PURE__ */ jsx(Price, { amount: bundle.discount_value })
|
|
7277
|
-
] })
|
|
7278
|
-
] });
|
|
7279
|
-
}
|
|
7280
|
-
function BundleComponentCard({
|
|
7281
|
-
data,
|
|
7282
|
-
selectedVariantId,
|
|
7283
|
-
onVariantChange
|
|
7284
|
-
}) {
|
|
7285
|
-
const { component, product, variants } = data;
|
|
7286
|
-
const showVariantPicker = component.allow_variant_choice && variants.length > 1;
|
|
7287
|
-
return /* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-component": true, children: [
|
|
7288
|
-
/* @__PURE__ */ jsxs("div", { "data-cimplify-bundle-component-header": true, children: [
|
|
7289
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7290
|
-
component.quantity > 1 && /* @__PURE__ */ jsxs("span", { "data-cimplify-bundle-component-qty": true, children: [
|
|
7291
|
-
"\xD7",
|
|
7292
|
-
component.quantity
|
|
7293
|
-
] }),
|
|
7294
|
-
/* @__PURE__ */ jsx("span", { "data-cimplify-bundle-component-name": true, children: product.name })
|
|
7295
|
-
] }),
|
|
7296
|
-
/* @__PURE__ */ jsx(Price, { amount: product.default_price })
|
|
7297
|
-
] }),
|
|
7298
|
-
showVariantPicker && /* @__PURE__ */ jsx("div", { "data-cimplify-bundle-variant-picker": true, children: variants.map((variant) => {
|
|
7299
|
-
const isSelected = selectedVariantId === variant.id;
|
|
7300
|
-
const adjustment = parsePrice(variant.price_adjustment);
|
|
7301
|
-
return /* @__PURE__ */ jsxs(
|
|
7302
|
-
"button",
|
|
7303
|
-
{
|
|
7304
|
-
type: "button",
|
|
7305
|
-
"aria-selected": isSelected,
|
|
7306
|
-
onClick: () => onVariantChange(variant.id),
|
|
7307
|
-
"data-cimplify-bundle-variant-option": true,
|
|
7308
|
-
"data-selected": isSelected || void 0,
|
|
7309
|
-
children: [
|
|
7310
|
-
getVariantDisplayName(variant, product.name),
|
|
7311
|
-
adjustment !== 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-bundle-variant-adjustment": true, children: [
|
|
7312
|
-
adjustment > 0 ? "+" : "",
|
|
7313
|
-
/* @__PURE__ */ jsx(Price, { amount: variant.price_adjustment })
|
|
7314
|
-
] })
|
|
7315
|
-
]
|
|
7316
|
-
},
|
|
7317
|
-
variant.id
|
|
7318
|
-
);
|
|
7319
|
-
}) })
|
|
7320
|
-
] });
|
|
7321
|
-
}
|
|
7322
7054
|
function ProductCustomizer({
|
|
7323
7055
|
product,
|
|
7324
7056
|
onAddToCart,
|
|
@@ -7466,19 +7198,22 @@ function ProductCustomizer({
|
|
|
7466
7198
|
}
|
|
7467
7199
|
};
|
|
7468
7200
|
return /* @__PURE__ */ jsxs("div", { "data-cimplify-customizer": true, className, children: [
|
|
7469
|
-
isComposite && /* @__PURE__ */ jsx(
|
|
7201
|
+
isComposite && product.groups && product.composite_id && /* @__PURE__ */ jsx(
|
|
7470
7202
|
CompositeSelector,
|
|
7471
7203
|
{
|
|
7472
|
-
|
|
7204
|
+
compositeId: product.composite_id,
|
|
7205
|
+
groups: product.groups,
|
|
7473
7206
|
onSelectionsChange: setCompositeSelections,
|
|
7474
7207
|
onPriceChange: setCompositePrice,
|
|
7475
7208
|
onReady: setCompositeReady
|
|
7476
7209
|
}
|
|
7477
7210
|
),
|
|
7478
|
-
isBundle && /* @__PURE__ */ jsx(
|
|
7211
|
+
isBundle && product.components && /* @__PURE__ */ jsx(
|
|
7479
7212
|
BundleSelector,
|
|
7480
7213
|
{
|
|
7481
|
-
|
|
7214
|
+
components: product.components,
|
|
7215
|
+
bundlePrice: product.bundle_price,
|
|
7216
|
+
discountValue: product.discount_value,
|
|
7482
7217
|
onSelectionsChange: setBundleSelections,
|
|
7483
7218
|
onReady: setBundleReady
|
|
7484
7219
|
}
|
|
@@ -7703,4 +7438,4 @@ function CartSummary({
|
|
|
7703
7438
|
] }) });
|
|
7704
7439
|
}
|
|
7705
7440
|
|
|
7706
|
-
export { Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, BundleSelector, CartSummary, CimplifyCheckout, CimplifyProvider, CompositeSelector, ElementsProvider, PaymentElement, Price, ProductCustomizer, ProductImageGallery, QuantitySelector, VariantSelector, getVariantDisplayName, useAds,
|
|
7441
|
+
export { Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, BundleSelector, CartSummary, CimplifyCheckout, CimplifyProvider, CompositeSelector, ElementsProvider, PaymentElement, Price, ProductCustomizer, ProductImageGallery, QuantitySelector, VariantSelector, getVariantDisplayName, useAds, useCart, useCategories, useCheckout, useCimplify, useCollection, useCollections, useElements, useElementsReady, useLocations, useOptionalCimplify, useOrder, useProduct, useProducts, useQuote, useSearch };
|