@cimplify/sdk 0.26.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,14 +1,14 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkWMQXSDRC_js = require('./chunk-WMQXSDRC.js');
5
- var chunkI4F4Y3D4_js = require('./chunk-I4F4Y3D4.js');
4
+ var chunkGS7AX6B3_js = require('./chunk-GS7AX6B3.js');
5
+ var chunk2CGA3MUW_js = require('./chunk-2CGA3MUW.js');
6
6
  var chunkPEDLCL72_js = require('./chunk-PEDLCL72.js');
7
7
  var React3 = require('react');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
- var numberField = require('@base-ui/react/number-field');
10
9
  var clsx = require('clsx');
11
10
  var tailwindMerge = require('tailwind-merge');
11
+ var numberField = require('@base-ui/react/number-field');
12
12
  var radioGroup = require('@base-ui/react/radio-group');
13
13
  var radio = require('@base-ui/react/radio');
14
14
  var checkbox = require('@base-ui/react/checkbox');
@@ -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 chunkWMQXSDRC_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) {
@@ -1702,6 +1702,101 @@ function CimplifyCheckout({
1702
1702
  errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.error }, children: errorMessage })
1703
1703
  ] });
1704
1704
  }
1705
+ function cn(...inputs) {
1706
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
1707
+ }
1708
+ var DEFAULT_LINK_URL = "https://link.cimplify.io";
1709
+ function CimplifyAccount({
1710
+ client: clientProp,
1711
+ linkUrl,
1712
+ section,
1713
+ appearance,
1714
+ onLogout,
1715
+ className
1716
+ }) {
1717
+ const context = useOptionalCimplify();
1718
+ const client = clientProp ?? context?.client;
1719
+ const resolvedLinkUrl = linkUrl || DEFAULT_LINK_URL;
1720
+ const iframeRef = React3.useRef(null);
1721
+ const [height, setHeight] = React3.useState(400);
1722
+ const [isReady, setIsReady] = React3.useState(false);
1723
+ const iframeSrc = React3.useMemo(() => {
1724
+ const path = section ? `/elements/account/${section}` : "/elements/account";
1725
+ const url = new URL(path, resolvedLinkUrl);
1726
+ if (client) {
1727
+ const businessId = client.getBusinessId?.() ?? "";
1728
+ if (businessId) url.searchParams.set("businessId", businessId);
1729
+ }
1730
+ return url.toString();
1731
+ }, [resolvedLinkUrl, section, client]);
1732
+ React3.useEffect(() => {
1733
+ function handleMessage(event) {
1734
+ if (!event.data || typeof event.data !== "object") return;
1735
+ if (iframeRef.current?.contentWindow && event.source !== iframeRef.current.contentWindow) {
1736
+ return;
1737
+ }
1738
+ switch (event.data.type) {
1739
+ case "ready":
1740
+ setIsReady(true);
1741
+ if (typeof event.data.height === "number") {
1742
+ setHeight(event.data.height);
1743
+ }
1744
+ sendInit();
1745
+ break;
1746
+ case "height_change":
1747
+ if (typeof event.data.height === "number") {
1748
+ setHeight(event.data.height);
1749
+ }
1750
+ break;
1751
+ case "logout_complete":
1752
+ onLogout?.();
1753
+ break;
1754
+ }
1755
+ }
1756
+ window.addEventListener("message", handleMessage);
1757
+ return () => window.removeEventListener("message", handleMessage);
1758
+ }, [appearance, client, onLogout]);
1759
+ function sendInit() {
1760
+ const contentWindow = iframeRef.current?.contentWindow;
1761
+ if (!contentWindow) return;
1762
+ const token = client?.getAccessToken?.();
1763
+ contentWindow.postMessage(
1764
+ {
1765
+ type: "init",
1766
+ token: token ?? void 0,
1767
+ appearance: appearance ?? void 0
1768
+ },
1769
+ resolvedLinkUrl
1770
+ );
1771
+ }
1772
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1773
+ "div",
1774
+ {
1775
+ "data-cimplify-account": true,
1776
+ className: cn("relative overflow-hidden", className),
1777
+ children: [
1778
+ !isReady && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 border-2 border-border border-t-foreground rounded-full animate-spin" }) }),
1779
+ /* @__PURE__ */ jsxRuntime.jsx(
1780
+ "iframe",
1781
+ {
1782
+ ref: iframeRef,
1783
+ src: iframeSrc,
1784
+ style: {
1785
+ border: "none",
1786
+ width: "100%",
1787
+ height: `${height}px`,
1788
+ display: isReady ? "block" : "none",
1789
+ overflow: "hidden",
1790
+ background: "transparent"
1791
+ },
1792
+ allow: "geolocation",
1793
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
1794
+ }
1795
+ )
1796
+ ]
1797
+ }
1798
+ );
1799
+ }
1705
1800
  function Price({ amount, currency, className, prefix }) {
1706
1801
  const context = useOptionalCimplify();
1707
1802
  const resolvedCurrency = currency ?? context?.displayCurrency ?? "USD";
@@ -2757,6 +2852,84 @@ function useOrders(options = {}) {
2757
2852
  const { data, isLoading, error, refetch } = ordersQuery(options);
2758
2853
  return { orders: data ?? [], isLoading, error, refetch };
2759
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
+ }
2760
2933
 
2761
2934
  // src/react/hooks/use-services.ts
2762
2935
  var servicesQuery = createCachedQuery({
@@ -3215,19 +3388,19 @@ function AuthElement({
3215
3388
  }, [onReady, onAuthenticated, onRequiresOtp, onError]);
3216
3389
  React3.useEffect(() => {
3217
3390
  if (!elements || !containerRef.current) return;
3218
- const element = elements.create(chunkI4F4Y3D4_js.ELEMENT_TYPES.AUTH, { prefillEmail });
3391
+ const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.AUTH, { prefillEmail });
3219
3392
  elementRef.current = element;
3220
- element.on(chunkI4F4Y3D4_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3393
+ element.on(chunk2CGA3MUW_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3221
3394
  element.on(
3222
- chunkI4F4Y3D4_js.EVENT_TYPES.AUTHENTICATED,
3395
+ chunk2CGA3MUW_js.EVENT_TYPES.AUTHENTICATED,
3223
3396
  (data) => onAuthenticatedRef.current?.(data)
3224
3397
  );
3225
3398
  element.on(
3226
- chunkI4F4Y3D4_js.EVENT_TYPES.REQUIRES_OTP,
3399
+ chunk2CGA3MUW_js.EVENT_TYPES.REQUIRES_OTP,
3227
3400
  (data) => onRequiresOtpRef.current?.(data)
3228
3401
  );
3229
3402
  element.on(
3230
- chunkI4F4Y3D4_js.EVENT_TYPES.ERROR,
3403
+ chunk2CGA3MUW_js.EVENT_TYPES.ERROR,
3231
3404
  (data) => onErrorRef.current?.(data)
3232
3405
  );
3233
3406
  element.mount(containerRef.current);
@@ -3256,15 +3429,15 @@ function AddressElement({
3256
3429
  }, [onReady, onChange, onError]);
3257
3430
  React3.useEffect(() => {
3258
3431
  if (!elements || !containerRef.current) return;
3259
- const element = elements.create(chunkI4F4Y3D4_js.ELEMENT_TYPES.ADDRESS, { mode });
3432
+ const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.ADDRESS, { mode });
3260
3433
  elementRef.current = element;
3261
- element.on(chunkI4F4Y3D4_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3434
+ element.on(chunk2CGA3MUW_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3262
3435
  element.on(
3263
- chunkI4F4Y3D4_js.EVENT_TYPES.CHANGE,
3436
+ chunk2CGA3MUW_js.EVENT_TYPES.CHANGE,
3264
3437
  (data) => onChangeRef.current?.(data)
3265
3438
  );
3266
3439
  element.on(
3267
- chunkI4F4Y3D4_js.EVENT_TYPES.ERROR,
3440
+ chunk2CGA3MUW_js.EVENT_TYPES.ERROR,
3268
3441
  (data) => onErrorRef.current?.(data)
3269
3442
  );
3270
3443
  element.mount(containerRef.current);
@@ -3294,15 +3467,15 @@ function PaymentElement({
3294
3467
  }, [onReady, onChange, onError]);
3295
3468
  React3.useEffect(() => {
3296
3469
  if (!elements || !containerRef.current) return;
3297
- const element = elements.create(chunkI4F4Y3D4_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
3470
+ const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
3298
3471
  elementRef.current = element;
3299
- element.on(chunkI4F4Y3D4_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3472
+ element.on(chunk2CGA3MUW_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
3300
3473
  element.on(
3301
- chunkI4F4Y3D4_js.EVENT_TYPES.CHANGE,
3474
+ chunk2CGA3MUW_js.EVENT_TYPES.CHANGE,
3302
3475
  (data) => onChangeRef.current?.(data)
3303
3476
  );
3304
3477
  element.on(
3305
- chunkI4F4Y3D4_js.EVENT_TYPES.ERROR,
3478
+ chunk2CGA3MUW_js.EVENT_TYPES.ERROR,
3306
3479
  (data) => onErrorRef.current?.(data)
3307
3480
  );
3308
3481
  element.mount(containerRef.current);
@@ -3346,9 +3519,6 @@ function useCheckout() {
3346
3519
  );
3347
3520
  return { submit, process, isLoading };
3348
3521
  }
3349
- function cn(...inputs) {
3350
- return tailwindMerge.twMerge(clsx.clsx(inputs));
3351
- }
3352
3522
  function QuantitySelector({
3353
3523
  value,
3354
3524
  onChange,
@@ -3565,7 +3735,7 @@ function VariantSelector({
3565
3735
  {
3566
3736
  "data-cimplify-variant-name": true,
3567
3737
  className: cn("flex-1 min-w-0 text-sm", classNames?.name),
3568
- children: chunkWMQXSDRC_js.getVariantDisplayName(variant, productName)
3738
+ children: chunkGS7AX6B3_js.getVariantDisplayName(variant, productName)
3569
3739
  }
3570
3740
  ),
3571
3741
  /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm text-muted-foreground", classNames?.pricing), children: [
@@ -5101,7 +5271,7 @@ function CartLineItemRow({
5101
5271
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item": true, className: classNames?.item, children: [
5102
5272
  /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item-info": true, children: [
5103
5273
  /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-name": true, className: classNames?.itemName, children: item.product.name }),
5104
- item.variant && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-variant": true, children: chunkWMQXSDRC_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) }),
5105
5275
  item.addOnOptions && item.addOnOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-cart-item-addons": true, children: [
5106
5276
  "+ ",
5107
5277
  item.addOnOptions.map((opt) => opt.name).join(", ")
@@ -5626,7 +5796,7 @@ function FoodProductCard({
5626
5796
  const tags = product.tags || [];
5627
5797
  const isSignature = product.metadata?.is_signature === true;
5628
5798
  const isNew = product.metadata?.is_new === true;
5629
- const isComposite = product.type === chunkWMQXSDRC_js.PRODUCT_TYPE.Composite;
5799
+ const isComposite = product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Composite;
5630
5800
  return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
5631
5801
  /* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
5632
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: [
@@ -5795,6 +5965,98 @@ function DigitalProductCard({
5795
5965
  ] })
5796
5966
  ] });
5797
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
+ }
5798
6060
  function formatDuration2(minutes, unit) {
5799
6061
  if (unit && unit !== "minutes") return `${minutes} ${unit}`;
5800
6062
  if (minutes >= 60) {
@@ -6256,6 +6518,8 @@ var CardVariant = /* @__PURE__ */ ((CardVariant2) => {
6256
6518
  CardVariant2["Retail"] = "retail";
6257
6519
  CardVariant2["Wholesale"] = "wholesale";
6258
6520
  CardVariant2["Digital"] = "digital";
6521
+ CardVariant2["Bundle"] = "bundle";
6522
+ CardVariant2["Composite"] = "composite";
6259
6523
  CardVariant2["Standard"] = "standard";
6260
6524
  CardVariant2["Compact"] = "compact";
6261
6525
  CardVariant2["Schedule"] = "schedule";
@@ -6280,22 +6544,30 @@ var BUILT_IN_CARDS = {
6280
6544
  ["rental" /* Rental */]: RentalServiceCard,
6281
6545
  ["accommodation" /* Accommodation */]: AccommodationCard,
6282
6546
  ["lease" /* Lease */]: LeaseServiceCard,
6547
+ ["bundle" /* Bundle */]: BundleProductCard,
6548
+ ["composite" /* Composite */]: CompositeProductCard,
6283
6549
  ["subscription" /* Subscription */]: SubscriptionCard
6284
6550
  };
6285
- var RENTAL_UNITS = /* @__PURE__ */ new Set([chunkWMQXSDRC_js.DURATION_UNIT.Days, chunkWMQXSDRC_js.DURATION_UNIT.Hours]);
6286
- var LEASE_UNITS = /* @__PURE__ */ new Set([chunkWMQXSDRC_js.DURATION_UNIT.Weeks, chunkWMQXSDRC_js.DURATION_UNIT.Months, chunkWMQXSDRC_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]);
6287
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
+ }
6288
6560
  if (product.quantity_pricing && product.quantity_pricing.length > 1) {
6289
6561
  return "wholesale" /* Wholesale */;
6290
6562
  }
6291
- if (product.type === chunkWMQXSDRC_js.PRODUCT_TYPE.Digital) {
6563
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Digital) {
6292
6564
  return "digital" /* Digital */;
6293
6565
  }
6294
- if (product.type === chunkWMQXSDRC_js.PRODUCT_TYPE.Service) {
6566
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Service) {
6295
6567
  if (product.duration_unit && RENTAL_UNITS.has(product.duration_unit)) {
6296
6568
  return "rental" /* Rental */;
6297
6569
  }
6298
- if (product.duration_unit === chunkWMQXSDRC_js.DURATION_UNIT.Nights) {
6570
+ if (product.duration_unit === chunkGS7AX6B3_js.DURATION_UNIT.Nights) {
6299
6571
  return "accommodation" /* Accommodation */;
6300
6572
  }
6301
6573
  if (product.duration_unit && LEASE_UNITS.has(product.duration_unit)) {
@@ -6306,10 +6578,10 @@ function resolveCardVariant(product) {
6306
6578
  }
6307
6579
  return "standard" /* Standard */;
6308
6580
  }
6309
- if (product.render_hint === chunkWMQXSDRC_js.RENDER_HINT.Food) {
6581
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Food) {
6310
6582
  return "food" /* Food */;
6311
6583
  }
6312
- if (product.render_hint === chunkWMQXSDRC_js.RENDER_HINT.Physical) {
6584
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Physical) {
6313
6585
  return "retail" /* Retail */;
6314
6586
  }
6315
6587
  return "retail" /* Retail */;
@@ -8907,12 +9179,161 @@ function DigitalProductLayout({
8907
9179
  )
8908
9180
  ] });
8909
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
+ }
8910
9329
  var ProductTemplate = /* @__PURE__ */ ((ProductTemplate2) => {
8911
9330
  ProductTemplate2["Default"] = "default";
8912
9331
  ProductTemplate2["Food"] = "food";
8913
9332
  ProductTemplate2["Wholesale"] = "wholesale";
8914
9333
  ProductTemplate2["Service"] = "service";
8915
9334
  ProductTemplate2["Digital"] = "digital";
9335
+ ProductTemplate2["Bundle"] = "bundle";
9336
+ ProductTemplate2["Composite"] = "composite";
8916
9337
  ProductTemplate2["Physical"] = "physical";
8917
9338
  return ProductTemplate2;
8918
9339
  })(ProductTemplate || {});
@@ -8921,6 +9342,8 @@ var BUILT_IN_LAYOUTS2 = {
8921
9342
  ["wholesale" /* Wholesale */]: WholesaleProductLayout,
8922
9343
  ["service" /* Service */]: ServiceProductLayout,
8923
9344
  ["digital" /* Digital */]: DigitalProductLayout,
9345
+ ["bundle" /* Bundle */]: BundleProductLayout,
9346
+ ["composite" /* Composite */]: CompositeProductLayout,
8924
9347
  ["default" /* Default */]: DefaultProductLayout
8925
9348
  };
8926
9349
  function resolveTemplateKey(product) {
@@ -8928,19 +9351,25 @@ function resolveTemplateKey(product) {
8928
9351
  if (typeof metaTemplate === "string" && metaTemplate.trim()) {
8929
9352
  return metaTemplate.trim();
8930
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
+ }
8931
9360
  if (product.quantity_pricing && product.quantity_pricing.length > 1) {
8932
9361
  return "wholesale" /* Wholesale */;
8933
9362
  }
8934
- if (product.type === chunkWMQXSDRC_js.PRODUCT_TYPE.Service) {
9363
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Service) {
8935
9364
  return "service" /* Service */;
8936
9365
  }
8937
- if (product.type === chunkWMQXSDRC_js.PRODUCT_TYPE.Digital) {
9366
+ if (product.type === chunkGS7AX6B3_js.PRODUCT_TYPE.Digital) {
8938
9367
  return "digital" /* Digital */;
8939
9368
  }
8940
- if (product.render_hint === chunkWMQXSDRC_js.RENDER_HINT.Food) {
9369
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Food) {
8941
9370
  return "food" /* Food */;
8942
9371
  }
8943
- if (product.render_hint === chunkWMQXSDRC_js.RENDER_HINT.Physical) {
9372
+ if (product.render_hint === chunkGS7AX6B3_js.RENDER_HINT.Physical) {
8944
9373
  return "physical" /* Physical */;
8945
9374
  }
8946
9375
  return "default" /* Default */;
@@ -10518,7 +10947,7 @@ function ResourcePicker({
10518
10947
 
10519
10948
  Object.defineProperty(exports, "getVariantDisplayName", {
10520
10949
  enumerable: true,
10521
- get: function () { return chunkWMQXSDRC_js.getVariantDisplayName; }
10950
+ get: function () { return chunkGS7AX6B3_js.getVariantDisplayName; }
10522
10951
  });
10523
10952
  exports.AccommodationCard = AccommodationCard;
10524
10953
  exports.Ad = Ad;
@@ -10530,6 +10959,8 @@ exports.AvailabilityBadge = AvailabilityBadge;
10530
10959
  exports.BillingPlanSelector = BillingPlanSelector;
10531
10960
  exports.BookingCard = BookingCard;
10532
10961
  exports.BookingList = BookingList;
10962
+ exports.BundleProductCard = BundleProductCard;
10963
+ exports.BundleProductLayout = BundleProductLayout;
10533
10964
  exports.BundleSelector = BundleSelector;
10534
10965
  exports.CardImage = CardImage;
10535
10966
  exports.CardShell = CardShell;
@@ -10543,6 +10974,7 @@ exports.CatalogueTemplate = CatalogueTemplate;
10543
10974
  exports.CategoryFilter = CategoryFilter;
10544
10975
  exports.CategoryGrid = CategoryGrid;
10545
10976
  exports.CheckoutPage = CheckoutPage;
10977
+ exports.CimplifyAccount = CimplifyAccount;
10546
10978
  exports.CimplifyCheckout = CimplifyCheckout;
10547
10979
  exports.CimplifyProvider = CimplifyProvider;
10548
10980
  exports.CollectionPage = CollectionPage;
@@ -10551,6 +10983,8 @@ exports.CompactCartLayout = CompactCartLayout;
10551
10983
  exports.CompactCatalogueLayout = CompactCatalogueLayout;
10552
10984
  exports.CompactSearchLayout = CompactSearchLayout;
10553
10985
  exports.CompactServiceCard = CompactServiceCard;
10986
+ exports.CompositeProductCard = CompositeProductCard;
10987
+ exports.CompositeProductLayout = CompositeProductLayout;
10554
10988
  exports.CompositeSelector = CompositeSelector;
10555
10989
  exports.CurrencySelector = CurrencySelector;
10556
10990
  exports.CustomAttributesTable = CustomAttributesTable;
@@ -10656,6 +11090,8 @@ exports.useRecommendations = useRecommendations;
10656
11090
  exports.useSearch = useSearch;
10657
11091
  exports.useServiceAvailability = useServiceAvailability;
10658
11092
  exports.useServices = useServices;
11093
+ exports.useSubscription = useSubscription;
11094
+ exports.useSubscriptions = useSubscriptions;
10659
11095
  exports.useTaxonomies = useTaxonomies;
10660
11096
  exports.useTaxonomy = useTaxonomy;
10661
11097
  exports.useTaxonomyPath = useTaxonomyPath;