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