@cimplify/sdk 0.27.0 → 0.28.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/react.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunk4JSRPSNA_js = require('./chunk-4JSRPSNA.js');
4
+ var chunkGS7AX6B3_js = require('./chunk-GS7AX6B3.js');
5
5
  var chunk2CGA3MUW_js = require('./chunk-2CGA3MUW.js');
6
6
  var chunkPEDLCL72_js = require('./chunk-PEDLCL72.js');
7
7
  var React3 = require('react');
@@ -1061,7 +1061,7 @@ var DEFAULT_COUNTRY = "US";
1061
1061
  function createDefaultClient() {
1062
1062
  const processRef = globalThis.process;
1063
1063
  const envPublicKey = processRef?.env?.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || "";
1064
- return chunk4JSRPSNA_js.createCimplifyClient({ publicKey: envPublicKey });
1064
+ return chunkGS7AX6B3_js.createCimplifyClient({ publicKey: envPublicKey });
1065
1065
  }
1066
1066
  function getStoredLocationId() {
1067
1067
  if (typeof window === "undefined" || !window.localStorage) {
@@ -2852,6 +2852,84 @@ function useOrders(options = {}) {
2852
2852
  const { data, isLoading, error, refetch } = ordersQuery(options);
2853
2853
  return { orders: data ?? [], isLoading, error, refetch };
2854
2854
  }
2855
+ function useSubscriptions(options = {}) {
2856
+ const { client } = useCimplifyClient();
2857
+ const { status, enabled = true } = options;
2858
+ const [subscriptions, setSubscriptions] = React3.useState([]);
2859
+ const [isLoading, setIsLoading] = React3.useState(false);
2860
+ const [error, setError] = React3.useState(null);
2861
+ const fetch2 = React3.useCallback(async () => {
2862
+ if (!enabled) return;
2863
+ setIsLoading(true);
2864
+ setError(null);
2865
+ try {
2866
+ const result = await client.subscriptions.list();
2867
+ if (result.ok) {
2868
+ const filtered = status ? result.value.filter((s) => s.status === status) : result.value;
2869
+ setSubscriptions(filtered);
2870
+ } else {
2871
+ setError(result.error);
2872
+ }
2873
+ } catch (e) {
2874
+ setError(e);
2875
+ } finally {
2876
+ setIsLoading(false);
2877
+ }
2878
+ }, [client, enabled, status]);
2879
+ React3.useEffect(() => {
2880
+ void fetch2();
2881
+ }, [fetch2]);
2882
+ return { subscriptions, isLoading, error, refetch: fetch2 };
2883
+ }
2884
+ function useSubscription(id, options = {}) {
2885
+ const { client } = useCimplifyClient();
2886
+ const { enabled = true } = options;
2887
+ const normalizedId = (id || "").trim();
2888
+ const [subscription, setSubscription] = React3.useState(null);
2889
+ const [isLoading, setIsLoading] = React3.useState(false);
2890
+ const [error, setError] = React3.useState(null);
2891
+ const fetch2 = React3.useCallback(async () => {
2892
+ if (!enabled || !normalizedId) return;
2893
+ setIsLoading(true);
2894
+ setError(null);
2895
+ try {
2896
+ const result = await client.subscriptions.get(normalizedId);
2897
+ if (result.ok) {
2898
+ setSubscription(result.value);
2899
+ } else {
2900
+ setError(result.error);
2901
+ }
2902
+ } catch (e) {
2903
+ setError(e);
2904
+ } finally {
2905
+ setIsLoading(false);
2906
+ }
2907
+ }, [client, enabled, normalizedId]);
2908
+ React3.useEffect(() => {
2909
+ void fetch2();
2910
+ }, [fetch2]);
2911
+ const cancel = React3.useCallback(async (reason) => {
2912
+ if (!normalizedId) return;
2913
+ await client.subscriptions.cancel(normalizedId, reason);
2914
+ void fetch2();
2915
+ }, [client, normalizedId, fetch2]);
2916
+ const pause = React3.useCallback(async () => {
2917
+ if (!normalizedId) return;
2918
+ await client.subscriptions.pause(normalizedId);
2919
+ void fetch2();
2920
+ }, [client, normalizedId, fetch2]);
2921
+ const resume = React3.useCallback(async () => {
2922
+ if (!normalizedId) return;
2923
+ await client.subscriptions.resume(normalizedId);
2924
+ void fetch2();
2925
+ }, [client, normalizedId, fetch2]);
2926
+ const skipNext = React3.useCallback(async () => {
2927
+ if (!normalizedId) return;
2928
+ await client.subscriptions.skipNextRenewal(normalizedId);
2929
+ void fetch2();
2930
+ }, [client, normalizedId, fetch2]);
2931
+ return { subscription, isLoading, error, cancel, pause, resume, skipNext, refetch: fetch2 };
2932
+ }
2855
2933
 
2856
2934
  // src/react/hooks/use-services.ts
2857
2935
  var servicesQuery = createCachedQuery({
@@ -3657,7 +3735,7 @@ function VariantSelector({
3657
3735
  {
3658
3736
  "data-cimplify-variant-name": true,
3659
3737
  className: cn("flex-1 min-w-0 text-sm", classNames?.name),
3660
- children: chunk4JSRPSNA_js.getVariantDisplayName(variant, productName)
3738
+ children: chunkGS7AX6B3_js.getVariantDisplayName(variant, productName)
3661
3739
  }
3662
3740
  ),
3663
3741
  /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm text-muted-foreground", classNames?.pricing), children: [
@@ -5193,7 +5271,7 @@ function CartLineItemRow({
5193
5271
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item": true, className: classNames?.item, children: [
5194
5272
  /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item-info": true, children: [
5195
5273
  /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-name": true, className: classNames?.itemName, children: item.product.name }),
5196
- item.variant && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-variant": true, children: chunk4JSRPSNA_js.getVariantDisplayName(item.variant, item.product.name) }),
5274
+ item.variant && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-variant": true, children: chunkGS7AX6B3_js.getVariantDisplayName(item.variant, item.product.name) }),
5197
5275
  item.addOnOptions && item.addOnOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-cart-item-addons": true, children: [
5198
5276
  "+ ",
5199
5277
  item.addOnOptions.map((opt) => opt.name).join(", ")
@@ -5718,7 +5796,7 @@ function FoodProductCard({
5718
5796
  const tags = product.tags || [];
5719
5797
  const isSignature = product.metadata?.is_signature === true;
5720
5798
  const isNew = product.metadata?.is_new === true;
5721
- const isComposite = product.type === chunk4JSRPSNA_js.PRODUCT_TYPE.Composite;
5799
+ const isComposite = product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Composite;
5722
5800
  return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
5723
5801
  /* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
5724
5802
  isSignature && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 left-3 inline-flex items-center gap-1 text-[11px] font-semibold tracking-wide bg-amber-50 text-amber-700 border border-amber-200/60 px-2 py-0.5 rounded-md", children: [
@@ -5887,6 +5965,98 @@ function DigitalProductCard({
5887
5965
  ] })
5888
5966
  ] });
5889
5967
  }
5968
+ function BundleProductCard({
5969
+ product,
5970
+ onQuickAdd,
5971
+ renderImage,
5972
+ renderLink,
5973
+ className
5974
+ }) {
5975
+ const image = product.image_url || product.images?.[0] || "";
5976
+ const components = product.components || [];
5977
+ const componentCount = components.length;
5978
+ const onSale = chunkPEDLCL72_js.isOnSale(product);
5979
+ const discount = chunkPEDLCL72_js.getDiscountPercentage(product);
5980
+ const hasVariantChoice = components.some((c) => c.allow_variant_choice);
5981
+ return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
5982
+ /* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
5983
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-3 left-3 text-[11px] font-semibold tracking-wide bg-indigo-50 text-indigo-700 border border-indigo-200/60 px-2 py-0.5 rounded-md", children: "Bundle" }),
5984
+ componentCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 right-3 text-[11px] font-semibold tracking-wide bg-background/90 backdrop-blur text-foreground px-2 py-0.5 rounded-md", children: [
5985
+ componentCount,
5986
+ " item",
5987
+ componentCount !== 1 ? "s" : ""
5988
+ ] }),
5989
+ /* @__PURE__ */ jsxRuntime.jsx(
5990
+ QuickAddButton,
5991
+ {
5992
+ onClick: () => onQuickAdd?.(product),
5993
+ className: "absolute bottom-3 right-3"
5994
+ }
5995
+ )
5996
+ ] }),
5997
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3.5", children: [
5998
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[14.5px] font-semibold text-foreground leading-snug tracking-tight truncate", children: product.name }),
5999
+ componentCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[11px] text-muted-foreground mt-1 truncate", children: [
6000
+ "Includes: ",
6001
+ components.map((c) => c.product_name || c.product_id).join(", ")
6002
+ ] }),
6003
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2.5", children: [
6004
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-sm font-bold" }),
6005
+ onSale && product.bundle_price && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6006
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkPEDLCL72_js.getBasePrice(product), className: "text-xs text-muted-foreground line-through" }),
6007
+ discount != null && discount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-semibold text-emerald-600", children: [
6008
+ "Save ",
6009
+ discount,
6010
+ "%"
6011
+ ] })
6012
+ ] })
6013
+ ] }),
6014
+ hasVariantChoice && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block mt-2 text-[10px] font-medium text-muted-foreground px-1.5 py-0.5 bg-muted rounded", children: "Customizable" })
6015
+ ] })
6016
+ ] });
6017
+ }
6018
+ function CompositeProductCard({
6019
+ product,
6020
+ onQuickAdd,
6021
+ renderImage,
6022
+ renderLink,
6023
+ className
6024
+ }) {
6025
+ const image = product.image_url || product.images?.[0] || "";
6026
+ const groups = product.groups || [];
6027
+ const groupCount = groups.length;
6028
+ groups.reduce((sum, g) => sum + g.components.length, 0);
6029
+ const tags = product.tags || [];
6030
+ return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
6031
+ /* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
6032
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-3 left-3 text-[11px] font-semibold tracking-wide bg-violet-50 text-violet-700 border border-violet-200/60 px-2 py-0.5 rounded-md", children: "Build Your Own" }),
6033
+ groupCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 right-3 text-[11px] font-semibold tracking-wide bg-background/90 backdrop-blur text-foreground px-2 py-0.5 rounded-md", children: [
6034
+ groupCount,
6035
+ " choice",
6036
+ groupCount !== 1 ? "s" : ""
6037
+ ] }),
6038
+ /* @__PURE__ */ jsxRuntime.jsx(
6039
+ QuickAddButton,
6040
+ {
6041
+ onClick: () => onQuickAdd?.(product),
6042
+ className: "absolute bottom-3 right-3"
6043
+ }
6044
+ )
6045
+ ] }),
6046
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3.5", children: [
6047
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[14.5px] font-semibold text-foreground leading-snug tracking-tight truncate", children: product.name }),
6048
+ product.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] text-muted-foreground mt-1 line-clamp-1", children: product.description }),
6049
+ groupCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-muted-foreground mt-1 truncate", children: groups.map((g) => g.name).join(" + ") }),
6050
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mt-2.5", children: [
6051
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-bold", children: [
6052
+ "From ",
6053
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price })
6054
+ ] }),
6055
+ tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground px-1.5 py-0.5 bg-muted rounded", children: tags[0] })
6056
+ ] })
6057
+ ] })
6058
+ ] });
6059
+ }
5890
6060
  function formatDuration2(minutes, unit) {
5891
6061
  if (unit && unit !== "minutes") return `${minutes} ${unit}`;
5892
6062
  if (minutes >= 60) {
@@ -6348,6 +6518,8 @@ var CardVariant = /* @__PURE__ */ ((CardVariant2) => {
6348
6518
  CardVariant2["Retail"] = "retail";
6349
6519
  CardVariant2["Wholesale"] = "wholesale";
6350
6520
  CardVariant2["Digital"] = "digital";
6521
+ CardVariant2["Bundle"] = "bundle";
6522
+ CardVariant2["Composite"] = "composite";
6351
6523
  CardVariant2["Standard"] = "standard";
6352
6524
  CardVariant2["Compact"] = "compact";
6353
6525
  CardVariant2["Schedule"] = "schedule";
@@ -6372,22 +6544,30 @@ var BUILT_IN_CARDS = {
6372
6544
  ["rental" /* Rental */]: RentalServiceCard,
6373
6545
  ["accommodation" /* Accommodation */]: AccommodationCard,
6374
6546
  ["lease" /* Lease */]: LeaseServiceCard,
6547
+ ["bundle" /* Bundle */]: BundleProductCard,
6548
+ ["composite" /* Composite */]: CompositeProductCard,
6375
6549
  ["subscription" /* Subscription */]: SubscriptionCard
6376
6550
  };
6377
- var RENTAL_UNITS = /* @__PURE__ */ new Set([chunk4JSRPSNA_js.DURATION_UNIT.Days, chunk4JSRPSNA_js.DURATION_UNIT.Hours]);
6378
- var LEASE_UNITS = /* @__PURE__ */ new Set([chunk4JSRPSNA_js.DURATION_UNIT.Weeks, chunk4JSRPSNA_js.DURATION_UNIT.Months, chunk4JSRPSNA_js.DURATION_UNIT.Years]);
6551
+ var RENTAL_UNITS = /* @__PURE__ */ new Set([chunkGS7AX6B3_js.DURATION_UNIT.Days, chunkGS7AX6B3_js.DURATION_UNIT.Hours]);
6552
+ var LEASE_UNITS = /* @__PURE__ */ new Set([chunkGS7AX6B3_js.DURATION_UNIT.Weeks, chunkGS7AX6B3_js.DURATION_UNIT.Months, chunkGS7AX6B3_js.DURATION_UNIT.Years]);
6379
6553
  function resolveCardVariant(product) {
6554
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Bundle) {
6555
+ return "bundle" /* Bundle */;
6556
+ }
6557
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Composite) {
6558
+ return "composite" /* Composite */;
6559
+ }
6380
6560
  if (product.quantity_pricing && product.quantity_pricing.length > 1) {
6381
6561
  return "wholesale" /* Wholesale */;
6382
6562
  }
6383
- if (product.type === chunk4JSRPSNA_js.PRODUCT_TYPE.Digital) {
6563
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Digital) {
6384
6564
  return "digital" /* Digital */;
6385
6565
  }
6386
- if (product.type === chunk4JSRPSNA_js.PRODUCT_TYPE.Service) {
6566
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Service) {
6387
6567
  if (product.duration_unit && RENTAL_UNITS.has(product.duration_unit)) {
6388
6568
  return "rental" /* Rental */;
6389
6569
  }
6390
- if (product.duration_unit === chunk4JSRPSNA_js.DURATION_UNIT.Nights) {
6570
+ if (product.duration_unit === chunkGS7AX6B3_js.DURATION_UNIT.Nights) {
6391
6571
  return "accommodation" /* Accommodation */;
6392
6572
  }
6393
6573
  if (product.duration_unit && LEASE_UNITS.has(product.duration_unit)) {
@@ -6398,10 +6578,10 @@ function resolveCardVariant(product) {
6398
6578
  }
6399
6579
  return "standard" /* Standard */;
6400
6580
  }
6401
- if (product.render_hint === chunk4JSRPSNA_js.RENDER_HINT.Food) {
6581
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Food) {
6402
6582
  return "food" /* Food */;
6403
6583
  }
6404
- if (product.render_hint === chunk4JSRPSNA_js.RENDER_HINT.Physical) {
6584
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Physical) {
6405
6585
  return "retail" /* Retail */;
6406
6586
  }
6407
6587
  return "retail" /* Retail */;
@@ -8999,12 +9179,161 @@ function DigitalProductLayout({
8999
9179
  )
9000
9180
  ] });
9001
9181
  }
9182
+ function BundleProductLayout({
9183
+ product,
9184
+ onAddToCart,
9185
+ renderBreadcrumb,
9186
+ relatedProducts,
9187
+ showRelated = true,
9188
+ className
9189
+ }) {
9190
+ const images = product.images || (product.image_url ? [product.image_url] : []);
9191
+ const components = product.components || [];
9192
+ const onSale = chunkPEDLCL72_js.isOnSale(product);
9193
+ const discount = chunkPEDLCL72_js.getDiscountPercentage(product);
9194
+ const baseTotal = components.reduce(
9195
+ (sum, c) => sum + chunkPEDLCL72_js.parsePrice(c.effective_price ?? 0) * (c.quantity ?? 1),
9196
+ 0
9197
+ );
9198
+ const bundlePrice = chunkPEDLCL72_js.parsePrice(product.default_price);
9199
+ const savings = baseTotal > bundlePrice ? baseTotal - bundlePrice : 0;
9200
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-product-layout": "bundle", className: cn("space-y-8", className), children: [
9201
+ renderBreadcrumb?.(product),
9202
+ /* @__PURE__ */ jsxRuntime.jsx(
9203
+ TwoColumnGrid,
9204
+ {
9205
+ left: /* @__PURE__ */ jsxRuntime.jsx(
9206
+ ProductImageGallery,
9207
+ {
9208
+ images,
9209
+ productName: product.name
9210
+ }
9211
+ ),
9212
+ right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
9213
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
9214
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-indigo-700 bg-indigo-50 border border-indigo-200/60 px-2.5 py-1 rounded-md", children: "Bundle" }),
9215
+ savings > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-emerald-700 bg-emerald-50 border border-emerald-200/60 px-2.5 py-1 rounded-md", children: [
9216
+ "Save ",
9217
+ discount,
9218
+ "%"
9219
+ ] }),
9220
+ /* @__PURE__ */ jsxRuntime.jsx(TagPills, { tags: product.tags || [] })
9221
+ ] }),
9222
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9223
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { "data-cimplify-product-layout-name": true, className: "text-3xl lg:text-4xl font-bold tracking-tight", children: product.name }),
9224
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-3 mt-2", children: [
9225
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-2xl font-bold" }),
9226
+ onSale && baseTotal > 0 && /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: baseTotal, className: "text-lg text-muted-foreground line-through" })
9227
+ ] })
9228
+ ] }),
9229
+ product.description && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-product-layout-description": true, className: "text-muted-foreground leading-relaxed", children: product.description }),
9230
+ components.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-bundle-components": true, className: "space-y-3", children: [
9231
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold", children: "Included in this bundle" }),
9232
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border border border-border rounded-lg overflow-hidden", children: components.map((component) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 p-3", children: [
9233
+ component.product_image_url && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-lg overflow-hidden bg-muted shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: component.product_image_url, alt: component.product_name, className: "w-full h-full object-cover" }) }),
9234
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
9235
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium truncate", children: component.product_name }),
9236
+ component.quantity > 1 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
9237
+ "Qty: ",
9238
+ component.quantity
9239
+ ] }),
9240
+ component.allow_variant_choice && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-violet-600 font-medium", children: "Choose variant" })
9241
+ ] }),
9242
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: component.effective_price ?? 0, className: "text-sm text-muted-foreground shrink-0" })
9243
+ ] }, component.id)) })
9244
+ ] }),
9245
+ savings > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-bundle-savings": true, className: "flex items-center gap-2 p-3 bg-emerald-50 border border-emerald-200/60 text-sm text-emerald-800", children: [
9246
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }),
9247
+ "You save ",
9248
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: savings, className: "font-semibold" }),
9249
+ " with this bundle"
9250
+ ] }),
9251
+ /* @__PURE__ */ jsxRuntime.jsx(CustomAttributesTable, { attributes: product.custom_attributes || [] }),
9252
+ /* @__PURE__ */ jsxRuntime.jsx(
9253
+ ProductCustomizer,
9254
+ {
9255
+ product,
9256
+ onAddToCart
9257
+ }
9258
+ )
9259
+ ] })
9260
+ }
9261
+ ),
9262
+ showRelated && relatedProducts && relatedProducts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(RelatedProductsSection, { products: relatedProducts })
9263
+ ] });
9264
+ }
9265
+ function CompositeProductLayout({
9266
+ product,
9267
+ onAddToCart,
9268
+ renderBreadcrumb,
9269
+ relatedProducts,
9270
+ showRelated = true,
9271
+ className
9272
+ }) {
9273
+ const images = product.images || (product.image_url ? [product.image_url] : []);
9274
+ const groups = product.groups || [];
9275
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-product-layout": "composite", className: cn("space-y-8", className), children: [
9276
+ renderBreadcrumb?.(product),
9277
+ /* @__PURE__ */ jsxRuntime.jsx(
9278
+ TwoColumnGrid,
9279
+ {
9280
+ left: /* @__PURE__ */ jsxRuntime.jsx(
9281
+ ProductImageGallery,
9282
+ {
9283
+ images,
9284
+ productName: product.name
9285
+ }
9286
+ ),
9287
+ right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
9288
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
9289
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-violet-700 bg-violet-50 border border-violet-200/60 px-2.5 py-1 rounded-md", children: "Build Your Own" }),
9290
+ groups.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-muted-foreground bg-muted px-2.5 py-1 rounded-md", children: [
9291
+ groups.length,
9292
+ " choice",
9293
+ groups.length !== 1 ? "s" : ""
9294
+ ] }),
9295
+ /* @__PURE__ */ jsxRuntime.jsx(TagPills, { tags: product.tags || [] })
9296
+ ] }),
9297
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9298
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { "data-cimplify-product-layout-name": true, className: "text-3xl lg:text-4xl font-bold tracking-tight", children: product.name }),
9299
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg text-muted-foreground mt-2", children: [
9300
+ "From ",
9301
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "font-semibold text-foreground" })
9302
+ ] })
9303
+ ] }),
9304
+ product.description && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-product-layout-description": true, className: "text-muted-foreground leading-relaxed", children: product.description }),
9305
+ groups.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-composite-overview": true, className: "flex flex-wrap gap-2", children: groups.map((group) => {
9306
+ const availableCount = group.components.filter((c) => c.is_available && !c.is_archived).length;
9307
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 bg-muted rounded-lg text-sm", children: [
9308
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: group.name }),
9309
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-xs", children: [
9310
+ group.min_selections > 0 ? `Pick ${group.min_selections}` : "Optional",
9311
+ ` \xB7 ${availableCount} option${availableCount !== 1 ? "s" : ""}`
9312
+ ] })
9313
+ ] }, group.id);
9314
+ }) }),
9315
+ /* @__PURE__ */ jsxRuntime.jsx(CustomAttributesTable, { attributes: product.custom_attributes || [] }),
9316
+ /* @__PURE__ */ jsxRuntime.jsx(
9317
+ ProductCustomizer,
9318
+ {
9319
+ product,
9320
+ onAddToCart
9321
+ }
9322
+ )
9323
+ ] })
9324
+ }
9325
+ ),
9326
+ showRelated && relatedProducts && relatedProducts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(RelatedProductsSection, { products: relatedProducts })
9327
+ ] });
9328
+ }
9002
9329
  var ProductTemplate = /* @__PURE__ */ ((ProductTemplate2) => {
9003
9330
  ProductTemplate2["Default"] = "default";
9004
9331
  ProductTemplate2["Food"] = "food";
9005
9332
  ProductTemplate2["Wholesale"] = "wholesale";
9006
9333
  ProductTemplate2["Service"] = "service";
9007
9334
  ProductTemplate2["Digital"] = "digital";
9335
+ ProductTemplate2["Bundle"] = "bundle";
9336
+ ProductTemplate2["Composite"] = "composite";
9008
9337
  ProductTemplate2["Physical"] = "physical";
9009
9338
  return ProductTemplate2;
9010
9339
  })(ProductTemplate || {});
@@ -9013,6 +9342,8 @@ var BUILT_IN_LAYOUTS2 = {
9013
9342
  ["wholesale" /* Wholesale */]: WholesaleProductLayout,
9014
9343
  ["service" /* Service */]: ServiceProductLayout,
9015
9344
  ["digital" /* Digital */]: DigitalProductLayout,
9345
+ ["bundle" /* Bundle */]: BundleProductLayout,
9346
+ ["composite" /* Composite */]: CompositeProductLayout,
9016
9347
  ["default" /* Default */]: DefaultProductLayout
9017
9348
  };
9018
9349
  function resolveTemplateKey(product) {
@@ -9020,19 +9351,25 @@ function resolveTemplateKey(product) {
9020
9351
  if (typeof metaTemplate === "string" && metaTemplate.trim()) {
9021
9352
  return metaTemplate.trim();
9022
9353
  }
9354
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Bundle) {
9355
+ return "bundle" /* Bundle */;
9356
+ }
9357
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Composite) {
9358
+ return "composite" /* Composite */;
9359
+ }
9023
9360
  if (product.quantity_pricing && product.quantity_pricing.length > 1) {
9024
9361
  return "wholesale" /* Wholesale */;
9025
9362
  }
9026
- if (product.type === chunk4JSRPSNA_js.PRODUCT_TYPE.Service) {
9363
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Service) {
9027
9364
  return "service" /* Service */;
9028
9365
  }
9029
- if (product.type === chunk4JSRPSNA_js.PRODUCT_TYPE.Digital) {
9366
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Digital) {
9030
9367
  return "digital" /* Digital */;
9031
9368
  }
9032
- if (product.render_hint === chunk4JSRPSNA_js.RENDER_HINT.Food) {
9369
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Food) {
9033
9370
  return "food" /* Food */;
9034
9371
  }
9035
- if (product.render_hint === chunk4JSRPSNA_js.RENDER_HINT.Physical) {
9372
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Physical) {
9036
9373
  return "physical" /* Physical */;
9037
9374
  }
9038
9375
  return "default" /* Default */;
@@ -10610,7 +10947,7 @@ function ResourcePicker({
10610
10947
 
10611
10948
  Object.defineProperty(exports, "getVariantDisplayName", {
10612
10949
  enumerable: true,
10613
- get: function () { return chunk4JSRPSNA_js.getVariantDisplayName; }
10950
+ get: function () { return chunkGS7AX6B3_js.getVariantDisplayName; }
10614
10951
  });
10615
10952
  exports.AccommodationCard = AccommodationCard;
10616
10953
  exports.Ad = Ad;
@@ -10622,6 +10959,8 @@ exports.AvailabilityBadge = AvailabilityBadge;
10622
10959
  exports.BillingPlanSelector = BillingPlanSelector;
10623
10960
  exports.BookingCard = BookingCard;
10624
10961
  exports.BookingList = BookingList;
10962
+ exports.BundleProductCard = BundleProductCard;
10963
+ exports.BundleProductLayout = BundleProductLayout;
10625
10964
  exports.BundleSelector = BundleSelector;
10626
10965
  exports.CardImage = CardImage;
10627
10966
  exports.CardShell = CardShell;
@@ -10644,6 +10983,8 @@ exports.CompactCartLayout = CompactCartLayout;
10644
10983
  exports.CompactCatalogueLayout = CompactCatalogueLayout;
10645
10984
  exports.CompactSearchLayout = CompactSearchLayout;
10646
10985
  exports.CompactServiceCard = CompactServiceCard;
10986
+ exports.CompositeProductCard = CompositeProductCard;
10987
+ exports.CompositeProductLayout = CompositeProductLayout;
10647
10988
  exports.CompositeSelector = CompositeSelector;
10648
10989
  exports.CurrencySelector = CurrencySelector;
10649
10990
  exports.CustomAttributesTable = CustomAttributesTable;
@@ -10749,6 +11090,8 @@ exports.useRecommendations = useRecommendations;
10749
11090
  exports.useSearch = useSearch;
10750
11091
  exports.useServiceAvailability = useServiceAvailability;
10751
11092
  exports.useServices = useServices;
11093
+ exports.useSubscription = useSubscription;
11094
+ exports.useSubscriptions = useSubscriptions;
10752
11095
  exports.useTaxonomies = useTaxonomies;
10753
11096
  exports.useTaxonomy = useTaxonomy;
10754
11097
  exports.useTaxonomyPath = useTaxonomyPath;